diff options
author | Ezekiel Kigbo <ekigbo@gitlab.com> | 2019-08-19 06:51:06 +0000 |
---|---|---|
committer | Kushal Pandya <kushalspandya@gmail.com> | 2019-08-19 06:51:06 +0000 |
commit | 5e8f16bd00e7ed67f92ee3ea86381758ecc23585 (patch) | |
tree | d768a5d069f25958a46657232465b630555bf08f /app | |
parent | 6f4350e46ed839d6b1317d1e874670bad263e57e (diff) | |
download | gitlab-ce-5e8f16bd00e7ed67f92ee3ea86381758ecc23585.tar.gz |
Move cycle analytics stages templates to vue
The existing stage list items are rendered
in haml, migrating them to vuejs for future
work.
Fix alignment of median value
Test for stage_nav_item.vue
Diffstat (limited to 'app')
5 files changed, 150 insertions, 60 deletions
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_card_list_item.vue b/app/assets/javascripts/cycle_analytics/components/stage_card_list_item.vue new file mode 100644 index 00000000000..d946594a069 --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/stage_card_list_item.vue @@ -0,0 +1,41 @@ +<script> +import Icon from '~/vue_shared/components/icon.vue'; +import { GlButton } from '@gitlab/ui'; + +export default { + name: 'StageCardListItem', + components: { + Icon, + GlButton, + }, + props: { + isActive: { + type: Boolean, + required: true, + }, + canEdit: { + type: Boolean, + default: false, + required: false, + }, + }, +}; +</script> + +<template> + <div :class="{ active: isActive }" class="stage-nav-item d-flex pl-4 pr-4 m-0 mb-1 ml-2 rounded"> + <slot></slot> + <div v-if="canEdit" class="dropdown"> + <gl-button + :title="__('More actions')" + class="more-actions-toggle btn btn-transparent p-0" + data-toggle="dropdown" + > + <icon css-classes="icon" name="ellipsis_v" /> + </gl-button> + <ul class="more-actions-dropdown dropdown-menu dropdown-open-left"> + <slot name="dropdown-options"></slot> + </ul> + </div> + </div> +</template> diff --git a/app/assets/javascripts/cycle_analytics/components/stage_nav_item.vue b/app/assets/javascripts/cycle_analytics/components/stage_nav_item.vue new file mode 100644 index 00000000000..004d335f572 --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/stage_nav_item.vue @@ -0,0 +1,88 @@ +<script> +import StageCardListItem from './stage_card_list_item.vue'; + +export default { + name: 'StageNavItem', + components: { + StageCardListItem, + }, + props: { + isDefaultStage: { + type: Boolean, + default: false, + required: false, + }, + isActive: { + type: Boolean, + default: false, + required: false, + }, + isUserAllowed: { + type: Boolean, + required: true, + }, + title: { + type: String, + required: true, + }, + value: { + type: String, + default: '', + required: false, + }, + canEdit: { + type: Boolean, + default: false, + required: false, + }, + }, + computed: { + hasValue() { + return this.value && this.value.length > 0; + }, + editable() { + return this.isUserAllowed && this.canEdit; + }, + }, +}; +</script> + +<template> + <li @click="$emit('select')"> + <stage-card-list-item :is-active="isActive" :can-edit="editable"> + <div class="stage-nav-item-cell stage-name p-0" :class="{ 'font-weight-bold': isActive }"> + {{ title }} + </div> + <div class="stage-nav-item-cell stage-median mr-4"> + <template v-if="isUserAllowed"> + <span v-if="hasValue">{{ value }}</span> + <span v-else class="stage-empty">{{ __('Not enough data') }}</span> + </template> + <template v-else> + <span class="not-available">{{ __('Not available') }}</span> + </template> + </div> + <template v-slot:dropdown-options> + <template v-if="isDefaultStage"> + <li> + <button type="button" class="btn-default btn-transparent"> + {{ __('Hide stage') }} + </button> + </li> + </template> + <template v-else> + <li> + <button type="button" class="btn-default btn-transparent"> + {{ __('Edit stage') }} + </button> + </li> + <li> + <button type="button" class="btn-danger danger"> + {{ __('Remove stage') }} + </button> + </li> + </template> + </template> + </stage-card-list-item> + </li> +</template> diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js index 671405602cc..b3ae47af750 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js @@ -12,6 +12,7 @@ import stageComponent from './components/stage_component.vue'; import stageReviewComponent from './components/stage_review_component.vue'; import stageStagingComponent from './components/stage_staging_component.vue'; import stageTestComponent from './components/stage_test_component.vue'; +import stageNavItem from './components/stage_nav_item.vue'; import CycleAnalyticsService from './cycle_analytics_service'; import CycleAnalyticsStore from './cycle_analytics_store'; @@ -41,6 +42,7 @@ export default () => { import('ee_component/analytics/shared/components/projects_dropdown_filter.vue'), DateRangeDropdown: () => import('ee_component/analytics/shared/components/date_range_dropdown.vue'), + 'stage-nav-item': stageNavItem, }, mixins: [filterMixins], data() { diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index 2b932d164a5..d80155a416d 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -51,27 +51,19 @@ } .stage-header { - width: 26%; - padding-left: $gl-padding; + width: 18.5%; } .median-header { - width: 14%; + width: 21.5%; } .event-header { width: 45%; - padding-left: $gl-padding; } .total-time-header { width: 15%; - text-align: right; - padding-right: $gl-padding; - } - - .stage-name { - font-weight: $gl-font-weight-bold; } } @@ -153,23 +145,13 @@ } .stage-nav-item { - display: flex; line-height: 65px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - border-right: 1px solid $border-color; - background-color: $gray-light; + border: 1px solid $border-color; &.active { - background-color: transparent; - border-right-color: transparent; - border-top-color: $border-color; - border-bottom-color: $border-color; - box-shadow: inset 2px 0 0 0 $blue-500; - - .stage-name { - font-weight: $gl-font-weight-bold; - } + background: $blue-50; + border-color: $blue-300; + box-shadow: inset 4px 0 0 0 $blue-500; } &:hover:not(.active) { @@ -178,24 +160,12 @@ cursor: pointer; } - &:first-child { - border-top: 0; - } - - &:last-child { - border-bottom: 0; - } - - .stage-nav-item-cell { - &.stage-median { - margin-left: auto; - margin-right: $gl-padding; - min-width: calc(35% - #{$gl-padding}); - } + .stage-nav-item-cell.stage-name { + width: 44.5%; } - .stage-name { - padding-left: 16px; + .stage-nav-item-cell.stage-median { + min-width: 43%; } .stage-empty, diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml index 59f0afd59e6..2b594c125f4 100644 --- a/app/views/projects/cycle_analytics/show.html.haml +++ b/app/views/projects/cycle_analytics/show.html.haml @@ -34,40 +34,29 @@ {{ n__('Last %d day', 'Last %d days', 90) }} .stage-panel-container .card.stage-panel - .card-header + .card-header.border-bottom-0 %nav.col-headers %ul - %li.stage-header - %span.stage-name + %li.stage-header.pl-5 + %span.stage-name.font-weight-bold {{ s__('ProjectLifecycle|Stage') }} %i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The phase of the development lifecycle."), "aria-hidden" => "true" } %li.median-header - %span.stage-name + %span.stage-name.font-weight-bold {{ __('Median') }} %i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."), "aria-hidden" => "true" } - %li.event-header - %span.stage-name + %li.event-header.pl-3 + %span.stage-name.font-weight-bold {{ currentStage ? __(currentStage.legend) : __('Related Issues') }} %i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The collection of events added to the data gathered for that stage."), "aria-hidden" => "true" } - %li.total-time-header - %span.stage-name + %li.total-time-header.pr-5.text-right + %span.stage-name.font-weight-bold {{ __('Total Time') }} %i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The time taken by each data entry gathered by that stage."), "aria-hidden" => "true" } .stage-panel-body %nav.stage-nav %ul - %li.stage-nav-item{ ':class' => '{ active: stage.active }', '@click' => 'selectStage(stage)', "v-for" => "stage in state.stages" } - .stage-nav-item-cell.stage-name - {{ stage.title }} - .stage-nav-item-cell.stage-median - %template{ "v-if" => "stage.isUserAllowed" } - %span{ "v-if" => "stage.value" } - {{ stage.value }} - %span.stage-empty{ "v-else" => true } - {{ __('Not enough data') }} - %template{ "v-else" => true } - %span.not-available - {{ __('Not available') }} + %stage-nav-item{ "v-for" => "stage in state.stages", ":key" => '`ca-stage-title-${stage.title}`', '@select' => 'selectStage(stage)', ":title" => "stage.title", ":is-user-allowed" => "stage.isUserAllowed", ":value" => "stage.value", ":is-active" => "stage.active" } .section.stage-events %template{ "v-if" => "isLoadingStage" } = icon("spinner spin") |