Browse Source

feat(gui): set default color and option to add new option in dropdown

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/4406/head
Pranav C 2 years ago
parent
commit
1219657783
  1. 62
      packages/nc-gui/components/cell/MultiSelect.vue
  2. 67
      packages/nc-gui/components/cell/SingleSelect.vue

62
packages/nc-gui/components/cell/MultiSelect.vue

@ -5,7 +5,6 @@ import type { SelectOptionType, SelectOptionsType } from 'nocodb-sdk'
import {
ActiveCellInj,
ColumnInj,
EditModeInj,
IsKanbanInj,
ReadonlyInj,
computed,
@ -16,8 +15,7 @@ import {
useEventListener,
useProject,
useSelectedCellKeyupListener,
watch,
useMetas
watch,enumColor,useMetas
} from '#imports'
import MdiCloseCircle from '~icons/mdi/close-circle'
@ -30,6 +28,8 @@ const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const emptyOption = Symbol('emptyOption')
const { isMysql } = useProject()
const column = inject(ColumnInj)!
@ -48,6 +48,14 @@ const isOpen = ref(false)
const isKanban = inject(IsKanbanInj, ref(false))
const searchVal = ref()
const { $api } = useNuxtApp()
const { getMeta } = useMetas()
const isOptionMissing = computed(() => {
return (options.value ?? []).every((op) => op.title !== searchVal.value)
})
const options = computed<(SelectOptionType & { value?: string })[]>(() => {
if (column?.value.colOptions) {
const opts = column.value.colOptions
@ -72,6 +80,9 @@ const vModel = computed({
}, [] as string[])
},
set: (val) => {
if (isOptionMissing.value && val[val.length - 1] === searchVal.value) {
return addIfMissingAndSave()
}
emit('update:modelValue', val.length === 0 ? null : val.join(','))
},
})
@ -81,13 +92,13 @@ const selectedTitles = computed(() =>
? typeof modelValue === 'string'
? isMysql
? modelValue.split(',').sort((a, b) => {
const opa = options.value.find((el) => el.title === a)
const opb = options.value.find((el) => el.title === b)
if (opa && opb) {
return opa.order! - opb.order!
}
return 0
})
const opa = options.value.find((el) => el.title === a)
const opb = options.value.find((el) => el.title === b)
if (opa && opb) {
return opa.order! - opb.order!
}
return 0
})
: modelValue.split(',')
: modelValue
: [],
@ -162,20 +173,16 @@ useSelectedCellKeyupListener(active, (e) => {
}
})
const searchVal = ref()
const { $api } = useNuxtApp()
const { getMeta } = useMetas()
async function addIfMissingAndSave() {
const searchInput = aselect.value?.$el?.querySelector('.ant-select-selection-search-input')
if (!searchVal) return false
if (!searchInput) return false
const newOptValue = searchInput?.value
const newOptValue = searchVal?.value
if (newOptValue && !options.value.some((o) => o.title === newOptValue)) {
const newOptions = [...options.value]
newOptions.push({ title: newOptValue, value: newOptValue })
newOptions.push({ title: newOptValue, value: newOptValue,
color: enumColor.light[(options.value.length + 1) % enumColor.light.length], })
column.value.colOptions = { options: newOptions.map(({ value: _, ...rest }) => rest) }
await $api.dbTableColumn.update(column.value?.id as string, {
@ -184,9 +191,13 @@ async function addIfMissingAndSave() {
await getMeta(column.value.fk_model_id!, true)
vModel.value = [...vModel.value, newOptValue]
searchInput.value = ''
searchVal.value = ''
}
}
const search = () => {
searchVal.value = aselect.value?.$el?.querySelector('.ant-select-selection-search-input')?.value
}
</script>
<template>
@ -203,7 +214,8 @@ async function addIfMissingAndSave() {
:disabled="readOnly"
:class="{ '!ml-[-8px]': readOnly }"
:dropdown-class-name="`nc-dropdown-multi-select-cell ${isOpen ? 'active' : ''}`"
@keydown.enter.stop
@search="search"
@keydown.stop
@click="isOpen = (active || editable) && !isOpen"
>
<a-select-option
@ -228,6 +240,13 @@ async function addIfMissingAndSave() {
</a-tag>
</a-select-option>
<a-select-option v-if="searchVal && isOptionMissing" :key="searchVal" :value="searchVal">
<div class="flex gap-2 text-gray-500 items-center">
<MdiPlusThick class="min-w-4" />
<div class="text-xs whitespace-normal"> Create new option named <strong>{{ searchVal }}</strong></div>
</div>
</a-select-option>
<template #tagRender="{ value: val, onClose }">
<a-tag
v-if="options.find((el) => el.title === val)"
@ -301,6 +320,3 @@ async function addIfMissingAndSave() {
@apply "flex overflow-hidden";
}
</style>
<!--
-->

67
packages/nc-gui/components/cell/SingleSelect.vue

@ -14,6 +14,7 @@ import {
ref,
useEventListener,
watch,
enumColor,
} from '#imports'
interface Props {
@ -39,13 +40,25 @@ const isOpen = ref(false)
const isKanban = inject(IsKanbanInj, ref(false))
const { $api } = useNuxtApp()
const searchVal = ref()
const isOptionMissing = computed(() => {
return (options.value ?? []).every((op) => op.title !== searchVal.value)
})
const vModel = computed({
get: () => modelValue,
set: (val) => {
if (isOptionMissing.value && val === searchVal.value) {
return addIfMissingAndSave()
}
emit('update:modelValue', val || null)
},
})
const options = computed<(SelectOptionType & { value: string })[]>(() => {
if (column?.value.colOptions) {
const opts = column.value.colOptions
@ -68,8 +81,8 @@ const handleKeys = async (e: KeyboardEvent) => {
break
case 'Enter':
e.preventDefault()
if (await addIfMissingAndSave())
e.stopPropagation()
// if (await addIfMissingAndSave())
// e.stopPropagation()
break
}
}
@ -104,46 +117,36 @@ useSelectedCellKeyupListener(active, (e) => {
}
})
const val = ref()
const { $api } = useNuxtApp()
async function addIfMissingAndSave() {
const searchInput = aselect.value?.$el?.querySelector('.ant-select-selection-search-input')
if(!searchInput) return false
if (!searchVal.value) return false
const newOptValue = searchInput?.value
const newOptValue = searchVal.value
searchVal.value = ''
if (newOptValue && !options.value.some((o) => o.title === newOptValue)) {
options.value.push({ title: newOptValue, value: newOptValue })
options.value.push({
title: newOptValue,
value: newOptValue,
color: enumColor.light[(options.value.length + 1) % enumColor.light.length],
})
column.value.colOptions = { options: options.value.map(({ value: _, ...rest }) => rest) }
await $api.dbTableColumn.update(column.value?.id as string, {
...column.value,
})
vModel.value = newOptValue
}
}
</script>
<template>
<!-- <a-auto-complete
ref="aselect"
v-model:value="val"
class="w-full h-fill"
dropdown-class-name="nc-dropdown-single-select-cell"
:options="options"
@select="vModel = val"
:defaultActiveFirstOption="false"
@keydown.enter.prevent.stop="addIfMissingAndSave"
>
<template #option="item">
<div style="display: flex; justify-content: space-between">
{{ item.value }}
</div>
</template>
-->
const search = () => {
searchVal.value = aselect.value?.$el?.querySelector('.ant-select-selection-search-input')?.value
}
</script>
<template>
<a-select
ref="aselect"
v-model:value="vModel"
@ -155,6 +158,9 @@ async function addIfMissingAndSave() {
:show-arrow="!readOnly && (active || editable || vModel === null)"
:dropdown-class-name="`nc-dropdown-single-select-cell ${isOpen ? 'active' : ''}`"
@select="isOpen = false"
@keydown.stop
show-search
@search="search"
@keydown.enter.stop
@click="isOpen = (active || editable) && !isOpen"
>
@ -179,6 +185,15 @@ async function addIfMissingAndSave() {
</span>
</a-tag>
</a-select-option>
<a-select-option v-if="searchVal && isOptionMissing" :key="searchVal" :value="searchVal">
<div class="flex gap-2 text-gray-500 items-center">
<MdiPlusThick class="min-w-4" />
<div class="text-xs whitespace-normal"> Create new option named <strong>{{ searchVal }}</strong></div>
</div>
</a-select-option>
</a-select>
</template>

Loading…
Cancel
Save