Add option to render button as link (#2378)

Fixes: https://github.com/woodpecker-ci/woodpecker/issues/1259

Work from https://github.com/woodpecker-ci/woodpecker/pull/1602/files

With this approach, existing buttons are still working and buttons with
`to="https://..."` are rendered as `a` tag. Not sure about the
"recursive render" issue from the original PR, have not seen any
rendering issue, any idea about this?


![image](https://github.com/woodpecker-ci/woodpecker/assets/3391958/2e87be21-3d3d-47b3-a2c4-1ffe5cfee592)
This commit is contained in:
Robert Kaussow 2023-09-08 08:44:22 +02:00 committed by GitHub
parent 718ec6141c
commit e21a41de8c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,6 +1,7 @@
<template> <template>
<button <component
type="button" :is="to === null ? 'button' : httpLink ? 'a' : 'router-link'"
v-bind="btnAttrs"
class="relative flex items-center py-1 px-2 rounded-md border shadow-sm cursor-pointer transition-all duration-150 overflow-hidden disabled:opacity-50 disabled:cursor-not-allowed" class="relative flex items-center py-1 px-2 rounded-md border shadow-sm cursor-pointer transition-all duration-150 overflow-hidden disabled:opacity-50 disabled:cursor-not-allowed"
:class="{ :class="{
'bg-wp-control-neutral-100 hover:bg-wp-control-neutral-200 border-wp-control-neutral-300 text-wp-text-100': 'bg-wp-control-neutral-100 hover:bg-wp-control-neutral-200 border-wp-control-neutral-300 text-wp-text-100':
@ -12,7 +13,6 @@
}" }"
:title="title" :title="title"
:disabled="disabled" :disabled="disabled"
@click="doClick"
> >
<slot> <slot>
<Icon v-if="startIcon" :name="startIcon" class="!w-6 !h-6" :class="{ invisible: isLoading, 'mr-1': text }" /> <Icon v-if="startIcon" :name="startIcon" class="!w-6 !h-6" :class="{ invisible: isLoading, 'mr-1': text }" />
@ -32,12 +32,12 @@
<Icon name="loading" class="animate-spin" /> <Icon name="loading" class="animate-spin" />
</div> </div>
</slot> </slot>
</button> </component>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, useAttrs } from 'vue'; import { computed, useAttrs } from 'vue';
import { RouteLocationRaw, useRouter } from 'vue-router'; import { RouteLocationRaw } from 'vue-router';
import Icon, { IconNames } from '~/components/atomic/Icon.vue'; import Icon, { IconNames } from '~/components/atomic/Icon.vue';
@ -62,24 +62,19 @@ const props = withDefaults(
}, },
); );
const router = useRouter(); const httpLink = computed(() => typeof props.to === 'string' && props.to.startsWith('http'));
async function doClick() { const btnAttrs = computed(() => {
if (props.isLoading) { if (props.to === null) {
return; return { type: 'button' };
} }
if (!props.to) { if (httpLink.value) {
return; return { href: props.to };
} }
if (typeof props.to === 'string' && props.to.startsWith('http')) { return { to: props.to };
window.location.href = props.to; });
return;
}
await router.push(props.to);
}
const attrs = useAttrs(); const attrs = useAttrs();
const passedClasses = computed(() => { const passedClasses = computed(() => {