diff options
author | Phil Hughes <me@iamphill.com> | 2018-05-24 11:49:57 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2018-05-24 11:49:57 +0100 |
commit | 4b4618936d0af203820be3a9392d7e555464cf3f (patch) | |
tree | ae8f82462b794c2c36dc17bae9b94f1116915d6b /app | |
parent | d61a27d57ef8a97f36a1787db6fd8e2b4235cc42 (diff) | |
download | gitlab-ce-4b4618936d0af203820be3a9392d7e555464cf3f.tar.gz |
improve design of job items
allow ci icon to have a different size & be borderless
Diffstat (limited to 'app')
8 files changed, 137 insertions, 23 deletions
diff --git a/app/assets/javascripts/ide/components/jobs/item.vue b/app/assets/javascripts/ide/components/jobs/item.vue index 53d9baffd78..a6ca629a358 100644 --- a/app/assets/javascripts/ide/components/jobs/item.vue +++ b/app/assets/javascripts/ide/components/jobs/item.vue @@ -11,16 +11,48 @@ export default { required: true, }, }, + computed: { + jobId() { + return `#${this.job.id}`; + }, + }, }; </script> <template> - <div> - <ci-icon :status="job.status" /> - {{ job.name }} - <a - :href="job.build_path" - target="_blank" - >#{{ job.id }}</a> + <div class="ide-job-item"> + <ci-icon + :status="job.status" + :borderless="true" + :size="24" + /> + <span class="prepend-left-8"> + {{ job.name }} + <a + :href="job.build_path" + target="_blank" + v-text="jobId" + > + </a> + </span> </div> </template> + +<style scoped> +.ide-job-item { + display: flex; + padding: 16px; +} + +.ide-job-item:not(:last-child) { + border-bottom: 1px solid #e5e5e5; +} + +.ide-job-item .ci-status-icon { + display: flex; + justify-content: center; + height: 20px; + margin-top: -2px; + overflow: hidden; +} +</style> diff --git a/app/assets/javascripts/ide/components/jobs/list.vue b/app/assets/javascripts/ide/components/jobs/list.vue index 7ac1ce3ef54..ef1d4580d6a 100644 --- a/app/assets/javascripts/ide/components/jobs/list.vue +++ b/app/assets/javascripts/ide/components/jobs/list.vue @@ -1,8 +1,11 @@ <script> +import { mapState } from 'vuex'; +import LoadingIcon from '../../../vue_shared/components/loading_icon.vue'; import Stage from './stage.vue'; export default { components: { + LoadingIcon, Stage, }, props: { @@ -11,15 +14,25 @@ export default { required: true, }, }, + computed: { + ...mapState('pipelines', ['isLoadingJobs']), + }, }; </script> <template> - <div style="overflow: auto;"> - <stage - v-for="stage in stages" - :key="stage.id" - :stage="stage" + <div> + <loading-icon + v-if="isLoadingJobs && !stages.length" + class="prepend-top-default" + size="2" /> + <template v-else> + <stage + v-for="stage in stages" + :key="stage.id" + :stage="stage" + /> + </template> </div> </template> diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue index a4e3b8e7926..c00ac458745 100644 --- a/app/assets/javascripts/ide/components/jobs/stage.vue +++ b/app/assets/javascripts/ide/components/jobs/stage.vue @@ -1,11 +1,15 @@ <script> import { mapActions } from 'vuex'; +import tooltip from '../../../vue_shared/directives/tooltip'; import Icon from '../../../vue_shared/components/icon.vue'; import CiIcon from '../../../vue_shared/components/ci_icon.vue'; import LoadingIcon from '../../../vue_shared/components/loading_icon.vue'; import Item from './item.vue'; export default { + directives: { + tooltip, + }, components: { Icon, CiIcon, @@ -18,6 +22,11 @@ export default { required: true, }, }, + data() { + return { + showTooltip: false, + }; + }, computed: { collapseIcon() { return this.stage.isCollapsed ? 'angle-left' : 'angle-down'; @@ -26,6 +35,11 @@ export default { created() { this.fetchJobs(this.stage); }, + mounted() { + const { stageTitle } = this.$refs; + + this.showTooltip = stageTitle.scrollWidth > stageTitle.offsetWidth; + }, methods: { ...mapActions('pipelines', ['fetchJobs']), }, @@ -42,11 +56,18 @@ export default { > <ci-icon :status="stage.status" + :size="24" /> - <span class="prepend-left-8"> - {{ stage.title }} - </span> - <div> + <strong + v-tooltip="showTooltip" + :title="showTooltip ? stage.name : null" + data-container="body" + class="prepend-left-8 ide-stage-title" + ref="stageTitle" + > + {{ stage.name }} + </strong> + <div class="append-right-8"> <span class="badge"> {{ stage.jobs.length }} </span> @@ -87,4 +108,14 @@ export default { .panel-heading .pull-right { margin: auto 0 auto auto; } + +.panel-body { + padding: 0; +} + +.ide-stage-title { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} </style> diff --git a/app/assets/javascripts/ide/components/panes/right.vue b/app/assets/javascripts/ide/components/panes/right.vue index 7449822516b..485412867f6 100644 --- a/app/assets/javascripts/ide/components/panes/right.vue +++ b/app/assets/javascripts/ide/components/panes/right.vue @@ -70,7 +70,7 @@ export default { } .ide-right-sidebar .multi-file-commit-panel-inner { - width: 300px; + width: 350px; padding: 8px 16px; background-color: #fff; border-left: 1px solid #eaeaea; diff --git a/app/assets/javascripts/ide/components/pipelines/jobs.vue b/app/assets/javascripts/ide/components/pipelines/jobs.vue index ffe8a9e1696..08edc0e56a5 100644 --- a/app/assets/javascripts/ide/components/pipelines/jobs.vue +++ b/app/assets/javascripts/ide/components/pipelines/jobs.vue @@ -12,7 +12,7 @@ export default { }, computed: { ...mapGetters('pipelines', ['jobsCount', 'failedJobsCount', 'failedStages']), - ...mapState('pipelines', ['stages']), + ...mapState('pipelines', ['stages', 'isLoadingJobs']), }, created() { this.fetchStages(); @@ -28,7 +28,13 @@ export default { <tabs> <tab active> <template slot="title"> - Jobs <span class="badge">{{ jobsCount }}</span> + Jobs + <span + v-if="!isLoadingJobs || jobsCount" + class="badge" + > + {{ jobsCount }} + </span> </template> <jobs-list :stages="stages" @@ -36,7 +42,13 @@ export default { </tab> <tab> <template slot="title"> - Failed Jobs <span class="badge">{{ failedJobsCount }}</span> + Failed Jobs + <span + v-if="!isLoadingJobs || failedJobsCount" + class="badge" + > + {{ failedJobsCount }} + </span> </template> <jobs-list :stages="failedStages" diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue index 74ff51c7fad..d8f75d2f6a3 100644 --- a/app/assets/javascripts/ide/components/pipelines/list.vue +++ b/app/assets/javascripts/ide/components/pipelines/list.vue @@ -42,6 +42,7 @@ export default { > <ci-icon :status="statusIcon" + :size="24" /> <span class="prepend-left-8"> <strong> diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js index e4570717791..95bed0f9050 100644 --- a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js +++ b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js @@ -1,10 +1,14 @@ export const hasLatestPipeline = state => !state.isLoadingPipeline && !!state.latestPipeline; -export const failedStages = state => state.stages.filter(stage => stage.status.label === 'failed'); +export const failedStages = state => + state.stages.filter(stage => stage.status.text === 'failed').map(stage => ({ + ...stage, + jobs: stage.jobs.filter(job => job.status.text === 'failed'), + })); export const failedJobsCount = state => state.stages.reduce( - (acc, stage) => acc + stage.jobs.filter(j => j.status.label === 'failed').length, + (acc, stage) => acc + stage.jobs.filter(j => j.status.text === 'failed').length, 0, ); diff --git a/app/assets/javascripts/vue_shared/components/ci_icon.vue b/app/assets/javascripts/vue_shared/components/ci_icon.vue index fcab8f571dd..03f924ba99d 100644 --- a/app/assets/javascripts/vue_shared/components/ci_icon.vue +++ b/app/assets/javascripts/vue_shared/components/ci_icon.vue @@ -22,6 +22,8 @@ import Icon from '../../vue_shared/components/icon.vue'; * - Jobs show view header * - Jobs show view sidebar */ +const validSizes = [8, 12, 16, 18, 24, 32, 48, 72]; + export default { components: { Icon, @@ -31,17 +33,36 @@ export default { type: Object, required: true, }, + size: { + type: Number, + required: false, + default: 16, + validator(value) { + return validSizes.includes(value); + }, + }, + borderless: { + type: Boolean, + required: false, + default: false, + }, }, computed: { cssClass() { const status = this.status.group; return `ci-status-icon ci-status-icon-${status} js-ci-status-icon-${status}`; }, + icon() { + return this.borderless ? `${this.status.icon}_borderless` : this.status.icon; + }, }, }; </script> <template> <span :class="cssClass"> - <icon :name="status.icon" /> + <icon + :name="icon" + :size="size" + /> </span> </template> |