Browse Source

feat(nc-gui): list option for single & multiselect field

pull/7729/head
Ramesh Mane 10 months ago
parent
commit
bfc13045d2
  1. 347
      packages/nc-gui/components/cell/MultiSelect.vue
  2. 2
      packages/nc-gui/components/cell/SingleSelect.vue
  3. 2
      packages/nc-gui/components/smartsheet/Form.vue

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

@ -353,154 +353,194 @@ const onFocus = () => {
<template> <template>
<div <div
class="nc-cell-field nc-multi-select h-full w-full flex items-center" class="nc-cell-field nc-multi-select h-full w-full flex items-center"
:class="{ 'read-only': readOnly }" :class="{ 'read-only': readOnly, readOnly, 'max-w-full': isForm }"
@click="toggleMenu" @click="toggleMenu"
> >
<div <div v-if="!isEditColumn && isForm && parseProp(column.meta)?.isList" class="w-full max-w-full">
v-if="!active" <a-checkbox-group v-model:value="vModel" class="nc-field-layout-list">
class="flex flex-wrap" <a-checkbox
:style="{ v-for="op of options"
'display': '-webkit-box', :key="op.title"
'max-width': '100%', :value="op.title"
'-webkit-line-clamp': rowHeight || 1, :data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
'-webkit-box-orient': 'vertical', :class="`nc-select-option-${column.title}-${op.title}`"
'overflow': 'hidden', >
}" <a-tag class="rounded-tag max-w-full" :color="op.color">
> <span
<template v-for="selectedOpt of selectedOpts" :key="selectedOpt.value"> :style="{
<a-tag class="rounded-tag max-w-full" :color="selectedOpt.color"> 'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
<span ? '#fff'
:style="{ : tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'color': tinycolor.isReadable(selectedOpt.color || '#ccc', '#fff', { level: 'AA', size: 'large' }) 'font-size': '13px',
? '#fff' }"
: tinycolor.mostReadable(selectedOpt.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(), >
'font-size': '13px', <NcTooltip class="truncate max-w-full" show-on-truncate-only>
}" <template #title>
:class="{ 'text-sm': isKanban }" {{ op.title }}
> </template>
<NcTooltip class="truncate max-w-full" show-on-truncate-only> <span
<template #title> class="text-ellipsis overflow-hidden"
{{ selectedOpt.title }} :style="{
</template> wordBreak: 'keep-all',
<span whiteSpace: 'nowrap',
class="text-ellipsis overflow-hidden" display: 'inline',
:style="{ }"
wordBreak: 'keep-all', >
whiteSpace: 'nowrap', {{ op.title }}
display: 'inline', </span>
}" </NcTooltip>
> </span>
{{ selectedOpt.title }} </a-tag>
</span> </a-checkbox>
</NcTooltip> </a-checkbox-group>
</span>
</a-tag>
</template>
</div> </div>
<template v-else>
<a-select <div
v-else v-if="!active"
ref="aselect" class="flex flex-wrap"
v-model:value="vModel" :style="{
mode="multiple" 'display': '-webkit-box',
class="w-full overflow-hidden" 'max-width': '100%',
:placeholder="isEditColumn ? $t('labels.optional') : ''" '-webkit-line-clamp': rowHeight || 1,
:bordered="false" '-webkit-box-orient': 'vertical',
clear-icon 'overflow': 'hidden',
:show-search="!isMobileMode" }"
:show-arrow="editAllowed && !readOnly"
:open="isOpen && editAllowed"
:disabled="readOnly || !editAllowed"
:class="{ 'caret-transparent': !hasEditRoles }"
:dropdown-class-name="`nc-dropdown-multi-select-cell !min-w-200px ${isOpen ? 'active' : ''}`"
@search="search"
@keydown="onKeyDown"
@focus="onFocus"
@blur="isOpen = false"
>
<template #suffixIcon>
<GeneralIcon icon="arrowDown" class="text-gray-700 nc-select-expand-btn" />
</template>
<a-select-option
v-for="op of options"
:key="op.id || op.title"
:value="op.title"
:data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
:class="`nc-select-option-${column.title}-${op.title}`"
@click.stop
> >
<a-tag class="rounded-tag max-w-full" :color="op.color"> <template v-for="selectedOpt of selectedOpts" :key="selectedOpt.value">
<span <a-tag class="rounded-tag max-w-full" :color="selectedOpt.color">
:style="{ <span
'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' }) :style="{
? '#fff' 'color': tinycolor.isReadable(selectedOpt.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
: tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(), ? '#fff'
'font-size': '13px', : tinycolor.mostReadable(selectedOpt.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
}" 'font-size': '13px',
:class="{ 'text-sm': isKanban }" }"
> :class="{ 'text-sm': isKanban }"
<NcTooltip class="truncate max-w-full" show-on-truncate-only> >
<template #title> <NcTooltip class="truncate max-w-full" show-on-truncate-only>
{{ op.title }} <template #title>
</template> {{ selectedOpt.title }}
<span </template>
class="text-ellipsis overflow-hidden" <span
:style="{ class="text-ellipsis overflow-hidden"
wordBreak: 'keep-all', :style="{
whiteSpace: 'nowrap', wordBreak: 'keep-all',
display: 'inline', whiteSpace: 'nowrap',
}" display: 'inline',
> }"
{{ op.title }} >
</span> {{ selectedOpt.title }}
</NcTooltip> </span>
</span> </NcTooltip>
</a-tag> </span>
</a-select-option> </a-tag>
</template>
<a-select-option </div>
v-if="searchVal && isOptionMissing && !isPublic && !disableOptionCreation && isUIAllowed('fieldEdit')"
:key="searchVal" <a-select
:value="searchVal" v-else
ref="aselect"
v-model:value="vModel"
mode="multiple"
class="w-full overflow-hidden"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
:bordered="false"
clear-icon
:show-search="!isMobileMode"
:show-arrow="editAllowed && !readOnly"
:open="isOpen && editAllowed"
:disabled="readOnly || !editAllowed"
:class="{ 'caret-transparent': !hasEditRoles }"
:dropdown-class-name="`nc-dropdown-multi-select-cell !min-w-200px ${isOpen ? 'active' : ''}`"
@search="search"
@keydown="onKeyDown"
@focus="onFocus"
@blur="isOpen = false"
> >
<div class="flex gap-2 text-gray-500 items-center h-full"> <template #suffixIcon>
<component :is="iconMap.plusThick" class="min-w-4" /> <GeneralIcon icon="arrowDown" class="text-gray-700 nc-select-expand-btn" />
<div class="text-xs whitespace-normal"> </template>
{{ $t('msg.selectOption.createNewOptionNamed') }} <strong>{{ searchVal }}</strong> <a-select-option
</div> v-for="op of options"
</div> :key="op.id || op.title"
</a-select-option> :value="op.title"
:data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
<template #tagRender="{ value: val, onClose }"> :class="`nc-select-option-${column.title}-${op.title}`"
<a-tag @click.stop
v-if="options.find((el) => el.title === val)"
class="rounded-tag nc-selected-option"
:style="{ display: 'flex', alignItems: 'center' }"
:color="options.find((el) => el.title === val)?.color"
:closable="editAllowed && (vModel.length > 1 || !column?.rqd)"
:close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })"
@click="onTagClick($event, onClose)"
@close="onClose"
> >
<span <a-tag class="rounded-tag max-w-full" :color="op.color">
:style="{ <span
'color': tinycolor.isReadable(options.find((el) => el.title === val)?.color || '#ccc', '#fff', { :style="{
level: 'AA', 'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
size: 'large', ? '#fff'
}) : tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
? '#fff' 'font-size': '13px',
: tinycolor }"
.mostReadable(options.find((el) => el.title === val)?.color || '#ccc', ['#0b1d05', '#fff']) :class="{ 'text-sm': isKanban }"
.toHex8String(), >
'font-size': '13px', <NcTooltip class="truncate max-w-full" show-on-truncate-only>
}" <template #title>
:class="{ 'text-sm': isKanban }" {{ op.title }}
</template>
<span
class="text-ellipsis overflow-hidden"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ op.title }}
</span>
</NcTooltip>
</span>
</a-tag>
</a-select-option>
<a-select-option
v-if="searchVal && isOptionMissing && !isPublic && !disableOptionCreation && isUIAllowed('fieldEdit')"
:key="searchVal"
:value="searchVal"
>
<div class="flex gap-2 text-gray-500 items-center h-full">
<component :is="iconMap.plusThick" class="min-w-4" />
<div class="text-xs whitespace-normal">
{{ $t('msg.selectOption.createNewOptionNamed') }} <strong>{{ searchVal }}</strong>
</div>
</div>
</a-select-option>
<template #tagRender="{ value: val, onClose }">
<a-tag
v-if="options.find((el) => el.title === val)"
class="rounded-tag nc-selected-option"
:style="{ display: 'flex', alignItems: 'center' }"
:color="options.find((el) => el.title === val)?.color"
:closable="editAllowed && (vModel.length > 1 || !column?.rqd)"
:close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })"
@click="onTagClick($event, onClose)"
@close="onClose"
> >
{{ val }} <span
</span> :style="{
</a-tag> 'color': tinycolor.isReadable(options.find((el) => el.title === val)?.color || '#ccc', '#fff', {
</template> level: 'AA',
</a-select> size: 'large',
})
? '#fff'
: tinycolor
.mostReadable(options.find((el) => el.title === val)?.color || '#ccc', ['#0b1d05', '#fff'])
.toHex8String(),
'font-size': '13px',
}"
:class="{ 'text-sm': isKanban }"
>
{{ val }}
</span>
</a-tag>
</template>
</a-select>
</template>
</div> </div>
</template> </template>
@ -570,6 +610,31 @@ const onFocus = () => {
:deep(.ant-select-selection-search-input) { :deep(.ant-select-selection-search-input) {
@apply !text-xs; @apply !text-xs;
} }
.nc-field-layout-list {
@apply !flex !flex-col !items-start w-full !space-y-0.5 !max-w-full;
:deep(.ant-checkbox-wrapper) {
@apply !m-0 !h-9 !mr-0 !flex !items-center w-full !max-w-full pl-2 rounded-lg hover:bg-gray-100;
&:hover {
.ant-checkbox-checked:after {
@apply !rounded;
}
}
.ant-checkbox {
@apply !top-0;
& + span {
@apply !flex !pl-4 max-w-[calc(100%_-_16px)];
}
.ant-checkbox-checked:after,
.ant-checkbox-inner {
@apply !rounded;
}
}
}
}
</style> </style>
<style lang="scss"> <style lang="scss">

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

@ -276,7 +276,7 @@ const onFocus = () => {
@click="toggleMenu" @click="toggleMenu"
@keydown.enter.stop.prevent="toggleMenu" @keydown.enter.stop.prevent="toggleMenu"
> >
<div v-if="!isEditColumn && isForm && parseProp(column.meta)?.isList" class="max-w-full"> <div v-if="!isEditColumn && isForm && parseProp(column.meta)?.isList" class="w-full max-w-full">
<a-radio-group v-model:value="vModel" class="nc-field-layout-list"> <a-radio-group v-model:value="vModel" class="nc-field-layout-list">
<a-radio <a-radio
v-for="op of options" v-for="op of options"

2
packages/nc-gui/components/smartsheet/Form.vue

@ -1502,7 +1502,7 @@ useEventListener(
@apply !bg-white rounded-lg border-solid border-1 border-gray-200 focus-within:border-brand-500; @apply !bg-white rounded-lg border-solid border-1 border-gray-200 focus-within:border-brand-500;
} }
&.layout-list { &.layout-list {
@apply h-auto !pl-0; @apply h-auto !pl-0 !py-1;
} }
&.nc-cell-rating, &.nc-cell-rating,
&.nc-cell-geodata { &.nc-cell-geodata {

Loading…
Cancel
Save