mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-05-14 04:02:40 +00:00
170 lines
5.5 KiB
Vue
170 lines
5.5 KiB
Vue
<template>
|
|
<div class="flex flex-col flex-grow">
|
|
<div class="flex w-full min-h-0 flex-grow">
|
|
<BuildProcList v-model:selected-proc-id="selectedProcId" :build="build" />
|
|
|
|
<div class="flex flex-grow relative">
|
|
<div v-if="error" class="flex flex-col p-4">
|
|
<span class="text-red-400 font-bold text-xl mb-2">{{ $t('repo.build.execution_error') }}</span>
|
|
<span class="text-red-400">{{ error }}</span>
|
|
</div>
|
|
|
|
<div v-else-if="build.status === 'blocked'" class="flex flex-col flex-grow justify-center items-center">
|
|
<Icon name="status-blocked" class="w-32 h-32 text-color" />
|
|
<p class="text-xl text-color">{{ $t('repo.build.protected.awaits') }}</p>
|
|
<div v-if="repoPermissions.push" class="flex mt-2 space-x-4">
|
|
<Button
|
|
color="green"
|
|
:text="$t('repo.build.protected.approve')"
|
|
:is-loading="isApprovingBuild"
|
|
@click="approveBuild"
|
|
/>
|
|
<Button
|
|
color="red"
|
|
:text="$t('repo.build.protected.decline')"
|
|
:is-loading="isDecliningBuild"
|
|
@click="declineBuild"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-else-if="build.status === 'declined'" class="flex flex-col flex-grow justify-center items-center">
|
|
<Icon name="status-blocked" class="w-32 h-32 text-color" />
|
|
<p class="text-xl text-color">{{ $t('repo.build.protected.declined') }}</p>
|
|
</div>
|
|
|
|
<BuildLog
|
|
v-else-if="selectedProcId"
|
|
v-model:proc-id="selectedProcId"
|
|
:build="build"
|
|
class="fixed top-0 left-0 w-full h-full md:absolute"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { computed, defineComponent, inject, PropType, Ref, toRef } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
import Button from '~/components/atomic/Button.vue';
|
|
import Icon from '~/components/atomic/Icon.vue';
|
|
import BuildLog from '~/components/repo/build/BuildLog.vue';
|
|
import BuildProcList from '~/components/repo/build/BuildProcList.vue';
|
|
import useApiClient from '~/compositions/useApiClient';
|
|
import { useAsyncAction } from '~/compositions/useAsyncAction';
|
|
import useNotifications from '~/compositions/useNotifications';
|
|
import { Build, BuildProc, Repo, RepoPermissions } from '~/lib/api/types';
|
|
import { findProc } from '~/utils/helpers';
|
|
|
|
export default defineComponent({
|
|
name: 'Build',
|
|
|
|
components: {
|
|
Button,
|
|
BuildProcList,
|
|
Icon,
|
|
BuildLog,
|
|
},
|
|
|
|
props: {
|
|
// used by toRef
|
|
// eslint-disable-next-line vue/no-unused-properties
|
|
procId: {
|
|
type: String as PropType<string | null>,
|
|
default: null,
|
|
},
|
|
},
|
|
|
|
setup(props) {
|
|
const apiClient = useApiClient();
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
const notifications = useNotifications();
|
|
|
|
const build = inject<Ref<Build>>('build');
|
|
const repo = inject<Ref<Repo>>('repo');
|
|
const repoPermissions = inject<Ref<RepoPermissions>>('repo-permissions');
|
|
if (!repo || !repoPermissions || !build) {
|
|
throw new Error('Unexpected: "repo", "repoPermissions" & "build" should be provided at this place');
|
|
}
|
|
|
|
const procId = toRef(props, 'procId');
|
|
|
|
const defaultProcId = computed(() => {
|
|
if (!build.value || !build.value.procs || !build.value.procs[0].children) {
|
|
return null;
|
|
}
|
|
|
|
return build.value.procs[0].children[0].pid;
|
|
});
|
|
|
|
const selectedProcId = computed({
|
|
get() {
|
|
if (procId.value !== '' && procId.value !== null) {
|
|
const id = parseInt(procId.value, 10);
|
|
const proc = build.value?.procs?.reduce(
|
|
(prev, p) => prev || p.children?.find((c) => c.pid === id),
|
|
undefined as BuildProc | undefined,
|
|
);
|
|
if (proc) {
|
|
return proc.pid;
|
|
}
|
|
|
|
// return fallback if proc-id is provided, but proc can not be found
|
|
return defaultProcId.value;
|
|
}
|
|
|
|
// is opened on >= md-screen
|
|
if (window.innerWidth > 768) {
|
|
return defaultProcId.value;
|
|
}
|
|
|
|
return null;
|
|
},
|
|
set(_selectedProcId: number | null) {
|
|
if (!_selectedProcId) {
|
|
router.replace({ params: { ...route.params, procId: '' } });
|
|
return;
|
|
}
|
|
|
|
router.replace({ params: { ...route.params, procId: `${_selectedProcId}` } });
|
|
},
|
|
});
|
|
|
|
const selectedProc = computed(() => findProc(build.value.procs || [], selectedProcId.value || -1));
|
|
const error = computed(() => build.value?.error || selectedProc.value?.error);
|
|
|
|
const { doSubmit: approveBuild, isLoading: isApprovingBuild } = useAsyncAction(async () => {
|
|
if (!repo) {
|
|
throw new Error('Unexpected: Repo is undefined');
|
|
}
|
|
|
|
await apiClient.approveBuild(repo.value.owner, repo.value.name, `${build.value.number}`);
|
|
notifications.notify({ title: 'Pipeline approved', type: 'success' });
|
|
});
|
|
|
|
const { doSubmit: declineBuild, isLoading: isDecliningBuild } = useAsyncAction(async () => {
|
|
if (!repo) {
|
|
throw new Error('Unexpected: Repo is undefined');
|
|
}
|
|
|
|
await apiClient.declineBuild(repo.value.owner, repo.value.name, `${build.value.number}`);
|
|
notifications.notify({ title: 'Pipeline declined', type: 'success' });
|
|
});
|
|
|
|
return {
|
|
repoPermissions,
|
|
selectedProcId,
|
|
build,
|
|
error,
|
|
isApprovingBuild,
|
|
isDecliningBuild,
|
|
approveBuild,
|
|
declineBuild,
|
|
};
|
|
},
|
|
});
|
|
</script>
|