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:
qwerty287 2024-06-06 12:23:04 +02:00 committed by GitHub
parent d28e150534
commit 2aa8531ad6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 33 additions and 36 deletions

1
web/components.d.ts vendored
View File

@ -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']

View File

@ -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>

View File

@ -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>

View File

@ -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 () => {