Commit 4b461893 authored by Phil Hughes's avatar Phil Hughes

improve design of job items

allow ci icon to have a different size & be borderless
parent d61a27d5
...@@ -11,16 +11,48 @@ export default { ...@@ -11,16 +11,48 @@ export default {
required: true, required: true,
}, },
}, },
computed: {
jobId() {
return `#${this.job.id}`;
},
},
}; };
</script> </script>
<template> <template>
<div> <div class="ide-job-item">
<ci-icon :status="job.status" /> <ci-icon
{{ job.name }} :status="job.status"
<a :borderless="true"
:href="job.build_path" :size="24"
target="_blank" />
>#{{ job.id }}</a> <span class="prepend-left-8">
{{ job.name }}
<a
:href="job.build_path"
target="_blank"
v-text="jobId"
>
</a>
</span>
</div> </div>
</template> </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>
<script> <script>
import { mapState } from 'vuex';
import LoadingIcon from '../../../vue_shared/components/loading_icon.vue';
import Stage from './stage.vue'; import Stage from './stage.vue';
export default { export default {
components: { components: {
LoadingIcon,
Stage, Stage,
}, },
props: { props: {
...@@ -11,15 +14,25 @@ export default { ...@@ -11,15 +14,25 @@ export default {
required: true, required: true,
}, },
}, },
computed: {
...mapState('pipelines', ['isLoadingJobs']),
},
}; };
</script> </script>
<template> <template>
<div style="overflow: auto;"> <div>
<stage <loading-icon
v-for="stage in stages" v-if="isLoadingJobs && !stages.length"
:key="stage.id" class="prepend-top-default"
:stage="stage" size="2"
/> />
<template v-else>
<stage
v-for="stage in stages"
:key="stage.id"
:stage="stage"
/>
</template>
</div> </div>
</template> </template>
<script> <script>
import { mapActions } from 'vuex'; import { mapActions } from 'vuex';
import tooltip from '../../../vue_shared/directives/tooltip';
import Icon from '../../../vue_shared/components/icon.vue'; import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue'; import CiIcon from '../../../vue_shared/components/ci_icon.vue';
import LoadingIcon from '../../../vue_shared/components/loading_icon.vue'; import LoadingIcon from '../../../vue_shared/components/loading_icon.vue';
import Item from './item.vue'; import Item from './item.vue';
export default { export default {
directives: {
tooltip,
},
components: { components: {
Icon, Icon,
CiIcon, CiIcon,
...@@ -18,6 +22,11 @@ export default { ...@@ -18,6 +22,11 @@ export default {
required: true, required: true,
}, },
}, },
data() {
return {
showTooltip: false,
};
},
computed: { computed: {
collapseIcon() { collapseIcon() {
return this.stage.isCollapsed ? 'angle-left' : 'angle-down'; return this.stage.isCollapsed ? 'angle-left' : 'angle-down';
...@@ -26,6 +35,11 @@ export default { ...@@ -26,6 +35,11 @@ export default {
created() { created() {
this.fetchJobs(this.stage); this.fetchJobs(this.stage);
}, },
mounted() {
const { stageTitle } = this.$refs;
this.showTooltip = stageTitle.scrollWidth > stageTitle.offsetWidth;
},
methods: { methods: {
...mapActions('pipelines', ['fetchJobs']), ...mapActions('pipelines', ['fetchJobs']),
}, },
...@@ -42,11 +56,18 @@ export default { ...@@ -42,11 +56,18 @@ export default {
> >
<ci-icon <ci-icon
:status="stage.status" :status="stage.status"
:size="24"
/> />
<span class="prepend-left-8"> <strong
{{ stage.title }} v-tooltip="showTooltip"
</span> :title="showTooltip ? stage.name : null"
<div> data-container="body"
class="prepend-left-8 ide-stage-title"
ref="stageTitle"
>
{{ stage.name }}
</strong>
<div class="append-right-8">
<span class="badge"> <span class="badge">
{{ stage.jobs.length }} {{ stage.jobs.length }}
</span> </span>
...@@ -87,4 +108,14 @@ export default { ...@@ -87,4 +108,14 @@ export default {
.panel-heading .pull-right { .panel-heading .pull-right {
margin: auto 0 auto auto; margin: auto 0 auto auto;
} }
.panel-body {
padding: 0;
}
.ide-stage-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style> </style>
...@@ -70,7 +70,7 @@ export default { ...@@ -70,7 +70,7 @@ export default {
} }
.ide-right-sidebar .multi-file-commit-panel-inner { .ide-right-sidebar .multi-file-commit-panel-inner {
width: 300px; width: 350px;
padding: 8px 16px; padding: 8px 16px;
background-color: #fff; background-color: #fff;
border-left: 1px solid #eaeaea; border-left: 1px solid #eaeaea;
......
...@@ -12,7 +12,7 @@ export default { ...@@ -12,7 +12,7 @@ export default {
}, },
computed: { computed: {
...mapGetters('pipelines', ['jobsCount', 'failedJobsCount', 'failedStages']), ...mapGetters('pipelines', ['jobsCount', 'failedJobsCount', 'failedStages']),
...mapState('pipelines', ['stages']), ...mapState('pipelines', ['stages', 'isLoadingJobs']),
}, },
created() { created() {
this.fetchStages(); this.fetchStages();
...@@ -28,7 +28,13 @@ export default { ...@@ -28,7 +28,13 @@ export default {
<tabs> <tabs>
<tab active> <tab active>
<template slot="title"> <template slot="title">
Jobs <span class="badge">{{ jobsCount }}</span> Jobs
<span
v-if="!isLoadingJobs || jobsCount"
class="badge"
>
{{ jobsCount }}
</span>
</template> </template>
<jobs-list <jobs-list
:stages="stages" :stages="stages"
...@@ -36,7 +42,13 @@ export default { ...@@ -36,7 +42,13 @@ export default {
</tab> </tab>
<tab> <tab>
<template slot="title"> <template slot="title">
Failed Jobs <span class="badge">{{ failedJobsCount }}</span> Failed Jobs
<span
v-if="!isLoadingJobs || failedJobsCount"
class="badge"
>
{{ failedJobsCount }}
</span>
</template> </template>
<jobs-list <jobs-list
:stages="failedStages" :stages="failedStages"
......
...@@ -42,6 +42,7 @@ export default { ...@@ -42,6 +42,7 @@ export default {
> >
<ci-icon <ci-icon
:status="statusIcon" :status="statusIcon"
:size="24"
/> />
<span class="prepend-left-8"> <span class="prepend-left-8">
<strong> <strong>
......
export const hasLatestPipeline = state => !state.isLoadingPipeline && !!state.latestPipeline; 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 => export const failedJobsCount = state =>
state.stages.reduce( 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, 0,
); );
......
...@@ -22,6 +22,8 @@ import Icon from '../../vue_shared/components/icon.vue'; ...@@ -22,6 +22,8 @@ import Icon from '../../vue_shared/components/icon.vue';
* - Jobs show view header * - Jobs show view header
* - Jobs show view sidebar * - Jobs show view sidebar
*/ */
const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
export default { export default {
components: { components: {
Icon, Icon,
...@@ -31,17 +33,36 @@ export default { ...@@ -31,17 +33,36 @@ export default {
type: Object, type: Object,
required: true, required: true,
}, },
size: {
type: Number,
required: false,
default: 16,
validator(value) {
return validSizes.includes(value);
},
},
borderless: {
type: Boolean,
required: false,
default: false,
},
}, },
computed: { computed: {
cssClass() { cssClass() {
const status = this.status.group; const status = this.status.group;
return `ci-status-icon ci-status-icon-${status} js-ci-status-icon-${status}`; 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> </script>
<template> <template>
<span :class="cssClass"> <span :class="cssClass">
<icon :name="status.icon" /> <icon
:name="icon"
:size="size"
/>
</span> </span>
</template> </template>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment