Replace linter icons to match theme (#2765)

@qwerty287 @anbraten What do you think about this approach? This way the
icons fit more into the existing design. I've also moved the icon in the
tab to the end as this looks IMO a bit better on mobile view, but open
for discussions.


![image](https://github.com/woodpecker-ci/woodpecker/assets/3391958/f56a9688-4ca2-4b7b-a053-3e74effe6976)
<img
src="https://github.com/woodpecker-ci/woodpecker/assets/3391958/93cd4dd6-4e22-4210-9fee-f8d134d3df42"
width=350> <img
src="https://github.com/woodpecker-ci/woodpecker/assets/3391958/6128fec9-3dc5-4483-abde-5a911b236138"
width=350>

Alternative idea for errors:

<img
src="https://github.com/woodpecker-ci/woodpecker/assets/3391958/bee8b1ea-8d27-43cc-9fb1-2df0031d3551"
width=350>

Or just use one symbol and only change the color for errors/warnings?
This commit is contained in:
Robert Kaussow 2023-11-08 23:03:36 +01:00 committed by GitHub
parent 6ff2e7c97f
commit 4c2dbca2e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 45 additions and 20 deletions

6
web/components.d.ts vendored
View file

@ -23,7 +23,6 @@ declare module 'vue' {
Checkbox: typeof import('./src/components/form/Checkbox.vue')['default'] Checkbox: typeof import('./src/components/form/Checkbox.vue')['default']
CheckboxesField: typeof import('./src/components/form/CheckboxesField.vue')['default'] CheckboxesField: typeof import('./src/components/form/CheckboxesField.vue')['default']
Container: typeof import('./src/components/layout/Container.vue')['default'] Container: typeof import('./src/components/layout/Container.vue')['default']
copy: typeof import('./src/components/admin/settings/AdminAgentsTab copy.vue')['default']
CronTab: typeof import('./src/components/repo/settings/CronTab.vue')['default'] CronTab: typeof import('./src/components/repo/settings/CronTab.vue')['default']
DeployPipelinePopup: typeof import('./src/components/layout/popups/DeployPipelinePopup.vue')['default'] DeployPipelinePopup: typeof import('./src/components/layout/popups/DeployPipelinePopup.vue')['default']
DocsLink: typeof import('./src/components/atomic/DocsLink.vue')['default'] DocsLink: typeof import('./src/components/atomic/DocsLink.vue')['default']
@ -31,9 +30,13 @@ declare module 'vue' {
Header: typeof import('./src/components/layout/scaffold/Header.vue')['default'] Header: typeof import('./src/components/layout/scaffold/Header.vue')['default']
IBiCheckCircleFill: typeof import('~icons/bi/check-circle-fill')['default'] IBiCheckCircleFill: typeof import('~icons/bi/check-circle-fill')['default']
IBiCircle: typeof import('~icons/bi/circle')['default'] IBiCircle: typeof import('~icons/bi/circle')['default']
IBiExclamationCircleFill: typeof import('~icons/bi/exclamation-circle-fill')['default']
IBiExclamationTriangle: typeof import('~icons/bi/exclamation-triangle')['default']
IBiExclamationTriangleFill: typeof import('~icons/bi/exclamation-triangle-fill')['default']
IBiPlayCircleFill: typeof import('~icons/bi/play-circle-fill')['default'] IBiPlayCircleFill: typeof import('~icons/bi/play-circle-fill')['default']
IBiSlashCircleFill: typeof import('~icons/bi/slash-circle-fill')['default'] IBiSlashCircleFill: typeof import('~icons/bi/slash-circle-fill')['default']
IBiStopCircleFill: typeof import('~icons/bi/stop-circle-fill')['default'] IBiStopCircleFill: typeof import('~icons/bi/stop-circle-fill')['default']
IBiX: typeof import('~icons/bi/x')['default']
IBiXCircleFill: typeof import('~icons/bi/x-circle-fill')['default'] IBiXCircleFill: typeof import('~icons/bi/x-circle-fill')['default']
IBxBxPowerOff: typeof import('~icons/bx/bx-power-off')['default'] IBxBxPowerOff: typeof import('~icons/bx/bx-power-off')['default']
ICarbonCloseOutline: typeof import('~icons/carbon/close-outline')['default'] ICarbonCloseOutline: typeof import('~icons/carbon/close-outline')['default']
@ -83,7 +86,6 @@ declare module 'vue' {
Panel: typeof import('./src/components/layout/Panel.vue')['default'] Panel: typeof import('./src/components/layout/Panel.vue')['default']
PipelineFeedItem: typeof import('./src/components/pipeline-feed/PipelineFeedItem.vue')['default'] PipelineFeedItem: typeof import('./src/components/pipeline-feed/PipelineFeedItem.vue')['default']
PipelineFeedSidebar: typeof import('./src/components/pipeline-feed/PipelineFeedSidebar.vue')['default'] PipelineFeedSidebar: typeof import('./src/components/pipeline-feed/PipelineFeedSidebar.vue')['default']
PipelineInfo: typeof import('./src/components/repo/pipeline/PipelineInfo.vue')['default']
PipelineItem: typeof import('./src/components/repo/pipeline/PipelineItem.vue')['default'] PipelineItem: typeof import('./src/components/repo/pipeline/PipelineItem.vue')['default']
PipelineList: typeof import('./src/components/repo/pipeline/PipelineList.vue')['default'] PipelineList: typeof import('./src/components/repo/pipeline/PipelineList.vue')['default']
PipelineLog: typeof import('./src/components/repo/pipeline/PipelineLog.vue')['default'] PipelineLog: typeof import('./src/components/repo/pipeline/PipelineLog.vue')['default']

View file

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

View file

@ -22,6 +22,8 @@
<i-carbon-in-progress v-else-if="name === 'status-running' || name === 'status-started'" class="h-6 w-6" /> <i-carbon-in-progress v-else-if="name === 'status-running' || name === 'status-started'" class="h-6 w-6" />
<i-bi-slash-circle-fill v-else-if="name === 'status-skipped'" class="h-6 w-6" /> <i-bi-slash-circle-fill v-else-if="name === 'status-skipped'" class="h-6 w-6" />
<i-bi-check-circle-fill v-else-if="name === 'status-success'" class="h-6 w-6" /> <i-bi-check-circle-fill v-else-if="name === 'status-success'" class="h-6 w-6" />
<i-bi-exclamation-triangle-fill v-else-if="name === 'attention'" class="h-5 w-5" />
<i-bi-exclamation-triangle v-else-if="name === 'warning'" class="h-5 w-5" />
<i-simple-icons-gitea v-else-if="name === 'gitea'" class="h-8 w-8" /> <i-simple-icons-gitea v-else-if="name === 'gitea'" class="h-8 w-8" />
<i-ph-gitlab-logo-simple-fill v-else-if="name === 'gitlab'" class="h-8 w-8" /> <i-ph-gitlab-logo-simple-fill v-else-if="name === 'gitlab'" class="h-8 w-8" />
<i-mdi-bitbucket v-else-if="name === 'bitbucket'" class="h-8 w-8" /> <i-mdi-bitbucket v-else-if="name === 'bitbucket'" class="h-8 w-8" />
@ -94,7 +96,9 @@ export type IconNames =
| 'auto-scroll-off' | 'auto-scroll-off'
| 'refresh' | 'refresh'
| 'play' | 'play'
| 'pause'; | 'pause'
| 'warning'
| 'attention';
defineProps<{ defineProps<{
name: IconNames; name: IconNames;

View file

@ -1,8 +1,9 @@
<template> <template>
<div <div
class="text-sm text-gray-700 font-bold rounded-md border border-solid p-2 border-wp-hint-warn-200 bg-wp-hint-warn-100" class="flex gap-2 items-center text-sm text-gray-700 font-bold rounded-md border border-solid p-2 border-wp-hint-warn-200 bg-wp-hint-warn-100"
> >
{{ text }} <Icon name="warning" />
<span>{{ text }}</span>
</div> </div>
</template> </template>

View file

@ -7,11 +7,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { IconNames } from '~/components/atomic/Icon.vue';
import { Tab, useTabsClient } from '~/compositions/useTabs'; import { Tab, useTabsClient } from '~/compositions/useTabs';
const props = defineProps<{ const props = defineProps<{
id?: string; id?: string;
title: string; title: string;
icon?: IconNames;
iconClass?: string;
}>(); }>();
const { tabs, activeTab } = useTabsClient(); const { tabs, activeTab } = useTabsClient();
@ -21,6 +24,8 @@ onMounted(() => {
tab.value = { tab.value = {
id: props.id || props.title.toLocaleLowerCase().replace(' ', '-') || tabs.value.length.toString(), id: props.id || props.title.toLocaleLowerCase().replace(' ', '-') || tabs.value.length.toString(),
title: props.title, title: props.title,
icon: props.icon,
iconClass: props.iconClass,
}; };
// don't add tab if tab id is already present // don't add tab if tab id is already present

View file

@ -13,7 +13,10 @@
> >
<Icon v-if="activeTab === tab.id" name="chevron-right" class="md:hidden" /> <Icon v-if="activeTab === tab.id" name="chevron-right" class="md:hidden" />
<Icon v-else name="blank" class="md:hidden" /> <Icon v-else name="blank" class="md:hidden" />
<span class="flex gap-2 items-center flex-row-reverse md:flex-row">
<Icon v-if="tab.icon" :name="tab.icon" :class="tab.iconClass" />
<span>{{ tab.title }}</span> <span>{{ tab.title }}</span>
</span>
</button> </button>
</div> </div>
</template> </template>

View file

@ -4,6 +4,8 @@ import { useRoute } from 'vue-router';
export type Tab = { export type Tab = {
id: string; id: string;
title: string; title: string;
icon?: string;
iconClass?: string;
}; };
export function useTabsProvider({ export function useTabsProvider({

View file

@ -1,18 +1,30 @@
<template> <template>
<Panel> <Panel>
<div class="grid justify-center gap-2 text-left grid-3-1"> <div class="grid justify-center gap-x-4 text-left grid-3-1">
<template v-for="(error, i) in pipeline.errors" :key="i"> <template v-for="(error, i) in pipeline.errors" :key="i">
<span>{{ error.is_warning ? '⚠️' : '❌' }}</span> <Icon
name="attention"
class="flex-shrink-0 my-1"
:class="{
'text-wp-state-warn-100': error.is_warning,
'text-wp-state-error-100': !error.is_warning,
}"
/>
<span>[{{ error.type }}]</span> <span>[{{ error.type }}]</span>
<span v-if="isLinterError(error) || isDeprecationError(error)"> <span v-if="isLinterError(error) || isDeprecationError(error)" class="whitespace-nowrap">
<span v-if="error.data?.file" class="font-bold">{{ error.data?.file }}: </span> <span v-if="error.data?.file" class="font-bold">{{ error.data?.file }}: </span>
<span>{{ error.data?.field }}</span> <span>{{ error.data?.field }}</span>
</span> </span>
<span v-else /> <span v-else />
<a v-if="isDeprecationError(error)" :href="error.data?.docs" target="_blank" class="underline ml-4"> <a
v-if="isDeprecationError(error)"
:href="error.data?.docs"
target="_blank"
class="underline col-span-full col-start-2 md:col-span-auto md:col-start-auto"
>
{{ error.message }} {{ error.message }}
</a> </a>
<span v-else class="ml-4"> <span v-else class="col-span-full col-start-2 md:col-span-auto md:col-start-auto">
{{ error.message }} {{ error.message }}
</span> </span>
</template> </template>

View file

@ -77,17 +77,13 @@
<Tab <Tab
v-if="pipeline.errors && pipeline.errors.length > 0" v-if="pipeline.errors && pipeline.errors.length > 0"
id="errors" id="errors"
icon="attention"
:title=" :title="
pipeline.errors.some((e) => !e.is_warning) pipeline.errors.some((e) => !e.is_warning)
? '❌ ' + ? $t('repo.pipeline.errors', { count: pipeline.errors?.length })
$t('repo.pipeline.errors', { : $t('repo.pipeline.warnings', { count: pipeline.errors?.length })
count: pipeline.errors?.length,
})
: '⚠️ ' +
$t('repo.pipeline.warnings', {
count: pipeline.errors?.length,
})
" "
:icon-class="pipeline.errors.some((e) => !e.is_warning) ? 'text-wp-state-error-100' : 'text-wp-state-warn-100'"
/> />
<Tab id="config" :title="$t('repo.pipeline.config')" /> <Tab id="config" :title="$t('repo.pipeline.config')" />
<Tab <Tab