135 lines
4.0 KiB
Vue
135 lines
4.0 KiB
Vue
<template>
|
|
<Component
|
|
:is="noButtons ? NuxtLink : 'div'"
|
|
:class="classes"
|
|
:to="noButtons ? automateFunctionRoute(fn.id) : undefined"
|
|
:external="externalMoreInfo"
|
|
:target="externalMoreInfo ? '_blank' : undefined"
|
|
class="rounded-lg border border-outline-3 bg-foundation overflow-hidden"
|
|
>
|
|
<div class="px-4 py-4 flex flex-col gap-3 relative h-full">
|
|
<div class="flex gap-3 items-center" :class="{ 'w-4/5': hasLabel }">
|
|
<AutomateFunctionLogo :logo="fn.logo" />
|
|
<div class="flex flex-col truncate">
|
|
<div
|
|
:class="[
|
|
'text-heading-sm text-foreground truncate',
|
|
noButtons ? '' : 'hover:underline'
|
|
]"
|
|
>
|
|
<Component
|
|
:is="noButtons ? 'div' : NuxtLink"
|
|
:to="automateFunctionRoute(fn.id)"
|
|
:target="externalMoreInfo ? '_blank' : undefined"
|
|
class="truncate"
|
|
>
|
|
{{ fn.name }}
|
|
</Component>
|
|
</div>
|
|
<div class="text-body-2xs flex items-center text-foreground-2 space-x-0.5">
|
|
<span>by</span>
|
|
<Component :is="noButtons ? 'div' : NuxtLink" :to="fn.repo.url" external>
|
|
{{ fn.repo.owner }}
|
|
</Component>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="text-body-xs text-foreground-2 line-clamp-3 h-18 flex-1">
|
|
{{ plaintextDescription }}
|
|
</div>
|
|
<div v-if="!noButtons" class="flex flex-col sm:flex-row gap-x-1">
|
|
<template v-if="showEdit">
|
|
<FormButton full-width color="outline" @click="$emit('edit')">
|
|
Edit details
|
|
</FormButton>
|
|
</template>
|
|
<template v-else>
|
|
<FormButton
|
|
:icon-left="selected ? CheckIcon : undefined"
|
|
@click="$emit('use')"
|
|
>
|
|
{{ selected ? 'Selected' : 'Select' }}
|
|
</FormButton>
|
|
<FormButton
|
|
color="subtle"
|
|
:to="automateFunctionRoute(fn.id)"
|
|
:external="externalMoreInfo"
|
|
:target="externalMoreInfo ? '_blank' : undefined"
|
|
>
|
|
Learn more
|
|
</FormButton>
|
|
</template>
|
|
</div>
|
|
<div class="absolute top-0 right-0">
|
|
<div
|
|
v-if="hasLabel"
|
|
class="rounded-bl-md rounded-tr-lg font-medium text-body-3xs px-1.5 py-0.5"
|
|
:class="{
|
|
'bg-info-lighter text-primary-focus': fn.isFeatured,
|
|
'bg-danger-lighter text-danger-darker': isOutdated
|
|
}"
|
|
>
|
|
<template v-if="isOutdated">Outdated</template>
|
|
<template v-else-if="fn.isFeatured">Featured</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Component>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import { graphql } from '~/lib/common/generated/gql'
|
|
import type { AutomationsFunctionsCard_AutomateFunctionFragment } from '~/lib/common/generated/gql/graphql'
|
|
import { CheckIcon } from '@heroicons/vue/24/outline'
|
|
import { automateFunctionRoute } from '~/lib/common/helpers/route'
|
|
import { useMarkdown } from '~/lib/common/composables/markdown'
|
|
|
|
graphql(`
|
|
fragment AutomationsFunctionsCard_AutomateFunction on AutomateFunction {
|
|
id
|
|
name
|
|
isFeatured
|
|
description
|
|
logo
|
|
repo {
|
|
id
|
|
url
|
|
owner
|
|
name
|
|
}
|
|
}
|
|
`)
|
|
|
|
defineEmits<{
|
|
edit: []
|
|
use: []
|
|
}>()
|
|
|
|
const props = defineProps<{
|
|
fn: AutomationsFunctionsCard_AutomateFunctionFragment
|
|
showEdit?: boolean
|
|
noButtons?: boolean
|
|
externalMoreInfo?: boolean
|
|
selected?: boolean
|
|
isOutdated?: boolean
|
|
}>()
|
|
|
|
const NuxtLink = resolveComponent('NuxtLink')
|
|
const hasLabel = computed(() => props.fn.isFeatured || props.isOutdated)
|
|
const { html: plaintextDescription } = useMarkdown(
|
|
computed(() => props.fn.description || ''),
|
|
{ plaintext: true }
|
|
)
|
|
|
|
const classes = computed(() => {
|
|
const classParts = ['rounded-lg']
|
|
|
|
if (props.selected) {
|
|
classParts.push('border-primary')
|
|
} else if (props.noButtons) {
|
|
classParts.push('hover:border-outline-5 cursor-pointer')
|
|
}
|
|
|
|
return classParts.join(' ')
|
|
})
|
|
</script>
|