@ramathibodi/nuxt-commons 0.1.52 → 0.1.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/components/document/TemplateBuilder.vue +3 -4
- package/dist/runtime/components/form/Table.vue +3 -2
- package/dist/runtime/components/label/DateAgo.vue +74 -23
- package/dist/runtime/components/model/Table.vue +4 -0
- package/dist/runtime/components/model/label.vue +1 -1
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -3,7 +3,7 @@ import {computed, ref, watch} from 'vue'
|
|
|
3
3
|
import * as prettier from 'prettier'
|
|
4
4
|
import prettierPluginHtml from 'prettier/plugins/html'
|
|
5
5
|
import {useDocumentTemplate, validationRulesRegex,optionStringToChoiceObject} from '../../composables/document/template'
|
|
6
|
-
import {cloneDeep} from "lodash-es";
|
|
6
|
+
import {cloneDeep , filter} from "lodash-es";
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
9
9
|
title?: string
|
|
@@ -323,7 +323,6 @@ const ruleOptions = (inputType: string) => (value: any) => {
|
|
|
323
323
|
</form-table>
|
|
324
324
|
</v-col>
|
|
325
325
|
<v-col cols="12">
|
|
326
|
-
{{optionData}}
|
|
327
326
|
<form-table v-model="optionData.items"
|
|
328
327
|
hide-default-footer
|
|
329
328
|
:importable="false"
|
|
@@ -343,14 +342,14 @@ const ruleOptions = (inputType: string) => (value: any) => {
|
|
|
343
342
|
</v-container>
|
|
344
343
|
</template>
|
|
345
344
|
|
|
346
|
-
<template v-for="header of
|
|
345
|
+
<template v-for="header of filter(optionData.headers,(item)=> item.template)" #[`item.${header.key}`]="{item}">
|
|
347
346
|
<form-pad
|
|
348
347
|
:template="header.template"
|
|
349
348
|
v-model="item[header.key]">
|
|
350
349
|
</form-pad>
|
|
351
350
|
|
|
352
351
|
</template>
|
|
353
|
-
<template v-for="header of
|
|
352
|
+
<template v-for="header of filter(optionData.headers,(item)=> item.headerTemplate)" #[`header.${header.key}`]="{item}">
|
|
354
353
|
<form-pad
|
|
355
354
|
:template="header.headerTemplate"
|
|
356
355
|
>
|
|
@@ -43,8 +43,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
43
43
|
stringFields: ()=>[],
|
|
44
44
|
})
|
|
45
45
|
|
|
46
|
-
const emit = defineEmits(['update:modelValue'])
|
|
47
|
-
|
|
46
|
+
const emit = defineEmits(['update:modelValue','open:dialog','close:dialog'])
|
|
48
47
|
const attrs = useAttrs()
|
|
49
48
|
const plainAttrs = computed(() => {
|
|
50
49
|
return omit(attrs, ['modelValue', 'onUpdate:modelValue'])
|
|
@@ -175,6 +174,7 @@ function openDialog(item?: object) {
|
|
|
175
174
|
currentItem.value = item
|
|
176
175
|
nextTick(() => {
|
|
177
176
|
isDialogOpen.value = true
|
|
177
|
+
emit('open:dialog',item)
|
|
178
178
|
})
|
|
179
179
|
}
|
|
180
180
|
}
|
|
@@ -325,6 +325,7 @@ defineExpose({
|
|
|
325
325
|
:form-data="currentItem"
|
|
326
326
|
@create="createItem"
|
|
327
327
|
@update="updateItem"
|
|
328
|
+
@afterLeave="emit('close:dialog')"
|
|
328
329
|
:saveAndStay="saveAndStay"
|
|
329
330
|
v-if="!props.inputPadOnly"
|
|
330
331
|
>
|
|
@@ -1,41 +1,92 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { DateTime
|
|
2
|
+
import { DateTime } from "luxon";
|
|
3
3
|
import { computed } from "vue";
|
|
4
4
|
|
|
5
|
+
type Unit = 'years' | 'months' | 'days' | 'hours' | 'minutes' | 'seconds';
|
|
6
|
+
type Locale = 'th' | 'en' | 'en-US' | 'th-TH';
|
|
7
|
+
|
|
5
8
|
interface Props {
|
|
6
9
|
modelValue: DateTime;
|
|
7
|
-
locale?:
|
|
10
|
+
locale?: Locale;
|
|
11
|
+
showSuffix?: boolean;
|
|
12
|
+
units?: Unit[];
|
|
8
13
|
}
|
|
9
14
|
|
|
10
15
|
const props = withDefaults(defineProps<Props>(), {
|
|
11
|
-
locale: '
|
|
16
|
+
locale: 'th',
|
|
17
|
+
showSuffix: true
|
|
12
18
|
});
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
// Fallback map: map complex locale (e.g., en-US) to base (e.g., en)
|
|
21
|
+
const normalizeLocale = (locale: Locale): 'en' | 'th' => {
|
|
22
|
+
if (locale.startsWith('en')) return 'en';
|
|
23
|
+
if (locale.startsWith('th')) return 'th';
|
|
24
|
+
return 'th'; // default fallback
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const localizedLabels: Record<'en' | 'th', Record<Unit, string>> = {
|
|
28
|
+
en: {
|
|
29
|
+
years: 'years',
|
|
30
|
+
months: 'months',
|
|
31
|
+
days: 'days',
|
|
32
|
+
hours: 'hours',
|
|
33
|
+
minutes: 'minutes',
|
|
34
|
+
seconds: 'seconds',
|
|
35
|
+
},
|
|
36
|
+
th: {
|
|
37
|
+
years: 'ปี',
|
|
38
|
+
months: 'เดือน',
|
|
39
|
+
days: 'วัน',
|
|
40
|
+
hours: 'ชั่วโมง',
|
|
41
|
+
minutes: 'นาที',
|
|
42
|
+
seconds: 'วินาที',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const localizedSuffix: Record<'en' | 'th', string> = {
|
|
47
|
+
en: 'ago',
|
|
48
|
+
th: 'ที่ผ่านมา',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const outputText = computed(() => {
|
|
15
52
|
const now = DateTime.now();
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
53
|
+
const baseLocale = normalizeLocale(props.locale);
|
|
54
|
+
|
|
55
|
+
const units: Unit[] = props.units?.length
|
|
56
|
+
? props.units
|
|
57
|
+
: ['years', 'months', 'days', 'hours', 'minutes', 'seconds'];
|
|
58
|
+
|
|
59
|
+
const diff = now.diff(props.modelValue, units).toObject();
|
|
60
|
+
|
|
61
|
+
if (!props.units) {
|
|
62
|
+
const foundUnit = units.find(unit => (diff[unit] ?? 0) >= 1);
|
|
63
|
+
const value = Math.floor(diff[foundUnit!] ?? 0);
|
|
64
|
+
const label = localizedLabels[baseLocale][foundUnit!];
|
|
65
|
+
const suffix = props.showSuffix ? localizedSuffix[baseLocale] : '';
|
|
66
|
+
return `${value} ${label}${suffix}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const parts = units.map(unit => {
|
|
70
|
+
const value = Math.floor(diff[unit] ?? 0);
|
|
71
|
+
if (value > 0) {
|
|
72
|
+
const label = localizedLabels[baseLocale][unit];
|
|
73
|
+
return `${value} ${label}`;
|
|
74
|
+
}
|
|
75
|
+
return '';
|
|
76
|
+
}).filter(Boolean);
|
|
77
|
+
|
|
78
|
+
if (parts.length === 0) {
|
|
79
|
+
const lastUnit = units.at(-1)!;
|
|
80
|
+
const label = localizedLabels[baseLocale][lastUnit];
|
|
81
|
+
const suffix = props.showSuffix ? localizedSuffix[baseLocale] : '';
|
|
82
|
+
return `0 ${label} ${suffix}`;
|
|
29
83
|
}
|
|
30
84
|
|
|
31
|
-
|
|
85
|
+
const suffix = props.showSuffix ? localizedSuffix[baseLocale] : '';
|
|
86
|
+
return `${parts.join(' ')} ${suffix}`;
|
|
32
87
|
});
|
|
33
88
|
</script>
|
|
34
89
|
|
|
35
90
|
<template>
|
|
36
|
-
<span>{{
|
|
91
|
+
<span>{{ outputText }}</span>
|
|
37
92
|
</template>
|
|
38
|
-
|
|
39
|
-
<style scoped>
|
|
40
|
-
|
|
41
|
-
</style>
|
|
@@ -46,6 +46,7 @@ const props = withDefaults(defineProps<Props & GraphqlModelProps>(), {
|
|
|
46
46
|
onlyOwnerEdit: false,
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
+
const emit = defineEmits(['open:dialog','close:dialog'])
|
|
49
50
|
const attrs = useAttrs()
|
|
50
51
|
const plainAttrs = computed(() => {
|
|
51
52
|
const returnAttrs = clone(attrs)
|
|
@@ -75,6 +76,7 @@ function openDialog(item?: object) {
|
|
|
75
76
|
currentItem.value = item
|
|
76
77
|
nextTick(() => {
|
|
77
78
|
isDialogOpen.value = true
|
|
79
|
+
emit('open:dialog' , item)
|
|
78
80
|
})
|
|
79
81
|
}
|
|
80
82
|
|
|
@@ -83,6 +85,7 @@ function openDialogReadonly(item?: object) {
|
|
|
83
85
|
currentItem.value = item
|
|
84
86
|
nextTick(() => {
|
|
85
87
|
isDialogOpen.value = true
|
|
88
|
+
emit('open:dialog' , item)
|
|
86
89
|
})
|
|
87
90
|
}
|
|
88
91
|
|
|
@@ -289,6 +292,7 @@ defineExpose({ reload,operation })
|
|
|
289
292
|
:form-data="currentItem"
|
|
290
293
|
@create="createItem"
|
|
291
294
|
@update="updateItem"
|
|
295
|
+
@afterLeave="emit('close:dialog')"
|
|
292
296
|
:saveAndStay="saveAndStay"
|
|
293
297
|
:readonly="isDialogReadonly"
|
|
294
298
|
>
|