Harmonize pipeline status information and add a review link to the approval (#2345)

Ref:
https://github.com/woodpecker-ci/woodpecker/discussions/2162#discussioncomment-6666864

Adds a `PipelineInfo` view to harmonize pipeline status information and
add a review link to the approval view.


![image](https://github.com/woodpecker-ci/woodpecker/assets/3391958/41062b5f-0f15-4c3c-b72c-e22092804072)


![image](https://github.com/woodpecker-ci/woodpecker/assets/3391958/4cfb1bc8-8bfd-4217-bce3-c9a1378f58ee)


![image](https://github.com/woodpecker-ci/woodpecker/assets/3391958/f3b22a07-464e-4d29-85f0-de122bce1bbe)

---------

Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: qwerty287 <80460567+qwerty287@users.noreply.github.com>
This commit is contained in:
Robert Kaussow 2023-09-09 08:35:53 +02:00 committed by GitHub
parent 41f6ecfa1b
commit 5c2f02c4a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 18 deletions

1
web/components.d.ts vendored
View file

@ -83,6 +83,7 @@ declare module '@vue/runtime-core' {
Panel: typeof import('./src/components/layout/Panel.vue')['default'] Panel: typeof import('./src/components/layout/Panel.vue')['default']
PipelineFeedItem: typeof import('./src/components/pipeline-feed/PipelineFeedItem.vue')['default'] PipelineFeedItem: typeof import('./src/components/pipeline-feed/PipelineFeedItem.vue')['default']
PipelineFeedSidebar: typeof import('./src/components/pipeline-feed/PipelineFeedSidebar.vue')['default'] PipelineFeedSidebar: typeof import('./src/components/pipeline-feed/PipelineFeedSidebar.vue')['default']
PipelineInfo: typeof import('./src/components/repo/pipeline/PipelineInfo.vue')['default']
PipelineItem: typeof import('./src/components/repo/pipeline/PipelineItem.vue')['default'] PipelineItem: typeof import('./src/components/repo/pipeline/PipelineItem.vue')['default']
PipelineList: typeof import('./src/components/repo/pipeline/PipelineList.vue')['default'] PipelineList: typeof import('./src/components/repo/pipeline/PipelineList.vue')['default']
PipelineLog: typeof import('./src/components/repo/pipeline/PipelineLog.vue')['default'] PipelineLog: typeof import('./src/components/repo/pipeline/PipelineLog.vue')['default']

View file

@ -255,7 +255,8 @@
"log_auto_scroll_off": "Turn off automatic scrolling" "log_auto_scroll_off": "Turn off automatic scrolling"
}, },
"protected": { "protected": {
"awaits": "This pipeline is awaiting approval by some maintainer!", "review": "Review changes",
"awaits": "This pipeline is awaiting approval by a maintainer!",
"approve": "Approve", "approve": "Approve",
"decline": "Decline", "decline": "Decline",
"declined": "This pipeline has been declined!", "declined": "This pipeline has been declined!",

View file

@ -0,0 +1,9 @@
<template>
<div class="w-full md:px-4 text-wp-text-100">
<div
class="flex flex-col px-4 py-8 gap-4 justify-center items-center text-center flex-shrink-0 rounded-md border bg-wp-background-100 border-wp-background-400 dark:bg-wp-background-200"
>
<slot />
</div>
</div>
</template>

View file

@ -9,15 +9,26 @@
/> />
<div class="flex flex-grow relative"> <div class="flex flex-grow relative">
<div v-if="error" class="flex flex-col p-4"> <PipelineInfo v-if="error">
<span class="text-wp-state-error-100 font-bold text-xl mb-2">{{ $t('repo.pipeline.execution_error') }}</span> <Icon name="status-error" class="w-16 h-16 text-wp-state-error-100" />
<span class="text-wp-state-error-100">{{ error }}</span> <div class="flex flex-wrap items-center justify-center gap-2 text-xl">
</div> <span class="capitalize">{{ $t('repo.pipeline.execution_error') }}:</span>
<span>{{ error }}</span>
</div>
</PipelineInfo>
<div v-else-if="pipeline.status === 'blocked'" class="flex flex-col flex-grow justify-center items-center p-2"> <PipelineInfo v-else-if="pipeline.status === 'blocked'">
<Icon name="status-blocked" class="w-16 h-16 text-wp-text-100 mb-4" /> <Icon name="status-blocked" class="w-16 h-16" />
<p class="text-xl text-wp-text-100 mb-4">{{ $t('repo.pipeline.protected.awaits') }}</p> <span class="text-xl">{{ $t('repo.pipeline.protected.awaits') }}</span>
<div v-if="repoPermissions.push" class="flex space-x-4"> <div v-if="repoPermissions.push" class="flex gap-2 flex-wrap items-center justify-center">
<Button
color="blue"
:start-icon="forge ?? 'repo'"
:text="$t('repo.pipeline.protected.review')"
:is-loading="isApprovingPipeline"
:to="pipeline.link_url"
:title="message"
/>
<Button <Button
color="green" color="green"
:text="$t('repo.pipeline.protected.approve')" :text="$t('repo.pipeline.protected.approve')"
@ -31,12 +42,12 @@
@click="declinePipeline" @click="declinePipeline"
/> />
</div> </div>
</div> </PipelineInfo>
<div v-else-if="pipeline.status === 'declined'" class="flex flex-col flex-grow justify-center items-center"> <PipelineInfo v-else-if="pipeline.status === 'declined'">
<Icon name="status-blocked" class="w-16 h-16 text-wp-text-100 mb-4" /> <Icon name="status-blocked" class="w-16 h-16" />
<p class="text-xl text-wp-text-100">{{ $t('repo.pipeline.protected.declined') }}</p> <p class="text-xl">{{ $t('repo.pipeline.protected.declined') }}</p>
</div> </PipelineInfo>
<PipelineLog <PipelineLog
v-else-if="selectedStepId" v-else-if="selectedStepId"
@ -61,7 +72,9 @@ import PipelineLog from '~/components/repo/pipeline/PipelineLog.vue';
import PipelineStepList from '~/components/repo/pipeline/PipelineStepList.vue'; import PipelineStepList from '~/components/repo/pipeline/PipelineStepList.vue';
import useApiClient from '~/compositions/useApiClient'; import useApiClient from '~/compositions/useApiClient';
import { useAsyncAction } from '~/compositions/useAsyncAction'; import { useAsyncAction } from '~/compositions/useAsyncAction';
import useConfig from '~/compositions/useConfig';
import useNotifications from '~/compositions/useNotifications'; import useNotifications from '~/compositions/useNotifications';
import usePipeline from '~/compositions/usePipeline';
import { Pipeline, PipelineStep, Repo, RepoPermissions } from '~/lib/api/types'; import { Pipeline, PipelineStep, Repo, RepoPermissions } from '~/lib/api/types';
import { findStep } from '~/utils/helpers'; import { findStep } from '~/utils/helpers';
@ -125,6 +138,9 @@ const selectedStepId = computed({
}, },
}); });
const { forge } = useConfig();
const { message } = usePipeline(pipeline);
const selectedStep = computed(() => findStep(pipeline.value.workflows || [], selectedStepId.value || -1)); const selectedStep = computed(() => findStep(pipeline.value.workflows || [], selectedStepId.value || -1));
const error = computed(() => pipeline.value?.error || selectedStep.value?.error); const error = computed(() => pipeline.value?.error || selectedStep.value?.error);

View file

@ -11,8 +11,8 @@
<template #title>{{ repo.full_name }}</template> <template #title>{{ repo.full_name }}</template>
<template #titleActions> <template #titleActions>
<div class="flex md:items-center flex-col gap-x-2 md:flex-row md:justify-between min-w-0"> <div class="flex md:items-center flex-col gap-2 md:flex-row md:justify-between min-w-0">
<div class="flex content-start gap-x-2 py-2 md:mr-2 min-w-0"> <div class="flex content-start gap-2 min-w-0">
<PipelineStatusIcon :status="pipeline.status" class="flex flex-shrink-0" /> <PipelineStatusIcon :status="pipeline.status" class="flex flex-shrink-0" />
<span class="flex-shrink-0 text-center">{{ $t('repo.pipeline.pipeline', { pipelineId }) }}</span> <span class="flex-shrink-0 text-center">{{ $t('repo.pipeline.pipeline', { pipelineId }) }}</span>
<span class="hidden md:inline-block">-</span> <span class="hidden md:inline-block">-</span>
@ -21,7 +21,7 @@
}}</span> }}</span>
</div> </div>
<template v-if="repoPermissions.push"> <template v-if="repoPermissions.push && pipeline.status !== 'declined' && pipeline.status !== 'blocked'">
<div class="flex content-start gap-x-2"> <div class="flex content-start gap-x-2">
<Button <Button
v-if="pipeline.status === 'pending' || pipeline.status === 'running'" v-if="pipeline.status === 'pending' || pipeline.status === 'running'"
@ -31,7 +31,6 @@
@click="cancelPipeline" @click="cancelPipeline"
/> />
<Button <Button
v-else-if="pipeline.status !== 'blocked' && pipeline.status !== 'declined'"
class="flex-shrink-0" class="flex-shrink-0"
:text="$t('repo.pipeline.actions.restart')" :text="$t('repo.pipeline.actions.restart')"
:is-loading="isRestartingPipeline" :is-loading="isRestartingPipeline"