Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance pipeline list #3898

Merged
merged 40 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
9b85108
Update pipeline list UI
anbraten Jan 30, 2024
79df566
Merge remote-tracking branch 'upstream/main' into update-pipeline-list
anbraten Feb 10, 2024
9bfd2f3
gitea parse email too
6543 Feb 21, 2024
d07b161
example how tests should be
6543 Feb 21, 2024
fb627db
fix similar bugs
6543 Feb 22, 2024
0cf1fb6
tests tests tests
6543 Feb 22, 2024
9a9231b
Merge branch 'main' into gitea-parse-mail-too
6543 Feb 22, 2024
55441bf
move old tests to new tests
6543 Feb 22, 2024
2b4e136
tags dont have branch info
6543 Feb 22, 2024
7165ef5
extend tests and finish migration
6543 Feb 22, 2024
c691b31
fix
6543 Feb 22, 2024
7db9650
actually differ between title and message and use it propperly
6543 Feb 22, 2024
d1f49c0
refactor
6543 Feb 22, 2024
7f23b07
update tests etc...
6543 Feb 22, 2024
f25b7b0
fix test
6543 Feb 22, 2024
ada1819
dont forget the gitlab
6543 Feb 22, 2024
3812c62
bitbucket
6543 Feb 22, 2024
b0d5168
Merge branch 'main' into actually-use-title
6543 Feb 22, 2024
114ba6a
Merge branch 'main' into actually-use-title
6543 Feb 22, 2024
59086fe
Merge branch 'main' into actually-use-title
6543 Feb 23, 2024
9df94d8
Merge branch 'main' into actually-use-title2
6543 Jun 3, 2024
7344a90
Merge remote-tracking branch 'upstream/main' into update-pipeline-list
anbraten Jun 24, 2024
36cf5af
adjust pipeline item
anbraten Jun 25, 2024
a0960bb
Merge branch 'update-pipeline-list' into pr/6543/3421-1
anbraten Jun 25, 2024
f89f4e8
Merge branch 'main' into actually-use-title
anbraten Jun 25, 2024
ba83f48
Merge branch 'main' into actually-use-title
6543 Jun 26, 2024
acc52fc
Merge remote-tracking branch 'upstream/main' into pr/6543/3421
anbraten Jul 2, 2024
756f9ea
Merge branch 'actually-use-title' of github.com:6543-forks/woodpecker…
anbraten Jul 2, 2024
39d5350
adjust pipeline message and title
anbraten Jul 2, 2024
87946fa
adjust ui text
anbraten Jul 2, 2024
651663c
adjust to proper values
anbraten Jul 2, 2024
fbc586e
Merge branch 'main' into actually-use-title
6543 Jul 2, 2024
020aa18
Merge remote-tracking branch 'upstream/main' into pr/6543/3421
anbraten Jul 13, 2024
6c12da1
Merge branch 'actually-use-title' of github.com:6543-forks/woodpecker…
anbraten Jul 13, 2024
c5f6477
undo
anbraten Jul 13, 2024
1908a1e
Merge remote-tracking branch 'upstream/main' into refactor-pipeline-list
anbraten Jul 13, 2024
1543b0e
add warning and i18n
anbraten Jul 13, 2024
8b1bd84
Merge branch 'main' into refactor-pipeline-list
anbraten Jul 13, 2024
b996c44
fix lint
anbraten Jul 13, 2024
3fcbcf1
Merge branch 'refactor-pipeline-list' of github.com:anbraten/woodpeck…
anbraten Jul 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion web/src/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@
"push": "Push",
"tag": "Tag",
"pr": "Pull Request",
"pr_closed": "Pull Request merged / closed",
"deploy": "Deploy",
"cron": "Cron",
"manual": "Manual",
Expand Down Expand Up @@ -466,5 +467,15 @@
"internal_error": "Some internal error occurred",
"registration_closed": "The registration is closed",
"access_denied": "You are not allowed to access this instance",
"invalid_state": "The OAuth state is invalid"
"invalid_state": "The OAuth state is invalid",
"by_user": "by {user}",
"pushed_to": "pushed to",
"closed": "closed",
"deployed_to": "deployed to",
"created": "created",
"triggered": "triggered",
"pipeline_duration": "Pipeline duration",
"pipeline_since": "Pipeline was created {created} minutes ago",
"pipeline_has_warnings": "The pipeline has warnings",
"pipeline_has_errors": "The pipeline has errors"
}
4 changes: 2 additions & 2 deletions web/src/components/pipeline-feed/PipelineFeedItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
{{ repo?.owner }} / {{ repo?.name }}
</router-link>
<span class="whitespace-nowrap overflow-hidden overflow-ellipsis" :title="message">{{ title }}</span>
<span class="whitespace-nowrap overflow-hidden overflow-ellipsis" :title="message">{{ shortMessage }}</span>
<div class="flex flex-col mt-2">
<div class="flex space-x-2 items-center" :title="created">
<Icon name="since" />
Expand Down Expand Up @@ -45,5 +45,5 @@ const repoStore = useRepoStore();
const pipeline = toRef(props, 'pipeline');
const repo = repoStore.getRepo(computed(() => pipeline.value.repo_id));

const { since, duration, message, title, created } = usePipeline(pipeline);
const { since, duration, shortMessage, message, created } = usePipeline(pipeline);
</script>
126 changes: 82 additions & 44 deletions web/src/components/repo/pipeline/PipelineItem.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template>
<ListItem v-if="pipeline" class="p-0 w-full">
<div class="flex w-11 items-center md:mr-4">
<div class="flex w-6 items-center md:mr-4">
<div
class="h-full w-3"
class="h-full w-2 flex-shrink-0"
:class="{
'bg-wp-state-warn-100': pipeline.status === 'pending',
'bg-wp-state-error-100': pipelineStatusColors[pipeline.status] === 'red',
Expand All @@ -11,79 +11,117 @@
'bg-wp-state-info-100': pipelineStatusColors[pipeline.status] === 'blue',
}"
/>
<div class="w-8 flex flex-wrap justify-between items-center h-full">
<div class="w-6 flex flex-wrap justify-between items-center h-full">
<PipelineRunningIcon v-if="pipeline.status === 'started' || pipeline.status === 'running'" />
<PipelineStatusIcon v-else class="mx-2 md:mx-3" :status="pipeline.status" />
</div>
</div>

<div class="flex py-2 px-4 flex-grow min-w-0 <md:flex-wrap">
<div class="<md:hidden flex items-center flex-shrink-0">
<Icon v-if="pipeline.event === 'cron'" name="stopwatch" class="text-wp-text-100" />
<img v-else class="rounded-md w-8" :src="pipeline.author_avatar" />
</div>

<div class="w-full md:w-auto md:mx-4 flex items-center min-w-0">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
<span class="text-wp-text-alt-100 <md:hidden">#{{ pipeline.number }}</span>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
<span class="text-wp-text-alt-100 <md:hidden mx-2">-</span>
<span
class="text-wp-text-100 <md:underline whitespace-nowrap overflow-hidden overflow-ellipsis"
:title="message"
>
{{ title }}
<div class="flex py-2 px-4 flex-grow min-w-0 <md:flex-wrap gap-2">
<div class="flex flex-col min-w-0 justify-center gap-2">
<span class="text-wp-text-100 text-lg whitespace-nowrap overflow-hidden overflow-ellipsis" :title="message">
{{ shortMessage }}
</span>
</div>

<div
class="grid grid-rows-2 grid-flow-col w-full md:ml-auto md:w-96 py-2 gap-x-4 gap-y-2 flex-shrink-0 text-wp-text-100"
>
<div class="flex space-x-2 items-center min-w-0">
<Icon v-if="pipeline.event === 'pull_request'" name="pull-request" />
<Icon v-else-if="pipeline.event === 'pull_request_closed'" name="pull-request-closed" />
<Icon v-else-if="pipeline.event === 'deployment'" name="deployment" />
<Icon v-else-if="pipeline.event === 'tag' || pipeline.event === 'release'" name="tag" />
<Icon v-else-if="pipeline.event === 'cron'" name="push" />
<Icon v-else-if="pipeline.event === 'manual'" name="manual-pipeline" />
<Icon v-else name="push" />
<span class="truncate">{{ prettyRef }}</span>
</div>
<div class="flex <md:flex-wrap gap-1 text-wp-text-alt-100">
<div class="flex items-center" :title="pipelineEventTitle">
<Icon v-if="pipeline.event === 'pull_request'" name="pull-request" />
<Icon v-else-if="pipeline.event === 'pull_request_closed'" name="pull-request-closed" />
<Icon v-else-if="pipeline.event === 'deployment'" name="deployment" />
<Icon v-else-if="pipeline.event === 'tag' || pipeline.event === 'release'" name="tag" />
<Icon v-else-if="pipeline.event === 'cron'" name="push" />
<Icon v-else-if="pipeline.event === 'manual'" name="manual-pipeline" />
<Icon v-else name="push" />
</div>

<a :href="pipeline.forge_url" target="_blank" class="underline" :title="pipeline.commit">
<Badge :label="pipeline.commit.slice(0, 7)" />
</a>

<div class="flex space-x-2 items-center min-w-0">
<Icon name="commit" />
<span class="truncate">{{ pipeline.commit.slice(0, 10) }}</span>
<span v-if="pipeline.event === 'pull_request' || pipeline.event === 'push'">{{ $t('pushed_to') }}</span>
<span v-if="pipeline.event === 'pull_request_closed'">{{ $t('closed') }}</span>
<span v-if="pipeline.event === 'deployment'">{{ $t('deployed_to') }}</span>
<span v-if="pipeline.event === 'tag' || pipeline.event === 'release'">{{ $t('created') }}</span>
<span v-if="pipeline.event === 'cron' || pipeline.event === 'manual'">{{ $t('triggered') }}</span>
<span v-else>{{ $t('triggered') }}</span>
<Badge
v-if="prettyRef"
:title="prTitleWithDescription"
:label="prTitle ? `${prettyRef} (${truncate(prTitle, 30)})` : prettyRef"
/>
<span class="truncate">{{ $t('by_user', { user: pipeline.author }) }}</span>
</div>
</div>

<div class="flex min-w-0 <md:w-full gap-2 justify-between items-center md:ml-auto relative">
<div class="flex flex-col gap-2 text-wp-text-alt-100">
<div class="flex gap-2 items-center min-w-0" :title="$t('pipeline_duration')">
<Icon name="duration" />
<span class="truncate">{{ duration }}</span>
</div>

<div class="flex space-x-2 items-center min-w-0">
<Icon name="duration" />
<span class="truncate">{{ duration }}</span>
<div class="flex gap-2 items-center min-w-0" :title="$t('pipeline_since', { created })">
<Icon name="since" />
<span>{{ since }}</span>
</div>
</div>

<div class="flex space-x-2 items-center min-w-0" :title="created">
<Icon name="since" />
<span>{{ since }}</span>
<Icon v-if="pipeline.event === 'cron'" name="stopwatch" class="text-wp-text-100" />
<img v-else class="rounded-md w-8 flex-shrink-0" :src="pipeline.author_avatar" :title="pipeline.author" />

<div v-if="pipeline.errors" class="flex items-center absolute -top-1 -right-2">
<Icon v-if="hasErrors" name="attention" class="text-wp-state-error-100" :title="$t('pipeline_has_errors')" />
<Icon v-else name="warning" class="text-wp-state-warn-100" :title="$t('pipeline_has_warnings')" />
</div>
</div>
</div>
</ListItem>
</template>

<script lang="ts" setup>
import { toRef } from 'vue';
import { computed, toRef } from 'vue';
import { useI18n } from 'vue-i18n';

import Badge from '~/components/atomic/Badge.vue';
import Icon from '~/components/atomic/Icon.vue';
import ListItem from '~/components/atomic/ListItem.vue';
import { pipelineStatusColors } from '~/components/repo/pipeline/pipeline-status';
import PipelineRunningIcon from '~/components/repo/pipeline/PipelineRunningIcon.vue';
import PipelineStatusIcon from '~/components/repo/pipeline/PipelineStatusIcon.vue';
import usePipeline from '~/compositions/usePipeline';
import type { Pipeline } from '~/lib/api/types';
import { truncate } from '~/utils/locale';

const props = defineProps<{
pipeline: Pipeline;
}>();

const { t } = useI18n();

const pipeline = toRef(props, 'pipeline');
const { since, duration, message, title, prettyRef, created } = usePipeline(pipeline);
const { since, duration, message, shortMessage, prTitle, prTitleWithDescription, prettyRef, created } =
usePipeline(pipeline);

const hasErrors = computed(() => pipeline.value.errors?.some((e) => !e.is_warning));

const pipelineEventTitle = computed(() => {
switch (pipeline.value.event) {
case 'pull_request':
return t('repo.pipeline.event.pr');
case 'pull_request_closed':
return t('repo.pipeline.event.pr_closed');
case 'deployment':
return t('repo.pipeline.event.deploy');
case 'tag':
return t('repo.pipeline.event.tag');
case 'release':
return t('repo.pipeline.event.release');
case 'cron':
return t('repo.pipeline.event.cron');
case 'manual':
return t('repo.pipeline.event.manual');
default:
return t('repo.pipeline.event.push');
}
});
</script>
17 changes: 7 additions & 10 deletions web/src/compositions/usePipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export default (pipeline: Ref<Pipeline | undefined>) => {
const i18n = useI18n();
const since = computed(() => {
if (sinceRaw.value === 0) {
return i18n.t('time.not_started');
// return i18n.t('time.not_started');
return '-';
}

if (sinceElapsed.value === undefined) {
Expand Down Expand Up @@ -73,15 +74,11 @@ export default (pipeline: Ref<Pipeline | undefined>) => {
return prettyDuration(durationElapsed.value);
});

const message = computed(() => {
if (!pipeline.value) {
return '';
}

return convertEmojis(pipeline.value.message);
});
const message = computed(() => convertEmojis(pipeline.value?.message ?? ''));
const shortMessage = computed(() => message.value.split('\n')[0]);

const title = computed(() => message.value.split('\n')[0]);
const prTitleWithDescription = computed(() => convertEmojis(pipeline.value?.title ?? ''));
const prTitle = computed(() => prTitleWithDescription.value.split('\n')[0]);

const prettyRef = computed(() => {
if (pipeline.value?.event === 'push' || pipeline.value?.event === 'deployment') {
Expand Down Expand Up @@ -117,5 +114,5 @@ export default (pipeline: Ref<Pipeline | undefined>) => {
return toLocaleString(new Date(start * 1000));
});

return { since, duration, message, title, prettyRef, created };
return { since, duration, message, shortMessage, prTitle, prTitleWithDescription, prettyRef, created };
};
8 changes: 8 additions & 0 deletions web/src/utils/locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ export function getUserLanguage(): string {

return selectedLocale;
}

export function truncate(text: string, length: number): string {
if (text.length <= length) {
return text;
}

return `${text.slice(0, length)}...`;
}
6 changes: 4 additions & 2 deletions web/src/views/repo/pipeline/PipelineWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
<span class="flex-shrink-0 text-center">{{ $t('repo.pipeline.pipeline', { pipelineId }) }}</span>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
<span class="hidden md:inline-block">-</span>
<span class="min-w-0 whitespace-nowrap overflow-hidden overflow-ellipsis" :title="message">{{ title }}</span>
<span class="min-w-0 whitespace-nowrap overflow-hidden overflow-ellipsis" :title="message">{{
shortMessage
}}</span>
</div>

<template v-if="repoPermissions!.push && pipeline.status !== 'declined' && pipeline.status !== 'blocked'">
Expand Down Expand Up @@ -138,7 +140,7 @@ if (!repo || !repoPermissions) {
}

const pipeline = pipelineStore.getPipeline(repositoryId, pipelineId);
const { since, duration, created, message, title } = usePipeline(pipeline);
const { since, duration, created, message, shortMessage } = usePipeline(pipeline);
provide('pipeline', pipeline);

const pipelineConfigs = ref<PipelineConfig[]>();
Expand Down