多维表格
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

381 lines
7.7 KiB

<script setup lang="ts">
import type { ButtonType, ColumnType } from 'nocodb-sdk'
import type { Ref } from 'vue'
const column = inject(ColumnInj) as Ref<
ColumnType & {
colOptions: ButtonType
}
>
const cellValue = inject(CellValueInj, ref())
const { currentRow } = useSmartsheetRowStoreOrThrow()
const meta = inject(MetaInj, ref())
const isGrid = inject(IsGridInj, ref(false))
const isExpandedForm = inject(IsExpandedFormOpenInj, ref(false))
const { isUIAllowed } = useRoles()
const isPublic = inject(IsPublicInj, ref(false))
const { $api } = useNuxtApp()
const rowId = computed(() => {
return extractPkFromRow(currentRow.value?.row, meta.value!.columns!)
})
const isLoading = ref(false)
const triggerAction = async () => {
const colOptions = column.value.colOptions
if (colOptions.type === 'webhook') {
try {
isLoading.value = true
await $api.dbTableWebhook.trigger(cellValue.value?.fk_webhook_id, rowId!.value)
} catch (e) {
console.log(e)
message.error(await extractSdkResponseErrorMsg(e))
} finally {
isLoading.value = false
}
}
}
const componentProps = computed(() => {
if (column.value.colOptions.type === 'url') {
let url = `${cellValue.value?.url}`
url = /^(https?|ftp|mailto|file):\/\//.test(url) ? url : url.trim() ? `https://${url}` : ''
// if url params not encoded, encode them using encodeURI
try {
url = decodeURI(url) === url ? encodeURI(url) : url
} catch {
url = encodeURI(url)
}
return {
href: url,
target: '_blank',
...(column.value?.colOptions.error ? { disabled: true } : {}),
}
} else {
return {
disabled:
isPublic.value ||
!isUIAllowed('hookTrigger') ||
isLoading.value ||
!column.value.colOptions.fk_webhook_id ||
!cellValue.value?.fk_webhook_id,
}
}
})
</script>
<template>
<div
:class="{
'justify-center': isGrid && !isExpandedForm,
}"
class="w-full flex items-center"
>
<component
:is="column.colOptions.type === 'url' ? 'a' : 'button'"
v-bind="componentProps"
data-testid="nc-button-cell"
:class="[
`${column.colOptions.color ?? 'brand'} ${column.colOptions.theme ?? 'solid'}`,
{ '!w-6': !column.colOptions.label },
]"
class="nc-cell-button nc-button-cell-link btn-cell-colors truncate flex items-center h-6"
@click="triggerAction"
>
<GeneralLoader
v-if="isLoading"
:class="{
solid: column.colOptions.theme === 'solid',
text: column.colOptions.theme === 'text',
light: column.colOptions.theme === 'light',
}"
class="flex btn-cell-colors !bg-transparent w-4 h-4"
size="medium"
/>
<GeneralIcon v-else-if="column.colOptions.icon" :icon="column.colOptions.icon" class="!w-4 min-w-4 min-h-4 !h-4" />
<NcTooltip v-if="column.colOptions.label" class="!truncate" show-on-truncate-only>
<span class="text-[13px] truncate font-medium">
{{ column.colOptions.label }}
</span>
<template #title>
{{ column.colOptions.label }}
</template>
</NcTooltip>
</component>
</div>
</template>
<style lang="scss">
.nc-data-cell {
&:has(.nc-virtual-cell-button) {
@apply !border-none;
box-shadow: none !important;
}
.nc-cell-attachment {
@apply !border-none;
}
}
.nc-button-cell-link {
@apply !no-underline;
}
</style>
<style scoped lang="scss">
.nc-cell-button {
@apply rounded-lg px-2 flex items-center gap-2 transition-all justify-center;
&:not([class*='text']) {
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.06), 0px 5px 3px -2px rgba(0, 0, 0, 0.02);
}
&:focus-within {
box-shadow: 0px 0px 0px 2px #fff, 0px 0px 0px 4px #3069fe;
}
&[disabled] {
@apply !bg-gray-100 text-gray-400;
}
}
.btn-cell-colors {
&.solid {
@apply text-white;
&.brand {
@apply bg-brand-500 hover:bg-brand-600;
.nc-loader {
@apply !text-brand-500;
}
}
&.red {
@apply bg-red-600 hover:bg-red-700;
.nc-loader {
@apply !text-red-600;
}
}
&.green {
@apply bg-green-600 hover:bg-green-700;
.nc-loader {
@apply !text-green-600;
}
}
&.maroon {
@apply bg-maroon-600 hover:bg-maroon-700;
.nc-loader {
@apply !text-maroon-600;
}
}
&.blue {
@apply bg-blue-600 hover:bg-blue-700;
.nc-loader {
@apply !text-blue-600;
}
}
&.orange {
@apply bg-orange-600 hover:bg-orange-700;
.nc-loader {
@apply !text-orange-600;
}
}
&.pink {
@apply bg-pink-600 hover:bg-pink-700;
.nc-loader {
@apply !text-pink-600;
}
}
&.purple {
@apply bg-purple-500 hover:bg-purple-700;
.nc-loader {
@apply !text-purple-600;
}
}
&.yellow {
@apply bg-yellow-600 hover:bg-yellow-700;
.nc-loader {
@apply !text-yellow-600;
}
}
&.gray {
@apply bg-gray-600 hover:bg-gray-700;
.nc-loader {
@apply !text-gray-600;
}
}
}
&.light {
@apply text-gray-700;
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.06), 0px 5px 3px -2px rgba(0, 0, 0, 0.02);
&.brand {
@apply bg-brand-100 hover:bg-brand-200;
.nc-loader {
@apply !text-brand-500;
}
}
&.red {
@apply bg-red-100 hover:bg-red-200;
.nc-loader {
@apply !text-red-600;
}
}
&.green {
@apply bg-green-100 hover:bg-green-200;
.nc-loader {
@apply !text-green-600;
}
}
&.maroon {
@apply bg-maroon-100 hover:bg-maroon-200;
.nc-loader {
@apply !text-maroon-600;
}
}
&.blue {
@apply bg-blue-100 hover:bg-blue-200;
.nc-loader {
@apply !text-blue-600;
}
}
&.orange {
@apply bg-orange-100 hover:bg-orange-200;
.nc-loader {
@apply !text-orange-600;
}
}
&.pink {
@apply bg-pink-100 hover:bg-pink-200;
.nc-loader {
@apply !text-pink-600;
}
}
&.purple {
@apply bg-purple-100 hover:bg-purple-200;
.nc-loader {
@apply !text-purple-600;
}
}
&.yellow {
@apply bg-yellow-100 hover:bg-yellow-200;
.nc-loader {
@apply !text-yellow-600;
}
}
&.gray {
@apply bg-gray-100 hover:bg-gray-200;
.nc-loader {
@apply !text-gray-600;
}
}
}
&.text {
&:hover {
@apply bg-gray-200;
}
&:focus {
box-shadow: 0px 0px 0px 2px #fff, 0px 0px 0px 4px #3069fe;
}
&.brand {
@apply text-brand-500;
.nc-loader {
@apply !text-brand-500;
}
}
&.red {
@apply text-red-600;
.nc-loader {
@apply !text-red-600;
}
}
&.green {
@apply text-green-600;
.nc-loader {
@apply !text-green-600;
}
}
&.maroon {
@apply text-maroon-600;
.nc-loader {
@apply !text-maroon-600;
}
}
&.blue {
@apply text-blue-600;
.nc-loader {
@apply !text-blue-600;
}
}
&.orange {
@apply text-orange-600;
.nc-loader {
@apply !text-orange-600;
}
}
&.pink {
@apply text-pink-600;
.nc-loader {
@apply !text-pink-600;
}
}
&.purple {
@apply text-purple-500;
.nc-loader {
@apply !text-purple-600;
}
}
&.yellow {
@apply text-yellow-600;
.nc-loader {
@apply !text-yellow-600;
}
}
&.gray {
@apply text-gray-600;
.nc-loader {
@apply !text-gray-600;
}
}
}
}
</style>