diff --git a/src/plugins/index.js b/src/plugins/index.js
index 3f295b6..2c8538b 100644
--- a/src/plugins/index.js
+++ b/src/plugins/index.js
@@ -14,6 +14,8 @@ import viewDataviewEditor from "./web_view_dataview/FNAbviewdataviewEditor.js";
import viewDataviewProperties from "./web_view_dataview/FNAbviewdataview.js";
import viewDetailEditor from "./web_view_detail/FNAbviewdetailEditor.js";
import viewDetailProperties from "./web_view_detail/FNAbviewdetail.js";
+import viewFormEditor from "./web_view_form/FNAbviewformEditor.js";
+import viewFormProperties from "./web_view_form/FNAbviewform.js";
import viewGanttEditor from "./web_view_gantt/FNAbviewganttEditor.js";
import viewGanttProperties from "./web_view_gantt/FNAbviewgantt.js";
import viewGridEditor from "./web_view_grid/FNAbviewgridEditor.js";
@@ -51,6 +53,8 @@ const AllPlugins = [
viewDataviewProperties,
viewDetailEditor,
viewDetailProperties,
+ viewFormEditor,
+ viewFormProperties,
viewGanttEditor,
viewGanttProperties,
viewGridEditor,
diff --git a/src/plugins/web_view_form/FNAbviewform.js b/src/plugins/web_view_form/FNAbviewform.js
new file mode 100644
index 0000000..1ba128a
--- /dev/null
+++ b/src/plugins/web_view_form/FNAbviewform.js
@@ -0,0 +1,799 @@
+import FNAbviewFormButtonProperties from "./properties/FNAbviewFormButton.js";
+import FNAbviewFormCheckboxProperties from "./properties/FNAbviewFormCheckbox.js";
+import FNAbviewFormConnectProperties from "./properties/FNAbviewFormConnect.js";
+import FNAbviewFormCustomProperties from "./properties/FNAbviewFormCustom.js";
+import FNAbviewFormDatepickerProperties from "./properties/FNAbviewFormDatepicker.js";
+import FNAbviewFormJsonProperties from "./properties/FNAbviewFormJson.js";
+import FNAbviewFormNumberProperties from "./properties/FNAbviewFormNumber.js";
+import FNAbviewFormSelectMultipleProperties from "./properties/FNAbviewFormSelectMultiple.js";
+import FNAbviewFormSelectSingleProperties from "./properties/FNAbviewFormSelectSingle.js";
+import FNAbviewFormTextboxProperties from "./properties/FNAbviewFormTextbox.js";
+import FNAbviewFormTreeProperties from "./properties/FNAbviewFormTree.js";
+import FNAbviewFormUrlProperties from "./properties/FNAbviewFormUrl.js";
+
+export default function FNAbviewformProperties({
+ AB,
+ ABViewPropertiesPlugin,
+ // ABUIPlugin,
+}) {
+ const FABViewContainer =
+ require("../../rootPages/Designer/properties/views/ABViewContainer").default;
+ const FABViewRuleListFormRecordRules =
+ require("../../rootPages/Designer/properties/rules/ABViewRuleListFormRecordRules").default;
+ const FABViewRuleListFormSubmitRules =
+ require("../../rootPages/Designer/properties/rules/ABViewRuleListFormSubmitRules").default;
+
+ const ABViewContainer = FABViewContainer(AB);
+ const uiConfig = AB.Config.uiSettings();
+ const L = ABViewContainer.L();
+
+ var ABViewFormPropertyComponentDefaults = {};
+
+ const base = "properties_abview_form";
+
+ const PopupRecordRule = FABViewRuleListFormRecordRules(
+ AB,
+ `${base}_popupRecordRule`
+ );
+
+ const PopupSubmitRule = FABViewRuleListFormSubmitRules(
+ AB,
+ `${base}_popupSubmitRule`
+ );
+
+ const ABAbviewformProperties = class ABAbviewformProperties extends ABViewPropertiesPlugin {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ // properties-view : will display in the properties panel of the ABDesigner
+ }
+
+ constructor(b = null, id = null) {
+ b = b || base;
+ id = Object.assign(id || {}, {
+ // Put our ids here
+ datacollection: "",
+ fields: "",
+ showLabel: "",
+ labelPosition: "",
+ labelWidth: "",
+ height: "",
+ clearOnLoad: "",
+ clearOnSave: "",
+
+ buttonSubmitRules: "",
+ buttonRecordRules: "",
+ });
+ super(b, id);
+
+ this.AB = AB;
+ ABViewFormPropertyComponentDefaults =
+ this.AB.ClassManager.viewClass("form").defaultValues();
+ }
+
+ static get key() {
+ return "form";
+ }
+
+ ui(elements = null) {
+ let ids = this.ids;
+
+ elements = elements || [];
+
+ return super.ui(
+ [
+ {
+ id: ids.datacollection,
+ view: "richselect",
+ name: "datacollection",
+ label: L("Datacollection"),
+ labelWidth: uiConfig.labelWidthLarge,
+ skipAutoSave: true,
+ on: {
+ onChange: (newId, oldId) => {
+ this.selectSource(newId, oldId);
+ },
+ },
+ },
+
+ {
+ view: "fieldset",
+ label: L("Form Fields:"),
+ labelWidth: uiConfig.labelWidthLarge,
+ body: {
+ type: "clean",
+ padding: 10,
+ rows: [
+ {
+ id: ids.fields,
+ view: "list",
+ name: "fields",
+
+ select: false,
+ minHeight: 200,
+ template: (...params) => {
+ return this.listTemplate(...params);
+ },
+ type: {
+ markCheckbox: function (item) {
+ return (
+ ""
+ );
+ },
+ },
+ onClick: {
+ check: (...params) => {
+ return this.check(...params);
+ },
+ },
+ },
+ ],
+ },
+ },
+ {
+ id: ids.showLabel,
+ name: "showLabel",
+ view: "checkbox",
+ label: L("Display Label"),
+ labelWidth: uiConfig.labelWidthLarge,
+ click: () => {
+ this.onChange();
+ },
+ },
+ {
+ id: ids.labelPosition,
+ view: "richselect",
+ name: "labelPosition",
+
+ label: L("Label Position"),
+ labelWidth: uiConfig.labelWidthLarge,
+ options: [
+ {
+ id: "left",
+ value: L("Left"),
+ },
+ {
+ id: "top",
+ value: L("Top"),
+ },
+ ],
+ on: {
+ onChange: () => {
+ this.onChange();
+ },
+ },
+ },
+ {
+ id: ids.labelWidth,
+ view: "counter",
+ name: "labelWidth",
+
+ label: L("Label Width"),
+ labelWidth: uiConfig.labelWidthLarge,
+ on: {
+ onChange: () => {
+ this.onChange();
+ },
+ },
+ },
+ {
+ id: ids.height,
+ view: "counter",
+ name: "height",
+ label: L("Height"),
+ labelWidth: uiConfig.labelWidthLarge,
+ on: {
+ onChange: () => {
+ this.onChange();
+ },
+ },
+ },
+ {
+ id: ids.clearOnLoad,
+ view: "checkbox",
+ name: "clearOnLoad",
+
+ label: L("Clear on load"),
+ labelWidth: uiConfig.labelWidthLarge,
+ on: {
+ onChange: () => {
+ this.onChange();
+ },
+ },
+ },
+ {
+ id: ids.clearOnSave,
+ view: "checkbox",
+ name: "clearOnSave",
+ label: L("Clear on save"),
+ labelWidth: uiConfig.labelWidthLarge,
+ on: {
+ onChange: () => {
+ this.onChange();
+ },
+ },
+ },
+ {
+ view: "fieldset",
+ label: L("Rules:"),
+ labelWidth: uiConfig.labelWidthLarge,
+ body: {
+ type: "clean",
+ padding: 10,
+ rows: [
+ {
+ cols: [
+ {
+ view: "label",
+ label: L("Submit Rules:"),
+ width: uiConfig.labelWidthLarge,
+ },
+ {
+ id: ids.buttonSubmitRules,
+ view: "button",
+ css: "webix_primary",
+ name: "buttonSubmitRules",
+ label: L("Settings"),
+ icon: "fa fa-gear",
+ type: "icon",
+ badge: 0,
+ click: () => {
+ this.submitRuleShow();
+ },
+ },
+ ],
+ },
+ // {
+ // cols: [
+ // {
+ // view: "label",
+ // label: L("Display Rules:"),
+ // width: uiConfig.labelWidthLarge,
+ // },
+ // {
+ // view: "button",
+ // name: "buttonDisplayRules",
+ // css: "webix_primary",
+ // label: L("Settings"),
+ // icon: "fa fa-gear",
+ // type: "icon",
+ // badge: 0,
+ // click: () => {
+ // this.displayRuleShow();
+ // },
+ // },
+ // ],
+ // },
+ {
+ cols: [
+ {
+ view: "label",
+ label: L("Record Rules:"),
+ width: uiConfig.labelWidthLarge,
+ },
+ {
+ id: ids.buttonRecordRules,
+ view: "button",
+ name: "buttonRecordRules",
+ css: "webix_primary",
+ label: L("Settings"),
+ icon: "fa fa-gear",
+ type: "icon",
+ badge: 0,
+ click: () => {
+ this.recordRuleShow();
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ].concat(elements)
+ );
+ }
+
+ async init(AB) {
+ super.init(AB);
+
+ webix.extend($$(this.ids.component), webix.ProgressBar);
+
+ let allInits = [];
+ allInits.push(PopupRecordRule.init(AB));
+ PopupRecordRule.on("save", () => {
+ this.onChange();
+ this.populateBadgeNumber();
+ });
+ allInits.push(PopupSubmitRule.init(AB));
+ PopupSubmitRule.on("save", (/* settings */) => {
+ this.onChange();
+ this.populateBadgeNumber();
+ });
+
+ return Promise.all(allInits);
+ }
+
+ populate(view) {
+ super.populate(view);
+ let ids = this.ids;
+ if (!view) return;
+
+ let formCom = view.parentFormComponent();
+ let datacollectionId = formCom.settings.dataviewID
+ ? formCom.settings.dataviewID
+ : null;
+ var SourceSelector = $$(ids.datacollection);
+
+ // Pull data collections to options
+ var dcOptions = view.application
+ .datacollectionsIncluded()
+ .filter((dc) => {
+ const obj = dc.datasource;
+ return (
+ dc.sourceType == "object" &&
+ !obj?.isImported &&
+ !obj?.isReadOnly
+ );
+ })
+ .map((d) => {
+ let entry = { id: d.id, value: d.label };
+ if (d.sourceType == "query") {
+ entry.icon = "fa fa-filter";
+ } else {
+ entry.icon = "fa fa-database";
+ }
+ return entry;
+ });
+ SourceSelector.define("options", dcOptions);
+ SourceSelector.define("value", datacollectionId);
+ SourceSelector.refresh();
+
+ this.propertyUpdateFieldOptions(datacollectionId);
+
+ // update properties when a field component is deleted
+ view.views().forEach((v) => {
+ if (v.isFormField) v.once("destroyed", () => this.populate(view));
+ });
+
+ SourceSelector.enable();
+ $$(ids.showLabel).setValue(view.settings.showLabel);
+ $$(ids.labelPosition).setValue(
+ view.settings.labelPosition ||
+ ABViewFormPropertyComponentDefaults.labelPosition
+ );
+ $$(ids.labelWidth).setValue(
+ view.settings.labelWidth ||
+ ABViewFormPropertyComponentDefaults.labelWidth
+ );
+ $$(ids.height).setValue(
+ view.settings.height || ABViewFormPropertyComponentDefaults.height
+ );
+ $$(ids.clearOnLoad).setValue(
+ view.settings.clearOnLoad ||
+ ABViewFormPropertyComponentDefaults.clearOnLoad
+ );
+ $$(ids.clearOnSave).setValue(
+ view.settings.clearOnSave ||
+ ABViewFormPropertyComponentDefaults.clearOnSave
+ );
+
+ // NOTE: load the object and view BEFORE the .fromSettings();
+ PopupRecordRule.objectLoad(this.CurrentObject);
+ PopupRecordRule.viewLoad(view);
+ PopupRecordRule.fromSettings(view.settings.recordRules || []);
+
+ PopupSubmitRule.objectLoad(this.CurrentObject);
+ PopupSubmitRule.viewLoad(view);
+ PopupSubmitRule.fromSettings(view.settings.submitRules || []);
+
+ // this.propertyUpdateRules(ids, view, datacollectionId);
+ this.populateBadgeNumber();
+
+ // when a change is made in the properties the popups need to reflect the change
+ this.updateEventIds = this.updateEventIds || {}; // { viewId: boolean, ..., viewIdn: boolean }
+ if (!this.updateEventIds[view.id]) {
+ this.updateEventIds[view.id] = true;
+
+ view.addListener("properties.updated", () => {
+ this.populateBadgeNumber();
+ });
+ }
+ }
+
+ defaultValues() {
+ let values = {};
+ var ViewClass = this.ViewClass();
+ if (ViewClass) {
+ values = ViewClass.defaultValues();
+ }
+ return values;
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ let ids = this.ids;
+ let vals = super.values();
+
+ vals.settings = vals.settings || {};
+
+ vals.settings.dataviewID = $$(ids.datacollection).getValue();
+ vals.settings.showLabel = $$(ids.showLabel).getValue();
+ vals.settings.labelPosition =
+ $$(ids.labelPosition).getValue() ||
+ ABViewFormPropertyComponentDefaults.labelPosition;
+ vals.settings.labelWidth =
+ $$(ids.labelWidth).getValue() ||
+ ABViewFormPropertyComponentDefaults.labelWidth;
+ vals.settings.height = $$(ids.height).getValue();
+ vals.settings.clearOnLoad = $$(ids.clearOnLoad).getValue();
+ vals.settings.clearOnSave = $$(ids.clearOnSave).getValue();
+
+ vals.settings.recordRules = PopupRecordRule.toSettings();
+ vals.settings.submitRules = PopupSubmitRule.toSettings();
+ return vals;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("form");
+ }
+
+ //
+ //
+ //
+
+ busy() {
+ $$(this.ids.component)?.showProgress?.({ type: "icon" });
+ }
+
+ check(e, fieldId) {
+ if (this._isBusy) return;
+ this._isBusy = true;
+ this.busy();
+ const ids = this.ids;
+ let currView = this.CurrentView;
+ let formView = currView.parentFormComponent();
+
+ // update UI list
+ let item = $$(ids.fields).getItem(fieldId);
+ item.selected = item.selected ? 0 : 1;
+ $$(ids.fields).updateItem(fieldId, item);
+
+ let doneFn = () => {
+ this._isBusy = false;
+ formView
+ .refreshDefaultButton(ids)
+ .save()
+ .then(() => {
+ // refresh UI
+ currView.emit("properties.updated", currView);
+ this.onChange();
+ this.ready();
+ });
+
+ // // trigger a save()
+ // this.propertyEditorSave(ids, currView);
+ };
+
+ // add a field to the form
+ if (item.selected) {
+ // Check for duplication
+ let exists = formView
+ .fieldComponents()
+ .find((c) => c.settings.fieldId == fieldId);
+ if (exists) {
+ this._isBusy = false;
+ this.ready();
+ return;
+ }
+
+ let fieldView = formView.addFieldToForm(item);
+ if (fieldView) {
+ fieldView.save().then(() => {
+ fieldView.once("destroyed", () => this.populate(currView));
+ formView.viewInsert(fieldView).then(() => {
+ doneFn();
+ });
+ });
+ } else {
+ this._isBusy = false;
+ this.ready();
+ }
+ }
+ // remove field in the form
+ else {
+ let fieldView = formView
+ .fieldComponents()
+ .filter((c) => c.settings.fieldId == fieldId)[0];
+ if (fieldView) {
+ // let remainingViews = formView.views(c => c.settings.fieldId != fieldId);
+ // formView._views = remainingViews;
+
+ fieldView.destroy();
+ formView.viewRemove(fieldView).then(() => {
+ doneFn();
+ });
+ } else {
+ this._isBusy = false;
+ this.ready();
+ }
+ }
+ }
+
+ populateBadgeNumber(/* */) {
+ const ids = this.ids;
+
+ let view = this.CurrentView;
+
+ if (!view) return;
+
+ if (view.settings.submitRules) {
+ $$(ids.buttonSubmitRules).define(
+ "badge",
+ view.settings.submitRules.length || null
+ );
+ } else {
+ $$(ids.buttonSubmitRules).define("badge", null);
+ }
+ $$(ids.buttonSubmitRules).refresh();
+
+ // if (view.settings.displayRules) {
+ // $$(ids.buttonDisplayRules).define(
+ // "badge",
+ // view.settings.displayRules.length || null
+ // );
+ // $$(ids.buttonDisplayRules).refresh();
+ // } else {
+ // $$(ids.buttonDisplayRules).define("badge", null);
+ // $$(ids.buttonDisplayRules).refresh();
+ // }
+
+ if (view.settings.recordRules) {
+ $$(ids.buttonRecordRules).define(
+ "badge",
+ view.settings.recordRules.length || null
+ );
+ } else {
+ $$(ids.buttonRecordRules).define("badge", null);
+ }
+ $$(ids.buttonRecordRules).refresh();
+ }
+
+ ready() {
+ $$(this.ids.component)?.hideProgress?.();
+ }
+
+ recordRuleShow() {
+ PopupRecordRule.fromSettings(this.CurrentView.settings.recordRules);
+ PopupRecordRule.show();
+ }
+
+ submitRuleShow() {
+ PopupSubmitRule.fromSettings(this.CurrentView.settings.submitRules);
+ PopupSubmitRule.show();
+ }
+
+ listTemplate(field, common) {
+ let currView = this.CurrentView;
+
+ // disable in form
+ var fieldComponent = field.formComponent();
+ if (fieldComponent == null)
+ return ` ${field.label}
Disable
`;
+
+ var componentKey = fieldComponent.common().key;
+ var formComponent = currView.application.viewAll(
+ (v) => v.common().key == componentKey
+ )[0];
+
+ return `${common.markCheckbox(field)} ${
+ field.label
+ } ${
+ formComponent ? L(formComponent.common().labelKey) : ""
+ }
`;
+ }
+
+ /**
+ * @method propertyUpdateFieldOptions
+ * Populate fields of object to select list in property
+ *
+ * @param {ABViewForm} view - the current component
+ * @param {string} dcId - id of ABDatacollection
+ */
+ propertyUpdateFieldOptions(dcId) {
+ const ids = this.ids;
+ var formComponent = this.CurrentView.parentFormComponent();
+ var existsFields = formComponent.fieldComponents();
+ var datacollection = this.AB.datacollectionByID(dcId);
+ var object = datacollection ? datacollection.datasource : null;
+
+ // Pull field list
+ var fieldOptions = [];
+ if (object != null) {
+ fieldOptions = object.fields().map((f) => {
+ f.selected =
+ existsFields.filter((com) => {
+ return f.id == com.settings.fieldId;
+ }).length > 0;
+
+ return f;
+ });
+
+ this.objectLoad(object);
+ }
+
+ $$(ids.fields).clearAll();
+ $$(ids.fields).parse(fieldOptions);
+ }
+
+ refreshDefaultButton() {
+ const ids = this.ids;
+ const ABViewFormButton = this.AB.ClassManager.viewClass("button");
+
+ // If default button is not exists, then skip this
+ let defaultButton = this.views(
+ (v) => v instanceof ABViewFormButton && v.settings.isDefault
+ )[0];
+
+ // Add a default button
+ if (defaultButton == null) {
+ defaultButton = ABViewFormButton.newInstance(
+ this.application,
+ this
+ );
+ defaultButton.settings.isDefault = true;
+ }
+ // Remove default button from array, then we will add it to be the last item later (.push)
+ else {
+ this._views = this.views(
+ (v) => !(v instanceof ABViewFormButton) && !v.settings.isDefault
+ );
+ }
+
+ // Calculate position Y of the default button
+ let yList = this.views().map((v) => (v.position.y || 0) + 1);
+ yList.push(this._views.length || 0);
+ yList.push($$(ids.fields).length || 0);
+ let posY = Math.max(...yList);
+
+ // Update to be the last item
+ defaultButton.position.y = posY;
+
+ // Keep the default button is always the last item of array
+ this._views.push(defaultButton);
+
+ return defaultButton;
+ }
+
+ selectSource(dcId /*, oldDcId */) {
+ // TODO : warning message
+ const ids = this.ids;
+ this.busy();
+
+ let currView = this.CurrentView;
+ let formView = currView.parentFormComponent();
+
+ currView.settings.dataviewID = dcId;
+
+ // clear sub views
+ var viewsToRemove = currView._views;
+ currView._views = [];
+
+ return (
+ Promise.resolve()
+ .then(() => {
+ var allRemoves = [];
+ viewsToRemove.forEach((v) => {
+ allRemoves.push(v.destroy());
+ });
+ return Promise.all(allRemoves);
+ })
+ // .then(() => {
+ // // remove all old components
+ // let destroyTasks = [];
+ // if (oldDcId != null) {
+ // let oldComps = formView.views();
+ // oldComps.forEach(child => destroyTasks.push(() => child.destroy()));
+ // }
+
+ // return destroyTasks.reduce((promiseChain, currTask) => {
+ // return promiseChain.then(currTask);
+ // }, Promise.resolve([]));
+ // })
+ .then(() => {
+ // refresh UI
+ // formView.emit('properties.updated', currView);
+
+ // Update field options in property
+ this.propertyUpdateFieldOptions(dcId);
+
+ // add all fields to editor by default
+ if (currView._views.length > 0) return Promise.resolve();
+
+ let saveTasks = [];
+ let fields = $$(ids.fields).find({});
+ fields.reverse();
+ fields.forEach((f, index) => {
+ if (!f.selected) {
+ let yPosition = fields.length - index - 1;
+
+ // Add new form field
+ let newFieldView = currView.addFieldToForm(
+ f,
+ yPosition
+ );
+ if (newFieldView) {
+ newFieldView.once("destroyed", () =>
+ this.populate(currView)
+ );
+
+ // // Call save API
+ saveTasks.push(newFieldView.save());
+ }
+
+ // update item to UI list
+ f.selected = 1;
+ $$(ids.fields).updateItem(f.id, f);
+ }
+ });
+
+ let defaultButton = formView.refreshDefaultButton(ids);
+ if (defaultButton) saveTasks.push(defaultButton.save());
+
+ return Promise.all(saveTasks);
+ })
+ // Saving
+ .then(() => {
+ //// NOTE: the way the .addFieldToForm() works, it will prevent
+ //// the typical field.save() -> triggering the form.save() on a
+ //// new Field. So once all our field.saves() are finished, we
+ //// need to perform a form.save() to persist the changes.
+ return currView.save();
+ })
+ // Finally
+ .then(() => {
+ // refresh UI
+ formView.emit("properties.updated", currView);
+
+ // Update field options in property
+ // this.propertyUpdateRules(ids, currView, dcId);
+
+ this.ready();
+ this.onChange();
+ return Promise.resolve();
+ })
+ );
+ }
+ };
+
+ return [
+ ABAbviewformProperties,
+ FNAbviewFormButtonProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormCheckboxProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormConnectProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormCustomProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormDatepickerProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormJsonProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormNumberProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormSelectMultipleProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormSelectSingleProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormTextboxProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormTreeProperties({ AB, ABViewPropertiesPlugin }),
+ FNAbviewFormUrlProperties({ AB, ABViewPropertiesPlugin }),
+ ];
+}
diff --git a/src/plugins/web_view_form/FNAbviewformEditor.js b/src/plugins/web_view_form/FNAbviewformEditor.js
new file mode 100644
index 0000000..43e3a9c
--- /dev/null
+++ b/src/plugins/web_view_form/FNAbviewformEditor.js
@@ -0,0 +1,61 @@
+import FNAbviewFormUrlEditor from "./editors/FNAbviewFormUrlEditor.js";
+
+export default function FNAbviewformEditor({ AB, ABViewEditorPlugin }) {
+ const FABViewContainer =
+ require("../../rootPages/Designer/editors/views/ABViewContainer").default;
+
+ const ABViewContainer = FABViewContainer(AB);
+ // var L = UIClass.L();
+ // var L = ABViewContainer.L();
+
+ const ABAbviewformEditor = class ABAbviewformEditor extends ABViewContainer {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ /**
+ * @method getPluginType
+ * return the plugin type for this editor.
+ * plugin types are how our ClassManager knows how to store
+ * the plugin.
+ * @return {string} plugin type
+ */
+ static getPluginType() {
+ return "editor-view";
+ // editor-view : will display in the editor panel of the ABDesigner
+ }
+
+ static get key() {
+ return "form";
+ }
+
+ constructor(view, base = "interface_editor_viewform") {
+ // base: {string} unique base id reference
+
+ super(view, base);
+
+ // this.component = this.view.component();
+ }
+
+ ui() {
+ let _ui = super.ui();
+ _ui.rows[0].cellHeight = 75;
+ return _ui;
+ }
+
+ init(AB) {
+ this.AB = AB;
+ return super.init(AB);
+ }
+
+ detatch() {
+ this.component?.detatch?.();
+ }
+
+ onShow() {
+ this.component?.onShow?.();
+ }
+ };
+
+ return [ABAbviewformEditor, FNAbviewFormUrlEditor({ ABViewEditorPlugin })];
+}
diff --git a/src/plugins/web_view_form/editors/FNAbviewFormUrlEditor.js b/src/plugins/web_view_form/editors/FNAbviewFormUrlEditor.js
new file mode 100644
index 0000000..d719d12
--- /dev/null
+++ b/src/plugins/web_view_form/editors/FNAbviewFormUrlEditor.js
@@ -0,0 +1,62 @@
+import FNAbviewformEditor from "../FNAbviewformEditor.js";
+
+/**
+ * ABViewFormEditor
+ * The widget that displays the UI Editor Component on the screen
+ * when designing the UI.
+ */
+var myClass = null;
+// {singleton}
+// we will want to call this factory fn() repeatedly in our imports,
+// but we only want to define 1 Class reference.
+
+export default function FNAbviewFormUrlEditor({ ABViewEditorPlugin }) {
+ const ABViewForm = FNAbviewformEditor({ ABViewEditorPlugin });
+
+ if (!myClass) {
+ // var L = UIClass.L();
+ // var L = ABViewContainer.L();
+
+ myClass = class ABViewFormEditor extends ABViewForm {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "editor-view";
+ }
+ static get key() {
+ return "form-url";
+ }
+
+ // constructor(view, base = "interface_editor_viewform") {
+ // // base: {string} unique base id reference
+
+ // super(view, base);
+
+ // // this.component = this.view.component();
+ // }
+
+ // ui() {
+ // let _ui = super.ui();
+ // _ui.rows[0].cellHeight = 75;
+ // return _ui;
+ // }
+
+ // init(AB) {
+ // this.AB = AB;
+ // return super.init(AB);
+ // }
+
+ // detatch() {
+ // this.component?.detatch?.();
+ // }
+
+ // onShow() {
+ // this.component?.onShow?.();
+ // }
+ };
+ }
+
+ return myClass;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormButton.js b/src/plugins/web_view_form/properties/FNAbviewFormButton.js
new file mode 100644
index 0000000..087d34b
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormButton.js
@@ -0,0 +1,282 @@
+/*
+ * ABViewButton
+ * A Property manager for our ABViewButton definitions
+ */
+
+export default function FNAbviewFormButtonProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const BASE_ID = "properties_abview_button";
+
+ const L = AB.Label();
+
+ class ABViewButtonProperty extends ABViewPropertiesPlugin {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {
+ // Put our ids here
+ includeSave: "",
+ saveLabel: "",
+ includeCancel: "",
+ cancelLabel: "",
+ includeReset: "",
+ resetLabel: "",
+ includeDelete: "",
+ deleteLabel: "",
+ afterCancel: "",
+ alignment: "",
+ });
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "button";
+ }
+
+ ui() {
+ const ids = this.ids;
+ const uiConfig = this.AB.UISettings.config();
+
+ return super.ui([
+ {
+ id: ids.includeSave,
+ name: "includeSave",
+ view: "checkbox",
+ label: L("Save"),
+ click: () => this.onChange(),
+ },
+ {
+ id: ids.saveLabel,
+ name: "saveLabel",
+ view: "text",
+ labelWidth: uiConfig.labelWidthLarge,
+ label: L("Save Label"),
+ placeholder: L("Save Placeholder"),
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ {
+ id: ids.includeCancel,
+ name: "includeCancel",
+ view: "checkbox",
+ label: L("Cancel"),
+ click: () => this.onChange(),
+ },
+ {
+ id: ids.cancelLabel,
+ name: "cancelLabel",
+ view: "text",
+ labelWidth: uiConfig.labelWidthLarge,
+ label: L("Cancel Label"),
+ placeholder: L("Cancel Placeholder"),
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ {
+ id: ids.includeReset,
+ name: "includeReset",
+ view: "checkbox",
+ label: L("Reset"),
+ click: () => this.onChange(),
+ },
+ {
+ id: ids.resetLabel,
+ name: "resetLabel",
+ view: "text",
+ labelWidth: uiConfig.labelWidthLarge,
+ label: L("Reset Label"),
+ placeholder: L("Reset Placeholder"),
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ {
+ id: ids.includeDelete,
+ name: "includeDelete",
+ view: "checkbox",
+ label: L("Delete"),
+ click: () => this.onChange(),
+ },
+ {
+ id: ids.deleteLabel,
+ name: "deleteLabel",
+ view: "text",
+ labelWidth: uiConfig.labelWidthLarge,
+ label: L("Delete Label"),
+ placeholder: L("Delete Placeholder"),
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ {
+ id: ids.afterCancel,
+ name: "afterCancel",
+ view: "richselect",
+ labelWidth: uiConfig.labelWidthLarge,
+ label: L("After Cancel"),
+ on: {
+ onChange: () => this.onChange(),
+ },
+ // options: []
+ },
+ {
+ id: ids.alignment,
+ name: "alignment",
+ view: "richselect",
+ labelWidth: uiConfig.labelWidthLarge,
+ label: L("Alignment"),
+ options: [
+ {
+ id: "left",
+ value: L("Left"),
+ },
+ {
+ id: "center",
+ value: L("Center"),
+ },
+ {
+ id: "right",
+ value: L("Right"),
+ },
+ ],
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ ]);
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ await super.init(AB);
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ const ids = this.ids;
+ const ABViewFormButtonPropertyComponentDefaults = this.defaultValues();
+
+ const pagesList = [];
+ this.addPagesToList(pagesList, view.application, view.pageRoot().id);
+
+ const opts = pagesList.map((opt) => {
+ return {
+ id: opt.id,
+ value: opt.value,
+ };
+ });
+ $$(ids.afterCancel).define("options", opts);
+
+ $$(ids.includeSave).setValue(
+ view.settings.includeSave != null
+ ? view.settings.includeSave
+ : ABViewFormButtonPropertyComponentDefaults.includeSave
+ );
+ $$(ids.includeCancel).setValue(
+ view.settings.includeCancel != null
+ ? view.settings.includeCancel
+ : ABViewFormButtonPropertyComponentDefaults.includeCancel
+ );
+ $$(ids.includeReset).setValue(
+ view.settings.includeReset != null
+ ? view.settings.includeReset
+ : ABViewFormButtonPropertyComponentDefaults.includeReset
+ );
+ $$(ids.includeDelete).setValue(
+ view.settings.includeDelete != null
+ ? view.settings.includeDelete
+ : ABViewFormButtonPropertyComponentDefaults.includeDelete
+ );
+
+ $$(ids.saveLabel).setValue(view.settings.saveLabel ?? "");
+ $$(ids.cancelLabel).setValue(view.settings.cancelLabel ?? "");
+ $$(ids.resetLabel).setValue(view.settings.resetLabel ?? "");
+ $$(ids.deleteLabel).setValue(view.settings.deleteLabel ?? "");
+
+ $$(ids.afterCancel).setValue(
+ view.settings.afterCancel ??
+ ABViewFormButtonPropertyComponentDefaults.afterCancel
+ );
+ $$(ids.alignment).setValue(
+ view.settings.alignment ??
+ ABViewFormButtonPropertyComponentDefaults.alignment
+ );
+ }
+
+ defaultValues() {
+ const ViewClass = this.ViewClass();
+
+ let values = null;
+
+ if (ViewClass) {
+ values = ViewClass.defaultValues();
+ }
+
+ return values;
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ const ids = this.ids;
+
+ const $component = $$(ids.component);
+
+ const values = super.values() ?? {};
+ values.settings = $component.getValues() ?? {};
+ values.settings.includeSave = $$(ids.includeSave).getValue();
+ values.settings.saveLabel = $$(ids.saveLabel).getValue();
+ values.settings.includeCancel = $$(ids.includeCancel).getValue();
+ values.settings.cancelLabel = $$(ids.cancelLabel).getValue();
+ values.settings.includeReset = $$(ids.includeReset).getValue();
+ values.settings.resetLabel = $$(ids.resetLabel).getValue();
+ values.settings.includeDelete = $$(ids.includeDelete).getValue();
+ values.settings.deleteLabel = $$(ids.deleteLabel).getValue();
+ values.settings.afterCancel = $$(ids.afterCancel).getValue();
+ values.settings.alignment = $$(ids.alignment).getValue();
+
+ return values;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("button");
+ }
+
+ addPagesToList(pagesList, parent, rootPageId) {
+ if (!parent || !parent.pages || !pagesList) return;
+
+ (parent.pages() ?? []).forEach((page) => {
+ if (page.parent != null || page.id == rootPageId) {
+ pagesList.push({
+ id: page.id,
+ value: page.label,
+ });
+
+ this.addPagesToList(pagesList, page, page.id);
+ }
+ });
+ }
+ }
+
+ return ABViewButtonProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormCheckbox.js b/src/plugins/web_view_form/properties/FNAbviewFormCheckbox.js
new file mode 100644
index 0000000..0a07b5e
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormCheckbox.js
@@ -0,0 +1,36 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormCheckbox
+ * A Property manager for our ABViewFormCheckbox definitions
+ */
+
+export default function FNAbviewFormCheckboxProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_checkbox";
+
+ class ABViewFormCheckboxProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {});
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "checkbox";
+ }
+ }
+
+ return ABViewFormCheckboxProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormConnect.js b/src/plugins/web_view_form/properties/FNAbviewFormConnect.js
new file mode 100644
index 0000000..d0c4b1d
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormConnect.js
@@ -0,0 +1,527 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+import ABPopupSort from "../../../rootPages/Designer/ui_work_object_workspace_popupSortFields";
+import ABViewPropertyAddPage from "../../../rootPages/Designer/properties/views/viewProperties/ABViewPropertyAddPage";
+import ABViewPropertyEditPage from "../../../rootPages/Designer/properties/views/viewProperties/ABViewPropertyEditPage";
+
+/*
+ * ABViewConnect
+ * A Property manager for our ABViewConnect definitions
+ */
+
+export default function FNAbviewFormConnectProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_connect";
+
+ const ABAddPage = ABViewPropertyAddPage(AB, BASE_ID);
+ const ABEditPage = ABViewPropertyEditPage(AB, BASE_ID);
+ const L = AB.Label();
+
+ let FilterComponent = null;
+ let SortComponent = null;
+
+ class ABViewConnectProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {
+ // Put our ids here
+ addNewSettings: "",
+ popupWidth: "",
+ popupHeight: "",
+ advancedOption: "",
+ buttonFilter: "",
+ filterConnectedValue: "",
+ buttonSort: "",
+ });
+
+ this.AB = AB;
+ FilterComponent = this.AB.filterComplexNew(`${BASE_ID}_filter`);
+ FilterComponent.on("save", () => this.onChange());
+ SortComponent = ABPopupSort(this.AB, `${BASE_ID}_sort`);
+ SortComponent.on("changed", () => this.onChange());
+ }
+
+ static get key() {
+ return "connect";
+ }
+
+ ui() {
+ const self = this;
+ const ids = this.ids;
+ const uiConfig = this.AB.UISettings.config();
+
+ return super.ui([
+ this.addPageProperty.ui(),
+ this.editPageProperty.ui(),
+ {
+ id: ids.addNewSettings,
+ view: "fieldset",
+ name: "addNewSettings",
+ label: L("Add New Popup Settings:"),
+ labelWidth: uiConfig.labelWidthLarge,
+ body: {
+ type: "clean",
+ padding: 10,
+ rows: [
+ {
+ id: ids.popupWidth,
+ view: "text",
+ name: "popupWidth",
+ placeholder: L("Set popup width"),
+ label: L("Width:"),
+ labelWidth: uiConfig.labelWidthLarge,
+ validate: this.AB.Webix.rules.isNumber,
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ {
+ id: ids.popupHeight,
+ view: "text",
+ name: "popupHeight",
+ placeholder: L("Set popup height"),
+ label: L("Height:"),
+ labelWidth: uiConfig.labelWidthLarge,
+ validate: this.AB.Webix.rules.isNumber,
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ ],
+ },
+ },
+ {
+ id: ids.advancedOption,
+ view: "fieldset",
+ name: "advancedOption",
+ label: L("Advanced Options:"),
+ labelWidth: uiConfig.labelWidthLarge,
+ body: {
+ type: "clean",
+ padding: 10,
+ rows: [
+ {
+ cols: [
+ {
+ view: "label",
+ label: L("Filter Options:"),
+ width: uiConfig.labelWidthLarge,
+ },
+ {
+ id: ids.buttonFilter,
+ view: "button",
+ name: "buttonFilter",
+ css: "webix_primary",
+ label: L("Settings"),
+ icon: "fa fa-gear",
+ type: "icon",
+ badge: 0,
+ click: function () {
+ self.showFilterPopup(this.$view);
+ },
+ },
+ ],
+ },
+ {
+ rows: [
+ {
+ view: "label",
+ label: L("Filter by Connected Field Value:"),
+ },
+ {
+ id: ids.filterConnectedValue,
+ view: "combo",
+ name: "filterConnectedValue",
+ options: [], // we will add these in propertyEditorPopulate
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ ],
+ },
+ {
+ height: 30,
+ },
+ {
+ rows: [
+ {
+ cols: [
+ {
+ view: "label",
+ label: L("Sort Options:"),
+ width: uiConfig.labelWidthLarge,
+ },
+ {
+ id: ids.buttonSort,
+ view: "button",
+ name: "buttonSort",
+ css: "webix_primary",
+ label: L("Settings"),
+ icon: "fa fa-gear",
+ type: "icon",
+ badge: 0,
+ click: function () {
+ self.showSortPopup(this.$view);
+ },
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ]);
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ await super.init(AB);
+
+ FilterComponent.init();
+ // when we make a change in the popups we want to make sure we save the new workspace to the properties to do so just fire an onChange event
+ // FilterComponent.on("change", (val) => {
+ // this.onChange();
+ // });
+
+ SortComponent.init(AB);
+
+ this.addPageProperty.on("change", () => {
+ this.onChange();
+ });
+
+ this.editPageProperty.on("change", () => {
+ this.onChange();
+ });
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ this.populateFilterByConnectedFieldValue(view);
+
+ const ids = this.ids;
+ const ABViewFormConnectPropertyComponentDefaults =
+ this.defaultValues();
+
+ // Default set of options for filter connected combo
+ const filterConnectedOptions = [{ id: null, value: "" }];
+
+ // get the definitions for the connected field
+ const fieldDefs = this.AB.definitionByID(view.settings.fieldId);
+
+ // get the definition for the object that the field is related to
+ const objectDefs = this.AB.definitionByID(
+ fieldDefs.settings.linkObject
+ );
+
+ // we need these definitions later as we check to find out which field
+ // we are filtering by so push them into an array for later
+ const fieldsDefs = [];
+ objectDefs.fieldIDs.forEach((fld) => {
+ fieldsDefs.push(this.AB.definitionByID(fld));
+ });
+
+ // find out what connected objects this field has
+ const connectedObjs = view.application.connectedObjects(
+ fieldDefs.settings.linkObject
+ );
+
+ // loop through the form's elements (need to ensure that just looking at parent is okay in all cases)
+ view.parent.views().forEach((element) => {
+ // identify if element is a connected field
+ if (element.key == "connect") {
+ // we need to get the fields defs to find out what it is connected to
+ const formElementsDefs = this.AB.definitionByID(
+ element.settings.fieldId
+ );
+
+ // loop through the connected objects discovered above
+ connectedObjs.forEach((connObj) => {
+ // see if the connected object matches the connected object of the form element
+ if (connObj.id == formElementsDefs.settings.linkObject) {
+ // get the ui id of this component that matches the link Object
+ let fieldToCheck;
+ fieldsDefs.forEach((fdefs) => {
+ // if the field has a custom foreign key we need to store it
+ // so selectivity later can know what value to get, otherwise
+ // we just get the uuid of the record
+ if (
+ fdefs.settings.isCustomFK &&
+ fdefs.settings.indexField != "" &&
+ fdefs.settings.linkObject &&
+ fdefs.settings.linkType == "one" &&
+ fdefs.settings.linkObject ==
+ formElementsDefs.settings.linkObject
+ ) {
+ fieldToCheck = fdefs.id;
+ let customFK = this.AB.definitionByID(
+ fdefs.settings.indexField
+ );
+
+ // if the index definitions were found
+ if (customFK) {
+ fieldToCheck = `${fdefs.id}:${customFK.columnName}`;
+ }
+ } else if (
+ fdefs.settings.linkObject &&
+ fdefs.settings.linkType == "one" &&
+ fdefs.settings.linkObject ==
+ formElementsDefs.settings.linkObject
+ ) {
+ fieldToCheck = `${fdefs.id}:uuid`;
+ }
+ });
+
+ // only add optinos that have a fieldToCheck
+ if (fieldToCheck) {
+ // get the component we are referencing so we can display its label
+ const formComponent =
+ view.parent.viewComponents[element.id]; // need to ensure that just looking at parent is okay in all cases
+
+ const uiComp = formComponent.ui();
+ const uiInput = uiComp.rows[0] ?? uiComp;
+
+ filterConnectedOptions.push({
+ id: `${uiInput.name}:${fieldToCheck}`, // store the columnName name because the ui id changes on each load
+ value: uiInput.label, // should be the translated field label
+ });
+ }
+ }
+ });
+ }
+ });
+
+ // Set the options of the possible edit forms
+ this.addPageProperty.setSettings(view, {
+ formView: view.settings.formView,
+ });
+ this.editPageProperty.setSettings(view, {
+ editForm: view.settings.editForm,
+ });
+ $$(ids.filterConnectedValue).define("options", filterConnectedOptions);
+ $$(ids.filterConnectedValue).setValue(
+ view.settings.filterConnectedValue
+ );
+
+ $$(ids.popupWidth).setValue(
+ view.settings.popupWidth ||
+ ABViewFormConnectPropertyComponentDefaults.popupWidth
+ );
+ $$(ids.popupHeight).setValue(
+ view.settings.popupHeight ||
+ ABViewFormConnectPropertyComponentDefaults.popupHeight
+ );
+
+ // initial populate of popups
+ this.populatePopupEditors(view);
+
+ // inform the user that some advanced settings have been set
+ this.populateBadgeNumber(ids, view);
+ }
+
+ _filterCondition(view) {
+ if (view?.options?.filters?.rules?.length) {
+ return view.options.filters;
+ } else if (view?.settings?.filterConditions?.rules?.length) {
+ return view.settings.filterConditions;
+ } else {
+ return null;
+ }
+ }
+
+ populatePopupEditors(view) {
+ const filterConditions =
+ this._filterCondition(view) ??
+ this.defaultValues().filterConditions;
+
+ // Populate data to popups
+ // FilterComponent.objectLoad(objectCopy);
+ let linkedObj;
+ const field = view.field();
+ if (field) {
+ linkedObj = field.datasourceLink;
+ if (linkedObj)
+ FilterComponent.fieldsLoad(linkedObj.fields(), linkedObj);
+ }
+
+ FilterComponent.setValue(filterConditions);
+
+ if (linkedObj) SortComponent.objectLoad(linkedObj);
+ SortComponent.setSettings(view.settings.sortFields);
+ }
+
+ populateBadgeNumber(ids, view) {
+ const $buttonFilter = $$(ids.buttonFilter);
+ const filterCondition = this._filterCondition(view);
+ if (filterCondition?.rules) {
+ $buttonFilter.define("badge", filterCondition.rules.length || null);
+ $buttonFilter.refresh();
+ } else {
+ $buttonFilter.define("badge", null);
+ $buttonFilter.refresh();
+ }
+
+ const $buttonSort = $$(ids.buttonSort);
+ if (view?.settings?.sortFields?.length) {
+ $buttonSort.define(
+ "badge",
+ view.settings.sortFields.length || null
+ );
+ $buttonSort.refresh();
+ } else {
+ $buttonSort.define("badge", null);
+ $buttonSort.refresh();
+ }
+ }
+
+ populateFilterByConnectedFieldValue(view) {
+ const fieldDef = this.AB.definitionByID(view.settings.fieldId);
+
+ // Support only 1:M and 1:1 relation type of the connect field
+ if (
+ // 1:M
+ (fieldDef.settings.linkType == "one" &&
+ fieldDef.settings.linkViaType == "many") ||
+ // 1:1 isSource = true
+ (fieldDef.settings.linkType == "one" &&
+ fieldDef.settings.linkViaType == "one" &&
+ fieldDef.settings.isSource)
+ ) {
+ // Pull link object
+ const linkObject = this.AB.objectByID(fieldDef.settings.linkObject);
+ if (!linkObject) return;
+
+ let connectFields = linkObject.fields(
+ (f) => f.key == "connectObject"
+ );
+ if (!connectFields || !connectFields.length) return;
+
+ connectFields.forEach((f) => {
+ let connectFieldOptions = view.parent
+ .views((element) => {
+ let linkFieldDef = this.AB.definitionByID(
+ element.settings.fieldId
+ );
+
+ // Pull other connected field input elements
+ return (
+ element.key == "connect" &&
+ element.id != view.id &&
+ f.settings.linkObject ==
+ linkFieldDef.settings.linkObject
+ );
+ })
+ .map((element) => {
+ const formComponent =
+ view.parent.viewComponents[element.id];
+
+ const uiComp = formComponent.ui();
+ const uiInput = uiComp.rows[0] ?? uiComp;
+
+ return {
+ id: uiInput.name,
+ value: uiInput.label,
+ };
+ });
+
+ if (connectFieldOptions && connectFieldOptions.length) {
+ FilterComponent.addCustomOption(f.id, {
+ conditions: [
+ {
+ id: "filterByConnectValue",
+ value: L("Filter by Connected Field Value:"),
+ batch: "FilterByConnectedFieldValue",
+ handler: () => true,
+ },
+ ],
+ values: [
+ {
+ batch: "FilterByConnectedFieldValue",
+ view: "combo",
+ options: connectFieldOptions,
+ },
+ ],
+ });
+ }
+ });
+ }
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ const ids = this.ids;
+ const view = this.CurrentView;
+
+ const $component = $$(ids.component);
+
+ const values = super.values() ?? {};
+ values.settings = $component.getValues() ?? {};
+ values.settings.popupWidth = $$(ids.popupWidth).getValue();
+ values.settings.popupHeight = $$(ids.popupHeight).getValue();
+ values.settings.filterConnectedValue = $$(
+ ids.filterConnectedValue
+ ).getValue();
+ values.settings.filterConditions = FilterComponent.getValue();
+ values.settings.sortFields = SortComponent.getSettings();
+
+ const settingsAddPage = this.addPageProperty.getSettings(view) ?? {};
+ const settingsEditPage = this.editPageProperty.getSettings(view) ?? {};
+ values.settings.formView = settingsAddPage.formView;
+ values.settings.editForm = settingsEditPage.editForm;
+
+ // refresh settings of app page tool
+ // this.addPageProperty.setSettings(view, values.settingsAddPage);
+ // this.editPageProperty.setSettings(view, values.settingsEditPage);
+
+ return values;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("connect");
+ }
+
+ get addPageProperty() {
+ if (!this._addPage) this._addPage = new ABAddPage();
+
+ return this._addPage;
+ }
+
+ get editPageProperty() {
+ if (!this._editPage) this._editPage = new ABEditPage();
+
+ return this._editPage;
+ }
+
+ showFilterPopup($view) {
+ FilterComponent.popUp($view, null, { pos: "top" });
+ }
+
+ showSortPopup($button) {
+ SortComponent.show($button, null, {
+ pos: "top",
+ });
+ }
+ }
+
+ return ABViewConnectProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormCustom.js b/src/plugins/web_view_form/properties/FNAbviewFormCustom.js
new file mode 100644
index 0000000..4e933fc
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormCustom.js
@@ -0,0 +1,36 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormCustom
+ * A Property manager for our ABViewFormCustom definitions
+ */
+
+export default function FNAbviewFormCustomProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_custom";
+
+ class ABViewFormCustomProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {});
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "fieldcustom";
+ }
+ }
+
+ return ABViewFormCustomProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormDatepicker.js b/src/plugins/web_view_form/properties/FNAbviewFormDatepicker.js
new file mode 100644
index 0000000..c3d666d
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormDatepicker.js
@@ -0,0 +1,36 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormDatepicker
+ * A Property manager for our ABViewFormDatepicker definitions
+ */
+
+export default function FNAbviewFormDatepickerProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_datepicker";
+
+ class ABViewFormDatepickerProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {});
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "datepicker";
+ }
+ }
+
+ return ABViewFormDatepickerProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormItem.js b/src/plugins/web_view_form/properties/FNAbviewFormItem.js
new file mode 100644
index 0000000..f1388fb
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormItem.js
@@ -0,0 +1,120 @@
+/*
+ * ABViewFormItem
+ * A Property manager for our ABViewFormItem definitions
+ */
+
+export default function FNAbviewFormItemProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const L = AB.Label();
+ const DEFAULT_VALUES = {
+ required: 0,
+ disable: 0,
+ };
+
+ class ABViewFormItemProperty extends ABViewPropertiesPlugin {
+ constructor(BASE_ID, ids = {}) {
+ super(
+ BASE_ID,
+ Object.assign(ids, {
+ // Put our ids here
+ field: "",
+ required: "",
+ disable: "",
+ })
+ );
+
+ this.AB = AB;
+ }
+
+ ui(elements = [], rules = {}) {
+ const ids = this.ids;
+ const uiSettings = this.AB.UISettings.config();
+ const _ui = [
+ {
+ id: ids.field,
+ name: "fieldLabel",
+ view: "text",
+ disabled: true,
+ label: L("Field"),
+ },
+ {
+ id: ids.required,
+ name: "required",
+ view: "checkbox",
+ labelWidth: uiSettings.labelWidthCheckbox,
+ labelRight: L("Required"),
+ click: () => this.onChange(),
+ },
+ {
+ id: ids.disable,
+ name: "disable",
+ view: "checkbox",
+ labelWidth: uiSettings.labelWidthCheckbox,
+ labelRight: L("Disable"),
+ click: () => this.onChange(),
+ },
+ ].concat(elements);
+
+ return super.ui(_ui, rules);
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ const ids = this.ids;
+ const ABViewFormItemPropertyDefaults = this.defaultValues();
+ const field = view.field();
+
+ $$(ids.field).setValue(field ? field.label : "");
+
+ if (field?.settings?.required == 1) {
+ $$(ids.required).setValue(field.settings.required);
+ $$(ids.required).disable();
+ } else {
+ $$(ids.required).setValue(
+ view.settings?.required != null
+ ? view.settings.required
+ : ABViewFormItemPropertyDefaults.required
+ );
+ }
+
+ if (view.settings?.disable == 1) {
+ $$(ids.disable).setValue(view.settings.disable);
+ } else {
+ $$(ids.disable).setValue(ABViewFormItemPropertyDefaults.disable);
+ }
+ }
+
+ defaultValues() {
+ const ViewClass = this.ViewClass();
+
+ let values = {};
+
+ if (ViewClass) {
+ values = ViewClass.defaultValues();
+ }
+
+ return Object.assign(DEFAULT_VALUES, values);
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ const ids = this.ids;
+
+ const values = super.values() ?? {};
+ values.settings = values.settings ?? {};
+ values.settings.required = $$(ids.required).getValue();
+ values.settings.disable = $$(ids.disable).getValue();
+
+ return values;
+ }
+ }
+
+ return ABViewFormItemProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormJson.js b/src/plugins/web_view_form/properties/FNAbviewFormJson.js
new file mode 100644
index 0000000..a10ddb0
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormJson.js
@@ -0,0 +1,157 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormJson
+ * A Property manager for our ABViewFormJson definitions
+ */
+
+export default function FNAbviewFormJsonProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_json";
+
+ const L = AB.Label();
+
+ class ABViewFormJsonProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {
+ // Put our ids here
+ type: "",
+ filterField: "",
+ });
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "json";
+ }
+
+ ui() {
+ const ids = this.ids;
+
+ return super.ui([
+ {
+ id: ids.type,
+ name: "type",
+ view: "radio",
+ label: L("Type"),
+ vertical: true,
+ options: [
+ {
+ id: "string",
+ value: L("JSON String"),
+ },
+ {
+ id: "systemObject",
+ value: L("System Object Chooser UI"),
+ },
+ {
+ id: "filter",
+ value: L("Filter UI"),
+ },
+ ],
+ on: {
+ onChange: (newValue) => {
+ if (newValue == "filter") {
+ $$(ids.filterField).show();
+ } else {
+ $$(ids.filterField).hide();
+ }
+ this.onChange();
+ },
+ },
+ },
+ {
+ id: ids.filterField,
+ name: "filterField",
+ view: "combo",
+ hidden: true,
+ label: L("Object Field to Filter"),
+ labelPosition: "top",
+ placeholder: L("Select a field to filter by"),
+ // options: look at populate
+ on: {
+ onChange: (/* newValue */) => {
+ this.onChange();
+ },
+ },
+ },
+ ]);
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ await super.init(AB);
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ const ids = this.ids;
+ const ABViewFormJsonPropertyComponentDefaults = this.defaultValues();
+
+ // set the options for the filterField
+ let filterFieldOptions = [{ id: "", value: "" }];
+ view.parent.views().forEach((element) => {
+ if (
+ element.key == "json" &&
+ element.settings.type == "systemObject"
+ ) {
+ let formComponent = view.parent.viewComponents[element.id];
+ filterFieldOptions.push({
+ id: element.settings.fieldId,
+ value: formComponent.settings.fieldLabel,
+ });
+ }
+ });
+ $$(ids.filterField).define("options", filterFieldOptions);
+
+ if (view.settings.filterField)
+ $$(ids.filterField).setValue(view.settings.filterField);
+
+ $$(ids.type).setValue(
+ view.settings.type || ABViewFormJsonPropertyComponentDefaults.type
+ );
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ const ids = this.ids;
+
+ const $component = $$(ids.component);
+
+ const values = super.values() ?? {};
+ values.settings = $component.getValues() ?? {};
+ values.settings.type = $$(ids.type).getValue();
+
+ return values;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("json");
+ }
+ }
+
+ return ABViewFormJsonProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormNumber.js b/src/plugins/web_view_form/properties/FNAbviewFormNumber.js
new file mode 100644
index 0000000..da83114
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormNumber.js
@@ -0,0 +1,104 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormNumber
+ * A Property manager for our ABViewFormNumber definitions
+ */
+
+export default function FNAbviewFormNumberProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_number";
+
+ const L = AB.Label();
+
+ class ABViewFormNumberProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {
+ // Put our ids here
+ isStepper: "",
+ });
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "numberbox";
+ }
+
+ ui() {
+ const ids = this.ids;
+ const uiConfig = this.AB.UISettings.config();
+
+ return super.ui([
+ {
+ id: ids.isStepper,
+ name: "isStepper",
+ view: "checkbox",
+ labelWidth: uiConfig.labelWidthCheckbox,
+ labelRight: L("Plus/Minus Buttons"),
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ ]);
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ await super.init(AB);
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ const ids = this.ids;
+ const ABViewFormNumberPropertyComponentDefaults = this.defaultValues();
+
+ $$(ids.isStepper).setValue(
+ view.settings.isStepper != null
+ ? view.settings.isStepper
+ : ABViewFormNumberPropertyComponentDefaults.isStepper
+ );
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ const ids = this.ids;
+
+ const $component = $$(ids.component);
+
+ const values = super.values() ?? {};
+ values.settings = $component.getValues() ?? {};
+ values.settings.isStepper = $$(ids.isStepper).getValue();
+
+ return values;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("numberbox");
+ }
+ }
+
+ return ABViewFormNumberProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormSelectMultiple.js b/src/plugins/web_view_form/properties/FNAbviewFormSelectMultiple.js
new file mode 100644
index 0000000..adc1e15
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormSelectMultiple.js
@@ -0,0 +1,112 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormSelectMultiple
+ * A Property manager for our ABViewFormSelectMultiple definitions
+ */
+
+export default function FNAbviewFormSelectMultipleProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_select_multiple";
+
+ const L = AB.Label();
+
+ class ABViewFormSelectMultipleProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {
+ // Put our ids here
+ type: "",
+ });
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "selectmultiple";
+ }
+
+ ui() {
+ const ids = this.ids;
+
+ return super.ui([
+ {
+ id: ids.type,
+ name: "type",
+ view: "richselect",
+ label: L("Type"),
+ options: [
+ {
+ id: "multicombo",
+ value: L("Multi Combo"),
+ },
+ {
+ id: "checkbox",
+ value: L("Checkboxes"),
+ },
+ ],
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ ]);
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ await super.init(AB);
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ const ids = this.ids;
+ const ABViewFormSelectMultiplePropertyComponentDefaults =
+ this.defaultValues();
+
+ $$(ids.type).setValue(
+ view.settings.type ||
+ ABViewFormSelectMultiplePropertyComponentDefaults.type
+ );
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ const ids = this.ids;
+
+ const $component = $$(ids.component);
+
+ const values = super.values() ?? {};
+ values.settings = $component.getValues() ?? {};
+ values.settings.type = $$(ids.type).getValue();
+
+ return values;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("selectmultiple");
+ }
+ }
+
+ return ABViewFormSelectMultipleProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormSelectSingle.js b/src/plugins/web_view_form/properties/FNAbviewFormSelectSingle.js
new file mode 100644
index 0000000..bd3a7f0
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormSelectSingle.js
@@ -0,0 +1,112 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormSelectSingle
+ * A Property manager for our ABViewFormSelectSingle definitions
+ */
+
+export default function FNAbviewFormSelectSingleProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_select_single";
+
+ const L = AB.Label();
+
+ class ABViewFormSelectSingleProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {
+ // Put our ids here
+ type: "",
+ });
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "selectsingle";
+ }
+
+ ui() {
+ const ids = this.ids;
+
+ return super.ui([
+ {
+ id: ids.type,
+ name: "type",
+ view: "richselect",
+ label: L("Type"),
+ options: [
+ {
+ id: "richselect",
+ value: L("Select list"),
+ },
+ {
+ id: "radio",
+ value: L("Radio"),
+ },
+ ],
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ ]);
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ await super.init(AB);
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ const ids = this.ids;
+ const ABViewFormSelectSinglePropertyComponentDefaults =
+ this.defaultValues();
+
+ $$(ids.type).setValue(
+ view.settings.type ||
+ ABViewFormSelectSinglePropertyComponentDefaults.type
+ );
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ const ids = this.ids;
+
+ const $component = $$(ids.component);
+
+ const values = super.values() ?? {};
+ values.settings = $component.getValues() ?? {};
+ values.settings.type = $$(ids.type).getValue();
+
+ return values;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("selectsingle");
+ }
+ }
+
+ return ABViewFormSelectSingleProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormTextbox.js b/src/plugins/web_view_form/properties/FNAbviewFormTextbox.js
new file mode 100644
index 0000000..5083da9
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormTextbox.js
@@ -0,0 +1,117 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormTextbox
+ * A Property manager for our ABViewFormTextbox definitions
+ */
+
+export default function FNAbviewFormTextboxProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_textbox";
+
+ const L = AB.Label();
+
+ class ABViewFormTextboxProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {
+ // Put our ids here
+ type: "",
+ });
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "textbox";
+ }
+
+ ui() {
+ const ids = this.ids;
+
+ return super.ui([
+ {
+ id: ids.type,
+ name: "type",
+ view: "radio",
+ label: L("Type"),
+ vertical: true,
+ options: [
+ {
+ id: "single",
+ value: L("Single line"),
+ },
+ {
+ id: "multiple",
+ value: L("Multiple lines"),
+ },
+ {
+ id: "rich",
+ value: L("Rich editor"),
+ },
+ ],
+ on: {
+ onChange: () => this.onChange(),
+ },
+ },
+ ]);
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ await super.init(AB);
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ const ids = this.ids;
+ const ABViewFormTextboxPropertyComponentDefaults =
+ this.defaultValues();
+
+ $$(ids.type).setValue(
+ view.settings.type ||
+ ABViewFormTextboxPropertyComponentDefaults.type
+ );
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ const ids = this.ids;
+
+ const $component = $$(ids.component);
+
+ const values = super.values() ?? {};
+ values.settings = $component.getValues() ?? {};
+ values.settings.type = $$(ids.type).getValue();
+
+ return values;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("textbox");
+ }
+ }
+
+ return ABViewFormTextboxProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormTree.js b/src/plugins/web_view_form/properties/FNAbviewFormTree.js
new file mode 100644
index 0000000..3017e28
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormTree.js
@@ -0,0 +1,36 @@
+import FNAbviewformItem from "./FNAbviewFormItem.js";
+
+/*
+ * ABViewFormTree
+ * A Property manager for our ABViewFormTree definitions
+ */
+
+export default function FNAbviewFormTreeProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewFormItem = FNAbviewformItem({ AB, ABViewPropertiesPlugin });
+
+ const BASE_ID = "properties_abview_form_tree";
+
+ class ABViewFormTreeProperty extends ABViewFormItem {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(BASE_ID, {});
+
+ this.AB = AB;
+ }
+
+ static get key() {
+ return "formtree";
+ }
+ }
+
+ return ABViewFormTreeProperty;
+}
diff --git a/src/plugins/web_view_form/properties/FNAbviewFormUrl.js b/src/plugins/web_view_form/properties/FNAbviewFormUrl.js
new file mode 100644
index 0000000..a2666de
--- /dev/null
+++ b/src/plugins/web_view_form/properties/FNAbviewFormUrl.js
@@ -0,0 +1,166 @@
+import FCommonKeyValue from "../../../rootPages/Designer/ui_common_key_value";
+import FNAbviewformProperties from "../FNAbviewform.js";
+
+/*
+ * ABViewForm
+ * A Property manager for our ABViewForm definitions
+ */
+
+export default function FNAbviewFormUrlProperties({
+ AB,
+ ABViewPropertiesPlugin,
+}) {
+ const ABViewForm = FNAbviewformProperties({ AB, ABViewPropertiesPlugin });
+
+ const UIClassCommonKeyValue = FCommonKeyValue(AB);
+ const uiConfig = AB.Config.uiSettings();
+ const L = AB.Label();
+
+ const base = "properties_abview_form_url";
+
+ class ABViewFormUrlProperty extends ABViewForm {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+ constructor() {
+ super(base, {
+ method: "",
+ url: "",
+ headers: "",
+ });
+
+ this.AB = AB;
+
+ this.UIKeyValues = new UIClassCommonKeyValue({
+ title: L("Headers"),
+ keyTitle: L("Key"),
+ valueTitle: L("Value"),
+ // contextID: base || randomID(),
+ });
+ }
+
+ static get key() {
+ return "form-url";
+ }
+
+ ui() {
+ let ids = this.ids;
+
+ return super.ui([
+ {
+ view: "fieldset",
+ label: L("URL:"),
+ labelWidth: uiConfig.labelWidthLarge,
+ body: {
+ type: "clean",
+ padding: 10,
+ rows: [
+ {
+ id: ids.method,
+ view: "richselect",
+ name: "urlMethod",
+
+ label: L("Method"),
+ labelWidth: uiConfig.labelWidthLarge,
+ options: [
+ {
+ id: "get",
+ value: L("GET"),
+ },
+ {
+ id: "post",
+ value: L("POST"),
+ },
+
+ {
+ id: "put",
+ value: L("PUT"),
+ },
+ {
+ id: "delete",
+ value: L("DELETE"),
+ },
+ ],
+ on: {
+ onChange: () => {
+ this.onChange();
+ },
+ },
+ },
+ {
+ id: ids.url,
+ view: "text",
+ label: L("URL"),
+ name: "url",
+ value: "",
+ on: {
+ onChange: () => {
+ this.onChange();
+ },
+ },
+ },
+ this.UIKeyValues.ui(),
+ ],
+ },
+ },
+ ]);
+ }
+
+ populate(view) {
+ super.populate(view);
+ let ids = this.ids;
+ if (!view) return;
+
+ var methodSelector = $$(ids.method);
+ methodSelector.define("value", view.settings?.method || "get");
+ methodSelector.refresh();
+ methodSelector.enable();
+
+ $$(ids.url).setValue(view.settings.url);
+
+ this.UIKeyValues.populate(view.settings?.headers || []);
+ }
+
+ defaultValues() {
+ let values = {};
+ var ViewClass = this.ViewClass();
+ if (ViewClass) {
+ values = ViewClass.defaultValues();
+ }
+ return values;
+ }
+
+ /**
+ * @method values
+ * return the values for this form.
+ * @return {obj}
+ */
+ values() {
+ let ids = this.ids;
+ let vals = super.values();
+
+ vals.settings = vals.settings || {};
+
+ vals.settings.method = $$(ids.method).getValue();
+ vals.settings.url = $$(ids.url).getValue();
+
+ vals.headers = this.UIKeyValues.getValues();
+ return vals;
+ }
+
+ /**
+ * @method FieldClass()
+ * A method to return the proper ABViewXXX Definition.
+ * NOTE: Must be overwritten by the Child Class
+ */
+ ViewClass() {
+ return super._ViewClass("form-url");
+ }
+ }
+
+ return ABViewFormUrlProperty;
+}
diff --git a/src/rootPages/Designer/editors/EditorManager.js b/src/rootPages/Designer/editors/EditorManager.js
index 5d02be7..d6f7460 100644
--- a/src/rootPages/Designer/editors/EditorManager.js
+++ b/src/rootPages/Designer/editors/EditorManager.js
@@ -25,8 +25,7 @@ export default function (AB) {
// require("./views/ABViewDataview"),
// require("./views/ABViewDetail"),
// require("./views/ABViewDocxBuilder"),
- require("./views/ABViewForm"),
- require("./views/ABViewFormUrl"),
+ // require("./views/ABViewFormUrl"),
// require("./views/ABViewGantt"),
// require("./views/ABViewKanban"),
// require("./views/ABViewGrid"),
diff --git a/src/rootPages/Designer/properties/PropertyManager.js b/src/rootPages/Designer/properties/PropertyManager.js
index 27505aa..27cf058 100644
--- a/src/rootPages/Designer/properties/PropertyManager.js
+++ b/src/rootPages/Designer/properties/PropertyManager.js
@@ -90,19 +90,19 @@ export default function (AB) {
require("./views/ABViewDetailText"),
require("./views/ABViewDetailTree"),
// require("./views/ABViewDocxBuilder"),
- require("./views/ABViewForm"),
- require("./views/ABViewFormButton"),
- require("./views/ABViewFormCheckbox"),
- require("./views/ABViewFormConnect"),
- require("./views/ABViewFormCustom"),
- require("./views/ABViewFormDatepicker"),
- require("./views/ABViewFormJson"),
- require("./views/ABViewFormNumber"),
- require("./views/ABViewFormSelectMultiple"),
- require("./views/ABViewFormSelectSingle"),
- require("./views/ABViewFormTextbox"),
- require("./views/ABViewFormTree"),
- require("./views/ABViewFormUrl"),
+ // require("./views/ABViewForm"),
+ // require("./views/ABViewFormButton"),
+ // require("./views/ABViewFormCheckbox"),
+ // require("./views/ABViewFormConnect"),
+ // require("./views/ABViewFormCustom"),
+ // require("./views/ABViewFormDatepicker"),
+ // require("./views/ABViewFormJson"),
+ // require("./views/ABViewFormNumber"),
+ // require("./views/ABViewFormSelectMultiple"),
+ // require("./views/ABViewFormSelectSingle"),
+ // require("./views/ABViewFormTextbox"),
+ // require("./views/ABViewFormTree"),
+ // require("./views/ABViewFormUrl"),
// require("./views/ABViewGantt"),
// require("./views/ABViewGrid"),
// require("./views/ABViewImage"),