@ -3,6 +3,14 @@ import Draggable from 'vuedraggable'
import { UITypes } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import { IsKanbanInj , enumColor , onMounted , useColumnCreateStoreOrThrow , useVModel , watch } from '#imports'
import { IsKanbanInj , enumColor , onMounted , useColumnCreateStoreOrThrow , useVModel , watch } from '#imports'
interface Option {
color : string
title : string
id ? : string
fk _colum _id ? : string
order ? : number
}
const props = defineProps < {
const props = defineProps < {
value : any
value : any
} > ( )
} > ( )
@ -13,7 +21,10 @@ const vModel = useVModel(props, 'value', emit)
const { setAdditionalValidations , validateInfos , isPg , isMysql } = useColumnCreateStoreOrThrow ( )
const { setAdditionalValidations , validateInfos , isPg , isMysql } = useColumnCreateStoreOrThrow ( )
let options = $ref < any [ ] > ( [ ] )
let options = $ref < Option [ ] > ( [ ] )
let renderedOptions = $ref < ( Option & { status ? : 'remove' } ) [ ] > ( [ ] )
let savedDefaultOption = $ref < Option | null > ( null )
let savedCdf = $ref < string | null > ( null )
const colorMenus = $ref < any > ( { } )
const colorMenus = $ref < any > ( { } )
@ -58,6 +69,9 @@ onMounted(() => {
}
}
}
}
options = vModel . value . colOptions . options
options = vModel . value . colOptions . options
renderedOptions = [ ... options ]
/ / S u p p o r t f o r o l d e r o p t i o n s
/ / S u p p o r t f o r o l d e r o p t i o n s
for ( const op of options . filter ( ( el ) => el . order === null ) ) {
for ( const op of options . filter ( ( el ) => el . order === null ) ) {
op . title = op . title . replace ( /^'/ , '' ) . replace ( /'$/ , '' )
op . title = op . title . replace ( /^'/ , '' ) . replace ( /'$/ , '' )
@ -87,13 +101,6 @@ const optionChanged = (changedId: string) => {
}
}
}
}
const optionDropped = ( changedId : string ) => {
if ( changedId && changedId === defaultOption . value ? . id ) {
vModel . value . cdf = null
defaultOption . value = null
}
}
const getNextColor = ( ) => {
const getNextColor = ( ) => {
let tempColor = colors [ 0 ]
let tempColor = colors [ 0 ]
if ( options . length && options [ options . length - 1 ] . color ) {
if ( options . length && options [ options . length - 1 ] . color ) {
@ -108,13 +115,40 @@ const addNewOption = () => {
title : '' ,
title : '' ,
color : getNextColor ( ) ,
color : getNextColor ( ) ,
}
}
renderedOptions . push ( tempOption )
options . push ( tempOption )
options . push ( tempOption )
}
}
const removeOption = ( index : number ) => {
const syncOptions = ( ) => {
const optionId = options [ index ] ? . id
vModel . value . colOptions . options = renderedOptions . filter ( ( op ) => op . status !== 'remove' )
options . splice ( index , 1 )
}
optionDropped ( optionId )
const removeRenderedOption = ( index : number ) => {
renderedOptions [ index ] . status = 'remove'
syncOptions ( )
const optionId = renderedOptions [ index ] ? . id
if ( optionId === defaultOption . value ? . id ) {
savedDefaultOption = { ... defaultOption . value }
savedCdf = vModel . value . cdf
defaultOption . value = null
vModel . value . cdf = null
}
}
const undoRemoveRenderedOption = ( index : number ) => {
renderedOptions [ index ] . status = undefined
syncOptions ( )
const optionId = renderedOptions [ index ] ? . id
if ( optionId === savedDefaultOption ? . id ) {
defaultOption . value = { ... savedDefaultOption }
vModel . value . cdf = savedCdf
savedDefaultOption = null
savedCdf = null
}
}
}
/ / f o c u s l a s t c r e a t e d i n p u t
/ / f o c u s l a s t c r e a t e d i n p u t
@ -128,47 +162,62 @@ watch(inputs, () => {
< template >
< template >
< div class = "w-full" >
< div class = "w-full" >
< div class = "max-h-[250px] overflow-x-auto scrollbar-thin-dull pr-3" >
< div class = "max-h-[250px] overflow-x-auto scrollbar-thin-dull pr-3" >
< Draggable :list ="o ptions" item -key = " id " handle = ".nc-child-draggable-icon" >
< Draggable :list ="renderedO ptions" item -key = " id " handle = ".nc-child-draggable-icon" @change ="syncOptions" >
< template # item = "{ element, index }" >
< template # item = "{ element, index }" >
< div class = "flex py-1 items-center nc-select-option" >
< div class = "flex p-1 items-center nc-select-option" >
< MdiDragVertical
< div
v - if = "!isKanban"
class = "flex items-center w-full"
small
: data - testid = "`select-column-option-${index}`"
class = "nc-child-draggable-icon handle"
: class = "{ removed: element.status === 'remove' }"
: data - testid = "`select-option-column-handle-icon-${element.title}`"
/ >
< a -dropdown
v - model : visible = "colorMenus[index]"
: trigger = "['click']"
overlay - class - name = "nc-dropdown-select-color-options"
>
>
< template # overlay >
< MdiDragVertical
< LazyGeneralColorPicker
v - if = "!isKanban"
v - model = "element.color"
small
: pick - button = "true"
class = "nc-child-draggable-icon handle"
@ update : model - value = "colorMenus[index] = false"
: data - testid = "`select-option-column-handle-icon-${element.title}`"
/ >
< a -dropdown
v - model : visible = "colorMenus[index]"
: trigger = "['click']"
overlay - class - name = "nc-dropdown-select-color-options"
>
< template # overlay >
< LazyGeneralColorPicker
v - model = "element.color"
: pick - button = "true"
@ update : model - value = "colorMenus[index] = false"
/ >
< / template >
< MdiArrowDownDropCircle
class = "mr-2 text-[1.5em] outline-0 hover:!text-[1.75em]"
: class = "{ 'text-[1.75em]': colorMenus[index] }"
: style = "{ color: element.color }"
/ >
/ >
< / template >
< / a - d r o p d o w n >
< MdiArrowDownDropCircle
class = "mr-2 text-[1.5em] outline-0 hover:!text-[1.75em]"
< a -input
: class = "{ 'text-[1.75em]': colorMenus[index] }"
ref = "inputs"
: style = "{ color: element.color }"
v - model : value = "element.title"
class = "caption"
: data - testid = "`select-column-option-input-${index}`"
: disabled = "element.status === 'remove'"
@ keydown . enter . prevent = "element.title?.trim() && addNewOption()"
@ change = "optionChanged(element.id)"
/ >
/ >
< / a - d r o p d o w n >
< / div >
< a -input
ref = "inputs"
v - model : value = "element.title"
class = "caption"
: data - testid = "`select-column-option-input-${index}`"
@ keydown . enter . prevent = "element.title?.trim() && addNewOption()"
@ change = "optionChanged(element.id)"
/ >
< MdiClose
< MdiClose
v - if = "element.status !== 'remove'"
class = "ml-2 hover:!text-black-500 text-gray-500 cursor-pointer"
class = "ml-2 hover:!text-black-500 text-gray-500 cursor-pointer"
: data - testid = "`select-column-option-remove-${index}`"
: data - testid = "`select-column-option-remove-${index}`"
@ click = "removeOption(index)"
@ click = "removeRenderedOption(index)"
/ >
< MdiArrowULeftBottom
v - else
class = "ml-2 hover:!text-black-500 text-gray-500 cursor-pointer"
: data - testid = "`select-column-option-remove-undo-${index}`"
@ click = "undoRemoveRenderedOption(index)"
/ >
/ >
< / div >
< / div >
< / template >
< / template >
@ -186,3 +235,19 @@ watch(inputs, () => {
< / a - b u t t o n >
< / a - b u t t o n >
< / div >
< / div >
< / template >
< / template >
< style scoped >
. removed {
position : relative ;
}
. removed : after {
position : absolute ;
left : 0 ;
top : 50 % ;
height : 1 px ;
background : # ccc ;
content : '' ;
width : calc ( 100 % + 5 px ) ;
display : block ;
}
< / style >