@vc-shell/framework 1.0.189 → 1.0.190
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/CHANGELOG.md +17 -0
- package/core/types/index.ts +12 -1
- package/dist/core/types/index.d.ts +1 -1
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/framework.js +30667 -20092
- package/dist/index.css +1 -1
- package/dist/shared/components/error-interceptor/interceptor.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/EditorField.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/InputField.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/TextareaField.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/Card.stories.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/Checkbox.stories.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/ContentField.stories.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/EditorField.stories.d.ts +9 -0
- package/dist/shared/modules/dynamic/components/fields/storybook/EditorField.stories.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/InputField.stories.d.ts +12 -0
- package/dist/shared/modules/dynamic/components/fields/storybook/InputField.stories.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/TextareaField.stories.d.ts +12 -0
- package/dist/shared/modules/dynamic/components/fields/storybook/TextareaField.stories.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/factories/types/index.d.ts +1 -0
- package/dist/shared/modules/dynamic/factories/types/index.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/types/index.d.ts +15 -0
- package/dist/shared/modules/dynamic/types/index.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/atoms/vc-card/vc-card.stories.d.ts +16 -16
- package/dist/ui/components/molecules/vc-editor/vc-editor.stories.d.ts +16 -4
- package/dist/ui/components/molecules/vc-editor/vc-editor.stories.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-editor/vc-editor.vue.d.ts +2 -1
- package/dist/ui/components/molecules/vc-editor/vc-editor.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-input/vc-input.stories.d.ts +30 -16
- package/dist/ui/components/molecules/vc-input/vc-input.stories.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-input-currency/vc-input-currency.stories.d.ts +12 -12
- package/dist/ui/components/molecules/vc-textarea/vc-textarea.stories.d.ts +63 -63
- package/dist/ui/components/molecules/vc-textarea/vc-textarea.vue.d.ts +6 -6
- package/dist/ui/components/molecules/vc-textarea/vc-textarea.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue.d.ts +1 -0
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-column-switcher/vc-table-column-switcher.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/vc-table.stories.d.ts +8 -2
- package/dist/ui/components/organisms/vc-table/vc-table.stories.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts +3 -1
- package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
- package/package.json +8 -4
- package/shared/components/error-interceptor/interceptor.ts +1 -1
- package/shared/modules/dynamic/components/fields/EditorField.ts +1 -0
- package/shared/modules/dynamic/components/fields/InputField.ts +1 -0
- package/shared/modules/dynamic/components/fields/TextareaField.ts +1 -0
- package/shared/modules/dynamic/components/fields/storybook/Card.stories.ts +1 -2
- package/shared/modules/dynamic/components/fields/storybook/Checkbox.stories.ts +0 -1
- package/shared/modules/dynamic/components/fields/storybook/ContentField.stories.ts +1 -2
- package/shared/modules/dynamic/components/fields/storybook/EditorField.stories.ts +10 -3
- package/shared/modules/dynamic/components/fields/storybook/Fieldset.stories.ts +3 -3
- package/shared/modules/dynamic/components/fields/storybook/InputField.stories.ts +12 -0
- package/shared/modules/dynamic/components/fields/storybook/TextareaField.stories.ts +12 -0
- package/shared/modules/dynamic/factories/types/index.ts +2 -0
- package/shared/modules/dynamic/types/index.ts +15 -0
- package/shared/pages/LoginPage/components/login/Login.vue +1 -1
- package/ui/components/molecules/vc-editor/vc-editor.vue +24 -29
- package/ui/components/molecules/vc-input/vc-input.stories.ts +14 -0
- package/ui/components/molecules/vc-textarea/vc-textarea.stories.ts +1 -1
- package/ui/components/molecules/vc-textarea/vc-textarea.vue +4 -6
- package/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +1 -1
- package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +140 -108
- package/ui/components/organisms/vc-table/_internal/vc-table-column-switcher/vc-table-column-switcher.vue +20 -6
- package/ui/components/organisms/vc-table/vc-table.stories.ts +6 -2
- package/ui/components/organisms/vc-table/vc-table.vue +176 -125
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { template, templateWithVisibilityToggle } from "./common/templates";
|
|
2
2
|
import { Meta, StoryFn } from "@storybook/vue3";
|
|
3
|
-
import
|
|
4
|
-
import { computed, reactive, ref } from "vue";
|
|
3
|
+
import { reactive, ref } from "vue";
|
|
5
4
|
import page from "./pages/DynamicRender";
|
|
6
5
|
import * as _ from "lodash-es";
|
|
7
6
|
import { SchemaBaseArgTypes } from "./common/args";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Meta, StoryFn } from "@storybook/vue3";
|
|
2
|
-
import
|
|
3
|
-
import { computed, reactive, ref } from "vue";
|
|
2
|
+
import { reactive, ref } from "vue";
|
|
4
3
|
import page from "./pages/DynamicRender";
|
|
5
4
|
import { template, templateWithVisibilityToggle } from "./common/templates";
|
|
6
5
|
import * as _ from "lodash-es";
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Meta, StoryFn } from "@storybook/vue3";
|
|
2
|
-
import EditorField from "../EditorField";
|
|
3
2
|
import { template, templateWithVisibilityToggle } from "./common/templates";
|
|
4
3
|
import page from "./pages/DynamicRender";
|
|
5
|
-
import {
|
|
6
|
-
import * as _ from "lodash-es";
|
|
4
|
+
import { reactive, ref } from "vue";
|
|
7
5
|
import { SchemaBaseArgTypes } from "./common/args";
|
|
8
6
|
import { EditorSchema } from "../../..";
|
|
9
7
|
|
|
@@ -44,6 +42,15 @@ export default {
|
|
|
44
42
|
},
|
|
45
43
|
},
|
|
46
44
|
},
|
|
45
|
+
maxlength: {
|
|
46
|
+
description: "Maximum length of the editor content.",
|
|
47
|
+
control: "number",
|
|
48
|
+
table: {
|
|
49
|
+
type: {
|
|
50
|
+
summary: "number",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
47
54
|
},
|
|
48
55
|
parameters: {
|
|
49
56
|
docs: {
|
|
@@ -73,13 +73,13 @@ export default {
|
|
|
73
73
|
description: `Array of numbers that define the aspect ratio of each column.
|
|
74
74
|
Example - If you have two columns - set to [1, 1] to make all columns equal width.
|
|
75
75
|
Uses CSS flex-grow property to set the width of each column.`,
|
|
76
|
-
control: "
|
|
76
|
+
control: "object",
|
|
77
77
|
table: {
|
|
78
78
|
type: {
|
|
79
|
-
summary: "
|
|
79
|
+
summary: "array",
|
|
80
80
|
},
|
|
81
81
|
defaultValue: {
|
|
82
|
-
summary: "1
|
|
82
|
+
summary: "[1, 1]",
|
|
83
83
|
},
|
|
84
84
|
},
|
|
85
85
|
},
|
|
@@ -87,6 +87,18 @@ export default {
|
|
|
87
87
|
},
|
|
88
88
|
},
|
|
89
89
|
},
|
|
90
|
+
maxlength: {
|
|
91
|
+
description: "Maximum number of characters that can be entered.",
|
|
92
|
+
control: "number",
|
|
93
|
+
table: {
|
|
94
|
+
type: {
|
|
95
|
+
summary: "number",
|
|
96
|
+
},
|
|
97
|
+
defaultValue: {
|
|
98
|
+
summary: 1024,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
90
102
|
},
|
|
91
103
|
parameters: {
|
|
92
104
|
docs: {
|
|
@@ -38,6 +38,18 @@ export default {
|
|
|
38
38
|
},
|
|
39
39
|
},
|
|
40
40
|
},
|
|
41
|
+
maxlength: {
|
|
42
|
+
description: "Maximum number of characters that can be entered.",
|
|
43
|
+
control: "number",
|
|
44
|
+
table: {
|
|
45
|
+
type: {
|
|
46
|
+
summary: "number",
|
|
47
|
+
},
|
|
48
|
+
defaultValue: {
|
|
49
|
+
summary: "1024",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
41
53
|
},
|
|
42
54
|
parameters: {
|
|
43
55
|
docs: {
|
|
@@ -80,6 +80,8 @@ export interface ListBaseBladeScope<Item = Record<string, any>, Query = Record<s
|
|
|
80
80
|
breadcrumbs?: ComputedRef<Breadcrumbs[]>;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
export type TOpenBladeArgs = Omit<Parameters<ReturnType<typeof useBladeNavigation>["openBlade"]>["0"], "blade">;
|
|
84
|
+
|
|
83
85
|
export interface DetailsBaseBladeScope extends BaseBladeScope {
|
|
84
86
|
disabled?: ComputedRef<boolean | undefined>;
|
|
85
87
|
multilanguage?: {
|
|
@@ -387,6 +387,11 @@ export interface TextareaSchema extends SchemaBase {
|
|
|
387
387
|
* @type {boolean}
|
|
388
388
|
*/
|
|
389
389
|
clearable?: boolean;
|
|
390
|
+
/**
|
|
391
|
+
* Maximum number of characters that can be entered.
|
|
392
|
+
* @type {number}
|
|
393
|
+
*/
|
|
394
|
+
maxlength?: number;
|
|
390
395
|
}
|
|
391
396
|
|
|
392
397
|
/**
|
|
@@ -429,6 +434,11 @@ export interface InputSchema extends SchemaBase {
|
|
|
429
434
|
* @type {ControlSchema}
|
|
430
435
|
*/
|
|
431
436
|
prependInner?: ControlSchema;
|
|
437
|
+
/**
|
|
438
|
+
* Maximum number of characters that can be entered.
|
|
439
|
+
* @type {number}
|
|
440
|
+
*/
|
|
441
|
+
maxlength?: number;
|
|
432
442
|
}
|
|
433
443
|
|
|
434
444
|
/**
|
|
@@ -628,6 +638,11 @@ export interface EditorSchema extends SchemaBase {
|
|
|
628
638
|
* @type {string}
|
|
629
639
|
*/
|
|
630
640
|
assetsFolder: string;
|
|
641
|
+
/**
|
|
642
|
+
* Maximum length of the editor content.
|
|
643
|
+
* @type {number}
|
|
644
|
+
*/
|
|
645
|
+
maxlength?: number;
|
|
631
646
|
}
|
|
632
647
|
|
|
633
648
|
/**
|
|
@@ -197,7 +197,7 @@ const props = defineProps<Props>();
|
|
|
197
197
|
|
|
198
198
|
const router = useRouter();
|
|
199
199
|
|
|
200
|
-
const {
|
|
200
|
+
const { validateField } = useForm({ validateOnMount: false });
|
|
201
201
|
const { uiSettings, loading: customizationLoading } = useSettings();
|
|
202
202
|
const { t } = useI18n({ useScope: "global" });
|
|
203
203
|
let useLogin;
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
:id="id"
|
|
30
30
|
:key="`${id}-${disabled}`"
|
|
31
31
|
ref="quillRef"
|
|
32
|
-
:content="
|
|
32
|
+
:content="modelValue"
|
|
33
33
|
class="quill-editor tw-border tw-border-solid tw-border-[color:var(--editor-border-color)] tw-rounded-b-[var(--editor-border-radius)] tw-h-[200px]"
|
|
34
34
|
:class="{ 'tw-bg-[#fafafa] tw-text-[#424242] tw-cursor-default': disabled }"
|
|
35
35
|
theme="snow"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
:read-only="disabled"
|
|
40
40
|
:placeholder="placeholder"
|
|
41
41
|
:options="options"
|
|
42
|
-
@
|
|
42
|
+
@ready="initializeQuill"
|
|
43
43
|
/>
|
|
44
44
|
<slot
|
|
45
45
|
v-if="errorMessage"
|
|
@@ -53,15 +53,15 @@
|
|
|
53
53
|
</template>
|
|
54
54
|
<!-- eslint-disable @typescript-eslint/no-explicit-any -->
|
|
55
55
|
<script lang="ts" setup>
|
|
56
|
-
import { QuillEditor
|
|
56
|
+
import { QuillEditor } from "@vueup/vue-quill";
|
|
57
57
|
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
|
58
|
-
import { ref, unref,
|
|
58
|
+
import { ref, unref, onMounted, onUpdated, getCurrentInstance, Ref } from "vue";
|
|
59
59
|
import ImageUploader from "quill-image-uploader";
|
|
60
60
|
import { VcLabel, VcHint } from "../..";
|
|
61
61
|
|
|
62
62
|
export interface Props {
|
|
63
63
|
placeholder?: string;
|
|
64
|
-
modelValue?: string
|
|
64
|
+
modelValue?: string;
|
|
65
65
|
required?: boolean;
|
|
66
66
|
disabled?: boolean;
|
|
67
67
|
label?: string;
|
|
@@ -70,6 +70,7 @@ export interface Props {
|
|
|
70
70
|
assetsFolder: string;
|
|
71
71
|
multilanguage?: boolean;
|
|
72
72
|
currentLanguage?: string;
|
|
73
|
+
maxlength?: number;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
export interface Emits {
|
|
@@ -86,8 +87,9 @@ defineSlots<{
|
|
|
86
87
|
error?: (props: any) => any;
|
|
87
88
|
}>();
|
|
88
89
|
|
|
89
|
-
const content = ref();
|
|
90
|
-
const quillRef = ref<
|
|
90
|
+
// const content = ref();
|
|
91
|
+
const quillRef = ref(null) as Ref<typeof QuillEditor | null>;
|
|
92
|
+
const quill = ref();
|
|
91
93
|
|
|
92
94
|
const toolbar = {
|
|
93
95
|
container: [
|
|
@@ -139,39 +141,32 @@ onUpdated(() => {
|
|
|
139
141
|
removeBlankClass();
|
|
140
142
|
});
|
|
141
143
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
},
|
|
151
|
-
{ immediate: true },
|
|
152
|
-
);
|
|
144
|
+
function initializeQuill() {
|
|
145
|
+
quill.value = quillRef.value?.getQuill();
|
|
146
|
+
if (props.modelValue) {
|
|
147
|
+
quill.value.root.innerHTML = unref(props.modelValue);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
quill.value.on("text-change", onTextChange);
|
|
151
|
+
}
|
|
153
152
|
|
|
154
153
|
function removeBlankClass() {
|
|
155
154
|
// fixes quill editor placeholder visibility issue when content is not empty
|
|
156
155
|
const editor = document.getElementById(id)?.querySelector(".ql-editor.ql-blank");
|
|
157
|
-
if (editor &&
|
|
156
|
+
if (editor && props.modelValue) {
|
|
158
157
|
editor.classList.remove("ql-blank");
|
|
159
158
|
}
|
|
160
159
|
}
|
|
161
160
|
|
|
162
|
-
function
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
emit("update:modelValue", value);
|
|
161
|
+
function onTextChange() {
|
|
162
|
+
const len = quill.value.getLength();
|
|
163
|
+
if (props.maxlength !== undefined && len > props.maxlength) {
|
|
164
|
+
quill.value.deleteText(props.maxlength, len);
|
|
167
165
|
}
|
|
168
|
-
}
|
|
169
166
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return true;
|
|
167
|
+
if (quill.value.getText().trim() !== props.modelValue?.trim()) {
|
|
168
|
+
emit("update:modelValue", quill.value.root.innerHTML);
|
|
173
169
|
}
|
|
174
|
-
return false;
|
|
175
170
|
}
|
|
176
171
|
</script>
|
|
177
172
|
|
|
@@ -9,6 +9,20 @@ export default {
|
|
|
9
9
|
label: "This is an input",
|
|
10
10
|
placeholder: "Placeholder",
|
|
11
11
|
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
maxlength: {
|
|
14
|
+
description: "Maximum number of characters that can be entered.",
|
|
15
|
+
control: "number",
|
|
16
|
+
table: {
|
|
17
|
+
type: {
|
|
18
|
+
summary: "number",
|
|
19
|
+
},
|
|
20
|
+
defaultValue: {
|
|
21
|
+
summary: 1024,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
12
26
|
} satisfies Meta<typeof VcInput>;
|
|
13
27
|
|
|
14
28
|
export const Template: StoryFn<typeof VcInput> = (args) => ({
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
:placeholder="placeholder"
|
|
31
31
|
:value="modelValue"
|
|
32
32
|
:disabled="disabled"
|
|
33
|
-
:maxlength="
|
|
33
|
+
:maxlength="maxlength"
|
|
34
34
|
@input="onInput"
|
|
35
35
|
></textarea>
|
|
36
36
|
</div>
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
</template>
|
|
48
48
|
|
|
49
49
|
<script lang="ts" setup>
|
|
50
|
-
import { watch } from "vue";
|
|
51
50
|
import { VcHint, VcLabel } from "./../../";
|
|
52
51
|
|
|
53
52
|
export interface Props {
|
|
@@ -58,7 +57,7 @@ export interface Props {
|
|
|
58
57
|
label?: string;
|
|
59
58
|
tooltip?: string;
|
|
60
59
|
name?: string;
|
|
61
|
-
|
|
60
|
+
maxlength?: string;
|
|
62
61
|
errorMessage?: string;
|
|
63
62
|
multilanguage?: boolean;
|
|
64
63
|
currentLanguage?: string;
|
|
@@ -69,13 +68,12 @@ export interface Emits {
|
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
defineSlots<{
|
|
72
|
-
|
|
73
|
-
error: (props: any) => any;
|
|
71
|
+
error: void;
|
|
74
72
|
}>();
|
|
75
73
|
|
|
76
74
|
withDefaults(defineProps<Props>(), {
|
|
77
75
|
name: "Field",
|
|
78
|
-
|
|
76
|
+
maxlength: "1024",
|
|
79
77
|
});
|
|
80
78
|
|
|
81
79
|
const emit = defineEmits<Emits>();
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
<div class="tw-overflow-hidden tw-grow tw-basis-0">
|
|
16
16
|
<div
|
|
17
|
-
class="tw-text-[color:var(--blade-header-title-color)] tw-text-lg tw-truncate"
|
|
17
|
+
class="tw-text-[color:var(--blade-header-title-color)] tw-text-lg/[23px] tw-truncate"
|
|
18
18
|
:class="{
|
|
19
19
|
'!tw-text-[length:var(--blade-header-title-font-size)] tw-font-medium': !subtitle,
|
|
20
20
|
}"
|
|
@@ -1,124 +1,150 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
<
|
|
5
|
-
v-if="typeof Number(value) === 'number' && Number(value) > 0"
|
|
6
|
-
class="tw-truncate"
|
|
7
|
-
>
|
|
8
|
-
<span class="tw-truncate">{{ Math.trunc(Number(value)) }}</span
|
|
9
|
-
><span class="tw-text-[#a5a5a5] tw-text-xs tw-truncate"
|
|
10
|
-
>.{{ `${(Number(value) * 100) % 100}`.padEnd(2, "0").slice(0, 2) }}</span
|
|
11
|
-
>
|
|
12
|
-
</div>
|
|
13
|
-
<template v-else>
|
|
14
|
-
<div class="tw-truncate">N/A</div>
|
|
15
|
-
</template>
|
|
16
|
-
</template>
|
|
17
|
-
|
|
18
|
-
<!-- Date ago cell -->
|
|
19
|
-
<span
|
|
20
|
-
v-else-if="cell.type === 'date-ago'"
|
|
21
|
-
class="tw-text-[#a5a5a5]"
|
|
22
|
-
:title="(value instanceof Date && value.toLocaleString(locale)) || ''"
|
|
23
|
-
>
|
|
24
|
-
<div
|
|
25
|
-
v-if="value"
|
|
26
|
-
class="tw-truncate"
|
|
27
|
-
>
|
|
28
|
-
{{ moment(value).fromNow() }}
|
|
29
|
-
</div>
|
|
30
|
-
<div
|
|
31
|
-
v-else
|
|
32
|
-
class="tw-truncate"
|
|
33
|
-
>
|
|
34
|
-
N/A
|
|
35
|
-
</div>
|
|
36
|
-
</span>
|
|
37
|
-
|
|
38
|
-
<!-- Date exact cell -->
|
|
39
|
-
<div
|
|
40
|
-
v-else-if="cell.type === 'date' || cell.type === 'time' || cell.type === 'date-time'"
|
|
41
|
-
class="tw-text-[#a5a5a5] tw-truncate"
|
|
42
|
-
>
|
|
43
|
-
<template v-if="value">
|
|
2
|
+
<div>
|
|
3
|
+
<!-- Money cell -->
|
|
4
|
+
<template v-if="cell.type === 'money'">
|
|
44
5
|
<div
|
|
45
|
-
v-if="
|
|
6
|
+
v-if="typeof Number(value) === 'number' && Number(value) > 0"
|
|
46
7
|
class="tw-truncate"
|
|
8
|
+
:class="cell.class"
|
|
47
9
|
>
|
|
48
|
-
{{
|
|
10
|
+
<span class="tw-truncate">{{ Math.trunc(Number(value)) }}</span
|
|
11
|
+
><span class="tw-text-[#a5a5a5] tw-text-xs tw-truncate"
|
|
12
|
+
>.{{ `${(Number(value) * 100) % 100}`.padEnd(2, "0").slice(0, 2) }}</span
|
|
13
|
+
>
|
|
49
14
|
</div>
|
|
50
15
|
<template v-else>
|
|
51
16
|
<div
|
|
52
|
-
v-if="cell.type === 'date'"
|
|
53
17
|
class="tw-truncate"
|
|
18
|
+
:class="cell.class"
|
|
54
19
|
>
|
|
55
|
-
|
|
20
|
+
N/A
|
|
56
21
|
</div>
|
|
22
|
+
</template>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<!-- Date ago cell -->
|
|
26
|
+
<span
|
|
27
|
+
v-else-if="cell.type === 'date-ago'"
|
|
28
|
+
class="tw-text-[#a5a5a5]"
|
|
29
|
+
:class="cell.class"
|
|
30
|
+
:title="(value instanceof Date && value.toLocaleString(locale)) || ''"
|
|
31
|
+
>
|
|
32
|
+
<div
|
|
33
|
+
v-if="value"
|
|
34
|
+
class="tw-truncate"
|
|
35
|
+
>
|
|
36
|
+
{{ moment(value).fromNow() }}
|
|
37
|
+
</div>
|
|
38
|
+
<div
|
|
39
|
+
v-else
|
|
40
|
+
class="tw-truncate"
|
|
41
|
+
>
|
|
42
|
+
N/A
|
|
43
|
+
</div>
|
|
44
|
+
</span>
|
|
45
|
+
|
|
46
|
+
<!-- Date exact cell -->
|
|
47
|
+
<div
|
|
48
|
+
v-else-if="cell.type === 'date' || cell.type === 'time' || cell.type === 'date-time'"
|
|
49
|
+
class="tw-text-[#a5a5a5] tw-truncate"
|
|
50
|
+
:class="cell.class"
|
|
51
|
+
>
|
|
52
|
+
<template v-if="value">
|
|
57
53
|
<div
|
|
58
|
-
v-if="cell.
|
|
54
|
+
v-if="cell.format"
|
|
59
55
|
class="tw-truncate"
|
|
60
56
|
>
|
|
61
|
-
{{ value
|
|
57
|
+
{{ moment(value).locale(locale).format(cell.format) }}
|
|
62
58
|
</div>
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
<template v-else>
|
|
60
|
+
<div
|
|
61
|
+
v-if="cell.type === 'date'"
|
|
62
|
+
class="tw-truncate"
|
|
63
|
+
>
|
|
64
|
+
{{ value instanceof Date && value.toLocaleDateString(locale) }}
|
|
65
|
+
</div>
|
|
66
|
+
<div
|
|
67
|
+
v-if="cell.type === 'time'"
|
|
68
|
+
class="tw-truncate"
|
|
69
|
+
>
|
|
70
|
+
{{ value instanceof Date && value.toLocaleTimeString(locale) }}
|
|
71
|
+
</div>
|
|
72
|
+
<p
|
|
73
|
+
v-if="cell.type === 'date-time'"
|
|
74
|
+
class="tw-truncate"
|
|
75
|
+
>
|
|
76
|
+
{{ value instanceof Date && value.toLocaleString(locale) }}
|
|
77
|
+
</p>
|
|
78
|
+
</template>
|
|
69
79
|
</template>
|
|
80
|
+
<div
|
|
81
|
+
v-else
|
|
82
|
+
class="tw-truncate"
|
|
83
|
+
>
|
|
84
|
+
N/A
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<!-- Image cell -->
|
|
89
|
+
<template v-else-if="cell.type === 'image'">
|
|
90
|
+
<VcImage
|
|
91
|
+
:bordered="true"
|
|
92
|
+
size="s"
|
|
93
|
+
aspect="1x1"
|
|
94
|
+
:src="value as string"
|
|
95
|
+
background="contain"
|
|
96
|
+
/>
|
|
97
|
+
</template>
|
|
98
|
+
|
|
99
|
+
<!-- Status cell -->
|
|
100
|
+
<template v-else-if="cell.type === 'status'">
|
|
101
|
+
<VcStatus>{{ value }}</VcStatus>
|
|
70
102
|
</template>
|
|
103
|
+
|
|
104
|
+
<!-- Status icon cell -->
|
|
71
105
|
<div
|
|
72
|
-
v-else
|
|
73
|
-
class="tw-
|
|
106
|
+
v-else-if="cell.type === 'status-icon'"
|
|
107
|
+
class="tw-flex tw-justify-center"
|
|
108
|
+
:class="cell.class"
|
|
74
109
|
>
|
|
75
|
-
|
|
110
|
+
<VcStatusIcon :status="value as boolean"></VcStatusIcon>
|
|
76
111
|
</div>
|
|
77
|
-
</div>
|
|
78
112
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
/>
|
|
88
|
-
</template>
|
|
89
|
-
|
|
90
|
-
<!-- Status cell -->
|
|
91
|
-
<template v-else-if="cell.type === 'status'">
|
|
92
|
-
<VcStatus>{{ value }}</VcStatus>
|
|
93
|
-
</template>
|
|
94
|
-
|
|
95
|
-
<!-- Status icon cell -->
|
|
96
|
-
<div
|
|
97
|
-
v-else-if="cell.type === 'status-icon'"
|
|
98
|
-
class="tw-flex tw-justify-center"
|
|
99
|
-
>
|
|
100
|
-
<VcStatusIcon :status="value as boolean"></VcStatusIcon>
|
|
101
|
-
</div>
|
|
113
|
+
<!-- Number cell -->
|
|
114
|
+
<div
|
|
115
|
+
v-else-if="cell.type === 'number'"
|
|
116
|
+
class="tw-text-right tw-truncate"
|
|
117
|
+
:class="cell.class"
|
|
118
|
+
>
|
|
119
|
+
{{ Number(value).toFixed(0) }}
|
|
120
|
+
</div>
|
|
102
121
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
<!-- Link cell -->
|
|
123
|
+
<template v-else-if="cell.type === 'link'">
|
|
124
|
+
<VcLink
|
|
125
|
+
class="tw-truncate"
|
|
126
|
+
:class="cell.class"
|
|
127
|
+
>{{ value }}</VcLink
|
|
128
|
+
>
|
|
129
|
+
</template>
|
|
130
|
+
|
|
131
|
+
<!-- HTML cell -->
|
|
132
|
+
<template v-else-if="cell.type === 'html'">
|
|
133
|
+
<div
|
|
134
|
+
class="tw-p-1"
|
|
135
|
+
:class="cell.class"
|
|
136
|
+
v-html="truncatedHtml"
|
|
137
|
+
/>
|
|
138
|
+
</template>
|
|
110
139
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
class="tw-truncate"
|
|
120
|
-
>
|
|
121
|
-
{{ value }}
|
|
140
|
+
<!-- Default cell -->
|
|
141
|
+
<div
|
|
142
|
+
v-else
|
|
143
|
+
class="tw-truncate"
|
|
144
|
+
:class="cell.class"
|
|
145
|
+
>
|
|
146
|
+
{{ value }}
|
|
147
|
+
</div>
|
|
122
148
|
</div>
|
|
123
149
|
</template>
|
|
124
150
|
|
|
@@ -126,24 +152,30 @@
|
|
|
126
152
|
import { computed } from "vue";
|
|
127
153
|
import moment from "moment";
|
|
128
154
|
import { ITableColumns } from "./../../../../../../core/types";
|
|
155
|
+
import * as _ from "lodash-es";
|
|
156
|
+
import htmlTruncate from "truncate-html";
|
|
157
|
+
import * as DOMPurify from "dompurify";
|
|
129
158
|
|
|
130
159
|
export interface Props {
|
|
131
160
|
cell: ITableColumns;
|
|
132
161
|
item: Record<string, unknown>;
|
|
162
|
+
width?: number;
|
|
133
163
|
}
|
|
134
164
|
|
|
135
165
|
const props = defineProps<Props>();
|
|
136
166
|
|
|
137
167
|
const locale = window.navigator.language;
|
|
138
168
|
|
|
139
|
-
const value = computed(()
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return val !== undefined ? val : null;
|
|
147
|
-
}, props.item);
|
|
169
|
+
const value = computed(() => _.get(props.item, props.cell.field || props.cell.id));
|
|
170
|
+
|
|
171
|
+
const sanitizedHtml = computed(() => {
|
|
172
|
+
if (props.cell.type === "html") {
|
|
173
|
+
return DOMPurify.default.sanitize(value.value as string, { USE_PROFILES: { html: true } });
|
|
174
|
+
}
|
|
175
|
+
return "";
|
|
148
176
|
});
|
|
177
|
+
|
|
178
|
+
const truncatedHtml = computed(() =>
|
|
179
|
+
htmlTruncate(sanitizedHtml.value, +(typeof props.width !== "undefined" ? Math.floor(props.width / 5) : 30)),
|
|
180
|
+
);
|
|
149
181
|
</script>
|