Browse Source

Merge branch 'develop' into fix/gui-v2-quick-import

pull/2885/head
Wing-Kam Wong 2 years ago
parent
commit
ac751cb0d7
  1. 2
      packages/nc-gui-v2/components.d.ts
  2. 71
      packages/nc-gui-v2/components/cell/Currency.vue
  3. 103
      packages/nc-gui-v2/components/cell/DatePicker.vue
  4. 160
      packages/nc-gui-v2/components/cell/DateTimePicker.vue
  5. 27
      packages/nc-gui-v2/components/cell/Email.vue
  6. 59
      packages/nc-gui-v2/components/cell/YearPicker.vue
  7. 6
      packages/nc-gui-v2/components/smartsheet-header/CellIcon.vue
  8. 6
      packages/nc-gui-v2/components/smartsheet/Cell.vue
  9. 2
      packages/nc-gui-v2/composables/useColumn.ts
  10. 74
      packages/nc-gui-v2/package-lock.json
  11. 5
      packages/nc-gui-v2/utils/dateTimeUtils.ts

2
packages/nc-gui-v2/components.d.ts vendored

@ -16,6 +16,7 @@ declare module '@vue/runtime-core' {
ACol: typeof import('ant-design-vue/es')['Col'] ACol: typeof import('ant-design-vue/es')['Col']
ACollapse: typeof import('ant-design-vue/es')['Collapse'] ACollapse: typeof import('ant-design-vue/es')['Collapse']
ACollapsePanel: typeof import('ant-design-vue/es')['CollapsePanel'] ACollapsePanel: typeof import('ant-design-vue/es')['CollapsePanel']
ADatePicker: typeof import('ant-design-vue/es')['DatePicker']
ADivider: typeof import('ant-design-vue/es')['Divider'] ADivider: typeof import('ant-design-vue/es')['Divider']
ADrawer: typeof import('ant-design-vue/es')['Drawer'] ADrawer: typeof import('ant-design-vue/es')['Drawer']
ADropdown: typeof import('ant-design-vue/es')['Dropdown'] ADropdown: typeof import('ant-design-vue/es')['Dropdown']
@ -54,6 +55,7 @@ declare module '@vue/runtime-core' {
ATag: typeof import('ant-design-vue/es')['Tag'] ATag: typeof import('ant-design-vue/es')['Tag']
ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATooltip: typeof import('ant-design-vue/es')['Tooltip'] ATooltip: typeof import('ant-design-vue/es')['Tooltip']
ATypographyText: typeof import('ant-design-vue/es')['TypographyText']
ATypographyTitle: typeof import('ant-design-vue/es')['TypographyTitle'] ATypographyTitle: typeof import('ant-design-vue/es')['TypographyTitle']
AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger'] AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']

71
packages/nc-gui-v2/components/cell/Currency.vue

@ -1,36 +1,49 @@
<script> <script setup lang="ts">
export default { import { computed, inject } from '#imports'
name: 'CurrencyCell', import { ColumnInj } from '~/context'
props: {
column: Object, const { modelValue: value } = defineProps<Props>()
value: [String, Number],
}, const emit = defineEmits(['update:modelValue'])
computed: {
currency() { const column = inject(ColumnInj)
try {
return isNaN(this.value) const editEnabled = inject<boolean>('editEnabled')
? this.value
: new Intl.NumberFormat(this.currencyMeta.currency_locale || 'en-US', { interface Props {
style: 'currency', modelValue: number
currency: this.currencyMeta.currency_code || 'USD',
}).format(this.value)
} catch (e) {
return this.value
}
},
currencyMeta() {
return {
currency_locale: 'en-US',
currency_code: 'USD',
...(this.column && this.column.meta ? this.column.meta : {}),
}
},
},
} }
const root = ref<HTMLInputElement>()
const localState = computed({
get: () => value,
set: (val) => emit('update:modelValue', val),
})
const currencyMeta = computed(() => {
return {
currency_locale: 'en-US',
currency_code: 'USD',
...(column && column.meta ? column.meta : {}),
}
})
const currency = computed(() => {
try {
return isNaN(value)
? value
: new Intl.NumberFormat(currencyMeta?.value?.currency_locale || 'en-US', {
style: 'currency',
currency: currencyMeta?.value?.currency_code || 'USD',
}).format(value)
} catch (e) {
return value
}
})
</script> </script>
<template> <template>
<a v-if="value">{{ currency }}</a> <input v-if="editEnabled" ref="root" v-model="localState" />
<span v-else-if="value">{{ currency }}</span>
<span v-else /> <span v-else />
</template> </template>

103
packages/nc-gui-v2/components/cell/DatePicker.vue

@ -1,91 +1,60 @@
<script setup lang="ts"> <script setup lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { computed } from '#imports' import { ColumnInj, ReadonlyInj } from '~/context'
const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
interface Props { interface Props {
modelValue: string modelValue: string
} }
const { modelValue } = defineProps<Props>() const columnMeta = inject(ColumnInj, null)
const readOnlyMode = inject(ReadonlyInj, false)
const emit = defineEmits(['update:modelValue']) let isDateInvalid = $ref(false)
const dateFormat = columnMeta?.meta?.date_format ?? 'YYYY-MM-DD'
const localState = computed({ const localState = $computed({
get() { get() {
if (!modelValue || !dayjs(modelValue).isValid()) { if (!modelValue) {
return undefined return undefined
} }
return (/^\d+$/.test(modelValue) ? dayjs(+modelValue) : dayjs(modelValue)).format('YYYY-MM-DD') if (!dayjs(modelValue).isValid()) {
}, isDateInvalid = true
set(val?: string) { return undefined
if (dayjs(val).isValid()) {
emit('update:modelValue', val && dayjs(val).format('YYYY-MM-DD'))
} }
},
})
/*
export default { return /^\d+$/.test(modelValue) ? dayjs(+modelValue) : dayjs(modelValue)
name: 'DatePickerCell',
props: {
value: [String, Date],
}, },
computed: { set(val?: dayjs.Dayjs) {
localState: { if (!val) {
get() { emit('update:modelValue', null)
if (!this.value || !dayjs(this.value).isValid()) { return
return undefined }
}
return (/^\d+$/.test(this.value) ? dayjs(+this.value) : dayjs(this.value)).format('YYYY-MM-DD')
},
set(val) {
if (dayjs(val).isValid()) {
this.$emit('input', val && dayjs(val).format('YYYY-MM-DD'))
}
},
},
date() {
if (!this.value || this.localState) {
return this.localState
}
return 'Invalid Date'
},
parentListeners() {
const $listeners = {}
if (this.$listeners.blur) {
$listeners.blur = this.$listeners.blur
}
if (this.$listeners.focus) {
$listeners.focus = this.$listeners.focus
}
return $listeners if (val.isValid()) {
}, emit('update:modelValue', val?.format('YYYY-MM-DD'))
},
mounted() {
if (this.$el && this.$el.$el) {
this.$el.$el.focus()
} }
}, },
} */ })
</script> </script>
<template> <template>
<!-- <v-menu> --> <a-date-picker
<!-- <template #activator="{ on }"> --> v-model:value="localState"
<input v-model="localState" type="date" class="value" /> :bordered="false"
<!-- </template> --> class="!w-full px-1"
<!-- <v-date-picker v-model="localState" flat @click.native.stop v-on="parentListeners" /> --> :format="dateFormat"
<!-- </v-menu> --> :placeholder="isDateInvalid ? 'Invalid date' : !readOnlyMode ? 'Select date' : ''"
:allow-clear="!readOnlyMode"
:input-read-only="true"
:open="readOnlyMode ? false : undefined"
>
<template v-if="readOnlyMode" #suffixIcon></template>
</a-date-picker>
</template> </template>
<style scoped> <style scoped></style>
.value {
width: 100%;
min-height: 20px;
}
</style>

160
packages/nc-gui-v2/components/cell/DateTimePicker.vue

@ -1,146 +1,62 @@
<script setup lang="ts"> <script setup lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { computed, ref, useProject } from '#imports' import { ReadonlyInj } from '~/context'
interface Props {
modelValue?: string
}
const { modelValue } = defineProps<Props>() const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
interface Props {
modelValue: string
}
const { isMysql } = useProject() const { isMysql } = useProject()
const showMessage = ref(false)
const localState = computed({ const readOnlyMode = inject(ReadonlyInj, false)
let isDateInvalid = $ref(false)
const dateFormat = isMysql ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD HH:mm:ssZ'
const localState = $computed({
get() { get() {
if (!modelValue) { if (!modelValue) {
return modelValue return undefined
}
const d = /^\d+$/.test(modelValue) ? dayjs(+modelValue) : dayjs(modelValue)
if (d.isValid()) {
showMessage.value = false
return d.format('YYYY-MM-DD HH:mm')
} else {
showMessage.value = true
}
},
set(value?: string) {
if (isMysql) {
emit('update:modelValue', value && dayjs(value).format('YYYY-MM-DD HH:mm:ss'))
} else {
emit('update:modelValue', value && dayjs(value).format('YYYY-MM-DD HH:mm:ssZ'))
} }
},
})
/* import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
dayjs.extend(utc)
export default { if (!dayjs(modelValue).isValid()) {
name: 'DateTimePickerCell', isDateInvalid = true
props: { return undefined
value: [String, Date, Number], }
ignoreFocus: Boolean,
},
data: () => ({
showMessage: false,
}),
computed: {
isMysql() {
return ['mysql', 'mysql2'].indexOf(this.$store.getters['project/GtrClientType'])
},
localState: {
get() {
if (!this.value) {
return this.value
}
const d = /^\d+$/.test(this.value) ? dayjs(+this.value) : dayjs(this.value)
if (d.isValid()) {
this.showMessage = false
return d.format('YYYY-MM-DD HH:mm')
} else {
this.showMessage = true
}
},
set(value) {
if (this.isMysql) {
this.$emit('input', value && dayjs(value).format('YYYY-MM-DD HH:mm:ss'))
} else {
this.$emit('input', value && dayjs(value).format('YYYY-MM-DD HH:mm:ssZ'))
}
},
},
parentListeners() {
const $listeners = {}
if (this.$listeners.blur) {
// $listeners.blur = this.$listeners.blur
}
if (this.$listeners.focus) {
$listeners.focus = this.$listeners.focus
}
return $listeners return /^\d+$/.test(modelValue) ? dayjs(+modelValue) : dayjs(modelValue)
},
}, },
mounted() { set(val?: dayjs.Dayjs) {
// listen dialog click:outside event and save on close if (!val) {
if (this.$refs.picker && this.$refs.picker.$children && this.$refs.picker.$children[0]) { emit('update:modelValue', null)
this.$refs.picker.$children[0].$on('click:outside', () => { return
this.$refs.picker.okHandler()
})
} }
if (!this.ignoreFocus) { if (val.isValid()) {
this.$refs.picker.display = true emit('update:modelValue', val?.format(dateFormat))
} }
}, },
} */ })
</script> </script>
<template> <template>
<input v-model="localState" type="datetime-local" /> <a-date-picker
<!-- <div> --> v-model:value="localState"
<!-- <div v-show="!showMessage"> --> :show-time="true"
<!-- <v-datetime-picker --> :bordered="false"
<!-- ref="picker" --> class="!w-full px-1"
<!-- v-model="localState" --> format="YYYY-MM-DD HH:mm"
<!-- class="caption xc-date-time-picker" --> :placeholder="isDateInvalid ? 'Invalid date' : !readOnlyMode ? 'Select date' : ''"
<!-- :text-field-props="{ --> :allow-clear="!readOnlyMode"
<!-- class: 'caption mt-0 pt-0', --> :input-read-only="true"
<!-- flat: true, --> :open="readOnlyMode ? false : undefined"
<!-- solo: true, --> >
<!-- dense: true, --> <template v-if="readOnlyMode" #suffixIcon></template>
<!-- hideDetails: true, --> </a-date-picker>
<!-- }" -->
<!-- :time-picker-props="{ -->
<!-- format: '24hr', -->
<!-- }" -->
<!-- v-on="parentListeners" -->
<!-- /> -->
<!-- </div> -->
<!-- <div v-show="showMessage" class="edit-warning" @dblclick="$refs.picker.display = true"> -->
<!-- &lt;!&ndash; TODO: i18n &ndash;&gt; -->
<!-- ERR: Couldn't parse {{ value }} -->
<!-- </div> -->
<!-- </div> -->
</template> </template>
<style scoped> <style scoped></style>
/*:deep(.v-input),*/
/*:deep(.v-text-field) {*/
/* margin-top: 0 !important;*/
/* padding-top: 0 !important;*/
/* font-size: inherit !important;*/
/*}*/
/*.edit-warning {*/
/* padding: 10px;*/
/* text-align: left;*/
/* color: #e65100;*/
/*}*/
</style>

27
packages/nc-gui-v2/components/cell/Email.vue

@ -1,15 +1,24 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed } from '#imports' import { computed } from '#imports'
import { isEmail } from '~/utils/validation' import { isEmail } from '~/utils/validation'
const { modelValue: value } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const editEnabled = inject<boolean>('editEnabled')
interface Props { interface Props {
modelValue: string modelValue: string
} }
const { modelValue } = defineProps<Props>() const root = ref<HTMLInputElement>()
const localState = computed({
get: () => value,
set: (val) => emit('update:modelValue', val),
})
const validEmail = computed(() => isEmail(modelValue)) const validEmail = computed(() => isEmail(value))
</script> </script>
<script lang="ts"> <script lang="ts">
@ -19,6 +28,14 @@ export default {
</script> </script>
<template> <template>
<a v-if="validEmail" :href="`mailto:${modelValue}`" target="_blank">{{ modelValue }}</a> <input v-if="editEnabled" ref="root" v-model="localState" />
<span v-else>{{ modelValue }}</span> <a
v-else-if="validEmail"
class="caption py-2 text-primary underline hover:opacity-75"
:href="`mailto:${value}`"
target="_blank"
>
{{ value }}
</a>
<span v-else>{{ value }}</span>
</template> </template>

59
packages/nc-gui-v2/components/cell/YearPicker.vue

@ -0,0 +1,59 @@
<script setup lang="ts">
import dayjs from 'dayjs'
import { ReadonlyInj } from '~/context'
const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
interface Props {
modelValue: number
}
const readOnlyMode = inject(ReadonlyInj, false)
let isYearInvalid = $ref(false)
const localState = $computed({
get() {
if (!modelValue) {
return undefined
}
const yearDate = dayjs(modelValue.toString(), 'YYYY')
if (!yearDate.isValid()) {
isYearInvalid = true
return undefined
}
return yearDate
},
set(val?: dayjs.Dayjs) {
if (!val) {
emit('update:modelValue', null)
return
}
if (val?.isValid()) {
emit('update:modelValue', Number(val.format('YYYY')))
}
},
})
</script>
<template>
<a-date-picker
v-model:value="localState"
picker="year"
:bordered="false"
class="!w-full px-1"
:placeholder="isYearInvalid ? 'Invalid year' : !readOnlyMode ? 'Select year' : ''"
:allow-clear="!readOnlyMode"
:input-read-only="true"
:open="readOnlyMode ? false : undefined"
>
<template v-if="readOnlyMode" #suffixIcon></template>
</a-date-picker>
</template>
<style scoped></style>

6
packages/nc-gui-v2/components/smartsheet-header/CellIcon.vue

@ -16,6 +16,8 @@ import RatingIcon from '~icons/mdi/star'
import GenericIcon from '~icons/mdi/square-rounded' import GenericIcon from '~icons/mdi/square-rounded'
import AttachmentIcon from '~icons/mdi/image-multiple-outline' import AttachmentIcon from '~icons/mdi/image-multiple-outline'
import URLIcon from '~icons/mdi/link' import URLIcon from '~icons/mdi/link'
import EmailIcon from '~icons/mdi/email'
import CurrencyIcon from '~icons/mdi/currency-usd-circle-outline'
const column = inject(ColumnInj) const column = inject(ColumnInj)
@ -38,6 +40,8 @@ const icon = computed(() => {
return BooleanIcon return BooleanIcon
} else if (additionalColMeta.isTextArea) { } else if (additionalColMeta.isTextArea) {
return TextAreaIcon return TextAreaIcon
} else if (additionalColMeta.isEmail) {
return EmailIcon
} else if (additionalColMeta.isRating) { } else if (additionalColMeta.isRating) {
return RatingIcon return RatingIcon
} else if (additionalColMeta.isAttachment) { } else if (additionalColMeta.isAttachment) {
@ -48,6 +52,8 @@ const icon = computed(() => {
// } // }
else if (additionalColMeta.isURL) { else if (additionalColMeta.isURL) {
return URLIcon return URLIcon
} else if (additionalColMeta.isCurrency) {
return CurrencyIcon
} else if (additionalColMeta.isString) { } else if (additionalColMeta.isString) {
return h(StringIcon, { return h(StringIcon, {
class: 'text-[1.5rem]', class: 'text-[1.5rem]',

6
packages/nc-gui-v2/components/smartsheet/Cell.vue

@ -32,6 +32,7 @@ const {
isEmail, isEmail,
isJSON, isJSON,
isDate, isDate,
isYear,
isDateTime, isDateTime,
isTime, isTime,
isBoolean, isBoolean,
@ -51,8 +52,6 @@ const {
<!-- <!--
todo : todo :
JSONCell JSONCell
Currency
Email
--> -->
<!-- <RatingCell --> <!-- <RatingCell -->
@ -177,6 +176,7 @@ todo :
<CellSingleSelect v-else-if="isSingleSelect" v-model="localState" /> <CellSingleSelect v-else-if="isSingleSelect" v-model="localState" />
<CellMultiSelect v-else-if="isMultiSelect" v-model="localState" /> <CellMultiSelect v-else-if="isMultiSelect" v-model="localState" />
<CellDatePicker v-else-if="isDate" v-model="localState" /> <CellDatePicker v-else-if="isDate" v-model="localState" />
<CellYearPicker v-else-if="isYear" v-model="localState" />
<CellDateTimePicker v-else-if="isDateTime" v-model="localState" /> <CellDateTimePicker v-else-if="isDateTime" v-model="localState" />
<CellDateTimePicker v-else-if="isTime" v-model="localState" /> <CellDateTimePicker v-else-if="isTime" v-model="localState" />
<CellRating v-else-if="isRating" v-model="localState" /> <CellRating v-else-if="isRating" v-model="localState" />
@ -193,10 +193,12 @@ todo :
v-on="$listeners" v-on="$listeners"
/> --> /> -->
<CellDuration v-else-if="isDuration" v-model="localState" /> <CellDuration v-else-if="isDuration" v-model="localState" />
<CellEmail v-else-if="isEmail" v-model="localState" />
<CellUrl v-else-if="isURL" v-model="localState" /> <CellUrl v-else-if="isURL" v-model="localState" />
<!-- v-on="parentListeners" <!-- v-on="parentListeners"
/> />
--> -->
<CellCurrency v-else-if="isCurrency" v-model="localState" />
<CellText v-else-if="isString" v-model="localState" /> <CellText v-else-if="isString" v-model="localState" />
<!-- v-on="parentListeners" <!-- v-on="parentListeners"
/> />

2
packages/nc-gui-v2/composables/useColumn.ts

@ -17,6 +17,7 @@ export default (column: ColumnType) => {
const isInt = abstractType === 'integer' const isInt = abstractType === 'integer'
const isFloat = abstractType === 'float' const isFloat = abstractType === 'float'
const isDate = abstractType === 'date' || uiDatatype === 'Date' const isDate = abstractType === 'date' || uiDatatype === 'Date'
const isYear = abstractType === 'year' || uiDatatype === 'Year'
const isTime = abstractType === 'time' || uiDatatype === 'Time' const isTime = abstractType === 'time' || uiDatatype === 'Time'
const isDateTime = abstractType === 'datetime' || uiDatatype === 'DateTime' const isDateTime = abstractType === 'datetime' || uiDatatype === 'DateTime'
const isJSON = uiDatatype === 'JSON' const isJSON = uiDatatype === 'JSON'
@ -55,6 +56,7 @@ export default (column: ColumnType) => {
isInt, isInt,
isFloat, isFloat,
isDate, isDate,
isYear,
isTime, isTime,
isDateTime, isDateTime,
isJSON, isJSON,

74
packages/nc-gui-v2/package-lock.json generated

@ -10478,14 +10478,15 @@
} }
}, },
"node_modules/@intlify/bundle-utils": { "node_modules/@intlify/bundle-utils": {
"version": "2.2.2", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/@intlify/bundle-utils/-/bundle-utils-3.1.0.tgz",
"integrity": "sha512-ghlJ0kR2cCQ8D+poKknC0Xx0ncOt3J3os7CcIAqqIWVF7k6AtGoCDnIru+YzlZcvFRNmP9wEZ7jKliojCdAWNg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@intlify/message-compiler": "^9.1.0", "@intlify/message-compiler": "next",
"@intlify/shared": "^9.1.0", "@intlify/shared": "next",
"jsonc-eslint-parser": "^1.0.1", "jsonc-eslint-parser": "^1.0.1",
"source-map": "^0.6.1", "source-map": "0.6.1",
"yaml-eslint-parser": "^0.3.2" "yaml-eslint-parser": "^0.3.2"
}, },
"engines": { "engines": {
@ -10500,6 +10501,28 @@
} }
} }
}, },
"node_modules/@intlify/bundle-utils/node_modules/@intlify/message-compiler": {
"version": "9.2.0-beta.40",
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.0-beta.40.tgz",
"integrity": "sha512-6QWTSYewmkew4nsRqgkwTVuGFKzxVCOK8EXsPt15N+tN1g+OYjC3PfGA2dPB6cVkNxqA9mV/hNK02uHPWU9t0A==",
"dev": true,
"dependencies": {
"@intlify/shared": "9.2.0-beta.40",
"source-map": "0.6.1"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@intlify/bundle-utils/node_modules/@intlify/shared": {
"version": "9.2.0-beta.40",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.0-beta.40.tgz",
"integrity": "sha512-xWz+SFjgt/LfaSbbHVn+V7gmvX4ZNP3cIFta790GWZ/tEgwJeC3tkV7i45iUbZ4ZimOerFgKH05b7qvJlKb6RQ==",
"dev": true,
"engines": {
"node": ">= 14"
}
},
"node_modules/@intlify/bundle-utils/node_modules/acorn": { "node_modules/@intlify/bundle-utils/node_modules/acorn": {
"version": "7.4.1", "version": "7.4.1",
"dev": true, "dev": true,
@ -10686,6 +10709,15 @@
} }
} }
}, },
"node_modules/@intlify/vite-plugin-vue-i18n/node_modules/@intlify/shared": {
"version": "9.2.0-beta.40",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.0-beta.40.tgz",
"integrity": "sha512-xWz+SFjgt/LfaSbbHVn+V7gmvX4ZNP3cIFta790GWZ/tEgwJeC3tkV7i45iUbZ4ZimOerFgKH05b7qvJlKb6RQ==",
"dev": true,
"engines": {
"node": ">= 14"
}
},
"node_modules/@intlify/vite-plugin-vue-i18n/node_modules/source-map": { "node_modules/@intlify/vite-plugin-vue-i18n/node_modules/source-map": {
"version": "0.6.1", "version": "0.6.1",
"dev": true, "dev": true,
@ -23075,16 +23107,34 @@
} }
}, },
"@intlify/bundle-utils": { "@intlify/bundle-utils": {
"version": "2.2.2", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/@intlify/bundle-utils/-/bundle-utils-3.1.0.tgz",
"integrity": "sha512-ghlJ0kR2cCQ8D+poKknC0Xx0ncOt3J3os7CcIAqqIWVF7k6AtGoCDnIru+YzlZcvFRNmP9wEZ7jKliojCdAWNg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@intlify/message-compiler": "^9.1.0", "@intlify/message-compiler": "next",
"@intlify/shared": "^9.1.0", "@intlify/shared": "next",
"jsonc-eslint-parser": "^1.0.1", "jsonc-eslint-parser": "^1.0.1",
"source-map": "^0.6.1", "source-map": "0.6.1",
"yaml-eslint-parser": "^0.3.2" "yaml-eslint-parser": "^0.3.2"
}, },
"dependencies": { "dependencies": {
"@intlify/message-compiler": {
"version": "9.2.0-beta.40",
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.0-beta.40.tgz",
"integrity": "sha512-6QWTSYewmkew4nsRqgkwTVuGFKzxVCOK8EXsPt15N+tN1g+OYjC3PfGA2dPB6cVkNxqA9mV/hNK02uHPWU9t0A==",
"dev": true,
"requires": {
"@intlify/shared": "9.2.0-beta.40",
"source-map": "0.6.1"
}
},
"@intlify/shared": {
"version": "9.2.0-beta.40",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.0-beta.40.tgz",
"integrity": "sha512-xWz+SFjgt/LfaSbbHVn+V7gmvX4ZNP3cIFta790GWZ/tEgwJeC3tkV7i45iUbZ4ZimOerFgKH05b7qvJlKb6RQ==",
"dev": true
},
"acorn": { "acorn": {
"version": "7.4.1", "version": "7.4.1",
"dev": true "dev": true
@ -23195,6 +23245,12 @@
"source-map": "0.6.1" "source-map": "0.6.1"
}, },
"dependencies": { "dependencies": {
"@intlify/shared": {
"version": "9.2.0-beta.40",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.0-beta.40.tgz",
"integrity": "sha512-xWz+SFjgt/LfaSbbHVn+V7gmvX4ZNP3cIFta790GWZ/tEgwJeC3tkV7i45iUbZ4ZimOerFgKH05b7qvJlKb6RQ==",
"dev": true
},
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"dev": true "dev": true

5
packages/nc-gui-v2/utils/dateTimeUtils.ts

@ -1,9 +1,14 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime' import relativeTime from 'dayjs/plugin/relativeTime'
import customParseFormat from 'dayjs/plugin/customParseFormat'
import utc from 'dayjs/plugin/utc' import utc from 'dayjs/plugin/utc'
import customParseFormat from 'dayjs/plugin/customParseFormat'
dayjs.extend(utc) dayjs.extend(utc)
dayjs.extend(relativeTime) dayjs.extend(relativeTime)
dayjs.extend(customParseFormat)
export const timeAgo = (date: any) => { export const timeAgo = (date: any) => {
return dayjs.utc(date).fromNow() return dayjs.utc(date).fromNow()

Loading…
Cancel
Save