@solidstarters/solid-core-ui 1.1.22 → 1.1.24

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 (92) hide show
  1. package/dist/components/common/SolidBreadcrumb.d.ts +2 -10
  2. package/dist/components/common/SolidBreadcrumb.d.ts.map +1 -1
  3. package/dist/components/common/SolidBreadcrumb.js +28 -8
  4. package/dist/components/common/SolidBreadcrumb.js.map +1 -1
  5. package/dist/components/core/common/SolidGlobalSearchElement.d.ts.map +1 -1
  6. package/dist/components/core/common/SolidGlobalSearchElement.js +1 -0
  7. package/dist/components/core/common/SolidGlobalSearchElement.js.map +1 -1
  8. package/dist/components/core/common/SolidViewLayoutManager.d.ts +13 -0
  9. package/dist/components/core/common/SolidViewLayoutManager.d.ts.map +1 -0
  10. package/dist/components/core/common/SolidViewLayoutManager.js +90 -0
  11. package/dist/components/core/common/SolidViewLayoutManager.js.map +1 -0
  12. package/dist/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.d.ts.map +1 -1
  13. package/dist/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.js +6 -4
  14. package/dist/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.js.map +1 -1
  15. package/dist/components/core/extension/solid-core/moduleMetadata/list/GenerateModuleCodeRowAction.d.ts.map +1 -1
  16. package/dist/components/core/extension/solid-core/moduleMetadata/list/GenerateModuleCodeRowAction.js +5 -3
  17. package/dist/components/core/extension/solid-core/moduleMetadata/list/GenerateModuleCodeRowAction.js.map +1 -1
  18. package/dist/components/core/form/SolidFormLayouts.d.ts.map +1 -1
  19. package/dist/components/core/form/SolidFormLayouts.js +6 -2
  20. package/dist/components/core/form/SolidFormLayouts.js.map +1 -1
  21. package/dist/components/core/form/SolidFormView.d.ts.map +1 -1
  22. package/dist/components/core/form/SolidFormView.js +134 -48
  23. package/dist/components/core/form/SolidFormView.js.map +1 -1
  24. package/dist/components/core/form/fields/ISolidField.d.ts +2 -1
  25. package/dist/components/core/form/fields/ISolidField.d.ts.map +1 -1
  26. package/dist/components/core/form/fields/SolidSelectionStaticField.d.ts.map +1 -1
  27. package/dist/components/core/form/fields/SolidSelectionStaticField.js +4 -2
  28. package/dist/components/core/form/fields/SolidSelectionStaticField.js.map +1 -1
  29. package/dist/components/core/form/fields/SolidShortTextField.d.ts.map +1 -1
  30. package/dist/components/core/form/fields/SolidShortTextField.js +19 -13
  31. package/dist/components/core/form/fields/SolidShortTextField.js.map +1 -1
  32. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js +2 -2
  33. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js.map +1 -1
  34. package/dist/components/core/form/widgets/CustomHtml.d.ts +3 -0
  35. package/dist/components/core/form/widgets/CustomHtml.d.ts.map +1 -0
  36. package/dist/components/core/form/widgets/CustomHtml.js +15 -0
  37. package/dist/components/core/form/widgets/CustomHtml.js.map +1 -0
  38. package/dist/components/core/list/SolidListView.js +1 -1
  39. package/dist/components/core/model/CreateModel.d.ts.map +1 -1
  40. package/dist/components/core/model/CreateModel.js +3 -7
  41. package/dist/components/core/model/CreateModel.js.map +1 -1
  42. package/dist/components/core/model/FieldMetaData.d.ts +1 -1
  43. package/dist/components/core/model/FieldMetaData.d.ts.map +1 -1
  44. package/dist/components/core/model/FieldMetaData.js +7 -3
  45. package/dist/components/core/model/FieldMetaData.js.map +1 -1
  46. package/dist/components/core/model/FieldMetaDataForm.d.ts +1 -1
  47. package/dist/components/core/model/FieldMetaDataForm.d.ts.map +1 -1
  48. package/dist/components/core/model/FieldMetaDataForm.js +23 -15
  49. package/dist/components/core/model/FieldMetaDataForm.js.map +1 -1
  50. package/dist/components/core/model/ModelMetaData.js +5 -5
  51. package/dist/components/core/model/ModelMetaData.js.map +1 -1
  52. package/dist/components/core/module/CreateModule.d.ts.map +1 -1
  53. package/dist/components/core/module/CreateModule.js +1 -5
  54. package/dist/components/core/module/CreateModule.js.map +1 -1
  55. package/dist/components/core/users/CreateUser.d.ts.map +1 -1
  56. package/dist/components/core/users/CreateUser.js +1 -5
  57. package/dist/components/core/users/CreateUser.js.map +1 -1
  58. package/dist/components/layout/AppSidebar.d.ts.map +1 -1
  59. package/dist/components/layout/AppSidebar.js +2 -14
  60. package/dist/components/layout/AppSidebar.js.map +1 -1
  61. package/dist/helpers/registry.d.ts.map +1 -1
  62. package/dist/helpers/registry.js +9 -3
  63. package/dist/helpers/registry.js.map +1 -1
  64. package/dist/index.d.ts +2 -1
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +1 -0
  67. package/dist/index.js.map +1 -1
  68. package/package.json +3 -1
  69. package/src/components/common/SolidBreadcrumb.tsx +38 -14
  70. package/src/components/core/common/SolidGlobalSearchElement.tsx +2 -0
  71. package/src/components/core/common/SolidViewLayoutManager.ts +85 -0
  72. package/src/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.tsx +11 -1
  73. package/src/components/core/extension/solid-core/moduleMetadata/list/GenerateModuleCodeRowAction.tsx +16 -7
  74. package/src/components/core/form/SolidFormLayouts.tsx +6 -3
  75. package/src/components/core/form/SolidFormView.tsx +184 -65
  76. package/src/components/core/form/fields/ISolidField.tsx +2 -1
  77. package/src/components/core/form/fields/SolidSelectionStaticField.tsx +3 -1
  78. package/src/components/core/form/fields/SolidShortTextField.tsx +49 -23
  79. package/src/components/core/form/fields/relations/SolidRelationManyToOneField.tsx +6 -6
  80. package/src/components/core/form/widgets/CustomHtml.tsx +19 -0
  81. package/src/components/core/list/SolidListView.tsx +1 -1
  82. package/src/components/core/model/CreateModel.tsx +4 -8
  83. package/src/components/core/model/FieldMetaData.tsx +7 -3
  84. package/src/components/core/model/FieldMetaDataForm.tsx +343 -339
  85. package/src/components/core/model/ModelMetaData.tsx +5 -5
  86. package/src/components/core/module/CreateModule.tsx +1 -6
  87. package/src/components/core/users/CreateUser.tsx +1 -6
  88. package/src/components/layout/AppSidebar.tsx +2 -20
  89. package/src/helpers/registry.ts +16 -4
  90. package/src/index.ts +16 -1
  91. package/src/types/index.d.ts +24 -2
  92. package/src/types/solid-core.d.ts +12 -3
@@ -37,6 +37,7 @@ import { OverlayPanel } from "primereact/overlaypanel";
37
37
  import { SolidBreadcrumb } from "@/components/common/SolidBreadcrumb";
38
38
  import { SolidUiEvent } from "@/types";
39
39
  import { getExtensionComponent, getExtensionFunction } from "@/helpers/registry";
40
+ import { SolidFormWidgetProps } from "@/types/solid-core";
40
41
 
41
42
  export type SolidFormViewProps = {
42
43
  moduleName: string;
@@ -89,7 +90,7 @@ const fieldFactory = (type: string, fieldContext: SolidFieldProps): ISolidField
89
90
  if (type === 'longText') {
90
91
  return new SolidLongTextField(fieldContext);
91
92
  }
92
- if (type === 'int') {
93
+ if (type === 'int' || type === 'bigint' ) {
93
94
  return new SolidIntegerField(fieldContext);
94
95
  }
95
96
  if (type === 'decimal' || type === 'float') {
@@ -132,7 +133,7 @@ const fieldFactory = (type: string, fieldContext: SolidFieldProps): ISolidField
132
133
  }
133
134
 
134
135
  // solidFieldsMetadata={solidFieldsMetadata} solidView={solidView}
135
- const SolidField = ({ formik, field, fieldMetadata, initialEntityData, solidFormViewMetaData, modelName, readOnly, changeHandler }: any) => {
136
+ const SolidField = ({ formik, field, fieldMetadata, initialEntityData, solidFormViewMetaData, modelName, readOnly, onChange, onBlur }: any) => {
136
137
  const fieldContext: SolidFieldProps = {
137
138
  // field metadata - coming from the field-metadata table.
138
139
  fieldMetadata: fieldMetadata,
@@ -144,7 +145,8 @@ const SolidField = ({ formik, field, fieldMetadata, initialEntityData, solidForm
144
145
  solidFormViewMetaData: solidFormViewMetaData,
145
146
  modelName: modelName,
146
147
  readOnly: readOnly,
147
- changeHandler: changeHandler
148
+ onChange: onChange,
149
+ onBlur: onBlur
148
150
  }
149
151
  const solidField = fieldFactory(fieldMetadata?.type, fieldContext);
150
152
 
@@ -225,6 +227,7 @@ const SolidSheet = ({ children }: any) => (
225
227
  {children}
226
228
  </div>
227
229
  );
230
+
228
231
  const SolidNotebook = ({ children }: any) => {
229
232
 
230
233
  return (
@@ -236,6 +239,26 @@ const SolidNotebook = ({ children }: any) => {
236
239
  )
237
240
  };
238
241
 
242
+ const SolidDynamicWidget = ({ widgetName, formik, field, solidFormViewMetaData }: any) => {
243
+ const solidView = solidFormViewMetaData.data.solidView;
244
+ const solidFieldsMetadata = solidFormViewMetaData.data.solidFieldsMetadata;
245
+
246
+ let DynamicWidget = getExtensionComponent(widgetName);
247
+
248
+ const widgetProps: SolidFormWidgetProps = {
249
+ formData: formik.values,
250
+ field: field,
251
+ fieldsMetadata: solidFieldsMetadata,
252
+ viewMetadata: solidView
253
+ }
254
+
255
+ return (
256
+ <div className="solid-tab-view w-full">
257
+ {DynamicWidget && <DynamicWidget {...widgetProps} />}
258
+ </div>
259
+ )
260
+ };
261
+
239
262
 
240
263
  const SolidPage = ({ attrs, children, key }: any) => (
241
264
  <TabPanel key={key} header={attrs.label} >
@@ -472,9 +495,7 @@ const SolidFormView = (params: SolidFormViewProps) => {
472
495
  field: layoutFieldsObj[key],
473
496
  data: initialEntityData,
474
497
  solidFormViewMetaData: solidFormViewMetaData,
475
- modelName: params.modelName,
476
- // TODO: do we need to pass the change handler?
477
- changeHandler: null
498
+ modelName: params.modelName
478
499
  }
479
500
 
480
501
  let solidField = fieldFactory(fieldMetadata?.type, fieldContext);
@@ -598,9 +619,7 @@ const SolidFormView = (params: SolidFormViewProps) => {
598
619
  field: formLayoutField,
599
620
  data: initialEntityData,
600
621
  solidFormViewMetaData: solidFormViewMetaData,
601
- modelName: params.modelName,
602
- // TODO: do we need to pass the change handler?
603
- changeHandler: null,
622
+ modelName: params.modelName
604
623
  }
605
624
  let solidField = fieldFactory(fieldMetadata?.type, fieldContext);
606
625
  if (!fieldMetadata?.type) {
@@ -625,14 +644,20 @@ const SolidFormView = (params: SolidFormViewProps) => {
625
644
  onSubmit: onFormikSubmit,
626
645
  });
627
646
 
628
- const formChangeHandler = async (event: ChangeEvent<HTMLInputElement>) => {
647
+ const formFieldOnXXX = async (event: ChangeEvent<HTMLInputElement>, eventType: string) => {
648
+
649
+ // Invoke the formik change
650
+ if (eventType === 'onFieldChange') {
651
+ formik.handleChange(event);
652
+ }
653
+
629
654
  // get details from the form event
630
655
  const { name: fieldName, value, type, checked } = event.target;
631
- console.log(`formChangeHandler invoked for change in ${fieldName}, with updated value: ${value}`);
656
+ // console.log(`${eventType}: formFieldOnXXX ${fieldName} invoked for change with value:`, value);
632
657
 
633
658
  // TODO: check if there is a change handler registered with this form view, load it and fire it.
634
- const changeHandler = solidView.layout?.changeHandler;
635
- console.log(`changeHandler for this form is ${changeHandler}`);
659
+ const changeHandler = solidView.layout[eventType];
660
+ // console.log(`changeHandler for this form is ${changeHandler}`);
636
661
 
637
662
  if (changeHandler) {
638
663
  // Get hold of the dynamic module...
@@ -645,69 +670,170 @@ const SolidFormView = (params: SolidFormViewProps) => {
645
670
  fieldsMetadata: solidFieldsMetadata,
646
671
  formData: formik.values,
647
672
  modifiedField: fieldName,
648
- type: 'onFieldUpdate',
673
+ modifiedFieldValue: value,
674
+ // @ts-ignore
675
+ // TODO: HP & OR: This will be fixed once we figure out how to get types exported from solid-core-ui
676
+ type: eventType,
649
677
  viewMetadata: solidView
650
678
  }
679
+
680
+ // Invoke the dynamic change handler:
681
+ // TODO: encapsulate in try/catch, catch the exception render in the UI as an error & stop form rendering.
651
682
  const updatedFormInfo = dynamicChangeHandler(event);
652
- console.log(`I have triggered on change hander: `, updatedFormInfo);
683
+ // console.log(`${eventType}: formFieldOnXXX response received: `, updatedFormInfo);
684
+
685
+ // If dataChanged is true, update Formik values
686
+ if (updatedFormInfo?.dataChanged && updatedFormInfo.newFormData) {
687
+ // This does one field at a time.
688
+ // TODO: does the below fire change events again?
689
+ Object.entries(updatedFormInfo.newFormData).forEach(([key, newValue]) => {
690
+ formik.setFieldValue(key, newValue);
691
+ });
692
+
693
+ // This does all at once.
694
+ // formik.setValues({
695
+ // ...formik.values,
696
+ // ...updatedFormInfo.newFormData
697
+ // });
698
+ }
653
699
 
700
+ // if layout has changed then we need to re-render.
701
+ if (updatedFormInfo?.layoutChanged && updatedFormInfo.newLayout) {
702
+ // setFormViewMetaData({ ...formViewMetaData, layout: updatedFormInfo.newLayout });
703
+ // console.log(`Existing form view metadata is: `, formViewMetaData);
704
+
705
+ // TODO: this will trigger a useEffect dependent on formViewMetadata that invokes setFormViewLayout,
706
+ // TODO: which means that this will not work if custom layout has been injected as a prop.
707
+ setFormViewLayout(updatedFormInfo.newLayout);
708
+ setFormViewMetaData((prevMetaData: any) => {
709
+ const updatedFormViewMetadata = {
710
+ ...prevMetaData,
711
+ data: {
712
+ ...prevMetaData.data,
713
+ solidView: {
714
+ ...prevMetaData.data.solidView,
715
+ layout: updatedFormInfo.newLayout,
716
+ },
717
+ },
718
+ };
719
+ // console.log(`Updated form view metadata is: `, updatedFormViewMetadata);
720
+ return updatedFormViewMetadata;
721
+ });
722
+ }
654
723
  }
655
724
  else {
725
+ // TODO: Show an error popup and stop form rendering ideallly...
656
726
  console.log(`Unable to load dynamic module:`, changeHandler);
657
727
  }
658
-
659
728
  }
660
-
661
- // Invoke the formik change
662
- formik.handleChange(event);
663
729
  }
664
730
 
665
731
  // Now render the form dynamically...
666
732
  const renderFormElementDynamically: any = (element: any, solidFormViewMetaData: any) => {
667
- const { type, attrs, children } = element;
733
+ let { type, attrs, body, children } = element;
668
734
 
669
735
  // const key = attrs?.name ?? generateRandomKey();
670
736
  const key = attrs?.name;
737
+ let visible = attrs?.visible;
738
+ if (visible === undefined || visible === null) {
739
+ visible = true;
740
+ }
741
+ // console.log(`Resolved visibility of form element ${key} to ${visible}`);
742
+ // console.log(`Form element ${key}: `, attrs);
671
743
 
672
744
  switch (type) {
673
745
  case "form":
746
+ if (!children)
747
+ children = [];
674
748
  return <div key={key}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</div>;
749
+ case "div":
750
+ if (!children)
751
+ children = [];
752
+ return <div key={key} {...attrs}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</div>
753
+ case "span":
754
+ return <span key={key} {...attrs}>{body}</span>
755
+ case "p":
756
+ return <p key={key} {...attrs}>{body}</p>
757
+ case "h1":
758
+ return <h1 key={key} {...attrs}>{body}</h1>
759
+ case "h2":
760
+ return <h2 key={key} {...attrs}>{body}</h2>
761
+ case "ul":
762
+ if (!children)
763
+ children = [];
764
+ return <ul key={key} {...attrs}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</ul>
765
+ case "li":
766
+ return <li key={key} {...attrs}>{body}</li>
675
767
  case "sheet":
676
768
  return <SolidSheet key={key}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidSheet>;
677
769
  case "group":
678
- return <SolidGroup key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidGroup>;
770
+ if (visible === true) {
771
+ return <SolidGroup key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidGroup>;
772
+ }
679
773
  case "row":
680
- return <SolidRow key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidRow>;
774
+ if (visible === true) {
775
+ return <SolidRow key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidRow>;
776
+ }
681
777
  case "column":
682
- return <SolidColumn key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidColumn>;
778
+ if (visible === true) {
779
+ return <SolidColumn key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidColumn>;
780
+ }
683
781
  case "field": {
684
- // const fieldMetadata = solidFieldsMetadata[attrs.name];
685
- const fieldMetadata = solidFormViewMetaData.data.solidFieldsMetadata[attrs.name];
686
- // Read only permission if there is no update permission on model and router doesnt contains new
687
- const readOnlyPermission = !actionsAllowed.includes(`${updatePermission(params.modelName)}`) && params.id !== "new"
688
- return <SolidField
689
- key={key}
690
- field={element}
691
- formik={formik}
692
- fieldMetadata={fieldMetadata}
693
- initialEntityData={solidFormViewData ? solidFormViewData.data : null}
694
- solidFormViewMetaData={solidFormViewMetaData}
695
- modelName={params.modelName}
696
- readOnly={readOnlyPermission}
697
- changeHandler={formChangeHandler}
698
- />;
782
+ if (visible === true) {
783
+
784
+ // const fieldMetadata = solidFieldsMetadata[attrs.name];
785
+ const fieldMetadata = solidFormViewMetaData.data.solidFieldsMetadata[attrs.name];
786
+ // Read only permission if there is no update permission on model and router doesnt contains new
787
+ const readOnlyPermission = !actionsAllowed.includes(`${updatePermission(params.modelName)}`) && params.id !== "new"
788
+ return <SolidField
789
+ key={key}
790
+ field={element}
791
+ formik={formik}
792
+ fieldMetadata={fieldMetadata}
793
+ initialEntityData={solidFormViewData ? solidFormViewData.data : null}
794
+ solidFormViewMetaData={solidFormViewMetaData}
795
+ modelName={params.modelName}
796
+ readOnly={readOnlyPermission}
797
+ onChange={formFieldOnXXX}
798
+ onBlur={formFieldOnXXX}
799
+ />;
800
+ }
699
801
  }
700
802
  case "notebook":
701
- return <SolidNotebook key={key}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidNotebook>;
803
+ if (visible === true) {
804
+ return <SolidNotebook key={key}>{children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData))}</SolidNotebook>;
805
+ }
702
806
  case "page":
703
- const pageChildren = children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData));
704
- return SolidPage({ children: pageChildren, attrs: attrs, key: key });
807
+ // console.log(`Resolved visibility of form element ${key} to ${visible}`);
808
+ if (visible === true) {
809
+ const pageChildren = children.map((element: any) => renderFormElementDynamically(element, solidFormViewMetaData));
810
+ return SolidPage({ children: pageChildren, attrs: attrs, key: key });
811
+ }
812
+ case "custom":
813
+ if (visible === true) {
814
+ const widgetName = attrs?.widget;
815
+ const fieldMetadata = solidFormViewMetaData.data.solidFieldsMetadata[attrs.name];
816
+
817
+ if (widgetName) {
818
+ // widgetName, formik, field, fieldMetadata, solidFormViewMetaData
819
+ return <SolidDynamicWidget
820
+ key={key}
821
+ widgetName={widgetName}
822
+ field={element}
823
+ formik={formik}
824
+ fieldMetadata={fieldMetadata}
825
+ solidFormViewMetaData={solidFormViewMetaData}
826
+ />
827
+ }
828
+ }
829
+
705
830
  default:
706
831
  return null;
707
832
  }
708
833
  };
709
834
 
710
835
  const renderFormDynamically = (solidFormViewMetaData: any) => {
836
+ // console.log(`renderFormDynamically invoked....`);
711
837
  if (!solidFormViewMetaData) {
712
838
  return;
713
839
  }
@@ -794,35 +920,16 @@ const SolidFormView = (params: SolidFormViewProps) => {
794
920
  onClick={() => setDeleteDialogVisible(true)}
795
921
  />
796
922
  }
797
- {params.embeded == true &&
798
- actionsAllowed.includes(`${deletePermission(params.modelName)}`) &&
799
- !formViewLayout.attrs.readonly &&
800
- <Button
801
- text
802
- type="button"
803
- className="w-8rem text-left gap-2"
804
- label="Delete"
805
- size="small"
806
- iconPos="left"
807
- severity="danger"
808
- icon={'pi pi-trash'}
809
- onClick={() => setDeleteDialogVisible(true)}
810
- />
811
- }
812
923
  </div>
813
924
  </OverlayPanel>
814
925
  </div>
815
926
  )
816
927
  }
817
928
 
818
- const breadcrumbData = [
819
- { label: 'Book', link: '/admin/core/library-management/book/list' },
820
- { label: params.id === "new" ? `Add ${params.modelName}` : `Edit ${params.modelName}` },
821
- ];
822
-
823
- // see if we have an injected dynamic component.s
929
+ // TODO: This was simply to demonstrate how we can use dynamic components, we will remove this and use it in a more sensible way in the layout.
930
+ // TODO: to demonstrated this you can simply add the below to the layout of the book form view.
931
+ // TODO: "header": "BookFormViewDynamicComponent",
824
932
  const dynamicHeader = solidView.layout?.header;
825
- // const dynamicHeader = "BookFormViewDynamicComponent";
826
933
  let DynamicHeaderComponent = null;
827
934
  if (dynamicHeader) {
828
935
  DynamicHeaderComponent = getExtensionComponent(dynamicHeader);
@@ -844,7 +951,6 @@ const SolidFormView = (params: SolidFormViewProps) => {
844
951
  {params.embeded !== true &&
845
952
  actionsAllowed.includes(`${createPermission(params.modelName)}`) &&
846
953
  !formViewLayout.attrs.readonly &&
847
- formik.dirty &&
848
954
  <div>
849
955
  <Button
850
956
  label="Save"
@@ -943,6 +1049,19 @@ const SolidFormView = (params: SolidFormViewProps) => {
943
1049
  />
944
1050
  </div>
945
1051
  } */}
1052
+ {params.embeded == true &&
1053
+ actionsAllowed.includes(`${deletePermission(params.modelName)}`) &&
1054
+ !formViewLayout.attrs.readonly &&
1055
+ <div>
1056
+ <Button
1057
+ size="small"
1058
+ type="button"
1059
+ label="Delete"
1060
+ severity="danger"
1061
+ onClick={() => setDeleteDialogVisible(true)}
1062
+ />
1063
+ </div>
1064
+ }
946
1065
  {params.embeded == true &&
947
1066
  <Button outlined size="small" type="button" label="Close" onClick={() => params.handlePopupClose()} className='bg-primary-reverse' />
948
1067
 
@@ -955,7 +1074,7 @@ const SolidFormView = (params: SolidFormViewProps) => {
955
1074
  </>
956
1075
  )}
957
1076
  </div>
958
- <SolidBreadcrumb breadcrumbItems={breadcrumbData} />
1077
+ <SolidBreadcrumb />
959
1078
  {/* {params.embeded !== true &&
960
1079
  <div className="solid-form-stepper">
961
1080
  <SolidFormStepper />
@@ -9,7 +9,8 @@ export type SolidFieldProps = {
9
9
  data: any,
10
10
  modelName?: any,
11
11
  readOnly?: any,
12
- changeHandler: any
12
+ onChange?: any,
13
+ onBlur?: any
13
14
  };
14
15
 
15
16
  export type FormikObject = {
@@ -111,13 +111,15 @@ export class SolidSelectionStaticField implements ISolidField {
111
111
  disabled={formDisabled || fieldDisabled}
112
112
  {...formik.getFieldProps(fieldLayoutInfo.attrs.name)}
113
113
  id={fieldLayoutInfo.attrs.name}
114
+ name={fieldLayoutInfo.attrs.name}
114
115
  field="label"
115
116
  value={formik.values[fieldLayoutInfo.attrs.name] || ''}
116
117
  dropdown
117
118
  suggestions={selectionStaticItems}
118
119
  completeMethod={selectionStaticSearch}
119
120
  // onChange={(e) => updateInputs(index, e.value)} />
120
- onChange={formik.handleChange}
121
+ // onChange={formik.handleChange}
122
+ onChange={(e) => this.fieldContext.onChange(e, 'onFieldChange')}
121
123
  className="solid-standard-autocomplete"
122
124
  />
123
125
  </div>
@@ -64,6 +64,7 @@ export class SolidShortTextField implements ISolidField {
64
64
  const fieldMetadata = this.fieldContext.fieldMetadata;
65
65
  const fieldLayoutInfo = this.fieldContext.field;
66
66
  const className = fieldLayoutInfo.attrs?.className || 'field col-12';
67
+ const includeWrapper = fieldLayoutInfo.attrs?.includeWrapper || 'yes';
67
68
  const fieldLabel = fieldLayoutInfo.attrs.label ?? fieldMetadata.displayName;
68
69
  const fieldDescription = fieldLayoutInfo.attrs.description ?? fieldMetadata.description;
69
70
  const solidFormViewMetaData = this.fieldContext.solidFormViewMetaData;
@@ -79,29 +80,54 @@ export class SolidShortTextField implements ISolidField {
79
80
  const formReadonly = solidFormViewMetaData.data.solidView?.layout?.attrs?.readonly;
80
81
 
81
82
  return (
82
- <div className={className}>
83
- <div className="flex flex-column gap-2 mt-4">
84
- {showFieldLabel != false &&
85
- <label htmlFor={fieldLayoutInfo.attrs.name} className="form-field-label">{fieldLabel}
86
- {/* &nbsp; {fieldDescription && <span className="form_field_help">({fieldDescription}) </span>} */}
87
-
88
- {/* &nbsp; {fieldDescription && <span className="form_field_help_text">`(${fieldDescription})` </span>} */}
89
- </label>
90
- }
91
- <InputText
92
- readOnly={formReadonly || fieldReadonly || readOnlyPermission}
93
- disabled={formDisabled || fieldDisabled}
94
- id={fieldLayoutInfo.attrs.name}
95
- aria-describedby={`${fieldLayoutInfo.attrs.name}-help`}
96
- // onChange={formik.handleChange}
97
- onChange={this.fieldContext.changeHandler}
98
- value={formik.values[fieldLayoutInfo.attrs.name] || ''}
99
- />
100
- </div>
101
- {isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (
102
- <Message severity="error" text={formik?.errors[fieldLayoutInfo.attrs.name]?.toString()} />
103
- )}
104
- </div>
83
+ <>
84
+ {includeWrapper === 'yes' && <div className={className}>
85
+ <div className="flex flex-column gap-2 mt-4">
86
+ {showFieldLabel != false &&
87
+ <label htmlFor={fieldLayoutInfo.attrs.name} className="form-field-label">{fieldLabel}
88
+ {/* &nbsp; {fieldDescription && <span className="form_field_help">({fieldDescription}) </span>} */}
89
+ {/* &nbsp; {fieldDescription && <span className="form_field_help_text">`(${fieldDescription})` </span>} */}
90
+ </label>
91
+ }
92
+ <InputText
93
+ readOnly={formReadonly || fieldReadonly || readOnlyPermission}
94
+ disabled={formDisabled || fieldDisabled}
95
+ id={fieldLayoutInfo.attrs.name}
96
+ name={fieldMetadata.name}
97
+ aria-describedby={`${fieldLayoutInfo.attrs.name}-help`}
98
+ // onChange={formik.handleChange}
99
+ onChange={(e) => this.fieldContext.onChange(e, 'onFieldChange')}
100
+ onBlur={(e) => this.fieldContext.onBlur(e, 'onFieldBlur')}
101
+ value={formik.values[fieldLayoutInfo.attrs.name] || ''}
102
+ />
103
+ </div>
104
+ {isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (
105
+ <Message severity="error" text={formik?.errors[fieldLayoutInfo.attrs.name]?.toString()} />
106
+ )}
107
+ </div>}
108
+ {includeWrapper === 'no' &&
109
+ <>
110
+ {showFieldLabel != false &&
111
+ <label htmlFor={fieldLayoutInfo.attrs.name} className="form-field-label">{fieldLabel}
112
+ {/* &nbsp; {fieldDescription && <span className="form_field_help">({fieldDescription}) </span>} */}
113
+
114
+ {/* &nbsp; {fieldDescription && <span className="form_field_help_text">`(${fieldDescription})` </span>} */}
115
+ </label>
116
+ }
117
+ <InputText
118
+ readOnly={formReadonly || fieldReadonly || readOnlyPermission}
119
+ disabled={formDisabled || fieldDisabled}
120
+ id={fieldLayoutInfo.attrs.name}
121
+ name={fieldMetadata.name}
122
+ aria-describedby={`${fieldLayoutInfo.attrs.name}-help`}
123
+ // onChange={formik.handleChange}
124
+ onChange={(e) => this.fieldContext.onChange(e, 'onFieldChange')}
125
+ onBlur={(e) => this.fieldContext.onBlur(e, 'onFieldBlur')}
126
+ value={formik.values[fieldLayoutInfo.attrs.name] || ''}
127
+ />
128
+ </>
129
+ }
130
+ </>
105
131
  );
106
132
  }
107
133
  }
@@ -137,12 +137,12 @@ export class SolidRelationManyToOneField implements ISolidField {
137
137
  }
138
138
  return (
139
139
  <div className={className}>
140
- <div className="flex flex-column gap-2 mt-4">
141
- {showFieldLabel != false &&
142
- <label htmlFor={fieldLayoutInfo.attrs.name} className="form-field-label">
143
- {fieldLabel}
144
- </label>
145
- }
140
+ {showFieldLabel != false &&
141
+ <label htmlFor={fieldLayoutInfo.attrs.name} className="form-field-label">
142
+ {fieldLabel}
143
+ </label>
144
+ }
145
+ <div className="flex align-items-center gap-3">
146
146
  <AutoComplete
147
147
  readOnly={formReadonly || fieldReadonly || readOnlyPermission}
148
148
  disabled={formDisabled || fieldDisabled || readOnlyPermission}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+
3
+ import { SolidFormWidgetProps } from "@/types";
4
+ import parse from 'html-react-parser';
5
+ import Handlebars from "handlebars";
6
+
7
+ export const CustomHtml = ({ field, formData, viewMetadata, fieldsMetadata }: SolidFormWidgetProps) => {
8
+ let { type, attrs, body, children } = field;
9
+
10
+ // TODO: null check on this field required, show a proper error message on the UI suggesting that you are using a CustomHtml widget, however the html is not specified in the layout.
11
+ const html = attrs.html;
12
+
13
+ // TODO: run dompurify to avoid XSS attacks...
14
+
15
+ // TODO: assume the html is a handlebars template, we try to do variable replacement on it using formData.
16
+ const template = Handlebars.compile(html);
17
+
18
+ return (<div className={attrs.className}>{parse(template(formData))}</div>)
19
+ }
@@ -702,7 +702,7 @@ export const SolidListView = (params: SolidListViewParams) => {
702
702
  loadingIcon="pi pi-spinner"
703
703
  selection={[...selectedRecords, ...selectedRecoverRecords]}
704
704
  onSelectionChange={onSelectionChange}
705
- selectionMode="multiple"
705
+ selectionMode="checkbox"
706
706
  removableSort
707
707
  filterIcon={<FilterIcon />}
708
708
  tableClassName="solid-data-table"
@@ -356,11 +356,6 @@ const CreateModel = ({ data, params }: any) => {
356
356
  )
357
357
  }
358
358
 
359
- const breadcrumbData = [
360
- { label: 'Model', link: '/admin/core/solid-core/model-metadata/list' },
361
- { label: params.id === "new" ? 'Create Model' : 'Edit Model' },
362
- ];
363
-
364
359
  const [isDirty, setIsDirty] = useState(false);
365
360
 
366
361
 
@@ -396,9 +391,9 @@ const CreateModel = ({ data, params }: any) => {
396
391
  <Button label="Save" size="small" type="submit" onClick={handleSubmit} />
397
392
  }
398
393
  </div>
399
- <div>
394
+ {/* <div>
400
395
  <Button outlined label="Delete" size="small" severity="danger" type="button" onClick={() => setDeleteEntity(true)} />
401
- </div>
396
+ </div> */}
402
397
  </>
403
398
  }
404
399
  <CancelButton />
@@ -407,7 +402,7 @@ const CreateModel = ({ data, params }: any) => {
407
402
  </>
408
403
  }
409
404
  </div>
410
- <SolidBreadcrumb breadcrumbItems={breadcrumbData} />
405
+ <SolidBreadcrumb />
411
406
  {/* <div className="solid-form-stepper">
412
407
  <SolidFormStepper />
413
408
  </div> */}
@@ -450,6 +445,7 @@ const CreateModel = ({ data, params }: any) => {
450
445
  nextTab={nextTab}
451
446
  formikFieldsMetadataRef={formikFieldsMetadataRef}
452
447
  params={params}
448
+ setIsDirty={setIsDirty}
453
449
  ></FieldMetaData>
454
450
  </TabPanel>
455
451
  </TabView>
@@ -11,7 +11,7 @@ import { useRef, useState } from "react";
11
11
  import FieldMetaDataForm from "./FieldMetaDataForm";
12
12
 
13
13
 
14
- const FieldMetaData = ({ modelMetaData, fieldMetaData, setFieldMetaData, deleteModelFunction, nextTab, formikFieldsMetadataRef, params }: any) => {
14
+ const FieldMetaData = ({ setIsDirty, modelMetaData, fieldMetaData, setFieldMetaData, deleteModelFunction, nextTab, formikFieldsMetadataRef, params }: any) => {
15
15
  const pathname = usePathname();
16
16
  const msgs = useRef<Messages>(null);
17
17
 
@@ -59,7 +59,11 @@ const FieldMetaData = ({ modelMetaData, fieldMetaData, setFieldMetaData, deleteM
59
59
 
60
60
  // Function to delete a row
61
61
  const deleteRow = (rowData: any) => {
62
- setFieldMetaData((prevData: any) => prevData.filter((item: any) => item.name !== rowData.name)); // Remove the row from the data array
62
+ setFieldMetaData((prevData: any) => {
63
+ const updatedData = prevData.filter((item: any) => item.name !== rowData.name);
64
+ setIsDirty(true); // Ensure dirty state is updated immediately
65
+ return updatedData;
66
+ });
63
67
  };
64
68
 
65
69
  // Template for the trash (delete) icon column
@@ -156,7 +160,7 @@ const FieldMetaData = ({ modelMetaData, fieldMetaData, setFieldMetaData, deleteM
156
160
  }}
157
161
  showHeader={false}
158
162
  >
159
- <FieldMetaDataForm modelMetaData={modelMetaData} fieldMetaData={selectedFieldMetaData} allFields={fieldMetaData} setFieldMetaData={setFieldMetaData} deleteModelFunction={deleteModelFunction} setVisiblePopup={setVisiblePopup} formikFieldsMetadataRef={formikFieldsMetadataRef} params={params} setIsRequiredPopUp={setIsRequiredPopUp} showToaster={showToaster}></FieldMetaDataForm>
163
+ <FieldMetaDataForm setIsDirty={setIsDirty} modelMetaData={modelMetaData} fieldMetaData={selectedFieldMetaData} allFields={fieldMetaData} setFieldMetaData={setFieldMetaData} deleteModelFunction={deleteModelFunction} setVisiblePopup={setVisiblePopup} formikFieldsMetadataRef={formikFieldsMetadataRef} params={params} setIsRequiredPopUp={setIsRequiredPopUp} showToaster={showToaster}></FieldMetaDataForm>
160
164
  </Dialog>
161
165
  <Dialog
162
166
  visible={isRequiredPopUp}