-
-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Url.vue
146 lines (118 loc) Β· 3.94 KB
/
Url.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core'
import {
CellUrlDisableOverlayInj,
ColumnInj,
EditColumnInj,
EditModeInj,
IsExpandedFormOpenInj,
IsFormInj,
IsSurveyFormInj,
computed,
inject,
isValidURL,
message,
parseProp,
ref,
useCellUrlConfig,
useI18n,
watch,
} from '#imports'
interface Props {
modelValue?: string | null
}
const { modelValue: value } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const { t } = useI18n()
const { showNull } = useGlobal()
const column = inject(ColumnInj)!
const editEnabled = inject(EditModeInj)!
const isEditColumn = inject(EditColumnInj, ref(false))
const disableOverlay = inject(CellUrlDisableOverlayInj, ref(false))
// Used in the logic of when to display error since we are not storing the url if it's not valid
const localState = ref(value)
const rowHeight = inject(RowHeightInj, ref(undefined))
const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const vModel = computed({
get: () => value,
set: (val) => {
localState.value = val
if (!parseProp(column.value.meta)?.validate || (val && isValidURL(val)) || !val || isSurveyForm.value) {
emit('update:modelValue', val)
}
},
})
const isValid = computed(() => value && isValidURL(value))
const url = computed(() => {
if (!value || !isValidURL(value)) return ''
/** add url scheme if missing */
if (/^https?:\/\//.test(value)) return value
return `https://${value}`
})
const { cellUrlOptions } = useCellUrlConfig(url)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const isForm = inject(IsFormInj)!
const focus: VNodeRef = (el) =>
!isExpandedFormOpen.value && !isEditColumn.value && isForm.value && (el as HTMLInputElement)?.focus()
watch(
() => editEnabled.value,
() => {
if (parseProp(column.value.meta)?.validate && !editEnabled.value && localState.value && !isValidURL(localState.value)) {
message.error(t('msg.error.invalidURL'))
localState.value = undefined
return
}
localState.value = value
},
)
</script>
<template>
<div class="flex flex-row items-center justify-between w-full h-full">
<input
v-if="editEnabled"
:ref="focus"
v-model="vModel"
:placeholder="isEditColumn ? $t('labels.enterDefaultUrlOptional') : ''"
class="outline-none text-sm w-full py-1 bg-transparent h-full"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
@blur="editEnabled = false"
@keydown.down.stop
@keydown.left.stop
@keydown.right.stop
@keydown.up.stop
@keydown.delete.stop
@selectstart.capture.stop
@mousedown.stop
/>
<span v-else-if="vModel === null && showNull" class="nc-null uppercase"> {{ $t('general.null') }}</span>
<nuxt-link
v-else-if="isValid && !cellUrlOptions?.overlay"
no-prefetch
no-rel
class="z-3 text-sm underline hover:opacity-75"
:to="url"
:target="cellUrlOptions?.behavior === 'replace' ? undefined : '_blank'"
>
<LazyCellClampedText :value="value" :lines="rowHeight" />
</nuxt-link>
<nuxt-link
v-else-if="isValid && !disableOverlay && cellUrlOptions?.overlay"
no-prefetch
no-rel
class="z-3 w-full h-full text-center !no-underline hover:opacity-75"
:to="url"
:target="cellUrlOptions?.behavior === 'replace' ? undefined : '_blank'"
>
<LazyCellClampedText :value="cellUrlOptions.overlay" :lines="rowHeight" />
</nuxt-link>
<span v-else class="w-9/10 overflow-ellipsis overflow-hidden"><LazyCellClampedText :value="value" :lines="rowHeight" /></span>
<div v-if="column.meta?.validate && !isValid && value?.length && !editEnabled" class="mr-1 w-1/10">
<a-tooltip placement="top">
<template #title> {{ t('msg.error.invalidURL') }} </template>
<div class="flex flex-row items-center">
<MiCircleWarning class="text-red-400 h-4" />
</div>
</a-tooltip>
</div>
</div>
</template>