mirror of https://github.com/nocodb/nocodb
DarkPhoenix2704
9 months ago
4 changed files with 362 additions and 0 deletions
After Width: | Height: | Size: 433 B |
After Width: | Height: | Size: 547 B |
@ -0,0 +1,347 @@
|
||||
<script lang="ts" setup> |
||||
import { |
||||
type ColumnType, |
||||
type LookupType, |
||||
type RollupType, |
||||
dateFormats, |
||||
isCreatedOrLastModifiedByCol, |
||||
isCreatedOrLastModifiedTimeCol, |
||||
timeFormats, |
||||
} from 'nocodb-sdk' |
||||
import dayjs from 'dayjs' |
||||
import { |
||||
computed, |
||||
isBoolean, |
||||
isDate, |
||||
isDateTime, |
||||
isInt, |
||||
parseProp, |
||||
ref, |
||||
storeToRefs, |
||||
useAttachment, |
||||
useBase, |
||||
useMetas, |
||||
} from '#imports' |
||||
|
||||
interface Props { |
||||
column: ColumnType |
||||
modelValue: any |
||||
bold?: boolean |
||||
italic?: boolean |
||||
underline?: boolean |
||||
} |
||||
|
||||
const props = defineProps<Props>() |
||||
|
||||
const meta = inject(MetaInj) |
||||
|
||||
const { metas } = useMetas() |
||||
|
||||
const column = toRef(props, 'column') |
||||
|
||||
const { sqlUis } = storeToRefs(useBase()) |
||||
|
||||
const basesStore = useBases() |
||||
|
||||
const { basesUser } = storeToRefs(basesStore) |
||||
|
||||
const { isXcdbBase, isMssql, isMysql } = useBase() |
||||
|
||||
const { getPossibleAttachmentSrc } = useAttachment() |
||||
|
||||
const sqlUi = ref(column.value?.source_id ? sqlUis.value[column.value?.source_id] : Object.values(sqlUis.value)[0]) |
||||
|
||||
const abstractType = computed(() => column.value && sqlUi.value.getAbstractType(column.value)) |
||||
|
||||
const getCheckBoxValue = (modelValue: any) => { |
||||
return !modelValue && modelValue !== '0' && modelValue !== 0 && modelValue !== 'false' |
||||
} |
||||
|
||||
const getMultiSelectValue = (modelValue: any, col: ColumnType): string => { |
||||
return modelValue |
||||
? Array.isArray(modelValue) |
||||
? modelValue.join(', ') |
||||
: modelValue.toString() |
||||
: isMysql(col.source_id) |
||||
? modelValue.toString().split(',').join(', ') |
||||
: modelValue.split(', ') |
||||
} |
||||
|
||||
const getDateValue = (modelValue: string | null | number, col: ColumnType, isSystemCol?: boolean) => { |
||||
const dateFormat = !isSystemCol ? parseProp(col.meta)?.date_format ?? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss' |
||||
if (!modelValue || !dayjs(modelValue).isValid()) { |
||||
return 'Invalid Date' |
||||
} else { |
||||
return dayjs(/^\d+$/.test(String(modelValue)) ? +modelValue : modelValue).format(dateFormat) |
||||
} |
||||
} |
||||
|
||||
const getYearValue = (modelValue: string | null) => { |
||||
if (!modelValue) { |
||||
return undefined |
||||
} else if (!dayjs(modelValue).isValid()) { |
||||
return 'Invalid Date' |
||||
} else { |
||||
return dayjs(modelValue.toString(), 'YYYY').format('YYYY') |
||||
} |
||||
} |
||||
|
||||
const getDateTimeValue = (modelValue: string | null, col: ColumnType) => { |
||||
if (!modelValue || !dayjs(modelValue).isValid()) { |
||||
return 'Invalid Date' |
||||
} |
||||
|
||||
const dateFormat = parseProp(col?.meta)?.date_format ?? dateFormats[0] |
||||
const timeFormat = parseProp(col?.meta)?.time_format ?? timeFormats[0] |
||||
const dateTimeFormat = `${dateFormat} ${timeFormat}` |
||||
|
||||
const isXcDB = isXcdbBase(col.source_id) |
||||
|
||||
if (!isXcDB) { |
||||
return dayjs(/^\d+$/.test(modelValue) ? +modelValue : modelValue, dateTimeFormat).format(dateTimeFormat) |
||||
} |
||||
|
||||
if (isMssql(col.source_id)) { |
||||
// e.g. 2023-04-29T11:41:53.000Z |
||||
return dayjs(modelValue, dateTimeFormat).format(dateTimeFormat) |
||||
} else { |
||||
return dayjs(modelValue).utc().local().format(dateTimeFormat) |
||||
} |
||||
} |
||||
|
||||
const getTimeValue = (modelValue: string | null) => { |
||||
if (!modelValue) { |
||||
return undefined |
||||
} |
||||
let dateTime = dayjs(modelValue) |
||||
|
||||
if (!dateTime.isValid()) { |
||||
dateTime = dayjs(modelValue, 'HH:mm:ss') |
||||
} |
||||
if (!dateTime.isValid()) { |
||||
dateTime = dayjs(`1999-01-01 ${modelValue}`) |
||||
} |
||||
if (!dateTime.isValid()) { |
||||
return 'Invalid Date' |
||||
} |
||||
|
||||
return dateTime.format('HH:mm') |
||||
} |
||||
|
||||
const getDurationValue = (modelValue: string | null, col: ColumnType) => { |
||||
const durationType = parseProp(col.meta)?.duration || 0 |
||||
return convertMS2Duration(modelValue, durationType) |
||||
} |
||||
|
||||
const getPercentValue = (modelValue: string | null) => { |
||||
return modelValue ? `${modelValue}%` : undefined |
||||
} |
||||
|
||||
const getCurrencyValue = (modelValue: string | number | null, col: ColumnType) => { |
||||
const currencyMeta = { |
||||
currency_locale: 'en-US', |
||||
currency_code: 'USD', |
||||
...parseProp(col.meta), |
||||
} |
||||
try { |
||||
if (modelValue === null || modelValue === undefined || isNaN(modelValue)) { |
||||
return modelValue |
||||
} |
||||
return new Intl.NumberFormat(currencyMeta.currency_locale || 'en-US', { |
||||
style: 'currency', |
||||
currency: currencyMeta.currency_code || 'USD', |
||||
}).format(+modelValue) |
||||
} catch (e) { |
||||
return modelValue |
||||
} |
||||
} |
||||
|
||||
const getUserValue = (modelValue: string | string[] | null | Array<any>) => { |
||||
if (!modelValue) { |
||||
return 'Invalid User' |
||||
} |
||||
const baseUsers = meta?.value.base_id ? basesUser.value.get(meta?.value.base_id) || [] : [] |
||||
|
||||
if (typeof modelValue === 'string') { |
||||
const idsOrMails = modelValue.split(',') |
||||
|
||||
return idsOrMails |
||||
.map((idOrMail) => { |
||||
const user = baseUsers.find((u) => u.id === idOrMail || u.email === idOrMail) |
||||
return user ? user.display_name || user.email : idOrMail.id |
||||
}) |
||||
.join(', ') |
||||
} else { |
||||
if (Array.isArray(modelValue)) { |
||||
return modelValue |
||||
.map((idOrMail) => { |
||||
const user = baseUsers.find((u) => u.id === idOrMail.id || u.email === idOrMail.email) |
||||
return user ? user.display_name || user.email : idOrMail.id |
||||
}) |
||||
.join(', ') |
||||
} else { |
||||
return modelValue ? modelValue.display_name || modelValue.email : 'Invalid User' |
||||
} |
||||
} |
||||
} |
||||
|
||||
const getDecimalValue = (modelValue: string | null | number, col: ColumnType) => { |
||||
if (!modelValue || isNaN(Number(modelValue))) { |
||||
return 'Invalid Number' |
||||
} |
||||
const columnMeta = parseProp(col.meta) |
||||
|
||||
return Number(modelValue).toFixed(columnMeta?.precision ?? 1) |
||||
} |
||||
|
||||
const getIntValue = (modelValue: string | null | number) => { |
||||
if (!modelValue || isNaN(Number(modelValue))) { |
||||
return 'Invalid Number' |
||||
} |
||||
return Number(modelValue) |
||||
} |
||||
|
||||
const getTextAreaValue = (modelValue: string | null, col: ColumnType) => { |
||||
const isRichMode = typeof col.meta === 'string' ? JSON.parse(col.meta).richMode : col.meta?.richMode |
||||
if (isRichMode) { |
||||
return modelValue?.replace(/[*_~\[\]]|<\/?[^>]+(>|$)/g, '') |
||||
} |
||||
return modelValue |
||||
} |
||||
|
||||
const getRollupValue = (modelValue: string | null | number, col: ColumnType) => { |
||||
const colOptions = col.colOptions as RollupType |
||||
|
||||
const fns = ['count', 'avg', 'sum', 'countDistinct', 'sumDistinct', 'avgDistinct'] |
||||
if (fns.includes(colOptions.rollup_function!)) { |
||||
return modelValue |
||||
} else { |
||||
const relationColumnOptions = colOptions.fk_relation_column_id |
||||
? meta?.value.columns?.find((c) => c.id === colOptions.fk_relation_column_id)?.colOptions |
||||
: null |
||||
const relatedTableMeta = |
||||
relationColumnOptions?.fk_related_model_id && metas.value?.[relationColumnOptions.fk_related_model_id as string] |
||||
|
||||
const childColumn = relatedTableMeta?.columns.find((c: ColumnType) => c.id === colOptions.fk_rollup_column_id) |
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define |
||||
return parseValue(modelValue, childColumn) |
||||
} |
||||
} |
||||
|
||||
const getLookupValue = (modelValue: string | null | number | Array<any>, col: ColumnType) => { |
||||
const colOptions = col.colOptions as LookupType |
||||
const relationColumnOptions = colOptions.fk_relation_column_id |
||||
? meta?.value.columns?.find((c) => c.id === colOptions.fk_relation_column_id)?.colOptions |
||||
: null |
||||
const relatedTableMeta = |
||||
relationColumnOptions?.fk_related_model_id && metas.value?.[relationColumnOptions.fk_related_model_id as string] |
||||
|
||||
const childColumn = relatedTableMeta?.columns.find((c: ColumnType) => c.id === colOptions.fk_lookup_column_id) as |
||||
| ColumnType |
||||
| undefined |
||||
|
||||
if (Array.isArray(modelValue)) { |
||||
return modelValue |
||||
.map((v) => { |
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define |
||||
return parseValue(v, childColumn!) |
||||
}) |
||||
.join(', ') |
||||
} |
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define |
||||
return parseValue(modelValue, childColumn!) |
||||
} |
||||
|
||||
const getAttachmentValue = (modelValue: string | null | number | Array<any>) => { |
||||
console.log(modelValue) |
||||
if (Array.isArray(modelValue)) { |
||||
return modelValue.map((v) => `${v.title} (${getPossibleAttachmentSrc(v).join(', ')})`).join(', ') |
||||
} |
||||
return modelValue |
||||
} |
||||
|
||||
const parseValue = (value: any, col: ColumnType): string => { |
||||
if (!value || !col) { |
||||
return undefined |
||||
} |
||||
if (isGeoData(col)) { |
||||
const [latitude, longitude] = ((value as string) || '').split(';') |
||||
return latitude && longitude ? `${latitude}; ${longitude}` : 'Invalid location' |
||||
} |
||||
if (isTextArea(col)) { |
||||
return getTextAreaValue(value, col) |
||||
} |
||||
if (isBoolean(col, abstractType)) { |
||||
return getCheckBoxValue(value) ? 'Checked' : 'UnChecked' |
||||
} |
||||
if (isMultiSelect(col)) { |
||||
return getMultiSelectValue(value, col) |
||||
} |
||||
if (isDate(col, abstractType)) { |
||||
return getDateValue(value, col) |
||||
} |
||||
if (isYear(col, abstractType)) { |
||||
return getYearValue(value) |
||||
} |
||||
if (isDateTime(col, abstractType)) { |
||||
return getDateTimeValue(value, col) |
||||
} |
||||
if (isTime(col, abstractType)) { |
||||
return getTimeValue(value) |
||||
} |
||||
if (isDuration(col)) { |
||||
return getDurationValue(value, col) |
||||
} |
||||
if (isPercent(col)) { |
||||
return getPercentValue(value) |
||||
} |
||||
if (isCurrency(col)) { |
||||
return getCurrencyValue(value, col) |
||||
} |
||||
if (isUser(col)) { |
||||
return getUserValue(value, col, false) |
||||
} |
||||
if (isDecimal(col)) { |
||||
return getDecimalValue(value, col) |
||||
} |
||||
if (isInt(col, abstractType)) { |
||||
return getIntValue(value) |
||||
} |
||||
if (isJSON(col)) { |
||||
return JSON.stringify(value, null, 2) |
||||
} |
||||
if (isRollup(col)) { |
||||
return getRollupValue(value, col) |
||||
} |
||||
if (isLookup(col)) { |
||||
return getLookupValue(value, col) |
||||
} |
||||
if (isCreatedOrLastModifiedTimeCol(col)) { |
||||
return getDateValue(value, col, true) |
||||
} |
||||
if (isCreatedOrLastModifiedByCol(col)) { |
||||
return getUserValue(value) |
||||
} |
||||
if (isAttachment(col)) { |
||||
return getAttachmentValue(value) |
||||
} |
||||
|
||||
return value as unknown as string |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<span |
||||
:class="{ |
||||
'font-bold': props.bold, |
||||
'italic': props.italic, |
||||
'underline': props.underline, |
||||
}" |
||||
data-testid="nc-calendar-cell" |
||||
> |
||||
{{ parseValue(props.modelValue, column) }} |
||||
</span> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped></style> |
Loading…
Reference in new issue