woodpecker/web/src/components/repo/pipeline/PipelineStepList.vue
Robert Kaussow dca01e6817
Use consistent woodpecker color scheme (#2003)
Fixes: https://github.com/woodpecker-ci/woodpecker/issues/1079

What do you think about using a consistent `woodpecker` color scheme?
Right now, the `lime` color scheme from windicss is used that does not
really fit the primary color used for the documentation website. I have
used the primary color `#4CAF50` from the docs and created a color
palette with https://palettte.app/:

<details>
  <summary>JSON source</summary>

```Json
[
  {
    "paletteName": "New Palette",
    "swatches": [
      {
        "name": "New Swatch",
        "color": "166E30"
      },
      {
        "name": "New Swatch",
        "color": "248438"
      },
      {
        "name": "New Swatch",
        "color": "369943"
      },
      {
        "name": "New Swatch",
        "color": "4CAF50"
      },
      {
        "name": "New Swatch",
        "color": "68C464"
      },
      {
        "name": "New Swatch",
        "color": "8AD97F"
      }
    ]
  }
]
```

</details>


![image](https://github.com/woodpecker-ci/woodpecker/assets/3391958/a254f1e0-ce17-43a9-9e8b-72252296fd6f)

I have added this color scheme to the windicss config and replaced the
use of `lime` in the UI. While `woodpecker-300` would be the primary
color that is used for the docs, I currently use `woodpecke-400` as
primary color for the UI to fix some contrast issues.


![image](https://github.com/woodpecker-ci/woodpecker/assets/3391958/7bf751e1-f2a6-481c-bee7-a27d27cf8adb)

![image](https://github.com/woodpecker-ci/woodpecker/assets/3391958/e5673dc7-81c1-4fd4-bef9-14494bc5aa27)

What do you think? If you would like to stay with the current colors,
that's fine for me, I can just use the custom CSS feature in this case.

---------

Co-authored-by: 6543 <6543@obermui.de>
2023-08-02 09:09:12 +02:00

151 lines
6.1 KiB
Vue

<template>
<div class="flex flex-col w-full md:w-3/12 md:ml-2 text-wp-text-100 gap-2 pb-2">
<div
class="flex flex-wrap p-4 gap-1 justify-between flex-shrink-0 md:rounded-md border bg-wp-background-100 border-wp-background-400 dark:bg-wp-background-200"
>
<div class="flex space-x-1 items-center flex-shrink-0">
<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" />
</div>
<span>{{ pipeline.author }}</span>
</div>
<div class="flex space-x-1 items-center min-w-0">
<Icon v-if="pipeline.event === 'manual'" name="manual-pipeline" />
<Icon v-if="pipeline.event === 'push'" name="push" />
<Icon v-if="pipeline.event === 'deployment'" name="deployment" />
<Icon v-else-if="pipeline.event === 'tag'" name="tag" />
<a
v-else-if="pipeline.event === 'pull_request'"
class="flex items-center space-x-1 text-wp-link-100 hover:text-wp-link-200 min-w-0"
:href="pipeline.link_url"
target="_blank"
>
<Icon name="pull_request" />
<span class="truncate">{{ prettyRef }}</span>
</a>
<span v-if="pipeline.event !== 'pull_request'" class="truncate">{{ pipeline.branch }}</span>
</div>
<div class="flex items-center flex-shrink-0">
<template v-if="pipeline.event === 'pull_request'">
<Icon name="commit" />
<span>{{ pipeline.commit.slice(0, 10) }}</span>
</template>
<a
v-else
class="text-wp-link-100 hover:text-wp-link-200 flex items-center"
:href="pipeline.link_url"
target="_blank"
>
<Icon name="commit" />
<span>{{ pipeline.commit.slice(0, 10) }}</span>
</a>
</div>
</div>
<div v-if="pipeline.workflows === undefined || pipeline.workflows.length === 0" class="m-auto mt-4">
<span>{{ $t('repo.pipeline.no_pipeline_steps') }}</span>
</div>
<div class="flex-grow min-h-0 w-full relative">
<div class="absolute top-0 left-0 right-0 h-full flex flex-col overflow-y-scroll gap-y-2">
<div
v-for="workflow in pipeline.workflows"
:key="workflow.id"
class="p-2 md:rounded-md shadow border bg-wp-background-100 border-wp-background-400 dark:bg-wp-background-200"
>
<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-for="(value, key) in workflow.environ" :key="key">
<Badge :label="key" :value="value" />
</div>
</div>
<button
v-if="pipeline.workflows && pipeline.workflows.length > 1"
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"
@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] }"
/>
<PipelineStatusIcon :status="workflow.state" class="!h-4 !w-4" />
<span class="truncate">{{ workflow.name }}</span>
<PipelineStepDuration
v-if="workflow.start_time !== workflow.end_time"
:workflow="workflow"
class="mr-1 pr-2px"
/>
</button>
</div>
<div
class="transition-height duration-150 overflow-hidden"
:class="{
'max-h-screen': !workflowsCollapsed[workflow.id],
'max-h-0': workflowsCollapsed[workflow.id],
'ml-6': pipeline.workflows && pipeline.workflows.length > 1,
}"
>
<button
v-for="step in workflow.children"
: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="{
'bg-wp-background-300 dark:bg-wp-background-400': selectedStepId && selectedStepId === step.pid,
'mt-1':
(pipeline.workflows && pipeline.workflows.length > 1) ||
(workflow.children && step.pid !== workflow.children[0].pid),
}"
@click="$emit('update:selected-step-id', step.pid)"
>
<PipelineStatusIcon :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>
import { ref, toRef } from 'vue';
import Badge from '~/components/atomic/Badge.vue';
import Icon from '~/components/atomic/Icon.vue';
import PipelineStatusIcon from '~/components/repo/pipeline/PipelineStatusIcon.vue';
import PipelineStepDuration from '~/components/repo/pipeline/PipelineStepDuration.vue';
import usePipeline from '~/compositions/usePipeline';
import { Pipeline, PipelineStep } from '~/lib/api/types';
const props = defineProps<{
pipeline: Pipeline;
selectedStepId?: number | null;
}>();
defineEmits<{
(event: 'update:selected-step-id', selectedStepId: number): void;
}>();
const pipeline = toRef(props, 'pipeline');
const { prettyRef } = usePipeline(pipeline);
const workflowsCollapsed = ref<Record<PipelineStep['id'], boolean>>(
props.pipeline.workflows && props.pipeline.workflows.length > 1
? (props.pipeline.workflows || []).reduce(
(collapsed, workflow) => ({
...collapsed,
[workflow.id]: ['success', 'skipped', 'blocked'].includes(workflow.state),
}),
{},
)
: {},
);
</script>