Merge branch 'origin/main' into 'next-release/main'

This commit is contained in:
oauth 2025-01-01 15:17:58 +00:00
commit c11bee4d50
76 changed files with 364 additions and 277 deletions

View file

@ -117,4 +117,5 @@ vscode:
- 'redhat.vscode-yaml'
- 'davidanson.vscode-markdownlint'
- 'streetsidesoftware.code-spell-checker'
- 'stivo.tailwind-fold'
# cSpell:enable

View file

@ -8,7 +8,8 @@
"voorjaar.windicss-intellisense",
"Vue.volar",
"redhat.vscode-yaml",
"davidanson.vscode-markdownlint"
"davidanson.vscode-markdownlint",
"stivo.tailwind-fold"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": []

View file

@ -38,9 +38,12 @@ when:
steps:
prettier:
image: docker.io/woodpeckerci/plugin-prettier:1.0.0
image: docker.io/woodpeckerci/plugin-prettier:next
settings:
version: 3.3.3
plugins:
- 'prettier-plugin-tailwindcss'
- '@ianvs/prettier-plugin-sort-imports'
when:
- event: pull_request

View file

@ -19,7 +19,11 @@ steps:
- tree --gitignore -I 012_columns_rename_procs_to_steps.go -I versioned_docs -I '*opensource.svg'| pnpx cspell lint --no-progress stdin
- name: prettier
image: docker.io/woodpeckerci/plugin-prettier:1.0.0
image: docker.io/woodpeckerci/plugin-prettier:next
pull: true
depends_on: []
settings:
version: 3.3.3
plugins:
- 'prettier-plugin-tailwindcss'
- '@ianvs/prettier-plugin-sort-imports'

View file

@ -24,6 +24,18 @@ steps:
- pnpm install --frozen-lockfile
when: *when
prettier:
depends_on:
- install-dependencies
image: docker.io/woodpeckerci/plugin-prettier:next
pull: true
settings:
version: 3.3.3
plugins:
- 'prettier-plugin-tailwindcss'
- '@ianvs/prettier-plugin-sort-imports'
when: *when
lint:
depends_on:
- install-dependencies

View file

@ -24,6 +24,7 @@ The following list contains some tools and frameworks used by the Woodpecker UI.
- [Windicss](https://windicss.org/) (similar to Tailwind)
- use Windicss classes where possible
- if needed extend the Windicss config to use new classes
- classes are sorted following the [prettier tailwind sort plugin](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier)
- [Vite](https://vitejs.dev/) (similar to Webpack)
- [Typescript](https://www.typescriptlang.org/)
- avoid using `any` and `unknown` (the linter will prevent you from doing so anyways :wink:)

View file

@ -7,7 +7,7 @@ import { IconContainer, IconPlugin, IconVerified, IconWebsite } from './Icons';
export function WoodpeckerPlugin({ plugin }: { plugin: WoodpeckerPluginType }) {
return (
<Layout title="Woodpecker CI plugins" description="List of Woodpecker-CI plugins">
<main className="container margin-vert--lg">
<main className="margin-vert--lg container">
<section>
<div className="container">
<div className="wp-plugin-breadcrumbs">

View file

@ -52,7 +52,7 @@ export function WoodpeckerPluginList({ plugins }: { plugins: WoodpeckerPlugin[]
return (
<Layout title="Woodpecker CI plugins" description="List of all Woodpecker-CI plugins">
<main className="container margin-vert--lg">
<main className="margin-vert--lg container">
<section>
<div style={{ display: 'flex', flexFlow: 'column', alignItems: 'center' }}>
<h1>Woodpecker CI plugins</h1>

View file

@ -5,7 +5,7 @@ const config = JSON.parse(await readFile(new URL('../.prettierrc.json', import.m
export default {
...config,
plugins: ['@ianvs/prettier-plugin-sort-imports'],
plugins: ['@ianvs/prettier-plugin-sort-imports', 'prettier-plugin-tailwindcss'],
importOrder: [
'<THIRD_PARTY_MODULES>', // Imports not matched by other special words or groups.
'', // Empty string will match any import not matched by other special words or groups.

View file

@ -29,6 +29,7 @@
"marked": "^15.0.4",
"node-emoji": "^2.2.0",
"pinia": "^2.3.0",
"prettier-plugin-tailwindcss": "^0.6.9",
"prismjs": "^1.29.0",
"semver": "^7.6.3",
"simple-icons": "^14.0.0",

View file

@ -44,6 +44,9 @@ importers:
pinia:
specifier: ^2.3.0
version: 2.3.0(typescript@5.7.2)(vue@3.5.13(typescript@5.7.2))
prettier-plugin-tailwindcss:
specifier: ^0.6.9
version: 0.6.9(@ianvs/prettier-plugin-sort-imports@4.4.0(@vue/compiler-sfc@3.5.13)(prettier@3.4.2))(prettier@3.4.2)
prismjs:
specifier: ^1.29.0
version: 1.29.0
@ -2361,6 +2364,61 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
prettier-plugin-tailwindcss@0.6.9:
resolution: {integrity: sha512-r0i3uhaZAXYP0At5xGfJH876W3HHGHDp+LCRUJrs57PBeQ6mYHMwr25KH8NPX44F2yGTvdnH7OqCshlQx183Eg==}
engines: {node: '>=14.21.3'}
peerDependencies:
'@ianvs/prettier-plugin-sort-imports': '*'
'@prettier/plugin-pug': '*'
'@shopify/prettier-plugin-liquid': '*'
'@trivago/prettier-plugin-sort-imports': '*'
'@zackad/prettier-plugin-twig-melody': '*'
prettier: ^3.0
prettier-plugin-astro: '*'
prettier-plugin-css-order: '*'
prettier-plugin-import-sort: '*'
prettier-plugin-jsdoc: '*'
prettier-plugin-marko: '*'
prettier-plugin-multiline-arrays: '*'
prettier-plugin-organize-attributes: '*'
prettier-plugin-organize-imports: '*'
prettier-plugin-sort-imports: '*'
prettier-plugin-style-order: '*'
prettier-plugin-svelte: '*'
peerDependenciesMeta:
'@ianvs/prettier-plugin-sort-imports':
optional: true
'@prettier/plugin-pug':
optional: true
'@shopify/prettier-plugin-liquid':
optional: true
'@trivago/prettier-plugin-sort-imports':
optional: true
'@zackad/prettier-plugin-twig-melody':
optional: true
prettier-plugin-astro:
optional: true
prettier-plugin-css-order:
optional: true
prettier-plugin-import-sort:
optional: true
prettier-plugin-jsdoc:
optional: true
prettier-plugin-marko:
optional: true
prettier-plugin-multiline-arrays:
optional: true
prettier-plugin-organize-attributes:
optional: true
prettier-plugin-organize-imports:
optional: true
prettier-plugin-sort-imports:
optional: true
prettier-plugin-style-order:
optional: true
prettier-plugin-svelte:
optional: true
prettier@3.4.2:
resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==}
engines: {node: '>=14'}
@ -5404,6 +5462,12 @@ snapshots:
prelude-ls@1.2.1: {}
prettier-plugin-tailwindcss@0.6.9(@ianvs/prettier-plugin-sort-imports@4.4.0(@vue/compiler-sfc@3.5.13)(prettier@3.4.2))(prettier@3.4.2):
dependencies:
prettier: 3.4.2
optionalDependencies:
'@ianvs/prettier-plugin-sort-imports': 4.4.0(@vue/compiler-sfc@3.5.13)(prettier@3.4.2)
prettier@3.4.2: {}
prismjs@1.29.0: {}

View file

@ -1,14 +1,14 @@
<template>
<div class="app flex flex-col m-auto w-full h-full bg-wp-background-200 dark:bg-wp-background-100">
<div class="app bg-wp-background-200 dark:bg-wp-background-100 m-auto flex h-full w-full flex-col">
<router-view v-if="blank" />
<template v-else>
<Navbar />
<main class="relative flex min-h-0 h-full">
<div id="scroll-component" class="flex flex-col overflow-y-auto flex-grow">
<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="shadow-md border-l w-full absolute top-0 right-0 bottom-0 max-w-80 xl:max-w-96" />
<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>

View file

@ -1,22 +1,22 @@
<template>
<div v-if="stats" class="flex justify-center">
<div
class="border-wp-background-300 bg-wp-background-200 dark:bg-wp-background-100 px-5 py-5 border rounded-md w-full text-wp-text-100"
class="border-wp-background-300 bg-wp-background-200 dark:bg-wp-background-100 text-wp-text-100 w-full rounded-md border px-5 py-5"
>
<div class="flex w-full">
<h3 class="flex-1 font-semibold text-lg uppercase leading-tight">
<h3 class="flex-1 text-lg font-semibold uppercase leading-tight">
{{ $t('admin.settings.queue.stats.completed_count') }}
</h3>
</div>
<div class="relative transition-all duration-500 overflow-hidden">
<div class="relative overflow-hidden transition-all duration-500">
<div>
<div class="pb-4 lg:pb-6">
<h4 class="inline-block font-semibold text-2xl lg:text-3xl leading-tight">
<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 rounded-full h-3 transition-all duration-500 overflow-hidden">
<div class="flex h-3 overflow-hidden rounded-full transition-all duration-500">
<div
v-for="item in data"
:key="item.key"
@ -28,18 +28,18 @@
</div>
</div>
</div>
<div class="flex sm:flex-wrap -mx-4">
<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="{ 'md:border-l border-gray-300 dark:border-gray-600': index !== 0 }"
:class="{ 'border-gray-300 md:border-l dark:border-gray-600': index !== 0 }"
>
<div class="text-ellipsis text-sm whitespace-nowrap overflow-hidden">
<span class="inline-block mr-1 rounded-full w-2 h-2 align-middle" :class="`${item.color}`">&nbsp;</span>
<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}`">&nbsp;</span>
<span class="align-middle">{{ item.label }}</span>
</div>
<div class="font-medium text-lg">
<div class="text-lg font-medium">
{{ item.value }}
</div>
</div>

View file

@ -1,13 +1,13 @@
<template>
<div v-if="!props.loading" class="space-y-4 text-wp-text-100">
<div v-if="!props.loading" class="text-wp-text-100 space-y-4">
<ListItem
v-for="agent in props.agents"
:key="agent.id"
class="items-center !bg-wp-background-200 !dark:bg-wp-background-100"
class="!bg-wp-background-200 !dark:bg-wp-background-100 items-center"
>
<span>{{ agent.name || `Agent ${agent.id}` }}</span>
<span class="ml-auto">
<span class="md:inline-block space-x-2 hidden">
<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')"
@ -24,13 +24,13 @@
<IconButton
icon="edit"
:title="$t('admin.settings.agents.edit_agent')"
class="ml-2 w-8 h-8"
class="ml-2 h-8 w-8"
@click="$emit('edit', agent)"
/>
<IconButton
icon="trash"
:title="$t('admin.settings.agents.delete_agent')"
class="ml-2 w-8 h-8 hover:text-wp-error-100"
class="hover:text-wp-error-100 ml-2 h-8 w-8"
:is-loading="props.isDeleting"
@click="$emit('delete', agent)"
/>

View file

@ -1,7 +1,7 @@
<template>
<span class="text-xs font-medium inline-flex">
<span class="inline-flex text-xs font-medium">
<span
class="pl-2 pr-1 py-0.5 bg-wp-state-neutral-100 text-gray-300 border-2 border-wp-state-neutral-100 rounded-l-full flex items-center"
class="bg-wp-state-neutral-100 border-wp-state-neutral-100 flex items-center rounded-l-full border-2 py-0.5 pl-2 pr-1 text-gray-300"
:class="{
'rounded-r-full pr-2': value === undefined,
}"
@ -10,7 +10,7 @@
</span>
<span
v-if="value !== undefined"
class="pl-1 pr-2 py-0.5 border-2 border-wp-state-neutral-100 rounded-r-full flex items-center"
class="border-wp-state-neutral-100 flex items-center rounded-r-full border-2 py-0.5 pl-1 pr-2"
>
{{ value }}
</span>

View file

@ -2,7 +2,7 @@
<component
:is="to === undefined ? 'button' : httpLink ? 'a' : 'router-link'"
v-bind="btnAttrs"
class="relative flex flex-shrink-0 items-center disabled:opacity-50 shadow-sm px-2 py-1 border rounded-md whitespace-nowrap transition-all duration-150 cursor-pointer disabled:cursor-not-allowed overflow-hidden"
class="relative flex flex-shrink-0 cursor-pointer items-center overflow-hidden whitespace-nowrap rounded-md border px-2 py-1 shadow-sm transition-all duration-150 disabled:cursor-not-allowed disabled:opacity-50"
:class="{
'bg-wp-control-neutral-100 hover:bg-wp-control-neutral-200 border-wp-control-neutral-300 text-wp-text-100':
color === 'gray',
@ -15,12 +15,12 @@
:disabled="disabled"
>
<slot>
<Icon v-if="startIcon" :name="startIcon" class="!w-5 !h-5" :class="{ invisible: isLoading, 'mr-1': text }" />
<Icon v-if="startIcon" :name="startIcon" class="!h-5 !w-5" :class="{ invisible: isLoading, 'mr-1': text }" />
<span :class="{ invisible: isLoading }">{{ text }}</span>
<Icon v-if="endIcon" :name="endIcon" class="ml-2 w-6 h-6" :class="{ invisible: isLoading }" />
<Icon v-if="endIcon" :name="endIcon" class="ml-2 h-6 w-6" :class="{ invisible: isLoading }" />
<div
v-if="isLoading"
class="top-0 right-0 bottom-0 left-0 absolute flex justify-center items-center"
class="absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center"
:class="{
'bg-wp-control-neutral-200': color === 'gray',
'bg-wp-control-ok-200': color === 'green',

View file

@ -1,6 +1,6 @@
<template>
<span
class="text-xs font-bold inline-block min-w-5 leading-4 rounded-full bg-wp-background-300 dark:bg-wp-background-100 text-wp-text-100 text-center py-0.5 px-1.5"
class="bg-wp-background-300 dark:bg-wp-background-100 text-wp-text-100 inline-block min-w-5 rounded-full px-1.5 py-0.5 text-center text-xs font-bold leading-4"
>
{{ value }}
</span>

View file

@ -5,7 +5,7 @@
target="_blank"
class="text-wp-link-100 hover:text-wp-link-200 cursor-pointer"
>
<Icon name="question" class="!w-5 !h-5" />
<Icon name="question" class="!h-5 !w-5" />
</a>
</template>

View file

@ -1,6 +1,6 @@
<template>
<div
class="flex items-center gap-2 border-wp-error-300 dark:border-wp-error-300 bg-wp-error-100 dark:bg-wp-error-200 p-2 border border-l-6 border-solid rounded-md text-white"
class="border-wp-error-300 dark:border-wp-error-300 bg-wp-error-100 dark:bg-wp-error-200 border-l-6 flex items-center gap-2 rounded-md border border-solid p-2 text-white"
>
<Icon v-if="!textOnly" name="alert" />
<slot>

View file

@ -77,7 +77,7 @@
</path>
</svg>
<div v-else-if="name === 'blank'" class="w-6 h-6" />
<div v-else-if="name === 'blank'" class="h-6 w-6" />
</template>
<script lang="ts" setup>

View file

@ -1,5 +1,5 @@
<template>
<router-link v-if="to" :to="to" :title="title" :aria-label="title" class="w-8 h-8 icon-button">
<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>
@ -21,7 +21,7 @@
<slot>
<Icon v-if="icon" :name="icon" />
</slot>
<div v-if="isLoading" class="top-0 right-0 bottom-0 left-0 absolute flex justify-center items-center">
<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" />
</div>
</button>
@ -44,6 +44,6 @@ defineProps<{
<style scoped>
.icon-button {
@apply relative flex justify-center items-center bg-transparent disabled:opacity-50 px-1 py-1 rounded-md disabled:cursor-not-allowed overflow-hidden hover-effect;
@apply hover-effect relative flex items-center justify-center overflow-hidden rounded-md bg-transparent px-1 py-1 disabled:cursor-not-allowed disabled:opacity-50;
}
</style>

View file

@ -2,9 +2,9 @@
<component
:is="to ? 'router-link' : clickable ? 'button' : 'div'"
:to="to"
class="w-full flex border rounded-md bg-wp-background-100 overflow-hidden p-4 border-wp-background-400 dark:bg-wp-background-200"
class="bg-wp-background-100 border-wp-background-400 dark:bg-wp-background-200 flex w-full overflow-hidden rounded-md border p-4"
:class="{
'cursor-pointer hover:shadow-md hover:bg-wp-background-300 dark:hover:bg-wp-background-300': clickable || to,
'hover:bg-wp-background-300 dark:hover:bg-wp-background-300 cursor-pointer hover:shadow-md': clickable || to,
}"
>
<slot />

View file

@ -1,6 +1,6 @@
<template>
<div
class="flex gap-4 items-center text-gray-700 font-bold rounded-md p-4 border border-solid border-l-6 border-wp-hint-warn-200 bg-wp-hint-warn-100"
class="border-l-6 border-wp-hint-warn-200 bg-wp-hint-warn-100 flex items-center gap-4 rounded-md border border-solid p-4 font-bold text-gray-700"
>
<Icon v-if="!textOnly" name="alert" class="flex-shrink-0" />
<slot>

View file

@ -1,15 +1,15 @@
<template>
<div class="flex items-center mb-2">
<div class="mb-2 flex items-center">
<input
:id="`checkbox-${id}`"
type="checkbox"
class="relative flex-shrink-0 border-wp-control-neutral-200 checked:border-wp-control-ok-200 focus-visible:border-wp-control-neutral-300 checked:focus-visible:border-wp-control-ok-300 bg-wp-control-neutral-100 checked:bg-wp-control-ok-200 border rounded-md w-5 h-5 transition-colors duration-150 cursor-pointer checkbox"
class="border-wp-control-neutral-200 checked:border-wp-control-ok-200 focus-visible:border-wp-control-neutral-300 checked:focus-visible:border-wp-control-ok-300 bg-wp-control-neutral-100 checked:bg-wp-control-ok-200 checkbox relative h-5 w-5 flex-shrink-0 cursor-pointer rounded-md border transition-colors duration-150"
:checked="innerValue"
@click="innerValue = !innerValue"
/>
<div class="flex flex-col ml-4">
<div class="ml-4 flex flex-col">
<label class="text-wp-text-100 cursor-pointer" :for="`checkbox-${id}`">{{ label }}</label>
<span v-if="description" class="text-sm text-wp-text-alt-100">{{ description }}</span>
<span v-if="description" class="text-wp-text-alt-100 text-sm">{{ description }}</span>
</div>
</div>
</template>

View file

@ -1,12 +1,12 @@
<template>
<div class="flex flex-col mt-2 mb-4">
<div class="flex items-center mb-2">
<div class="mb-4 mt-2 flex flex-col">
<div class="mb-2 flex items-center">
<label class="text-wp-text-100 font-bold" :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>
<slot :id="id" />
<div v-if="$slots.description" class="ml-1 text-wp-text-alt-100">
<div v-if="$slots.description" class="text-wp-text-alt-100 ml-1">
<slot name="description" />
</div>
</div>

View file

@ -1,16 +1,16 @@
<template>
<div v-for="option in options" :key="option.value" class="flex items-center mb-2">
<div v-for="option in options" :key="option.value" class="mb-2 flex items-center">
<input
:id="`radio-${id}-${option.value}`"
type="radio"
class="relative flex-shrink-0 border-wp-control-neutral-200 checked:border-wp-control-ok-200 focus-visible:border-wp-control-neutral-300 checked:focus-visible:border-wp-control-ok-300 bg-wp-control-neutral-100 checked:bg-wp-control-ok-200 border rounded-full w-5 h-5 cursor-pointer radio"
class="border-wp-control-neutral-200 checked:border-wp-control-ok-200 focus-visible:border-wp-control-neutral-300 checked:focus-visible:border-wp-control-ok-300 bg-wp-control-neutral-100 checked:bg-wp-control-ok-200 radio relative h-5 w-5 flex-shrink-0 cursor-pointer rounded-full border"
:value="option.value"
:checked="innerValue?.includes(option.value)"
@click="innerValue = option.value"
/>
<div class="flex flex-col ml-4">
<div class="ml-4 flex flex-col">
<label class="text-wp-text-100 cursor-pointer" :for="`radio-${id}-${option.value}`">{{ option.text }}</label>
<span v-if="option.description" class="text-sm text-wp-text-alt-100">{{ option.description }}</span>
<span v-if="option.description" class="text-wp-text-alt-100 text-sm">{{ option.description }}</span>
</div>
</div>
</template>

View file

@ -1,7 +1,7 @@
<template>
<select
v-model="innerValue"
class="bg-wp-control-neutral-100 text-wp-text-100 border-wp-control-neutral-200 w-full border py-1 px-2 rounded-md"
class="bg-wp-control-neutral-100 text-wp-text-100 border-wp-control-neutral-200 w-full rounded-md border px-2 py-1"
>
<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">

View file

@ -2,7 +2,7 @@
<input
v-if="lines === 1"
v-model="innerValue"
class="w-full border border-wp-control-neutral-200 py-1 px-2 rounded-md bg-wp-background-100 focus-visible:outline-none focus-visible:border-wp-control-neutral-300"
class="border-wp-control-neutral-200 bg-wp-background-100 focus-visible:border-wp-control-neutral-300 w-full rounded-md border px-2 py-1 focus-visible:outline-none"
:class="{ 'opacity-50': disabled }"
:disabled="disabled"
:type="type"
@ -11,7 +11,7 @@
<textarea
v-else
v-model="innerValue"
class="w-full border border-wp-control-neutral-200 py-1 px-2 rounded-md bg-wp-background-100 focus-visible:outline-none focus-visible:border-wp-control-neutral-300"
class="border-wp-control-neutral-200 bg-wp-background-100 focus-visible:border-wp-control-neutral-300 w-full rounded-md border px-2 py-1 focus-visible:outline-none"
:class="{ 'opacity-50': disabled }"
:disabled="disabled"
:placeholder="placeholder"

View file

@ -1,5 +1,5 @@
<template>
<div class="mx-auto p-4 w-full" :class="{ 'max-w-5xl': !fullWidth && !fillWidth, 'md:px-0': fullWidth }">
<div class="mx-auto w-full p-4" :class="{ 'max-w-5xl': !fullWidth && !fillWidth, 'md:px-0': fullWidth }">
<slot />
</div>
</template>

View file

@ -1,19 +1,19 @@
<template>
<div
class="rounded-md w-full shadow overflow-hidden bg-wp-background-100 dark:bg-wp-background-200 border border-wp-background-400"
class="bg-wp-background-100 dark:bg-wp-background-200 border-wp-background-400 w-full overflow-hidden rounded-md border shadow"
>
<component
:is="collapsable ? 'button' : 'div'"
v-if="title"
type="button"
class="flex w-full font-bold gap-2 text-wp-text-100 px-4 py-2 bg-wp-background-300"
class="text-wp-text-100 bg-wp-background-300 flex w-full gap-2 px-4 py-2 font-bold"
@click="_collapsed = !_collapsed"
>
<Icon
v-if="collapsable"
name="chevron-right"
class="transition-transform duration-150 min-w-6 h-6"
:class="{ 'transform rotate-90': !collapsed }"
class="h-6 min-w-6 transition-transform duration-150"
:class="{ 'rotate-90 transform': !collapsed }"
/>
{{ title }}
</component>
@ -22,9 +22,9 @@
'max-h-auto': !collapsed,
'max-h-0': collapsed,
}"
class="transition-height duration-150 overflow-hidden"
class="transition-height overflow-hidden duration-150"
>
<div class="w-full p-4 text-wp-text-100">
<div class="text-wp-text-100 w-full p-4">
<slot />
</div>
</div>

View file

@ -2,15 +2,15 @@
<!-- overlay -->
<div
v-if="open"
class="fixed bg-gray-900 opacity-80 left-0 top-0 right-0 bottom-0 z-500 print:hidden"
class="z-500 fixed bottom-0 left-0 right-0 top-0 bg-gray-900 opacity-80 print:hidden"
@click="$emit('close')"
/>
<!-- overlay end -->
<div
v-if="open"
class="print:hidden fixed flex max-w-1/3 <md:max-w-4/5 max-h-3/5 top-1/2 left-1/2 transform z-1000 -translate-x-1/2 -translate-y-1/2"
class="max-w-1/3 <md:max-w-4/5 max-h-3/5 z-1000 fixed left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 transform print:hidden"
>
<div class="m-auto flex flex-col shadow-all h-auto">
<div class="shadow-all m-auto flex h-auto flex-col">
<slot />
</div>
</div>

View file

@ -1,16 +1,16 @@
<template>
<Panel>
<div class="flex flex-col border-b mb-4 pb-4 justify-center dark:border-wp-background-100">
<div class="dark:border-wp-background-100 mb-4 flex flex-col justify-center border-b pb-4">
<div class="flex items-center justify-between">
<h1 class="text-xl text-wp-text-100 flex items-center gap-1">
<h1 class="text-wp-text-100 flex items-center gap-1 text-xl">
{{ title }}
<DocsLink v-if="docsUrl" :topic="title" :url="docsUrl" />
</h1>
<slot v-if="$slots.titleActions" name="titleActions" />
</div>
<div class="flex flex-wrap gap-x-4 gap-y-2 items-center justify-between">
<p v-if="description" class="text-sm text-wp-text-alt-100">{{ description }}</p>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2">
<p v-if="description" class="text-wp-text-alt-100 text-sm">{{ description }}</p>
<div v-if="$slots.headerActions">
<slot name="headerActions" />
</div>

View file

@ -1,12 +1,12 @@
<template>
<IconButton
:title="pipelineCount > 0 ? `${$t('pipeline_feed')} (${pipelineCount})` : $t('pipeline_feed')"
class="relative !p-1.5 text-current active-pipelines-toggle"
class="active-pipelines-toggle relative !p-1.5 text-current"
@click="toggle"
>
<div v-if="pipelineCount > 0" class="spinner" />
<div
class="z-0 flex justify-center items-center bg-white dark:bg-black bg-opacity-15 dark:bg-opacity-10 rounded-md w-full h-full font-bold"
class="z-0 flex h-full w-full items-center justify-center rounded-md bg-white bg-opacity-15 font-bold dark:bg-black dark:bg-opacity-10"
>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
{{ pipelineCount > 9 ? '9+' : pipelineCount }}
@ -41,7 +41,7 @@ onMounted(async () => {
overflow: hidden;
}
.spinner::before {
@apply absolute bg-wp-primary-200 dark:bg-wp-primary-300;
@apply bg-wp-primary-200 dark:bg-wp-primary-300 absolute;
content: '';
left: -50%;
top: -50%;
@ -55,7 +55,7 @@ onMounted(async () => {
animation: rotate 1.5s linear infinite;
}
.spinner::after {
@apply absolute inset-0.5 bg-wp-primary-200 dark:bg-wp-primary-300;
@apply bg-wp-primary-200 dark:bg-wp-primary-300 absolute inset-0.5;
/*
The nested border radius needs to be calculated correctly to look right:
https://www.30secondsofcode.org/css/s/nested-border-radius/

View file

@ -1,36 +1,36 @@
<template>
<nav
class="flex border-wp-background-100 bg-wp-primary-200 dark:bg-wp-primary-300 p-4 border-b font-bold text-neutral-content text-wp-primary-text-100"
class="border-wp-background-100 bg-wp-primary-200 dark:bg-wp-primary-300 text-neutral-content text-wp-primary-text-100 flex border-b p-4 font-bold"
>
<div class="flex items-center space-x-2">
<router-link :to="{ name: 'home' }" class="flex flex-col -my-2 px-2">
<WoodpeckerLogo class="w-8 h-8" />
<router-link :to="{ name: 'home' }" class="-my-2 flex flex-col px-2">
<WoodpeckerLogo class="h-8 w-8" />
<span class="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="md:flex hidden">{{ $t('repositories') }}</span>
<span class="hidden md:flex">{{ $t('repositories') }}</span>
</router-link>
<a href="https://woodpecker-ci.org/" target="_blank" class="md:flex hidden navbar-clickable navbar-link">{{
<a href="https://woodpecker-ci.org/" target="_blank" class="navbar-clickable navbar-link hidden md:flex">{{
$t('docs')
}}</a>
<a v-if="enableSwagger" :href="apiUrl" target="_blank" class="md:flex hidden navbar-clickable navbar-link">{{
<a v-if="enableSwagger" :href="apiUrl" target="_blank" class="navbar-clickable navbar-link hidden md:flex">{{
$t('api')
}}</a>
</div>
<div class="flex items-center space-x-2 -m-1.5 ml-auto">
<div class="-m-1.5 ml-auto flex items-center space-x-2">
<IconButton
v-if="user?.admin"
class="relative navbar-icon"
class="navbar-icon relative"
:title="$t('settings')"
:to="{ name: 'admin-settings' }"
>
<Icon name="settings" />
<div v-if="version?.needsUpdate" class="top-2 right-2 absolute bg-int-wp-error-100 rounded-full w-3 h-3" />
<div v-if="version?.needsUpdate" class="bg-int-wp-error-100 absolute right-2 top-2 h-3 w-3 rounded-full" />
</IconButton>
<ActivePipelines v-if="user" class="!p-1.5 navbar-icon" />
<IconButton v-if="user" :to="{ name: 'user' }" :title="$t('user.settings.settings')" class="!p-1.5 navbar-icon">
<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}`" />
@ -63,14 +63,14 @@ const { enableSwagger } = config;
<style scoped>
.navbar-icon {
@apply p-2.5 rounded-md w-11 h-11;
@apply h-11 w-11 rounded-md p-2.5;
}
.navbar-icon :deep(svg) {
@apply w-full h-full;
@apply h-full w-full;
}
.navbar-link {
@apply -my-1 px-3 py-2 rounded-md hover-effect;
@apply hover-effect -my-1 rounded-md px-3 py-2;
}
</style>

View file

@ -2,7 +2,7 @@
<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-wp-text-100 text-xl">{{
$t('repo.deploy_pipeline.title', { pipelineId: pipelineNumber })
}}</span>
<InputField v-slot="{ id }" :label="$t('repo.deploy_pipeline.enter_target')">
@ -12,7 +12,7 @@
<TextField :id="id" v-model="payload.task" />
</InputField>
<InputField v-slot="{ id }" :label="$t('repo.deploy_pipeline.variables.title')">
<span class="text-sm text-wp-text-alt-100 mb-2">{{ $t('repo.deploy_pipeline.variables.desc') }}</span>
<span class="text-wp-text-alt-100 mb-2 text-sm">{{ $t('repo.deploy_pipeline.variables.desc') }}</span>
<KeyValueEditor
:id="id"
v-model="payload.variables"

View file

@ -4,9 +4,9 @@
:class="{ 'md:px-4': fullWidth }"
>
<Container :full-width="fullWidth" class="!py-0">
<div class="flex md:flex-row flex-col md:justify-between md:items-center gap-2 md:gap-10 py-3 w-full">
<div class="flex w-full flex-col gap-2 py-3 md:flex-row md:items-center md:justify-between md:gap-10">
<div
class="flex items-center content-start min-h-10"
class="flex min-h-10 content-start items-center"
:class="{
'md:flex-1': searchBoxPresent,
}"
@ -15,16 +15,16 @@
v-if="goBack"
icon="back"
:title="$t('back')"
class="flex-shrink-0 mr-2 <md:hidden md:justify-between w-8 h-8"
class="<md:hidden mr-2 h-8 w-8 flex-shrink-0 md:justify-between"
@click="goBack"
/>
<h1 class="flex items-center gap-x-2 min-w-0 text-wp-text-100 text-xl">
<h1 class="text-wp-text-100 flex min-w-0 items-center gap-x-2 text-xl">
<slot name="title" />
</h1>
</div>
<TextField
v-if="searchBoxPresent"
class="w-auto <md:w-full flex-grow <md:order-3"
class="<md:w-full <md:order-3 w-auto flex-grow"
:aria-label="$t('search')"
:placeholder="$t('search')"
:model-value="search"
@ -32,7 +32,7 @@
/>
<div
v-if="$slots.headerActions"
class="flex md:justify-end items-center gap-x-2 min-w-0"
class="flex min-w-0 items-center gap-x-2 md:justify-end"
:class="{
'md:flex-1': searchBoxPresent,
}"
@ -41,9 +41,9 @@
</div>
</div>
<div v-if="enableTabs" class="flex md:flex-row flex-col md:justify-between md:items-center py-2 md:py-0">
<div v-if="enableTabs" class="flex flex-col py-2 md:flex-row md:items-center md:justify-between md:py-0">
<Tabs class="<md:order-2" />
<div v-if="$slots.headerActions" class="flex md:justify-end content-start">
<div v-if="$slots.headerActions" class="flex content-start md:justify-end">
<slot name="tabActions" />
</div>
</div>

View file

@ -1,22 +1,22 @@
<template>
<div class="flex flex-wrap mt-2 md:gap-4">
<div class="mt-2 flex flex-wrap md:gap-4">
<router-link
v-for="tab in tabs"
:key="tab.title"
v-slot="{ isActive, isExactActive }"
:to="tab.to"
class="border-transparent w-full py-1 md:w-auto flex cursor-pointer md:border-b-2 text-wp-text-100 items-center"
class="text-wp-text-100 flex w-full cursor-pointer items-center border-transparent py-1 md:w-auto md:border-b-2"
:active-class="tab.matchChildren ? '!border-wp-text-100' : ''"
:exact-active-class="tab.matchChildren ? '' : '!border-wp-text-100'"
>
<Icon
v-if="isExactActive || (isActive && tab.matchChildren)"
name="chevron-right"
class="md:hidden flex-shrink-0"
class="flex-shrink-0 md:hidden"
/>
<Icon v-else name="blank" class="md:hidden" />
<span
class="flex gap-2 items-center md:justify-center flex-row py-1 px-2 w-full min-w-20 dark:hover:bg-wp-background-100 hover:bg-wp-background-200 rounded-md"
class="dark:hover:bg-wp-background-100 hover:bg-wp-background-200 flex w-full min-w-20 flex-row items-center gap-2 rounded-md px-2 py-1 md:justify-center"
>
<Icon v-if="tab.icon" :name="tab.icon" :class="tab.iconClass" class="flex-shrink-0" />
<span>{{ tab.title }}</span>

View file

@ -1,7 +1,7 @@
<template>
<div v-if="pipeline" class="flex text-wp-text-100 w-full">
<div v-if="pipeline" class="text-wp-text-100 flex w-full">
<PipelineStatusIcon :status="pipeline.status" class="flex items-center" />
<div class="flex flex-col ml-4 min-w-0">
<div class="ml-4 flex min-w-0 flex-col">
<router-link
:to="{
name: 'repo',
@ -12,13 +12,13 @@
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
{{ repo?.owner }} / {{ repo?.name }}
</router-link>
<span class="whitespace-nowrap overflow-hidden overflow-ellipsis" :title="message">{{ shortMessage }}</span>
<div class="flex flex-col mt-2">
<div class="flex space-x-2 items-center" :title="created">
<span class="overflow-hidden overflow-ellipsis whitespace-nowrap" :title="message">{{ shortMessage }}</span>
<div class="mt-2 flex flex-col">
<div class="flex items-center space-x-2" :title="created">
<Icon name="since" />
<span>{{ since }}</span>
</div>
<div class="flex space-x-2 items-center">
<div class="flex items-center space-x-2">
<Icon name="duration" />
<span>{{ duration }}</span>
</div>

View file

@ -2,7 +2,7 @@
<aside
v-if="isOpen"
ref="target"
class="flex flex-col z-50 overflow-y-auto items-center bg-wp-background-100 dark:bg-wp-background-200 border-wp-background-400"
class="bg-wp-background-100 dark:bg-wp-background-200 border-wp-background-400 z-50 flex flex-col items-center overflow-y-auto"
:aria-label="$t('pipeline_feed')"
>
<router-link
@ -12,7 +12,7 @@
name: 'repo-pipeline',
params: { repoId: pipeline.repo_id, pipelineId: pipeline.number },
}"
class="flex border-b border-wp-background-400 py-4 px-2 w-full hover:bg-wp-background-300 dark:hover:bg-wp-background-400 hover:shadow-sm"
class="border-wp-background-400 hover:bg-wp-background-300 dark:hover:bg-wp-background-400 flex w-full border-b px-2 py-4 hover:shadow-sm"
>
<PipelineFeedItem :pipeline="pipeline" />
</router-link>

View file

@ -1,21 +1,21 @@
<template>
<div class="space-y-4 text-wp-text-100">
<div class="text-wp-text-100 space-y-4">
<ListItem
v-for="registry in registries"
:key="registry.id"
class="items-center !bg-wp-background-200 !dark:bg-wp-background-100"
class="!bg-wp-background-200 !dark:bg-wp-background-100 items-center"
>
<span>{{ registry.address }}</span>
<IconButton
:icon="registry.readonly ? 'chevron-right' : 'edit'"
class="ml-auto w-8 h-8"
class="ml-auto h-8 w-8"
:title="registry.readonly ? $t('registries.view') : $t('registries.edit')"
@click="editRegistry(registry)"
/>
<IconButton
v-if="!registry.readonly"
icon="trash"
class="w-8 h-8 hover:text-wp-error-100"
class="hover:text-wp-error-100 h-8 w-8"
:is-loading="isDeleting"
:title="$t('registries.delete')"
@click="deleteRegistry(registry)"

View file

@ -2,11 +2,11 @@
<router-link
v-if="repo"
:to="{ name: 'repo', params: { repoId: repo.id } }"
class="flex flex-col border rounded-md bg-wp-background-100 overflow-hidden p-4 border-wp-background-400 dark:bg-wp-background-200 cursor-pointer hover:shadow-md hover:bg-wp-background-300 dark:hover:bg-wp-background-300"
class="bg-wp-background-100 border-wp-background-400 dark:bg-wp-background-200 hover:bg-wp-background-300 dark:hover:bg-wp-background-300 flex cursor-pointer flex-col overflow-hidden rounded-md border p-4 hover:shadow-md"
>
<div class="grid grid-cols-[auto,1fr] gap-y-4 items-center">
<div class="grid grid-cols-[auto,1fr] items-center gap-y-4">
<div class="text-wp-text-100 text-lg">{{ `${repo.owner} / ${repo.name}` }}</div>
<div class="ml-auto text-wp-text-100">
<div class="text-wp-text-100 ml-auto">
<div
v-if="repo.visibility === RepoVisibility.Private"
:title="`${$t('repo.visibility.visibility')}: ${$t(`repo.visibility.private.private`)}`"
@ -21,14 +21,14 @@
</div>
</div>
<div class="col-span-2 text-wp-text-100 flex w-full gap-x-4">
<div class="text-wp-text-100 col-span-2 flex w-full gap-x-4">
<template v-if="lastPipeline">
<div class="flex flex-1 min-w-0 gap-x-1 items-center">
<div class="flex min-w-0 flex-1 items-center gap-x-1">
<PipelineStatusIcon v-if="lastPipeline" :status="lastPipeline.status" />
<span class="whitespace-nowrap overflow-hidden overflow-ellipsis">{{ shortMessage }}</span>
<span class="overflow-hidden overflow-ellipsis whitespace-nowrap">{{ shortMessage }}</span>
</div>
<div class="flex flex-shrink-0 gap-x-1 items-center ml-auto">
<div class="ml-auto flex flex-shrink-0 items-center gap-x-1">
<Icon name="since" />
<span>{{ since }}</span>
</div>

View file

@ -1,8 +1,8 @@
<template>
<ListItem v-if="pipeline" class="p-0 w-full">
<div class="flex items-center w-11">
<ListItem v-if="pipeline" class="w-full p-0">
<div class="flex w-11 items-center">
<div
class="w-3 h-full"
class="h-full w-3"
:class="{
'bg-wp-state-warn-100': pipeline.status === 'pending',
'bg-wp-error-100 dark:bg-wp-error-200': pipelineStatusColors[pipeline.status] === 'red',
@ -11,25 +11,25 @@
'bg-wp-state-info-100': pipelineStatusColors[pipeline.status] === 'blue',
}"
/>
<div class="flex flex-wrap justify-between items-center w-8 h-full">
<div class="flex h-full w-8 flex-wrap items-center justify-between">
<PipelineRunningIcon v-if="pipeline.status === 'started' || pipeline.status === 'running'" />
<PipelineStatusIcon v-else class="mx-2 md:mx-3" :status="pipeline.status" />
</div>
</div>
<div class="flex py-2 px-4 flex-grow min-w-0 <md:flex-wrap">
<div class="<md:hidden flex items-center flex-shrink-0">
<div class="<md:flex-wrap flex min-w-0 flex-grow px-4 py-2">
<div class="<md:hidden flex flex-shrink-0 items-center">
<Icon v-if="pipeline.event === 'cron'" name="stopwatch" class="text-wp-text-100" />
<img v-else class="rounded-md w-6" :src="pipeline.author_avatar" />
<img v-else class="w-6 rounded-md" :src="pipeline.author_avatar" />
</div>
<div class="flex items-center md:mx-4 w-full md:w-auto min-w-0">
<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="text-wp-text-alt-100 <md:hidden">#{{ pipeline.number }}</span>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
<span class="text-wp-text-alt-100 <md:hidden mx-2">-</span>
<span
class="text-wp-text-100 <md:underline whitespace-nowrap overflow-hidden overflow-ellipsis"
class="text-wp-text-100 <md:underline overflow-hidden overflow-ellipsis whitespace-nowrap"
:title="message"
>
{{ shortMessage }}
@ -37,9 +37,9 @@
</div>
<div
class="flex-shrink-0 gap-x-4 gap-y-2 grid grid-cols-2 grid-rows-2 grid-flow-col md:ml-auto py-2 w-full md:w-96 text-wp-text-100"
class="text-wp-text-100 grid w-full flex-shrink-0 grid-flow-col grid-cols-2 grid-rows-2 gap-x-4 gap-y-2 py-2 md:ml-auto md:w-96"
>
<div class="flex items-center space-x-2 min-w-0">
<div class="flex min-w-0 items-center space-x-2">
<span :title="pipelineEventTitle">
<Icon v-if="pipeline.event === 'pull_request'" name="pull-request" />
<Icon v-else-if="pipeline.event === 'pull_request_closed'" name="pull-request-closed" />
@ -52,17 +52,17 @@
<span class="truncate">{{ prettyRef }}</span>
</div>
<div class="flex items-center space-x-2 min-w-0">
<div class="flex min-w-0 items-center space-x-2">
<Icon name="commit" />
<span class="truncate">{{ pipeline.commit.slice(0, 10) }}</span>
</div>
<div class="flex items-center space-x-2 min-w-0" :title="$t('repo.pipeline.duration')">
<div class="flex min-w-0 items-center space-x-2" :title="$t('repo.pipeline.duration')">
<Icon name="duration" />
<span class="truncate">{{ duration }}</span>
</div>
<div class="flex items-center space-x-2 min-w-0" :title="$t('repo.pipeline.created', { created })">
<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>
</div>

View file

@ -1,17 +1,17 @@
<template>
<div v-if="pipeline" class="flex flex-col pt-10 md:pt-0">
<div
class="flex flex-grow flex-col code-box shadow !p-0 !rounded-none md:mt-0 !md:rounded-md overflow-hidden"
class="code-box !md:rounded-md flex flex-grow flex-col overflow-hidden !rounded-none !p-0 shadow md:mt-0"
@mouseover="showActions = true"
@mouseleave="showActions = false"
>
<div class="<md:fixed <md:top-0 <md:left-0 flex flex-row items-center w-full bg-wp-code-100 px-4 py-2">
<span class="text-base font-bold text-wp-code-text-alt-100">
<div class="<md:fixed <md:top-0 <md:left-0 bg-wp-code-100 flex w-full flex-row items-center px-4 py-2">
<span class="text-wp-code-text-alt-100 text-base font-bold">
<span class="<md:hidden">{{ $t('repo.pipeline.log_title') }}</span>
<span class="md:hidden">{{ step?.name }}</span>
</span>
<div class="flex flex-row items-center ml-auto gap-x-2">
<div class="ml-auto flex flex-row items-center gap-x-2">
<IconButton
v-if="step?.finished !== undefined && hasLogs"
:is-loading="downloadInProgress"
@ -47,17 +47,17 @@
<div
v-show="hasLogs && loadedLogs && (log?.length || 0) > 0"
ref="consoleElement"
class="w-full max-w-full grid grid-cols-[min-content,minmax(0,1fr),min-content] p-4 auto-rows-min flex-grow overflow-x-hidden overflow-y-auto text-xs md:text-sm"
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
:id="`L${line.number}`"
:href="`#L${line.number}`"
class="text-wp-code-text-alt-100 whitespace-nowrap select-none text-right pl-2 pr-6"
class="text-wp-code-text-alt-100 select-none whitespace-nowrap pl-2 pr-6 text-right"
:class="{
'bg-opacity-40 dark:bg-opacity-50 bg-red-600 dark:bg-red-800': line.type === 'error',
'bg-opacity-40 dark:bg-opacity-50 bg-yellow-600 dark:bg-yellow-800': line.type === 'warning',
'bg-opacity-30 bg-blue-600': isSelected(line),
'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),
underline: isSelected(line),
}"
>
@ -65,21 +65,21 @@
</a>
<!-- eslint-disable vue/no-v-html -->
<span
class="align-top whitespace-pre-wrap break-words"
class="whitespace-pre-wrap break-words align-top"
:class="{
'bg-opacity-40 dark:bg-opacity-50 bg-10.168.64.121-600 dark:bg-red-800': line.type === 'error',
'bg-opacity-40 dark:bg-opacity-50 bg-yellow-600 dark:bg-yellow-800': line.type === 'warning',
'bg-opacity-30 bg-blue-600': isSelected(line),
'bg-10.168.64.121-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),
}"
v-html="line.text"
/>
<!-- eslint-enable vue/no-v-html -->
<span
class="text-wp-code-text-alt-100 whitespace-nowrap select-none text-right pr-1"
class="text-wp-code-text-alt-100 select-none whitespace-nowrap pr-1 text-right"
:class="{
'bg-opacity-40 dark:bg-opacity-50 bg-red-600 dark:bg-red-800': line.type === 'error',
'bg-opacity-40 dark:bg-opacity-50 bg-yellow-600 dark:bg-yellow-800': line.type === 'warning',
'bg-opacity-30 bg-blue-600': isSelected(line),
'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) }}
@ -87,7 +87,7 @@
</div>
</div>
<div class="m-auto text-xl text-wp-text-alt-100">
<div class="text-wp-text-alt-100 m-auto text-xl">
<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>
@ -96,7 +96,7 @@
<div
v-if="step?.finished !== undefined"
class="flex items-center w-full bg-wp-code-100 text-md text-wp-code-text-alt-100 p-4 font-bold"
class="bg-wp-code-100 text-md text-wp-code-text-alt-100 flex w-full items-center p-4 font-bold"
>
<PipelineStatusIcon :status="step.state" class="!h-4 !w-4" />
<span v-if="step?.error" class="px-2">{{ step.error }}</span>

View file

@ -1,6 +1,6 @@
<template>
<div
class="flex justify-center items-center"
class="flex items-center justify-center"
:title="$t('repo.pipeline.status.status', { status: statusDescriptions[status] })"
>
<Icon

View file

@ -1,18 +1,18 @@
<template>
<div class="flex flex-col w-full md:w-3/12 md:max-w-md md:min-w-xs text-wp-text-100 gap-2 pb-2">
<div class="md:min-w-xs text-wp-text-100 flex w-full flex-col gap-2 pb-2 md:w-3/12 md:max-w-md">
<div
class="flex flex-wrap p-4 gap-1 justify-between flex-shrink-0 rounded-md border bg-wp-background-100 border-wp-background-400 dark:bg-wp-background-200"
class="border-wp-background-400 bg-wp-background-100 dark:bg-wp-background-200 flex flex-shrink-0 flex-wrap justify-between gap-1 rounded-md border p-4"
>
<div class="flex space-x-1 items-center flex-shrink-0">
<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="rounded-md w-6" :src="pipeline.author_avatar" />
<img v-else class="w-6 rounded-md" :src="pipeline.author_avatar" />
</div>
<span>{{ pipeline.author }}</span>
</div>
<a
v-if="pipeline.event === 'pull_request' || pipeline.event === 'pull_request_closed'"
class="flex items-center space-x-1 text-wp-link-100 hover:text-wp-link-200 min-w-0"
class="text-wp-link-100 hover:text-wp-link-200 flex min-w-0 items-center space-x-1"
:href="pipeline.forge_url"
>
<Icon name="pull-request" />
@ -20,7 +20,7 @@
</a>
<router-link
v-else-if="pipeline.event === 'push' || pipeline.event === 'manual' || pipeline.event === 'deployment'"
class="flex items-center space-x-1 text-wp-link-100 hover:text-wp-link-200 min-w-0"
class="text-wp-link-100 hover:text-wp-link-200 flex min-w-0 items-center space-x-1"
:to="{ name: 'repo-branch', params: { branch: prettyRef } }"
>
<Icon v-if="pipeline.event === 'manual'" name="manual-pipeline" />
@ -28,12 +28,12 @@
<Icon v-else-if="pipeline.event === 'deployment'" name="deployment" />
<span class="truncate">{{ prettyRef }}</span>
</router-link>
<div v-else class="flex space-x-1 items-center min-w-0">
<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>
</div>
<div class="flex items-center flex-shrink-0">
<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>
@ -54,15 +54,15 @@
<span>{{ $t('repo.pipeline.no_pipeline_steps') }}</span>
</Panel>
<div class="flex-grow min-h-0 w-full relative">
<div class="absolute top-0 left-0 right-0 h-full flex flex-col md:overflow-y-auto gap-y-2">
<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="p-2 rounded-md shadow border bg-wp-background-100 border-wp-background-400 dark:bg-wp-background-200"
class="border-wp-background-400 bg-wp-background-100 dark:bg-wp-background-200 rounded-md border p-2 shadow"
>
<div class="flex flex-col gap-2">
<div v-if="workflow.environ" class="flex flex-wrap gap-x-1 gap-y-2 text-xs justify-end pt-1 pr-1">
<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>
@ -71,25 +71,25 @@
v-if="!singleConfig"
type="button"
:title="workflow.name"
class="flex items-center gap-2 py-2 px-1 hover-effect hover:bg-wp-background-300 dark:hover:bg-wp-background-400 rounded-md"
class="hover:bg-wp-background-300 dark:hover:bg-wp-background-400 hover-effect flex items-center gap-2 rounded-md px-1 py-2"
@click="workflowsCollapsed[workflow.id] = !workflowsCollapsed[workflow.id]"
>
<Icon
name="chevron-right"
class="transition-transform duration-150 min-w-6 h-6"
:class="{ 'transform rotate-90': !workflowsCollapsed[workflow.id] }"
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
v-if="workflow.started !== workflow.finished"
:workflow="workflow"
class="mr-1 pr-2px"
class="pr-2px mr-1"
/>
</button>
</div>
<div
class="transition-height duration-150 overflow-hidden"
class="transition-height overflow-hidden duration-150"
:class="{ 'max-h-0': workflowsCollapsed[workflow.id], 'ml-[1.6rem]': !singleConfig }"
>
<button
@ -97,7 +97,7 @@
:key="step.pid"
type="button"
:title="step.name"
class="flex p-2 gap-2 border-2 border-transparent rounded-md items-center hover-effect hover:bg-wp-background-300 dark:hover:bg-wp-background-400 w-full"
class="hover:bg-wp-background-300 dark:hover:bg-wp-background-400 hover-effect flex w-full items-center gap-2 rounded-md border-2 border-transparent p-2"
:class="{
'bg-wp-background-300 dark:bg-wp-background-400': selectedStepId && selectedStepId === step.pid,
'mt-1': !singleConfig || (workflow.children && step.pid !== workflow.children[0].pid),

View file

@ -22,7 +22,7 @@
</InputField>
<InputField v-slot="{ id }" :label="$t('secrets.plugins.images')">
<span class="ml-1 mb-2 text-wp-text-alt-100">{{ $t('secrets.plugins.desc') }}</span>
<span class="text-wp-text-alt-100 mb-2 ml-1">{{ $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">

View file

@ -1,9 +1,9 @@
<template>
<div class="space-y-4 text-wp-text-100">
<div class="text-wp-text-100 space-y-4">
<ListItem
v-for="secret in secrets"
:key="secret.id"
class="items-center !bg-wp-background-200 !dark:bg-wp-background-100"
class="!bg-wp-background-200 !dark:bg-wp-background-100 items-center"
>
<span>{{ secret.name }}</span>
<Badge
@ -11,19 +11,19 @@
class="ml-2"
:label="secret.org_id === 0 ? $t('global_level_secret') : $t('org_level_secret')"
/>
<div class="ml-auto space-x-2 <md:hidden">
<div class="<md:hidden ml-auto space-x-2">
<Badge v-for="event in secret.events" :key="event" :label="event" />
</div>
<template v-if="secret.edit !== false">
<IconButton
icon="edit"
class="ml-2 <md:ml-auto w-8 h-8"
class="<md:ml-auto ml-2 h-8 w-8"
:title="$t('secrets.edit')"
@click="editSecret(secret)"
/>
<IconButton
icon="trash"
class="ml-2 w-8 h-8 hover:text-wp-error-100"
class="hover:text-wp-error-100 ml-2 h-8 w-8"
:is-loading="isDeleting"
:title="$t('secrets.delete')"
@click="deleteSecret(secret)"

View file

@ -107,7 +107,7 @@ body,
}
.vue-notification .notification-title {
@apply font-normal text-base;
@apply text-base font-normal;
}
.vue-notification.success {
@ -119,7 +119,7 @@ body,
}
*::-webkit-scrollbar {
@apply bg-transparent w-12px h-12px;
@apply w-12px h-12px bg-transparent;
}
* {
@ -129,7 +129,7 @@ body,
*::-webkit-scrollbar-thumb {
transition: background 0.2s ease-in-out;
border: 3px solid transparent;
@apply bg-clip-content bg-cool-gray-200 dark:bg-dark-200 rounded-full;
@apply bg-cool-gray-200 dark:bg-dark-200 rounded-full bg-clip-content;
}
*::-webkit-scrollbar-thumb:hover {
@ -141,11 +141,11 @@ body,
}
.code-box {
@apply bg-wp-code-200 p-4 rounded-md text-sm text-wp-code-text-100 break-words;
@apply bg-wp-code-200 text-wp-code-text-100 break-words rounded-md p-4 text-sm;
white-space: pre-wrap;
}
.code-box-inline,
code:not(pre > code) {
@apply bg-wp-code-200 px-1 py-px rounded-md text-wp-code-text-100;
@apply bg-wp-code-200 text-wp-code-text-100 rounded-md px-1 py-px;
}

View file

@ -1,26 +1,26 @@
<template>
<main class="flex flex-col w-full h-full justify-center items-center">
<Error v-if="errorMessage" class="w-full md:w-3xl">
<main class="flex h-full w-full flex-col items-center justify-center">
<Error v-if="errorMessage" class="md:w-3xl w-full">
<span class="whitespace-pre">{{ errorMessage }}</span>
<span v-if="errorDescription" class="whitespace-pre mt-1">{{ errorDescription }}</span>
<span v-if="errorDescription" class="mt-1 whitespace-pre">{{ errorDescription }}</span>
<a
v-if="errorUri"
:href="errorUri"
target="_blank"
class="text-wp-link-100 hover:text-wp-link-200 cursor-pointer mt-1"
class="text-wp-link-100 hover:text-wp-link-200 mt-1 cursor-pointer"
>
<span>{{ errorUri }}</span>
</a>
</Error>
<div
class="flex flex-col w-full overflow-hidden bg-wp-background-100 shadow border border-wp-background-400 dark:bg-wp-background-200 md:m-8 md:rounded-md md:flex-row md:w-3xl md:h-sm"
class="bg-wp-background-100 border-wp-background-400 dark:bg-wp-background-200 md:w-3xl md:h-sm flex w-full flex-col overflow-hidden border shadow md:m-8 md:flex-row md:rounded-md"
>
<div class="flex justify-center items-center bg-wp-primary-200 dark:bg-wp-primary-300 min-h-48 md:w-3/5">
<WoodpeckerLogo preserveAspectRatio="xMinYMin slice" class="w-30 h-30 md:w-48 md:h-48" />
<div class="bg-wp-primary-200 dark:bg-wp-primary-300 flex min-h-48 items-center justify-center md:w-3/5">
<WoodpeckerLogo preserveAspectRatio="xMinYMin slice" class="w-30 h-30 md:h-48 md:w-48" />
</div>
<div class="flex justify-center items-center flex-col md:w-2/5 min-h-48 gap-4 text-center">
<h1 class="text-xl text-wp-text-100">{{ $t('welcome') }}</h1>
<div class="flex min-h-48 flex-col items-center justify-center gap-4 text-center md:w-2/5">
<h1 class="text-wp-text-100 text-xl">{{ $t('welcome') }}</h1>
<div class="flex flex-col gap-2">
<Button
v-for="forge in forges"

View file

@ -1,6 +1,6 @@
<template>
<div class="flex flex-col h-full w-full items-center justify-center">
<p class="text-2xl mb-8">{{ $t('not_found.not_found') }}</p>
<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>

View file

@ -13,7 +13,7 @@
: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 v-if="repo.active" class="text-wp-text-alt-100 ml-auto">{{ $t('repo.enable.enabled') }}</span>
<div v-else class="ml-auto flex items-center">
<Badge v-if="repo.id" class="<md:hidden mr-2" :label="$t('repo.enable.disabled')" />
<Button
@ -24,7 +24,7 @@
</div>
</ListItem>
</template>
<div v-else-if="loading" class="flex justify-center text-wp-text-100">
<div v-else-if="loading" class="text-wp-text-100 flex justify-center">
<Icon name="spinner" />
</div>
</div>

View file

@ -9,8 +9,8 @@
</template>
<Transition name="fade" mode="out-in">
<div v-if="search === '' && repos.length > 0" class="gap-8 grid">
<div v-if="reposLastAccess.length > 0" class="gap-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2">
<div v-if="search === '' && repos.length > 0" class="grid gap-8">
<div v-if="reposLastAccess.length > 0" 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" />
</div>
@ -25,7 +25,7 @@
<div v-if="reposLastActivity.length > 0" class="flex flex-col gap-4">
<RepoItem v-for="repo in reposLastActivity" :key="repo.id" :repo="repo" />
</div>
<span v-else class="text-wp-text-100 text-lg text-center">{{ $t('no_search_results') }}</span>
<span v-else class="text-wp-text-100 text-center text-lg">{{ $t('no_search_results') }}</span>
</div>
</Transition>
</Scaffold>

View file

@ -1,9 +1,9 @@
<template>
<Settings :title="$t('info')">
<div class="flex flex-col items-center gap-4">
<WoodpeckerLogo class="w-32 h-32 fill-wp-text-200" />
<WoodpeckerLogo class="fill-wp-text-200 h-32 w-32" />
<i18n-t keypath="running_version" tag="p" class="text-xl text-center">
<i18n-t keypath="running_version" tag="p" class="text-center text-xl">
<span class="font-bold">{{ version?.current }}</span>
</i18n-t>

View file

@ -1,28 +1,28 @@
<template>
<Settings :title="$t('admin.settings.orgs.orgs')" :description="$t('admin.settings.orgs.desc')">
<div class="space-y-4 text-wp-text-100">
<div class="text-wp-text-100 space-y-4">
<ListItem
v-for="org in orgs"
:key="org.id"
class="items-center gap-2 !bg-wp-background-200 !dark:bg-wp-background-100"
class="!bg-wp-background-200 !dark:bg-wp-background-100 items-center gap-2"
>
<span>{{ org.name }}</span>
<IconButton
icon="chevron-right"
:title="$t('admin.settings.orgs.view')"
class="ml-auto w-8 h-8"
class="ml-auto h-8 w-8"
:to="{ name: 'org', params: { orgId: org.id } }"
/>
<IconButton
icon="settings-outline"
:title="$t('admin.settings.orgs.org_settings')"
class="w-8 h-8"
class="h-8 w-8"
:to="{ name: 'org-settings', params: { orgId: org.id } }"
/>
<IconButton
icon="trash"
:title="$t('admin.settings.orgs.delete_org')"
class="ml-2 w-8 h-8 hover:text-wp-error-100"
class="hover:text-wp-error-100 ml-2 h-8 w-8"
:is-loading="isDeleting"
@click="deleteOrg(org)"
/>

View file

@ -12,7 +12,7 @@
<Button v-else :text="$t('admin.settings.queue.pause')" start-icon="pause" @click="pauseQueue" />
<Icon
:name="queueInfo.paused ? 'pause' : 'play'"
class="w-6 h-6"
class="h-6 w-6"
:class="{
'text-wp-error-100': queueInfo.paused,
'text-wp-text-100': !queueInfo.paused,
@ -26,11 +26,11 @@
<AdminQueueStats :stats="queueInfo?.stats" />
<div v-if="tasks.length > 0" class="flex flex-col">
<p class="mt-6 mb-2 text-xl">{{ $t('admin.settings.queue.tasks') }}</p>
<p class="mb-2 mt-6 text-xl">{{ $t('admin.settings.queue.tasks') }}</p>
<ListItem
v-for="task in tasks"
:key="task.id"
class="items-center !bg-wp-background-200 !dark:bg-wp-background-100 mb-2"
class="!bg-wp-background-200 !dark:bg-wp-background-100 mb-2 items-center"
>
<div
class="flex items-center"
@ -58,7 +58,7 @@
/>
</div>
<span class="ml-2">{{ task.id }}</span>
<span class="flex gap-2 ml-auto">
<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" />

View file

@ -15,7 +15,7 @@
</template>
<template #headerEnd>
<Warning class="text-sm mt-4" :text="$t('admin.settings.registries.warning')" />
<Warning class="mt-4 text-sm" :text="$t('admin.settings.registries.warning')" />
</template>
<RegistryList

View file

@ -9,25 +9,25 @@
/>
</template>
<div class="space-y-4 text-wp-text-100">
<div class="text-wp-text-100 space-y-4">
<ListItem
v-for="repo in repos"
:key="repo.id"
class="items-center gap-2 !bg-wp-background-200 !dark:bg-wp-background-100"
class="!bg-wp-background-200 !dark:bg-wp-background-100 items-center gap-2"
>
<span>{{ repo.full_name }}</span>
<div class="flex items-center ml-auto">
<div class="ml-auto flex items-center">
<Badge v-if="!repo.active" class="<md:hidden mr-2" :label="$t('admin.settings.repos.disabled')" />
<IconButton
icon="chevron-right"
:title="$t('admin.settings.repos.view')"
class="w-8 h-8"
class="h-8 w-8"
:to="{ name: 'repo', params: { repoId: repo.id } }"
/>
<IconButton
icon="settings-outline"
:title="$t('admin.settings.repos.settings')"
class="w-8 h-8"
class="h-8 w-8"
:to="{ name: 'repo-settings', params: { repoId: repo.id } }"
/>
</div>

View file

@ -10,7 +10,7 @@
</template>
<template #headerEnd>
<Warning class="text-sm mt-4" :text="$t('admin.settings.secrets.warning')" />
<Warning class="mt-4 text-sm" :text="$t('admin.settings.secrets.warning')" />
</template>
<SecretList

View file

@ -10,30 +10,30 @@
<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">
<div v-if="!selectedUser" class="text-wp-text-100 space-y-4">
<ListItem
v-for="user in users"
:key="user.id"
class="items-center gap-2 !bg-wp-background-200 !dark:bg-wp-background-100"
class="!bg-wp-background-200 !dark:bg-wp-background-100 items-center gap-2"
>
<img v-if="user.avatar_url" class="rounded-md h-6" :src="user.avatar_url" />
<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:inline-block hidden ml-auto"
class="ml-auto hidden md:inline-block"
:label="$t('admin.settings.users.admin.admin')"
/>
<IconButton
icon="edit"
:title="$t('admin.settings.users.edit_user')"
class="w-8 h-8 <md:ml-auto"
class="<md:ml-auto h-8 w-8"
:class="{ 'ml-auto': !user.admin, 'ml-2': user.admin }"
@click="editUser(user)"
/>
<IconButton
icon="trash"
:title="$t('admin.settings.users.delete_user')"
class="ml-2 w-8 h-8 hover:text-wp-error-100"
class="hover:text-wp-error-100 ml-2 h-8 w-8"
:is-loading="isDeleting"
@click="deleteUser(user)"
/>
@ -53,7 +53,7 @@
<InputField v-slot="{ id }" :label="$t('admin.settings.users.avatar_url')">
<div class="flex gap-2">
<img v-if="selectedUser.avatar_url" class="rounded-md w-8 h-8" :src="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>

View file

@ -1,7 +1,7 @@
<template>
<div class="flex flex-col gap-4 m-auto">
<div class="text-center text-wp-text-100">
<WoodpeckerLogo preserveAspectRatio="xMinYMin slice" class="w-32 m-auto mb-8" />
<div class="m-auto flex flex-col gap-4">
<div class="text-wp-text-100 text-center">
<WoodpeckerLogo 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>
@ -11,16 +11,16 @@
<p class="text-2xl">{{ $t('return_to_cli') }}</p>
</template>
<template v-else-if="state === 'failed'">
<h1 class="text-4xl font-bold mt-4">{{ $t('cli_login_failed') }}</h1>
<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'">
<h1 class="text-4xl font-bold mt-4">{{ $t('cli_login_denied') }}</h1>
<h1 class="mt-4 text-4xl font-bold">{{ $t('cli_login_denied') }}</h1>
<p class="text-2xl">{{ $t('return_to_cli') }}</p>
</template>
</div>
<div v-if="state === 'confirm'" class="flex gap-4 justify-center">
<div v-if="state === 'confirm'" class="flex justify-center gap-4">
<Button :text="$t('login_to_cli')" color="green" @click="sendToken(false)" />
<Button :text="$t('abort')" color="red" @click="abortLogin" />
</div>

View file

@ -1,5 +1,5 @@
<template>
<div class="flex w-full mb-4 justify-center">
<div class="mb-4 flex w-full justify-center">
<span class="text-wp-text-100 text-xl">{{ $t('repo.pipeline.pipelines_for', { branch }) }}</span>
</div>
<PipelineList :pipelines="pipelines" :repo="repo" />

View file

@ -11,7 +11,7 @@
<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">
<div v-else-if="loading" class="text-wp-text-100 flex justify-center">
<Icon name="spinner" />
</div>
<Panel v-else class="flex justify-center">

View file

@ -1,12 +1,12 @@
<template>
<Panel v-if="!loading">
<form @submit.prevent="triggerManualPipeline">
<span class="text-xl text-wp-text-100">{{ $t('repo.manual_pipeline.title') }}</span>
<span class="text-wp-text-100 text-xl">{{ $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="text-sm text-wp-text-alt-100 mb-2">{{ $t('repo.manual_pipeline.variables.desc') }}</span>
<span class="text-wp-text-alt-100 mb-2 text-sm">{{ $t('repo.manual_pipeline.variables.desc') }}</span>
<KeyValueEditor
:id="id"
v-model="payload.variables"
@ -19,7 +19,7 @@
<Button type="submit" :text="$t('repo.manual_pipeline.trigger')" :disabled="!isFormValid" />
</form>
</Panel>
<div v-else class="flex justify-center text-wp-text-100">
<div v-else class="text-wp-text-100 flex justify-center">
<Icon name="spinner" />
</div>
</template>

View file

@ -1,5 +1,5 @@
<template>
<div class="flex w-full mb-4 justify-center">
<div class="mb-4 flex w-full justify-center">
<span class="text-wp-text-100 text-xl">{{ $t('repo.pipeline.pipelines_for_pr', { index: pullRequest }) }}</span>
</div>
<PipelineList :pipelines="pipelines" :repo="repo" />

View file

@ -11,12 +11,12 @@
<span class="text-wp-text-alt-100 <md:hidden">#{{ pullRequest.index }}</span>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
<span class="text-wp-text-alt-100 <md:hidden mx-2">-</span>
<span class="text-wp-text-100 <md:underline whitespace-nowrap overflow-hidden overflow-ellipsis">{{
<span class="text-wp-text-100 <md:underline overflow-hidden overflow-ellipsis whitespace-nowrap">{{
pullRequest.title
}}</span>
</ListItem>
</template>
<div v-else-if="loading" class="flex justify-center text-wp-text-100">
<div v-else-if="loading" class="text-wp-text-100 flex justify-center">
<Icon name="spinner" />
</div>
<Panel v-else class="flex justify-center">

View file

@ -14,7 +14,7 @@
<a v-if="badgeUrl" :href="badgeUrl" target="_blank">
<img class="w-28" :src="badgeUrl" />
</a>
<IconButton :href="repo.forge_url" :title="$t('repo.open_in_forge')" :icon="forgeIcon" class="w-8 h-8 forge" />
<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' }"

View file

@ -1,17 +1,17 @@
<template>
<Container full-width class="flex flex-col md:flex-grow flex-grow-0 md:px-4 md:min-h-xs">
<div class="flex flex-wrap-reverse md:flex-nowrap flex-grow gap-4 w-full min-h-0">
<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 gap-4 md:flex-nowrap">
<PipelineStepList
v-model:selected-step-id="selectedStepId"
:class="{ 'hidden md:flex': pipeline!.status === 'blocked' }"
:pipeline="pipeline!"
/>
<div class="relative flex flex-grow justify-center items-start basis-full md:basis-auto">
<div class="relative flex flex-grow basis-full items-start justify-center md:basis-auto">
<Container v-if="pipeline!.errors?.some((e) => !e.is_warning)" fill-width class="p-0">
<Panel>
<div class="flex flex-col items-center gap-4 text-center">
<Icon name="status-error" class="w-16 h-16 text-wp-error-100" size="1.5rem" />
<Icon name="status-error" class="text-wp-error-100 h-16 w-16" 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>
@ -21,9 +21,9 @@
<Container v-else-if="pipeline!.status === 'blocked'" fill-width class="p-0">
<Panel>
<div class="flex flex-col items-center gap-4">
<Icon name="status-blocked" size="1.5rem" class="w-16 h-16" />
<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 justify-center items-center gap-2">
<div v-if="repoPermissions!.push" class="flex flex-wrap items-center justify-center gap-2">
<Button
color="green"
:text="$t('repo.pipeline.protected.approve')"
@ -44,7 +44,7 @@
<Container v-else-if="pipeline!.status === 'declined'" fill-width class="p-0">
<Panel>
<div class="flex flex-col items-center gap-4">
<Icon name="status-declined" size="1.5rem" class="w-16 h-16 text-wp-error-100" />
<Icon name="status-declined" size="1.5rem" class="text-wp-error-100 h-16 w-16" />
<p class="text-xl">{{ $t('repo.pipeline.protected.declined') }}</p>
</div>
</Panel>
@ -54,7 +54,7 @@
v-else-if="selectedStepId !== null"
v-model:step-id="selectedStepId"
:pipeline="pipeline!"
class="top-0 left-0 fixed md:absolute w-full h-full"
class="fixed left-0 top-0 h-full w-full md:absolute"
/>
</div>
</div>

View file

@ -1,6 +1,6 @@
<template>
<Panel>
<ul class="list-disc list-inside w-full">
<ul class="w-full list-inside list-disc">
<li v-for="file in pipeline!.changed_files" :key="file">{{ file }}</li>
</ul>
</Panel>

View file

@ -7,7 +7,7 @@
collapsed-by-default
:title="pipelineConfigsDecoded && pipelineConfigsDecoded.length > 1 ? pipelineConfig.name : ''"
>
<SyntaxHighlight class="font-mono whitespace-pre overflow-auto" language="yaml" :code="pipelineConfig.data" />
<SyntaxHighlight class="overflow-auto whitespace-pre font-mono" language="yaml" :code="pipelineConfig.data" />
</Panel>
</div>
</template>

View file

@ -2,7 +2,7 @@
<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>
<p class="text-wp-text-alt-100 mb-2 text-sm">{{ $t('repo.pipeline.debug.metadata_exec_desc') }}</p>
<pre class="code-box">{{ cliExecWithMetadata }}</pre>
</InputField>
<div class="flex items-center space-x-4">
@ -10,9 +10,9 @@
</div>
</Panel>
</template>
<div v-else class="flex justify-center items-center h-full">
<div class="bg-wp-error-100 dark:bg-wp-error-200 shadow-lg p-8 rounded-lg text-center">
<p class="font-bold text-2xl text-white">{{ $t('repo.pipeline.debug.no_permission') }}</p>
<div v-else class="flex h-full items-center justify-center">
<div class="bg-wp-error-100 dark:bg-wp-error-200 rounded-lg p-8 text-center shadow-lg">
<p class="text-2xl font-bold text-white">{{ $t('repo.pipeline.debug.no_permission') }}</p>
</div>
</div>
</template>

View file

@ -7,7 +7,7 @@
<span class="flex items-center gap-x-2">
<Icon
name="alert"
class="flex-shrink-0 my-1"
class="my-1 flex-shrink-0"
:class="{
'text-wp-state-warn-100': error.is_warning,
'text-wp-error-100': !error.is_warning,
@ -35,7 +35,7 @@
</span>
<span v-else />
</div>
<div class="grid grid-cols-[minmax(10rem,auto),4fr] col-start-2">
<div class="col-start-2 grid grid-cols-[minmax(10rem,auto),4fr]">
<span />
<span>
<RenderMarkdown :content="error.message" />

View file

@ -18,13 +18,13 @@
</template>
<template #headerActions>
<div class="flex md:flex-row flex-col md:justify-between md:items-center gap-2 min-w-0">
<div class="flex content-start gap-2 min-w-0">
<div class="flex min-w-0 flex-col gap-2 md:flex-row md:items-center md:justify-between">
<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="md:inline-block hidden">-</span>
<span class="min-w-0 whitespace-nowrap overflow-ellipsis overflow-hidden" :title="message">{{
<span class="hidden md:inline-block">-</span>
<span class="min-w-0 overflow-hidden overflow-ellipsis whitespace-nowrap" :title="message">{{
shortMessage
}}</span>
</div>

View file

@ -2,7 +2,7 @@
<Settings :title="$t('repo.settings.actions.actions')">
<div class="flex flex-wrap items-center">
<Button
class="mr-4 my-1"
class="my-1 mr-4"
color="blue"
start-icon="heal"
:is-loading="isRepairingRepo"
@ -13,7 +13,7 @@
<Button
v-if="isActive"
color="blue"
class="mr-4 my-1"
class="my-1 mr-4"
start-icon="turn-off"
:is-loading="isDeactivatingRepo"
:text="$t('repo.settings.actions.disable.disable')"
@ -21,7 +21,7 @@
/>
<Button
v-else
class="mr-4 my-1"
class="my-1 mr-4"
color="blue"
start-icon="turn-off"
:is-loading="isActivatingRepo"
@ -30,7 +30,7 @@
/>
<Button
class="mr-4 my-1"
class="my-1 mr-4"
color="red"
start-icon="trash"
:is-loading="isDeletingRepo"

View file

@ -14,30 +14,30 @@
<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">
<div v-if="!selectedCron" class="text-wp-text-100 space-y-4">
<ListItem
v-for="cron in crons"
:key="cron.id"
class="items-center !bg-wp-background-200 !dark:bg-wp-background-100"
class="!bg-wp-background-200 !dark:bg-wp-background-100 items-center"
>
<span class="grid grid-cols-3 w-full">
<span class="grid w-full grid-cols-3">
<span>{{ cron.name }}</span>
<span v-if="cron.next_exec && cron.next_exec > 0" class="col-span-2 <md:hidden">
<span v-if="cron.next_exec && cron.next_exec > 0" class="<md:hidden col-span-2">
<!-- 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="col-span-2 <md:hidden">{{ $t('repo.settings.crons.not_executed_yet') }}</span>
<span v-else class="<md:hidden col-span-2">{{ $t('repo.settings.crons.not_executed_yet') }}</span>
</span>
<IconButton
icon="play-outline"
class="ml-auto w-8 h-8"
class="ml-auto h-8 w-8"
:title="$t('repo.settings.crons.run')"
@click="runCron(cron)"
/>
<IconButton icon="edit" class="w-8 h-8" :title="$t('repo.settings.crons.edit')" @click="selectedCron = cron" />
<IconButton icon="edit" class="h-8 w-8" :title="$t('repo.settings.crons.edit')" @click="selectedCron = cron" />
<IconButton
icon="trash"
class="w-8 h-8 hover:text-wp-error-100"
class="hover:text-wp-error-100 h-8 w-8"
:is-loading="isDeleting"
:title="$t('repo.settings.crons.delete')"
@click="deleteCron(cron)"

View file

@ -22,7 +22,7 @@
:label="$t('repo.settings.general.netrc_only_trusted.netrc_only_trusted')"
docs-url="docs/usage/project-settings#custom-trusted-clone-plugins"
>
<span class="ml-1 mb-2 text-wp-text-alt-100">{{ $t('repo.settings.general.netrc_only_trusted.desc') }}</span>
<span class="text-wp-text-alt-100 mb-2 ml-1">{{ $t('repo.settings.general.netrc_only_trusted.desc') }}</span>
<div class="flex flex-col gap-2">
<div v-for="image in repoSettings.netrc_trusted" :key="image" class="flex gap-2">
@ -99,7 +99,7 @@
>
<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>
<span class="text-wp-text-alt-100 ml-4">{{ $t('repo.settings.general.timeout.minutes') }}</span>
</div>
</InputField>
@ -115,7 +115,7 @@
/>
</template>
<template #description>
<i18n-t keypath="repo.settings.general.pipeline_path.desc" tag="p" class="text-sm text-wp-text-alt-100">
<i18n-t keypath="repo.settings.general.pipeline_path.desc" tag="p" class="text-wp-text-alt-100 text-sm">
<span class="code-box-inline">{{ $t('repo.settings.general.pipeline_path.desc_path_example') }}</span>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
<span class="code-box-inline">/</span>

View file

@ -2,7 +2,7 @@
<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">{{
<a :href="cliDownload" target="_blank" class="text-wp-link-100 hover:text-wp-link-200 ml-4">{{
$t('user.settings.cli_and_api.download_cli')
}}</a>
</template>
@ -22,7 +22,7 @@
v-if="enableSwagger"
:href="`${address}/swagger/index.html`"
target="_blank"
class="ml-4 text-wp-link-100 hover:text-wp-link-200"
class="text-wp-link-100 hover:text-wp-link-200 ml-4"
>
{{ $t('user.settings.cli_and_api.swagger_ui') }}
</a>