140 lines
4.0 KiB
Vue
140 lines
4.0 KiB
Vue
<template>
|
|
<CardDetails :showDetails="showDetails">
|
|
<div class="px-6 py-5">
|
|
<template v-if="showDetails">
|
|
<div class="flex items-center">
|
|
<Button
|
|
class="mr-3 md:hidden"
|
|
@click="$router.back()"
|
|
icon="chevron-left"
|
|
/>
|
|
<div>
|
|
<h4 class="text-lg font-medium">
|
|
{{ title }}
|
|
</h4>
|
|
<p class="mt-1 text-sm text-gray-600" v-if="subtitle">
|
|
{{ subtitle }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<div v-else>
|
|
<LoadingText v-if="loading" />
|
|
<span v-else class="text-base text-gray-600"> No item selected </span>
|
|
</div>
|
|
</div>
|
|
<div class="flex-auto overflow-auto" v-if="showDetails">
|
|
<details
|
|
:open="['Failure', 'Running'].includes(step.status)"
|
|
class="cursor-pointer px-6"
|
|
v-for="(step, index) in steps"
|
|
:key="step.name"
|
|
>
|
|
<summary
|
|
:ref="
|
|
['Failure', 'Running'].includes(step.status) ? 'openedSummary' : ''
|
|
"
|
|
class="inline-flex w-full items-center py-2 focus:outline-none"
|
|
>
|
|
<span class="ml-1">
|
|
<div
|
|
v-if="step.running"
|
|
class="grid h-4 w-4 place-items-center rounded-full bg-gray-50"
|
|
>
|
|
<Spinner class="h-3 w-3 text-gray-500" />
|
|
</div>
|
|
<div
|
|
v-else-if="step.status"
|
|
class="grid h-4 w-4 place-items-center rounded-full border"
|
|
:class="{
|
|
'border-green-500 bg-green-50': step.completed,
|
|
'border-red-500 bg-red-50': step.status === 'Failure',
|
|
'border-gray-500 bg-gray-50': step.status === 'Skipped'
|
|
}"
|
|
>
|
|
<FeatherIcon
|
|
:name="
|
|
// prettier-ignore
|
|
step.completed
|
|
? 'check'
|
|
: step.status === 'Failure'
|
|
? 'x'
|
|
: step.status === 'Skipped'
|
|
? 'minus'
|
|
: 'clock'
|
|
"
|
|
:class="{
|
|
'text-green-500': step.completed,
|
|
'text-red-500': step.status === 'Failure',
|
|
'text-gray-500': step.status === 'Skipped'
|
|
}"
|
|
:stroke-width="3"
|
|
class="h-3 w-3"
|
|
/>
|
|
</div>
|
|
</span>
|
|
<span class="ml-2 select-none text-sm font-medium text-gray-900">
|
|
{{ step.name }}
|
|
</span>
|
|
<div class="ml-auto">
|
|
<span class="text-sm text-gray-600" v-if="step.duration">
|
|
{{ step.duration }}
|
|
</span>
|
|
<component :is="step.action" v-if="step.action" />
|
|
</div>
|
|
</summary>
|
|
<div :class="index == steps.length - 1 ? 'pb-4' : 'pb-2'">
|
|
<div
|
|
class="ml-4 overflow-auto rounded-md bg-gray-100 px-2 py-2.5 font-mono text-xs text-gray-900"
|
|
:style="{ width: viewportWidth < 768 ? 'calc(100vw - 6rem)' : '' }"
|
|
>
|
|
<div class="max-w-md">
|
|
<pre>{{ step.output || 'No output' }}</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</details>
|
|
</div>
|
|
</CardDetails>
|
|
</template>
|
|
<script>
|
|
import CardDetails from '@/components/CardDetails.vue';
|
|
export default {
|
|
name: 'StepsDetail',
|
|
props: ['showDetails', 'title', 'subtitle', 'loading', 'steps'],
|
|
components: {
|
|
CardDetails
|
|
},
|
|
inject: ['viewportWidth'],
|
|
mounted() {
|
|
this.scrollToElement();
|
|
},
|
|
methods: {
|
|
scrollToElement() {
|
|
setTimeout(() => {
|
|
const el = this.$refs.openedSummary;
|
|
if (el) el[0].scrollIntoView({ behavior: 'smooth' });
|
|
}, 1000);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
details > summary {
|
|
list-style-type: none;
|
|
}
|
|
|
|
details > summary::-webkit-details-marker {
|
|
display: none;
|
|
}
|
|
|
|
details > summary::before {
|
|
content: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.25 9.5L7.75 6L4.25 2.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
}
|
|
|
|
details[open] > summary::before {
|
|
content: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.5 4.25L6 7.75L9.5 4.25' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
|
|
}
|
|
</style>
|