@beinformed/ui 1.48.1 → 1.49.3

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 (111) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/esm/hooks/useForm.js +17 -2
  3. package/esm/hooks/useForm.js.map +1 -1
  4. package/esm/models/attributes/AttributeModel.js +2 -1
  5. package/esm/models/attributes/AttributeModel.js.map +1 -1
  6. package/esm/models/attributes/ChoiceAttributeModel.js +16 -1
  7. package/esm/models/attributes/ChoiceAttributeModel.js.map +1 -1
  8. package/esm/models/attributes/ChoiceAttributeOptionCollection.js +10 -3
  9. package/esm/models/attributes/ChoiceAttributeOptionCollection.js.map +1 -1
  10. package/esm/models/concepts/ConceptDetailModel.js +7 -0
  11. package/esm/models/concepts/ConceptDetailModel.js.map +1 -1
  12. package/esm/models/form/FormModel.js +22 -2
  13. package/esm/models/form/FormModel.js.map +1 -1
  14. package/esm/models/form/FormObjectModel.js +9 -1
  15. package/esm/models/form/FormObjectModel.js.map +1 -1
  16. package/esm/modularui/ModularUIRequest.js +1 -1
  17. package/esm/modularui/ModularUIRequest.js.map +1 -1
  18. package/esm/redux/_modularui/ModularUIActions.js +4 -10
  19. package/esm/redux/_modularui/ModularUIActions.js.map +1 -1
  20. package/esm/redux/actions/FormAttributeSet.js +22 -6
  21. package/esm/redux/actions/FormAttributeSet.js.map +1 -1
  22. package/esm/redux/actions/FormAutosubmit.js +9 -1
  23. package/esm/redux/actions/FormAutosubmit.js.map +1 -1
  24. package/esm/redux/actions/FormAutoupdate.js +29 -0
  25. package/esm/redux/actions/FormAutoupdate.js.map +1 -0
  26. package/esm/redux/connectors/FormAttributeSet.js +3 -2
  27. package/esm/redux/connectors/FormAttributeSet.js.map +1 -1
  28. package/esm/redux/types.js.map +1 -1
  29. package/esm/utils/fetch/types.js.map +1 -1
  30. package/lib/hooks/useForm.js +17 -2
  31. package/lib/hooks/useForm.js.flow +22 -7
  32. package/lib/hooks/useForm.js.map +1 -1
  33. package/lib/models/attributes/AttributeModel.js +2 -1
  34. package/lib/models/attributes/AttributeModel.js.flow +2 -1
  35. package/lib/models/attributes/AttributeModel.js.map +1 -1
  36. package/lib/models/attributes/ChoiceAttributeModel.js +16 -1
  37. package/lib/models/attributes/ChoiceAttributeModel.js.flow +23 -2
  38. package/lib/models/attributes/ChoiceAttributeModel.js.map +1 -1
  39. package/lib/models/attributes/ChoiceAttributeOptionCollection.js +10 -3
  40. package/lib/models/attributes/ChoiceAttributeOptionCollection.js.flow +16 -8
  41. package/lib/models/attributes/ChoiceAttributeOptionCollection.js.map +1 -1
  42. package/lib/models/concepts/ConceptDetailModel.js +7 -0
  43. package/lib/models/concepts/ConceptDetailModel.js.flow +8 -0
  44. package/lib/models/concepts/ConceptDetailModel.js.map +1 -1
  45. package/lib/models/form/FormModel.js +22 -2
  46. package/lib/models/form/FormModel.js.flow +25 -5
  47. package/lib/models/form/FormModel.js.map +1 -1
  48. package/lib/models/form/FormObjectModel.js +9 -1
  49. package/lib/models/form/FormObjectModel.js.flow +9 -1
  50. package/lib/models/form/FormObjectModel.js.map +1 -1
  51. package/lib/modularui/ModularUIRequest.js +1 -1
  52. package/lib/modularui/ModularUIRequest.js.flow +1 -1
  53. package/lib/modularui/ModularUIRequest.js.map +1 -1
  54. package/lib/redux/_modularui/ModularUIActions.js +4 -10
  55. package/lib/redux/_modularui/ModularUIActions.js.flow +8 -16
  56. package/lib/redux/_modularui/ModularUIActions.js.map +1 -1
  57. package/lib/redux/actions/FormAttributeSet.js +22 -6
  58. package/lib/redux/actions/FormAttributeSet.js.flow +36 -11
  59. package/lib/redux/actions/FormAttributeSet.js.map +1 -1
  60. package/lib/redux/actions/FormAutosubmit.js +10 -1
  61. package/lib/redux/actions/FormAutosubmit.js.flow +10 -3
  62. package/lib/redux/actions/FormAutosubmit.js.map +1 -1
  63. package/lib/redux/actions/FormAutoupdate.js +37 -0
  64. package/lib/redux/actions/FormAutoupdate.js.flow +43 -0
  65. package/lib/redux/actions/FormAutoupdate.js.map +1 -0
  66. package/lib/redux/connectors/FormAttributeSet.js +3 -2
  67. package/lib/redux/connectors/FormAttributeSet.js.flow +4 -2
  68. package/lib/redux/connectors/FormAttributeSet.js.map +1 -1
  69. package/lib/redux/types.js.flow +1 -0
  70. package/lib/redux/types.js.map +1 -1
  71. package/lib/utils/fetch/types.js.flow +2 -1
  72. package/lib/utils/fetch/types.js.map +1 -1
  73. package/package.json +1 -1
  74. package/src/hooks/useForm.js +22 -7
  75. package/src/models/attributes/AttributeModel.js +2 -1
  76. package/src/models/attributes/ChoiceAttributeModel.js +23 -2
  77. package/src/models/attributes/ChoiceAttributeOptionCollection.js +16 -8
  78. package/src/models/concepts/ConceptDetailModel.js +8 -0
  79. package/src/models/form/FormModel.js +25 -5
  80. package/src/models/form/FormObjectModel.js +9 -1
  81. package/src/modularui/ModularUIRequest.js +1 -1
  82. package/src/redux/_modularui/ModularUIActions.js +8 -16
  83. package/src/redux/actions/FormAttributeSet.js +36 -11
  84. package/src/redux/actions/FormAutosubmit.js +10 -3
  85. package/src/redux/actions/FormAutoupdate.js +43 -0
  86. package/src/redux/connectors/FormAttributeSet.js +4 -2
  87. package/src/redux/types.js +1 -0
  88. package/src/utils/fetch/types.js +2 -1
  89. package/types/hooks/useI18n.d.ts +1 -1
  90. package/types/models/application/ApplicationModel.d.ts +7 -0
  91. package/types/models/attributes/AttributeModel.d.ts +4 -3
  92. package/types/models/attributes/ChoiceAttributeModel.d.ts +4 -0
  93. package/types/models/attributes/ChoiceAttributeOptionCollection.d.ts +1 -1
  94. package/types/models/attributes/ChoiceAttributeOptionModel.d.ts +2 -1
  95. package/types/models/attributes/input-constraints/ConstraintModel.d.ts +1 -1
  96. package/types/models/base/ResourceCollection.d.ts +2 -1
  97. package/types/models/base/ResourceModel.d.ts +3 -2
  98. package/types/models/concepts/BusinessScenarioModel.d.ts +1 -1
  99. package/types/models/concepts/ConceptRelationModel.d.ts +19 -4
  100. package/types/models/content/ContentModel.d.ts +4 -0
  101. package/types/models/content/ContentTOCModel.d.ts +4 -0
  102. package/types/models/form/FormModel.d.ts +7 -1
  103. package/types/models/form/FormObjectModel.d.ts +11 -2
  104. package/types/models/links/normalizeLinkJSON.d.ts +2 -2
  105. package/types/models/list/ListModel.d.ts +4 -0
  106. package/types/models/panels/GroupingPanelModel.d.ts +4 -0
  107. package/types/models/tab/TabModel.d.ts +4 -0
  108. package/types/models/types.d.ts +2 -1
  109. package/types/models/user/UserServicesModel.d.ts +7 -0
  110. package/types/redux/types.d.ts +1 -0
  111. package/types/utils/fetch/types.d.ts +2 -1
@@ -0,0 +1,43 @@
1
+ // @flow
2
+ import { loadModularUI } from "../_modularui/ModularUIActions";
3
+ import { HTTP_METHODS } from "../../constants/Constants";
4
+
5
+ import FormModel from "../../models/form/FormModel";
6
+
7
+ import type { AttributeType, ModularUIModel } from "../../models/types";
8
+ import type { ThunkAction } from "../types";
9
+
10
+ /**
11
+ */
12
+ export const autoupdateFormObject = (
13
+ form: FormModel,
14
+ attribute: AttributeType,
15
+ ): ?ThunkAction => {
16
+ // As long as we have form objects,
17
+ // and the current attribute is not found in the current form object, go back.
18
+ // When a form has a result, the current form object is null
19
+ while (
20
+ form.allObjects.length > 0 &&
21
+ (!form.currentFormObject ||
22
+ !form.currentFormObject.hasAttributeByKey(attribute.key))
23
+ ) {
24
+ form.setPreviousObject();
25
+ }
26
+
27
+ if (form.isChanged()) {
28
+ return loadModularUI(form.connectKey, form.selfhref, {
29
+ method: HTTP_METHODS.POST,
30
+ data: form.formdata,
31
+ updateHandler: (newModel: ModularUIModel): ModularUIModel => {
32
+ if (newModel instanceof FormModel) {
33
+ const clonedModel: FormModel = form.clone();
34
+ clonedModel.updateCurrentFormObject(newModel);
35
+ return clonedModel;
36
+ }
37
+ return newModel;
38
+ },
39
+ });
40
+ }
41
+
42
+ return null;
43
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormAutoupdate.js","names":["_ModularUIActions","require","_Constants","_FormModel","_interopRequireDefault","autoupdateFormObject","form","attribute","allObjects","length","currentFormObject","hasAttributeByKey","key","setPreviousObject","isChanged","loadModularUI","connectKey","selfhref","method","HTTP_METHODS","POST","data","formdata","updateHandler","newModel","FormModel","clonedModel","clone","updateCurrentFormObject","exports"],"sources":["../../../src/redux/actions/FormAutoupdate.js"],"sourcesContent":["// @flow\nimport { loadModularUI } from \"../_modularui/ModularUIActions\";\nimport { HTTP_METHODS } from \"../../constants/Constants\";\n\nimport FormModel from \"../../models/form/FormModel\";\n\nimport type { AttributeType, ModularUIModel } from \"../../models/types\";\nimport type { ThunkAction } from \"../types\";\n\n/**\n */\nexport const autoupdateFormObject = (\n form: FormModel,\n attribute: AttributeType,\n): ?ThunkAction => {\n // As long as we have form objects,\n // and the current attribute is not found in the current form object, go back.\n // When a form has a result, the current form object is null\n while (\n form.allObjects.length > 0 &&\n (!form.currentFormObject ||\n !form.currentFormObject.hasAttributeByKey(attribute.key))\n ) {\n form.setPreviousObject();\n }\n\n if (form.isChanged()) {\n return loadModularUI(form.connectKey, form.selfhref, {\n method: HTTP_METHODS.POST,\n data: form.formdata,\n updateHandler: (newModel: ModularUIModel): ModularUIModel => {\n if (newModel instanceof FormModel) {\n const clonedModel: FormModel = form.clone();\n clonedModel.updateCurrentFormObject(newModel);\n return clonedModel;\n }\n return newModel;\n },\n });\n }\n\n return null;\n};\n"],"mappings":";;;;;;;AACA,IAAAA,iBAAA,GAAAC,OAAA;AACA,IAAAC,UAAA,GAAAD,OAAA;AAEA,IAAAE,UAAA,GAAAC,sBAAA,CAAAH,OAAA;AAKA;AACA;AACO,MAAMI,oBAAoB,GAAGA,CAClCC,IAAe,EACfC,SAAwB,KACP;EACjB;EACA;EACA;EACA,OACED,IAAI,CAACE,UAAU,CAACC,MAAM,GAAG,CAAC,KACzB,CAACH,IAAI,CAACI,iBAAiB,IACtB,CAACJ,IAAI,CAACI,iBAAiB,CAACC,iBAAiB,CAACJ,SAAS,CAACK,GAAG,CAAC,CAAC,EAC3D;IACAN,IAAI,CAACO,iBAAiB,CAAC,CAAC;EAC1B;EAEA,IAAIP,IAAI,CAACQ,SAAS,CAAC,CAAC,EAAE;IACpB,OAAO,IAAAC,+BAAa,EAACT,IAAI,CAACU,UAAU,EAAEV,IAAI,CAACW,QAAQ,EAAE;MACnDC,MAAM,EAAEC,uBAAY,CAACC,IAAI;MACzBC,IAAI,EAAEf,IAAI,CAACgB,QAAQ;MACnBC,aAAa,EAAGC,QAAwB,IAAqB;QAC3D,IAAIA,QAAQ,YAAYC,kBAAS,EAAE;UACjC,MAAMC,WAAsB,GAAGpB,IAAI,CAACqB,KAAK,CAAC,CAAC;UAC3CD,WAAW,CAACE,uBAAuB,CAACJ,QAAQ,CAAC;UAC7C,OAAOE,WAAW;QACpB;QACA,OAAOF,QAAQ;MACjB;IACF,CAAC,CAAC;EACJ;EAEA,OAAO,IAAI;AACb,CAAC;AAACK,OAAA,CAAAxB,oBAAA,GAAAA,oBAAA","ignoreList":[]}
@@ -10,8 +10,9 @@ var _FormAttributeSetRepeatable = require("../actions/FormAttributeSetRepeatable
10
10
  const mapDispatchToProps = (dispatch, ownProps) => ({
11
11
  onAttributeChange: function (attribute, value) {
12
12
  let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
13
- autosubmit: ownProps.autosubmit || false,
14
- autosave: ownProps.autosave || false
13
+ autosubmit: ownProps.autosubmit ?? false,
14
+ autosave: ownProps.autosave ?? false,
15
+ autoupdate: ownProps.autoupdate ?? false
15
16
  };
16
17
  return dispatch((0, _FormAttributeSet.updateFormAttribute)(ownProps.form, ownProps.object, attribute, value, options));
17
18
  },
@@ -24,6 +24,7 @@ type OwnProps = {
24
24
  formLayout?: "vertical" | "horizontal" | "compact",
25
25
  autosubmit?: boolean,
26
26
  autosave?: boolean,
27
+ autoupdate?: boolean,
27
28
  };
28
29
 
29
30
  type DispatchProps = {
@@ -50,8 +51,9 @@ const mapDispatchToProps = (
50
51
  attribute: AttributeType,
51
52
  value: string,
52
53
  options: UpdateFormOptions = {
53
- autosubmit: ownProps.autosubmit || false,
54
- autosave: ownProps.autosave || false,
54
+ autosubmit: ownProps.autosubmit ?? false,
55
+ autosave: ownProps.autosave ?? false,
56
+ autoupdate: ownProps.autoupdate ?? false,
55
57
  },
56
58
  ) =>
57
59
  dispatch(
@@ -1 +1 @@
1
- {"version":3,"file":"FormAttributeSet.js","names":["_reactRedux","require","_FormAttributeSet","_FormAttributeSetRepeatable","mapDispatchToProps","dispatch","ownProps","onAttributeChange","attribute","value","options","arguments","length","undefined","autosubmit","autosave","updateFormAttribute","form","object","onAddAttributeSetClick","addRepeatableAttributeSet","onCancelAttributeSetClick","formObject","cancelRepeatableAttributeSet","onRemoveAttributeSetClick","removeRepeatableAttributeSet","connectFormAttributeSet","exports","connect"],"sources":["../../../src/redux/connectors/FormAttributeSet.js"],"sourcesContent":["// @flow\nimport { connect } from \"react-redux\";\n\nimport { updateFormAttribute } from \"../actions/FormAttributeSet\";\nimport {\n addRepeatableAttributeSet,\n cancelRepeatableAttributeSet,\n removeRepeatableAttributeSet,\n} from \"../actions/FormAttributeSetRepeatable\";\n\nimport type { ThunkAction, UpdateFormOptions } from \"../types\";\nimport type { UpdateFormAction } from \"../_modularui/types\";\nimport type { AttributeType } from \"../../models/types\";\nimport type FormModel from \"../../models/form/FormModel\";\nimport type FormObjectModel from \"../../models/form/FormObjectModel\";\nimport type { DispatchAPI } from \"redux\";\nimport type { ComponentType } from \"react\";\n\ntype Dispatch = DispatchAPI<UpdateFormAction> & DispatchAPI<ThunkAction>;\n\ntype OwnProps = {\n form: FormModel,\n object: FormObjectModel,\n formLayout?: \"vertical\" | \"horizontal\" | \"compact\",\n autosubmit?: boolean,\n autosave?: boolean,\n};\n\ntype DispatchProps = {\n onAttributeChange: (\n attribute: AttributeType,\n value: string,\n options: UpdateFormOptions,\n ) => ThunkAction,\n onAddAttributeSetClick: () => UpdateFormAction,\n onCancelAttributeSetClick: (formObject: FormObjectModel) => UpdateFormAction,\n onRemoveAttributeSetClick: (formObject: FormObjectModel) => UpdateFormAction,\n};\n\ntype Props = {\n ...OwnProps,\n ...DispatchProps,\n};\n\nconst mapDispatchToProps = (\n dispatch: Dispatch,\n ownProps: OwnProps,\n): DispatchProps => ({\n onAttributeChange: (\n attribute: AttributeType,\n value: string,\n options: UpdateFormOptions = {\n autosubmit: ownProps.autosubmit || false,\n autosave: ownProps.autosave || false,\n },\n ) =>\n dispatch(\n updateFormAttribute(\n ownProps.form,\n ownProps.object,\n attribute,\n value,\n options,\n ),\n ),\n onAddAttributeSetClick: () =>\n dispatch(addRepeatableAttributeSet(ownProps.form)),\n onCancelAttributeSetClick: (formObject: FormObjectModel) =>\n dispatch(cancelRepeatableAttributeSet(ownProps.form, formObject)),\n onRemoveAttributeSetClick: (formObject: FormObjectModel) =>\n dispatch(removeRepeatableAttributeSet(ownProps.form, formObject)),\n});\n\n/**\n */\nexport const connectFormAttributeSet: ComponentType<any> = connect<\n Props,\n OwnProps,\n _,\n DispatchProps,\n _,\n _,\n>(null, mapDispatchToProps);\n"],"mappings":";;;;;;AACA,IAAAA,WAAA,GAAAC,OAAA;AAEA,IAAAC,iBAAA,GAAAD,OAAA;AACA,IAAAE,2BAAA,GAAAF,OAAA;AAwCA,MAAMG,kBAAkB,GAAGA,CACzBC,QAAkB,EAClBC,QAAkB,MACC;EACnBC,iBAAiB,EAAE,SAAAA,CACjBC,SAAwB,EACxBC,KAAa;IAAA,IACbC,OAA0B,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG;MAC3BG,UAAU,EAAER,QAAQ,CAACQ,UAAU,IAAI,KAAK;MACxCC,QAAQ,EAAET,QAAQ,CAACS,QAAQ,IAAI;IACjC,CAAC;IAAA,OAEDV,QAAQ,CACN,IAAAW,qCAAmB,EACjBV,QAAQ,CAACW,IAAI,EACbX,QAAQ,CAACY,MAAM,EACfV,SAAS,EACTC,KAAK,EACLC,OACF,CACF,CAAC;EAAA;EACHS,sBAAsB,EAAEA,CAAA,KACtBd,QAAQ,CAAC,IAAAe,qDAAyB,EAACd,QAAQ,CAACW,IAAI,CAAC,CAAC;EACpDI,yBAAyB,EAAGC,UAA2B,IACrDjB,QAAQ,CAAC,IAAAkB,wDAA4B,EAACjB,QAAQ,CAACW,IAAI,EAAEK,UAAU,CAAC,CAAC;EACnEE,yBAAyB,EAAGF,UAA2B,IACrDjB,QAAQ,CAAC,IAAAoB,wDAA4B,EAACnB,QAAQ,CAACW,IAAI,EAAEK,UAAU,CAAC;AACpE,CAAC,CAAC;;AAEF;AACA;AACO,MAAMI,uBAA2C,GAAAC,OAAA,CAAAD,uBAAA,GAAG,IAAAE,mBAAO,EAOhE,IAAI,EAAExB,kBAAkB,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"FormAttributeSet.js","names":["_reactRedux","require","_FormAttributeSet","_FormAttributeSetRepeatable","mapDispatchToProps","dispatch","ownProps","onAttributeChange","attribute","value","options","arguments","length","undefined","autosubmit","autosave","autoupdate","updateFormAttribute","form","object","onAddAttributeSetClick","addRepeatableAttributeSet","onCancelAttributeSetClick","formObject","cancelRepeatableAttributeSet","onRemoveAttributeSetClick","removeRepeatableAttributeSet","connectFormAttributeSet","exports","connect"],"sources":["../../../src/redux/connectors/FormAttributeSet.js"],"sourcesContent":["// @flow\nimport { connect } from \"react-redux\";\n\nimport { updateFormAttribute } from \"../actions/FormAttributeSet\";\nimport {\n addRepeatableAttributeSet,\n cancelRepeatableAttributeSet,\n removeRepeatableAttributeSet,\n} from \"../actions/FormAttributeSetRepeatable\";\n\nimport type { ThunkAction, UpdateFormOptions } from \"../types\";\nimport type { UpdateFormAction } from \"../_modularui/types\";\nimport type { AttributeType } from \"../../models/types\";\nimport type FormModel from \"../../models/form/FormModel\";\nimport type FormObjectModel from \"../../models/form/FormObjectModel\";\nimport type { DispatchAPI } from \"redux\";\nimport type { ComponentType } from \"react\";\n\ntype Dispatch = DispatchAPI<UpdateFormAction> & DispatchAPI<ThunkAction>;\n\ntype OwnProps = {\n form: FormModel,\n object: FormObjectModel,\n formLayout?: \"vertical\" | \"horizontal\" | \"compact\",\n autosubmit?: boolean,\n autosave?: boolean,\n autoupdate?: boolean,\n};\n\ntype DispatchProps = {\n onAttributeChange: (\n attribute: AttributeType,\n value: string,\n options: UpdateFormOptions,\n ) => ThunkAction,\n onAddAttributeSetClick: () => UpdateFormAction,\n onCancelAttributeSetClick: (formObject: FormObjectModel) => UpdateFormAction,\n onRemoveAttributeSetClick: (formObject: FormObjectModel) => UpdateFormAction,\n};\n\ntype Props = {\n ...OwnProps,\n ...DispatchProps,\n};\n\nconst mapDispatchToProps = (\n dispatch: Dispatch,\n ownProps: OwnProps,\n): DispatchProps => ({\n onAttributeChange: (\n attribute: AttributeType,\n value: string,\n options: UpdateFormOptions = {\n autosubmit: ownProps.autosubmit ?? false,\n autosave: ownProps.autosave ?? false,\n autoupdate: ownProps.autoupdate ?? false,\n },\n ) =>\n dispatch(\n updateFormAttribute(\n ownProps.form,\n ownProps.object,\n attribute,\n value,\n options,\n ),\n ),\n onAddAttributeSetClick: () =>\n dispatch(addRepeatableAttributeSet(ownProps.form)),\n onCancelAttributeSetClick: (formObject: FormObjectModel) =>\n dispatch(cancelRepeatableAttributeSet(ownProps.form, formObject)),\n onRemoveAttributeSetClick: (formObject: FormObjectModel) =>\n dispatch(removeRepeatableAttributeSet(ownProps.form, formObject)),\n});\n\n/**\n */\nexport const connectFormAttributeSet: ComponentType<any> = connect<\n Props,\n OwnProps,\n _,\n DispatchProps,\n _,\n _,\n>(null, mapDispatchToProps);\n"],"mappings":";;;;;;AACA,IAAAA,WAAA,GAAAC,OAAA;AAEA,IAAAC,iBAAA,GAAAD,OAAA;AACA,IAAAE,2BAAA,GAAAF,OAAA;AAyCA,MAAMG,kBAAkB,GAAGA,CACzBC,QAAkB,EAClBC,QAAkB,MACC;EACnBC,iBAAiB,EAAE,SAAAA,CACjBC,SAAwB,EACxBC,KAAa;IAAA,IACbC,OAA0B,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG;MAC3BG,UAAU,EAAER,QAAQ,CAACQ,UAAU,IAAI,KAAK;MACxCC,QAAQ,EAAET,QAAQ,CAACS,QAAQ,IAAI,KAAK;MACpCC,UAAU,EAAEV,QAAQ,CAACU,UAAU,IAAI;IACrC,CAAC;IAAA,OAEDX,QAAQ,CACN,IAAAY,qCAAmB,EACjBX,QAAQ,CAACY,IAAI,EACbZ,QAAQ,CAACa,MAAM,EACfX,SAAS,EACTC,KAAK,EACLC,OACF,CACF,CAAC;EAAA;EACHU,sBAAsB,EAAEA,CAAA,KACtBf,QAAQ,CAAC,IAAAgB,qDAAyB,EAACf,QAAQ,CAACY,IAAI,CAAC,CAAC;EACpDI,yBAAyB,EAAGC,UAA2B,IACrDlB,QAAQ,CAAC,IAAAmB,wDAA4B,EAAClB,QAAQ,CAACY,IAAI,EAAEK,UAAU,CAAC,CAAC;EACnEE,yBAAyB,EAAGF,UAA2B,IACrDlB,QAAQ,CAAC,IAAAqB,wDAA4B,EAACpB,QAAQ,CAACY,IAAI,EAAEK,UAAU,CAAC;AACpE,CAAC,CAAC;;AAEF;AACA;AACO,MAAMI,uBAA2C,GAAAC,OAAA,CAAAD,uBAAA,GAAG,IAAAE,mBAAO,EAOhE,IAAI,EAAEzB,kBAAkB,CAAC","ignoreList":[]}
@@ -46,6 +46,7 @@ export type PreferenceValue =
46
46
  export type UpdateFormOptions = {
47
47
  autosubmit: boolean,
48
48
  autosave: boolean,
49
+ autoupdate: boolean,
49
50
  forceUpdate?: boolean,
50
51
  /** Default true: Activate/deactivate the form object validate by an update */
51
52
  validate?: boolean,
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../src/redux/types.js"],"sourcesContent":["// @flow\nimport type { Store, DispatchAPI } from \"redux\";\n\nimport type ErrorResponse from \"../models/error/ErrorResponse\";\n\nimport type FormModel from \"../models/form/FormModel\";\nimport typeof {\n NOTIFICATION_TYPES,\n AUTOSAVE_STATUS,\n} from \"../constants/Constants\";\n\nimport type { MessageObject } from \"../i18n/types\";\nimport type {\n I18nState,\n UpdateLocaleAction,\n SetLocalesAction,\n} from \"./_i18n/types\";\nimport type {\n ModularUIState,\n ModularUIAction,\n UpdateStatusAction,\n SetModelAction,\n UpdateModelAction,\n UpdateFormAction,\n RemoveModelByKeyAction,\n ResetModularUIAction,\n InitModelAction,\n} from \"./_modularui/types\";\nimport type {\n RouterState,\n LocationChangeAction,\n PushAction,\n ReplaceAction,\n GoAction,\n GoBackAction,\n GoForwardAction,\n} from \"./_router/types\";\n\nexport type PreferenceValue =\n | null\n | string\n | boolean\n | { [key: string]: any }\n | Array<PreferenceValue>;\n\nexport type UpdateFormOptions = {\n autosubmit: boolean,\n autosave: boolean,\n forceUpdate?: boolean,\n /** Default true: Activate/deactivate the form object validate by an update */\n validate?: boolean,\n};\n\nexport type NoAction = {\n type: \"NO_ACTION\",\n};\n\nexport type SaveErrorAction = {\n type: \"SAVE_ERROR\",\n payload: ErrorResponse,\n};\n\nexport type ShowModalAction = {\n type: \"SHOW_MODAL\",\n payload: string,\n};\n\nexport type CloseModalAction = {\n type: \"CLOSE_MODAL\",\n payload: string,\n};\n\nexport type DismissNotificationAction = {\n type: \"DISMISS_NOTIFICATION\",\n};\nexport type ShowNotificationAction = {\n type: \"SHOW_NOTIFICATION\",\n payload: {\n type: $Keys<NOTIFICATION_TYPES>,\n message: MessageObject,\n error: ?ErrorResponse,\n },\n};\n\nexport type SetPreferenceAction = {\n type: \"SET_PREFERENCE\",\n payload: { [name: string]: PreferenceValue },\n};\nexport type SetPreferencesAction = {\n type: \"SET_PREFERENCES\",\n payload: { [name: string]: PreferenceValue },\n};\n\nexport type StartProgressAction = {\n type: \"START_PROGRESS\",\n};\nexport type FinishProgressAction = {\n type: \"FINISH_PROGRESS\",\n};\nexport type ResetProgressAction = {\n type: \"RESET_PROGRESS\",\n};\nexport type UpdateProgressAction = {\n type: \"UPDATE_PROGRESS\",\n payload: { percentComplete: number },\n};\n\nexport type SendAuthenticationErrorAction = {\n type: \"AUTHENTICATION_ERROR\",\n payload: string,\n};\n\nexport type ResetAuthErrorsAction = {\n type: \"AUTHENTICATION_RESET_ERRORS\",\n};\n\nexport type LoginSuccessAction = {\n type: \"AUTHENTICATION_SUCCESS\",\n};\n\nexport type ChangePasswordAction = {\n type: \"CHANGE_PASSWORD\",\n};\n\nexport type LogoutSuccessAction = {\n type: \"AUTHENTICATION_LOGOUT\",\n};\n\nexport type UpdateAutosaveAction = {\n type: \"UPDATE_AUTOSAVE_STATUS\",\n payload: {\n status: $Keys<AUTOSAVE_STATUS>,\n model: FormModel,\n },\n};\n\nexport type ReduxAction =\n | UpdateStatusAction\n | SetModelAction\n | InitModelAction\n | UpdateModelAction\n | UpdateFormAction\n | RemoveModelByKeyAction\n | ResetModularUIAction\n | SaveErrorAction\n | UpdateLocaleAction\n | SetLocalesAction\n | ShowModalAction\n | CloseModalAction\n | DismissNotificationAction\n | ShowNotificationAction\n | SetPreferenceAction\n | SetPreferencesAction\n | StartProgressAction\n | FinishProgressAction\n | ResetProgressAction\n | UpdateProgressAction\n | ResetAuthErrorsAction\n | SendAuthenticationErrorAction\n | LoginSuccessAction\n | ChangePasswordAction\n | LogoutSuccessAction\n | UpdateAutosaveAction\n | LocationChangeAction\n | PushAction\n | ReplaceAction\n | GoAction\n | GoBackAction\n | GoForwardAction\n | ModularUIAction\n | NoAction;\n\n// Redux state\nexport type AuthState = {\n +mustChangePassword: boolean,\n +error: ?string,\n};\n\nexport type ErrorState = null | ErrorResponse;\n\nexport type ModalState = {\n +key: string,\n +visible: boolean,\n +size?: string,\n};\n\nexport type ModalsState = {\n +modals: Array<ModalState>,\n};\n\nexport type NotificationState = {\n +render: boolean,\n +messageType: string | null,\n +message: MessageObject | null,\n +error: ?ErrorResponse | null,\n};\n\nexport type PreferencesState = {\n +[name: string]: PreferenceValue,\n};\n\nexport type ProgressIndicatorState = {\n +count: number,\n +timestamp: number,\n +percentComplete: number,\n};\n\nexport type ReduxState = {\n +router: RouterState,\n +modularui: ModularUIState,\n +i18n: I18nState,\n +auth: AuthState,\n +error: ErrorState,\n +modals: ModalsState,\n +notification: NotificationState,\n +progressindicator: ProgressIndicatorState,\n +preferences: PreferencesState,\n ...\n};\n\nexport type GetState = () => ReduxState;\nexport type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;\nexport type PromiseAction = Promise<PossibleAction>;\nexport type Dispatch = DispatchAPI<PossibleAction>;\nexport type ReduxStore = Store<ReduxState, ReduxAction, Dispatch>;\n\nexport type PossibleAction = ReduxAction | ThunkAction | PromiseAction;\n\nexport type CustomReducers = { [reducerKey: string]: any };\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/redux/types.js"],"sourcesContent":["// @flow\nimport type { Store, DispatchAPI } from \"redux\";\n\nimport type ErrorResponse from \"../models/error/ErrorResponse\";\n\nimport type FormModel from \"../models/form/FormModel\";\nimport typeof {\n NOTIFICATION_TYPES,\n AUTOSAVE_STATUS,\n} from \"../constants/Constants\";\n\nimport type { MessageObject } from \"../i18n/types\";\nimport type {\n I18nState,\n UpdateLocaleAction,\n SetLocalesAction,\n} from \"./_i18n/types\";\nimport type {\n ModularUIState,\n ModularUIAction,\n UpdateStatusAction,\n SetModelAction,\n UpdateModelAction,\n UpdateFormAction,\n RemoveModelByKeyAction,\n ResetModularUIAction,\n InitModelAction,\n} from \"./_modularui/types\";\nimport type {\n RouterState,\n LocationChangeAction,\n PushAction,\n ReplaceAction,\n GoAction,\n GoBackAction,\n GoForwardAction,\n} from \"./_router/types\";\n\nexport type PreferenceValue =\n | null\n | string\n | boolean\n | { [key: string]: any }\n | Array<PreferenceValue>;\n\nexport type UpdateFormOptions = {\n autosubmit: boolean,\n autosave: boolean,\n autoupdate: boolean,\n forceUpdate?: boolean,\n /** Default true: Activate/deactivate the form object validate by an update */\n validate?: boolean,\n};\n\nexport type NoAction = {\n type: \"NO_ACTION\",\n};\n\nexport type SaveErrorAction = {\n type: \"SAVE_ERROR\",\n payload: ErrorResponse,\n};\n\nexport type ShowModalAction = {\n type: \"SHOW_MODAL\",\n payload: string,\n};\n\nexport type CloseModalAction = {\n type: \"CLOSE_MODAL\",\n payload: string,\n};\n\nexport type DismissNotificationAction = {\n type: \"DISMISS_NOTIFICATION\",\n};\nexport type ShowNotificationAction = {\n type: \"SHOW_NOTIFICATION\",\n payload: {\n type: $Keys<NOTIFICATION_TYPES>,\n message: MessageObject,\n error: ?ErrorResponse,\n },\n};\n\nexport type SetPreferenceAction = {\n type: \"SET_PREFERENCE\",\n payload: { [name: string]: PreferenceValue },\n};\nexport type SetPreferencesAction = {\n type: \"SET_PREFERENCES\",\n payload: { [name: string]: PreferenceValue },\n};\n\nexport type StartProgressAction = {\n type: \"START_PROGRESS\",\n};\nexport type FinishProgressAction = {\n type: \"FINISH_PROGRESS\",\n};\nexport type ResetProgressAction = {\n type: \"RESET_PROGRESS\",\n};\nexport type UpdateProgressAction = {\n type: \"UPDATE_PROGRESS\",\n payload: { percentComplete: number },\n};\n\nexport type SendAuthenticationErrorAction = {\n type: \"AUTHENTICATION_ERROR\",\n payload: string,\n};\n\nexport type ResetAuthErrorsAction = {\n type: \"AUTHENTICATION_RESET_ERRORS\",\n};\n\nexport type LoginSuccessAction = {\n type: \"AUTHENTICATION_SUCCESS\",\n};\n\nexport type ChangePasswordAction = {\n type: \"CHANGE_PASSWORD\",\n};\n\nexport type LogoutSuccessAction = {\n type: \"AUTHENTICATION_LOGOUT\",\n};\n\nexport type UpdateAutosaveAction = {\n type: \"UPDATE_AUTOSAVE_STATUS\",\n payload: {\n status: $Keys<AUTOSAVE_STATUS>,\n model: FormModel,\n },\n};\n\nexport type ReduxAction =\n | UpdateStatusAction\n | SetModelAction\n | InitModelAction\n | UpdateModelAction\n | UpdateFormAction\n | RemoveModelByKeyAction\n | ResetModularUIAction\n | SaveErrorAction\n | UpdateLocaleAction\n | SetLocalesAction\n | ShowModalAction\n | CloseModalAction\n | DismissNotificationAction\n | ShowNotificationAction\n | SetPreferenceAction\n | SetPreferencesAction\n | StartProgressAction\n | FinishProgressAction\n | ResetProgressAction\n | UpdateProgressAction\n | ResetAuthErrorsAction\n | SendAuthenticationErrorAction\n | LoginSuccessAction\n | ChangePasswordAction\n | LogoutSuccessAction\n | UpdateAutosaveAction\n | LocationChangeAction\n | PushAction\n | ReplaceAction\n | GoAction\n | GoBackAction\n | GoForwardAction\n | ModularUIAction\n | NoAction;\n\n// Redux state\nexport type AuthState = {\n +mustChangePassword: boolean,\n +error: ?string,\n};\n\nexport type ErrorState = null | ErrorResponse;\n\nexport type ModalState = {\n +key: string,\n +visible: boolean,\n +size?: string,\n};\n\nexport type ModalsState = {\n +modals: Array<ModalState>,\n};\n\nexport type NotificationState = {\n +render: boolean,\n +messageType: string | null,\n +message: MessageObject | null,\n +error: ?ErrorResponse | null,\n};\n\nexport type PreferencesState = {\n +[name: string]: PreferenceValue,\n};\n\nexport type ProgressIndicatorState = {\n +count: number,\n +timestamp: number,\n +percentComplete: number,\n};\n\nexport type ReduxState = {\n +router: RouterState,\n +modularui: ModularUIState,\n +i18n: I18nState,\n +auth: AuthState,\n +error: ErrorState,\n +modals: ModalsState,\n +notification: NotificationState,\n +progressindicator: ProgressIndicatorState,\n +preferences: PreferencesState,\n ...\n};\n\nexport type GetState = () => ReduxState;\nexport type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;\nexport type PromiseAction = Promise<PossibleAction>;\nexport type Dispatch = DispatchAPI<PossibleAction>;\nexport type ReduxStore = Store<ReduxState, ReduxAction, Dispatch>;\n\nexport type PossibleAction = ReduxAction | ThunkAction | PromiseAction;\n\nexport type CustomReducers = { [reducerKey: string]: any };\n"],"mappings":"","ignoreList":[]}
@@ -31,11 +31,12 @@ export type RequestBaseOptions = {
31
31
 
32
32
  export type RequestOptions = { ...RequestURLOptions, ...RequestBaseOptions };
33
33
 
34
+ export type UpdateHandler = (newModel: ModularUIModel) => ModularUIModel;
34
35
  export type RequestModularUIOptions = {
35
36
  ...RequestBaseOptions,
36
37
  targetModel?: TargetModel,
37
38
  forceTargetModel?: boolean,
38
- updateModel?: ModularUIModel,
39
+ updateHandler?: UpdateHandler | void,
39
40
  childmodels?: boolean,
40
41
  isValidationRequest?: boolean,
41
42
  removeOnUnmount?: boolean,
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../../src/utils/fetch/types.js"],"sourcesContent":["// @flow\nimport typeof { HTTP_METHODS } from \"../../constants/Constants\";\nimport type { ModularUIModel } from \"../../models/types\";\nimport type { TargetModel } from \"../../modularui/types\";\n\nexport type RequestURLOptions = {\n url: string,\n};\n\nexport type RequestBaseOptions = {\n method?: $Keys<HTTP_METHODS>,\n params?: string,\n data?: any,\n timeout?: number,\n responseType?: string,\n headers?: {\n [headerName: string]: string,\n Accept?: string,\n \"Accept-Language\"?: string,\n \"Content-Type\"?: string,\n \"x-filename\"?: string,\n \"x-filesize\"?: string,\n },\n events?: { [eventName: string]: () => void },\n onProgress?: ProgressEventHandler,\n includeContext?: boolean,\n locale?: string,\n cache?: boolean,\n isReload?: boolean,\n};\n\nexport type RequestOptions = { ...RequestURLOptions, ...RequestBaseOptions };\n\nexport type RequestModularUIOptions = {\n ...RequestBaseOptions,\n targetModel?: TargetModel,\n forceTargetModel?: boolean,\n updateModel?: ModularUIModel,\n childmodels?: boolean,\n isValidationRequest?: boolean,\n removeOnUnmount?: boolean,\n};\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../../src/utils/fetch/types.js"],"sourcesContent":["// @flow\nimport typeof { HTTP_METHODS } from \"../../constants/Constants\";\nimport type { ModularUIModel } from \"../../models/types\";\nimport type { TargetModel } from \"../../modularui/types\";\n\nexport type RequestURLOptions = {\n url: string,\n};\n\nexport type RequestBaseOptions = {\n method?: $Keys<HTTP_METHODS>,\n params?: string,\n data?: any,\n timeout?: number,\n responseType?: string,\n headers?: {\n [headerName: string]: string,\n Accept?: string,\n \"Accept-Language\"?: string,\n \"Content-Type\"?: string,\n \"x-filename\"?: string,\n \"x-filesize\"?: string,\n },\n events?: { [eventName: string]: () => void },\n onProgress?: ProgressEventHandler,\n includeContext?: boolean,\n locale?: string,\n cache?: boolean,\n isReload?: boolean,\n};\n\nexport type RequestOptions = { ...RequestURLOptions, ...RequestBaseOptions };\n\nexport type UpdateHandler = (newModel: ModularUIModel) => ModularUIModel;\nexport type RequestModularUIOptions = {\n ...RequestBaseOptions,\n targetModel?: TargetModel,\n forceTargetModel?: boolean,\n updateHandler?: UpdateHandler | void,\n childmodels?: boolean,\n isValidationRequest?: boolean,\n removeOnUnmount?: boolean,\n};\n"],"mappings":"","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beinformed/ui",
3
- "version": "1.48.1",
3
+ "version": "1.49.3",
4
4
  "description": "Toolbox for be informed javascript layouts",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "bugs": "http://support.beinformed.com",
@@ -5,6 +5,10 @@ import Href from "../models/href/Href";
5
5
 
6
6
  import { getSetting, HTTP_METHODS } from "../constants";
7
7
 
8
+ import type {
9
+ RemoveModelByKeyAction,
10
+ UpdateFormAction,
11
+ } from "../redux/_modularui";
8
12
  import { loadModularUI, removeModelByKey } from "../redux/_modularui";
9
13
  import { useModularUI } from "./useModularUI";
10
14
 
@@ -20,12 +24,8 @@ import {
20
24
 
21
25
  import FormModel from "../models/form/FormModel";
22
26
 
23
- import type { FormObjectModel, AttributeType } from "../models";
27
+ import type { AttributeType, FormObjectModel, ModularUIModel } from "../models";
24
28
  import type { UpdateFormOptions } from "../redux/types";
25
- import type {
26
- RemoveModelByKeyAction,
27
- UpdateFormAction,
28
- } from "../redux/_modularui";
29
29
 
30
30
  type FormNavigationHook = {
31
31
  previous: (form: FormModel) => UpdateFormAction,
@@ -84,7 +84,14 @@ export const useFormNavigation = (): FormNavigationHook => {
84
84
  loadModularUI(form.connectKey, form.selfhref, {
85
85
  method: HTTP_METHODS.POST,
86
86
  data: form.formdata,
87
- updateModel: form,
87
+ updateHandler: (newModel: ModularUIModel): ModularUIModel => {
88
+ if (newModel instanceof FormModel) {
89
+ const clonedModel: FormModel = form.clone();
90
+ clonedModel.update(newModel);
91
+ return clonedModel;
92
+ }
93
+ return newModel;
94
+ },
88
95
  targetModel: FormModel,
89
96
  }),
90
97
  );
@@ -105,7 +112,15 @@ export const useFormNavigation = (): FormNavigationHook => {
105
112
  };
106
113
 
107
114
  /**
108
- * Update attributes of a form
115
+ * Hook that returns a function to update attributes of a form object.
116
+ * <br >
117
+ * The returned function accepts the following options:
118
+ *
119
+ * - autosubmit: Automatically submit the form after a change
120
+ * - autosav: Automatically save the form (in the background) after a change
121
+ * - autoupdate: Automatically update the current form object after a change
122
+ * - forceUpdate: Force the update even if conditions are not met.
123
+ * - validate: Activate/deactivate the form object validation by an update.
109
124
  */
110
125
  export const useAttributeUpdate = (
111
126
  form: FormModel,
@@ -744,7 +744,8 @@ export default class AttributeModel
744
744
  /**
745
745
  * Registers a missing error that was received from the server
746
746
  */
747
- addMissingError(): void {
747
+ // eslint-disable-next-line no-unused-vars
748
+ addMissingError(receivedAttribute?: AttributeType): void {
748
749
  this._errorCollection.addServerError("Constraint.Missing");
749
750
  }
750
751
 
@@ -303,11 +303,19 @@ export default class ChoiceAttributeModel extends AttributeModel {
303
303
 
304
304
  /**
305
305
  */
306
- mergeAttribute(oldAttribute: AttributeType) {
306
+ mergeAttribute(
307
+ oldAttribute: AttributeType,
308
+ addNotExistingOptions: boolean = false,
309
+ removeNotExistingOptions: boolean = false,
310
+ ) {
307
311
  // when attribute is readonly, don't merge the options no modifications necessary
308
312
  if (!this.readonly && oldAttribute instanceof ChoiceAttributeModel) {
309
313
  this.concept = oldAttribute.concept;
310
- this.options.mergeOptions(oldAttribute.options, this.type === "lookup");
314
+ this.options.mergeOptions(
315
+ oldAttribute.options,
316
+ addNotExistingOptions ?? this.type === "lookup",
317
+ removeNotExistingOptions,
318
+ );
311
319
  this.options.deselectAll();
312
320
 
313
321
  if (oldAttribute.isValid && oldAttribute.inputvalue !== null) {
@@ -354,6 +362,19 @@ export default class ChoiceAttributeModel extends AttributeModel {
354
362
  return this;
355
363
  }
356
364
 
365
+ /**
366
+ * Registers a missing error that was received from the server
367
+ */
368
+ addMissingError(receivedAttribute?: AttributeType): void {
369
+ if (this.isChangedSince(0)) {
370
+ this._errorCollection.addServerError("Constraint.Missing");
371
+ }
372
+ // update choice options
373
+ if (receivedAttribute instanceof ChoiceAttributeModel) {
374
+ this.mergeAttribute(receivedAttribute, true, true);
375
+ }
376
+ }
377
+
357
378
  /**
358
379
  */
359
380
  set hasContentConfiguration(hasContentConfiguration: boolean) {
@@ -309,15 +309,9 @@ class ChoiceAttributeOptionCollection extends ResourceCollection<ChoiceAttribute
309
309
  mergeOptions(
310
310
  withOptions: ChoiceAttributeOptionCollection,
311
311
  addNotExistingOptions: boolean = false,
312
+ removeNotExistingOptions: boolean = false,
312
313
  ) {
313
- if (addNotExistingOptions) {
314
- this.collection = [
315
- ...this.collection,
316
- ...withOptions.filter(
317
- (option) => !this.collection.some((opt) => opt.code === option.code),
318
- ),
319
- ];
320
- }
314
+ const newCollection = [];
321
315
 
322
316
  this.collection.forEach((option) => {
323
317
  const foundOption = withOptions.find(
@@ -325,8 +319,22 @@ class ChoiceAttributeOptionCollection extends ResourceCollection<ChoiceAttribute
325
319
  );
326
320
  if (foundOption) {
327
321
  option.mergeOption(foundOption);
322
+ newCollection.push(option);
323
+ } else if (!removeNotExistingOptions) {
324
+ newCollection.push(option);
328
325
  }
329
326
  });
327
+
328
+ if (addNotExistingOptions) {
329
+ this.collection = [
330
+ ...newCollection,
331
+ ...withOptions.filter(
332
+ (option) => !this.collection.some((opt) => opt.code === option.code),
333
+ ),
334
+ ];
335
+ } else {
336
+ this.collection = newCollection;
337
+ }
330
338
  }
331
339
 
332
340
  /**
@@ -15,6 +15,7 @@ import type {
15
15
  import type { ModularUIResponse } from "../../modularui";
16
16
  import type Href from "../href/Href";
17
17
  import type LinkModel from "../links/LinkModel";
18
+ import type LinkCollection from "../links/LinkCollection";
18
19
  import type ErrorResponse from "../error/ErrorResponse";
19
20
 
20
21
  /**
@@ -109,6 +110,13 @@ export default class ConceptDetailModel extends ResourceModel {
109
110
  return href;
110
111
  }
111
112
 
113
+ /**
114
+ * Available diagrams for the concept, most of the time just one
115
+ */
116
+ get diagramLinks(): LinkCollection {
117
+ return this.links.getLinksByGroup("diagram");
118
+ }
119
+
112
120
  /**
113
121
  * Get conceptType of concept
114
122
  */
@@ -1013,6 +1013,27 @@ class FormModel extends ResourceModel {
1013
1013
  return this;
1014
1014
  }
1015
1015
 
1016
+ /**
1017
+ * Updates the current form object with new information about the object,
1018
+ * like for example a new dynamicschema. Used for autoupdate functionality that makes it possible
1019
+ * to update the options of a next missing attribute in a form-tree iq question
1020
+ */
1021
+ updateCurrentFormObject(receivedForm: ModularUIModel) {
1022
+ if (receivedForm instanceof FormModel) {
1023
+ const receivedFormData = receivedForm.data ?? {};
1024
+ const hasMissing = has(receivedFormData, "missing");
1025
+ const hasErrors = has(receivedFormData, "errors");
1026
+
1027
+ if (hasErrors) {
1028
+ this.handleErrors(receivedForm);
1029
+ }
1030
+
1031
+ if (hasMissing) {
1032
+ this.handleMissing(receivedForm);
1033
+ }
1034
+ }
1035
+ }
1036
+
1016
1037
  /**
1017
1038
  */
1018
1039
  updateValidations(data: any): FormModel {
@@ -1125,11 +1146,10 @@ class FormModel extends ResourceModel {
1125
1146
  }
1126
1147
 
1127
1148
  this.currentFormObject.attributeCollection.map((attribute) => {
1128
- if (
1129
- receivedForm.currentFormObject &&
1130
- receivedForm.currentFormObject.hasAttributeByKey(attribute.key)
1131
- ) {
1132
- attribute.addMissingError();
1149
+ const receivedAttribute =
1150
+ receivedForm.currentFormObject?.getAttributeByKey(attribute.key);
1151
+ if (receivedAttribute) {
1152
+ attribute.addMissingError(receivedAttribute);
1133
1153
  } else {
1134
1154
  attribute.removeMissingError();
1135
1155
  }
@@ -218,7 +218,15 @@ export default class FormObjectModel extends BaseModel {
218
218
  }
219
219
 
220
220
  /**
221
- * Indicates if object is dynamic. A dynamic object should be submitted on each attribute change
221
+ * Indicates if object is dynamic.
222
+ *
223
+ * A subtle difference exists between objects for wizard style instrument dialogs and other objects.
224
+ * In the 'missing object' response, wizard style objects will include only the first attribute(s) to be answered,
225
+ * while other objects will include the complete set of attributes of that object.
226
+ *
227
+ * This difference is condensed in the term of 'dynamic objects': these objects start (in the 'missing object' response)
228
+ * with a very select set of attributes to be answered, and each successive 'missing elements' response will include next attributes to be answered.
229
+ * When an object is dynamic, the form contributions will mention a "dynamicObject": true property.
222
230
  */
223
231
  get isDynamic(): boolean {
224
232
  return this.getContribution("dynamicObject", false);
@@ -156,7 +156,7 @@ class ModularUIRequest {
156
156
  const {
157
157
  targetModel,
158
158
  forceTargetModel,
159
- updateModel,
159
+ updateHandler,
160
160
  childmodels,
161
161
  isValidationRequest,
162
162
  removeOnUnmount,
@@ -17,7 +17,10 @@ import type {
17
17
  ResetModularUIAction,
18
18
  UpdateStatusAction,
19
19
  } from "./types";
20
- import type { RequestModularUIOptions } from "../../utils/fetch/types";
20
+ import type {
21
+ RequestModularUIOptions,
22
+ UpdateHandler,
23
+ } from "../../utils/fetch/types";
21
24
 
22
25
  /**
23
26
  */
@@ -88,22 +91,11 @@ export const updateStatus = (
88
91
  const loadModelSuccessAction = (
89
92
  key: string,
90
93
  model: ModularUIModel,
91
- modelToUpdate: ?ModularUIModel,
94
+ updateHandler: UpdateHandler | void,
92
95
  ): UpdateModelAction | SetModelAction => {
93
- if (modelToUpdate) {
94
- // $FlowFixMe[prop-missing]
95
- if (typeof modelToUpdate["update"] === "function") {
96
- const clonedModel = modelToUpdate.clone();
97
- clonedModel.update(model);
98
-
99
- return updateModel(clonedModel);
100
- }
101
-
102
- throw new Error(
103
- `loadModel action: updateModel is set as option for ${key}, but the model is missing an update methode`,
104
- );
96
+ if (updateHandler) {
97
+ return updateModel(updateHandler(model));
105
98
  }
106
-
107
99
  return setModel(key, model);
108
100
  };
109
101
 
@@ -127,7 +119,7 @@ export const loadModel = (
127
119
  /**
128
120
  */
129
121
  successAction: (model) =>
130
- loadModelSuccessAction(key, model, options?.updateModel),
122
+ loadModelSuccessAction(key, model, options?.updateHandler),
131
123
  /**
132
124
  */
133
125
  errorAction: (error) => {
@@ -6,6 +6,7 @@ import { getSetting } from "../../constants/Settings";
6
6
  import { validateFormObject } from "./FormValidations";
7
7
  import { autosaveFormObject } from "./FormAutosave";
8
8
  import { autosubmitFormObject } from "./FormAutosubmit";
9
+ import { autoupdateFormObject } from "./FormAutoupdate";
9
10
 
10
11
  import type { Dispatch, ThunkAction, UpdateFormOptions } from "../types";
11
12
  import type { AttributeType } from "../../models/types";
@@ -23,7 +24,8 @@ export const updateFormAttribute =
23
24
  inputvalue: string,
24
25
  options: UpdateFormOptions = {
25
26
  autosubmit: false,
26
- autosave: false,
27
+ autosave: false, // autosave commits the form in the background
28
+ autoupdate: false, // autoupdate does not commit and updates the form with for example a new dynamicschema (work-around for form-tree iq)
27
29
  forceUpdate: false,
28
30
  validate: true,
29
31
  },
@@ -56,18 +58,41 @@ export const updateFormAttribute =
56
58
  }
57
59
  }
58
60
 
59
- if (options.autosave && newForm.isValid && newForm.isChanged()) {
60
- dispatch(autosaveFormObject(newForm));
61
+ if (options.autoupdate && newForm.isValid) {
62
+ const autoupdateAction = autoupdateFormObject(newForm, attribute);
63
+ if (autoupdateAction) {
64
+ return dispatch(autoupdateAction);
65
+ }
61
66
  }
62
67
 
63
- if (
64
- options.validate &&
65
- newForm.currentFormObject?.hasDynamicValidations &&
66
- getSetting("USE_INSTANT_SERVER_VALIDATION")
67
- ) {
68
- // server form validations happens async, don't wait for the form to return
69
- dispatch(validateFormObject(newForm));
70
- }
68
+ handleAutoSave(dispatch, newForm, options);
69
+
70
+ handleValidate(dispatch, newForm, options);
71
71
 
72
72
  return dispatch(updateForm(newForm));
73
73
  };
74
+
75
+ const handleAutoSave = (
76
+ dispatch: Dispatch,
77
+ newForm: FormModel,
78
+ options: UpdateFormOptions,
79
+ ) => {
80
+ if (options.autosave && newForm.isValid && newForm.isChanged()) {
81
+ dispatch(autosaveFormObject(newForm));
82
+ }
83
+ };
84
+
85
+ const handleValidate = (
86
+ dispatch: Dispatch,
87
+ newForm: FormModel,
88
+ options: UpdateFormOptions,
89
+ ) => {
90
+ if (
91
+ options.validate &&
92
+ newForm.currentFormObject?.hasDynamicValidations &&
93
+ getSetting("USE_INSTANT_SERVER_VALIDATION")
94
+ ) {
95
+ // server form validations happens async, don't wait for the form to return
96
+ dispatch(validateFormObject(newForm));
97
+ }
98
+ };
@@ -1,9 +1,9 @@
1
1
  // @flow
2
2
  import { loadModularUI } from "../_modularui/ModularUIActions";
3
3
  import { HTTP_METHODS } from "../../constants/Constants";
4
+ import FormModel from "../../models/form/FormModel";
4
5
 
5
- import type { AttributeType } from "../../models/types";
6
- import type FormModel from "../../models/form/FormModel";
6
+ import type { ModularUIModel, AttributeType } from "../../models/types";
7
7
  import type { ThunkAction } from "../types";
8
8
 
9
9
  /**
@@ -28,7 +28,14 @@ export const autosubmitFormObject = (
28
28
  return loadModularUI(form.connectKey, form.selfhref, {
29
29
  method: HTTP_METHODS.POST,
30
30
  data: form.formdata,
31
- updateModel: form,
31
+ updateHandler: (newModel: ModularUIModel): ModularUIModel => {
32
+ if (newModel instanceof FormModel) {
33
+ const clonedModel: FormModel = form.clone();
34
+ clonedModel.update(newModel);
35
+ return clonedModel;
36
+ }
37
+ return newModel;
38
+ },
32
39
  });
33
40
  }
34
41
 
@@ -0,0 +1,43 @@
1
+ // @flow
2
+ import { loadModularUI } from "../_modularui/ModularUIActions";
3
+ import { HTTP_METHODS } from "../../constants/Constants";
4
+
5
+ import FormModel from "../../models/form/FormModel";
6
+
7
+ import type { AttributeType, ModularUIModel } from "../../models/types";
8
+ import type { ThunkAction } from "../types";
9
+
10
+ /**
11
+ */
12
+ export const autoupdateFormObject = (
13
+ form: FormModel,
14
+ attribute: AttributeType,
15
+ ): ?ThunkAction => {
16
+ // As long as we have form objects,
17
+ // and the current attribute is not found in the current form object, go back.
18
+ // When a form has a result, the current form object is null
19
+ while (
20
+ form.allObjects.length > 0 &&
21
+ (!form.currentFormObject ||
22
+ !form.currentFormObject.hasAttributeByKey(attribute.key))
23
+ ) {
24
+ form.setPreviousObject();
25
+ }
26
+
27
+ if (form.isChanged()) {
28
+ return loadModularUI(form.connectKey, form.selfhref, {
29
+ method: HTTP_METHODS.POST,
30
+ data: form.formdata,
31
+ updateHandler: (newModel: ModularUIModel): ModularUIModel => {
32
+ if (newModel instanceof FormModel) {
33
+ const clonedModel: FormModel = form.clone();
34
+ clonedModel.updateCurrentFormObject(newModel);
35
+ return clonedModel;
36
+ }
37
+ return newModel;
38
+ },
39
+ });
40
+ }
41
+
42
+ return null;
43
+ };
@@ -24,6 +24,7 @@ type OwnProps = {
24
24
  formLayout?: "vertical" | "horizontal" | "compact",
25
25
  autosubmit?: boolean,
26
26
  autosave?: boolean,
27
+ autoupdate?: boolean,
27
28
  };
28
29
 
29
30
  type DispatchProps = {
@@ -50,8 +51,9 @@ const mapDispatchToProps = (
50
51
  attribute: AttributeType,
51
52
  value: string,
52
53
  options: UpdateFormOptions = {
53
- autosubmit: ownProps.autosubmit || false,
54
- autosave: ownProps.autosave || false,
54
+ autosubmit: ownProps.autosubmit ?? false,
55
+ autosave: ownProps.autosave ?? false,
56
+ autoupdate: ownProps.autoupdate ?? false,
55
57
  },
56
58
  ) =>
57
59
  dispatch(
@@ -46,6 +46,7 @@ export type PreferenceValue =
46
46
  export type UpdateFormOptions = {
47
47
  autosubmit: boolean,
48
48
  autosave: boolean,
49
+ autoupdate: boolean,
49
50
  forceUpdate?: boolean,
50
51
  /** Default true: Activate/deactivate the form object validate by an update */
51
52
  validate?: boolean,