Browse Source

Nc fix: Formula modal UI/UX (#8825)

* fix(nc-gui): small changes

* fix(nc-gui): formula suggestion popover visibility issue in MFE

* fix(nc-gui): console warnings

* fix(nc-gui): formula field madal width issue

* fix(nc-gui): formula fun or field empty state
pull/8830/head
Ramesh Mane 2 weeks ago committed by GitHub
parent
commit
b5d8902175
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      packages/nc-gui/components/smartsheet/column/EditOrAdd.vue
  2. 88
      packages/nc-gui/components/smartsheet/column/FormulaOptions.vue
  3. 1
      packages/nc-gui/composables/useColumnCreateStore.ts
  4. 1
      packages/nc-gui/lang/en.json

4
packages/nc-gui/components/smartsheet/column/EditOrAdd.vue

@ -360,8 +360,8 @@ const isFullUpdateAllowed = computed(() => {
:class="{
'bg-white': !props.fromTableExplorer,
'w-[384px]': !props.embedMode,
'min-w-500px': formState.uidt === UITypes.LinkToAnotherRecord || formState.uidt === UITypes.Links,
'!w-116 overflow-visible': formState.uidt === UITypes.Formula && !props.embedMode,
'min-w-[500px]': formState.uidt === UITypes.LinkToAnotherRecord || formState.uidt === UITypes.Links,
'overflow-visible': formState.uidt === UITypes.Formula,
'!w-[600px]': formState.uidt === UITypes.LinkToAnotherRecord || formState.uidt === UITypes.Links,
'shadow-lg border-1 border-gray-200 shadow-gray-300 rounded-xl p-5': !embedMode,
}"

88
packages/nc-gui/components/smartsheet/column/FormulaOptions.vue

@ -22,7 +22,7 @@ const uiTypesNotSupportedInFormulas = [UITypes.QrCode, UITypes.Barcode]
const vModel = useVModel(props, 'value', emit)
const { setAdditionalValidations, validateInfos, sqlUi, column } = useColumnCreateStoreOrThrow()
const { setAdditionalValidations, validateInfos, sqlUi, column, fromTableExplorer } = useColumnCreateStoreOrThrow()
const { t } = useI18n()
@ -48,6 +48,8 @@ const { getMeta } = useMetas()
const suggestionPreviewed = ref<Record<any, string> | undefined>()
const showFunctionList = ref<boolean>(true)
const validators = {
formula_raw: [
{
@ -84,8 +86,6 @@ const autocomplete = ref(false)
const formulaRef = ref()
const sugListRef = ref()
const variableListRef = ref<(typeof AntListItem)[]>([])
const sugOptionsRef = ref<(typeof AntListItem)[]>([])
@ -124,7 +124,7 @@ const suggestionsList = computed(() => {
.map((c: any) => ({
text: c.title,
type: 'column',
icon: getUIDTIcon(c.uidt),
icon: getUIDTIcon(c.uidt) ? markRaw(getUIDTIcon(c.uidt)!) : undefined,
uidt: c.uidt,
})),
...availableBinOps.map((op: string) => ({
@ -218,7 +218,11 @@ function handleInput() {
if (!isCurlyBracketBalanced()) {
suggestion.value = suggestion.value.filter((v) => v.type === 'column')
showFunctionList.value = false
} else if (!showFunctionList.value) {
showFunctionList.value = true
}
autocomplete.value = !!suggestion.value.length
}
@ -284,27 +288,62 @@ onMounted(() => {
jsep.plugins.register(jsepCurlyHook)
})
const suggestionPreviewLeft = ref('-left-85')
watch(sugListRef, () => {
nextTick(() => {
setTimeout(() => {
const fieldModal = document.querySelector('.nc-dropdown-edit-column.active') as HTMLDivElement
const suggestionPreviewPostion = ref({
top: '0px',
left: '-344px',
})
if (fieldModal && fieldModal.getBoundingClientRect().left < 364) {
suggestionPreviewLeft.value = '-right-85'
}
}, 500)
})
onMounted(() => {
// wait until MFE field modal transition complete
setTimeout(() => {
const textAreaPosition = formulaRef.value?.$el?.getBoundingClientRect()
if (!textAreaPosition) return
if (fromTableExplorer?.value) {
suggestionPreviewPostion.value.left = `${textAreaPosition.left - 344}px`
suggestionPreviewPostion.value.top = `${textAreaPosition.top}px`
} else {
suggestionPreviewPostion.value.left = textAreaPosition.left < 352 ? '350px' : '-344px'
suggestionPreviewPostion.value.top = `0px`
}
}, 250)
})
const handleKeydown = (e: KeyboardEvent) => {
e.stopPropagation()
switch (e.key) {
case 'ArrowUp': {
e.preventDefault()
suggestionListUp()
break
}
case 'ArrowDown': {
e.preventDefault()
suggestionListDown()
break
}
case 'Enter': {
e.preventDefault()
selectText()
break
}
}
}
</script>
<template>
<div class="formula-wrapper relative">
<div
v-if="suggestionPreviewed && !suggestionPreviewed.unsupported && suggestionPreviewed.type === 'function'"
class="absolute w-84 top-0 bg-white z-10 pl-3 pt-3 border-1 shadow-md rounded-xl"
:class="suggestionPreviewLeft"
class="w-84 bg-white z-10 pl-3 pt-3 border-1 shadow-md rounded-xl"
:class="{
'fixed': fromTableExplorer,
'absolute top-0': !fromTableExplorer,
}"
:style="{
left: suggestionPreviewPostion.left,
top: suggestionPreviewPostion.top,
}"
>
<div class="pr-3">
<div class="flex flex-row w-full justify-between pb-2 border-b-1">
@ -358,15 +397,13 @@ watch(sugListRef, () => {
ref="formulaRef"
v-model:value="vModel.formula_raw"
class="nc-formula-input !rounded-md"
@keydown.down.prevent="suggestionListDown"
@keydown.up.prevent="suggestionListUp"
@keydown.enter.prevent="selectText"
@keydown="handleKeydown"
@change="handleInputDeb"
/>
</a-form-item>
<div ref="sugListRef" class="h-[250px] overflow-auto nc-scrollbar-thin border-1 border-gray-200 rounded-lg mt-4">
<template v-if="suggestedFormulas.length > 0">
<div class="h-[250px] overflow-auto nc-scrollbar-thin border-1 border-gray-200 rounded-lg mt-4">
<template v-if="suggestedFormulas && showFunctionList">
<div class="border-b-1 bg-gray-50 px-3 py-1 uppercase text-gray-600 text-xs font-semibold sticky top-0 z-10">
Formulas
</div>
@ -405,13 +442,13 @@ watch(sugListRef, () => {
</a-list>
</template>
<template v-if="variableList.length > 0">
<template v-if="variableList">
<div class="border-b-1 bg-gray-50 px-3 py-1 uppercase text-gray-600 text-xs font-semibold sticky top-0 z-10">Fields</div>
<a-list
ref="variableListRef"
:data-source="variableList"
:locale="{ emptyText: $t('msg.formula.noSuggestedFormulaFound') }"
:locale="{ emptyText: $t('msg.formula.noSuggestedFieldFound') }"
class="!overflow-hidden"
>
<template #renderItem="{ item, index }">
@ -450,9 +487,6 @@ watch(sugListRef, () => {
</template>
</a-list>
</template>
<div v-if="suggestion.length === 0">
<span class="text-gray-500">Empty</span>
</div>
</div>
</div>
</template>

1
packages/nc-gui/composables/useColumnCreateStore.ts

@ -393,6 +393,7 @@ const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState
disableSubmitBtn,
setPostSaveOrUpdateCbk,
updateFieldName,
fromTableExplorer,
}
},
)

1
packages/nc-gui/lang/en.json

@ -1165,6 +1165,7 @@
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.",
"noSuggestedFormulaFound": "No suggested formula found",
"noSuggestedFieldFound": "No suggested field found",
"typeIsExpected": "{calleeName} requires a {type} at position {position}",
"numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected",

Loading…
Cancel
Save