@cwa/nuxt-edge 0.0.0-29699738.c20e607 → 0.0.0-29699908.de8da67

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.
@@ -66,20 +66,7 @@ export default class FetchStatusManager {
66
66
  }
67
67
  const isCurrent = this.fetcherStore.isCurrentFetchingToken(event.token);
68
68
  const fetchStatus = this.fetcherStore.fetches[event.token];
69
- if (fetchStatus?.abort) {
70
- this.resourcesStore.setResourceFetchError({
71
- iri: event.resource,
72
- error: createCwaResourceError(new Error(`Not Saved. Fetching token '${event.token}' has been aborted.`)),
73
- isCurrent
74
- });
75
- return;
76
- }
77
- if (!isCurrent) {
78
- this.resourcesStore.setResourceFetchError({
79
- iri: event.resource,
80
- error: createCwaResourceError(new Error(`Not Saved. Fetching token '${event.token}' is no longer current.`)),
81
- isCurrent
82
- });
69
+ if (fetchStatus?.abort || !isCurrent) {
83
70
  return;
84
71
  }
85
72
  const showErrorPage = this.finishFetchShowError(fetchStatus, event.resource);
@@ -43,6 +43,7 @@ export default class Forms {
43
43
  private readonly _resourcesStore;
44
44
  private readonly _submitAttempted;
45
45
  private readonly _fieldValues;
46
+ private readonly _localEntries;
46
47
  constructor(resourcesStoreDefinition: ResourcesStore, cwaFetch: CwaFetch);
47
48
  isSubmitAttempted(iri: string): boolean;
48
49
  setSubmitAttempted(iri: string, attempted: boolean): void;
@@ -55,6 +56,8 @@ export default class Forms {
55
56
  success: boolean;
56
57
  formErrors?: string[];
57
58
  }>;
59
+ registerLocalEntry(iri: string, entry: Record<string, any>): string[];
60
+ unregisterLocalEntries(iri: string, keys: string[]): void;
58
61
  getForm(iri: string): ComputedRef<KeyedFormView | undefined>;
59
62
  getFormViewErrors(formIri: string, field: string): ComputedRef<string[] | undefined>;
60
63
  private get resourcesStore();
@@ -16,6 +16,23 @@ function bracketToNested(flat) {
16
16
  }
17
17
  return result;
18
18
  }
19
+ function createFormViewObject(apiFormView) {
20
+ const structuredFormView = {
21
+ vars: Object.assign({}, apiFormView.vars)
22
+ };
23
+ if (apiFormView.prototype) {
24
+ structuredFormView.prototype = apiFormView.prototype;
25
+ }
26
+ let data = {};
27
+ if (apiFormView.children) {
28
+ for (const child of apiFormView.children) {
29
+ data = { ...data, ...createFormViewObject(child) };
30
+ }
31
+ }
32
+ const fullName = apiFormView.vars.multiple && apiFormView.vars.full_name?.endsWith("[]") ? apiFormView.vars.full_name.slice(0, -2) : apiFormView.vars.full_name;
33
+ data[fullName] = structuredFormView;
34
+ return data;
35
+ }
19
36
  export default class Forms {
20
37
  constructor(resourcesStoreDefinition, cwaFetch) {
21
38
  this.cwaFetch = cwaFetch;
@@ -25,6 +42,7 @@ export default class Forms {
25
42
  _resourcesStore;
26
43
  _submitAttempted = reactive({});
27
44
  _fieldValues = reactive({});
45
+ _localEntries = reactive({});
28
46
  isSubmitAttempted(iri) {
29
47
  return this._submitAttempted[iri] ?? false;
30
48
  }
@@ -105,30 +123,28 @@ export default class Forms {
105
123
  return { success: false };
106
124
  }
107
125
  }
126
+ registerLocalEntry(iri, entry) {
127
+ if (!this._localEntries[iri]) {
128
+ this._localEntries[iri] = {};
129
+ }
130
+ const flat = createFormViewObject(entry);
131
+ Object.assign(this._localEntries[iri], flat);
132
+ return Object.keys(flat);
133
+ }
134
+ unregisterLocalEntries(iri, keys) {
135
+ if (!this._localEntries[iri]) return;
136
+ for (const key of keys) {
137
+ delete this._localEntries[iri][key];
138
+ }
139
+ }
108
140
  getForm(iri) {
109
141
  return computed(() => {
110
142
  const resource = this.resourcesStore.current.byId[iri];
111
143
  if (resource?.data?.["@type"] !== "Form") {
112
144
  return;
113
145
  }
114
- const createFormViewObject = (apiFormView) => {
115
- const structuredFormView = {
116
- vars: Object.assign({}, apiFormView.vars)
117
- };
118
- if (apiFormView.prototype) {
119
- structuredFormView.prototype = apiFormView.prototype;
120
- }
121
- let data = {
122
- [apiFormView.vars.full_name]: structuredFormView
123
- };
124
- if (apiFormView.children) {
125
- for (const child of apiFormView.children) {
126
- data = { ...data, ...createFormViewObject(child) };
127
- }
128
- }
129
- return data;
130
- };
131
- return createFormViewObject(resource.data.formView);
146
+ const apiData = createFormViewObject(resource.data.formView);
147
+ return { ...this._localEntries[iri] ?? {}, ...apiData };
132
148
  });
133
149
  }
134
150
  getFormViewErrors(formIri, field) {
@@ -4,6 +4,9 @@ function replaceNameInTree(node, index) {
4
4
  if (typeof node?.vars?.full_name === "string") {
5
5
  node.vars.full_name = node.vars.full_name.replace(/__name__/g, index);
6
6
  }
7
+ if (typeof node?.vars?.label === "string" && node.vars.label.includes("__name__")) {
8
+ delete node.vars.label;
9
+ }
7
10
  if (Array.isArray(node?.children)) {
8
11
  for (const child of node.children) {
9
12
  replaceNameInTree(child, index);
@@ -19,18 +22,27 @@ export const useCwaFormCollection = (iri, collectionFullName) => {
19
22
  });
20
23
  const vars = computed(() => formEntry.value?.vars);
21
24
  const _entries = reactive([]);
25
+ const _entryKeys = /* @__PURE__ */ new Map();
22
26
  let _nextIndex = 0;
23
27
  const entries = computed(() => [..._entries]);
24
28
  const addEntry = () => {
25
29
  const prototype = formEntry.value?.prototype;
26
- if (!prototype) return;
30
+ if (!prototype || !iri.value) return;
27
31
  const index = _nextIndex++;
28
32
  const cloned = replaceNameInTree(JSON.parse(JSON.stringify(prototype)), String(index));
33
+ const keys = $cwa.forms.registerLocalEntry(iri.value, cloned);
34
+ _entryKeys.set(cloned.vars.full_name, keys);
29
35
  _entries.push(cloned.vars.full_name);
30
36
  };
31
37
  const removeEntry = (fullName) => {
32
38
  const idx = _entries.indexOf(fullName);
33
- if (idx !== -1) _entries.splice(idx, 1);
39
+ if (idx !== -1) {
40
+ _entries.splice(idx, 1);
41
+ if (iri.value) {
42
+ $cwa.forms.unregisterLocalEntries(iri.value, _entryKeys.get(fullName) ?? []);
43
+ }
44
+ _entryKeys.delete(fullName);
45
+ }
34
46
  };
35
47
  return { entries, addEntry, removeEntry, vars };
36
48
  };
@@ -10,7 +10,7 @@ export const useCwaFormInput = (iri, fullName, opts) => {
10
10
  const initValue = () => {
11
11
  const v = vars.value;
12
12
  if (v?.block_prefixes?.includes("checkbox")) {
13
- return v.checked ? v.value ?? "1" : "";
13
+ return v.checked ? v.value ?? "1" : null;
14
14
  }
15
15
  return v?.value;
16
16
  };
@@ -36,16 +36,16 @@ export const useCwaFormInput = (iri, fullName, opts) => {
36
36
  });
37
37
  const hasBlurred = ref(false);
38
38
  const hasPreviouslyBeenValid = ref(false);
39
+ const validating = ref(false);
39
40
  watch(valid, (v) => {
40
41
  if (v === true) hasPreviouslyBeenValid.value = true;
41
42
  });
42
43
  const displayErrors = computed(
43
- () => (opts?.blurTrigger !== void 0 ? opts.blurTrigger.value : hasBlurred.value) || hasPreviouslyBeenValid.value && valid.value === false || $cwa.forms.isSubmitAttempted(iri.value ?? "")
44
+ () => !validating.value && ((opts?.blurTrigger !== void 0 ? opts.blurTrigger.value : hasBlurred.value) || hasPreviouslyBeenValid.value && valid.value === false || $cwa.forms.isSubmitAttempted(iri.value ?? ""))
44
45
  );
45
46
  const onBlur = () => {
46
47
  hasBlurred.value = true;
47
48
  };
48
- const validating = ref(false);
49
49
  const result = {
50
50
  vars,
51
51
  value,
@@ -57,7 +57,11 @@ export const useCwaFormInput = (iri, fullName, opts) => {
57
57
  validate: async (extraData) => {
58
58
  if (!iri.value || !vars.value) return;
59
59
  validating.value = true;
60
- await $cwa.forms.validateField(`${iri.value}/submit`, { [fullName]: value.value, ...extraData });
60
+ await $cwa.forms.validateField(`${iri.value}/submit`, {
61
+ ...$cwa.forms.getFieldValues(iri.value),
62
+ [fullName]: value.value,
63
+ ...extraData
64
+ });
61
65
  validating.value = false;
62
66
  },
63
67
  onInput: null
@@ -1,25 +1,25 @@
1
- import type { Ref } from 'vue';
1
+ import type { ComputedRef, Ref } from 'vue';
2
2
  export declare const useCwaFormRepeated: (iri: Ref<string | undefined>, fullName: string) => {
3
3
  first: {
4
+ errors: ComputedRef<string[]>;
5
+ valid: ComputedRef<boolean | null>;
4
6
  onInput: import("lodash-es/debounce").DebouncedFunc<() => void>;
5
7
  onBlur: () => void;
6
- vars: import("vue").ComputedRef<import("../api/forms.js").ViewVars | undefined>;
8
+ vars: ComputedRef<import("../api/forms.js").ViewVars | undefined>;
7
9
  value: Ref<any, any>;
8
- errors: import("vue").ComputedRef<string[]>;
9
- valid: import("vue").ComputedRef<boolean | null>;
10
10
  validating: Ref<boolean, boolean>;
11
- displayErrors: import("vue").ComputedRef<boolean>;
11
+ displayErrors: ComputedRef<boolean>;
12
12
  validate: (extraData?: Record<string, any>) => Promise<void>;
13
13
  };
14
14
  second: {
15
+ errors: ComputedRef<string[]>;
16
+ valid: ComputedRef<boolean | null>;
15
17
  onInput: import("lodash-es/debounce").DebouncedFunc<() => void>;
16
18
  onBlur: () => void;
17
- vars: import("vue").ComputedRef<import("../api/forms.js").ViewVars | undefined>;
19
+ vars: ComputedRef<import("../api/forms.js").ViewVars | undefined>;
18
20
  value: Ref<any, any>;
19
- errors: import("vue").ComputedRef<string[]>;
20
- valid: import("vue").ComputedRef<boolean | null>;
21
21
  validating: Ref<boolean, boolean>;
22
- displayErrors: import("vue").ComputedRef<boolean>;
22
+ displayErrors: ComputedRef<boolean>;
23
23
  validate: (extraData?: Record<string, any>) => Promise<void>;
24
24
  };
25
25
  };
@@ -1,32 +1,83 @@
1
- import { ref } from "vue";
1
+ import { computed, ref } from "vue";
2
2
  import debounce from "lodash-es/debounce";
3
+ import { useCwa } from "#cwa/composables/cwa";
3
4
  import { useCwaFormInput } from "#cwa/composables/cwa-form-input";
4
5
  export const useCwaFormRepeated = (iri, fullName) => {
6
+ const $cwa = useCwa();
5
7
  const firstFullName = `${fullName}[first]`;
6
8
  const secondFullName = `${fullName}[second]`;
7
9
  const bothBlurred = ref(false);
8
10
  let firstHasBlurred = false;
9
11
  let secondHasBlurred = false;
12
+ const lastTriggeredBy = ref(null);
10
13
  const first = useCwaFormInput(iri, firstFullName, { blurTrigger: bothBlurred });
11
14
  const second = useCwaFormInput(iri, secondFullName, { blurTrigger: bothBlurred });
15
+ const parentVars = computed(() => {
16
+ if (!iri.value) return void 0;
17
+ return $cwa.forms.getForm(iri.value).value?.[fullName]?.vars;
18
+ });
19
+ const parentValid = computed(() => {
20
+ if (!parentVars.value?.submitted) return null;
21
+ return parentVars.value?.valid ?? null;
22
+ });
23
+ const firstValid = computed(() => {
24
+ if (!first.value.value || !second.value.value) return null;
25
+ return parentValid.value;
26
+ });
27
+ const secondValid = computed(() => {
28
+ if (!first.value.value || !second.value.value) return null;
29
+ return parentValid.value;
30
+ });
31
+ const firstErrors = computed(() => {
32
+ if (lastTriggeredBy.value === "second") return [];
33
+ return first.errors.value;
34
+ });
35
+ const secondErrors = computed(() => {
36
+ const base = second.errors.value;
37
+ if (lastTriggeredBy.value === "second" && first.errors.value.length) {
38
+ const extra = first.errors.value.filter((e) => !base.includes(e));
39
+ return [...base, ...extra];
40
+ }
41
+ return base;
42
+ });
12
43
  const firstOnInput = debounce(() => {
13
- first.validate({ [secondFullName]: second.value.value || "__FAKE__" });
44
+ lastTriggeredBy.value = "first";
45
+ const extra = second.value.value ? { [secondFullName]: second.value.value } : void 0;
46
+ first.validate(extra);
14
47
  }, 300);
15
48
  const secondOnInput = debounce(() => {
16
- second.validate({ [firstFullName]: first.value.value || "__FAKE__" });
49
+ lastTriggeredBy.value = "second";
50
+ const extra = first.value.value ? { [firstFullName]: first.value.value } : void 0;
51
+ second.validate(extra);
17
52
  }, 300);
18
53
  const firstOnBlur = () => {
19
54
  firstHasBlurred = true;
20
55
  if (secondHasBlurred) bothBlurred.value = true;
21
- first.validate({ [secondFullName]: second.value.value || "__FAKE__" });
56
+ lastTriggeredBy.value = "first";
57
+ const extra = second.value.value ? { [secondFullName]: second.value.value } : void 0;
58
+ first.validate(extra);
22
59
  };
23
60
  const secondOnBlur = () => {
24
61
  secondHasBlurred = true;
25
62
  if (firstHasBlurred) bothBlurred.value = true;
26
- second.validate({ [firstFullName]: first.value.value || "__FAKE__" });
63
+ lastTriggeredBy.value = "second";
64
+ const extra = first.value.value ? { [firstFullName]: first.value.value } : void 0;
65
+ second.validate(extra);
27
66
  };
28
67
  return {
29
- first: { ...first, onInput: firstOnInput, onBlur: firstOnBlur },
30
- second: { ...second, onInput: secondOnInput, onBlur: secondOnBlur }
68
+ first: {
69
+ ...first,
70
+ errors: firstErrors,
71
+ valid: firstValid,
72
+ onInput: firstOnInput,
73
+ onBlur: firstOnBlur
74
+ },
75
+ second: {
76
+ ...second,
77
+ errors: secondErrors,
78
+ valid: secondValid,
79
+ onInput: secondOnInput,
80
+ onBlur: secondOnBlur
81
+ }
31
82
  };
32
83
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cwa/nuxt-edge",
3
- "version": "0.0.0-29699738.c20e607",
3
+ "version": "0.0.0-29699908.de8da67",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Components Web Apps Nuxt Module. UI for creating component-driven web apps with the API Components Bundle",