create-nuxt-base 0.1.22 → 0.2.0

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.
Files changed (72) hide show
  1. package/.eslintignore +14 -0
  2. package/.eslintrc +3 -0
  3. package/.github/workflows/release.yml +1 -1
  4. package/.prettierignore +5 -0
  5. package/.prettierrc +6 -0
  6. package/.vscode/settings.json +10 -10
  7. package/CHANGELOG.md +22 -33
  8. package/README.md +1 -0
  9. package/index.js +30 -29
  10. package/nuxt-base-template/.env.example +8 -0
  11. package/nuxt-base-template/.eslintrc +1 -1
  12. package/nuxt-base-template/.vscode/settings.json +6 -16
  13. package/nuxt-base-template/nuxt.config.ts +27 -12
  14. package/nuxt-base-template/package-lock.json +5772 -4389
  15. package/nuxt-base-template/package.json +45 -29
  16. package/nuxt-base-template/src/app.vue +4 -4
  17. package/nuxt-base-template/src/assets/css/tailwind.css +42 -33
  18. package/nuxt-base-template/src/components/SocialMediaBubble.vue +1 -1
  19. package/nuxt-base-template/src/components/base/BaseAccordion.vue +16 -13
  20. package/nuxt-base-template/src/components/base/BaseButton.vue +10 -13
  21. package/nuxt-base-template/src/components/base/BaseContainer.vue +1 -1
  22. package/nuxt-base-template/src/components/base/BaseContextMenuContainer.vue +61 -0
  23. package/nuxt-base-template/src/components/base/BaseInfinityList.vue +1 -1
  24. package/nuxt-base-template/src/components/base/BaseProgressbar.vue +28 -30
  25. package/nuxt-base-template/src/components/base/BaseToggle.vue +17 -10
  26. package/nuxt-base-template/src/components/form/FormInput.vue +34 -0
  27. package/nuxt-base-template/src/components/form/FormPassword.vue +47 -0
  28. package/nuxt-base-template/src/components/form/FormSelect.vue +40 -0
  29. package/nuxt-base-template/src/components/form/FormSubmit.vue +18 -0
  30. package/nuxt-base-template/src/components/form/FormTextarea.vue +36 -0
  31. package/nuxt-base-template/src/components/form/FormToggle.vue +27 -0
  32. package/nuxt-base-template/src/components/modal/Modal.vue +48 -0
  33. package/nuxt-base-template/src/components/modal/ModalConfirm.vue +38 -0
  34. package/nuxt-base-template/src/components/{base/BaseModalContainer.vue → modal/ModalContainer.vue} +1 -1
  35. package/nuxt-base-template/src/components/modal/ModalInfo.vue +22 -0
  36. package/nuxt-base-template/src/components/{ModalShare.vue → modal/ModalShare.vue} +7 -11
  37. package/nuxt-base-template/src/components/{base/BaseNotification.vue → notification/Notification.vue} +8 -7
  38. package/nuxt-base-template/src/components/{base/BaseNotificationContainer.vue → notification/NotificationContainer.vue} +11 -5
  39. package/nuxt-base-template/src/components/pwa/pwa-install-banner.vue +224 -0
  40. package/nuxt-base-template/src/components/transition/TransitionFade.vue +10 -7
  41. package/nuxt-base-template/src/components/transition/TransitionFadeScale.vue +10 -7
  42. package/nuxt-base-template/src/composables/use-auth-fetch.ts +22 -8
  43. package/nuxt-base-template/src/composables/use-context-menu.ts +19 -0
  44. package/nuxt-base-template/src/composables/use-file.ts +1 -2
  45. package/nuxt-base-template/src/composables/use-modal.ts +1 -1
  46. package/nuxt-base-template/src/composables/use-notification.ts +2 -2
  47. package/nuxt-base-template/src/composables/use-share.ts +3 -3
  48. package/nuxt-base-template/src/error.vue +10 -14
  49. package/nuxt-base-template/src/layouts/default.vue +13 -0
  50. package/nuxt-base-template/src/middleware/auth.global.ts +2 -2
  51. package/nuxt-base-template/src/pages/index.vue +31 -6
  52. package/nuxt-base-template/src/plugins/auth.server.ts +72 -0
  53. package/nuxt-base-template/src/plugins/form.plugin.ts +21 -0
  54. package/nuxt-base-template/src/plugins/pwa.plugin.ts +110 -0
  55. package/nuxt-base-template/src/tests/init.test.ts +1 -1
  56. package/nuxt-base-template/tailwind.config.js +33 -23
  57. package/nuxt-base-template/vitest.config.js +3 -3
  58. package/package.json +3 -1
  59. package/nuxt-base-template/formkit-theme.js +0 -137
  60. package/nuxt-base-template/formkit.config.js +0 -35
  61. package/nuxt-base-template/src/components/hello-world.vue +0 -10
  62. package/nuxt-base-template/src/composables/use-form-helper.ts +0 -100
  63. package/nuxt-base-template/src/composables/use-helper.ts +0 -52
  64. package/nuxt-base-template/src/forms/inputs/InputCheckbox.vue +0 -29
  65. package/nuxt-base-template/src/forms/inputs/InputFreeTags.vue +0 -98
  66. package/nuxt-base-template/src/forms/inputs/InputImage.vue +0 -65
  67. package/nuxt-base-template/src/forms/inputs/InputTags.vue +0 -112
  68. package/nuxt-base-template/src/forms/inputs/InputToggle.vue +0 -18
  69. package/nuxt-base-template/src/forms/plugins/asterisk-plugin.ts +0 -29
  70. package/nuxt-base-template/src/forms/plugins/scroll-error-plugin.ts +0 -36
  71. package/nuxt-base-template/src/forms/plugins/value-changes-plugin.ts +0 -13
  72. package/nuxt-base-template/src/plugins/4.auth.server.ts +0 -70
@@ -1,10 +0,0 @@
1
- <script setup lang="ts">
2
- </script>
3
-
4
- <template>
5
- <h1
6
- class="text-transparent text-2xl bg-clip-text bg-gradient-to-r from-purple-400 to-pink-600"
7
- >
8
- Hello World
9
- </h1>
10
- </template>
@@ -1,100 +0,0 @@
1
- import type { FormKitEventListener, FormKitNode } from '@formkit/core';
2
- import { getNode, submitForm as submitFormkit } from '@formkit/core';
3
-
4
- export function useFormHelper() {
5
- function prepareNode(node: FormKitNode | undefined, listener: FormKitEventListener, eventName: string = 'input') {
6
- if (node?.on) {
7
- node.on(eventName, listener);
8
- }
9
- node?.children?.forEach((childNode) => {
10
- prepareNode(childNode as FormKitNode, listener, eventName);
11
- });
12
- }
13
-
14
- async function valueChanges(nodeId: string, listener: FormKitEventListener, eventName: string = 'input') {
15
- // Puffer to load form
16
- await new Promise<void>((resolve) => setTimeout(() => {
17
- resolve();
18
- }, 1));
19
- prepareNode(getNode(nodeId), listener, eventName);
20
- }
21
-
22
- function submitForm(formId: string) {
23
- submitFormkit(formId);
24
- }
25
-
26
- function isDirty(formId: string): boolean {
27
- const form = getNode(formId);
28
-
29
- return !!form?.context?.state?.dirty;
30
- }
31
-
32
- async function getChangedValue(formId: string): Promise<null | object> {
33
- await new Promise(f => setTimeout(f, 100));
34
- const form = getNode(formId);
35
-
36
- if (!form) {
37
- return null;
38
- }
39
- return getDifferences(form?.props?.initial, form?.value);
40
- }
41
-
42
- function getDifferences(obj1: any, obj2: any): any {
43
- if (obj1 === obj2) {
44
- return undefined;
45
- }
46
-
47
- if (typeof obj1 !== typeof obj2) {
48
- return obj2;
49
- }
50
-
51
- if (typeof obj1 !== 'object' || obj1 === null || obj2 === null) {
52
- return obj2;
53
- }
54
-
55
- if (Array.isArray(obj1) !== Array.isArray(obj2)) {
56
- return obj2;
57
- }
58
-
59
- if (Array.isArray(obj1)) {
60
- if (obj1.length !== obj2.length) {
61
- return obj2;
62
- }
63
-
64
- const diffArray: any[] = [];
65
-
66
- for (let i = 0; i < obj1.length; i++) {
67
- const itemDiff = getDifferences(obj1[i], obj2[i]);
68
- if (itemDiff !== undefined) {
69
- diffArray[i] = itemDiff;
70
- }
71
- }
72
-
73
- if (diffArray.length === 0) {
74
- return undefined;
75
- } else {
76
- return diffArray;
77
- }
78
- }
79
-
80
- const keys1 = Object.keys(obj1);
81
- const keys2 = Object.keys(obj2);
82
-
83
- const allKeys = new Set([...keys1, ...keys2]);
84
- const diffObj: any = {};
85
- for (const key of allKeys) {
86
- const keyDiff = getDifferences(obj1[key], obj2[key]);
87
- if (keyDiff !== undefined) {
88
- diffObj[key] = keyDiff;
89
- }
90
- }
91
-
92
- if (Object.keys(diffObj).length === 0) {
93
- return undefined;
94
- } else {
95
- return diffObj;
96
- }
97
- }
98
-
99
- return { getChangedValue, getDifferences, isDirty, submitForm, prepareNode, valueChanges };
100
- }
@@ -1,52 +0,0 @@
1
- export function useHelper() {
2
- function removeFields(obj: any): any {
3
- const ignoreFields = ['id', '__typename'];
4
- if (Array.isArray(obj)) {
5
- return obj.map(item => removeFields(item));
6
- } else if (typeof obj === 'object' && obj !== null) {
7
- const newObj: any = {};
8
- for (const key in obj) {
9
- if (!ignoreFields.includes(key)) {
10
- newObj[key] = removeFields(obj[key]);
11
- }
12
- }
13
- return newObj;
14
- } else {
15
- return obj;
16
- }
17
- }
18
-
19
- function removeNullOrUndefined(obj: any): any {
20
- if (Array.isArray(obj)) {
21
- return obj.map(item => removeNullOrUndefined(item)).filter(item => item !== null && item !== undefined);
22
- } else if (typeof obj === 'object' && obj !== null) {
23
- const newObj: any = {};
24
- for (const key in obj) {
25
- const value = removeNullOrUndefined(obj[key]);
26
- if (value !== null && value !== undefined) {
27
- newObj[key] = value;
28
- }
29
- }
30
- return newObj;
31
- } else {
32
- return obj;
33
- }
34
- }
35
-
36
- function isValidMongoID(id: string): boolean {
37
- const validHexChars = /^[0-9a-fA-F]{24}$/;
38
-
39
- return validHexChars.test(id);
40
- }
41
-
42
- function groupBy<T>(arr: T[], fn: (item: T) => any) {
43
- return arr.reduce<Record<string, T[]>>((prev, curr) => {
44
- const groupKey = fn(curr);
45
- const group = prev[groupKey] || [];
46
- group.push(curr);
47
- return { ...prev, [groupKey]: group };
48
- }, {});
49
- }
50
-
51
- return { removeFields, removeNullOrUndefined, isValidMongoID, groupBy };
52
- }
@@ -1,29 +0,0 @@
1
- <script setup lang="ts">
2
- const props = defineProps({
3
- context: Object,
4
- });
5
- const name = props.context.name;
6
- const label = props.context.attrs.text;
7
-
8
- function setInput(e) {
9
- props.context.node.input(e.target.checked);
10
- }
11
- </script>
12
-
13
- <template>
14
- <div :class="context.classes.container">
15
- <label :id="props.context?.id" :class="context.classes.wrapper">
16
- <div :class="context.classes.inner">
17
- <input :class="context.classes.input" type="checkbox" :name="name" @input="setInput" />
18
- <span :class="context.classes.decorator" aria-hidden="true">
19
- <span :class="[context.classes.decoratorIcon, context.classes.icon]">
20
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 27">
21
- <polygon fill="currentColor" points="26.99 0 10.13 17.17 4.69 11.63 0 16.41 10.4 27 15.05 22.27 15.09 22.31 32 5.1 26.99 0" />
22
- </svg>
23
- </span>
24
- </span>
25
- </div>
26
- </label>
27
- <span :class="context.classes.label" v-html="label"></span>
28
- </div>
29
- </template>
@@ -1,98 +0,0 @@
1
- <script setup lang="ts">
2
- const props = defineProps({
3
- context: Object,
4
- });
5
-
6
- const inputRef = ref();
7
- const inputValue = ref<string>();
8
- const name = props.context?.name;
9
- const placeholder = props.context?.attrs?.placeholder;
10
- const defaultSuggestions = [...props.context?.attrs?.suggestions] || [];
11
- const suggestions = ref<string[]>([...props.context?.attrs?.suggestions]);
12
- const tags = ref<string[]>([]);
13
- patch();
14
-
15
- function patch() {
16
- const values = props.context?._value;
17
- if (values && Array.isArray(values)) {
18
- for (let item of values) {
19
- addTag(item);
20
- }
21
- }
22
- }
23
-
24
-
25
- function addTag(tag?: string) {
26
- if (!inputValue.value && !tag) {
27
- return;
28
- }
29
-
30
- if (tag) {
31
- tags.value.push(tag);
32
- // remove tag from suggestions
33
- if (suggestions.value.findIndex((e) => e === tag) >= 0) {
34
- suggestions.value.splice(suggestions.value.findIndex((e) => e === tag), 1);
35
- }
36
- } else {
37
- if (!tags.value.includes(inputValue.value as string)) {
38
- tags.value.push(inputValue.value as string);
39
- }
40
-
41
- if (suggestions.value.includes(inputValue.value as string)) {
42
- if (suggestions.value.findIndex((e) => e === tag) >= 0) {
43
- suggestions.value.splice(suggestions.value.findIndex((e) => e === inputValue.value), 1);
44
- }
45
- }
46
-
47
- inputValue.value = '';
48
- }
49
-
50
- props.context?.node.input(tags.value);
51
- }
52
-
53
- function removeTag(tag: string) {
54
- tags.value.splice(tags.value.findIndex((e) => e === tag), 1);
55
-
56
- if (defaultSuggestions.includes(tag) && !suggestions.value.includes(tag)) {
57
- suggestions.value.push(tag);
58
- }
59
-
60
- props.context?.node.input(tags.value);
61
- }
62
- </script>
63
-
64
- <template>
65
- <div class="flex flex-col">
66
- <div class="flex flex-row flex-wrap gap-2">
67
- <span v-for="(tag, index) of tags" :key="index" :class="context?.classes.tag">{{ tag }} <span class="i-bi-x" :class="context?.classes.tagIcon" @click="removeTag(tag)"></span> </span>
68
- </div>
69
- <div :class="context?.classes.inputWrapper">
70
- <input
71
- :id="props.context?.id"
72
- ref="inputRef"
73
- v-model="inputValue"
74
- :name="name"
75
- type="text"
76
- :placeholder="placeholder"
77
- :class="context?.classes.input"
78
- @keydown.enter.prevent="addTag()"
79
- />
80
- <span :class="context?.classes.inputIcon"></span>
81
- </div>
82
- <div>
83
- <button type="button" :disabled="!inputValue" :class="context?.classes.button" @click="addTag()">
84
- {{ context?.attrs.buttonText ?? context?.attrs['button-text'] }}
85
- </button>
86
- </div>
87
- <div v-if="suggestions?.length" :class="context?.classes.suggestionsWrapper">
88
- <p :class="context?.classes.suggestionsHeadline">
89
- Beliebte Skills
90
- </p>
91
- <div class="flex flex-row flex-wrap gap-2">
92
- <div v-for="(tag, index) of suggestions" :key="index" :class="context?.classes.suggestionsTag">
93
- {{ tag }} <span :class="context?.classes.suggestionsIcon" @click="addTag(tag)"></span>
94
- </div>
95
- </div>
96
- </div>
97
- </div>
98
- </template>
@@ -1,65 +0,0 @@
1
- <script setup lang="ts">
2
- const props = defineProps({
3
- context: Object,
4
- });
5
-
6
- const value = ref('');
7
- const label = props.context?.label;
8
- const text = props.context?.attrs.text;
9
- const name = props.context?.name;
10
- const config = useRuntimeConfig();
11
- await getPreviewUrl(props.context?._value);
12
-
13
- watch(() => props.context?._value, async () => {
14
- await getPreviewUrl(props.context?._value);
15
- });
16
-
17
- function handleInput(e: any) {
18
- if (!e) {
19
- props.context?.node.input(null);
20
- return;
21
- }
22
-
23
- props.context?.node.input(e.target.files[0]);
24
- }
25
-
26
- async function getPreviewUrl(src: string | File) {
27
- if (!src) {
28
- value.value = '';
29
- }
30
-
31
- const validHexChars = /^[0-9a-fA-F]{24}$/;
32
- if (typeof src === 'object' && validHexChars.test(src?.id)) {
33
- // return config.public.apiUrl + '/files/' + src.id;
34
- const response = await useAuthFetch(config.public.apiUrl + '/files/' + src?.id, { method: 'GET' });
35
- value.value = URL.createObjectURL(response as any);
36
- }
37
- else if (typeof src === 'string') {
38
- value.value = src;
39
- } else if (src instanceof File) {
40
- value.value = URL.createObjectURL(src);
41
- }
42
- }
43
- </script>
44
-
45
- <template>
46
- <div class="image-container" :class="props?.context?.classes.container">
47
- <div v-if="!props.context?._value" :class="props?.context?.classes.uploader">
48
- <label :class="context?.classes.placeholder">{{ text }}</label>
49
- <input
50
- :id="props.context?.id"
51
- :name="name"
52
- type="file"
53
- :class="props?.context?.classes.input"
54
- @input="handleInput"
55
- />
56
- </div>
57
- <div v-else :class="props?.context.classes.fileItem">
58
- <img :src="value" :class="props?.context?.classes.fileItemImage" />
59
- <span :class="props?.context.classes.fileItemImageName">{{ props.context?._value?.name ?? props.context?._value?.filename }}</span>
60
- <button type="button" :class="props?.context.classes.fileItemRemove" @click="handleInput(null)">
61
- Entfernen
62
- </button>
63
- </div>
64
- </div>
65
- </template>
@@ -1,112 +0,0 @@
1
- <script setup lang="ts">
2
- interface TagOption {
3
- label: string;
4
- value: string;
5
- }
6
-
7
- const props = defineProps({
8
- context: Object,
9
- });
10
-
11
- const inputRef = ref();
12
- const inputValue = ref<string>();
13
- const inputFocus = ref();
14
- const name = props.context?.name;
15
- const placeholder = props.context?.attrs?.placeholder;
16
- const tags = ref<TagOption[]>([]);
17
- const defaultOptions: TagOption[] = [...props?.context?.attrs?.options] || [];
18
- const selectOptions = ref<TagOption[]>([...props?.context?.attrs?.options]);
19
- patch();
20
-
21
- function patch() {
22
- const values = props.context?._value;
23
- if (!values) {
24
- return;
25
- }
26
-
27
- if (Array.isArray(values)) {
28
- for (let item of values) {
29
- handleSelect(item);
30
- }
31
- } else {
32
- handleSelect(values);
33
- }
34
- }
35
-
36
- function handleSelect(value: string) {
37
- const tag = selectOptions.value.find((e) => e.value === value);
38
- const included = tags.value?.find((e) => e.value === tag?.value) ?? false;
39
-
40
- if (!tag) {
41
- return;
42
- }
43
-
44
- if (!included) {
45
- tags.value.push(tag);
46
- selectOptions.value = defaultOptions.filter((e) => e.value !== tag.value);
47
- }
48
-
49
- props.context?.node.input(tags.value.map((e) => e.value));
50
- inputValue.value = '';
51
- }
52
-
53
- function handleInput(event: any) {
54
- const value = event.target.value.toLowerCase();
55
-
56
- if (!value) {
57
- selectOptions.value = defaultOptions.filter((e: TagOption) => !props.context?._value?.includes(e.value));
58
- } else {
59
- selectOptions.value = selectOptions.value.filter((e: TagOption) => e.label.toLowerCase().includes(value));
60
- }
61
- }
62
-
63
- function removeTag(tag: TagOption) {
64
- tags.value.splice(tags.value.findIndex((e) => e.value === tag.value), 1);
65
- props.context?.node.input(tags.value.map((e) => e.value));
66
- selectOptions.value = defaultOptions.filter((e: TagOption) => !props.context?._value?.includes(e.value));
67
- }
68
-
69
- function setFocus() {
70
- inputFocus.value = true;
71
- inputValue.value = '';
72
- selectOptions.value = defaultOptions.filter((e: TagOption) => !props.context?._value?.includes(e.value));
73
- }
74
- </script>
75
-
76
- <template>
77
- <div class="flex flex-col">
78
- <div class="flex flex-row flex-wrap gap-2">
79
- <span v-for="tag of tags" :key="tag.value" :class="context?.classes.tag">{{ tag.label }} <span class="i-bi-x" :class="context?.classes.tagIcon" @click="removeTag(tag)"></span> </span>
80
- </div>
81
- <div v-if="selectOptions.length" class="relative" :class="context?.classes.inputWrapper">
82
- <div class="relative w-full flex items-center">
83
- <input
84
- :id="props.context?.id"
85
- ref="inputRef"
86
- v-model="inputValue"
87
- autocomplete="off"
88
- :name="name" type="text" :placeholder="placeholder" :class="context?.classes.input" @focus="setFocus"
89
- @blur="inputFocus = false" @input="handleInput"
90
- />
91
- <span :class="context?.classes.selectIcon" class="formkit-select-icon flex p-[3px] shrink-0 w-5 mr-2 -ml-[1.5em] h-full pointer-events-none formkit-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 7"><path d="M8,6.5c-.13,0-.26-.05-.35-.15L3.15,1.85c-.2-.2-.2-.51,0-.71,.2-.2,.51-.2,.71,0l4.15,4.15L12.15,1.15c.2-.2,.51-.2,.71,0,.2,.2,.2,.51,0,.71l-4.5,4.5c-.1,.1-.23,.15-.35,.15Z" fill="currentColor" /></svg></span>
92
- </div>
93
- <TransitionFade :start-duration="200" :leave-duration="200">
94
- <div
95
- v-show="inputFocus && defaultOptions.length"
96
- class="absolute right-0 left-0 z-50 h-fit max-h-12 flex flex-col justify-start items-start"
97
- :style="`top: ${inputRef?.clientHeight + 1}px`"
98
- :class="context?.classes.dropdown"
99
- >
100
- <div v-if="selectOptions.length" class="w-full">
101
- <button v-for="option of selectOptions" :key="option.value" :class="context?.classes.dropdownItem" @click="handleSelect(option.value)">
102
- {{ option.label }}
103
- </button>
104
- </div>
105
- <div v-else :class="context?.classes.noItemsFound">
106
- Keine Einträge gefunden
107
- </div>
108
- </div>
109
- </TransitionFade>
110
- </div>
111
- </div>
112
- </template>
@@ -1,18 +0,0 @@
1
- <script setup lang="ts">
2
- const props = defineProps({
3
- context: Object,
4
- });
5
- const inputValue = ref(props?.context?._value ?? false);
6
-
7
- watch(() => inputValue.value, () => {
8
- props.context?.node.input(inputValue.value);
9
- });
10
- </script>
11
-
12
- <template>
13
- <div class="flex justify-between items-center" @click="inputValue = !inputValue">
14
- <div class="w-8 h-5 flex items-center bg-gray-300 rounded-full p-1 duration-300 ease-in-out" :class="{ 'bg-green-400': inputValue }">
15
- <div class="bg-white w-4 h-4 rounded-full shadow-md transform duration-300 ease-in-out" :class="{ 'translate-x-2': inputValue }"></div>
16
- </div>
17
- </div>
18
- </template>
@@ -1,29 +0,0 @@
1
- const isCheckboxAndRadioMultiple = (node: any) => (node.props.type === 'checkbox' || node.props.type === 'radio') && node.props.options;
2
-
3
- export function addAsteriskPlugin(node: any) {
4
- node.on('created', () => {
5
- const isRequired = node.props.parsedRules.some((rule: any) => rule.name === 'required');
6
- if (!isRequired) {
7
- return;
8
- }
9
-
10
- const isMultiOption = isCheckboxAndRadioMultiple(node);
11
-
12
- // if we're going to modify the schema then we need
13
- // to update the schemaMemoKey so we don't get an
14
- // invalid cached schema.
15
- node.props.definition.schemaMemoKey = `required_${isMultiOption ? 'multi_' : ''}${node.props.definition.schemaMemoKey}`;
16
-
17
- const schemaFn = node.props.definition.schema;
18
- node.props.definition.schema = (sectionsSchema: any = {}) => {
19
- if (isRequired) {
20
- if (!isMultiOption) {
21
- sectionsSchema.label = {
22
- children: ['$label', ' *'],
23
- };
24
- }
25
- }
26
- return schemaFn(sectionsSchema);
27
- };
28
- });
29
- }
@@ -1,36 +0,0 @@
1
- import type { FormKitNode } from '@formkit/core';
2
-
3
- export function scrollToErrors(node: any) {
4
- if (node.props.type === 'form') {
5
- function scrollTo(node: FormKitNode) {
6
- const el = document.getElementById(node.props.id);
7
- if (el) {
8
- el.scrollIntoView({ block: 'center', behavior: 'smooth' });
9
- }
10
- }
11
-
12
- function scrollToErrors() {
13
- node.walk((child: any) => {
14
- // Check if this child has errors
15
- if (child.ledger.value('blocking') || child.ledger.value('errors')) {
16
- // We found an input with validation errors
17
- scrollTo(child);
18
- // Stop searching
19
- return false;
20
- }
21
- }, true);
22
- }
23
-
24
- function defaultInvalid(node: FormKitNode) {
25
- console.error('FormKit::invalidForm', node);
26
- }
27
-
28
- const onSubmitInvalid = node.props.onSubmitInvalid ?? defaultInvalid;
29
- node.props.onSubmitInvalid = () => {
30
- onSubmitInvalid(node);
31
- scrollToErrors();
32
- };
33
- node.on('unsettled:errors', scrollToErrors);
34
- }
35
- return false;
36
- }
@@ -1,13 +0,0 @@
1
- import type { FormKitEvent, FormKitNode } from '@formkit/core';
2
-
3
- export function valueChangesPlugin(node: FormKitNode) {
4
- const { getDifferences } = useFormHelper();
5
- if (node.props.type === 'form') {
6
- setTimeout(() => {
7
- node.on('commit', (event: FormKitEvent) => {
8
- const diff = getDifferences(event.origin.props._init, event.payload);
9
- node.emit('valueChanges', { init: event.origin.props._init, current: event.payload, diff: diff });
10
- });
11
- }, 300);
12
- }
13
- }
@@ -1,70 +0,0 @@
1
- import { callWithNuxt, defineNuxtPlugin, useNuxtApp, useRuntimeConfig } from 'nuxt/app';
2
- import { ofetch } from 'ofetch';
3
-
4
- export default defineNuxtPlugin({
5
- name: 'auth-server',
6
- enforce: 'pre',
7
- async setup() {
8
- console.debug('4.auth.server.ts::init');
9
- const _nuxt = useNuxtApp();
10
- const config = await callWithNuxt(_nuxt, useRuntimeConfig);
11
- const { refreshToken, accessToken } = await callWithNuxt(_nuxt, useAuthState);
12
- const { setCurrentUser, getDecodedAccessToken, setTokens } = await callWithNuxt(_nuxt, useAuth);
13
- const payload = accessToken.value ? getDecodedAccessToken(accessToken.value) : null;
14
-
15
- if (!refreshToken.value) {
16
- return;
17
- }
18
-
19
- const refreshTokenResult = await ofetch(config.public.host, {
20
- method: 'POST',
21
- headers: {
22
- Authorization: `Bearer ${refreshToken.value}`,
23
- },
24
- body: JSON.stringify({
25
- query: 'mutation refreshToken {refreshToken {token, refreshToken}}',
26
- variables: {},
27
- }),
28
- }).catch((err) => {
29
- console.error('4.auth.server.ts::refreshToken::catch', err.data);
30
- });
31
-
32
- console.debug('4.auth.server.ts::refreshTokenResult', refreshTokenResult);
33
-
34
- if (refreshTokenResult?.data) {
35
- const data = refreshTokenResult.data.refreshToken;
36
- console.debug('4.auth.server.ts::token', data?.token);
37
- console.debug('4.auth.server.ts::refreshToken', data?.refreshToken);
38
- setTokens(data.token, data.refreshToken);
39
-
40
- if (payload?.id) {
41
- const userResult = await ofetch(config.public.host, {
42
- method: 'POST',
43
- headers: {
44
- Authorization: `Bearer ${refreshTokenResult.data.refreshToken?.token}`,
45
- },
46
- body: JSON.stringify({
47
- query: 'query getUser($id: String!){' +
48
- 'getUser(id: $id){' +
49
- 'id ' +
50
- 'avatar ' +
51
- 'firstName ' +
52
- 'lastName ' +
53
- 'email ' +
54
- 'roles ' +
55
- '}}',
56
- variables: {
57
- id: payload.id,
58
- },
59
- }),
60
- }).catch((err) => {
61
- console.error('4.auth.server.ts::getUser::catch', err.data);
62
- });
63
- console.debug('4.auth.server.ts::getUser::userResult', userResult);
64
- if (userResult?.data) {
65
- setCurrentUser(userResult?.data?.getUser);
66
- }
67
- }
68
- }
69
- },
70
- });