quasar-ui-danx 0.4.12 → 0.4.13
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/danx.es.js +10673 -6194
- package/dist/danx.es.js.map +1 -1
- package/dist/danx.umd.js +137 -7
- package/dist/danx.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -2
- package/src/components/ActionTable/Form/RenderedForm.vue +48 -42
- package/src/components/PanelsDrawer/PanelsDrawer.vue +15 -5
- package/src/components/PanelsDrawer/PanelsDrawerPanels.vue +3 -1
- package/src/components/PanelsDrawer/PanelsDrawerTabs.vue +17 -4
- package/src/components/Utility/Tools/RenderVnode.vue +5 -1
- package/src/helpers/date.ts +2 -2
- package/src/helpers/formats.ts +52 -5
- package/src/helpers/utils.ts +3 -3
- package/src/types/actions.d.ts +3 -3
- package/src/types/forms.d.ts +19 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "quasar-ui-danx",
|
3
|
-
"version": "0.4.
|
3
|
+
"version": "0.4.13",
|
4
4
|
"author": "Dan <dan@flytedesk.com>",
|
5
5
|
"description": "DanX Vue / Quasar component library",
|
6
6
|
"license": "MIT",
|
@@ -57,7 +57,8 @@
|
|
57
57
|
"danx-icon": "^1.0.2",
|
58
58
|
"exifreader": "^4.21.1",
|
59
59
|
"gsap": "^3.12.5",
|
60
|
-
"luxon": "^3.4.4"
|
60
|
+
"luxon": "^3.4.4",
|
61
|
+
"yaml": "^2.4.5"
|
61
62
|
},
|
62
63
|
"browserslist": [
|
63
64
|
"last 4 Chrome versions",
|
@@ -62,32 +62,36 @@
|
|
62
62
|
</QTab>
|
63
63
|
</QTabs>
|
64
64
|
</div>
|
65
|
-
<
|
65
|
+
<template
|
66
66
|
v-for="(field, index) in mappedFields"
|
67
67
|
:key="field.id"
|
68
|
-
:class="{ 'mt-4': index > 0, [fieldClass]: true }"
|
69
68
|
>
|
70
|
-
<
|
71
|
-
v-
|
72
|
-
:
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
69
|
+
<div
|
70
|
+
v-show="isFieldEnabled(field)"
|
71
|
+
:class="{ 'mt-4': index > 0, [fieldClass]: true }"
|
72
|
+
>
|
73
|
+
<RenderVnode
|
74
|
+
v-if="field.vnode"
|
75
|
+
:vnode="field.vnode"
|
76
|
+
:props="getVnodeProps(field)"
|
77
|
+
:params="fieldInputs"
|
78
|
+
@update:model-value="onInput(field.name, $event)"
|
79
|
+
/>
|
80
|
+
<Component
|
81
|
+
:is="field.component"
|
82
|
+
:key="field.name + '-' + currentVariation"
|
83
|
+
:model-value="getFieldValue(field.name)"
|
84
|
+
:field="field"
|
85
|
+
:label="field.label || undefined"
|
86
|
+
:no-label="noLabel"
|
87
|
+
:show-name="showName"
|
88
|
+
:clearable="field.clearable || clearable"
|
89
|
+
:disable="disable"
|
90
|
+
:readonly="readonly"
|
91
|
+
@update:model-value="onInput(field.name, $event)"
|
92
|
+
/>
|
93
|
+
</div>
|
94
|
+
</template>
|
91
95
|
<div
|
92
96
|
v-if="savedAt"
|
93
97
|
:class="savingClass"
|
@@ -136,7 +140,7 @@ import { ExclamationCircleIcon as MissingIcon, PencilIcon as EditIcon } from "@h
|
|
136
140
|
import { computed, ref } from "vue";
|
137
141
|
import { fDateTime, FlashMessages, incrementName, replace } from "../../../helpers";
|
138
142
|
import { TrashIcon as RemoveIcon } from "../../../svg";
|
139
|
-
import { AnyObject,
|
143
|
+
import { AnyObject, FormFieldValue, RenderedFormProps } from "../../../types";
|
140
144
|
import { ConfirmDialog, RenderVnode } from "../../Utility";
|
141
145
|
import {
|
142
146
|
BooleanField,
|
@@ -150,22 +154,6 @@ import {
|
|
150
154
|
WysiwygField
|
151
155
|
} from "./Fields";
|
152
156
|
|
153
|
-
export interface RenderedFormProps {
|
154
|
-
values?: FormFieldValue[] | object | null;
|
155
|
-
form: Form;
|
156
|
-
noLabel?: boolean;
|
157
|
-
showName?: boolean;
|
158
|
-
disable?: boolean;
|
159
|
-
readonly?: boolean;
|
160
|
-
saving?: boolean;
|
161
|
-
clearable?: boolean;
|
162
|
-
emptyValue?: string | number | boolean;
|
163
|
-
canModifyVariations?: boolean;
|
164
|
-
fieldClass?: string;
|
165
|
-
savingClass?: string;
|
166
|
-
savedAt?: string;
|
167
|
-
}
|
168
|
-
|
169
157
|
const props = withDefaults(defineProps<RenderedFormProps>(), {
|
170
158
|
values: null,
|
171
159
|
emptyValue: undefined,
|
@@ -190,9 +178,9 @@ const FORM_FIELD_MAP = {
|
|
190
178
|
|
191
179
|
const mappedFields = props.form.fields.map((field) => ({
|
192
180
|
placeholder: `Enter ${field.label}`,
|
181
|
+
default: field.type === "BOOLEAN" ? false : "",
|
193
182
|
...field,
|
194
|
-
component: field.component || FORM_FIELD_MAP[field.type]
|
195
|
-
default: field.type === "BOOLEAN" ? false : ""
|
183
|
+
component: field.component || FORM_FIELD_MAP[field.type]
|
196
184
|
}));
|
197
185
|
|
198
186
|
const fieldResponses = computed(() => {
|
@@ -201,6 +189,24 @@ const fieldResponses = computed(() => {
|
|
201
189
|
return Object.entries(props.values).map(([name, value]) => ({ name, value, variation: "" }));
|
202
190
|
});
|
203
191
|
|
192
|
+
const fieldInputs = computed(() => {
|
193
|
+
const inputs: AnyObject = {};
|
194
|
+
for (const field of mappedFields) {
|
195
|
+
inputs[field.name] = getFieldValue(field.name);
|
196
|
+
}
|
197
|
+
return inputs;
|
198
|
+
});
|
199
|
+
|
200
|
+
function isFieldEnabled(field) {
|
201
|
+
if (field.enabled === undefined) return true;
|
202
|
+
|
203
|
+
if (typeof field.enabled === "function") {
|
204
|
+
return field.enabled(fieldInputs.value);
|
205
|
+
}
|
206
|
+
|
207
|
+
return field.enabled;
|
208
|
+
}
|
209
|
+
|
204
210
|
function getVnodeProps(field) {
|
205
211
|
return {
|
206
212
|
modelValue: getFieldValue(field.name),
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<template>
|
2
2
|
<ContentDrawer
|
3
3
|
position="right"
|
4
|
-
|
4
|
+
show
|
5
5
|
overlay
|
6
6
|
content-class="h-full"
|
7
7
|
class="dx-panels-drawer"
|
@@ -13,7 +13,13 @@
|
|
13
13
|
<div class="dx-panels-drawer-header flex items-center px-6 py-4">
|
14
14
|
<div class="flex-grow">
|
15
15
|
<slot name="header">
|
16
|
-
<h2
|
16
|
+
<h2 v-if="title">
|
17
|
+
{{ title }}
|
18
|
+
</h2>
|
19
|
+
<div v-if="!activeItem">
|
20
|
+
Loading
|
21
|
+
<QSpinnerHourglass />
|
22
|
+
</div>
|
17
23
|
</slot>
|
18
24
|
</div>
|
19
25
|
<div
|
@@ -32,10 +38,14 @@
|
|
32
38
|
</div>
|
33
39
|
</div>
|
34
40
|
<div class="dx-panels-drawer-body flex-grow overflow-hidden h-full">
|
35
|
-
<div
|
41
|
+
<div
|
42
|
+
v-if="activeItem.__timestamp > 0"
|
43
|
+
class="flex items-stretch flex-nowrap h-full"
|
44
|
+
>
|
36
45
|
<PanelsDrawerTabs
|
37
46
|
:key="'pd-tabs:' + activeItem.id"
|
38
47
|
v-model="activePanel"
|
48
|
+
:active-item="activeItem"
|
39
49
|
:class="tabsClass"
|
40
50
|
:panels="panels"
|
41
51
|
@update:model-value="$emit('update:model-value', $event)"
|
@@ -44,6 +54,7 @@
|
|
44
54
|
:key="'pd-panels:' + activeItem.id"
|
45
55
|
:panels="panels"
|
46
56
|
:active-panel="activePanel"
|
57
|
+
:active-item="activeItem"
|
47
58
|
:class="activePanelOptions?.class || panelsClass"
|
48
59
|
/>
|
49
60
|
<div
|
@@ -68,7 +79,7 @@ import PanelsDrawerTabs from "./PanelsDrawerTabs";
|
|
68
79
|
export interface Props {
|
69
80
|
title?: string,
|
70
81
|
modelValue?: string | number,
|
71
|
-
activeItem
|
82
|
+
activeItem: ActionTargetItem;
|
72
83
|
tabsClass?: string | object,
|
73
84
|
panelsClass?: string | object,
|
74
85
|
panels: ActionPanel[]
|
@@ -78,7 +89,6 @@ defineEmits(["update:model-value", "close"]);
|
|
78
89
|
const props = withDefaults(defineProps<Props>(), {
|
79
90
|
title: "",
|
80
91
|
modelValue: null,
|
81
|
-
activeItem: null,
|
82
92
|
tabsClass: "w-[13.5rem]",
|
83
93
|
panelsClass: "w-[35.5rem]"
|
84
94
|
});
|
@@ -11,17 +11,19 @@
|
|
11
11
|
<RenderVnode
|
12
12
|
v-if="panel.vnode"
|
13
13
|
:vnode="panel.vnode"
|
14
|
+
:props="activeItem"
|
14
15
|
/>
|
15
16
|
</QTabPanel>
|
16
17
|
</QTabPanels>
|
17
18
|
</template>
|
18
19
|
|
19
20
|
<script setup lang="ts">
|
20
|
-
import { ActionPanel } from "../../types";
|
21
|
+
import { ActionPanel, ActionTargetItem } from "../../types";
|
21
22
|
import { RenderVnode } from "../Utility";
|
22
23
|
|
23
24
|
defineProps<{
|
24
25
|
activePanel?: string | number,
|
26
|
+
activeItem: ActionTargetItem,
|
25
27
|
panels: ActionPanel[]
|
26
28
|
}>();
|
27
29
|
</script>
|
@@ -9,11 +9,11 @@
|
|
9
9
|
@update:model-value="$emit('update:model-value', $event)"
|
10
10
|
>
|
11
11
|
<template v-for="panel in panels">
|
12
|
-
<template v-if="panel
|
12
|
+
<template v-if="isEnabled(panel)">
|
13
13
|
<RenderVnode
|
14
14
|
v-if="panel.tabVnode"
|
15
15
|
:key="panel.name"
|
16
|
-
:vnode="panel.tabVnode(modelValue)"
|
16
|
+
:vnode="panel.tabVnode(activeItem, modelValue)"
|
17
17
|
:is-active="modelValue === panel.name"
|
18
18
|
:name="panel.name"
|
19
19
|
:label="panel.label"
|
@@ -30,19 +30,32 @@
|
|
30
30
|
</template>
|
31
31
|
<script setup lang="ts">
|
32
32
|
import { QTab } from "quasar";
|
33
|
-
import { ActionPanel } from "../../types";
|
33
|
+
import { ActionPanel, ActionTargetItem } from "../../types";
|
34
34
|
import { RenderVnode } from "../Utility";
|
35
35
|
|
36
36
|
defineEmits(["update:model-value"]);
|
37
37
|
|
38
38
|
interface Props {
|
39
39
|
modelValue?: string | number;
|
40
|
+
activeItem: ActionTargetItem;
|
40
41
|
panels: ActionPanel[];
|
41
42
|
}
|
42
43
|
|
43
|
-
withDefaults(defineProps<Props>(), {
|
44
|
+
const props = withDefaults(defineProps<Props>(), {
|
44
45
|
modelValue: "general"
|
45
46
|
});
|
47
|
+
|
48
|
+
function isEnabled(panel) {
|
49
|
+
if (panel.enabled === undefined) return true;
|
50
|
+
|
51
|
+
if (!panel.enabled) return false;
|
52
|
+
|
53
|
+
if (typeof panel.enabled === "function") {
|
54
|
+
return panel.enabled(props.activeItem);
|
55
|
+
}
|
56
|
+
|
57
|
+
return true;
|
58
|
+
}
|
46
59
|
</script>
|
47
60
|
|
48
61
|
<style lang="scss" module="cls">
|
@@ -11,7 +11,7 @@ const RenderVnode = (props) => {
|
|
11
11
|
}
|
12
12
|
|
13
13
|
if (typeof props.vnode === "function") {
|
14
|
-
return props.vnode(props.props);
|
14
|
+
return props.vnode(props.props, props.params);
|
15
15
|
}
|
16
16
|
|
17
17
|
return null;
|
@@ -24,6 +24,10 @@ RenderVnode.props = {
|
|
24
24
|
props: {
|
25
25
|
type: Object,
|
26
26
|
default: () => ({})
|
27
|
+
},
|
28
|
+
params: {
|
29
|
+
type: Object,
|
30
|
+
default: null
|
27
31
|
}
|
28
32
|
};
|
29
33
|
export default RenderVnode;
|
package/src/helpers/date.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { parseDateTime } from "./formats";
|
2
2
|
|
3
|
-
export function diffInDays(date1, date2) {
|
4
|
-
|
3
|
+
export function diffInDays(date1: string, date2: string) {
|
4
|
+
return parseDateTime(date2).diff(parseDateTime(date1), ["days"]).days;
|
5
5
|
}
|
package/src/helpers/formats.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { DateTime, IANAZone } from "luxon";
|
2
|
+
import { parse as parseYAML, stringify as stringifyYAML } from "yaml";
|
2
3
|
import { ActionTargetItem, fDateOptions } from "../types";
|
3
4
|
import { isJSON } from "./utils";
|
4
5
|
|
@@ -335,10 +336,56 @@ export function fJSON(string: string | object) {
|
|
335
336
|
}
|
336
337
|
}
|
337
338
|
|
338
|
-
|
339
|
-
|
340
|
-
|
339
|
+
/**
|
340
|
+
* Convert markdown formatted string into a valid JSON object
|
341
|
+
*/
|
342
|
+
export function parseMarkdownJSON(string: string | object): object | null | undefined {
|
343
|
+
if (typeof string === "object") return string as object;
|
344
|
+
|
345
|
+
try {
|
346
|
+
return JSON.parse(parseMarkdownCode(string));
|
347
|
+
} catch (e) {
|
348
|
+
return undefined;
|
341
349
|
}
|
342
|
-
|
343
|
-
|
350
|
+
}
|
351
|
+
|
352
|
+
export function parseMarkdownYAML(string: string): object | null | undefined {
|
353
|
+
try {
|
354
|
+
return parseYAML(parseMarkdownCode(string)) || (string ? undefined : null);
|
355
|
+
} catch (e) {
|
356
|
+
return undefined;
|
357
|
+
}
|
358
|
+
}
|
359
|
+
|
360
|
+
/**
|
361
|
+
* Parse a markdown formatted string and return the code block content
|
362
|
+
*/
|
363
|
+
export function parseMarkdownCode(string: string): string {
|
364
|
+
return string.replace(/^```[a-z0-9]{1,6}\s/, "").replace(/```$/, "");
|
365
|
+
}
|
366
|
+
|
367
|
+
/**
|
368
|
+
* Convert a JSON object or string of code into a markdown formatted JSON string
|
369
|
+
* ie: a valid JSON string with a ```json prefix and ``` postfix
|
370
|
+
*/
|
371
|
+
export function fMarkdownCode(type: string, string: string | object): string {
|
372
|
+
if (typeof string === "object" || isJSON(string)) {
|
373
|
+
switch (type) {
|
374
|
+
case "yaml":
|
375
|
+
string = stringifyYAML(string);
|
376
|
+
break;
|
377
|
+
case "ts":
|
378
|
+
string = "";
|
379
|
+
break;
|
380
|
+
default:
|
381
|
+
string = fJSON(string);
|
382
|
+
}
|
383
|
+
}
|
384
|
+
|
385
|
+
const regex = new RegExp(`\`\`\`${type}`, "g");
|
386
|
+
if (!((string || "") as string).match(regex)) {
|
387
|
+
return `\`\`\`${type}\n${string}\n\`\`\``;
|
388
|
+
}
|
389
|
+
|
390
|
+
return string as string;
|
344
391
|
}
|
package/src/helpers/utils.ts
CHANGED
@@ -91,12 +91,12 @@ export function incrementName(name: string) {
|
|
91
91
|
* Check if a string is a valid JSON object. If an object is passed, always return true
|
92
92
|
*/
|
93
93
|
export function isJSON(string: string | object) {
|
94
|
-
if (!string) {
|
95
|
-
return false;
|
96
|
-
}
|
97
94
|
if (typeof string === "object") {
|
98
95
|
return true;
|
99
96
|
}
|
97
|
+
if (!string) {
|
98
|
+
return false;
|
99
|
+
}
|
100
100
|
try {
|
101
101
|
JSON.parse(string);
|
102
102
|
return true;
|
package/src/types/actions.d.ts
CHANGED
@@ -6,9 +6,9 @@ export interface ActionPanel {
|
|
6
6
|
label: string;
|
7
7
|
category?: string;
|
8
8
|
class?: string | object;
|
9
|
-
enabled?: boolean | (() => boolean);
|
10
|
-
tabVnode?: (activePanel: string | number) => VNode | any;
|
11
|
-
vnode: (
|
9
|
+
enabled?: boolean | ((activeItem: ActionTargetItem) => boolean);
|
10
|
+
tabVnode?: (activeItem: ActionTargetItem | null | undefined, activePanel: string | number) => VNode | any;
|
11
|
+
vnode: (activeItem: ActionTargetItem | null | undefined) => VNode | any;
|
12
12
|
}
|
13
13
|
|
14
14
|
export interface ActionTargetItem extends TypedObject {
|
package/src/types/forms.d.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { VNode } from "vue";
|
2
|
+
import { AnyObject } from "./shared";
|
2
3
|
|
3
4
|
export interface FormFieldOption {
|
4
5
|
value: string;
|
@@ -11,7 +12,8 @@ export interface FormField {
|
|
11
12
|
name: string;
|
12
13
|
label: string;
|
13
14
|
placeholder?: string;
|
14
|
-
|
15
|
+
enabled?: boolean | ((input: AnyObject) => boolean);
|
16
|
+
vnode?: ((field: FormFieldOption, input?: AnyObject) => VNode | any);
|
15
17
|
component?: any;
|
16
18
|
clearable?: boolean;
|
17
19
|
required?: boolean;
|
@@ -35,3 +37,19 @@ export interface FormFieldValue {
|
|
35
37
|
value: any,
|
36
38
|
variation?: string
|
37
39
|
}
|
40
|
+
|
41
|
+
export interface RenderedFormProps {
|
42
|
+
values?: FormFieldValue[] | object | null;
|
43
|
+
form: Form;
|
44
|
+
noLabel?: boolean;
|
45
|
+
showName?: boolean;
|
46
|
+
disable?: boolean;
|
47
|
+
readonly?: boolean;
|
48
|
+
saving?: boolean;
|
49
|
+
clearable?: boolean;
|
50
|
+
emptyValue?: string | number | boolean;
|
51
|
+
canModifyVariations?: boolean;
|
52
|
+
fieldClass?: string;
|
53
|
+
savingClass?: string;
|
54
|
+
savedAt?: string;
|
55
|
+
}
|