mirror of
https://codeberg.org/crowci/crow.git
synced 2025-04-18 04:44:01 +03:00
chore: format web/
This commit is contained in:
parent
47dfcd89db
commit
648416613a
@ -14,6 +14,7 @@
|
||||
"Makefile",
|
||||
"Justfile",
|
||||
"venv",
|
||||
"site"
|
||||
"site",
|
||||
".vue"
|
||||
]
|
||||
}
|
||||
|
@ -2,17 +2,26 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
<link rel="alternate icon" type="image/png" href="/favicons/favicon-light-default.png" id="favicon-png" />
|
||||
|
||||
<link rel="alternate icon" type="image/png" href="/favicons/favicon-dark-default.png" id="favicon-png-dark" />
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/favicons/favicon-light-default.svg" id="favicon-svg" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<meta name="theme-color" content="#65a30d" />
|
||||
|
||||
<title>Crow CI</title>
|
||||
|
||||
<script type="" src="/web-config.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
|
||||
<script type="application/javascript" src="/assets/custom.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,19 +1,21 @@
|
||||
<template>
|
||||
|
||||
<div class="app m-auto flex h-full w-full flex-col bg-wp-background-200 dark:bg-wp-background-100">
|
||||
<router-view v-if="blank" />
|
||||
<template v-else>
|
||||
<Navbar />
|
||||
<router-view v-if="blank" /> <template v-else
|
||||
> <Navbar />
|
||||
<main class="relative flex h-full min-h-0">
|
||||
<div id="scroll-component" class="flex flex-grow flex-col overflow-y-auto">
|
||||
<router-view />
|
||||
</div>
|
||||
<transition name="slide-right">
|
||||
<PipelineFeedSidebar class="absolute bottom-0 right-0 top-0 w-full max-w-80 border-l shadow-md xl:max-w-96" />
|
||||
</transition>
|
||||
|
||||
<div id="scroll-component" class="flex flex-grow flex-col overflow-y-auto"> <router-view /> </div>
|
||||
<transition name="slide-right"
|
||||
> <PipelineFeedSidebar
|
||||
class="absolute bottom-0 right-0 top-0 w-full max-w-80 border-l shadow-md xl:max-w-96"
|
||||
/> </transition
|
||||
>
|
||||
</main>
|
||||
</template>
|
||||
<notifications position="bottom right" />
|
||||
</template
|
||||
> <notifications position="bottom right" />
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,22 +1,33 @@
|
||||
<template>
|
||||
|
||||
<div v-if="stats" class="flex justify-center">
|
||||
|
||||
<div
|
||||
class="w-full rounded-md border border-wp-background-300 bg-wp-background-200 px-5 py-5 text-wp-text-100 shadow-md dark:bg-wp-background-100"
|
||||
>
|
||||
|
||||
<div class="flex w-full">
|
||||
|
||||
<h3 class="flex-1 text-lg font-semibold uppercase leading-tight">
|
||||
{{ $t('admin.settings.queue.stats.completed_count') }}
|
||||
{{ $t('admin.settings.queue.stats.completed_count') }}
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="relative overflow-hidden transition-all duration-500">
|
||||
|
||||
<div>
|
||||
|
||||
<div class="pb-4 lg:pb-6">
|
||||
<h4 class="inline-block text-2xl font-semibold leading-tight lg:text-3xl">
|
||||
{{ stats.completed_count }}
|
||||
</h4>
|
||||
|
||||
<h4 class="inline-block text-2xl font-semibold leading-tight lg:text-3xl"> {{ stats.completed_count }} </h4>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-if="total > 0" class="pb-4 lg:pb-6">
|
||||
|
||||
<div class="flex h-3 overflow-hidden rounded-full transition-all duration-500">
|
||||
|
||||
<div
|
||||
v-for="item in data"
|
||||
:key="item.key"
|
||||
@ -24,30 +35,42 @@
|
||||
:class="`${item.color}`"
|
||||
:style="{ width: `${item.percentage}%` }"
|
||||
>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="-mx-4 flex sm:flex-wrap">
|
||||
|
||||
<div
|
||||
v-for="(item, index) in data"
|
||||
:key="item.key"
|
||||
class="px-4 sm:w-full md:w-1/4"
|
||||
:class="{ 'border-gray-300 dark:border-gray-600 md:border-l': index !== 0 }"
|
||||
>
|
||||
|
||||
<div class="overflow-hidden text-ellipsis whitespace-nowrap text-sm">
|
||||
<span class="mr-1 inline-block h-2 w-2 rounded-full align-middle" :class="`${item.color}`"> </span>
|
||||
<span class="align-middle">{{ item.label }}</span>
|
||||
</div>
|
||||
<div class="text-lg font-medium">
|
||||
{{ item.value }}
|
||||
<span class="mr-1 inline-block h-2 w-2 rounded-full align-middle" :class="`${item.color}`"> </span
|
||||
> <span class="align-middle">{{ item.label }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="text-lg font-medium"> {{ item.value }} </div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,77 +1,60 @@
|
||||
<template>
|
||||
<form @submit.prevent="$emit('save')">
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.name.name')">
|
||||
<TextField :id="id" v-model="agent.name" :placeholder="$t('admin.settings.agents.name.placeholder')" required />
|
||||
</InputField>
|
||||
|
||||
<InputField :label="$t('admin.settings.agents.no_schedule.name')">
|
||||
<Checkbox
|
||||
<form @submit.prevent="$emit('save')">
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.name.name')"
|
||||
> <TextField :id="id" v-model="agent.name" :placeholder="$t('admin.settings.agents.name.placeholder')" required />
|
||||
</InputField
|
||||
> <InputField :label="$t('admin.settings.agents.no_schedule.name')"
|
||||
> <Checkbox
|
||||
:model-value="agent.no_schedule || false"
|
||||
:label="$t('admin.settings.agents.no_schedule.placeholder')"
|
||||
@update:model-value="updateAgent({ no_schedule: $event })"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<template v-if="isEditingAgent">
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.token')">
|
||||
<TextField :id="id" v-model="agent.token" :placeholder="$t('admin.settings.agents.token')" disabled />
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.id')">
|
||||
<TextField :id="id" :model-value="agent.id?.toString()" disabled />
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.backend.backend')" :docs-url="backendDocsUrl">
|
||||
<TextField :id="id" v-model="agent.backend" disabled />
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.platform.platform')">
|
||||
<TextField :id="id" v-model="agent.platform" disabled />
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
/> </InputField
|
||||
> <template v-if="isEditingAgent"
|
||||
> <InputField v-slot="{ id }" :label="$t('admin.settings.agents.token')"
|
||||
> <TextField :id="id" v-model="agent.token" :placeholder="$t('admin.settings.agents.token')" disabled />
|
||||
</InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('admin.settings.agents.id')"
|
||||
> <TextField :id="id" :model-value="agent.id?.toString()" disabled /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('admin.settings.agents.backend.backend')" :docs-url="backendDocsUrl"
|
||||
> <TextField :id="id" v-model="agent.backend" disabled /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('admin.settings.agents.platform.platform')"
|
||||
> <TextField :id="id" v-model="agent.platform" disabled /> </InputField
|
||||
> <InputField
|
||||
v-if="agent.custom_labels && Object.keys(agent.custom_labels).length > 0"
|
||||
v-slot="{ id }"
|
||||
:label="$t('admin.settings.agents.custom_labels.custom_labels')"
|
||||
>
|
||||
<span class="text-wp-text-alt-100">{{ $t('admin.settings.agents.custom_labels.desc') }}</span>
|
||||
<TextField :id="id" :model-value="formatCustomLabels(agent.custom_labels)" disabled />
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
> <span class="text-wp-text-alt-100">{{ $t('admin.settings.agents.custom_labels.desc') }}</span
|
||||
> <TextField :id="id" :model-value="formatCustomLabels(agent.custom_labels)" disabled /> </InputField
|
||||
> <InputField
|
||||
v-slot="{ id }"
|
||||
:label="$t('admin.settings.agents.capacity.capacity')"
|
||||
docs-url="docs/next/administration/agent-config#woodpecker_max_workflows"
|
||||
>
|
||||
<span class="text-wp-text-alt-100">{{ $t('admin.settings.agents.capacity.desc') }}</span>
|
||||
<TextField :id="id" :model-value="agent.capacity?.toString()" disabled />
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.version')">
|
||||
<TextField :id="id" :model-value="agent.version" disabled />
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.agents.last_contact')">
|
||||
<TextField
|
||||
> <span class="text-wp-text-alt-100">{{ $t('admin.settings.agents.capacity.desc') }}</span
|
||||
> <TextField :id="id" :model-value="agent.capacity?.toString()" disabled /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('admin.settings.agents.version')"
|
||||
> <TextField :id="id" :model-value="agent.version" disabled /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('admin.settings.agents.last_contact')"
|
||||
> <TextField
|
||||
:id="id"
|
||||
:model-value="
|
||||
agent.last_contact ? date.timeAgo(agent.last_contact * 1000) : $t('admin.settings.agents.never')
|
||||
"
|
||||
disabled
|
||||
/>
|
||||
</InputField>
|
||||
</template>
|
||||
|
||||
/> </InputField
|
||||
> </template
|
||||
>
|
||||
<div class="flex gap-2">
|
||||
<Button type="button" color="gray" :text="$t('cancel')" @click="$emit('cancel')" />
|
||||
<Button
|
||||
<Button type="button" color="gray" :text="$t('cancel')" @click="$emit('cancel')" /> <Button
|
||||
:is-loading="isSaving"
|
||||
type="submit"
|
||||
color="default"
|
||||
:text="isEditingAgent ? $t('admin.settings.agents.save') : $t('admin.settings.agents.add')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,46 +1,44 @@
|
||||
<template>
|
||||
|
||||
<div v-if="!props.loading" class="space-y-4 text-wp-text-100">
|
||||
<ListItem
|
||||
<ListItem
|
||||
v-for="agent in props.agents"
|
||||
:key="agent.id"
|
||||
class="items-center !bg-wp-background-200 shadow-md dark:!bg-wp-background-100"
|
||||
>
|
||||
<span>{{ agent.name || `Agent ${agent.id}` }}</span>
|
||||
<span class="ml-auto">
|
||||
<span class="hidden space-x-2 md:inline-block">
|
||||
<Badge
|
||||
> <span>{{ agent.name || `Agent ${agent.id}` }}</span
|
||||
> <span class="ml-auto"
|
||||
> <span class="hidden space-x-2 md:inline-block"
|
||||
> <Badge
|
||||
v-if="props.isAdmin === true && agent.org_id !== -1"
|
||||
:label="$t('admin.settings.agents.org.badge')"
|
||||
:value="agent.org_id"
|
||||
/>
|
||||
<Badge v-if="agent.platform" :label="$t('admin.settings.agents.platform.badge')" :value="agent.platform" />
|
||||
/> <Badge v-if="agent.platform" :label="$t('admin.settings.agents.platform.badge')" :value="agent.platform" />
|
||||
<Badge v-if="agent.backend" :label="$t('admin.settings.agents.backend.badge')" :value="agent.backend" />
|
||||
<Badge v-if="agent.capacity" :label="$t('admin.settings.agents.capacity.badge')" :value="agent.capacity" />
|
||||
</span>
|
||||
<span title="Last contact" class="ml-2">{{
|
||||
</span
|
||||
> <span title="Last contact" class="ml-2">{{
|
||||
agent.last_contact ? date.timeAgo(agent.last_contact * 1000) : $t('admin.settings.agents.never')
|
||||
}}</span>
|
||||
</span>
|
||||
<IconButton
|
||||
}}</span
|
||||
> </span
|
||||
> <IconButton
|
||||
icon="edit"
|
||||
:title="$t('admin.settings.agents.edit_agent')"
|
||||
class="ml-2 h-8 w-8"
|
||||
@click="$emit('edit', agent)"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="trash"
|
||||
:title="$t('admin.settings.agents.delete_agent')"
|
||||
class="ml-2 h-8 w-8 hover:text-wp-error-100"
|
||||
:is-loading="props.isDeleting"
|
||||
@click="$emit('delete', agent)"
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
/> </ListItem
|
||||
>
|
||||
<div v-if="props.agents?.length === 0" class="ml-2">{{ $t('admin.settings.agents.none') }}</div>
|
||||
|
||||
</div>
|
||||
<div v-else class="flex justify-center">
|
||||
<Icon name="loading" class="animate-spin" />
|
||||
</div>
|
||||
|
||||
<div v-else class="flex justify-center"> <Icon name="loading" class="animate-spin" /> </div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,16 +1,13 @@
|
||||
<template>
|
||||
<Settings :title="$t('admin.settings.agents.agents')" :description>
|
||||
<template #headerActions>
|
||||
<Button
|
||||
<Settings :title="$t('admin.settings.agents.agents')" :description
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedAgent"
|
||||
:text="$t('admin.settings.agents.show')"
|
||||
start-icon="back"
|
||||
@click="selectedAgent = undefined"
|
||||
/>
|
||||
<Button v-else :text="$t('admin.settings.agents.add')" start-icon="plus" @click="showAddAgent" />
|
||||
</template>
|
||||
|
||||
<AgentList
|
||||
/> <Button v-else :text="$t('admin.settings.agents.add')" start-icon="plus" @click="showAddAgent" /> </template
|
||||
> <AgentList
|
||||
v-if="!selectedAgent"
|
||||
:loading="loading"
|
||||
:agents="agents"
|
||||
@ -18,16 +15,15 @@
|
||||
:is-admin="isAdmin"
|
||||
@edit="editAgent"
|
||||
@delete="deleteAgent"
|
||||
/>
|
||||
<AgentForm
|
||||
/> <AgentForm
|
||||
v-else
|
||||
v-model="selectedAgent"
|
||||
:is-editing-agent="isEditingAgent"
|
||||
:is-saving="isSaving"
|
||||
@save="saveAgent"
|
||||
@cancel="selectedAgent = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,22 +1,19 @@
|
||||
<template>
|
||||
<span class="inline-flex text-xs font-medium">
|
||||
<span
|
||||
<span class="inline-flex text-xs font-medium"
|
||||
> <span
|
||||
class="flex items-center rounded-l-full border border-wp-custom-highlight-100 py-0.5 pl-2 pr-1 text-gray-300 text-wp-text-100"
|
||||
:class="{
|
||||
'rounded-r-full pr-2': value === undefined,
|
||||
'!border-wp-error-100': label === 'global secret',
|
||||
'!border-wp-hint-warn-200': label === 'organization secret',
|
||||
}"
|
||||
>
|
||||
{{ label }}
|
||||
</span>
|
||||
<span
|
||||
> {{ label }} </span
|
||||
> <span
|
||||
v-if="value !== undefined"
|
||||
class="flex items-center rounded-r-full border border-l-0 border-wp-custom-highlight-100 py-0.5 pl-1 pr-2"
|
||||
>
|
||||
{{ value }}
|
||||
</span>
|
||||
</span>
|
||||
> {{ value }} </span
|
||||
> </span
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<component
|
||||
<component
|
||||
:is="to === undefined ? 'button' : httpLink ? 'a' : 'router-link'"
|
||||
v-bind="btnAttrs"
|
||||
class="relative flex flex-shrink-0 cursor-pointer items-center overflow-hidden whitespace-nowrap rounded-md border border-wp-custom-highlight-100 px-2 py-1 shadow-sm transition-all duration-150 hover:border-wp-orange-300 hover:bg-wp-orange-300 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:border-orange-600 dark:hover:bg-orange-600"
|
||||
@ -15,16 +15,14 @@
|
||||
}"
|
||||
:title="title"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<slot>
|
||||
<Icon
|
||||
> <slot
|
||||
> <Icon
|
||||
v-if="startIcon"
|
||||
:name="startIcon"
|
||||
class="!h-5 !w-5 dark:text-wp-text-200"
|
||||
:class="{ invisible: isLoading, 'mr-1': text }"
|
||||
/>
|
||||
<span :class="{ invisible: isLoading }">{{ text }}</span>
|
||||
<Icon v-if="endIcon" :name="endIcon" class="ml-2 h-6 w-6" :class="{ invisible: isLoading }" />
|
||||
/> <span :class="{ invisible: isLoading }">{{ text }}</span
|
||||
> <Icon v-if="endIcon" :name="endIcon" class="ml-2 h-6 w-6" :class="{ invisible: isLoading }" />
|
||||
<div
|
||||
v-if="isLoading"
|
||||
class="absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center"
|
||||
@ -34,10 +32,11 @@
|
||||
'bg-wp-error-200': color === 'red',
|
||||
}"
|
||||
>
|
||||
<Icon name="spinner" class="h-5 w-5" />
|
||||
<Icon name="spinner" class="h-5 w-5" />
|
||||
</div>
|
||||
</slot>
|
||||
</component>
|
||||
</slot
|
||||
> </component
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<span
|
||||
<span
|
||||
class="inline-block min-w-5 rounded-full bg-wp-background-300 px-1.5 py-0.5 text-center text-xs font-bold leading-4 text-wp-text-100 dark:bg-wp-background-50"
|
||||
> {{ value }} </span
|
||||
>
|
||||
{{ value }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,12 +1,11 @@
|
||||
<template>
|
||||
<a
|
||||
<a
|
||||
:href="`${docsUrl}`"
|
||||
:title="$t('documentation_for', { topic })"
|
||||
target="_blank"
|
||||
class="hover:text-wp-link-300 cursor-pointer text-wp-custom-highlight-100"
|
||||
> <Icon name="question" class="!h-5 !w-5" /> </a
|
||||
>
|
||||
<Icon name="question" class="!h-5 !w-5" />
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,12 +1,14 @@
|
||||
<template>
|
||||
|
||||
<div
|
||||
class="flex items-center gap-2 rounded-md border border-l-4 border-solid border-wp-error-200 bg-wp-error-100 p-2 text-white"
|
||||
>
|
||||
<Icon v-if="!textOnly" name="alert" />
|
||||
<slot>
|
||||
<span class="whitespace-pre">{{ text }}</span>
|
||||
</slot>
|
||||
<Icon v-if="!textOnly" name="alert" /> <slot
|
||||
> <span class="whitespace-pre">{{ text }}</span
|
||||
> </slot
|
||||
>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,69 +1,118 @@
|
||||
<!-- cSpell:ignore radiobox timelapse -->
|
||||
<template>
|
||||
<SvgIcon v-if="name === 'duration'" :path="mdiTimerOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'since'" :path="mdiClockTimeEightOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'push'" :path="mdiSourceBranch" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'pull-request'" :path="mdiSourcePull" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'pull-request-closed'" :path="mdiSourceMerge" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'manual-pipeline'" :path="mdiGestureTap" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'tag'" :path="mdiTagOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'deployment'" :path="mdiPackageVariant" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'commit'" :path="mdiSourceCommit" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'back'" :path="mdiArrowLeft" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'github'" :path="mdiGithub" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'repo'" :path="mdiGit" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'settings'" :path="mdiCog" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'settings-outline'" :path="mdiCogOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'trash'" :path="mdiTrashCanOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'status-blocked'" :path="mdiPlay" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'status-declined'" :path="mdiStop" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'status-killed'" :path="mdiStop" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'status-failure' || name === 'status-error'" type="mdi" :path="mdiClose" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'status-pending'" :path="mdiRadioboxBlank" size="1.3rem" />
|
||||
<SvgIcon
|
||||
<SvgIcon v-if="name === 'duration'" :path="mdiTimerOutline" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'since'"
|
||||
:path="mdiClockTimeEightOutline"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'push'" :path="mdiSourceBranch" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'pull-request'"
|
||||
:path="mdiSourcePull"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'pull-request-closed'" :path="mdiSourceMerge" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'manual-pipeline'"
|
||||
:path="mdiGestureTap"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'tag'" :path="mdiTagOutline" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'deployment'"
|
||||
:path="mdiPackageVariant"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'commit'" :path="mdiSourceCommit" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'back'"
|
||||
:path="mdiArrowLeft"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'github'" :path="mdiGithub" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'repo'"
|
||||
:path="mdiGit"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'settings'" :path="mdiCog" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'settings-outline'"
|
||||
:path="mdiCogOutline"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'trash'" :path="mdiTrashCanOutline" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'status-blocked'"
|
||||
:path="mdiPlay"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'status-declined'" :path="mdiStop" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'status-killed'"
|
||||
:path="mdiStop"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon
|
||||
v-else-if="name === 'status-failure' || name === 'status-error'"
|
||||
type="mdi"
|
||||
:path="mdiClose"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'status-pending'" :path="mdiRadioboxBlank" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'status-running' || name === 'status-started'"
|
||||
type="mdi"
|
||||
:path="mdiRadioboxIndeterminateVariant"
|
||||
size="1.3rem"
|
||||
/>
|
||||
<SvgIcon v-else-if="name === 'status-skipped'" :path="mdiMinus" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'status-success'" :path="mdiCheck" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'alert'" :path="mdiAlertCircle" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'question'" :path="mdiInformationSlabCircleOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'plus'" :path="mdiPlus" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'list'" :path="mdiFormatListBulleted" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'heal'" :path="mdiWrenchCogOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'turn-off'" :path="mdiPower" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'chevron-right'" :path="mdiChevronRight" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'close'" :path="mdiClose" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'edit'" :path="mdiPencilOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'download'" :path="mdiDownloadOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'stopwatch'" :path="mdiAlarm" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'auto-scroll'" :path="mdiEyeOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'auto-scroll-off'" :path="mdiEyeOffOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'pause'" :path="mdiPause" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'play'" :path="mdiPlay" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'play-outline'" :path="mdiPlayOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'dots'" :path="mdiDotsVertical" size="1.3rem" />
|
||||
/> <SvgIcon v-else-if="name === 'status-skipped'" :path="mdiMinus" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'status-success'"
|
||||
:path="mdiCheck"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'alert'" :path="mdiAlertCircle" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'question'"
|
||||
:path="mdiInformationSlabCircleOutline"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'plus'" :path="mdiPlus" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'list'"
|
||||
:path="mdiFormatListBulleted"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'heal'" :path="mdiWrenchCogOutline" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'turn-off'"
|
||||
:path="mdiPower"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'chevron-right'" :path="mdiChevronRight" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'close'"
|
||||
:path="mdiClose"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'edit'" :path="mdiPencilOutline" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'download'"
|
||||
:path="mdiDownloadOutline"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'stopwatch'" :path="mdiAlarm" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'auto-scroll'"
|
||||
:path="mdiEyeOutline"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'auto-scroll-off'" :path="mdiEyeOffOutline" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'pause'"
|
||||
:path="mdiPause"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'play'" :path="mdiPlay" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'play-outline'"
|
||||
:path="mdiPlayOutline"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'dots'" :path="mdiDotsVertical" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'visibility-private'"
|
||||
:path="mdiLockOutline"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'visibility-internal'" :path="mdiLockOpenOutline" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'forgejo'"
|
||||
:path="siForgejo.path"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'gitea'" :path="siGitea.path" size="1.3rem" /> <SvgIcon
|
||||
v-else-if="name === 'gitlab'"
|
||||
:path="mdiGitlab"
|
||||
size="1.3rem"
|
||||
/> <SvgIcon v-else-if="name === 'bitbucket' || name === 'bitbucket-dc'" :path="mdiBitbucket" size="1.3rem" /> <svg
|
||||
v-else-if="name === 'spinner'"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
|
||||
<SvgIcon v-else-if="name === 'visibility-private'" :path="mdiLockOutline" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'visibility-internal'" :path="mdiLockOpenOutline" size="1.3rem" />
|
||||
|
||||
<SvgIcon v-else-if="name === 'forgejo'" :path="siForgejo.path" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'gitea'" :path="siGitea.path" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'gitlab'" :path="mdiGitlab" size="1.3rem" />
|
||||
<SvgIcon v-else-if="name === 'bitbucket' || name === 'bitbucket-dc'" :path="mdiBitbucket" size="1.3rem" />
|
||||
|
||||
<svg v-else-if="name === 'spinner'" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
|
||||
opacity=".25"
|
||||
/>
|
||||
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z"
|
||||
>
|
||||
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
type="rotate"
|
||||
@ -71,10 +120,12 @@
|
||||
values="0 12 12;360 12 12"
|
||||
repeatCount="indefinite"
|
||||
/>
|
||||
</path>
|
||||
</svg>
|
||||
|
||||
</path>
|
||||
</svg
|
||||
>
|
||||
<div v-else-if="name === 'blank'" class="h-6 w-6" />
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,10 +1,7 @@
|
||||
<template>
|
||||
<router-link v-if="to" :to="to" :title="title" :aria-label="title" class="icon-button h-8 w-8">
|
||||
<slot>
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
</slot>
|
||||
</router-link>
|
||||
<a
|
||||
<router-link v-if="to" :to="to" :title="title" :aria-label="title" class="icon-button h-8 w-8"
|
||||
> <slot> <Icon v-if="icon" :name="icon" /> </slot> </router-link
|
||||
> <a
|
||||
v-else-if="href"
|
||||
:href="href"
|
||||
:title="title"
|
||||
@ -12,19 +9,14 @@
|
||||
class="icon-button"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<slot>
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
</slot>
|
||||
</a>
|
||||
<button v-else :disabled="disabled" class="icon-button" type="button" :title="title" :aria-label="title">
|
||||
<slot>
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
</slot>
|
||||
> <slot> <Icon v-if="icon" :name="icon" /> </slot> </a
|
||||
> <button v-else :disabled="disabled" class="icon-button" type="button" :title="title" :aria-label="title">
|
||||
<slot> <Icon v-if="icon" :name="icon" /> </slot>
|
||||
<div v-if="isLoading" class="absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center">
|
||||
<Icon name="loading" class="animate-spin" />
|
||||
<Icon name="loading" class="animate-spin" />
|
||||
</div>
|
||||
</button>
|
||||
</button
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,14 +1,13 @@
|
||||
<template>
|
||||
<component
|
||||
<component
|
||||
:is="to ? 'router-link' : clickable ? 'button' : 'div'"
|
||||
:to="to"
|
||||
class="flex w-full overflow-hidden rounded-md border border-wp-background-400 bg-wp-background-100 p-4 shadow-sm dark:bg-wp-background-200"
|
||||
:class="{
|
||||
'cursor-pointer hover:bg-wp-background-300 hover:shadow-sm dark:hover:bg-wp-background-300': clickable || to,
|
||||
}"
|
||||
> <slot /> </component
|
||||
>
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,6 +1,4 @@
|
||||
<template>
|
||||
<span v-html="contentHTML" />
|
||||
</template>
|
||||
<template> <span v-html="contentHTML" /> </template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DOMPurify from 'dompurify';
|
||||
|
@ -1,7 +1,9 @@
|
||||
<template>
|
||||
<svg fill="currentColor" :width="size" :height="size" viewBox="0 0 24 24">
|
||||
<svg fill="currentColor" :width="size" :height="size" viewBox="0 0 24 24">
|
||||
|
||||
<path :d="path" />
|
||||
</svg>
|
||||
</svg
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,12 +1,14 @@
|
||||
<template>
|
||||
|
||||
<div
|
||||
class="flex items-center gap-4 rounded-md border border-l-4 border-solid border-wp-hint-warn-200 bg-wp-hint-warn-100 p-4 font-bold text-wp-text-100"
|
||||
>
|
||||
<Icon v-if="!textOnly" name="alert" class="flex-shrink-0 text-wp-hint-warn-200" />
|
||||
<slot>
|
||||
<span class="whitespace-pre-wrap">{{ text }}</span>
|
||||
</slot>
|
||||
<Icon v-if="!textOnly" name="alert" class="flex-shrink-0 text-wp-hint-warn-200" /> <slot
|
||||
> <span class="whitespace-pre-wrap">{{ text }}</span
|
||||
> </slot
|
||||
>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
|
||||
<div class="mb-2 flex items-center">
|
||||
<input
|
||||
<input
|
||||
:id="`checkbox-${id}`"
|
||||
type="checkbox"
|
||||
class="checkbox relative h-5 w-5 flex-shrink-0 cursor-pointer border border-wp-background-400 bg-wp-control-neutral-100 shadow-sm transition-colors duration-150 checked:border-wp-background-secondary-800 checked:bg-wp-background-secondary-800 focus-visible:border-wp-control-neutral-300 checked:focus-visible:border-wp-control-ok-300"
|
||||
@ -8,10 +9,13 @@
|
||||
@click="innerValue = !innerValue"
|
||||
/>
|
||||
<div class="ml-4 flex flex-col">
|
||||
<label class="cursor-pointer text-wp-text-100" :for="`checkbox-${id}`">{{ label }}</label>
|
||||
<span v-if="description" class="text-sm text-wp-text-alt-100">{{ description }}</span>
|
||||
<label class="cursor-pointer text-wp-text-100" :for="`checkbox-${id}`">{{ label }}</label
|
||||
> <span v-if="description" class="text-sm text-wp-text-alt-100">{{ description }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Checkbox
|
||||
<Checkbox
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:model-value="innerValue.includes(option.value)"
|
||||
|
@ -1,15 +1,19 @@
|
||||
<template>
|
||||
|
||||
<div class="mb-4 mt-2 flex flex-col">
|
||||
|
||||
<div class="mb-2 flex items-center">
|
||||
<label class="font-bold text-wp-text-100" :for="id" v-bind="$attrs">{{ label }}</label>
|
||||
<DocsLink v-if="docsUrl" :topic="label" :url="docsUrl" class="ml-2" />
|
||||
<slot v-else-if="$slots.titleActions" name="titleActions" />
|
||||
<label class="font-bold text-wp-text-100" :for="id" v-bind="$attrs">{{ label }}</label
|
||||
> <DocsLink v-if="docsUrl" :topic="label" :url="docsUrl" class="ml-2" /> <slot
|
||||
v-else-if="$slots.titleActions"
|
||||
name="titleActions"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="$slots.description" class="mb-2 text-sm text-wp-text-alt-100">
|
||||
<slot name="description" />
|
||||
</div>
|
||||
<slot :id="id" />
|
||||
|
||||
<div v-if="$slots.description" class="mb-2 text-sm text-wp-text-alt-100"> <slot name="description" /> </div>
|
||||
<slot :id="id" />
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,7 +1,9 @@
|
||||
<template>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
|
||||
<div v-for="(item, index) in displayItems" :key="index" class="flex gap-4">
|
||||
<TextField
|
||||
<TextField
|
||||
:id="`${id}-key-${index}`"
|
||||
:model-value="item.key"
|
||||
:placeholder="keyPlaceholder"
|
||||
@ -10,27 +12,28 @@
|
||||
isDuplicateKey(item.key, index) || (item.key === '' && index !== displayItems.length - 1),
|
||||
}"
|
||||
@update:model-value="updateItem(index, 'key', $event)"
|
||||
/>
|
||||
<TextField
|
||||
/> <TextField
|
||||
:id="`${id}-value-${index}`"
|
||||
:model-value="item.value"
|
||||
:placeholder="valuePlaceholder"
|
||||
@update:model-value="updateItem(index, 'value', $event)"
|
||||
/>
|
||||
<div class="w-10 flex-shrink-0">
|
||||
<Button
|
||||
<Button
|
||||
v-if="index !== displayItems.length - 1"
|
||||
type="button"
|
||||
color="red"
|
||||
class="ml-auto"
|
||||
:title="deleteTitle"
|
||||
@click="deleteItem(index)"
|
||||
> <Icon name="close" /> </Button
|
||||
>
|
||||
<Icon name="close" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,6 +1,4 @@
|
||||
<template>
|
||||
<TextField v-model="innerValue" :placeholder="placeholder" type="number" />
|
||||
</template>
|
||||
<template> <TextField v-model="innerValue" :placeholder="placeholder" type="number" /> </template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, toRef } from 'vue';
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
|
||||
<div v-for="option in options" :key="option.value" class="mb-2 flex items-center">
|
||||
<input
|
||||
<input
|
||||
:id="`radio-${id}-${option.value}`"
|
||||
type="radio"
|
||||
class="radio relative h-5 w-5 flex-shrink-0 cursor-pointer rounded-full border border-wp-background-400 bg-wp-control-neutral-100 shadow-sm checked:border-wp-background-secondary-800 checked:bg-wp-background-secondary-800 focus-visible:border-wp-control-neutral-300 checked:focus-visible:border-wp-control-ok-300"
|
||||
@ -9,10 +10,13 @@
|
||||
@click="innerValue = option.value"
|
||||
/>
|
||||
<div class="ml-4 flex flex-col">
|
||||
<label class="cursor-pointer text-wp-text-100" :for="`radio-${id}-${option.value}`">{{ option.text }}</label>
|
||||
<span v-if="option.description" class="text-sm text-wp-text-alt-100">{{ option.description }}</span>
|
||||
<label class="cursor-pointer text-wp-text-100" :for="`radio-${id}-${option.value}`">{{ option.text }}</label
|
||||
> <span v-if="option.description" class="text-sm text-wp-text-alt-100">{{ option.description }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,13 +1,16 @@
|
||||
<template>
|
||||
<select
|
||||
<select
|
||||
v-model="innerValue"
|
||||
class="w-full rounded-md border border-wp-background-400 bg-wp-control-neutral-100 px-2 py-1 text-wp-text-100"
|
||||
>
|
||||
|
||||
<option v-if="placeholder" value="" class="hidden">{{ placeholder }}</option>
|
||||
|
||||
<option v-for="option in options" :key="option.value" :value="option.value" class="text-wp-text-100">
|
||||
{{ option.text }}
|
||||
{{ option.text }}
|
||||
</option>
|
||||
</select>
|
||||
</select
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<input
|
||||
<input
|
||||
v-if="lines === 1"
|
||||
v-model="innerValue"
|
||||
class="w-full rounded-md border border-wp-background-400 bg-wp-background-100 px-2 py-1 shadow-md focus-visible:border-wp-control-neutral-300 focus-visible:outline-none"
|
||||
@ -7,8 +7,7 @@
|
||||
:disabled="disabled"
|
||||
:type="type"
|
||||
:placeholder="placeholder"
|
||||
/>
|
||||
<textarea
|
||||
/> <textarea
|
||||
v-else
|
||||
v-model="innerValue"
|
||||
class="w-full rounded-md border border-wp-background-400 bg-wp-background-100 px-2 py-1 shadow-md focus-visible:border-wp-control-neutral-300 focus-visible:outline-none"
|
||||
|
@ -1,7 +1,9 @@
|
||||
<template>
|
||||
|
||||
<div class="mx-auto w-full p-4" :class="{ 'max-w-5xl': !fullWidth && !fillWidth, 'md:px-0': fullWidth }">
|
||||
<slot />
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,22 +1,21 @@
|
||||
<template>
|
||||
|
||||
<div
|
||||
class="w-full overflow-hidden rounded-md border border-wp-background-400 bg-wp-background-100 shadow-sm dark:bg-wp-background-200"
|
||||
>
|
||||
<component
|
||||
<component
|
||||
:is="collapsable ? 'button' : 'div'"
|
||||
v-if="title"
|
||||
type="button"
|
||||
class="flex w-full gap-2 bg-wp-background-300 px-4 py-2 font-bold text-wp-text-100"
|
||||
@click="_collapsed = !_collapsed"
|
||||
>
|
||||
<Icon
|
||||
> <Icon
|
||||
v-if="collapsable"
|
||||
name="chevron-right"
|
||||
class="h-6 min-w-6 transition-transform duration-150"
|
||||
:class="{ 'rotate-90 transform': !collapsed }"
|
||||
/>
|
||||
{{ title }}
|
||||
</component>
|
||||
/> {{ title }} </component
|
||||
>
|
||||
<div
|
||||
:class="{
|
||||
'max-h-auto': !collapsed,
|
||||
@ -24,11 +23,13 @@
|
||||
}"
|
||||
class="overflow-hidden transition-height duration-150"
|
||||
>
|
||||
<div class="w-full p-4 text-wp-text-100">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<div class="w-full p-4 text-wp-text-100"> <slot /> </div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,16 +1,17 @@
|
||||
<template>
|
||||
<!-- overlay -->
|
||||
<!-- overlay -->
|
||||
<div
|
||||
v-if="open"
|
||||
class="fixed bottom-0 left-0 right-0 top-0 z-40 bg-gray-900 opacity-80 print:hidden"
|
||||
@click="$emit('close')"
|
||||
/>
|
||||
<!-- overlay end -->
|
||||
<!-- overlay end -->
|
||||
<div v-if="open" class="fixed inset-0 z-50 m-auto flex max-w-2xl print:hidden">
|
||||
<div class="shadow-all m-auto flex h-auto flex-col p-2">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<div class="shadow-all m-auto flex h-auto flex-col p-2"> <slot /> </div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,25 +1,27 @@
|
||||
<template>
|
||||
<Panel>
|
||||
<Panel
|
||||
>
|
||||
<div class="mb-4 flex flex-col justify-center border-b pb-4 dark:border-wp-custom-highlight-100">
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
|
||||
<h1 class="flex items-center gap-1 text-xl text-wp-text-100">
|
||||
{{ title }}
|
||||
<DocsLink v-if="docsUrl" :topic="title" :url="docsUrl" />
|
||||
{{ title }} <DocsLink v-if="docsUrl" :topic="title" :url="docsUrl" />
|
||||
</h1>
|
||||
<slot v-if="$slots.titleActions" name="titleActions" />
|
||||
<slot v-if="$slots.titleActions" name="titleActions" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2">
|
||||
<p v-if="description" class="text-sm text-wp-text-alt-100">{{ description }}</p>
|
||||
<div v-if="$slots.headerActions">
|
||||
<slot name="headerActions" />
|
||||
</div>
|
||||
</div>
|
||||
<slot name="headerEnd" />
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
</Panel>
|
||||
<p v-if="description" class="text-sm text-wp-text-alt-100">{{ description }}</p>
|
||||
|
||||
<div v-if="$slots.headerActions"> <slot name="headerActions" /> </div>
|
||||
|
||||
</div>
|
||||
<slot name="headerEnd" />
|
||||
</div>
|
||||
<slot /> </Panel
|
||||
>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,17 +1,18 @@
|
||||
<template>
|
||||
<IconButton
|
||||
<IconButton
|
||||
:title="pipelineCount > 0 ? `${$t('pipeline_feed')} (${pipelineCount})` : $t('pipeline_feed')"
|
||||
class="active-pipelines-toggle relative !p-1.5 text-current"
|
||||
@click="toggle"
|
||||
>
|
||||
>
|
||||
<div v-if="pipelineCount > 0" class="spinner" />
|
||||
|
||||
<div
|
||||
class="z-0 flex h-full w-full items-center justify-center rounded-md border border-wp-custom-highlight-100 bg-white bg-opacity-10 font-bold"
|
||||
>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
{{ pipelineCount > 9 ? '9+' : pipelineCount }}
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> {{ pipelineCount > 9 ? '9+' : pipelineCount }}
|
||||
</div>
|
||||
</IconButton>
|
||||
</IconButton
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,41 +1,46 @@
|
||||
<template>
|
||||
|
||||
<nav
|
||||
class="text-neutral-content flex border-wp-background-100 bg-wp-background-secondary-800 p-3 text-wp-primary-text-100"
|
||||
>
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<router-link :to="{ name: 'home' }" class="-my-2 flex flex-col px-2">
|
||||
<CrowLogo class="h-8 w-8" />
|
||||
<!-- <span class="text-center text-xs" :title="version?.current">{{ version?.currentShort }}</span> -->
|
||||
</router-link>
|
||||
<router-link v-if="user" :to="{ name: 'repos' }" class="navbar-clickable navbar-link">
|
||||
<span class="flex md:hidden">{{ $t('repos') }}</span>
|
||||
<span class="hidden md:flex">{{ $t('repositories') }}</span>
|
||||
</router-link>
|
||||
<a href="https://crowci.dev/" target="_blank" class="navbar-clickable navbar-link hidden md:flex">{{
|
||||
<router-link :to="{ name: 'home' }" class="-my-2 flex flex-col px-2"
|
||||
> <CrowLogo class="h-8 w-8" /> <!-- <span class="text-center text-xs" :title="version?.current">{{ version?.currentShort }}</span> -->
|
||||
</router-link
|
||||
> <router-link v-if="user" :to="{ name: 'repos' }" class="navbar-clickable navbar-link"
|
||||
> <span class="flex md:hidden">{{ $t('repos') }}</span
|
||||
> <span class="hidden md:flex">{{ $t('repositories') }}</span
|
||||
> </router-link
|
||||
> <a href="https://crowci.dev/" target="_blank" class="navbar-clickable navbar-link hidden md:flex">{{
|
||||
$t('docs')
|
||||
}}</a>
|
||||
<a v-if="enableSwagger" :href="apiUrl" target="_blank" class="navbar-clickable navbar-link hidden md:flex">{{
|
||||
}}</a
|
||||
> <a v-if="enableSwagger" :href="apiUrl" target="_blank" class="navbar-clickable navbar-link hidden md:flex">{{
|
||||
$t('api')
|
||||
}}</a>
|
||||
}}</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="-m-1.5 ml-auto flex items-center space-x-2">
|
||||
<IconButton
|
||||
<IconButton
|
||||
v-if="user?.admin"
|
||||
class="navbar-icon relative"
|
||||
:title="$t('settings')"
|
||||
:to="{ name: 'admin-settings' }"
|
||||
>
|
||||
<Icon name="settings" />
|
||||
> <Icon name="settings" />
|
||||
<div v-if="version?.needsUpdate" class="absolute right-2 top-2 h-3 w-3 rounded-full bg-wp-error-100" />
|
||||
</IconButton>
|
||||
|
||||
<ActivePipelines v-if="user" class="navbar-icon !p-1.5" />
|
||||
<IconButton v-if="user" :to="{ name: 'user' }" :title="$t('user.settings.settings')" class="navbar-icon !p-1.5">
|
||||
<img v-if="user && user.avatar_url" class="rounded-md" :src="`${user.avatar_url}`" />
|
||||
</IconButton>
|
||||
<Button v-else :text="$t('login')" :to="`/login?url=${route.fullPath}`" />
|
||||
</IconButton
|
||||
> <ActivePipelines v-if="user" class="navbar-icon !p-1.5" /> <IconButton
|
||||
v-if="user"
|
||||
:to="{ name: 'user' }"
|
||||
:title="$t('user.settings.settings')"
|
||||
class="navbar-icon !p-1.5"
|
||||
> <img v-if="user && user.avatar_url" class="rounded-md" :src="`${user.avatar_url}`" /> </IconButton
|
||||
> <Button v-else :text="$t('login')" :to="`/login?url=${route.fullPath}`" />
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,33 +1,32 @@
|
||||
<template>
|
||||
<Popup :open="open" @close="$emit('close')">
|
||||
<Panel v-if="!loading">
|
||||
<Popup :open="open" @close="$emit('close')"
|
||||
> <Panel v-if="!loading"
|
||||
>
|
||||
<form @submit.prevent="triggerDeployPipeline">
|
||||
<span class="text-xl text-wp-text-100">{{
|
||||
<span class="text-xl text-wp-text-100">{{
|
||||
$t('repo.deploy_pipeline.title', { pipelineId: pipelineNumber })
|
||||
}}</span>
|
||||
<InputField v-slot="{ id }" :label="$t('repo.deploy_pipeline.enter_target.title')">
|
||||
<span class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.deploy_pipeline.enter_target.desc') }}</span>
|
||||
<TextField :id="id" v-model="payload.environment" required />
|
||||
</InputField>
|
||||
<InputField v-slot="{ id }" :label="$t('repo.deploy_pipeline.enter_task.title')">
|
||||
<span class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.deploy_pipeline.enter_task.desc') }}</span>
|
||||
<TextField :id="id" v-model="payload.task" />
|
||||
</InputField>
|
||||
<InputField v-slot="{ id }" :label="$t('repo.deploy_pipeline.variables.title')">
|
||||
<span class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.deploy_pipeline.variables.desc') }}</span>
|
||||
<KeyValueEditor
|
||||
}}</span
|
||||
> <InputField v-slot="{ id }" :label="$t('repo.deploy_pipeline.enter_target.title')"
|
||||
> <span class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.deploy_pipeline.enter_target.desc') }}</span
|
||||
> <TextField :id="id" v-model="payload.environment" required /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('repo.deploy_pipeline.enter_task.title')"
|
||||
> <span class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.deploy_pipeline.enter_task.desc') }}</span
|
||||
> <TextField :id="id" v-model="payload.task" /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('repo.deploy_pipeline.variables.title')"
|
||||
> <span class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.deploy_pipeline.variables.desc') }}</span
|
||||
> <KeyValueEditor
|
||||
:id="id"
|
||||
v-model="payload.variables"
|
||||
:key-placeholder="$t('repo.deploy_pipeline.variables.name')"
|
||||
:value-placeholder="$t('repo.deploy_pipeline.variables.value')"
|
||||
:delete-title="$t('repo.deploy_pipeline.variables.delete')"
|
||||
@update:is-valid="isVariablesValid = $event"
|
||||
/>
|
||||
</InputField>
|
||||
<Button type="submit" :text="$t('repo.deploy_pipeline.trigger')" :disabled="!isFormValid" />
|
||||
/> </InputField
|
||||
> <Button type="submit" :text="$t('repo.deploy_pipeline.trigger')" :disabled="!isFormValid" />
|
||||
</form>
|
||||
</Panel>
|
||||
</Popup>
|
||||
</Panel
|
||||
> </Popup
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,28 +1,30 @@
|
||||
<template>
|
||||
|
||||
<header
|
||||
class="border-wp-background-400 bg-wp-background-100 text-wp-text-100 shadow-sm dark:border-wp-background-100 dark:bg-wp-background-300"
|
||||
:class="{ 'md:px-4': fullWidth }"
|
||||
>
|
||||
<Container :full-width="fullWidth" class="!py-0">
|
||||
<Container :full-width="fullWidth" class="!py-0"
|
||||
>
|
||||
<div class="flex w-full flex-col gap-2 py-2 md:flex-row md:items-center md:justify-between md:gap-10">
|
||||
|
||||
<div
|
||||
class="flex min-h-10 content-start items-center"
|
||||
:class="{
|
||||
'md:flex-1': searchBoxPresent,
|
||||
}"
|
||||
>
|
||||
<IconButton
|
||||
<IconButton
|
||||
v-if="goBack"
|
||||
icon="back"
|
||||
:title="$t('back')"
|
||||
class="md:display-unset mr-2 hidden h-8 w-8 flex-shrink-0 md:justify-between"
|
||||
@click="goBack"
|
||||
/>
|
||||
<h1 class="flex min-w-0 items-center gap-x-2 text-xl italic text-wp-text-100">
|
||||
<slot name="title" />
|
||||
</h1>
|
||||
<h1 class="flex min-w-0 items-center gap-x-2 text-xl italic text-wp-text-100"> <slot name="title" /> </h1>
|
||||
|
||||
</div>
|
||||
<TextField
|
||||
<TextField
|
||||
v-if="searchBoxPresent"
|
||||
class="order-3 w-full flex-grow md:order-none md:w-auto"
|
||||
:aria-label="$t('search')"
|
||||
@ -37,18 +39,22 @@
|
||||
'md:flex-1': searchBoxPresent,
|
||||
}"
|
||||
>
|
||||
<slot name="headerActions" />
|
||||
<slot name="headerActions" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-if="enableTabs" class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between md:py-0">
|
||||
<Tabs class="order-2 md:order-none" />
|
||||
<Tabs class="order-2 md:order-none" />
|
||||
<div v-if="$slots.headerActions" class="flex flex-wrap content-start pb-2 md:justify-end">
|
||||
<slot name="tabActions" />
|
||||
<slot name="tabActions" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Container>
|
||||
</Container
|
||||
>
|
||||
</header>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,20 +1,14 @@
|
||||
<template>
|
||||
<Header
|
||||
<Header
|
||||
:go-back="goBack"
|
||||
:enable-tabs="enableTabs"
|
||||
:search="search"
|
||||
:full-width="fullWidthHeader"
|
||||
@update:search="(value) => $emit('update:search', value)"
|
||||
>
|
||||
<template #title><slot name="title" /></template>
|
||||
<template v-if="$slots.headerActions" #headerActions><slot name="headerActions" /></template>
|
||||
<template v-if="$slots.tabActions" #tabActions><slot name="tabActions" /></template>
|
||||
</Header>
|
||||
|
||||
<slot v-if="fluidContent" />
|
||||
<Container v-else>
|
||||
<slot />
|
||||
</Container>
|
||||
> <template #title><slot name="title" /></template> <template v-if="$slots.headerActions" #headerActions
|
||||
><slot name="headerActions" /></template
|
||||
> <template v-if="$slots.tabActions" #tabActions><slot name="tabActions" /></template> </Header
|
||||
> <slot v-if="fluidContent" /> <Container v-else> <slot /> </Container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,49 +1,48 @@
|
||||
<template>
|
||||
<!-- Main tabs container -->
|
||||
<!-- Main tabs container -->
|
||||
<div ref="tabsRef" class="flex min-w-0 flex-auto gap-4">
|
||||
<router-link
|
||||
<router-link
|
||||
v-for="tab in visibleTabs"
|
||||
:key="tab.title"
|
||||
:to="tab.to"
|
||||
class="flex cursor-pointer items-center whitespace-nowrap border-b-2 border-transparent py-1 text-wp-text-100"
|
||||
:active-class="tab.matchChildren ? '!border-wp-custom-highlight-100' : ''"
|
||||
:exact-active-class="tab.matchChildren ? '' : '!border-wp-custom-highlight-100'"
|
||||
>
|
||||
<span
|
||||
> <span
|
||||
class="flex w-full min-w-20 flex-row items-center justify-center gap-2 rounded-md px-2 py-1 hover:bg-wp-background-200 dark:hover:bg-wp-background-100"
|
||||
>
|
||||
<Icon v-if="tab.icon" :name="tab.icon" :class="tab.iconClass" class="flex-shrink-0" />
|
||||
<span>{{ tab.title }}</span>
|
||||
<CountBadge v-if="tab.count" :value="tab.count" />
|
||||
</span>
|
||||
</router-link>
|
||||
|
||||
<!-- Overflow dropdown -->
|
||||
> <Icon v-if="tab.icon" :name="tab.icon" :class="tab.iconClass" class="flex-shrink-0" /> <span>{{
|
||||
tab.title
|
||||
}}</span
|
||||
> <CountBadge v-if="tab.count" :value="tab.count" /> </span
|
||||
> </router-link
|
||||
> <!-- Overflow dropdown -->
|
||||
<div v-if="hiddenTabs.length" class="relative border-b-2 border-transparent py-1">
|
||||
<IconButton icon="dots" class="tabs-more-button h-8 w-8" @click="toggleDropdown" />
|
||||
|
||||
<IconButton icon="dots" class="tabs-more-button h-8 w-8" @click="toggleDropdown" />
|
||||
<div
|
||||
v-if="isDropdownOpen"
|
||||
class="tabs-dropdown absolute z-20 mt-1 rounded-md border border-wp-background-400 bg-wp-background-100 shadow-lg dark:bg-wp-background-200"
|
||||
:class="[visibleTabs.length === 0 ? 'left-0' : 'right-0']"
|
||||
>
|
||||
<router-link
|
||||
<router-link
|
||||
v-for="tab in hiddenTabs"
|
||||
:key="tab.title"
|
||||
:to="tab.to"
|
||||
class="block w-full whitespace-nowrap p-1 text-left"
|
||||
@click="isDropdownOpen = false"
|
||||
>
|
||||
<span
|
||||
> <span
|
||||
class="flex w-full min-w-20 flex-row items-center justify-center gap-2 rounded-md px-2 py-1 hover:bg-wp-background-200 dark:hover:bg-wp-background-100"
|
||||
>
|
||||
<Icon v-if="tab.icon" :name="tab.icon" :class="tab.iconClass" class="flex-shrink-0" />
|
||||
<span>{{ tab.title }}</span>
|
||||
</span>
|
||||
</router-link>
|
||||
> <Icon v-if="tab.icon" :name="tab.icon" :class="tab.iconClass" class="flex-shrink-0" /> <span>{{
|
||||
tab.title
|
||||
}}</span
|
||||
> </span
|
||||
> </router-link
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,32 +1,38 @@
|
||||
<template>
|
||||
|
||||
<div v-if="pipeline" class="flex w-full text-wp-text-100">
|
||||
<PipelineStatusIcon :status="pipeline.status" class="flex items-center" />
|
||||
<PipelineStatusIcon :status="pipeline.status" class="flex items-center" />
|
||||
<div class="ml-4 flex min-w-0 flex-col">
|
||||
<router-link
|
||||
<router-link
|
||||
:to="{
|
||||
name: 'repo',
|
||||
params: { repoId: pipeline.repo_id },
|
||||
}"
|
||||
class="underline decoration-wp-custom-highlight-100"
|
||||
>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
{{ repo?.owner }} / {{ repo?.name }}
|
||||
</router-link>
|
||||
<span class="overflow-hidden overflow-ellipsis whitespace-nowrap italic" :title="message">{{
|
||||
> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> {{ repo?.owner }} / {{ repo?.name }}
|
||||
</router-link
|
||||
> <span class="overflow-hidden overflow-ellipsis whitespace-nowrap italic" :title="message">{{
|
||||
shortMessage
|
||||
}}</span>
|
||||
}}</span
|
||||
>
|
||||
<div class="mt-2 flex flex-col">
|
||||
|
||||
<div class="mb-1 flex items-center space-x-2" :title="created">
|
||||
<Icon name="since" />
|
||||
<span>{{ since }}</span>
|
||||
<Icon name="since" /> <span>{{ since }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="mb-1 flex items-center space-x-2">
|
||||
<Icon name="duration" />
|
||||
<span>{{ duration }}</span>
|
||||
<Icon name="duration" /> <span>{{ duration }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,11 +1,12 @@
|
||||
<template>
|
||||
|
||||
<aside
|
||||
v-if="isOpen"
|
||||
ref="target"
|
||||
class="z-50 flex flex-col items-center overflow-y-auto border-wp-background-400 bg-wp-background-100 dark:bg-wp-background-200"
|
||||
:aria-label="$t('pipeline_feed')"
|
||||
>
|
||||
<router-link
|
||||
<router-link
|
||||
v-for="pipeline in sortedPipelines"
|
||||
:key="pipeline.id"
|
||||
:to="{
|
||||
@ -13,12 +14,13 @@
|
||||
params: { repoId: pipeline.repo_id, pipelineId: pipeline.number },
|
||||
}"
|
||||
class="flex w-full border-b border-wp-background-400 px-2 py-4 hover:bg-wp-background-300 hover:shadow-sm dark:hover:bg-wp-background-400"
|
||||
> <PipelineFeedItem :pipeline="pipeline" /> </router-link
|
||||
> <span v-if="sortedPipelines.length === 0" class="m-4 text-wp-text-100">{{
|
||||
$t('repo.pipeline.no_pipelines')
|
||||
}}</span
|
||||
>
|
||||
<PipelineFeedItem :pipeline="pipeline" />
|
||||
</router-link>
|
||||
|
||||
<span v-if="sortedPipelines.length === 0" class="m-4 text-wp-text-100">{{ $t('repo.pipeline.no_pipelines') }}</span>
|
||||
</aside>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,42 +1,41 @@
|
||||
<template>
|
||||
|
||||
<div v-if="innerValue" class="space-y-4">
|
||||
|
||||
<form @submit.prevent="save">
|
||||
<InputField v-slot="{ id }" :label="$t('registries.address.address')">
|
||||
<!-- TODO: check input field Address is a valid address -->
|
||||
<TextField
|
||||
<InputField v-slot="{ id }" :label="$t('registries.address.address')"
|
||||
> <!-- TODO: check input field Address is a valid address --> <TextField
|
||||
:id="id"
|
||||
v-model="innerValue.address"
|
||||
:placeholder="$t('registries.address.desc')"
|
||||
required
|
||||
:disabled="isEditing || isReadOnly"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('username')">
|
||||
<TextField
|
||||
/> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('username')"
|
||||
> <TextField
|
||||
:id="id"
|
||||
v-model="innerValue.username"
|
||||
:placeholder="$t('username')"
|
||||
required
|
||||
:disabled="isReadOnly"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField v-if="!isReadOnly" v-slot="{ id }" :label="$t('password')">
|
||||
<TextField :id="id" v-model="innerValue.password" :placeholder="$t('password')" :required="!isEditing" />
|
||||
</InputField>
|
||||
|
||||
/> </InputField
|
||||
> <InputField v-if="!isReadOnly" v-slot="{ id }" :label="$t('password')"
|
||||
> <TextField :id="id" v-model="innerValue.password" :placeholder="$t('password')" :required="!isEditing" />
|
||||
</InputField
|
||||
>
|
||||
<div v-if="!isReadOnly" class="flex gap-2">
|
||||
<Button type="button" color="gray" :text="$t('cancel')" @click="$emit('cancel')" />
|
||||
<Button
|
||||
<Button type="button" color="gray" :text="$t('cancel')" @click="$emit('cancel')" /> <Button
|
||||
type="submit"
|
||||
color="default"
|
||||
:is-loading="isSaving"
|
||||
:text="isEditing ? $t('registries.save') : $t('registries.add')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,29 +1,29 @@
|
||||
<template>
|
||||
|
||||
<div class="space-y-4 text-wp-text-100">
|
||||
<ListItem
|
||||
<ListItem
|
||||
v-for="registry in registries"
|
||||
:key="registry.id"
|
||||
class="items-center !bg-wp-background-200 shadow-md dark:!bg-wp-background-100"
|
||||
>
|
||||
<span>{{ registry.address }}</span>
|
||||
<IconButton
|
||||
> <span>{{ registry.address }}</span
|
||||
> <IconButton
|
||||
:icon="registry.readonly ? 'chevron-right' : 'edit'"
|
||||
class="ml-auto h-8 w-8"
|
||||
:title="registry.readonly ? $t('registries.view') : $t('registries.edit')"
|
||||
@click="editRegistry(registry)"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
v-if="!registry.readonly"
|
||||
icon="trash"
|
||||
class="h-8 w-8 hover:text-wp-error-100"
|
||||
:is-loading="isDeleting"
|
||||
:title="$t('registries.delete')"
|
||||
@click="deleteRegistry(registry)"
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
/> </ListItem
|
||||
>
|
||||
<div v-if="registries?.length === 0" class="ml-2">{{ $t('registries.none') }}</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,45 +1,57 @@
|
||||
<template>
|
||||
<router-link
|
||||
<router-link
|
||||
v-if="repo"
|
||||
:to="{ name: 'repo', params: { repoId: repo.id } }"
|
||||
class="flex cursor-pointer flex-col overflow-hidden rounded-md border border-wp-background-400 bg-wp-background-100 p-3 shadow-sm hover:bg-wp-background-300 hover:shadow-sm dark:bg-wp-background-200 dark:hover:bg-wp-background-300"
|
||||
>
|
||||
>
|
||||
<div class="grid grid-cols-[auto,1fr] items-center gap-y-4">
|
||||
|
||||
<div class="text-lg text-wp-text-100">{{ `${repo.owner} / ${repo.name}` }}</div>
|
||||
|
||||
<div class="ml-auto text-wp-text-100">
|
||||
|
||||
<div
|
||||
v-if="repo.visibility === RepoVisibility.Private"
|
||||
:title="`${$t('repo.visibility.visibility')}: ${$t(`repo.visibility.private.private`)}`"
|
||||
>
|
||||
<Icon name="visibility-private" />
|
||||
<Icon name="visibility-private" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else-if="repo.visibility === RepoVisibility.Internal"
|
||||
:title="`${$t('repo.visibility.visibility')}: ${$t(`repo.visibility.internal.internal`)}`"
|
||||
>
|
||||
<Icon name="visibility-internal" />
|
||||
<Icon name="visibility-internal" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-span-2 flex w-full gap-x-4 text-wp-text-100">
|
||||
<template v-if="lastPipeline">
|
||||
<template v-if="lastPipeline"
|
||||
>
|
||||
<div class="flex min-w-0 flex-1 items-center gap-x-1">
|
||||
<PipelineStatusIcon v-if="lastPipeline" :status="lastPipeline.status" />
|
||||
<span class="overflow-hidden overflow-ellipsis whitespace-nowrap pl-1">{{ shortMessage }}</span>
|
||||
<PipelineStatusIcon v-if="lastPipeline" :status="lastPipeline.status" /> <span
|
||||
class="overflow-hidden overflow-ellipsis whitespace-nowrap pl-1"
|
||||
>{{ shortMessage }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto flex flex-shrink-0 items-center gap-x-1">
|
||||
<Icon name="since" />
|
||||
<span>{{ since }}</span>
|
||||
<Icon name="since" /> <span>{{ since }}</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</template
|
||||
>
|
||||
<div v-else class="flex gap-x-2">
|
||||
<span>{{ $t('repo.pipeline.no_pipelines') }}</span>
|
||||
<span>{{ $t('repo.pipeline.no_pipelines') }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</router-link>
|
||||
</router-link
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,63 +1,81 @@
|
||||
<template>
|
||||
<ListItem v-if="pipeline" class="w-full !p-0">
|
||||
<ListItem v-if="pipeline" class="w-full !p-0"
|
||||
>
|
||||
<div class="flex w-11 flex-shrink-0 items-center">
|
||||
|
||||
<div class="flex h-full w-6 flex-wrap items-center justify-between">
|
||||
<PipelineStatusIcon class="mx-2 md:mx-3" :status="pipeline.status" />
|
||||
<PipelineStatusIcon class="mx-2 md:mx-3" :status="pipeline.status" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex min-w-0 flex-grow flex-wrap px-4 py-0.5 !pl-0.5 md:flex-nowrap">
|
||||
|
||||
<div class="hidden flex-shrink-0 items-center md:flex">
|
||||
<Icon v-if="pipeline.event === 'cron'" name="stopwatch" class="text-wp-text-100" />
|
||||
<img v-else class="w-6 rounded-md" :src="pipeline.author_avatar" />
|
||||
<Icon v-if="pipeline.event === 'cron'" name="stopwatch" class="text-wp-text-100" /> <img
|
||||
v-else
|
||||
class="w-6 rounded-md"
|
||||
:src="pipeline.author_avatar"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex w-full min-w-0 items-center md:mx-4 md:w-auto">
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
<span class="md:display-unset hidden text-wp-text-alt-100">#{{ pipeline.number }}</span>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
<span class="md:display-unset mx-2 hidden text-wp-text-alt-100">-</span>
|
||||
<span
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> <span
|
||||
class="md:display-unset hidden text-wp-text-alt-100"
|
||||
>#{{ pipeline.number }}</span
|
||||
> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> <span
|
||||
class="md:display-unset mx-2 hidden text-wp-text-alt-100"
|
||||
>-</span
|
||||
> <span
|
||||
class="overflow-hidden overflow-ellipsis whitespace-nowrap text-wp-text-100 underline md:no-underline"
|
||||
:title="message"
|
||||
> {{ shortMessage }} </span
|
||||
>
|
||||
{{ shortMessage }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="grid w-full flex-shrink-0 grid-flow-col grid-cols-2 grid-rows-2 gap-x-4 gap-y-2 py-2 text-wp-text-100 md:ml-auto md:w-80"
|
||||
>
|
||||
|
||||
<div class="flex min-w-0 items-center space-x-2">
|
||||
<span :title="pipelineEventTitle">
|
||||
<Icon v-if="pipeline.event === 'pull_request'" name="pull-request" class="" />
|
||||
<Icon v-else-if="pipeline.event === 'pull_request_closed'" name="pull-request-closed" class="" />
|
||||
<Icon v-else-if="pipeline.event === 'deployment'" name="deployment" class="" />
|
||||
<Icon v-else-if="pipeline.event === 'tag' || pipeline.event === 'release'" name="tag" class="" />
|
||||
<Icon v-else-if="pipeline.event === 'cron'" name="push" class="" />
|
||||
<Icon v-else-if="pipeline.event === 'manual'" name="manual-pipeline" class="" />
|
||||
<Icon v-else name="push" class="" />
|
||||
</span>
|
||||
<span class="truncate">{{ prettyRef }}</span>
|
||||
<span :title="pipelineEventTitle"
|
||||
> <Icon v-if="pipeline.event === 'pull_request'" name="pull-request" class="" /> <Icon
|
||||
v-else-if="pipeline.event === 'pull_request_closed'"
|
||||
name="pull-request-closed"
|
||||
class=""
|
||||
/> <Icon v-else-if="pipeline.event === 'deployment'" name="deployment" class="" /> <Icon
|
||||
v-else-if="pipeline.event === 'tag' || pipeline.event === 'release'"
|
||||
name="tag"
|
||||
class=""
|
||||
/> <Icon v-else-if="pipeline.event === 'cron'" name="push" class="" /> <Icon
|
||||
v-else-if="pipeline.event === 'manual'"
|
||||
name="manual-pipeline"
|
||||
class=""
|
||||
/> <Icon v-else name="push" class="" /> </span
|
||||
> <span class="truncate">{{ prettyRef }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex min-w-0 items-center space-x-2">
|
||||
<Icon name="commit" class="" />
|
||||
<span class="truncate">{{ pipeline.commit.slice(0, 10) }}</span>
|
||||
<Icon name="commit" class="" /> <span class="truncate">{{ pipeline.commit.slice(0, 10) }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex min-w-0 items-center space-x-2" :title="$t('repo.pipeline.duration')">
|
||||
<Icon name="duration" />
|
||||
<span class="truncate">{{ duration }}</span>
|
||||
<Icon name="duration" /> <span class="truncate">{{ duration }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex min-w-0 items-center space-x-2" :title="$t('repo.pipeline.created', { created })">
|
||||
<Icon name="since" />
|
||||
<span class="truncate">{{ since }}</span>
|
||||
<Icon name="since" /> <span class="truncate">{{ since }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ListItem>
|
||||
</ListItem
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
|
||||
<div v-if="pipelines" class="space-y-4">
|
||||
<PipelineItem
|
||||
<PipelineItem
|
||||
v-for="pipeline in pipelines"
|
||||
:key="pipeline.id"
|
||||
:to="{
|
||||
@ -8,11 +9,12 @@
|
||||
params: { pipelineId: pipeline.number },
|
||||
}"
|
||||
:pipeline="pipeline"
|
||||
/>
|
||||
<Panel v-if="pipelines.length === 0">
|
||||
<span class="text-wp-text-100">{{ $t('repo.pipeline.no_pipelines') }}</span>
|
||||
</Panel>
|
||||
/> <Panel v-if="pipelines.length === 0"
|
||||
> <span class="text-wp-text-100">{{ $t('repo.pipeline.no_pipelines') }}</span
|
||||
> </Panel
|
||||
>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,35 +1,36 @@
|
||||
<template>
|
||||
|
||||
<div v-if="pipeline" class="flex flex-col pt-8 md:pt-0">
|
||||
|
||||
<div
|
||||
class="code-box-log flex flex-grow flex-col overflow-hidden !p-0 shadow-md md:mt-0 md:!rounded-lg"
|
||||
@mouseover="showActions = true"
|
||||
@mouseleave="showActions = false"
|
||||
>
|
||||
|
||||
<div
|
||||
class="fixed left-0 top-0 flex w-full flex-row items-center bg-wp-code-100 px-4 py-1 md:relative md:left-auto md:top-auto"
|
||||
>
|
||||
<span class="text-base font-bold text-wp-code-text-alt-100">
|
||||
<span class="md:display-unset hidden">{{ $t('repo.pipeline.log_title') }}</span>
|
||||
<span class="md:hidden">{{ step?.name }}</span>
|
||||
</span>
|
||||
|
||||
<span class="text-base font-bold text-wp-code-text-alt-100"
|
||||
> <span class="md:display-unset hidden">{{ $t('repo.pipeline.log_title') }}</span
|
||||
> <span class="md:hidden">{{ step?.name }}</span
|
||||
> </span
|
||||
>
|
||||
<div class="ml-auto flex flex-row items-center gap-x-2">
|
||||
<IconButton
|
||||
<IconButton
|
||||
v-if="step?.finished !== undefined && hasLogs"
|
||||
:is-loading="downloadInProgress"
|
||||
:title="$t('repo.pipeline.actions.log_download')"
|
||||
class="text-wp-code-text-alt-100 hover:!bg-white hover:!bg-opacity-10"
|
||||
icon="download"
|
||||
@click="download"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
v-if="step?.finished !== undefined && hasLogs && hasPushPermission"
|
||||
:title="$t('repo.pipeline.actions.log_delete')"
|
||||
class="text-wp-code-text-alt-100 hover:!bg-white hover:!bg-opacity-10"
|
||||
icon="trash"
|
||||
@click="deleteLogs"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
v-if="step?.finished === undefined"
|
||||
:title="
|
||||
autoScroll ? $t('repo.pipeline.actions.log_auto_scroll_off') : $t('repo.pipeline.actions.log_auto_scroll')
|
||||
@ -37,13 +38,13 @@
|
||||
class="text-wp-code-text-alt-100 hover:!bg-white hover:!bg-opacity-10"
|
||||
:icon="autoScroll ? 'auto-scroll' : 'auto-scroll-off'"
|
||||
@click="autoScroll = !autoScroll"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
class="text-wp-code-text-alt-100 hover:!bg-white hover:!bg-opacity-10 md:!hidden"
|
||||
icon="close"
|
||||
@click="$emit('update:step-id', null)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -51,8 +52,9 @@
|
||||
ref="consoleElement"
|
||||
class="grid w-full max-w-full flex-grow auto-rows-min grid-cols-[min-content,minmax(0,1fr),min-content] overflow-y-auto overflow-x-hidden p-4 text-xs md:text-sm"
|
||||
>
|
||||
|
||||
<div v-for="line in log" :key="line.index" class="contents font-mono">
|
||||
<a
|
||||
<a
|
||||
:id="`L${line.number}`"
|
||||
:href="`#L${line.number}`"
|
||||
class="select-none whitespace-nowrap pl-2 pr-6 text-right text-wp-code-text-line-numbers-100"
|
||||
@ -62,11 +64,8 @@
|
||||
'bg-blue-600 bg-opacity-30': isSelected(line),
|
||||
underline: isSelected(line),
|
||||
}"
|
||||
>
|
||||
{{ line.number }}
|
||||
</a>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<span
|
||||
> {{ line.number }} </a
|
||||
> <!-- eslint-disable vue/no-v-html --> <span
|
||||
class="whitespace-pre-wrap break-words align-top"
|
||||
:class="{
|
||||
'bg-10.168.64.121-600 bg-opacity-40 dark:bg-red-800 dark:bg-opacity-50': line.type === 'error',
|
||||
@ -74,38 +73,44 @@
|
||||
'bg-blue-600 bg-opacity-30': isSelected(line),
|
||||
}"
|
||||
v-html="line.text"
|
||||
/>
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
<span
|
||||
/> <!-- eslint-enable vue/no-v-html --> <span
|
||||
class="select-none whitespace-nowrap pr-1 text-right text-wp-code-text-line-numbers-100"
|
||||
:class="{
|
||||
'bg-red-600 bg-opacity-40 dark:bg-red-800 dark:bg-opacity-50': line.type === 'error',
|
||||
'bg-yellow-600 bg-opacity-40 dark:bg-yellow-800 dark:bg-opacity-50': line.type === 'warning',
|
||||
'bg-blue-600 bg-opacity-30': isSelected(line),
|
||||
}"
|
||||
> {{ formatTime(line.time) }} </span
|
||||
>
|
||||
{{ formatTime(line.time) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="m-auto text-xl text-wp-text-alt-100">
|
||||
<span v-if="step?.state === 'skipped'">{{ $t('repo.pipeline.actions.canceled') }}</span>
|
||||
<span v-else-if="!step?.started">{{ $t('repo.pipeline.step_not_started') }}</span>
|
||||
<span v-if="step?.state === 'skipped'">{{ $t('repo.pipeline.actions.canceled') }}</span
|
||||
> <span v-else-if="!step?.started">{{ $t('repo.pipeline.step_not_started') }}</span
|
||||
>
|
||||
<div v-else-if="!loadedLogs">{{ $t('repo.pipeline.loading') }}</div>
|
||||
|
||||
<div v-else-if="log?.length === 0">{{ $t('repo.pipeline.no_logs') }}</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="step?.finished !== undefined"
|
||||
class="text-md flex w-full items-center bg-wp-code-100 px-4 py-1 font-bold text-wp-code-text-alt-100 md:min-h-[27px]"
|
||||
>
|
||||
<PipelineStatusIcon :status="step.state" class="!h-4 !w-4" />
|
||||
<span v-if="step?.error" class="px-2">{{ step.error }}</span>
|
||||
<span v-else class="px-2">{{ $t('repo.pipeline.exit_code', { exitCode: step.exit_code }) }}</span>
|
||||
<PipelineStatusIcon :status="step.state" class="!h-4 !w-4" /> <span v-if="step?.error" class="px-2">{{
|
||||
step.error
|
||||
}}</span
|
||||
> <span v-else class="px-2">{{ $t('repo.pipeline.exit_code', { exitCode: step.exit_code }) }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,6 +1,4 @@
|
||||
<template>
|
||||
<CrowIcon class="crow h-15" />
|
||||
</template>
|
||||
<template> <CrowIcon class="crow h-15" /> </template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import CrowIcon from '~/assets/crow.svg?component';
|
||||
|
@ -1,9 +1,10 @@
|
||||
<template>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-center"
|
||||
:title="$t('repo.pipeline.status.status', { status: statusDescriptions[status] })"
|
||||
>
|
||||
<Icon
|
||||
<Icon
|
||||
:name="service ? 'settings' : `status-${status}`"
|
||||
size="1.5rem"
|
||||
:class="{
|
||||
@ -16,6 +17,7 @@
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<span v-if="started" class="ml-auto text-sm">{{ duration }}</span>
|
||||
<span v-if="started" class="ml-auto text-sm">{{ duration }}</span
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,98 +1,111 @@
|
||||
<template>
|
||||
|
||||
<div class="md:min-w-xs flex w-full flex-col gap-2 pb-2 text-wp-text-100 md:w-3/12 md:max-w-md">
|
||||
|
||||
<div
|
||||
class="flex flex-shrink-0 flex-wrap justify-between gap-1 rounded-md border border-wp-background-400 bg-wp-background-100 p-4 shadow-sm dark:bg-wp-background-200"
|
||||
>
|
||||
|
||||
<div class="flex flex-shrink-0 items-center space-x-1">
|
||||
|
||||
<div class="flex items-center">
|
||||
<Icon v-if="pipeline.event === 'cron'" name="stopwatch" />
|
||||
<img v-else class="w-6 rounded-md" :src="pipeline.author_avatar" />
|
||||
<Icon v-if="pipeline.event === 'cron'" name="stopwatch" /> <img
|
||||
v-else
|
||||
class="w-6 rounded-md"
|
||||
:src="pipeline.author_avatar"
|
||||
/>
|
||||
</div>
|
||||
<span>{{ pipeline.author }}</span>
|
||||
<span>{{ pipeline.author }}</span
|
||||
>
|
||||
</div>
|
||||
<a
|
||||
<a
|
||||
v-if="pipeline.event === 'pull_request' || pipeline.event === 'pull_request_closed'"
|
||||
class="flex min-w-0 items-center space-x-1 text-wp-link-100 hover:text-wp-link-200"
|
||||
:href="pipeline.forge_url"
|
||||
>
|
||||
<Icon name="pull-request" />
|
||||
<span class="truncate">{{ prettyRef }}</span>
|
||||
</a>
|
||||
<router-link
|
||||
> <Icon name="pull-request" /> <span class="truncate">{{ prettyRef }}</span
|
||||
> </a
|
||||
> <router-link
|
||||
v-else-if="pipeline.event === 'push' || pipeline.event === 'manual' || pipeline.event === 'deployment'"
|
||||
class="flex min-w-0 items-center space-x-1 text-wp-link-100 hover:text-wp-link-200"
|
||||
:to="{ name: 'repo-branch', params: { branch: prettyRef } }"
|
||||
> <Icon v-if="pipeline.event === 'manual'" name="manual-pipeline" /> <Icon
|
||||
v-else-if="pipeline.event === 'push'"
|
||||
name="push"
|
||||
/> <Icon v-else-if="pipeline.event === 'deployment'" name="deployment" /> <span class="truncate">{{
|
||||
prettyRef
|
||||
}}</span
|
||||
> </router-link
|
||||
>
|
||||
<Icon v-if="pipeline.event === 'manual'" name="manual-pipeline" />
|
||||
<Icon v-else-if="pipeline.event === 'push'" name="push" />
|
||||
<Icon v-else-if="pipeline.event === 'deployment'" name="deployment" />
|
||||
<span class="truncate">{{ prettyRef }}</span>
|
||||
</router-link>
|
||||
<div v-else class="flex min-w-0 items-center space-x-1">
|
||||
<Icon v-if="pipeline.event === 'tag' || pipeline.event === 'release'" name="tag" />
|
||||
|
||||
<span class="truncate">{{ prettyRef }}</span>
|
||||
<Icon v-if="pipeline.event === 'tag' || pipeline.event === 'release'" name="tag" /> <span class="truncate">{{
|
||||
prettyRef
|
||||
}}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-shrink-0 items-center">
|
||||
<template v-if="pipeline.event === 'pull_request'">
|
||||
<Icon name="commit" />
|
||||
<span>{{ pipeline.commit.slice(0, 10) }}</span>
|
||||
</template>
|
||||
<a
|
||||
<template v-if="pipeline.event === 'pull_request'"
|
||||
> <Icon name="commit" /> <span>{{ pipeline.commit.slice(0, 10) }}</span
|
||||
> </template
|
||||
> <a
|
||||
v-else
|
||||
class="flex items-center text-wp-link-100 hover:text-wp-link-200"
|
||||
:href="pipeline.forge_url"
|
||||
target="_blank"
|
||||
> <Icon name="commit" /> <span>{{ pipeline.commit.slice(0, 10) }}</span
|
||||
> </a
|
||||
>
|
||||
<Icon name="commit" />
|
||||
<span>{{ pipeline.commit.slice(0, 10) }}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<Panel v-if="pipeline.workflows === undefined || pipeline.workflows.length === 0">
|
||||
<span>{{ $t('repo.pipeline.no_pipeline_steps') }}</span>
|
||||
</Panel>
|
||||
|
||||
<Panel v-if="pipeline.workflows === undefined || pipeline.workflows.length === 0"
|
||||
> <span>{{ $t('repo.pipeline.no_pipeline_steps') }}</span
|
||||
> </Panel
|
||||
>
|
||||
<div class="relative min-h-0 w-full flex-grow">
|
||||
|
||||
<div class="absolute left-0 right-0 top-0 flex h-full flex-col gap-y-2 md:overflow-y-auto">
|
||||
|
||||
<div
|
||||
v-for="workflow in pipeline.workflows"
|
||||
:key="workflow.id"
|
||||
class="rounded-md border border-wp-background-400 bg-wp-background-100 p-2 shadow-sm dark:bg-wp-background-200"
|
||||
>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
|
||||
<div v-if="workflow.environ" class="flex flex-wrap justify-end gap-x-1 gap-y-2 pr-1 pt-1 text-xs">
|
||||
<div v-for="(value, key) in workflow.environ" :key="key">
|
||||
<Badge :label="key" :value="value" />
|
||||
</div>
|
||||
|
||||
<div v-for="(value, key) in workflow.environ" :key="key"> <Badge :label="key" :value="value" /> </div>
|
||||
|
||||
</div>
|
||||
<button
|
||||
<button
|
||||
v-if="!singleConfig"
|
||||
type="button"
|
||||
:title="workflow.name"
|
||||
class="hover-effect flex items-center gap-2 rounded-md px-1 py-2 hover:bg-wp-background-300 dark:hover:bg-wp-background-400"
|
||||
@click="workflowsCollapsed[workflow.id] = !workflowsCollapsed[workflow.id]"
|
||||
>
|
||||
<Icon
|
||||
<Icon
|
||||
name="chevron-right"
|
||||
class="h-6 min-w-6 transition-transform duration-150"
|
||||
:class="{ 'rotate-90 transform': !workflowsCollapsed[workflow.id] }"
|
||||
/>
|
||||
<PipelineStatusIcon :status="workflow.state" class="!h-4 !w-4" />
|
||||
<span class="truncate">{{ workflow.name }}</span>
|
||||
<PipelineStepDuration
|
||||
/> <PipelineStatusIcon :status="workflow.state" class="!h-4 !w-4" /> <span class="truncate">{{
|
||||
workflow.name
|
||||
}}</span
|
||||
> <PipelineStepDuration
|
||||
v-if="workflow.started !== workflow.finished"
|
||||
:workflow="workflow"
|
||||
class="pr-2px mr-1"
|
||||
/>
|
||||
</button>
|
||||
/> </button
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="overflow-hidden transition-height duration-150"
|
||||
:class="{ 'max-h-0': workflowsCollapsed[workflow.id], 'ml-[1.6rem]': !singleConfig }"
|
||||
>
|
||||
<button
|
||||
<button
|
||||
v-for="step in workflow.children"
|
||||
:key="step.pid"
|
||||
type="button"
|
||||
@ -104,15 +117,20 @@
|
||||
}"
|
||||
@click="$emit('update:selected-step-id', step.pid)"
|
||||
>
|
||||
<PipelineStatusIcon :service="step.type === StepType.Service" :status="step.state" class="!h-4 !w-4" />
|
||||
<span class="truncate">{{ step.name }}</span>
|
||||
<PipelineStepDuration :step="step" />
|
||||
</button>
|
||||
<PipelineStatusIcon :service="step.type === StepType.Service" :status="step.state" class="!h-4 !w-4" />
|
||||
<span class="truncate">{{ step.name }}</span
|
||||
> <PipelineStepDuration :step="step" /> </button
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,57 +1,68 @@
|
||||
<template>
|
||||
|
||||
<div v-if="innerValue" class="space-y-4">
|
||||
|
||||
<form @submit.prevent="save">
|
||||
<InputField v-slot="{ id }" :label="$t('secrets.name')">
|
||||
<TextField
|
||||
<InputField v-slot="{ id }" :label="$t('secrets.name')"
|
||||
> <TextField
|
||||
:id="id"
|
||||
v-model="innerValue.name"
|
||||
:placeholder="$t('secrets.name')"
|
||||
required
|
||||
:disabled="isEditingSecret"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('secrets.value')">
|
||||
<TextField
|
||||
/> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('secrets.value')"
|
||||
> <TextField
|
||||
:id="id"
|
||||
v-model="innerValue.value"
|
||||
:placeholder="$t('secrets.value')"
|
||||
:lines="5"
|
||||
:required="!isEditingSecret"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('secrets.plugins.images')">
|
||||
<span class="mb-2 ml-1 text-wp-text-alt-100">{{ $t('secrets.plugins.desc') }}</span>
|
||||
|
||||
/> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('secrets.plugins.images')"
|
||||
> <span class="mb-2 ml-1 text-wp-text-alt-100">{{ $t('secrets.plugins.desc') }}</span
|
||||
>
|
||||
<div class="flex flex-col gap-2">
|
||||
|
||||
<div v-for="image in innerValue.images" :key="image" class="flex gap-2">
|
||||
<TextField :id="id" :model-value="image" disabled />
|
||||
<Button type="button" color="gray" start-icon="trash" @click="removeImage(image)" />
|
||||
<TextField :id="id" :model-value="image" disabled /> <Button
|
||||
type="button"
|
||||
color="gray"
|
||||
start-icon="trash"
|
||||
@click="removeImage(image)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<TextField :id="id" v-model="newImage" @keydown.enter.prevent="addNewImage" />
|
||||
<Button type="button" color="gray" start-icon="plus" @click="addNewImage" />
|
||||
<TextField :id="id" v-model="newImage" @keydown.enter.prevent="addNewImage" /> <Button
|
||||
type="button"
|
||||
color="gray"
|
||||
start-icon="plus"
|
||||
@click="addNewImage"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</InputField>
|
||||
|
||||
<InputField :label="$t('secrets.events.events')">
|
||||
<Warning class="mb-4 text-sm" :text="$t('secrets.events.warning')" />
|
||||
<CheckboxesField v-model="innerValue.events" :options="secretEventsOptions" />
|
||||
</InputField>
|
||||
|
||||
</InputField
|
||||
> <InputField :label="$t('secrets.events.events')"
|
||||
> <Warning class="mb-4 text-sm" :text="$t('secrets.events.warning')" /> <CheckboxesField
|
||||
v-model="innerValue.events"
|
||||
:options="secretEventsOptions"
|
||||
/> </InputField
|
||||
>
|
||||
<div class="flex gap-2">
|
||||
<Button type="button" color="gray" :text="$t('cancel')" @click="$emit('cancel')" />
|
||||
<Button
|
||||
<Button type="button" color="gray" :text="$t('cancel')" @click="$emit('cancel')" /> <Button
|
||||
type="submit"
|
||||
color="default"
|
||||
:is-loading="isSaving"
|
||||
:text="isEditingSecret ? $t('secrets.save') : $t('secrets.add')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,38 +1,38 @@
|
||||
<template>
|
||||
|
||||
<div class="space-y-4 text-wp-text-100">
|
||||
<ListItem
|
||||
<ListItem
|
||||
v-for="secret in secrets"
|
||||
:key="secret.id"
|
||||
class="items-center !bg-wp-background-200 shadow-md dark:!bg-wp-background-100"
|
||||
>
|
||||
<span>{{ secret.name }}</span>
|
||||
<Badge
|
||||
> <span>{{ secret.name }}</span
|
||||
> <Badge
|
||||
v-if="secret.edit === false"
|
||||
class="ml-2"
|
||||
:label="secret.org_id === 0 ? $t('global_level_secret') : $t('org_level_secret')"
|
||||
/>
|
||||
<div class="md:display-unset ml-auto hidden space-x-2">
|
||||
<Badge v-for="event in secret.events" :key="event" :label="event" />
|
||||
<Badge v-for="event in secret.events" :key="event" :label="event" />
|
||||
</div>
|
||||
<template v-if="secret.edit !== false">
|
||||
<IconButton
|
||||
<template v-if="secret.edit !== false"
|
||||
> <IconButton
|
||||
icon="edit"
|
||||
class="ml-auto h-8 w-8 md:ml-2"
|
||||
:title="$t('secrets.edit')"
|
||||
@click="editSecret(secret)"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="trash"
|
||||
class="ml-2 h-8 w-8 hover:text-wp-error-100"
|
||||
:is-loading="isDeleting"
|
||||
:title="$t('secrets.delete')"
|
||||
@click="deleteSecret(secret)"
|
||||
/>
|
||||
</template>
|
||||
</ListItem>
|
||||
|
||||
/> </template
|
||||
> </ListItem
|
||||
>
|
||||
<div v-if="secrets?.length === 0" class="ml-2">{{ $t('secrets.none') }}</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,40 +1,49 @@
|
||||
<template>
|
||||
|
||||
<main class="flex h-full w-full flex-col items-center justify-center">
|
||||
<Error v-if="errorMessage" class="w-full md:w-3xl">
|
||||
<span class="whitespace-pre">{{ errorMessage }}</span>
|
||||
<span v-if="errorDescription" class="mt-1 whitespace-pre">{{ errorDescription }}</span>
|
||||
<a
|
||||
<Error v-if="errorMessage" class="w-full md:w-3xl"
|
||||
> <span class="whitespace-pre">{{ errorMessage }}</span
|
||||
> <span v-if="errorDescription" class="mt-1 whitespace-pre">{{ errorDescription }}</span
|
||||
> <a
|
||||
v-if="errorUri"
|
||||
:href="errorUri"
|
||||
target="_blank"
|
||||
class="mt-1 cursor-pointer text-wp-link-100 hover:text-wp-link-200"
|
||||
>
|
||||
<span>{{ errorUri }}</span>
|
||||
</a>
|
||||
</Error>
|
||||
|
||||
> <span>{{ errorUri }}</span
|
||||
> </a
|
||||
> </Error
|
||||
>
|
||||
<div
|
||||
class="flex min-h-sm w-full flex-col overflow-hidden border border-wp-background-400 bg-wp-background-100 shadow-sm dark:bg-wp-background-200 md:m-8 md:w-3xl md:flex-row md:rounded-md"
|
||||
>
|
||||
<div class="flex min-h-48 items-center justify-center bg-wp-background-secondary-800 dark:bg-wp-primary-300 md:w-3/5">
|
||||
<CrowLogo preserveAspectRatio="xMinYMin slice" class="h-32 w-auto md:h-48" />
|
||||
|
||||
<div
|
||||
class="flex min-h-48 items-center justify-center bg-wp-background-secondary-800 dark:bg-wp-primary-300 md:w-3/5"
|
||||
>
|
||||
<CrowLogo preserveAspectRatio="xMinYMin slice" class="h-32 w-auto md:h-48" />
|
||||
</div>
|
||||
|
||||
<div class="flex min-h-48 flex-col items-center justify-center gap-4 p-4 text-center md:w-2/5">
|
||||
|
||||
<h1 class="text-xl text-wp-text-100">{{ $t('welcome') }}</h1>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<Button
|
||||
<Button
|
||||
v-for="forge in forges"
|
||||
:key="forge.id"
|
||||
:start-icon="forge.type === 'addon' ? 'repo' : forge.type"
|
||||
class="!whitespace-normal"
|
||||
@click="doLogin(forge.id)"
|
||||
> {{ $t('login_with', { forge: getHostFromUrl(forge) }) }} </Button
|
||||
>
|
||||
{{ $t('login_with', { forge: getHostFromUrl(forge) }) }}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,8 +1,9 @@
|
||||
<template>
|
||||
|
||||
<div class="flex h-full w-full flex-col items-center justify-center">
|
||||
|
||||
<p class="mb-8 text-2xl">{{ $t('not_found.not_found') }}</p>
|
||||
<router-link class="text-blue-400" replace :to="{ name: 'home' }">
|
||||
{{ $t('not_found.back_home') }}
|
||||
</router-link>
|
||||
<router-link class="text-blue-400" replace :to="{ name: 'home' }"> {{ $t('not_found.back_home') }} </router-link>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
@ -1,34 +1,31 @@
|
||||
<template>
|
||||
<Scaffold v-model:search="search" :go-back="goBack">
|
||||
<template #title>
|
||||
{{ $t('repo.add') }}
|
||||
</template>
|
||||
|
||||
<Scaffold v-model:search="search" :go-back="goBack"
|
||||
> <template #title> {{ $t('repo.add') }} </template>
|
||||
<div class="space-y-4">
|
||||
<template v-if="repos !== undefined && repos.length > 0">
|
||||
<ListItem
|
||||
<template v-if="repos !== undefined && repos.length > 0"
|
||||
> <ListItem
|
||||
v-for="repo in searchedRepos"
|
||||
:key="repo.id"
|
||||
class="items-center"
|
||||
:to="repo.active ? { name: 'repo', params: { repoId: repo.id } } : undefined"
|
||||
>
|
||||
<span class="text-wp-text-100">{{ repo.full_name }}</span>
|
||||
<span v-if="repo.active" class="ml-auto text-wp-text-alt-100">{{ $t('repo.enable.enabled') }}</span>
|
||||
> <span class="text-wp-text-100">{{ repo.full_name }}</span
|
||||
> <span v-if="repo.active" class="ml-auto text-wp-text-alt-100">{{ $t('repo.enable.enabled') }}</span
|
||||
>
|
||||
<div v-else class="ml-auto flex items-center">
|
||||
<Badge v-if="repo.id" class="md:display-unset mr-2 hidden" :label="$t('repo.enable.disabled')" />
|
||||
<Button
|
||||
<Badge v-if="repo.id" class="md:display-unset mr-2 hidden" :label="$t('repo.enable.disabled')" /> <Button
|
||||
:text="$t('repo.enable.enable')"
|
||||
:is-loading="isActivatingRepo && repoToActivate?.forge_remote_id === repo.forge_remote_id"
|
||||
@click="activateRepo(repo)"
|
||||
/>
|
||||
</div>
|
||||
</ListItem>
|
||||
</template>
|
||||
<div v-else-if="loading" class="flex justify-center text-wp-text-100">
|
||||
<Icon name="spinner" />
|
||||
</div>
|
||||
</ListItem
|
||||
> </template
|
||||
>
|
||||
<div v-else-if="loading" class="flex justify-center text-wp-text-100"> <Icon name="spinner" /> </div>
|
||||
|
||||
</div>
|
||||
</Scaffold>
|
||||
</Scaffold
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,37 +1,41 @@
|
||||
<template>
|
||||
<Scaffold v-model:search="search">
|
||||
<template #title>
|
||||
{{ $t('repositories') }}
|
||||
</template>
|
||||
|
||||
<template #headerActions>
|
||||
<Button :to="{ name: 'repo-add' }" start-icon="plus" :text="$t('repo.add')" />
|
||||
</template>
|
||||
|
||||
<Transition name="fade" mode="out-in">
|
||||
<Scaffold v-model:search="search"
|
||||
> <template #title> {{ $t('repositories') }} </template> <template #headerActions
|
||||
> <Button :to="{ name: 'repo-add' }" start-icon="plus" :text="$t('repo.add')" /> </template
|
||||
> <Transition name="fade" mode="out-in"
|
||||
>
|
||||
<div v-if="search === '' && repos.length > 0" class="grid gap-8">
|
||||
|
||||
<div
|
||||
v-if="reposLastAccess.length > 0 && repos.length > 4"
|
||||
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-2"
|
||||
>
|
||||
<RepoItem v-for="repo in reposLastAccess" :key="repo.id" :repo="repo" />
|
||||
<RepoItem v-for="repo in reposLastAccess" :key="repo.id" :repo="repo" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
|
||||
<h2 class="text-lg text-wp-text-100">{{ $t('all_repositories') }}</h2>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<RepoItem v-for="repo in reposLastActivity" :key="repo.id" :repo="repo" />
|
||||
<RepoItem v-for="repo in reposLastActivity" :key="repo.id" :repo="repo" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-else class="flex flex-col">
|
||||
|
||||
<div v-if="reposLastActivity.length > 0" class="flex flex-col gap-4">
|
||||
<RepoItem v-for="repo in reposLastActivity" :key="repo.id" :repo="repo" />
|
||||
<RepoItem v-for="repo in reposLastActivity" :key="repo.id" :repo="repo" />
|
||||
</div>
|
||||
<span v-else class="text-center text-lg text-wp-text-100">{{ $t('no_search_results') }}</span>
|
||||
<span v-else class="text-center text-lg text-wp-text-100">{{ $t('no_search_results') }}</span
|
||||
>
|
||||
</div>
|
||||
</Transition>
|
||||
</Scaffold>
|
||||
</Transition
|
||||
> </Scaffold
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,3 +1 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
<template> <router-view /> </template>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<AgentManager
|
||||
<AgentManager
|
||||
:description="$t('admin.settings.agents.desc')"
|
||||
:load-agents="loadAgents"
|
||||
:create-agent="createAgent"
|
||||
|
@ -1,32 +1,29 @@
|
||||
<template>
|
||||
<Settings :title="$t('info')">
|
||||
<Settings :title="$t('info')"
|
||||
>
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<!-- <component :is="isLightTheme ? CrowLogoDark : CrowLogo" class="w-32 h-32 fill-wp-text-200" /> -->
|
||||
<!-- FIXME: theme-switch is working but the dark svg is somewhat not rendered correctly -->
|
||||
<component :is="CrowLogo" v-if="!isLightTheme" class="h-32 w-32 fill-wp-text-200" />
|
||||
|
||||
<i18n-t keypath="running_version" tag="p" class="text-center text-xl">
|
||||
<span class="font-bold">{{ version?.current }}</span>
|
||||
</i18n-t>
|
||||
|
||||
<Error v-if="version?.needsUpdate">
|
||||
<i18n-t keypath="update_crow" tag="span">
|
||||
<a
|
||||
<!-- <component :is="isLightTheme ? CrowLogoDark : CrowLogo" class="w-32 h-32 fill-wp-text-200" /> --> <!-- FIXME: theme-switch is working but the dark svg is somewhat not rendered correctly -->
|
||||
<component :is="CrowLogo" v-if="!isLightTheme" class="h-32 w-32 fill-wp-text-200" /> <i18n-t
|
||||
keypath="running_version"
|
||||
tag="p"
|
||||
class="text-center text-xl"
|
||||
> <span class="font-bold">{{ version?.current }}</span
|
||||
> </i18n-t
|
||||
> <Error v-if="version?.needsUpdate"
|
||||
> <i18n-t keypath="update_crow" tag="span"
|
||||
> <a
|
||||
v-if="!version.usesNext"
|
||||
:href="`https://codeberg.org/crowci/crow/releases/tag/${version.latest}`"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="underline"
|
||||
>
|
||||
{{ version.latest }}
|
||||
</a>
|
||||
<span v-else>
|
||||
{{ version.latest }}
|
||||
</span>
|
||||
</i18n-t>
|
||||
</Error>
|
||||
> {{ version.latest }} </a
|
||||
> <span v-else> {{ version.latest }} </span> </i18n-t
|
||||
> </Error
|
||||
>
|
||||
</div>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,36 +1,35 @@
|
||||
<template>
|
||||
<Settings :title="$t('admin.settings.orgs.orgs')" :description="$t('admin.settings.orgs.desc')">
|
||||
<Settings :title="$t('admin.settings.orgs.orgs')" :description="$t('admin.settings.orgs.desc')"
|
||||
>
|
||||
<div class="space-y-4 text-wp-text-100">
|
||||
<ListItem
|
||||
<ListItem
|
||||
v-for="org in orgs"
|
||||
:key="org.id"
|
||||
class="items-center gap-2 !bg-wp-background-200 dark:!bg-wp-background-100"
|
||||
>
|
||||
<span>{{ org.name }}</span>
|
||||
<IconButton
|
||||
> <span>{{ org.name }}</span
|
||||
> <IconButton
|
||||
icon="chevron-right"
|
||||
:title="$t('admin.settings.orgs.view')"
|
||||
class="ml-auto h-8 w-8"
|
||||
:to="{ name: 'org', params: { orgId: org.id } }"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="settings-outline"
|
||||
:title="$t('admin.settings.orgs.org_settings')"
|
||||
class="h-8 w-8"
|
||||
:to="{ name: 'org-settings', params: { orgId: org.id } }"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="trash"
|
||||
:title="$t('admin.settings.orgs.delete_org')"
|
||||
class="ml-2 h-8 w-8 hover:text-wp-error-100"
|
||||
:is-loading="isDeleting"
|
||||
@click="deleteOrg(org)"
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
/> </ListItem
|
||||
>
|
||||
<div v-if="orgs?.length === 0" class="ml-2">{{ $t('admin.settings.orgs.none') }}</div>
|
||||
|
||||
</div>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<Settings :title="$t('admin.settings.queue.queue')" :description="$t('admin.settings.queue.desc')">
|
||||
<template #headerActions>
|
||||
<Settings :title="$t('admin.settings.queue.queue')" :description="$t('admin.settings.queue.desc')"
|
||||
> <template #headerActions
|
||||
>
|
||||
<div v-if="queueInfo">
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<Button
|
||||
<Button
|
||||
v-if="queueInfo.paused"
|
||||
:text="$t('admin.settings.queue.resume')"
|
||||
start-icon="play"
|
||||
@click="resumeQueue"
|
||||
/>
|
||||
<Button v-else :text="$t('admin.settings.queue.pause')" start-icon="pause" @click="pauseQueue" />
|
||||
<Icon
|
||||
/> <Button v-else :text="$t('admin.settings.queue.pause')" start-icon="pause" @click="pauseQueue" /> <Icon
|
||||
:name="queueInfo.paused ? 'pause' : 'play'"
|
||||
class="h-6 w-6"
|
||||
:class="{
|
||||
@ -19,19 +19,20 @@
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</template
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<AdminQueueStats :stats="queueInfo?.stats" />
|
||||
|
||||
<AdminQueueStats :stats="queueInfo?.stats" />
|
||||
<div v-if="tasks.length > 0" class="flex flex-col">
|
||||
|
||||
<p class="mb-2 mt-6 text-xl">{{ $t('admin.settings.queue.tasks') }}</p>
|
||||
<ListItem
|
||||
<ListItem
|
||||
v-for="task in tasks"
|
||||
:key="task.id"
|
||||
class="mb-2 items-center !bg-wp-background-200 shadow-md dark:!bg-wp-background-100"
|
||||
>
|
||||
>
|
||||
<div
|
||||
class="flex items-center"
|
||||
:title="
|
||||
@ -42,7 +43,7 @@
|
||||
: $t('admin.settings.queue.task_waiting_on_deps')
|
||||
"
|
||||
>
|
||||
<Icon
|
||||
<Icon
|
||||
:name="
|
||||
task.status === 'pending'
|
||||
? 'status-pending'
|
||||
@ -57,22 +58,23 @@
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
<span class="ml-2">{{ task.id }}</span>
|
||||
<span class="ml-auto flex gap-2">
|
||||
<Badge v-if="task.agent_id !== 0" :label="$t('admin.settings.queue.agent')" :value="task.agent_id" />
|
||||
<template v-for="(value, label) in task.labels">
|
||||
<Badge v-if="value" :key="label" :label="label.toString()" :value="value" />
|
||||
</template>
|
||||
<Badge
|
||||
<span class="ml-2">{{ task.id }}</span
|
||||
> <span class="ml-auto flex gap-2"
|
||||
> <Badge v-if="task.agent_id !== 0" :label="$t('admin.settings.queue.agent')" :value="task.agent_id" />
|
||||
<template v-for="(value, label) in task.labels"
|
||||
> <Badge v-if="value" :key="label" :label="label.toString()" :value="value" /> </template
|
||||
> <Badge
|
||||
v-if="task.dependencies"
|
||||
:label="$t('admin.settings.queue.waiting_for')"
|
||||
:value="task.dependencies.join(', ')"
|
||||
/>
|
||||
</span>
|
||||
</ListItem>
|
||||
/> </span
|
||||
> </ListItem
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,39 +1,30 @@
|
||||
<template>
|
||||
<Settings
|
||||
<Settings
|
||||
:title="$t('registries.registries')"
|
||||
:description="$t('admin.settings.registries.desc')"
|
||||
docs-url="docs/usage/registries"
|
||||
>
|
||||
<template #headerActions>
|
||||
<Button
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedRegistry"
|
||||
:text="$t('registries.show')"
|
||||
start-icon="back"
|
||||
@click="selectedRegistry = undefined"
|
||||
/>
|
||||
<Button v-else :text="$t('registries.add')" start-icon="plus" @click="showAddRegistry" />
|
||||
</template>
|
||||
|
||||
<template #headerEnd>
|
||||
<Warning class="mt-4 text-sm" :text="$t('admin.settings.registries.warning')" />
|
||||
</template>
|
||||
|
||||
/> <Button v-else :text="$t('registries.add')" start-icon="plus" @click="showAddRegistry" /> </template
|
||||
> <template #headerEnd> <Warning class="mt-4 text-sm" :text="$t('admin.settings.registries.warning')" /> </template>
|
||||
<RegistryList
|
||||
v-if="!selectedRegistry"
|
||||
v-model="registries"
|
||||
:is-deleting="isDeleting"
|
||||
@edit="editRegistry"
|
||||
@delete="deleteRegistry"
|
||||
/>
|
||||
|
||||
<RegistryEdit
|
||||
/> <RegistryEdit
|
||||
v-else
|
||||
v-model="selectedRegistry"
|
||||
:is-saving="isSaving"
|
||||
@save="createRegistry"
|
||||
@cancel="selectedRegistry = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,45 +1,44 @@
|
||||
<template>
|
||||
<Settings :title="$t('admin.settings.repos.repos')" :description="$t('admin.settings.repos.desc')">
|
||||
<template #headerActions>
|
||||
<Button
|
||||
<Settings :title="$t('admin.settings.repos.repos')" :description="$t('admin.settings.repos.desc')"
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
start-icon="heal"
|
||||
:is-loading="isRepairingRepos"
|
||||
:text="$t('admin.settings.repos.repair.repair')"
|
||||
@click="repairRepos"
|
||||
/>
|
||||
</template>
|
||||
|
||||
/> </template
|
||||
>
|
||||
<div class="space-y-4 text-wp-text-100">
|
||||
<ListItem
|
||||
<ListItem
|
||||
v-for="repo in repos"
|
||||
:key="repo.id"
|
||||
class="items-center gap-2 bg-wp-background-200 dark:!bg-wp-background-100"
|
||||
>
|
||||
<span>{{ repo.full_name }}</span>
|
||||
> <span>{{ repo.full_name }}</span
|
||||
>
|
||||
<div class="ml-auto flex items-center">
|
||||
<Badge
|
||||
<Badge
|
||||
v-if="!repo.active"
|
||||
class="md:display-unset mr-2 hidden"
|
||||
:label="$t('admin.settings.repos.disabled')"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="chevron-right"
|
||||
:title="$t('admin.settings.repos.view')"
|
||||
class="h-8 w-8"
|
||||
:to="{ name: 'repo', params: { repoId: repo.id } }"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="settings-outline"
|
||||
:title="$t('admin.settings.repos.settings')"
|
||||
class="h-8 w-8"
|
||||
:to="{ name: 'repo-settings', params: { repoId: repo.id } }"
|
||||
/>
|
||||
</div>
|
||||
</ListItem>
|
||||
|
||||
</ListItem
|
||||
>
|
||||
<div v-if="repos?.length === 0" class="ml-2">{{ $t('admin.settings.repos.none') }}</div>
|
||||
|
||||
</div>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,34 +1,30 @@
|
||||
<template>
|
||||
<Settings
|
||||
<Settings
|
||||
:title="$t('secrets.secrets')"
|
||||
:description="$t('admin.settings.secrets.desc')"
|
||||
docs-url="docs/usage/secrets"
|
||||
>
|
||||
<template #headerActions>
|
||||
<Button v-if="selectedSecret" :text="$t('secrets.show')" start-icon="back" @click="selectedSecret = undefined" />
|
||||
<Button v-else :text="$t('secrets.add')" start-icon="plus" @click="showAddSecret" />
|
||||
</template>
|
||||
|
||||
<template #headerEnd>
|
||||
<Warning class="mt-4 text-sm" :text="$t('admin.settings.secrets.warning')" />
|
||||
</template>
|
||||
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedSecret"
|
||||
:text="$t('secrets.show')"
|
||||
start-icon="back"
|
||||
@click="selectedSecret = undefined"
|
||||
/> <Button v-else :text="$t('secrets.add')" start-icon="plus" @click="showAddSecret" /> </template
|
||||
> <template #headerEnd> <Warning class="mt-4 text-sm" :text="$t('admin.settings.secrets.warning')" /> </template>
|
||||
<SecretList
|
||||
v-if="!selectedSecret"
|
||||
v-model="secrets"
|
||||
:is-deleting="isDeleting"
|
||||
@edit="editSecret"
|
||||
@delete="deleteSecret"
|
||||
/>
|
||||
|
||||
<SecretEdit
|
||||
/> <SecretEdit
|
||||
v-else
|
||||
v-model="selectedSecret"
|
||||
:is-saving="isSaving"
|
||||
@save="createSecret"
|
||||
@cancel="selectedSecret = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,19 +1,18 @@
|
||||
<template>
|
||||
<Scaffold enable-tabs>
|
||||
<template #title>
|
||||
{{ $t('settings') }}
|
||||
</template>
|
||||
<Tab :to="{ name: 'admin-settings' }" :title="$t('info')" />
|
||||
<Tab :to="{ name: 'admin-settings-secrets' }" :title="$t('secrets.secrets')" />
|
||||
<Tab :to="{ name: 'admin-settings-registries' }" :title="$t('registries.registries')" />
|
||||
<Tab :to="{ name: 'admin-settings-repos' }" :title="$t('admin.settings.repos.repos')" />
|
||||
<Tab :to="{ name: 'admin-settings-users' }" :title="$t('admin.settings.users.users')" />
|
||||
<Tab :to="{ name: 'admin-settings-orgs' }" :title="$t('admin.settings.orgs.orgs')" />
|
||||
<Tab :to="{ name: 'admin-settings-agents' }" :title="$t('admin.settings.agents.agents')" />
|
||||
<Tab :to="{ name: 'admin-settings-queue' }" :title="$t('admin.settings.queue.queue')" />
|
||||
|
||||
<router-view />
|
||||
</Scaffold>
|
||||
<Scaffold enable-tabs
|
||||
> <template #title> {{ $t('settings') }} </template> <Tab :to="{ name: 'admin-settings' }" :title="$t('info')" />
|
||||
<Tab :to="{ name: 'admin-settings-secrets' }" :title="$t('secrets.secrets')" /> <Tab
|
||||
:to="{ name: 'admin-settings-registries' }"
|
||||
:title="$t('registries.registries')"
|
||||
/> <Tab :to="{ name: 'admin-settings-repos' }" :title="$t('admin.settings.repos.repos')" /> <Tab
|
||||
:to="{ name: 'admin-settings-users' }"
|
||||
:title="$t('admin.settings.users.users')"
|
||||
/> <Tab :to="{ name: 'admin-settings-orgs' }" :title="$t('admin.settings.orgs.orgs')" /> <Tab
|
||||
:to="{ name: 'admin-settings-agents' }"
|
||||
:title="$t('admin.settings.agents.agents')"
|
||||
/> <Tab :to="{ name: 'admin-settings-queue' }" :title="$t('admin.settings.queue.queue')" /> <router-view />
|
||||
</Scaffold
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,84 +1,78 @@
|
||||
<template>
|
||||
<Settings :title="$t('admin.settings.users.users')" :description="$t('admin.settings.users.desc')">
|
||||
<template #headerActions>
|
||||
<Button
|
||||
<Settings :title="$t('admin.settings.users.users')" :description="$t('admin.settings.users.desc')"
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedUser"
|
||||
:text="$t('admin.settings.users.show')"
|
||||
start-icon="back"
|
||||
@click="selectedUser = undefined"
|
||||
/>
|
||||
<Button v-else :text="$t('admin.settings.users.add')" start-icon="plus" @click="showAddUser" />
|
||||
</template>
|
||||
|
||||
/> <Button v-else :text="$t('admin.settings.users.add')" start-icon="plus" @click="showAddUser" /> </template
|
||||
>
|
||||
<div v-if="!selectedUser" class="space-y-4 text-wp-text-100">
|
||||
<ListItem
|
||||
<ListItem
|
||||
v-for="user in users"
|
||||
:key="user.id"
|
||||
class="items-center gap-2 !bg-wp-background-200 dark:!bg-wp-background-100"
|
||||
>
|
||||
<img v-if="user.avatar_url" class="h-6 rounded-md" :src="user.avatar_url" />
|
||||
<span>{{ user.login }}</span>
|
||||
<Badge
|
||||
> <img v-if="user.avatar_url" class="h-6 rounded-md" :src="user.avatar_url" /> <span>{{ user.login }}</span
|
||||
> <Badge
|
||||
v-if="user.admin"
|
||||
class="md:display-unset ml-auto hidden"
|
||||
:label="$t('admin.settings.users.admin.admin')"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="edit"
|
||||
:title="$t('admin.settings.users.edit_user')"
|
||||
class="md:display-unset h-8 w-8"
|
||||
:class="{ 'ml-auto': !user.admin, 'ml-2': user.admin }"
|
||||
@click="editUser(user)"
|
||||
/>
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="trash"
|
||||
:title="$t('admin.settings.users.delete_user')"
|
||||
class="ml-2 h-8 w-8 hover:text-wp-error-100"
|
||||
:is-loading="isDeleting"
|
||||
@click="deleteUser(user)"
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
/> </ListItem
|
||||
>
|
||||
<div v-if="users?.length === 0" class="ml-2">{{ $t('admin.settings.users.none') }}</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
|
||||
<form @submit.prevent="saveUser">
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.users.login')">
|
||||
<TextField :id="id" v-model="selectedUser.login" :disabled="isEditingUser" />
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.users.email')">
|
||||
<TextField :id="id" v-model="selectedUser.email" />
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.users.avatar_url')">
|
||||
<InputField v-slot="{ id }" :label="$t('admin.settings.users.login')"
|
||||
> <TextField :id="id" v-model="selectedUser.login" :disabled="isEditingUser" /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('admin.settings.users.email')"
|
||||
> <TextField :id="id" v-model="selectedUser.email" /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('admin.settings.users.avatar_url')"
|
||||
>
|
||||
<div class="flex gap-2">
|
||||
<img v-if="selectedUser.avatar_url" class="h-8 w-8 rounded-md" :src="selectedUser.avatar_url" />
|
||||
<TextField :id="id" v-model="selectedUser.avatar_url" />
|
||||
<img v-if="selectedUser.avatar_url" class="h-8 w-8 rounded-md" :src="selectedUser.avatar_url" /> <TextField
|
||||
:id="id"
|
||||
v-model="selectedUser.avatar_url"
|
||||
/>
|
||||
</div>
|
||||
</InputField>
|
||||
|
||||
<InputField :label="$t('admin.settings.users.admin.admin')">
|
||||
<Checkbox
|
||||
</InputField
|
||||
> <InputField :label="$t('admin.settings.users.admin.admin')"
|
||||
> <Checkbox
|
||||
:model-value="selectedUser.admin || false"
|
||||
:label="$t('admin.settings.users.admin.placeholder')"
|
||||
@update:model-value="selectedUser!.admin = $event"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
/> </InputField
|
||||
>
|
||||
<div class="flex gap-2">
|
||||
<Button :text="$t('admin.settings.users.cancel')" @click="selectedUser = undefined" />
|
||||
|
||||
<Button
|
||||
<Button :text="$t('admin.settings.users.cancel')" @click="selectedUser = undefined" /> <Button
|
||||
:is-loading="isSaving"
|
||||
type="submit"
|
||||
color="default"
|
||||
:text="isEditingUser ? $t('admin.settings.users.save') : $t('admin.settings.users.add')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,30 +1,45 @@
|
||||
<template>
|
||||
|
||||
<div class="m-auto flex flex-col gap-4">
|
||||
|
||||
<div class="text-center text-wp-text-100">
|
||||
<CrowLogo preserveAspectRatio="xMinYMin slice" class="m-auto mb-8 w-32" />
|
||||
<template v-if="state === 'confirm'">
|
||||
<CrowLogo preserveAspectRatio="xMinYMin slice" class="m-auto mb-8 w-32" /> <template v-if="state === 'confirm'"
|
||||
>
|
||||
<h1 class="text-4xl font-bold">{{ $t('login_to_cli') }}</h1>
|
||||
|
||||
<p class="text-2xl">{{ $t('login_to_cli_description') }}</p>
|
||||
</template>
|
||||
<template v-else-if="state === 'success'">
|
||||
</template
|
||||
> <template v-else-if="state === 'success'"
|
||||
>
|
||||
<h1 class="text-4xl font-bold">{{ $t('cli_login_success') }}</h1>
|
||||
|
||||
<p class="text-2xl">{{ $t('return_to_cli') }}</p>
|
||||
</template>
|
||||
<template v-else-if="state === 'failed'">
|
||||
</template
|
||||
> <template v-else-if="state === 'failed'"
|
||||
>
|
||||
<h1 class="mt-4 text-4xl font-bold">{{ $t('cli_login_failed') }}</h1>
|
||||
|
||||
<p class="text-2xl">{{ $t('return_to_cli') }}</p>
|
||||
</template>
|
||||
<template v-else-if="state === 'denied'">
|
||||
</template
|
||||
> <template v-else-if="state === 'denied'"
|
||||
>
|
||||
<h1 class="mt-4 text-4xl font-bold">{{ $t('cli_login_denied') }}</h1>
|
||||
|
||||
<p class="text-2xl">{{ $t('return_to_cli') }}</p>
|
||||
</template>
|
||||
</template
|
||||
>
|
||||
</div>
|
||||
|
||||
<div v-if="state === 'confirm'" class="flex justify-center gap-4">
|
||||
<Button :text="$t('login_to_cli')" color="default" @click="sendToken(false)" />
|
||||
<Button :text="$t('abort')" color="red" @click="abortLogin" />
|
||||
<Button :text="$t('login_to_cli')" color="default" @click="sendToken(false)" /> <Button
|
||||
:text="$t('abort')"
|
||||
color="red"
|
||||
@click="abortLogin"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
|
||||
<div />
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,25 +1,21 @@
|
||||
<template>
|
||||
<Scaffold v-if="org && orgPermissions" v-model:search="search">
|
||||
<template #title>
|
||||
{{ org.name }}
|
||||
</template>
|
||||
|
||||
<template #headerActions>
|
||||
<IconButton
|
||||
<Scaffold v-if="org && orgPermissions" v-model:search="search"
|
||||
> <template #title> {{ org.name }} </template> <template #headerActions
|
||||
> <IconButton
|
||||
v-if="orgPermissions.admin"
|
||||
icon="settings"
|
||||
:to="{ name: org.is_user ? 'user' : 'org-settings-secrets' }"
|
||||
:title="$t('settings')"
|
||||
/>
|
||||
</template>
|
||||
/> </template
|
||||
>
|
||||
<div class="flex flex-col gap-4"> <RepoItem v-for="repo in reposLastActivity" :key="repo.id" :repo="repo" /> </div>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<RepoItem v-for="repo in reposLastActivity" :key="repo.id" :repo="repo" />
|
||||
</div>
|
||||
<div v-if="(reposLastActivity || []).length <= 0" class="text-center">
|
||||
<span class="m-auto text-wp-text-100">{{ $t('repo.user_none') }}</span>
|
||||
<span class="m-auto text-wp-text-100">{{ $t('repo.user_none') }}</span
|
||||
>
|
||||
</div>
|
||||
</Scaffold>
|
||||
</Scaffold
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,21 +1,14 @@
|
||||
<template>
|
||||
<Scaffold v-if="org && orgPermissions && route.meta.orgHeader">
|
||||
<template #title>
|
||||
{{ org.name }}
|
||||
</template>
|
||||
|
||||
<template #headerActions>
|
||||
<IconButton
|
||||
<Scaffold v-if="org && orgPermissions && route.meta.orgHeader"
|
||||
> <template #title> {{ org.name }} </template> <template #headerActions
|
||||
> <IconButton
|
||||
v-if="orgPermissions.admin"
|
||||
:to="{ name: org.is_user ? 'user' : 'org-settings-secrets' }"
|
||||
:title="$t('settings')"
|
||||
icon="settings"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<router-view />
|
||||
</Scaffold>
|
||||
<router-view v-else-if="org && orgPermissions" />
|
||||
/> </template
|
||||
> <router-view /> </Scaffold
|
||||
> <router-view v-else-if="org && orgPermissions" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<AgentManager
|
||||
<AgentManager
|
||||
:description="$t('org.settings.agents.desc')"
|
||||
:load-agents="loadAgents"
|
||||
:create-agent="createAgent"
|
||||
|
@ -1,35 +1,29 @@
|
||||
<template>
|
||||
<Settings
|
||||
<Settings
|
||||
:title="$t('registries.registries')"
|
||||
:description="$t('org.settings.registries.desc')"
|
||||
docs-url="docs/usage/registries"
|
||||
>
|
||||
<template #headerActions>
|
||||
<Button
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedRegistry"
|
||||
:text="$t('registries.show')"
|
||||
start-icon="back"
|
||||
@click="selectedRegistry = undefined"
|
||||
/>
|
||||
<Button v-else :text="$t('registries.add')" start-icon="plus" @click="showAddRegistry" />
|
||||
</template>
|
||||
|
||||
<RegistryList
|
||||
/> <Button v-else :text="$t('registries.add')" start-icon="plus" @click="showAddRegistry" /> </template
|
||||
> <RegistryList
|
||||
v-if="!selectedRegistry"
|
||||
v-model="registries"
|
||||
:is-deleting="isDeleting"
|
||||
@edit="editRegistry"
|
||||
@delete="deleteRegistry"
|
||||
/>
|
||||
|
||||
<RegistryEdit
|
||||
/> <RegistryEdit
|
||||
v-else
|
||||
v-model="selectedRegistry"
|
||||
:is-saving="isSaving"
|
||||
@save="createRegistry"
|
||||
@cancel="selectedRegistry = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<Settings :title="$t('secrets.secrets')" :description="$t('org.settings.secrets.desc')" docs-url="docs/usage/secrets">
|
||||
<template #headerActions>
|
||||
<Button v-if="selectedSecret" :text="$t('secrets.show')" start-icon="back" @click="selectedSecret = undefined" />
|
||||
<Button v-else :text="$t('secrets.add')" start-icon="plus" @click="showAddSecret" />
|
||||
</template>
|
||||
|
||||
<SecretList
|
||||
<Settings :title="$t('secrets.secrets')" :description="$t('org.settings.secrets.desc')" docs-url="docs/usage/secrets"
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedSecret"
|
||||
:text="$t('secrets.show')"
|
||||
start-icon="back"
|
||||
@click="selectedSecret = undefined"
|
||||
/> <Button v-else :text="$t('secrets.add')" start-icon="plus" @click="showAddSecret" /> </template
|
||||
> <SecretList
|
||||
v-if="!selectedSecret"
|
||||
v-model="secrets"
|
||||
:is-deleting="isDeleting"
|
||||
@edit="editSecret"
|
||||
@delete="deleteSecret"
|
||||
/>
|
||||
|
||||
<SecretEdit
|
||||
/> <SecretEdit
|
||||
v-else
|
||||
v-model="selectedSecret"
|
||||
:is-saving="isSaving"
|
||||
@save="createSecret"
|
||||
@cancel="selectedSecret = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,26 +1,22 @@
|
||||
<template>
|
||||
<Scaffold v-if="org" enable-tabs :go-back="goBack">
|
||||
<template #title>
|
||||
<span>
|
||||
<router-link :to="{ name: 'org' }" class="hover:underline hover:decoration-wp-custom-highlight-100">{{
|
||||
<Scaffold v-if="org" enable-tabs :go-back="goBack"
|
||||
> <template #title
|
||||
> <span
|
||||
> <router-link :to="{ name: 'org' }" class="hover:underline hover:decoration-wp-custom-highlight-100">{{
|
||||
org.name
|
||||
/* eslint-disable-next-line @intlify/vue-i18n/no-raw-text */
|
||||
}}</router-link>
|
||||
/
|
||||
{{ $t('settings') }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<Tab :to="{ name: 'org-settings-secrets' }" :title="$t('secrets.secrets')" />
|
||||
<Tab :to="{ name: 'org-settings-registries' }" :title="$t('registries.registries')" />
|
||||
<Tab
|
||||
}}</router-link
|
||||
> / {{ $t('settings') }} </span
|
||||
> </template
|
||||
> <Tab :to="{ name: 'org-settings-secrets' }" :title="$t('secrets.secrets')" /> <Tab
|
||||
:to="{ name: 'org-settings-registries' }"
|
||||
:title="$t('registries.registries')"
|
||||
/> <Tab
|
||||
v-if="useConfig().userRegisteredAgents"
|
||||
:to="{ name: 'org-settings-agents' }"
|
||||
:title="$t('admin.settings.agents.agents')"
|
||||
/>
|
||||
|
||||
<router-view />
|
||||
</Scaffold>
|
||||
/> <router-view /> </Scaffold
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,8 +1,10 @@
|
||||
<template>
|
||||
|
||||
<div class="mb-4 flex w-full justify-center">
|
||||
<span class="text-xl text-wp-text-100">{{ $t('repo.pipeline.pipelines_for', { branch }) }}</span>
|
||||
<span class="text-xl text-wp-text-100">{{ $t('repo.pipeline.pipelines_for', { branch }) }}</span
|
||||
>
|
||||
</div>
|
||||
<PipelineList :pipelines="pipelines" :repo="repo" />
|
||||
<PipelineList :pipelines="pipelines" :repo="repo" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,23 +1,20 @@
|
||||
<template>
|
||||
|
||||
<div class="space-y-4">
|
||||
<template v-if="branches.length > 0">
|
||||
<ListItem
|
||||
<template v-if="branches.length > 0"
|
||||
> <ListItem
|
||||
v-for="branch in branchesWithDefaultBranchFirst"
|
||||
:key="branch"
|
||||
class="text-wp-text-100"
|
||||
:to="{ name: 'repo-branch', params: { branch } }"
|
||||
>
|
||||
{{ branch }}
|
||||
<Badge v-if="branch === repo?.default_branch" :label="$t('default')" class="ml-auto" />
|
||||
</ListItem>
|
||||
</template>
|
||||
<div v-else-if="loading" class="flex justify-center text-wp-text-100">
|
||||
<Icon name="spinner" />
|
||||
</div>
|
||||
<Panel v-else class="flex justify-center">
|
||||
{{ $t('empty_list', { entity: $t('repo.branches') }) }}
|
||||
</Panel>
|
||||
> {{ branch }} <Badge v-if="branch === repo?.default_branch" :label="$t('default')" class="ml-auto" />
|
||||
</ListItem
|
||||
> </template
|
||||
>
|
||||
<div v-else-if="loading" class="flex justify-center text-wp-text-100"> <Icon name="spinner" /> </div>
|
||||
<Panel v-else class="flex justify-center"> {{ $t('empty_list', { entity: $t('repo.branches') }) }} </Panel>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
|
||||
<div />
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,27 +1,26 @@
|
||||
<template>
|
||||
<Panel v-if="!loading">
|
||||
<Panel v-if="!loading"
|
||||
>
|
||||
<form @submit.prevent="triggerManualPipeline">
|
||||
<span class="text-xl text-wp-text-100">{{ $t('repo.manual_pipeline.title') }}</span>
|
||||
<InputField v-slot="{ id }" :label="$t('repo.manual_pipeline.select_branch')">
|
||||
<SelectField :id="id" v-model="payload.branch" :options="branches" required />
|
||||
</InputField>
|
||||
<InputField v-slot="{ id }" :label="$t('repo.manual_pipeline.variables.title')">
|
||||
<span class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.manual_pipeline.variables.desc') }}</span>
|
||||
<KeyValueEditor
|
||||
<span class="text-xl text-wp-text-100">{{ $t('repo.manual_pipeline.title') }}</span
|
||||
> <InputField v-slot="{ id }" :label="$t('repo.manual_pipeline.select_branch')"
|
||||
> <SelectField :id="id" v-model="payload.branch" :options="branches" required /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('repo.manual_pipeline.variables.title')"
|
||||
> <span class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.manual_pipeline.variables.desc') }}</span
|
||||
> <KeyValueEditor
|
||||
:id="id"
|
||||
v-model="payload.variables"
|
||||
:key-placeholder="$t('repo.manual_pipeline.variables.name')"
|
||||
:value-placeholder="$t('repo.manual_pipeline.variables.value')"
|
||||
:delete-title="$t('repo.manual_pipeline.variables.delete')"
|
||||
@update:is-valid="isVariablesValid = $event"
|
||||
/>
|
||||
</InputField>
|
||||
<Button type="submit" :text="$t('repo.manual_pipeline.trigger')" :disabled="!isFormValid" />
|
||||
/> </InputField
|
||||
> <Button type="submit" :text="$t('repo.manual_pipeline.trigger')" :disabled="!isFormValid" />
|
||||
</form>
|
||||
</Panel>
|
||||
<div v-else class="flex justify-center text-wp-text-100">
|
||||
<Icon name="spinner" />
|
||||
</div>
|
||||
</Panel
|
||||
>
|
||||
<div v-else class="flex justify-center text-wp-text-100"> <Icon name="spinner" /> </div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,6 +1,4 @@
|
||||
<template>
|
||||
<PipelineList :pipelines="pipelines" :repo="repo" />
|
||||
</template>
|
||||
<template> <PipelineList :pipelines="pipelines" :repo="repo" /> </template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject } from 'vue';
|
||||
|
@ -1,8 +1,10 @@
|
||||
<template>
|
||||
|
||||
<div class="mb-4 flex w-full justify-center">
|
||||
<span class="text-xl text-wp-text-100">{{ $t('repo.pipeline.pipelines_for_pr', { index: pullRequest }) }}</span>
|
||||
<span class="text-xl text-wp-text-100">{{ $t('repo.pipeline.pipelines_for_pr', { index: pullRequest }) }}</span
|
||||
>
|
||||
</div>
|
||||
<PipelineList :pipelines="pipelines" :repo="repo" />
|
||||
<PipelineList :pipelines="pipelines" :repo="repo" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,28 +1,28 @@
|
||||
<template>
|
||||
|
||||
<div class="space-y-4">
|
||||
<template v-if="pullRequests.length > 0">
|
||||
<ListItem
|
||||
<template v-if="pullRequests.length > 0"
|
||||
> <ListItem
|
||||
v-for="pullRequest in pullRequests"
|
||||
:key="pullRequest.index"
|
||||
class="text-wp-text-100"
|
||||
:to="{ name: 'repo-pull-request', params: { pullRequest: pullRequest.index } }"
|
||||
>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
<span class="md:display-unset hidden text-wp-text-alt-100">#{{ pullRequest.index }}</span>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
<span class="md:display-unset mx-2 hidden text-wp-text-alt-100">-</span>
|
||||
<span class="overflow-hidden overflow-ellipsis whitespace-nowrap text-wp-text-100 underline md:no-underline">{{
|
||||
pullRequest.title
|
||||
}}</span>
|
||||
</ListItem>
|
||||
</template>
|
||||
<div v-else-if="loading" class="flex justify-center text-wp-text-100">
|
||||
<Icon name="spinner" />
|
||||
</div>
|
||||
<Panel v-else class="flex justify-center">
|
||||
{{ $t('empty_list', { entity: $t('repo.pull_requests') }) }}
|
||||
</Panel>
|
||||
> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> <span
|
||||
class="md:display-unset hidden text-wp-text-alt-100"
|
||||
>#{{ pullRequest.index }}</span
|
||||
> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> <span
|
||||
class="md:display-unset mx-2 hidden text-wp-text-alt-100"
|
||||
>-</span
|
||||
> <span
|
||||
class="overflow-hidden overflow-ellipsis whitespace-nowrap text-wp-text-100 underline md:no-underline"
|
||||
>{{ pullRequest.title }}</span
|
||||
> </ListItem
|
||||
> </template
|
||||
>
|
||||
<div v-else-if="loading" class="flex justify-center text-wp-text-100"> <Icon name="spinner" /> </div>
|
||||
<Panel v-else class="flex justify-center"> {{ $t('empty_list', { entity: $t('repo.pull_requests') }) }} </Panel>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,54 +1,45 @@
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<template>
|
||||
<Scaffold v-if="repo && repoPermissions && route.meta.repoHeader" enable-tabs>
|
||||
<template #title>
|
||||
<span class="flex">
|
||||
<router-link
|
||||
<Scaffold v-if="repo && repoPermissions && route.meta.repoHeader" enable-tabs
|
||||
> <template #title
|
||||
> <span class="flex"
|
||||
> <router-link
|
||||
:to="{ name: 'org', params: { orgId: repo.org_id } }"
|
||||
class="hover:underline hover:decoration-wp-custom-highlight-100"
|
||||
>{{ repo.owner }}</router-link
|
||||
>
|
||||
/
|
||||
{{ repo.name }}
|
||||
</span>
|
||||
</template>
|
||||
<template #headerActions>
|
||||
<IconButton :href="repo.forge_url" :title="$t('repo.open_in_forge')" :icon="forgeIcon" class="forge h-8 w-8" />
|
||||
> / {{ repo.name }} </span
|
||||
> </template
|
||||
> <template #headerActions
|
||||
> <IconButton :href="repo.forge_url" :title="$t('repo.open_in_forge')" :icon="forgeIcon" class="forge h-8 w-8" />
|
||||
<IconButton
|
||||
v-if="repoPermissions.admin"
|
||||
:to="{ name: 'repo-settings' }"
|
||||
:title="$t('settings')"
|
||||
icon="settings"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #tabActions>
|
||||
<Button
|
||||
/> </template
|
||||
> <template #tabActions
|
||||
> <Button
|
||||
v-if="repoPermissions.push && route.name !== 'repo-manual'"
|
||||
:text="$t('repo.manual_pipeline.trigger')"
|
||||
start-icon="manual-pipeline"
|
||||
:to="{ name: 'repo-manual' }"
|
||||
/>
|
||||
<Button
|
||||
/> <Button
|
||||
v-else-if="repoPermissions.push"
|
||||
:text="$t('repo.manual_pipeline.show_pipelines')"
|
||||
start-icon="back"
|
||||
:to="{ name: 'repo' }"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<Tab :to="{ name: 'repo' }" :title="$t('repo.activity')" />
|
||||
<Tab :to="{ name: 'repo-branches' }" match-children :title="$t('repo.branches')" />
|
||||
<Tab
|
||||
/> </template
|
||||
> <Tab :to="{ name: 'repo' }" :title="$t('repo.activity')" /> <Tab
|
||||
:to="{ name: 'repo-branches' }"
|
||||
match-children
|
||||
:title="$t('repo.branches')"
|
||||
/> <Tab
|
||||
v-if="repo.pr_enabled && repo.allow_pr"
|
||||
:to="{ name: 'repo-pull-requests' }"
|
||||
match-children
|
||||
:title="$t('repo.pull_requests')"
|
||||
/>
|
||||
|
||||
<router-view />
|
||||
</Scaffold>
|
||||
<router-view v-else-if="repo && repoPermissions" />
|
||||
/> <router-view /> </Scaffold
|
||||
> <router-view v-else-if="repo && repoPermissions" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,64 +1,76 @@
|
||||
<template>
|
||||
<Container full-width class="md:min-h-xs flex flex-grow-0 flex-col md:flex-grow md:px-4">
|
||||
<Container full-width class="md:min-h-xs flex flex-grow-0 flex-col md:flex-grow md:px-4"
|
||||
>
|
||||
<div class="flex min-h-0 w-full flex-grow flex-wrap-reverse md:flex-nowrap md:gap-4">
|
||||
<PipelineStepList
|
||||
<PipelineStepList
|
||||
v-model:selected-step-id="selectedStepId"
|
||||
:class="{ 'hidden md:flex': pipeline!.status === 'blocked' }"
|
||||
:pipeline="pipeline!"
|
||||
/>
|
||||
|
||||
<div class="relative flex flex-grow basis-full items-start justify-center md:basis-auto">
|
||||
|
||||
<div v-if="pipeline!.errors?.some((e) => !e.is_warning)" class="mb-4 w-full md:mb-auto">
|
||||
<Panel>
|
||||
<Panel
|
||||
>
|
||||
<div class="flex flex-col items-center gap-4 text-center">
|
||||
<Icon name="status-error" class="h-16 w-16 text-wp-error-100" size="1.5rem" />
|
||||
<span class="text-xl">{{ $t('repo.pipeline.we_got_some_errors') }}</span>
|
||||
<Button color="red" :text="$t('repo.pipeline.show_errors')" :to="{ name: 'repo-pipeline-errors' }" />
|
||||
<Icon name="status-error" class="h-16 w-16 text-wp-error-100" size="1.5rem" /> <span class="text-xl">{{
|
||||
$t('repo.pipeline.we_got_some_errors')
|
||||
}}</span
|
||||
> <Button color="red" :text="$t('repo.pipeline.show_errors')" :to="{ name: 'repo-pipeline-errors' }" />
|
||||
</div>
|
||||
</Panel>
|
||||
</Panel
|
||||
>
|
||||
</div>
|
||||
|
||||
<div v-else-if="pipeline!.status === 'blocked'" class="mb-4 w-full md:mb-auto">
|
||||
<Panel>
|
||||
<Panel
|
||||
>
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<Icon name="status-blocked" size="1.5rem" class="h-16 w-16" />
|
||||
<span class="text-xl">{{ $t('repo.pipeline.protected.awaits') }}</span>
|
||||
<Icon name="status-blocked" size="1.5rem" class="h-16 w-16" /> <span class="text-xl">{{
|
||||
$t('repo.pipeline.protected.awaits')
|
||||
}}</span
|
||||
>
|
||||
<div v-if="repoPermissions!.push" class="flex flex-wrap items-center justify-center gap-2">
|
||||
<Button
|
||||
<Button
|
||||
color="default"
|
||||
:text="$t('repo.pipeline.protected.approve')"
|
||||
:is-loading="isApprovingPipeline"
|
||||
@click="approvePipeline"
|
||||
/>
|
||||
<Button
|
||||
/> <Button
|
||||
color="red"
|
||||
:text="$t('repo.pipeline.protected.decline')"
|
||||
:is-loading="isDecliningPipeline"
|
||||
@click="declinePipeline"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Panel>
|
||||
</Panel
|
||||
>
|
||||
</div>
|
||||
|
||||
<div v-else-if="pipeline!.status === 'declined'" class="mb-4 w-full md:mb-auto">
|
||||
<Panel>
|
||||
<Panel
|
||||
>
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<Icon name="status-declined" size="1.5rem" class="h-16 w-16 text-wp-error-100" />
|
||||
<Icon name="status-declined" size="1.5rem" class="h-16 w-16 text-wp-error-100" />
|
||||
<p class="text-xl">{{ $t('repo.pipeline.protected.declined') }}</p>
|
||||
</div>
|
||||
</Panel>
|
||||
</div>
|
||||
|
||||
<PipelineLog
|
||||
</div>
|
||||
</Panel
|
||||
>
|
||||
</div>
|
||||
<PipelineLog
|
||||
v-else-if="selectedStepId !== null"
|
||||
v-model:step-id="selectedStepId"
|
||||
:pipeline="pipeline!"
|
||||
class="fixed left-0 top-0 h-full w-full md:absolute"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Container>
|
||||
</Container
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,9 +1,13 @@
|
||||
<template>
|
||||
<Panel>
|
||||
<Panel
|
||||
>
|
||||
<ul class="w-full list-inside list-disc">
|
||||
|
||||
<li v-for="file in pipeline!.changed_files" :key="file">{{ file }}</li>
|
||||
|
||||
</ul>
|
||||
</Panel>
|
||||
</Panel
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,15 +1,17 @@
|
||||
<template>
|
||||
|
||||
<div class="flex flex-col gap-y-6">
|
||||
<Panel
|
||||
<Panel
|
||||
v-for="pipelineConfig in pipelineConfigsDecoded"
|
||||
:key="pipelineConfig.hash"
|
||||
:collapsable="pipelineConfigsDecoded && pipelineConfigsDecoded.length > 1"
|
||||
collapsed-by-default
|
||||
:title="pipelineConfigsDecoded && pipelineConfigsDecoded.length > 1 ? pipelineConfig.name : ''"
|
||||
> <SyntaxHighlight class="overflow-auto whitespace-pre font-mono" language="yaml" :code="pipelineConfig.data" />
|
||||
</Panel
|
||||
>
|
||||
<SyntaxHighlight class="overflow-auto whitespace-pre font-mono" language="yaml" :code="pipelineConfig.data" />
|
||||
</Panel>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,20 +1,33 @@
|
||||
<template>
|
||||
<template v-if="repoPermissions && repoPermissions.push">
|
||||
<Panel>
|
||||
<InputField :label="$t('repo.pipeline.debug.metadata_exec_title')">
|
||||
<template v-if="repoPermissions && repoPermissions.push"
|
||||
> <Panel
|
||||
> <InputField :label="$t('repo.pipeline.debug.metadata_exec_title')"
|
||||
>
|
||||
<p class="mb-2 text-sm text-wp-text-alt-100">{{ $t('repo.pipeline.debug.metadata_exec_desc') }}</p>
|
||||
|
||||
<pre class="code-box">{{ cliExecWithMetadata }}</pre>
|
||||
</InputField>
|
||||
</InputField
|
||||
>
|
||||
<div class="flex items-center space-x-4">
|
||||
<Button :is-loading="isLoading" :text="$t('repo.pipeline.debug.download_metadata')" @click="downloadMetadata" />
|
||||
<Button
|
||||
:is-loading="isLoading"
|
||||
:text="$t('repo.pipeline.debug.download_metadata')"
|
||||
@click="downloadMetadata"
|
||||
/>
|
||||
</div>
|
||||
</Panel>
|
||||
</template>
|
||||
</Panel
|
||||
> </template
|
||||
>
|
||||
<div v-else class="flex h-full items-center justify-center">
|
||||
|
||||
<div class="rounded-lg bg-wp-error-100 p-8 text-center shadow-lg dark:bg-wp-error-200">
|
||||
|
||||
<p class="text-2xl font-bold text-white">{{ $t('repo.pipeline.debug.no_permission') }}</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -1,50 +1,52 @@
|
||||
<template>
|
||||
<Panel>
|
||||
<Panel
|
||||
>
|
||||
<div class="flex flex-col gap-y-4">
|
||||
<template v-for="(error, _index) in pipeline!.errors" :key="_index">
|
||||
<template v-for="(error, _index) in pipeline!.errors" :key="_index"
|
||||
>
|
||||
<div>
|
||||
|
||||
<div class="grid grid-cols-[minmax(10rem,auto),3fr]">
|
||||
<span class="flex items-center gap-x-2">
|
||||
<Icon
|
||||
<span class="flex items-center gap-x-2"
|
||||
> <Icon
|
||||
name="alert"
|
||||
class="my-1 flex-shrink-0"
|
||||
:class="{
|
||||
'text-wp-state-warn-100': error.is_warning,
|
||||
'text-wp-error-100': !error.is_warning,
|
||||
}"
|
||||
/>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
<span>
|
||||
<code>{{ error.type }}</code>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
/> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> <span
|
||||
> <code>{{ error.type }}</code
|
||||
> </span
|
||||
> </span
|
||||
> <span
|
||||
v-if="isLinterError(error) || isDeprecationError(error) || isBadHabitError(error)"
|
||||
class="flex items-center gap-x-2 whitespace-nowrap"
|
||||
>
|
||||
<span>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
<span v-if="error.data?.file" class="font-bold">{{ error.data?.file }}: </span>
|
||||
<span>{{ error.data?.field }}</span>
|
||||
</span>
|
||||
<DocsLink
|
||||
> <span
|
||||
> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> <span
|
||||
v-if="error.data?.file"
|
||||
class="font-bold"
|
||||
>{{ error.data?.file }}: </span
|
||||
> <span>{{ error.data?.field }}</span
|
||||
> </span
|
||||
> <DocsLink
|
||||
v-if="isDeprecationError(error) || isBadHabitError(error)"
|
||||
:topic="error.data?.field || ''"
|
||||
:url="error.data?.docs || ''"
|
||||
/>
|
||||
</span>
|
||||
<span v-else />
|
||||
/> </span
|
||||
> <span v-else />
|
||||
</div>
|
||||
|
||||
<div class="col-start-2 grid grid-cols-[minmax(10rem,auto),4fr]">
|
||||
<span />
|
||||
<span>
|
||||
<RenderMarkdown :content="error.message" />
|
||||
</span>
|
||||
<span /> <span> <RenderMarkdown :content="error.message" /> </span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</template
|
||||
>
|
||||
</div>
|
||||
</Panel>
|
||||
</Panel
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,104 +1,97 @@
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<template>
|
||||
<Scaffold
|
||||
<Scaffold
|
||||
v-if="pipeline && repo"
|
||||
enable-tabs
|
||||
:go-back="goBack"
|
||||
:fluid-content="route.name === 'repo-pipeline'"
|
||||
full-width-header
|
||||
>
|
||||
<template #title>
|
||||
<span>
|
||||
<router-link
|
||||
> <template #title
|
||||
> <span
|
||||
> <router-link
|
||||
:to="{ name: 'org', params: { orgId: repo.org_id } }"
|
||||
class="hover:underline hover:decoration-wp-custom-highlight-100"
|
||||
>{{ repo.owner }}</router-link
|
||||
>
|
||||
/
|
||||
<router-link :to="{ name: 'repo' }" class="hover:underline">{{ repo.name }}</router-link>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #headerActions>
|
||||
> / <router-link :to="{ name: 'repo' }" class="hover:underline">{{ repo.name }}</router-link
|
||||
> </span
|
||||
> </template
|
||||
> <template #headerActions
|
||||
>
|
||||
<div class="flex w-full items-center justify-between gap-2">
|
||||
<div class="flex min-w-0 content-start gap-2">
|
||||
<PipelineStatusIcon :status="pipeline.status" class="flex flex-shrink-0" />
|
||||
<span class="flex-shrink-0 text-center">{{ $t('repo.pipeline.pipeline', { pipelineId }) }}</span>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
<span class="hidden md:inline-block">-</span>
|
||||
<span class="min-w-0 overflow-hidden overflow-ellipsis whitespace-nowrap" :title="message">{{
|
||||
shortMessage
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<template v-if="repoPermissions!.push && pipeline.status !== 'blocked'">
|
||||
<div class="flex min-w-0 content-start gap-2">
|
||||
<PipelineStatusIcon :status="pipeline.status" class="flex flex-shrink-0" /> <span
|
||||
class="flex-shrink-0 text-center"
|
||||
>{{ $t('repo.pipeline.pipeline', { pipelineId }) }}</span
|
||||
> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> <span class="hidden md:inline-block">-</span
|
||||
> <span class="min-w-0 overflow-hidden overflow-ellipsis whitespace-nowrap" :title="message">{{
|
||||
shortMessage
|
||||
}}</span
|
||||
>
|
||||
</div>
|
||||
<template v-if="repoPermissions!.push && pipeline.status !== 'blocked'"
|
||||
>
|
||||
<div class="flex content-start gap-x-2">
|
||||
<Button
|
||||
<Button
|
||||
v-if="pipeline.status === 'pending' || pipeline.status === 'running'"
|
||||
class="flex-shrink-0 !py-0"
|
||||
:text="$t('repo.pipeline.actions.cancel')"
|
||||
:is-loading="isCancelingPipeline"
|
||||
@click="cancelPipeline"
|
||||
/>
|
||||
<Button
|
||||
/> <Button
|
||||
class="flex-shrink-0 !py-0"
|
||||
:text="$t('repo.pipeline.actions.restart')"
|
||||
:is-loading="isRestartingPipeline"
|
||||
@click="restartPipeline"
|
||||
/>
|
||||
<Button
|
||||
/> <Button
|
||||
v-if="pipeline.status === 'success' && repo.allow_deploy"
|
||||
class="flex-shrink-0 !py-0"
|
||||
:text="$t('repo.pipeline.actions.deploy')"
|
||||
@click="showDeployPipelinePopup = true"
|
||||
/>
|
||||
<DeployPipelinePopup
|
||||
/> <DeployPipelinePopup
|
||||
:pipeline-number="pipelineId"
|
||||
:open="showDeployPipelinePopup"
|
||||
@close="showDeployPipelinePopup = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</template
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #tabActions>
|
||||
</template
|
||||
> <template #tabActions
|
||||
>
|
||||
<div class="flex flex-wrap gap-4 md:flex-nowrap">
|
||||
<div class="flex flex-shrink-0 items-center gap-2" :title="$t('repo.pipeline.created', { created })">
|
||||
<Icon name="since" />
|
||||
<span>{{ since }}</span>
|
||||
</div>
|
||||
<div class="flex flex-shrink-0 items-center gap-2" :title="$t('repo.pipeline.duration')">
|
||||
<Icon name="duration" />
|
||||
<span>{{ duration }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Tab :to="{ name: 'repo-pipeline' }" :title="$t('repo.pipeline.tasks')" />
|
||||
<Tab
|
||||
<div class="flex flex-shrink-0 items-center gap-2" :title="$t('repo.pipeline.created', { created })">
|
||||
<Icon name="since" /> <span>{{ since }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-shrink-0 items-center gap-2" :title="$t('repo.pipeline.duration')">
|
||||
<Icon name="duration" /> <span>{{ duration }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template
|
||||
> <Tab :to="{ name: 'repo-pipeline' }" :title="$t('repo.pipeline.tasks')" /> <Tab
|
||||
v-if="pipeline.errors && pipeline.errors.length > 0"
|
||||
:to="{ name: 'repo-pipeline-errors' }"
|
||||
icon="alert"
|
||||
:title="pipeline.errors.some((e) => !e.is_warning) ? $t('repo.pipeline.errors') : $t('repo.pipeline.warnings')"
|
||||
:count="pipeline.errors?.length"
|
||||
:icon-class="pipeline.errors.some((e) => !e.is_warning) ? 'text-wp-error-100' : 'text-wp-state-warn-100'"
|
||||
/>
|
||||
<Tab :to="{ name: 'repo-pipeline-config' }" :title="$t('repo.pipeline.config')" />
|
||||
<Tab
|
||||
/> <Tab :to="{ name: 'repo-pipeline-config' }" :title="$t('repo.pipeline.config')" /> <Tab
|
||||
v-if="pipeline.changed_files && pipeline.changed_files.length > 0"
|
||||
:to="{ name: 'repo-pipeline-changed-files' }"
|
||||
:title="$t('repo.pipeline.files')"
|
||||
:count="pipeline.changed_files?.length"
|
||||
/>
|
||||
<Tab
|
||||
/> <Tab
|
||||
v-if="repoPermissions && repoPermissions.push"
|
||||
:to="{ name: 'repo-pipeline-debug' }"
|
||||
:title="$t('repo.pipeline.debug.title')"
|
||||
/>
|
||||
|
||||
<router-view />
|
||||
</Scaffold>
|
||||
/> <router-view /> </Scaffold
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,16 +1,15 @@
|
||||
<template>
|
||||
<Settings :title="$t('repo.settings.actions.actions')">
|
||||
<Settings :title="$t('repo.settings.actions.actions')"
|
||||
>
|
||||
<div class="flex flex-wrap items-center">
|
||||
<Button
|
||||
<Button
|
||||
class="my-1 mr-4"
|
||||
color="default"
|
||||
start-icon="heal"
|
||||
:is-loading="isRepairingRepo"
|
||||
:text="$t('repo.settings.actions.repair.repair')"
|
||||
@click="repairRepo"
|
||||
/>
|
||||
|
||||
<Button
|
||||
/> <Button
|
||||
v-if="isActive"
|
||||
color="default"
|
||||
class="my-1 mr-4"
|
||||
@ -18,8 +17,7 @@
|
||||
:is-loading="isDeactivatingRepo"
|
||||
:text="$t('repo.settings.actions.disable.disable')"
|
||||
@click="deactivateRepo"
|
||||
/>
|
||||
<Button
|
||||
/> <Button
|
||||
v-else
|
||||
class="my-1 mr-4"
|
||||
color="default"
|
||||
@ -27,9 +25,7 @@
|
||||
:is-loading="isActivatingRepo"
|
||||
:text="$t('repo.settings.actions.enable.enable')"
|
||||
@click="activateRepo"
|
||||
/>
|
||||
|
||||
<Button
|
||||
/> <Button
|
||||
class="my-1 mr-4"
|
||||
color="red"
|
||||
start-icon="trash"
|
||||
@ -38,7 +34,8 @@
|
||||
@click="deleteRepo"
|
||||
/>
|
||||
</div>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,13 +1,9 @@
|
||||
<template>
|
||||
<Settings :title="$t('repo.settings.badge.badge')">
|
||||
<template #titleActions>
|
||||
<a v-if="badgeUrl" :href="badgeUrl" target="_blank">
|
||||
<img :src="badgeUrl" />
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('repo.settings.badge.type')">
|
||||
<SelectField
|
||||
<Settings :title="$t('repo.settings.badge.badge')"
|
||||
> <template #titleActions
|
||||
> <a v-if="badgeUrl" :href="badgeUrl" target="_blank"> <img :src="badgeUrl" /> </a> </template
|
||||
> <InputField v-slot="{ id }" :label="$t('repo.settings.badge.type')"
|
||||
> <SelectField
|
||||
:id="id"
|
||||
v-model="badgeType"
|
||||
:options="[
|
||||
@ -25,18 +21,21 @@
|
||||
},
|
||||
]"
|
||||
required
|
||||
/>
|
||||
</InputField>
|
||||
<InputField v-slot="{ id }" :label="$t('repo.settings.badge.branch')">
|
||||
<SelectField :id="id" v-model="branch" :options="branches" required />
|
||||
</InputField>
|
||||
|
||||
/> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('repo.settings.badge.branch')"
|
||||
> <SelectField :id="id" v-model="branch" :options="branches" required /> </InputField
|
||||
>
|
||||
<div v-if="badgeContent" class="flex flex-col space-y-4">
|
||||
|
||||
<div>
|
||||
|
||||
<pre class="code-box">{{ badgeContent }}</pre>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,107 +1,101 @@
|
||||
<template>
|
||||
<Settings
|
||||
<Settings
|
||||
:title="$t('repo.settings.crons.crons')"
|
||||
:description="$t('repo.settings.crons.desc')"
|
||||
docs-url="docs/usage/cron"
|
||||
>
|
||||
<template #headerActions>
|
||||
<Button
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedCron"
|
||||
start-icon="back"
|
||||
:text="$t('repo.settings.crons.show')"
|
||||
@click="selectedCron = undefined"
|
||||
/>
|
||||
<Button v-else start-icon="plus" :text="$t('repo.settings.crons.add')" @click="selectedCron = {}" />
|
||||
</template>
|
||||
|
||||
/> <Button v-else start-icon="plus" :text="$t('repo.settings.crons.add')" @click="selectedCron = {}" /> </template
|
||||
>
|
||||
<div v-if="!selectedCron" class="space-y-4 text-wp-text-100">
|
||||
<ListItem
|
||||
<ListItem
|
||||
v-for="cron in crons"
|
||||
:key="cron.id"
|
||||
class="items-center !bg-wp-background-200 shadow-md dark:!bg-wp-background-100"
|
||||
>
|
||||
<span class="grid w-full grid-cols-3">
|
||||
<span>{{ cron.name }}</span>
|
||||
<span v-if="cron.next_exec && cron.next_exec > 0" class="md:display-unset col-span-2 hidden">
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
{{ $t('repo.settings.crons.next_exec') }}: {{ date.toLocaleString(new Date(cron.next_exec * 1000)) }}
|
||||
</span>
|
||||
<span v-else class="md:display-unset col-span-2 hidden">{{
|
||||
> <span class="grid w-full grid-cols-3"
|
||||
> <span>{{ cron.name }}</span
|
||||
> <span v-if="cron.next_exec && cron.next_exec > 0" class="md:display-unset col-span-2 hidden"
|
||||
> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> {{ $t('repo.settings.crons.next_exec') }}:
|
||||
{{ date.toLocaleString(new Date(cron.next_exec * 1000)) }} </span
|
||||
> <span v-else class="md:display-unset col-span-2 hidden">{{
|
||||
$t('repo.settings.crons.not_executed_yet')
|
||||
}}</span>
|
||||
</span>
|
||||
<IconButton
|
||||
}}</span
|
||||
> </span
|
||||
> <IconButton
|
||||
icon="play-outline"
|
||||
class="ml-auto h-8 w-8"
|
||||
:title="$t('repo.settings.crons.run')"
|
||||
@click="runCron(cron)"
|
||||
/>
|
||||
<IconButton icon="edit" class="h-8 w-8" :title="$t('repo.settings.crons.edit')" @click="selectedCron = cron" />
|
||||
<IconButton
|
||||
/> <IconButton
|
||||
icon="edit"
|
||||
class="h-8 w-8"
|
||||
:title="$t('repo.settings.crons.edit')"
|
||||
@click="selectedCron = cron"
|
||||
/> <IconButton
|
||||
icon="trash"
|
||||
class="h-8 w-8 hover:text-wp-error-100"
|
||||
:is-loading="isDeleting"
|
||||
:title="$t('repo.settings.crons.delete')"
|
||||
@click="deleteCron(cron)"
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
/> </ListItem
|
||||
>
|
||||
<div v-if="crons?.length === 0" class="ml-2">{{ $t('repo.settings.crons.none') }}</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-else class="space-y-4">
|
||||
|
||||
<form @submit.prevent="createCron">
|
||||
<InputField v-slot="{ id }" :label="$t('repo.settings.crons.name.name')">
|
||||
<TextField
|
||||
<InputField v-slot="{ id }" :label="$t('repo.settings.crons.name.name')"
|
||||
> <TextField
|
||||
:id="id"
|
||||
v-model="selectedCron.name"
|
||||
:placeholder="$t('repo.settings.crons.name.placeholder')"
|
||||
required
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField v-slot="{ id }" :label="$t('repo.settings.crons.branch.title')">
|
||||
<TextField
|
||||
/> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('repo.settings.crons.branch.title')"
|
||||
> <TextField
|
||||
:id="id"
|
||||
v-model="selectedCron.branch"
|
||||
:placeholder="$t('repo.settings.crons.branch.placeholder')"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
/> </InputField
|
||||
> <InputField
|
||||
v-slot="{ id }"
|
||||
:label="$t('repo.settings.crons.schedule.title')"
|
||||
docs-url="https://pkg.go.dev/github.com/gdgvda/cron#hdr-CRON_Expression_Format"
|
||||
>
|
||||
<TextField
|
||||
> <TextField
|
||||
:id="id"
|
||||
v-model="selectedCron.schedule"
|
||||
:placeholder="$t('repo.settings.crons.schedule.placeholder')"
|
||||
required
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
/> </InputField
|
||||
>
|
||||
<div v-if="isEditingCron" class="mb-4 ml-auto">
|
||||
<span v-if="selectedCron.next_exec && selectedCron.next_exec > 0" class="text-wp-text-100">
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
|
||||
{{ $t('repo.settings.crons.next_exec') }}:
|
||||
{{ date.toLocaleString(new Date(selectedCron.next_exec * 1000)) }}
|
||||
</span>
|
||||
<span v-else class="text-wp-text-100">{{ $t('repo.settings.crons.not_executed_yet') }}</span>
|
||||
<span v-if="selectedCron.next_exec && selectedCron.next_exec > 0" class="text-wp-text-100"
|
||||
> <!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text --> {{ $t('repo.settings.crons.next_exec') }}:
|
||||
{{ date.toLocaleString(new Date(selectedCron.next_exec * 1000)) }} </span
|
||||
> <span v-else class="text-wp-text-100">{{ $t('repo.settings.crons.not_executed_yet') }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<Button type="button" color="gray" :text="$t('cancel')" @click="selectedCron = undefined" />
|
||||
<Button
|
||||
<Button type="button" color="gray" :text="$t('cancel')" @click="selectedCron = undefined" /> <Button
|
||||
type="submit"
|
||||
color="default"
|
||||
:is-loading="isSaving"
|
||||
:text="isEditingCron ? $t('repo.settings.crons.save') : $t('repo.settings.crons.add')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,64 +1,64 @@
|
||||
<template>
|
||||
<Settings :title="$t('repo.settings.general.project')">
|
||||
<Settings :title="$t('repo.settings.general.project')"
|
||||
>
|
||||
<form v-if="repoSettings" class="flex flex-col" @submit.prevent="saveRepoSettings">
|
||||
<InputField docs-url="usage/project-settings#general" :label="$t('repo.settings.general.general')">
|
||||
<Checkbox
|
||||
<InputField docs-url="usage/project-settings#general" :label="$t('repo.settings.general.general')"
|
||||
> <Checkbox
|
||||
v-model="repoSettings.allow_pr"
|
||||
:label="$t('repo.settings.general.allow_pr.allow')"
|
||||
:description="$t('repo.settings.general.allow_pr.desc')"
|
||||
/>
|
||||
<Checkbox
|
||||
/> <Checkbox
|
||||
v-model="repoSettings.allow_deploy"
|
||||
:label="$t('repo.settings.general.allow_deploy.allow')"
|
||||
:description="$t('repo.settings.general.allow_deploy.desc')"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
/> </InputField
|
||||
> <InputField
|
||||
:label="$t('repo.settings.general.netrc_only_trusted.netrc_only_trusted')"
|
||||
docs-url="usage/project-settings#custom-trusted-clone-plugins"
|
||||
>
|
||||
<template #default="{ id }">
|
||||
> <template #default="{ id }"
|
||||
>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div v-for="image in repoSettings.netrc_trusted" :key="image" class="flex gap-2">
|
||||
<TextField :id="id" :model-value="image" disabled />
|
||||
<Button type="button" color="gray" start-icon="trash" @click="removeImage(image)" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<TextField :id="id" v-model="newImage" @keydown.enter.prevent="addNewImage" />
|
||||
<Button type="button" color="gray" start-icon="plus" @click="addNewImage" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
{{ $t('repo.settings.general.netrc_only_trusted.desc') }}
|
||||
</template>
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
<div v-for="image in repoSettings.netrc_trusted" :key="image" class="flex gap-2">
|
||||
<TextField :id="id" :model-value="image" disabled /> <Button
|
||||
type="button"
|
||||
color="gray"
|
||||
start-icon="trash"
|
||||
@click="removeImage(image)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<TextField :id="id" v-model="newImage" @keydown.enter.prevent="addNewImage" /> <Button
|
||||
type="button"
|
||||
color="gray"
|
||||
start-icon="plus"
|
||||
@click="addNewImage"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template
|
||||
> <template #description> {{ $t('repo.settings.general.netrc_only_trusted.desc') }} </template> </InputField
|
||||
> <InputField
|
||||
v-if="user?.admin"
|
||||
docs-url="usage/repo-settings/#privileges-security"
|
||||
:label="$t('repo.settings.general.trusted.trusted')"
|
||||
>
|
||||
<Checkbox
|
||||
> <Checkbox
|
||||
v-model="repoSettings.trusted.network"
|
||||
:label="$t('repo.settings.general.trusted.network.network')"
|
||||
:description="$t('repo.settings.general.trusted.network.desc')"
|
||||
/>
|
||||
<Checkbox
|
||||
/> <Checkbox
|
||||
v-model="repoSettings.trusted.volumes"
|
||||
:label="$t('repo.settings.general.trusted.volumes.volumes')"
|
||||
:description="$t('repo.settings.general.trusted.volumes.desc')"
|
||||
/>
|
||||
<Checkbox
|
||||
/> <Checkbox
|
||||
v-model="repoSettings.trusted.security"
|
||||
:label="$t('repo.settings.general.trusted.security.security')"
|
||||
:description="$t('repo.settings.general.trusted.security.desc')"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField :label="$t('require_approval.require_approval_for')">
|
||||
<RadioField
|
||||
/> </InputField
|
||||
> <InputField :label="$t('require_approval.require_approval_for')"
|
||||
> <RadioField
|
||||
v-model="repoSettings.require_approval"
|
||||
docs-url="usage/repo-settings/#approval-requirements"
|
||||
:options="[
|
||||
@ -80,63 +80,44 @@
|
||||
text: $t('require_approval.all_events'),
|
||||
},
|
||||
]"
|
||||
/>
|
||||
<template #description>
|
||||
{{ $t('require_approval.desc') }}
|
||||
</template>
|
||||
</InputField>
|
||||
|
||||
<InputField docs-url="usage/project-settings#project-visibility" :label="$t('repo.visibility.visibility')">
|
||||
<RadioField v-model="repoSettings.visibility" :options="projectVisibilityOptions" />
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
/> <template #description> {{ $t('require_approval.desc') }} </template> </InputField
|
||||
> <InputField docs-url="usage/project-settings#project-visibility" :label="$t('repo.visibility.visibility')"
|
||||
> <RadioField v-model="repoSettings.visibility" :options="projectVisibilityOptions" /> </InputField
|
||||
> <InputField
|
||||
v-slot="{ id }"
|
||||
docs-url="usage/project-settings#timeout"
|
||||
:label="$t('repo.settings.general.timeout.timeout')"
|
||||
>
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<NumberField :id="id" v-model="repoSettings.timeout" class="w-24" />
|
||||
<span class="ml-4 text-wp-text-alt-100">{{ $t('repo.settings.general.timeout.minutes') }}</span>
|
||||
<NumberField :id="id" v-model="repoSettings.timeout" class="w-24" /> <span
|
||||
class="ml-4 text-wp-text-alt-100"
|
||||
>{{ $t('repo.settings.general.timeout.minutes') }}</span
|
||||
>
|
||||
</div>
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
</InputField
|
||||
> <InputField
|
||||
docs-url="usage/project-settings#pipeline-path"
|
||||
:label="$t('repo.settings.general.pipeline_path.path')"
|
||||
>
|
||||
<template #default="{ id }">
|
||||
<TextField
|
||||
> <template #default="{ id }"
|
||||
> <TextField
|
||||
:id="id"
|
||||
v-model="repoSettings.config_file"
|
||||
:placeholder="$t('repo.settings.general.pipeline_path.default')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<template #description>
|
||||
<i18n-t keypath="repo.settings.general.pipeline_path.desc">
|
||||
<span class="code-box-inline">{{ $t('repo.settings.general.pipeline_path.desc_path_example') }}</span>
|
||||
<span class="code-box-inline">/</span>
|
||||
</i18n-t>
|
||||
</template>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
/> </template
|
||||
> <!-- eslint-disable @intlify/vue-i18n/no-raw-text --> <template #description
|
||||
> <i18n-t keypath="repo.settings.general.pipeline_path.desc"
|
||||
> <span class="code-box-inline">{{ $t('repo.settings.general.pipeline_path.desc_path_example') }}</span
|
||||
> <span class="code-box-inline">/</span> </i18n-t
|
||||
> </template
|
||||
> <!-- eslint-enable @intlify/vue-i18n/no-raw-text --> </InputField
|
||||
> <InputField
|
||||
docs-url="usage/project-settings#cancel-previous-pipelines"
|
||||
:label="$t('repo.settings.general.cancel_prev.cancel')"
|
||||
>
|
||||
<CheckboxesField
|
||||
> <CheckboxesField
|
||||
v-model="repoSettings.cancel_previous_pipeline_events"
|
||||
:options="cancelPreviousPipelineEventsOptions"
|
||||
/>
|
||||
<template #description>
|
||||
{{ $t('repo.settings.general.cancel_prev.desc') }}
|
||||
</template>
|
||||
</InputField>
|
||||
|
||||
<Button
|
||||
/> <template #description> {{ $t('repo.settings.general.cancel_prev.desc') }} </template> </InputField
|
||||
> <Button
|
||||
type="submit"
|
||||
class="mr-auto"
|
||||
color="default"
|
||||
@ -144,7 +125,8 @@
|
||||
:text="$t('repo.settings.general.save')"
|
||||
/>
|
||||
</form>
|
||||
</Settings>
|
||||
</Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,31 +1,26 @@
|
||||
<template>
|
||||
<Settings :title="$t('registries.credentials')" :description="$t('registries.desc')" docs-url="docs/usage/registries">
|
||||
<template #headerActions>
|
||||
<Button
|
||||
<Settings :title="$t('registries.credentials')" :description="$t('registries.desc')" docs-url="docs/usage/registries"
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedRegistry"
|
||||
:text="$t('registries.show')"
|
||||
start-icon="back"
|
||||
@click="selectedRegistry = undefined"
|
||||
/>
|
||||
<Button v-else :text="$t('registries.add')" start-icon="plus" @click="showAddRegistry" />
|
||||
</template>
|
||||
|
||||
<RegistryList
|
||||
/> <Button v-else :text="$t('registries.add')" start-icon="plus" @click="showAddRegistry" /> </template
|
||||
> <RegistryList
|
||||
v-if="!selectedRegistry"
|
||||
v-model="registries"
|
||||
:is-deleting="isDeleting"
|
||||
@edit="editRegistry"
|
||||
@delete="deleteRegistry"
|
||||
/>
|
||||
|
||||
<RegistryEdit
|
||||
/> <RegistryEdit
|
||||
v-else
|
||||
v-model="selectedRegistry"
|
||||
:is-saving="isSaving"
|
||||
@save="createRegistry"
|
||||
@cancel="selectedRegistry = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,32 +1,29 @@
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<template>
|
||||
<Scaffold enable-tabs :go-back="goBack">
|
||||
<template #title>
|
||||
<span>
|
||||
<router-link
|
||||
<Scaffold enable-tabs :go-back="goBack"
|
||||
> <template #title
|
||||
> <span
|
||||
> <router-link
|
||||
:to="{ name: 'org', params: { orgId: repo!.org_id } }"
|
||||
class="hover:underline hover:decoration-wp-custom-highlight-100"
|
||||
>{{ repo!.owner }}</router-link
|
||||
>
|
||||
/
|
||||
<router-link :to="{ name: 'repo' }" class="hover:underline hover:decoration-wp-custom-highlight-100">{{
|
||||
> / <router-link :to="{ name: 'repo' }" class="hover:underline hover:decoration-wp-custom-highlight-100">{{
|
||||
repo!.name
|
||||
/* eslint-disable-next-line @intlify/vue-i18n/no-raw-text */
|
||||
}}</router-link>
|
||||
/
|
||||
{{ $t('settings') }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<Tab :to="{ name: 'repo-settings' }" :title="$t('repo.settings.general.general')" />
|
||||
<Tab :to="{ name: 'repo-settings-secrets' }" :title="$t('secrets.secrets')" />
|
||||
<Tab :to="{ name: 'repo-settings-registries' }" :title="$t('registries.registries')" />
|
||||
<Tab :to="{ name: 'repo-settings-crons' }" :title="$t('repo.settings.crons.crons')" />
|
||||
<Tab :to="{ name: 'repo-settings-badge' }" :title="$t('repo.settings.badge.badge')" />
|
||||
<Tab :to="{ name: 'repo-settings-actions' }" :title="$t('repo.settings.actions.actions')" />
|
||||
|
||||
<router-view />
|
||||
</Scaffold>
|
||||
}}</router-link
|
||||
> / {{ $t('settings') }} </span
|
||||
> </template
|
||||
> <Tab :to="{ name: 'repo-settings' }" :title="$t('repo.settings.general.general')" /> <Tab
|
||||
:to="{ name: 'repo-settings-secrets' }"
|
||||
:title="$t('secrets.secrets')"
|
||||
/> <Tab :to="{ name: 'repo-settings-registries' }" :title="$t('registries.registries')" /> <Tab
|
||||
:to="{ name: 'repo-settings-crons' }"
|
||||
:title="$t('repo.settings.crons.crons')"
|
||||
/> <Tab :to="{ name: 'repo-settings-badge' }" :title="$t('repo.settings.badge.badge')" /> <Tab
|
||||
:to="{ name: 'repo-settings-actions' }"
|
||||
:title="$t('repo.settings.actions.actions')"
|
||||
/> <router-view /> </Scaffold
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<Settings :title="$t('secrets.secrets')" :description="$t('secrets.desc')" docs-url="docs/usage/secrets">
|
||||
<template #headerActions>
|
||||
<Button v-if="selectedSecret" :text="$t('secrets.show')" start-icon="back" @click="selectedSecret = undefined" />
|
||||
<Button v-else :text="$t('secrets.add')" start-icon="plus" @click="showAddSecret" />
|
||||
</template>
|
||||
|
||||
<SecretList
|
||||
<Settings :title="$t('secrets.secrets')" :description="$t('secrets.desc')" docs-url="docs/usage/secrets"
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedSecret"
|
||||
:text="$t('secrets.show')"
|
||||
start-icon="back"
|
||||
@click="selectedSecret = undefined"
|
||||
/> <Button v-else :text="$t('secrets.add')" start-icon="plus" @click="showAddSecret" /> </template
|
||||
> <SecretList
|
||||
v-if="!selectedSecret"
|
||||
:model-value="secrets"
|
||||
:is-deleting="isDeleting"
|
||||
@edit="editSecret"
|
||||
@delete="deleteSecret"
|
||||
/>
|
||||
|
||||
<SecretEdit
|
||||
/> <SecretEdit
|
||||
v-else
|
||||
v-model="selectedSecret"
|
||||
:is-saving="isSaving"
|
||||
@save="createSecret"
|
||||
@cancel="selectedSecret = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<AgentManager
|
||||
<AgentManager
|
||||
:description="$t('user.settings.agents.desc')"
|
||||
:load-agents="loadAgents"
|
||||
:create-agent="createAgent"
|
||||
|
@ -1,35 +1,34 @@
|
||||
<template>
|
||||
<Settings :title="$t('user.settings.cli_and_api.cli_and_api')" :description="$t('user.settings.cli_and_api.desc')">
|
||||
<InputField :label="$t('user.settings.cli_and_api.cli_usage')">
|
||||
<template #headerActions>
|
||||
<a :href="cliDownload" target="_blank" class="ml-4 text-wp-link-100 hover:text-wp-link-200">{{
|
||||
<Settings :title="$t('user.settings.cli_and_api.cli_and_api')" :description="$t('user.settings.cli_and_api.desc')"
|
||||
> <InputField :label="$t('user.settings.cli_and_api.cli_usage')"
|
||||
> <template #headerActions
|
||||
> <a :href="cliDownload" target="_blank" class="ml-4 text-wp-link-100 hover:text-wp-link-200">{{
|
||||
$t('user.settings.cli_and_api.download_cli')
|
||||
}}</a>
|
||||
</template>
|
||||
}}</a
|
||||
> </template
|
||||
>
|
||||
<pre class="code-box">{{ usageWithCli }}</pre>
|
||||
</InputField>
|
||||
|
||||
<InputField :label="$t('user.settings.cli_and_api.token')">
|
||||
<template #titleActions>
|
||||
<Button class="ml-auto" :text="$t('user.settings.cli_and_api.reset_token')" @click="resetToken" />
|
||||
</template>
|
||||
</InputField
|
||||
> <InputField :label="$t('user.settings.cli_and_api.token')"
|
||||
> <template #titleActions
|
||||
> <Button class="ml-auto" :text="$t('user.settings.cli_and_api.reset_token')" @click="resetToken" /> </template
|
||||
>
|
||||
<pre class="code-box">{{ token }}</pre>
|
||||
</InputField>
|
||||
|
||||
<InputField :label="$t('user.settings.cli_and_api.api_usage')">
|
||||
<template #headerActions>
|
||||
<a
|
||||
</InputField
|
||||
> <InputField :label="$t('user.settings.cli_and_api.api_usage')"
|
||||
> <template #headerActions
|
||||
> <a
|
||||
v-if="enableSwagger"
|
||||
:href="`${address}/swagger/index.html`"
|
||||
target="_blank"
|
||||
class="ml-4 text-wp-link-100 hover:text-wp-link-200"
|
||||
>
|
||||
{{ $t('user.settings.cli_and_api.swagger_ui') }}
|
||||
</a>
|
||||
</template>
|
||||
> {{ $t('user.settings.cli_and_api.swagger_ui') }} </a
|
||||
> </template
|
||||
>
|
||||
<pre class="code-box">{{ usageWithCurl }}</pre>
|
||||
</InputField>
|
||||
</Settings>
|
||||
</InputField
|
||||
> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,10 +1,9 @@
|
||||
<template>
|
||||
<Settings :title="$t('user.settings.general.general')">
|
||||
<InputField v-slot="{ id }" :label="$t('user.settings.general.language')">
|
||||
<SelectField :id="id" v-model="selectedLocale" :options="localeOptions" />
|
||||
</InputField>
|
||||
<InputField v-slot="{ id }" :label="$t('user.settings.general.theme.theme')">
|
||||
<SelectField
|
||||
<Settings :title="$t('user.settings.general.general')"
|
||||
> <InputField v-slot="{ id }" :label="$t('user.settings.general.language')"
|
||||
> <SelectField :id="id" v-model="selectedLocale" :options="localeOptions" /> </InputField
|
||||
> <InputField v-slot="{ id }" :label="$t('user.settings.general.theme.theme')"
|
||||
> <SelectField
|
||||
:id="id"
|
||||
v-model="storeTheme"
|
||||
:options="[
|
||||
@ -12,9 +11,9 @@
|
||||
{ value: 'light', text: $t('user.settings.general.theme.light') },
|
||||
{ value: 'dark', text: $t('user.settings.general.theme.dark') },
|
||||
]"
|
||||
/>
|
||||
</InputField>
|
||||
</Settings>
|
||||
/> </InputField
|
||||
> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,35 +1,29 @@
|
||||
<template>
|
||||
<Settings
|
||||
<Settings
|
||||
:title="$t('registries.registries')"
|
||||
:description="$t('user.settings.registries.desc')"
|
||||
docs-url="docs/usage/registries"
|
||||
>
|
||||
<template #headerActions>
|
||||
<Button
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedRegistry"
|
||||
:text="$t('registries.show')"
|
||||
start-icon="back"
|
||||
@click="selectedRegistry = undefined"
|
||||
/>
|
||||
<Button v-else :text="$t('registries.add')" start-icon="plus" @click="showAddRegistry" />
|
||||
</template>
|
||||
|
||||
<RegistryList
|
||||
/> <Button v-else :text="$t('registries.add')" start-icon="plus" @click="showAddRegistry" /> </template
|
||||
> <RegistryList
|
||||
v-if="!selectedRegistry"
|
||||
v-model="registries"
|
||||
:is-deleting="isDeleting"
|
||||
@edit="editRegistry"
|
||||
@delete="deleteRegistry"
|
||||
/>
|
||||
|
||||
<RegistryEdit
|
||||
/> <RegistryEdit
|
||||
v-else
|
||||
v-model="selectedRegistry"
|
||||
:is-saving="isSaving"
|
||||
@save="createRegistry"
|
||||
@cancel="selectedRegistry = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,30 +1,29 @@
|
||||
<template>
|
||||
<Settings
|
||||
<Settings
|
||||
:title="$t('secrets.secrets')"
|
||||
:description="$t('user.settings.secrets.desc')"
|
||||
docs-url="docs/usage/secrets"
|
||||
>
|
||||
<template #headerActions>
|
||||
<Button v-if="selectedSecret" :text="$t('secrets.show')" start-icon="back" @click="selectedSecret = undefined" />
|
||||
<Button v-else :text="$t('secrets.add')" start-icon="plus" @click="showAddSecret" />
|
||||
</template>
|
||||
|
||||
<SecretList
|
||||
> <template #headerActions
|
||||
> <Button
|
||||
v-if="selectedSecret"
|
||||
:text="$t('secrets.show')"
|
||||
start-icon="back"
|
||||
@click="selectedSecret = undefined"
|
||||
/> <Button v-else :text="$t('secrets.add')" start-icon="plus" @click="showAddSecret" /> </template
|
||||
> <SecretList
|
||||
v-if="!selectedSecret"
|
||||
v-model="secrets"
|
||||
:is-deleting="isDeleting"
|
||||
@edit="editSecret"
|
||||
@delete="deleteSecret"
|
||||
/>
|
||||
|
||||
<SecretEdit
|
||||
/> <SecretEdit
|
||||
v-else
|
||||
v-model="selectedSecret"
|
||||
:is-saving="isSaving"
|
||||
@save="createSecret"
|
||||
@cancel="selectedSecret = undefined"
|
||||
/>
|
||||
</Settings>
|
||||
/> </Settings
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -1,20 +1,18 @@
|
||||
<template>
|
||||
<Scaffold enable-tabs>
|
||||
<template #title>{{ $t('user.settings.settings') }}</template>
|
||||
<template #headerActions><Button :text="$t('logout')" :to="`${address}/logout`" /></template>
|
||||
|
||||
<Tab :to="{ name: 'user' }" :title="$t('user.settings.general.general')" />
|
||||
<Tab :to="{ name: 'user-secrets' }" :title="$t('secrets.secrets')" />
|
||||
<Tab :to="{ name: 'user-registries' }" :title="$t('registries.registries')" />
|
||||
<Tab :to="{ name: 'user-cli-and-api' }" :title="$t('user.settings.cli_and_api.cli_and_api')" />
|
||||
<Tab
|
||||
<Scaffold enable-tabs
|
||||
> <template #title>{{ $t('user.settings.settings') }}</template
|
||||
> <template #headerActions><Button :text="$t('logout')" :to="`${address}/logout`" /></template> <Tab
|
||||
:to="{ name: 'user' }"
|
||||
:title="$t('user.settings.general.general')"
|
||||
/> <Tab :to="{ name: 'user-secrets' }" :title="$t('secrets.secrets')" /> <Tab
|
||||
:to="{ name: 'user-registries' }"
|
||||
:title="$t('registries.registries')"
|
||||
/> <Tab :to="{ name: 'user-cli-and-api' }" :title="$t('user.settings.cli_and_api.cli_and_api')" /> <Tab
|
||||
v-if="useConfig().userRegisteredAgents"
|
||||
:to="{ name: 'user-agents' }"
|
||||
:title="$t('admin.settings.agents.agents')"
|
||||
/>
|
||||
|
||||
<router-view />
|
||||
</Scaffold>
|
||||
/> <router-view /> </Scaffold
|
||||
>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
Loading…
x
Reference in New Issue
Block a user