mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-08-11 12:23:43 +00:00
Show workflow names if there are multiple configs (#3767)
Co-authored-by: Tchoupinax <corentinfiloche@hotmail.fr> Co-authored-by: Anbraten <6918444+anbraten@users.noreply.github.com>
This commit is contained in:
parent
d28e150534
commit
2aa8531ad6
1
web/components.d.ts
vendored
1
web/components.d.ts
vendored
@ -75,6 +75,7 @@ declare module 'vue' {
|
|||||||
IMdiTagOutline: typeof import('~icons/mdi/tag-outline')['default']
|
IMdiTagOutline: typeof import('~icons/mdi/tag-outline')['default']
|
||||||
InputField: typeof import('./src/components/form/InputField.vue')['default']
|
InputField: typeof import('./src/components/form/InputField.vue')['default']
|
||||||
IPhGitlabLogoSimpleFill: typeof import('~icons/ph/gitlab-logo-simple-fill')['default']
|
IPhGitlabLogoSimpleFill: typeof import('~icons/ph/gitlab-logo-simple-fill')['default']
|
||||||
|
ISimpleIconsForgejo: typeof import('~icons/simple-icons/forgejo')['default']
|
||||||
ISimpleIconsGitea: typeof import('~icons/simple-icons/gitea')['default']
|
ISimpleIconsGitea: typeof import('~icons/simple-icons/gitea')['default']
|
||||||
ISvgSpinners180RingWithBg: typeof import('~icons/svg-spinners/180-ring-with-bg')['default']
|
ISvgSpinners180RingWithBg: typeof import('~icons/svg-spinners/180-ring-with-bg')['default']
|
||||||
ITeenyiconsGitSolid: typeof import('~icons/teenyicons/git-solid')['default']
|
ITeenyiconsGitSolid: typeof import('~icons/teenyicons/git-solid')['default']
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
v-if="pipeline.workflows && pipeline.workflows.length > 1"
|
v-if="!singleConfig"
|
||||||
type="button"
|
type="button"
|
||||||
:title="workflow.name"
|
:title="workflow.name"
|
||||||
class="flex items-center gap-2 py-2 px-1 hover-effect hover:bg-wp-background-300 dark:hover:bg-wp-background-400 rounded-md"
|
class="flex items-center gap-2 py-2 px-1 hover-effect hover:bg-wp-background-300 dark:hover:bg-wp-background-400 rounded-md"
|
||||||
@ -92,7 +92,7 @@
|
|||||||
class="transition-height duration-150 overflow-hidden"
|
class="transition-height duration-150 overflow-hidden"
|
||||||
:class="{
|
:class="{
|
||||||
'max-h-0': workflowsCollapsed[workflow.id],
|
'max-h-0': workflowsCollapsed[workflow.id],
|
||||||
'ml-6': pipeline.workflows && pipeline.workflows.length > 1,
|
'ml-6': !singleConfig,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@ -103,9 +103,7 @@
|
|||||||
class="flex p-2 gap-2 border-2 border-transparent rounded-md items-center hover-effect hover:bg-wp-background-300 dark:hover:bg-wp-background-400 w-full"
|
class="flex p-2 gap-2 border-2 border-transparent rounded-md items-center hover-effect hover:bg-wp-background-300 dark:hover:bg-wp-background-400 w-full"
|
||||||
:class="{
|
:class="{
|
||||||
'bg-wp-background-300 dark:bg-wp-background-400': selectedStepId && selectedStepId === step.pid,
|
'bg-wp-background-300 dark:bg-wp-background-400': selectedStepId && selectedStepId === step.pid,
|
||||||
'mt-1':
|
'mt-1': !singleConfig || (workflow.children && step.pid !== workflow.children[0].pid),
|
||||||
(pipeline.workflows && pipeline.workflows.length > 1) ||
|
|
||||||
(workflow.children && step.pid !== workflow.children[0].pid),
|
|
||||||
}"
|
}"
|
||||||
@click="$emit('update:selected-step-id', step.pid)"
|
@click="$emit('update:selected-step-id', step.pid)"
|
||||||
>
|
>
|
||||||
@ -121,7 +119,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, toRef } from 'vue';
|
import { computed, inject, Ref, ref, toRef } from 'vue';
|
||||||
|
|
||||||
import Badge from '~/components/atomic/Badge.vue';
|
import Badge from '~/components/atomic/Badge.vue';
|
||||||
import Icon from '~/components/atomic/Icon.vue';
|
import Icon from '~/components/atomic/Icon.vue';
|
||||||
@ -129,7 +127,7 @@ import Panel from '~/components/layout/Panel.vue';
|
|||||||
import PipelineStatusIcon from '~/components/repo/pipeline/PipelineStatusIcon.vue';
|
import PipelineStatusIcon from '~/components/repo/pipeline/PipelineStatusIcon.vue';
|
||||||
import PipelineStepDuration from '~/components/repo/pipeline/PipelineStepDuration.vue';
|
import PipelineStepDuration from '~/components/repo/pipeline/PipelineStepDuration.vue';
|
||||||
import usePipeline from '~/compositions/usePipeline';
|
import usePipeline from '~/compositions/usePipeline';
|
||||||
import { Pipeline, PipelineStep, StepType } from '~/lib/api/types';
|
import { Pipeline, PipelineConfig, PipelineStep, StepType } from '~/lib/api/types';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
pipeline: Pipeline;
|
pipeline: Pipeline;
|
||||||
@ -143,6 +141,7 @@ defineEmits<{
|
|||||||
const pipeline = toRef(props, 'pipeline');
|
const pipeline = toRef(props, 'pipeline');
|
||||||
const selectedStepId = toRef(props, 'selectedStepId');
|
const selectedStepId = toRef(props, 'selectedStepId');
|
||||||
const { prettyRef } = usePipeline(pipeline);
|
const { prettyRef } = usePipeline(pipeline);
|
||||||
|
const pipelineConfigs = inject<Ref<PipelineConfig[]>>('pipeline-configs');
|
||||||
|
|
||||||
const workflowsCollapsed = ref<Record<PipelineStep['id'], boolean>>(
|
const workflowsCollapsed = ref<Record<PipelineStep['id'], boolean>>(
|
||||||
pipeline.value.workflows && pipeline.value.workflows.length > 1
|
pipeline.value.workflows && pipeline.value.workflows.length > 1
|
||||||
@ -157,4 +156,8 @@ const workflowsCollapsed = ref<Record<PipelineStep['id'], boolean>>(
|
|||||||
)
|
)
|
||||||
: {},
|
: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const singleConfig = computed(
|
||||||
|
() => pipelineConfigs?.value?.length === 1 && pipeline.value.workflows && pipeline.value.workflows.length === 1,
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-y-6">
|
<div class="flex flex-col gap-y-6">
|
||||||
<Panel
|
<Panel
|
||||||
v-for="pipelineConfig in pipelineConfigs || []"
|
v-for="pipelineConfig in pipelineConfigsDecoded || []"
|
||||||
:key="pipelineConfig.hash"
|
:key="pipelineConfig.hash"
|
||||||
:collapsable="pipelineConfigs && pipelineConfigs.length > 1"
|
:collapsable="pipelineConfigsDecoded && pipelineConfigsDecoded.length > 1"
|
||||||
collapsed-by-default
|
collapsed-by-default
|
||||||
:title="pipelineConfigs && pipelineConfigs.length > 1 ? pipelineConfig.name : ''"
|
:title="pipelineConfigsDecoded && pipelineConfigsDecoded.length > 1 ? pipelineConfig.name : ''"
|
||||||
>
|
>
|
||||||
<SyntaxHighlight class="font-mono whitespace-pre overflow-auto" language="yaml" :code="pipelineConfig.data" />
|
<SyntaxHighlight class="font-mono whitespace-pre overflow-auto" language="yaml" :code="pipelineConfig.data" />
|
||||||
</Panel>
|
</Panel>
|
||||||
@ -14,37 +14,21 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { decode } from 'js-base64';
|
import { decode } from 'js-base64';
|
||||||
import { inject, onMounted, Ref, ref, watch } from 'vue';
|
import { computed, inject, Ref } from 'vue';
|
||||||
|
|
||||||
import SyntaxHighlight from '~/components/atomic/SyntaxHighlight';
|
import SyntaxHighlight from '~/components/atomic/SyntaxHighlight';
|
||||||
import Panel from '~/components/layout/Panel.vue';
|
import Panel from '~/components/layout/Panel.vue';
|
||||||
import useApiClient from '~/compositions/useApiClient';
|
import { PipelineConfig } from '~/lib/api/types';
|
||||||
import { Pipeline, PipelineConfig, Repo } from '~/lib/api/types';
|
|
||||||
|
|
||||||
const pipeline = inject<Ref<Pipeline>>('pipeline');
|
const pipelineConfigs = inject<Ref<PipelineConfig[]>>('pipeline-configs');
|
||||||
const apiClient = useApiClient();
|
if (!pipelineConfigs) {
|
||||||
const repo = inject<Ref<Repo>>('repo');
|
throw new Error('Unexpected: "pipelineConfigs" should be provided at this place');
|
||||||
if (!repo || !pipeline) {
|
|
||||||
throw new Error('Unexpected: "repo" & "pipeline" should be provided at this place');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const pipelineConfigs = ref<PipelineConfig[]>();
|
const pipelineConfigsDecoded = computed(() =>
|
||||||
async function loadPipelineConfig() {
|
pipelineConfigs.value.map((i) => ({
|
||||||
if (!repo || !pipeline) {
|
|
||||||
throw new Error('Unexpected: "repo" & "pipeline" should be provided at this place');
|
|
||||||
}
|
|
||||||
|
|
||||||
pipelineConfigs.value = (await apiClient.getPipelineConfig(repo.value.id, pipeline.value.number)).map((i) => ({
|
|
||||||
...i,
|
...i,
|
||||||
data: decode(i.data),
|
data: decode(i.data),
|
||||||
}));
|
})),
|
||||||
}
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
loadPipelineConfig();
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(pipeline, () => {
|
|
||||||
loadPipelineConfig();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -116,7 +116,7 @@ import { useFavicon } from '~/compositions/useFavicon';
|
|||||||
import useNotifications from '~/compositions/useNotifications';
|
import useNotifications from '~/compositions/useNotifications';
|
||||||
import usePipeline from '~/compositions/usePipeline';
|
import usePipeline from '~/compositions/usePipeline';
|
||||||
import { useRouteBack } from '~/compositions/useRouteBack';
|
import { useRouteBack } from '~/compositions/useRouteBack';
|
||||||
import { Repo, RepoPermissions } from '~/lib/api/types';
|
import { PipelineConfig, Repo, RepoPermissions } from '~/lib/api/types';
|
||||||
import { usePipelineStore } from '~/store/pipelines';
|
import { usePipelineStore } from '~/store/pipelines';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -145,6 +145,9 @@ const pipeline = pipelineStore.getPipeline(repositoryId, pipelineId);
|
|||||||
const { since, duration, created, message, title } = usePipeline(pipeline);
|
const { since, duration, created, message, title } = usePipeline(pipeline);
|
||||||
provide('pipeline', pipeline);
|
provide('pipeline', pipeline);
|
||||||
|
|
||||||
|
const pipelineConfigs = ref<PipelineConfig[]>();
|
||||||
|
provide('pipeline-configs', pipelineConfigs);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
pipeline,
|
pipeline,
|
||||||
() => {
|
() => {
|
||||||
@ -161,6 +164,12 @@ async function loadPipeline(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await pipelineStore.loadPipeline(repo.value.id, parseInt(pipelineId.value, 10));
|
await pipelineStore.loadPipeline(repo.value.id, parseInt(pipelineId.value, 10));
|
||||||
|
|
||||||
|
if (!pipeline.value?.number) {
|
||||||
|
throw new Error('Unexpected: Pipeline number not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelineConfigs.value = await apiClient.getPipelineConfig(repo.value.id, pipeline.value.number);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { doSubmit: cancelPipeline, isLoading: isCancelingPipeline } = useAsyncAction(async () => {
|
const { doSubmit: cancelPipeline, isLoading: isCancelingPipeline } = useAsyncAction(async () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user