mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
4.1 KiB
125 lines
4.1 KiB
<script setup lang="ts"> |
|
import type { SelectProps } from 'ant-design-vue' |
|
import type { ColumnType, LinkToAnotherRecordType } from 'nocodb-sdk' |
|
import { RelationTypes, UITypes, isHiddenCol, isLinksOrLTAR, isSystemColumn, isVirtualCol } from 'nocodb-sdk' |
|
import { MetaInj, computed, inject, ref, resolveComponent, useViewColumnsOrThrow } from '#imports' |
|
|
|
const { modelValue, isSort, allowEmpty, ...restProps } = defineProps<{ |
|
modelValue?: string |
|
isSort?: boolean |
|
columns?: ColumnType[] |
|
allowEmpty?: boolean |
|
}>() |
|
|
|
const emit = defineEmits(['update:modelValue']) |
|
|
|
const customColumns = toRef(restProps, 'columns') |
|
|
|
const meta = inject(MetaInj, ref()) |
|
|
|
const localValue = computed({ |
|
get: () => modelValue, |
|
set: (val) => emit('update:modelValue', val), |
|
}) |
|
|
|
const { showSystemFields, metaColumnById } = useViewColumnsOrThrow() |
|
|
|
const options = computed<SelectProps['options']>(() => |
|
( |
|
customColumns.value?.filter((c: ColumnType) => { |
|
if (isSystemColumn(metaColumnById?.value?.[c.id!])) { |
|
if (isHiddenCol(c)) { |
|
/** ignore mm relation column, created by and last modified by system field */ |
|
return false |
|
} |
|
} |
|
return true |
|
}) || |
|
meta.value?.columns?.filter((c: ColumnType) => { |
|
if (c.uidt === UITypes.Links) { |
|
return true |
|
} |
|
if (isSystemColumn(metaColumnById?.value?.[c.id!])) { |
|
if (isHiddenCol(c)) { |
|
/** ignore mm relation column, created by and last modified by system field */ |
|
return false |
|
} |
|
|
|
return ( |
|
/** if the field is used in filter, then show it anyway */ |
|
localValue.value === c.id || |
|
/** hide system columns if not enabled */ |
|
showSystemFields.value |
|
) |
|
} else if (c.uidt === UITypes.QrCode || c.uidt === UITypes.Barcode || c.uidt === UITypes.ID) { |
|
return false |
|
} else if (isSort) { |
|
/** ignore hasmany and manytomany relations if it's using within sort menu */ |
|
return !(isLinksOrLTAR(c) && (c.colOptions as LinkToAnotherRecordType).type !== RelationTypes.BELONGS_TO) |
|
/** ignore virtual fields which are system fields ( mm relation ) and qr code fields */ |
|
} else { |
|
const isVirtualSystemField = c.colOptions && c.system |
|
return !isVirtualSystemField |
|
} |
|
}) |
|
)?.map((c: ColumnType) => ({ |
|
value: c.id, |
|
label: c.title, |
|
icon: h( |
|
isVirtualCol(c) ? resolveComponent('SmartsheetHeaderVirtualCellIcon') : resolveComponent('SmartsheetHeaderCellIcon'), |
|
{ |
|
columnMeta: c, |
|
}, |
|
), |
|
c, |
|
})), |
|
) |
|
|
|
const filterOption = (input: string, option: any) => option.label.toLowerCase()?.includes(input.toLowerCase()) |
|
|
|
// when a new filter is created, select a field by default |
|
if (!localValue.value && allowEmpty !== true) { |
|
localValue.value = (options.value?.[0].value as string) || '' |
|
} |
|
</script> |
|
|
|
<template> |
|
<NcSelect |
|
v-model:value="localValue" |
|
:dropdown-match-select-width="false" |
|
show-search |
|
:placeholder="$t('placeholder.selectField')" |
|
:filter-option="filterOption" |
|
dropdown-class-name="nc-dropdown-toolbar-field-list" |
|
> |
|
<a-select-option v-for="option in options" :key="option.value" :label="option.label" :value="option.value"> |
|
<div class="flex items-center w-full justify-between w-full gap-2 max-w-50"> |
|
<div class="flex gap-1 flex-1 items-center truncate items-center h-full"> |
|
<component :is="option.icon" class="min-w-5 !mx-0" /> |
|
<NcTooltip |
|
:style="{ wordBreak: 'keep-all', whiteSpace: 'nowrap', display: 'inline' }" |
|
class="max-w-[15rem] truncate select-none" |
|
show-on-truncate-only |
|
> |
|
<template #title> {{ option.label }}</template> |
|
<span> |
|
{{ option.label }} |
|
</span> |
|
</NcTooltip> |
|
</div> |
|
<component |
|
:is="iconMap.check" |
|
v-if="localValue === option.value" |
|
id="nc-selected-item-icon" |
|
class="text-primary w-4 h-4" |
|
/> |
|
</div> |
|
</a-select-option> |
|
</NcSelect> |
|
</template> |
|
|
|
<style lang="scss"> |
|
.ant-select-selection-search-input { |
|
box-shadow: none !important; |
|
} |
|
</style>
|
|
|