@mouseless/baked 1.5.3 → 1.6.1
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/module.mjs +2 -1
- package/dist/runtime/components/AwaitLoading.d.ts +7 -4
- package/dist/runtime/components/AwaitLoading.js +39 -11
- package/dist/runtime/components/Bake.d.vue.ts +1 -3
- package/dist/runtime/components/Bake.vue +101 -60
- package/dist/runtime/components/Bake.vue.d.ts +1 -3
- package/dist/runtime/components/DataContainer.vue +4 -7
- package/dist/runtime/components/DataPanel.vue +5 -7
- package/dist/runtime/components/DataTable.vue +12 -3
- package/dist/runtime/components/ErrorPage.vue +6 -5
- package/dist/runtime/components/ErrorPopover.d.vue.ts +15 -0
- package/dist/runtime/components/ErrorPopover.vue +22 -0
- package/dist/runtime/components/ErrorPopover.vue.d.ts +15 -0
- package/dist/runtime/components/FormPage.vue +36 -8
- package/dist/runtime/components/InlineError.d.vue.ts +15 -0
- package/dist/runtime/components/InlineError.vue +27 -0
- package/dist/runtime/components/InlineError.vue.d.ts +15 -0
- package/dist/runtime/components/Input.d.vue.ts +9 -1
- package/dist/runtime/components/Input.vue +31 -5
- package/dist/runtime/components/Input.vue.d.ts +9 -1
- package/dist/runtime/components/InputNumber.vue +23 -23
- package/dist/runtime/components/InputText.vue +22 -22
- package/dist/runtime/components/Inputs.d.vue.ts +7 -0
- package/dist/runtime/components/Inputs.vue +4 -2
- package/dist/runtime/components/Inputs.vue.d.ts +7 -0
- package/dist/runtime/components/Labeler.d.vue.ts +9 -25
- package/dist/runtime/components/Labeler.vue +32 -25
- package/dist/runtime/components/Labeler.vue.d.ts +9 -25
- package/dist/runtime/components/Layout.vue +5 -1
- package/dist/runtime/components/LoadingError.d.vue.ts +13 -0
- package/dist/runtime/components/LoadingError.vue +27 -0
- package/dist/runtime/components/LoadingError.vue.d.ts +13 -0
- package/dist/runtime/components/Message.d.vue.ts +8 -1
- package/dist/runtime/components/Message.vue +48 -17
- package/dist/runtime/components/Message.vue.d.ts +8 -1
- package/dist/runtime/components/NavLink.vue +6 -3
- package/dist/runtime/components/Paginator.vue +1 -3
- package/dist/runtime/components/Select.vue +39 -39
- package/dist/runtime/components/SelectButton.vue +46 -40
- package/dist/runtime/components/SimpleForm.vue +46 -11
- package/dist/runtime/components/TabbedPage.vue +5 -7
- package/dist/runtime/components/Validation.d.vue.ts +17 -0
- package/dist/runtime/components/Validation.vue +48 -0
- package/dist/runtime/components/Validation.vue.d.ts +17 -0
- package/dist/runtime/composables/useBakeError.d.ts +13 -0
- package/dist/runtime/composables/useBakeError.js +51 -0
- package/dist/runtime/composables/useContext.d.ts +14 -0
- package/dist/runtime/composables/useContext.js +77 -2
- package/dist/runtime/composables/useDataMounter.d.ts +4 -2
- package/dist/runtime/composables/useDataMounter.js +15 -6
- package/dist/runtime/composables/useDefaultValidation.d.ts +4 -0
- package/dist/runtime/composables/useDefaultValidation.js +37 -0
- package/dist/runtime/composables/useRedirect.d.ts +1 -1
- package/dist/runtime/composables/useRedirect.js +7 -1
- package/dist/runtime/composables/useValidation.d.ts +15 -0
- package/dist/runtime/composables/useValidation.js +79 -0
- package/dist/runtime/plugins/errorHandling.js +2 -2
- package/package.json +14 -14
|
@@ -1,29 +1,60 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
:
|
|
2
|
+
<div
|
|
3
|
+
class="b-message grid"
|
|
4
|
+
:class="[`message-${severity}`, `message-${variant}`]"
|
|
5
5
|
>
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
<div class="min-h-0">
|
|
7
|
+
<div
|
|
8
|
+
:class="sizeClass"
|
|
9
|
+
class="
|
|
10
|
+
b-message-body
|
|
11
|
+
flex flex-col gap-3
|
|
12
|
+
"
|
|
13
|
+
>
|
|
14
|
+
<div class="flex flex-row items-center gap-2">
|
|
15
|
+
<i
|
|
16
|
+
v-if="icon"
|
|
17
|
+
class="b-message-icon"
|
|
18
|
+
:class="icon"
|
|
19
|
+
/>
|
|
20
|
+
<AwaitLoading :skeleton="{ height: '1.5rem', width: '100%' }">
|
|
21
|
+
<span v-if="data">{{ localizeMessage ? l(data) : data }}</span>
|
|
22
|
+
<span v-else>-</span>
|
|
23
|
+
</AwaitLoading>
|
|
24
|
+
</div>
|
|
25
|
+
<slot name="content" />
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
17
29
|
</template>
|
|
18
30
|
|
|
19
31
|
<script setup>
|
|
20
|
-
import {
|
|
21
|
-
import { useLocalization } from "#imports";
|
|
32
|
+
import { computed, useLocalization } from "#imports";
|
|
22
33
|
import { AwaitLoading } from "#components";
|
|
23
34
|
const { localize: l } = useLocalization();
|
|
24
35
|
const { schema, data } = defineProps({
|
|
25
36
|
schema: { type: null, required: true },
|
|
26
37
|
data: { type: null, required: true }
|
|
27
38
|
});
|
|
28
|
-
const { icon, severity = "info",
|
|
39
|
+
const { icon, localizeMessage, severity = "info", size, variant = "outlined" } = schema;
|
|
40
|
+
const sizeClass = computed(() => {
|
|
41
|
+
switch (size) {
|
|
42
|
+
case "small":
|
|
43
|
+
return "text-sm font-normal";
|
|
44
|
+
case "large":
|
|
45
|
+
return "text-lg font-semibold";
|
|
46
|
+
default:
|
|
47
|
+
return "text-base font-medium";
|
|
48
|
+
}
|
|
49
|
+
});
|
|
29
50
|
</script>
|
|
51
|
+
|
|
52
|
+
<style scoped>
|
|
53
|
+
.message-outlined{@apply border rounded-md}.message-outlined .b-message-body{@apply py-[0.50rem] px-[0.75rem] min-w-[10rem] min-h-[1.5rem]}.message-simple{@apply !bg-transparent}.message-simple .b-message-body{@apply px-0}.message-info{@apply bg-blue-50/95 text-blue-600 border-blue-200
|
|
54
|
+
dark:bg-blue-950/95 dark:text-blue-500 dark:border-blue-700/65}.message-error{@apply bg-red-50/95 text-red-600 border-red-200
|
|
55
|
+
dark:bg-red-950/95 dark:text-red-500 dark:border-red-700/65}.message-warn{@apply bg-yellow-50/95 text-yellow-600 border-yellow-200
|
|
56
|
+
dark:bg-yellow-950/95 dark:text-yellow-500 dark:border-yellow-700/65}.message-success{@apply bg-green-50/95 text-green-600 border-green-200
|
|
57
|
+
dark:bg-green-950/95 dark:text-green-500 dark:border-green-700/65}.message-secondary{@apply bg-transparent text-slate-500 border-slate-500
|
|
58
|
+
dark:text-slate-400 dark:border-slate-400}.message-contrast{@apply bg-transparent text-slate-950 border-slate-950
|
|
59
|
+
dark:text-white dark:border-white}
|
|
60
|
+
</style>
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
declare const _default: typeof __VLS_export;
|
|
2
2
|
export default _default;
|
|
3
|
-
declare const __VLS_export:
|
|
3
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
4
|
+
type __VLS_WithSlots<T, S> = T & (new () => {
|
|
5
|
+
$slots: S;
|
|
6
|
+
});
|
|
7
|
+
declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
8
|
schema: {
|
|
5
9
|
type: null;
|
|
6
10
|
required: true;
|
|
@@ -19,3 +23,6 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
19
23
|
required: true;
|
|
20
24
|
};
|
|
21
25
|
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
26
|
+
type __VLS_Slots = {
|
|
27
|
+
content?: ((props: {}) => any) | undefined;
|
|
28
|
+
};
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<AwaitLoading :skeleton="{ height: '1.5rem' }">
|
|
3
3
|
<Button
|
|
4
|
+
v-if="data"
|
|
4
5
|
:icon
|
|
5
|
-
:label
|
|
6
|
+
:label
|
|
6
7
|
:to
|
|
7
8
|
as="router-link"
|
|
8
9
|
link
|
|
9
10
|
class="m-0 p-0"
|
|
10
11
|
/>
|
|
12
|
+
<span v-else>-</span>
|
|
11
13
|
</AwaitLoading>
|
|
12
14
|
</template>
|
|
13
15
|
|
|
@@ -16,15 +18,16 @@ import { computed } from "vue";
|
|
|
16
18
|
import { Button } from "primevue";
|
|
17
19
|
import { useDataMounter, usePathBuilder } from "#imports";
|
|
18
20
|
import { AwaitLoading } from "#components";
|
|
19
|
-
const { mount: mountData } = useDataMounter();
|
|
21
|
+
const { mount: mountData } = useDataMounter({ defaultInlineError: true });
|
|
20
22
|
const pathBuilder = usePathBuilder();
|
|
21
23
|
const { schema, data } = defineProps({
|
|
22
24
|
schema: { type: null, required: true },
|
|
23
25
|
data: { type: null, required: true }
|
|
24
26
|
});
|
|
25
|
-
const { icon, path, query: queryData, params: paramsData } = schema;
|
|
27
|
+
const { icon, labelProp, path, query: queryData, params: paramsData } = schema;
|
|
26
28
|
const query = mountData(queryData);
|
|
27
29
|
const params = mountData(paramsData);
|
|
30
|
+
const label = computed(() => labelProp ? data?.[labelProp] : data);
|
|
28
31
|
const to = computed(() => ({
|
|
29
32
|
path: params.value ? pathBuilder.build(path, params.value, { forRoute: true }) : path,
|
|
30
33
|
query: query.value
|
|
@@ -40,9 +40,7 @@ const allowPrevious = computed(() => !Number.isNaN(page.value) && page.value > 1
|
|
|
40
40
|
const allowNext = computed(() => !Number.isNaN(page.value) && data.length >= data.take);
|
|
41
41
|
const page = computed({
|
|
42
42
|
get: () => Number(model.value) / Number(data.take) + 1,
|
|
43
|
-
set: (value) =>
|
|
44
|
-
model.value = (value - 1) * Number(data.take);
|
|
45
|
-
}
|
|
43
|
+
set: (value) => model.value = (value - 1) * Number(data.take)
|
|
46
44
|
});
|
|
47
45
|
const path = context.injectPath();
|
|
48
46
|
const previousTake = paginatorStates[`${path}.previousTake`];
|
|
@@ -1,45 +1,44 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<AwaitLoading
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
:variant="labelVariant"
|
|
13
|
-
>
|
|
14
|
-
<Select
|
|
15
|
-
v-bind="$attrs"
|
|
16
|
-
v-model="selected"
|
|
17
|
-
:input-id="path"
|
|
18
|
-
:options="data"
|
|
19
|
-
:placeholder="l(label)"
|
|
20
|
-
:show-clear
|
|
21
|
-
:filter
|
|
22
|
-
:auto-filter-focus="filter"
|
|
23
|
-
:filter-fields="[optionLabel]"
|
|
24
|
-
reset-filter-on-hide
|
|
25
|
-
class="w-full"
|
|
2
|
+
<AwaitLoading
|
|
3
|
+
:skeleton="{
|
|
4
|
+
height: label?.mode === 'ifta' ? '3.6rem' : '2.6rem',
|
|
5
|
+
class: 'min-w-40'
|
|
6
|
+
}"
|
|
7
|
+
>
|
|
8
|
+
<Validation>
|
|
9
|
+
<Labeler
|
|
10
|
+
:label
|
|
11
|
+
:path
|
|
26
12
|
>
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
<Select
|
|
14
|
+
v-bind="$attrs"
|
|
15
|
+
v-model="selected"
|
|
16
|
+
:input-id="path"
|
|
17
|
+
:options="data"
|
|
18
|
+
:placeholder
|
|
19
|
+
:show-clear
|
|
20
|
+
:filter
|
|
21
|
+
:auto-filter-focus="filter"
|
|
22
|
+
:filter-fields="[optionLabel]"
|
|
23
|
+
reset-filter-on-hide
|
|
24
|
+
>
|
|
25
|
+
<template #value="slotProps">
|
|
26
|
+
<span>{{ getValueLabel(slotProps) }}</span>
|
|
27
|
+
</template>
|
|
28
|
+
<template #option="slotProps">
|
|
29
|
+
<span>{{ getOptionLabel(slotProps) }}</span>
|
|
30
|
+
</template>
|
|
31
|
+
</Select>
|
|
32
|
+
</Labeler>
|
|
33
|
+
</Validation>
|
|
35
34
|
</AwaitLoading>
|
|
36
35
|
</template>
|
|
37
36
|
|
|
38
37
|
<script setup>
|
|
39
38
|
import { ref, watch } from "vue";
|
|
40
|
-
import { Select
|
|
39
|
+
import { Select } from "primevue";
|
|
41
40
|
import { useContext, useUiStates, useLocalization } from "#imports";
|
|
42
|
-
import { AwaitLoading, Labeler } from "#components";
|
|
41
|
+
import { AwaitLoading, Labeler, Validation } from "#components";
|
|
43
42
|
const context = useContext();
|
|
44
43
|
const { localize: l } = useLocalization();
|
|
45
44
|
const { value: { selectStates } } = useUiStates();
|
|
@@ -48,9 +47,10 @@ const { schema, data } = defineProps({
|
|
|
48
47
|
data: { type: null, required: true }
|
|
49
48
|
});
|
|
50
49
|
const model = defineModel({ type: null, required: true });
|
|
51
|
-
const { filter, label,
|
|
50
|
+
const { filter, label, localizeOptionLabels, optionLabel, optionValue, showClear, stateful, targetProp } = schema;
|
|
52
51
|
const path = context.injectPath();
|
|
53
52
|
const selected = ref();
|
|
53
|
+
const placeholder = label?.text ? l(label.text) : null;
|
|
54
54
|
watch(
|
|
55
55
|
[() => data, getModel],
|
|
56
56
|
([_data, _model]) => {
|
|
@@ -65,11 +65,11 @@ watch(
|
|
|
65
65
|
watch(selected, (newSelected) => setModel(newSelected));
|
|
66
66
|
function getOptionLabel(slotProps) {
|
|
67
67
|
const result = slotProps.option[optionLabel] ?? slotProps.option;
|
|
68
|
-
return
|
|
68
|
+
return localizeOptionLabels ? l(result) : result;
|
|
69
69
|
}
|
|
70
70
|
function getValueLabel(slotProps) {
|
|
71
|
-
const result = slotProps.value?.[optionLabel] ?? slotProps.value ??
|
|
72
|
-
return (
|
|
71
|
+
const result = slotProps.value?.[optionLabel] ?? slotProps.value ?? placeholder;
|
|
72
|
+
return (localizeOptionLabels ? l(result) : result) ?? "\xA0";
|
|
73
73
|
}
|
|
74
74
|
function getModel() {
|
|
75
75
|
return targetProp ? model.value?.[targetProp] : model.value;
|
|
@@ -96,5 +96,5 @@ function setSelected(value) {
|
|
|
96
96
|
</script>
|
|
97
97
|
|
|
98
98
|
<style>
|
|
99
|
-
.b-component--Select .p-placeholder{opacity:0}.b-component--Select .p-select-label{font-size:inherit}
|
|
99
|
+
.b-component--Select .p-placeholder{opacity:0}.b-component--Select .p-select-label{font-size:inherit}.p-popover-content .b-component--Select{@apply max-md:w-full}
|
|
100
100
|
</style>
|
|
@@ -1,47 +1,54 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<AwaitLoading
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
<AwaitLoading
|
|
3
|
+
:skeleton="{
|
|
4
|
+
height: label?.mode === 'ifta' ? '3.6rem' : '2.6rem',
|
|
5
|
+
class: 'min-w-60'
|
|
6
|
+
}"
|
|
7
|
+
>
|
|
8
|
+
<Validation>
|
|
9
|
+
<Labeler
|
|
10
|
+
:label="{
|
|
11
|
+
...label,
|
|
12
|
+
mode: label?.mode === 'ifta' ? label.mode : null,
|
|
13
|
+
text: label?.mode === 'ifta' ? label.text : null
|
|
14
|
+
}"
|
|
15
|
+
:path
|
|
16
|
+
:dt="{
|
|
17
|
+
colorScheme: {
|
|
18
|
+
light: {
|
|
19
|
+
top: '-1rem',
|
|
20
|
+
},
|
|
21
|
+
dark: {
|
|
22
|
+
top: '-1rem'
|
|
23
|
+
}
|
|
19
24
|
}
|
|
20
|
-
}
|
|
21
|
-
}"
|
|
22
|
-
>
|
|
23
|
-
<SelectButton
|
|
24
|
-
v-if="data"
|
|
25
|
-
v-model="selected"
|
|
26
|
-
:options="data"
|
|
27
|
-
:allow-empty
|
|
28
|
-
:data-key="optionValue"
|
|
29
|
-
:option-label
|
|
30
|
-
:pt="{ pcToggleButton: { root: { class: 'text-[length:inherit]' } } }"
|
|
25
|
+
}"
|
|
31
26
|
>
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
<SelectButton
|
|
28
|
+
v-if="data"
|
|
29
|
+
v-bind="$attrs"
|
|
30
|
+
v-model="selected"
|
|
31
|
+
:options="data"
|
|
32
|
+
:allow-empty
|
|
33
|
+
:data-key="optionValue"
|
|
34
|
+
:option-label
|
|
35
|
+
class="!w-auto"
|
|
36
|
+
pt:pc-toggle-button:root="text-[length:inherit]"
|
|
37
|
+
>
|
|
38
|
+
<template #option="slotProps">
|
|
39
|
+
<span>{{ getOptionLabel(slotProps) }}</span>
|
|
40
|
+
</template>
|
|
41
|
+
</SelectButton>
|
|
42
|
+
</Labeler>
|
|
43
|
+
</Validation>
|
|
37
44
|
</AwaitLoading>
|
|
38
45
|
</template>
|
|
39
46
|
|
|
40
47
|
<script setup>
|
|
41
48
|
import { ref, watch } from "vue";
|
|
42
|
-
import { SelectButton
|
|
49
|
+
import { SelectButton } from "primevue";
|
|
43
50
|
import { useContext, useLocalization, useUiStates } from "#imports";
|
|
44
|
-
import { AwaitLoading, Labeler } from "#components";
|
|
51
|
+
import { AwaitLoading, Labeler, Validation } from "#components";
|
|
45
52
|
const context = useContext();
|
|
46
53
|
const { localize: l } = useLocalization();
|
|
47
54
|
const { value: { selectButtonStates } } = useUiStates();
|
|
@@ -53,8 +60,7 @@ const model = defineModel({ type: null, required: true });
|
|
|
53
60
|
const {
|
|
54
61
|
allowEmpty = false,
|
|
55
62
|
label,
|
|
56
|
-
|
|
57
|
-
localizeLabel,
|
|
63
|
+
localizeOptionLabels,
|
|
58
64
|
optionLabel,
|
|
59
65
|
optionValue,
|
|
60
66
|
stateful,
|
|
@@ -76,7 +82,7 @@ watch(
|
|
|
76
82
|
watch(selected, (newSelected) => setModel(newSelected));
|
|
77
83
|
function getOptionLabel(slotProps) {
|
|
78
84
|
const result = slotProps.option[optionLabel] ?? slotProps.option;
|
|
79
|
-
return
|
|
85
|
+
return localizeOptionLabels ? l(result) : result;
|
|
80
86
|
}
|
|
81
87
|
function getModel() {
|
|
82
88
|
return targetProp ? model.value?.[targetProp] : model.value;
|
|
@@ -103,9 +109,9 @@ function setSelected(value) {
|
|
|
103
109
|
</script>
|
|
104
110
|
|
|
105
111
|
<style>
|
|
106
|
-
.p-togglebutton-content{@apply whitespace-nowrap}.p-popover-content .b-component--SelectButton .p-selectbutton{@apply max-sm:flex max-sm:flex-col}.p-popover-content .b-component--SelectButton .p-selectbutton .p-togglebutton:first-child{@apply max-sm:rounded-t-lg max-sm:rounded-es-none}.p-popover-content .b-component--SelectButton .p-selectbutton .p-togglebutton:last-child{@apply max-sm:rounded-b-lg max-sm:rounded-se-none}
|
|
112
|
+
.p-togglebutton-content{@apply whitespace-nowrap}.p-popover-content .b-component--SelectButton .p-selectbutton,.p-popover-content .b-component--SelectButton.p-selectbutton{@apply max-sm:flex max-sm:flex-col}.p-popover-content .b-component--SelectButton .p-selectbutton .p-togglebutton:first-child,.p-popover-content .b-component--SelectButton.p-selectbutton .p-togglebutton:first-child{@apply max-sm:rounded-t-lg max-sm:rounded-es-none}.p-popover-content .b-component--SelectButton .p-selectbutton .p-togglebutton:last-child,.p-popover-content .b-component--SelectButton.p-selectbutton .p-togglebutton:last-child{@apply max-sm:rounded-b-lg max-sm:rounded-se-none}
|
|
107
113
|
</style>
|
|
108
114
|
|
|
109
115
|
<style scoped>
|
|
110
|
-
|
|
116
|
+
.p-iftalabel:has(.p-selectbutton){@apply mt-4}
|
|
111
117
|
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<template v-if="dialogOptions">
|
|
3
3
|
<Button
|
|
4
|
+
ref="submitRef"
|
|
4
5
|
:schema="dialogOptions.open"
|
|
5
6
|
v-bind="$attrs"
|
|
6
7
|
@click="visible = true"
|
|
@@ -47,6 +48,9 @@
|
|
|
47
48
|
/>
|
|
48
49
|
</template>
|
|
49
50
|
</Dialog>
|
|
51
|
+
<ErrorPopover ref="errorPopoverRef">
|
|
52
|
+
<InlineError :error />
|
|
53
|
+
</ErrorPopover>
|
|
50
54
|
</template>
|
|
51
55
|
<template v-else>
|
|
52
56
|
<div
|
|
@@ -60,49 +64,80 @@
|
|
|
60
64
|
<Inputs
|
|
61
65
|
v-if="inputs"
|
|
62
66
|
:inputs
|
|
67
|
+
form-mode
|
|
63
68
|
input-class="w-full"
|
|
64
69
|
@ready="onReady"
|
|
65
70
|
@changed="onChanged"
|
|
66
71
|
/>
|
|
67
72
|
</div>
|
|
68
73
|
<Button
|
|
74
|
+
ref="submitRef"
|
|
75
|
+
v-tooltip.top="{
|
|
76
|
+
disabled: !showValidationSummary,
|
|
77
|
+
value: messages,
|
|
78
|
+
pt: { text: 'text-sm' }
|
|
79
|
+
}"
|
|
69
80
|
:schema="submit"
|
|
70
81
|
:ready
|
|
71
|
-
@submit="$emit('submit',
|
|
82
|
+
@submit="$emit('submit', model)"
|
|
72
83
|
/>
|
|
84
|
+
<ErrorPopover ref="errorPopoverRef">
|
|
85
|
+
<InlineError :error />
|
|
86
|
+
</ErrorPopover>
|
|
73
87
|
</div>
|
|
74
88
|
</template>
|
|
75
89
|
</template>
|
|
76
90
|
|
|
77
91
|
<script setup>
|
|
78
|
-
import { ref } from "vue";
|
|
92
|
+
import { computed, ref, watch } from "vue";
|
|
79
93
|
import { Dialog } from "primevue";
|
|
80
|
-
import { useLocalization } from "#imports";
|
|
81
|
-
import { Button, Inputs } from "#components";
|
|
94
|
+
import { useBakeError, useLocalization, useValidation } from "#imports";
|
|
95
|
+
import { Button, ErrorPopover, InlineError, Inputs } from "#components";
|
|
96
|
+
const { handle: handleError } = useBakeError();
|
|
82
97
|
const { localize: l } = useLocalization();
|
|
98
|
+
const { validate } = useValidation();
|
|
83
99
|
const { schema } = defineProps({
|
|
84
100
|
schema: { type: null, required: true }
|
|
85
101
|
});
|
|
86
102
|
const emit = defineEmits(["submit"]);
|
|
87
|
-
const { dialogOptions, inputs, submit, title } = schema;
|
|
88
|
-
const
|
|
89
|
-
const
|
|
103
|
+
const { dialogOptions, inputs, submit, title, validations = [], showValidationSummary = false } = schema;
|
|
104
|
+
const model = ref({});
|
|
105
|
+
const readyData = ref({});
|
|
90
106
|
const submitted = ref(false);
|
|
91
107
|
const visible = ref(false);
|
|
108
|
+
const submitRef = ref();
|
|
109
|
+
const errorPopoverRef = ref();
|
|
110
|
+
const { error } = handleError();
|
|
111
|
+
const ready = computed(() => Object.values(readyData.value).every((v) => v) && isValid.value);
|
|
112
|
+
const { isValid, messages } = validate({
|
|
113
|
+
inputs,
|
|
114
|
+
model,
|
|
115
|
+
composables: validations
|
|
116
|
+
});
|
|
117
|
+
watch(error, (newError) => {
|
|
118
|
+
if (newError) {
|
|
119
|
+
errorPopoverRef.value.show(submitRef);
|
|
120
|
+
} else {
|
|
121
|
+
errorPopoverRef.value.hide();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
92
124
|
function onReady(value) {
|
|
93
|
-
|
|
125
|
+
readyData.value = value;
|
|
94
126
|
}
|
|
95
127
|
function onChanged({ values }) {
|
|
96
|
-
|
|
128
|
+
model.value = values;
|
|
97
129
|
}
|
|
98
130
|
function execute() {
|
|
131
|
+
if (!ready.value) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
99
134
|
submitted.value = true;
|
|
100
135
|
visible.value = false;
|
|
101
136
|
}
|
|
102
137
|
function emitSubmit() {
|
|
103
|
-
if (submitted.value) {
|
|
138
|
+
if (submitted.value && ready.value) {
|
|
104
139
|
submitted.value = false;
|
|
105
|
-
emit("submit",
|
|
140
|
+
emit("submit", model.value);
|
|
106
141
|
}
|
|
107
142
|
}
|
|
108
143
|
</script>
|
|
@@ -40,11 +40,9 @@
|
|
|
40
40
|
</Bake>
|
|
41
41
|
<Message
|
|
42
42
|
v-if="showRequiredMessage"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<span class="ml-3">{{ lc("Select required values to view this page") }}</span>
|
|
47
|
-
</Message>
|
|
43
|
+
:schema="{ severity: 'info', icon: 'pi pi-info-circle' }"
|
|
44
|
+
:data="lc('Select required values to view this page')"
|
|
45
|
+
/>
|
|
48
46
|
<div
|
|
49
47
|
v-if="ready"
|
|
50
48
|
class="pt-4 flex flex-col gap-4 items-center"
|
|
@@ -70,9 +68,9 @@
|
|
|
70
68
|
|
|
71
69
|
<script setup>
|
|
72
70
|
import { computed, onBeforeUnmount, onMounted, reactive, ref } from "vue";
|
|
73
|
-
import {
|
|
71
|
+
import { Tab, TabList, Tabs } from "primevue";
|
|
74
72
|
import { useContext, useLocalization, useReactionHandler } from "#imports";
|
|
75
|
-
import { Bake, Contents, DeferredTabContent, Inputs } from "#components";
|
|
73
|
+
import { Bake, Contents, DeferredTabContent, Inputs, Message } from "#components";
|
|
76
74
|
const context = useContext();
|
|
77
75
|
const { localize: l } = useLocalization();
|
|
78
76
|
const { localize: lc } = useLocalization({ group: "TabbedPage" });
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
4
|
+
type __VLS_WithSlots<T, S> = T & (new () => {
|
|
5
|
+
$slots: S;
|
|
6
|
+
});
|
|
7
|
+
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
8
|
+
type __VLS_Slots = {
|
|
9
|
+
default?: ((props: {}) => any) | undefined;
|
|
10
|
+
} & {
|
|
11
|
+
default?: ((props: {}) => any) | undefined;
|
|
12
|
+
} & {
|
|
13
|
+
message?: ((props: {
|
|
14
|
+
validation: any;
|
|
15
|
+
mutableValidation: any;
|
|
16
|
+
}) => any) | undefined;
|
|
17
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<template v-if="validationHandled || !validation">
|
|
3
|
+
<slot />
|
|
4
|
+
</template>
|
|
5
|
+
<div
|
|
6
|
+
v-else
|
|
7
|
+
class="b-Validation flex flex-col gap-2"
|
|
8
|
+
>
|
|
9
|
+
<slot />
|
|
10
|
+
<slot
|
|
11
|
+
name="message"
|
|
12
|
+
:validation
|
|
13
|
+
:mutable-validation
|
|
14
|
+
>
|
|
15
|
+
<Message
|
|
16
|
+
v-if="message"
|
|
17
|
+
:schema="{
|
|
18
|
+
severity: severity,
|
|
19
|
+
variant: 'simple',
|
|
20
|
+
size: 'small'
|
|
21
|
+
}"
|
|
22
|
+
:data="message || ''"
|
|
23
|
+
class="ml-3"
|
|
24
|
+
/>
|
|
25
|
+
</slot>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script setup>
|
|
30
|
+
import { computed } from "vue";
|
|
31
|
+
import { useContext } from "#imports";
|
|
32
|
+
import { Message } from "#components";
|
|
33
|
+
const context = useContext();
|
|
34
|
+
const validationHandled = context.injectValidationHandled();
|
|
35
|
+
const validation = context.injectValidation();
|
|
36
|
+
const mutableValidation = context.injectMutableValidation();
|
|
37
|
+
context.provideValidationHandled(true);
|
|
38
|
+
const message = computed(() => {
|
|
39
|
+
if (mutableValidation?.value.message) {
|
|
40
|
+
return mutableValidation.value.message;
|
|
41
|
+
}
|
|
42
|
+
if (validation.value?.message && validation.value?.persist) {
|
|
43
|
+
return validation.value.message;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
});
|
|
47
|
+
const severity = computed(() => mutableValidation?.value.severity || validation?.value.severity);
|
|
48
|
+
</script>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
4
|
+
type __VLS_WithSlots<T, S> = T & (new () => {
|
|
5
|
+
$slots: S;
|
|
6
|
+
});
|
|
7
|
+
declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
8
|
+
type __VLS_Slots = {
|
|
9
|
+
default?: ((props: {}) => any) | undefined;
|
|
10
|
+
} & {
|
|
11
|
+
default?: ((props: {}) => any) | undefined;
|
|
12
|
+
} & {
|
|
13
|
+
message?: ((props: {
|
|
14
|
+
validation: any;
|
|
15
|
+
mutableValidation: any;
|
|
16
|
+
}) => any) | undefined;
|
|
17
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default function _default(): {
|
|
2
|
+
handle: () => {
|
|
3
|
+
error: import("vue").ComputedRef<{
|
|
4
|
+
title: any;
|
|
5
|
+
detail: any;
|
|
6
|
+
} | null>;
|
|
7
|
+
rawError: any;
|
|
8
|
+
};
|
|
9
|
+
normalize: (error: any) => import("vue").ComputedRef<{
|
|
10
|
+
title: any;
|
|
11
|
+
detail: any;
|
|
12
|
+
} | null>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { computed, unref } from "vue";
|
|
2
|
+
import { useContext } from "#imports";
|
|
3
|
+
|
|
4
|
+
export default function() {
|
|
5
|
+
const context = useContext();
|
|
6
|
+
|
|
7
|
+
function handle() {
|
|
8
|
+
const data = context.injectError({ handle: true });
|
|
9
|
+
|
|
10
|
+
return NormalizedError(data);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function normalize(error) {
|
|
14
|
+
return NormalizedError(error).error;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
handle,
|
|
19
|
+
normalize
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function NormalizedError(rawError) {
|
|
24
|
+
const error = computed(() => {
|
|
25
|
+
const e = unref(rawError);
|
|
26
|
+
if(!e) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if(e.name === "FetchError") {
|
|
31
|
+
const messages = e.data?.errors
|
|
32
|
+
? Object.values(e.data.errors).flat().join(" ")
|
|
33
|
+
: null;
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
title: e.data?.title ?? e.statusCode ?? "ERROR",
|
|
37
|
+
detail: messages ?? e.data?.detail ?? e.message ?? e.cause ?? "An error occured."
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
title: e.statusCode ?? e.status ?? "ERROR",
|
|
43
|
+
detail: e.message ?? e.cause ?? "An error occured."
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
error,
|
|
49
|
+
rawError
|
|
50
|
+
};
|
|
51
|
+
}
|