diff --git a/src/plugins/index.js b/src/plugins/index.js
index 44e7aad2..389beaa2 100644
--- a/src/plugins/index.js
+++ b/src/plugins/index.js
@@ -1,3 +1,5 @@
+import viewKanbanEditor from "./web_view_kanban/FNAbviewkanbanEditor.js";
+import viewKanbanProperties from "./web_view_kanban/FNAbviewkanban.js";
import viewCarouselProperties from "./web_view_carousel/FNAbviewcarousel.js";
import viewCarouselEditor from "./web_view_carousel/FNAbviewcarouselEditor.js";
import viewCommentProperties from "./web_view_comment/FNAbviewcomment.js";
@@ -46,6 +48,8 @@ const AllPlugins = [
viewTabEditor,
viewTextProperties,
viewTextEditor,
+ viewKanbanProperties,
+ viewKanbanEditor,
];
export default {
@@ -54,4 +58,4 @@ export default {
AB.pluginRegister(plugin);
});
},
-};
+};
\ No newline at end of file
diff --git a/src/plugins/web_view_kanban/Abkanbanworkspace.js b/src/plugins/web_view_kanban/Abkanbanworkspace.js
new file mode 100644
index 00000000..4dadf0e7
--- /dev/null
+++ b/src/plugins/web_view_kanban/Abkanbanworkspace.js
@@ -0,0 +1,313 @@
+// Abkanbanworkspace.js
+//
+// Manages the settings for a KanBan View in the Object Workspace
+
+const defaultValues = {
+ name: "Default Kanban",
+ settings: {
+ verticalGroupingField: null,
+ horizontalGroupingField: null,
+ ownerField: null,
+ },
+};
+
+var classABViewKanban = null;
+
+import UI_Class from "../../rootPages/Designer/ui_class";
+
+export default function (AB, ibase) {
+ const UIClass = UI_Class(AB);
+ var L = UIClass.L();
+
+ const ABFieldConnect = AB.Class.ABFieldManager.fieldByKey("connectObject");
+ const ABFieldList = AB.Class.ABFieldManager.fieldByKey("list");
+ const ABFieldUser = AB.Class.ABFieldManager.fieldByKey("user");
+
+ if (!classABViewKanban) {
+ classABViewKanban = class ABViewKanban extends UIClass {
+ constructor(idBase) {
+ super(idBase, {
+ vGroupInput: "",
+ hGroupInput: "",
+ ownerInput: "",
+ });
+
+ this.on("field.added", (field) => {
+ this.refreshOptions(this.CurrentObject, this._view);
+ if (this._autoSelectInput) {
+ $$(this._autoSelectInput)?.setValue(field.id);
+ }
+ });
+
+ this._autoSelectInput = null;
+ }
+
+ type() {
+ return "kanban";
+ }
+
+ icon() {
+ return "fa fa-columns";
+ }
+
+ refreshOptions(object, view, options = {}) {
+ let ids = this.ids;
+
+ const initSelect = (
+ $option,
+ attribute,
+ filter = (f) => f.key === ABFieldList.defaults().key,
+ isRequired
+ ) => {
+ if ($option == null || object == null) return;
+
+ var options = object
+ .fields()
+ .filter(filter)
+ .map(({ id, label }) => ({ id, value: label }));
+ if (!isRequired && options.length) {
+ options.unshift({
+ id: "none",
+ value: L("None"),
+ });
+ }
+ $option.define("options", options);
+
+ if (view) {
+ if (view.settings[attribute]) {
+ $option.define("value", view.settings[attribute]);
+ } else if (!isRequired && options[0]) {
+ $option.define("value", options[0].id);
+ }
+ } else if (options.filter((o) => o.id).length === 1) {
+ $option.define("value", options[0].id);
+ }
+
+ $option.refresh();
+ };
+
+ const verticalGroupingFieldFilter = (field) =>
+ [
+ ABFieldList.defaults().key,
+ ABFieldUser.defaults().key,
+ ].includes(field.key);
+
+ const horizontalGroupingFieldFilter = (field) =>
+ [
+ ABFieldConnect.defaults().key,
+ ABFieldList.defaults().key,
+ ABFieldUser.defaults().key,
+ ].includes(field.key);
+
+ initSelect(
+ options.vGroupInput || $$(ids.vGroupInput),
+ "verticalGroupingField",
+ verticalGroupingFieldFilter,
+ true
+ );
+ initSelect(
+ options.hGroupInput || $$(ids.hGroupInput),
+ "horizontalGroupingField",
+ horizontalGroupingFieldFilter,
+ false
+ );
+ initSelect(
+ options.ownerInput || $$(ids.ownerInput),
+ "ownerField",
+ (f) => {
+ return (
+ f.key === ABFieldUser.defaults().key ||
+ (f.key === ABFieldConnect.defaults().key &&
+ f.settings.linkType == "one" &&
+ f.settings.linkViaType == "many")
+ );
+ },
+ false
+ );
+ }
+
+ ui() {
+ let ids = this.ids;
+ return {
+ batch: "kanban",
+ rows: [
+ {
+ cols: [
+ {
+ id: ids.vGroupInput,
+ view: "richselect",
+ label: ` ${L(
+ "Vertical Grouping"
+ )}`,
+ placeholder: L("Select a field"),
+ labelWidth: 180,
+ name: "verticalGroupingField",
+ required: true,
+ options: [],
+ on: {
+ onChange: () => {
+ $$(ids.vGroupInput).validate();
+ $$(ids.hGroupInput).validate();
+ this.emit("changed");
+ },
+ },
+ invalidMessage: L("Required"),
+ },
+ {
+ view: "button",
+ css: "webix_primary",
+ type: "icon",
+ icon: "fa fa-plus",
+ label: "",
+ width: 30,
+ click: () => {
+ this._autoSelectInput = ids.vGroupInput;
+ this.emit(
+ "new.field",
+ ABFieldList.defaults().key
+ );
+ },
+ },
+ ],
+ },
+ {
+ cols: [
+ {
+ id: ids.hGroupInput,
+ view: "richselect",
+ label: ` ${L(
+ "Horizontal Grouping"
+ )}`,
+ placeholder: L("Select a field"),
+ labelWidth: 180,
+ name: "horizontalGroupingField",
+ required: false,
+ options: [],
+ invalidMessage: L(
+ "Cannot be the same as vertical grouping field"
+ ),
+ validate: (value) => {
+ var vGroupValue = $$(ids.vGroupInput).getValue();
+ return (
+ !vGroupValue || !value || vGroupValue !== value
+ );
+ },
+ on: {
+ onChange: () => {
+ $$(ids.hGroupInput).validate();
+ this.emit("changed");
+ },
+ },
+ },
+ {
+ view: "button",
+ css: "webix_primary",
+ type: "icon",
+ icon: "fa fa-plus",
+ label: "",
+ width: 30,
+ click: () => {
+ this._autoSelectInput = ids.hGroupInput;
+ this.emit(
+ "new.field",
+ ABFieldList.defaults().key
+ );
+ },
+ },
+ ],
+ },
+ {
+ cols: [
+ {
+ id: ids.ownerInput,
+ view: "richselect",
+ label: ` ${L(
+ "Card Owner"
+ )}`,
+ placeholder: L("Select a user field"),
+ labelWidth: 180,
+ name: "ownerField",
+ options: [],
+ on: {
+ onChange: (newID, oldID) => {
+ if (newID == oldID) return;
+ this.emit("changed");
+ },
+ },
+ },
+ {
+ view: "button",
+ css: "webix_primary",
+ type: "icon",
+ icon: "fa fa-plus",
+ label: "",
+ width: 30,
+ click: () => {
+ this._autoSelectInput = ids.ownerInput;
+ this.emit(
+ "new.field",
+ ABFieldConnect.defaults().key
+ );
+ },
+ },
+ ],
+ },
+ ],
+ };
+ }
+
+ init(object, view) {
+ this.objectLoad(object);
+ this._view = view;
+ this.refreshOptions(object, view);
+ }
+
+ clearValues() {
+ const ids = this.ids;
+ let idFields = [ids.vGroupInput, ids.hGroupInput, ids.ownerInput];
+ idFields.forEach((id) => {
+ let $o = $$(id);
+ $o.blockEvent();
+ $o.define("value", null);
+ $o.unblockEvent();
+ $o.refresh();
+ });
+ }
+
+ values() {
+ let ids = this.ids;
+ let result = {};
+ result.verticalGroupingField =
+ $$(ids.vGroupInput).getValue() || null;
+ result.horizontalGroupingField =
+ $$(ids.hGroupInput).getValue() || null;
+ result.ownerField = $$(ids.ownerInput).getValue() || null;
+
+ return result;
+ }
+
+ fromSettings(data) {
+ for (var v in defaultValues) {
+ this[v] = data[v] || defaultValues[v];
+ }
+
+ this.type = this.type();
+ this.key = this.type();
+ }
+
+ toSettings() {
+ var obj = {};
+
+ for (var v in defaultValues) {
+ obj[v] = this[v] || defaultValues[v];
+ }
+
+ obj.key = this.type();
+ obj.type = this.type();
+ return obj;
+ }
+ };
+ }
+
+ return new classABViewKanban(ibase);
+}
diff --git a/src/plugins/web_view_kanban/FNAbviewkanban.js b/src/plugins/web_view_kanban/FNAbviewkanban.js
new file mode 100644
index 00000000..21214195
--- /dev/null
+++ b/src/plugins/web_view_kanban/FNAbviewkanban.js
@@ -0,0 +1,174 @@
+// FNAbviewkanban Properties
+// A properties side import for an ABView.
+//
+import FABViewKanbanWorkspace from "./Abkanbanworkspace.js";
+import FPopupNewDataField from "../../rootPages/Designer/ui_work_object_workspace_popupNewDataField";
+
+export default function FNAbviewkanbanProperties({
+ AB,
+ ABViewPropertiesPlugin,
+ ABViewPropertyLinkPage,
+}) {
+ const BASE_ID = "properties_abview_kanban";
+
+ const uiConfig = AB.UISettings.config();
+ const L = AB.Label();
+
+ const LinkPagePropertyClass = ABViewPropertyLinkPage(AB, BASE_ID);
+ const ViewKanbanProperties = FABViewKanbanWorkspace(AB, `${BASE_ID}_prop`);
+ var PopupNewDataFieldComponent = null;
+
+ return class ABAbviewkanbanProperties extends ABViewPropertiesPlugin {
+ static getPluginKey() {
+ return this.key;
+ }
+
+ static getPluginType() {
+ return "properties-view";
+ }
+
+ constructor() {
+ super(BASE_ID, { datacollection: "" });
+
+ this.AB = AB;
+ this.linkPageComponent = new LinkPagePropertyClass();
+ }
+
+ static get key() {
+ return "kanban";
+ }
+
+ ui() {
+ let _ui = ViewKanbanProperties.ui();
+
+ let rows = [
+ {
+ view: "fieldset",
+ label: L("Kanban Data:"),
+ labelWidth: uiConfig.labelWidthLarge,
+ body: {
+ type: "clean",
+ padding: 10,
+ rows: [
+ {
+ id: this.ids.datacollection,
+ view: "richselect",
+ name: "dataviewID",
+ label: L("Data Source:"),
+ placeholder: L("Select a Datacollection"),
+ labelWidth: uiConfig.labelWidthLarge,
+ options: [],
+ on: {
+ onChange: (newv, oldv) => {
+ if (newv != oldv) {
+ this.refreshFields(newv);
+ this.onChange();
+ }
+ },
+ },
+ },
+ ],
+ },
+ },
+ ..._ui.rows,
+ this.linkPageComponent.ui(),
+ ];
+
+ return super.ui(rows);
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ ViewKanbanProperties.on("new.field", (key) => {
+ let dc = this.AB.datacollectionByID(
+ this.CurrentView.settings.dataviewID
+ );
+ PopupNewDataFieldComponent.objectLoad(dc.datasource);
+ PopupNewDataFieldComponent.resetState();
+ PopupNewDataFieldComponent.show(null, key, false);
+ });
+ ViewKanbanProperties.on("changed", () => {
+ this.onChange();
+ });
+
+ PopupNewDataFieldComponent = FPopupNewDataField(
+ AB,
+ `${BASE_ID}_popupNewDataField`
+ );
+ await PopupNewDataFieldComponent.init(AB);
+ PopupNewDataFieldComponent.on("save", (...params) => {
+ ViewKanbanProperties.emit("field.added", params[0]);
+ });
+
+ this.linkPageComponent.init();
+ this.linkPageComponent.on("changed", () => {
+ this.onChange();
+ });
+
+ await super.init(AB);
+ }
+
+ populate(view) {
+ super.populate(view);
+
+ var listDC = view.application.datacollectionsIncluded().map((d) => {
+ return {
+ id: d.id,
+ value: d.label,
+ icon:
+ d.sourceType == "query" ? "fa fa-filter" : "fa fa-database",
+ };
+ });
+
+ let $dc = $$(this.ids.datacollection);
+ let dcID = view.settings.dataviewID || null;
+ $dc.blockEvent();
+ $dc.define("options", listDC);
+ $dc.define("value", dcID);
+ $dc.unblockEvent();
+ $dc.refresh();
+ this.refreshFields(dcID);
+
+ this.linkPageComponent.viewLoad(view);
+ this.linkPageComponent.setSettings(view.settings);
+ }
+
+ refreshFields(dcID) {
+ let dc = this.AB.datacollectionByID(dcID);
+ if (!dc) {
+ ViewKanbanProperties.clearValues();
+ return;
+ }
+
+ let obj = dc.datasource;
+ ViewKanbanProperties.init(obj, this.CurrentView);
+ PopupNewDataFieldComponent?.objectLoad(obj);
+ }
+
+ values() {
+ const values = super.values();
+
+ const ids = this.ids;
+ const $component = $$(ids.component);
+
+ values.settings = $component.getValues();
+
+ let fields = ViewKanbanProperties.values();
+ Object.keys(fields).forEach((f) => {
+ values.settings[f] = fields[f];
+ });
+
+ const linkSettings = this.linkPageComponent.getSettings();
+ for (const key in linkSettings) {
+ values.settings[key] = linkSettings[key];
+ }
+
+ return values;
+ }
+
+ ViewClass() {
+ return super._ViewClass("kanban");
+ }
+ };
+}
diff --git a/src/plugins/web_view_kanban/FNAbviewkanbanEditor.js b/src/plugins/web_view_kanban/FNAbviewkanbanEditor.js
new file mode 100644
index 00000000..6c628264
--- /dev/null
+++ b/src/plugins/web_view_kanban/FNAbviewkanbanEditor.js
@@ -0,0 +1,61 @@
+// FNAbviewkanban Editor
+// An Editor wrapper for the ABView Component.
+// The Editor is displayed in the ABDesigner as a view is worked on.
+// The Editor allows a widget to be moved and placed on the canvas.
+//
+export default function FNAbviewkanbanEditor({ AB, ABViewEditorPlugin }) {
+ const BASE_ID = "interface_editor_viewkanban";
+
+ return class ABAbviewkanbanEditor extends ABViewEditorPlugin {
+ 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 "kanban";
+ }
+
+ constructor(view, base = BASE_ID) {
+ // base: {string} unique base id reference
+ super(view, base);
+ }
+
+ ui() {
+ const component = this.component;
+ const _ui = component.ui();
+ _ui.minWidth = 400;
+
+ return {
+ view: "layout",
+ cols: [_ui, { fillspace: true }],
+ };
+ }
+
+ async init(AB) {
+ this.AB = AB;
+
+ await super.init(AB);
+ this.component?.init?.(AB);
+ }
+
+ detatch() {
+ this.component?.detatch?.();
+ }
+
+ onShow() {
+ this.component?.onShow?.();
+ }
+ };
+}
diff --git a/src/rootPages/Designer/editors/EditorManager.js b/src/rootPages/Designer/editors/EditorManager.js
index dde8f1de..49aa3aab 100644
--- a/src/rootPages/Designer/editors/EditorManager.js
+++ b/src/rootPages/Designer/editors/EditorManager.js
@@ -31,7 +31,7 @@ export default function (AB) {
require("./views/ABViewFormUrl"),
require("./views/ABViewGantt"),
require("./views/ABViewGrid"),
- require("./views/ABViewKanban"),
+ // require("./views/ABViewKanban"),
// require("./views/ABViewLabel"),
// require("./views/ABViewLayout"),
require("./views/ABViewMenu"),
diff --git a/src/rootPages/Designer/properties/PropertyManager.js b/src/rootPages/Designer/properties/PropertyManager.js
index 452280d1..6f816154 100644
--- a/src/rootPages/Designer/properties/PropertyManager.js
+++ b/src/rootPages/Designer/properties/PropertyManager.js
@@ -105,10 +105,10 @@ export default function (AB) {
require("./views/ABViewFormTextbox"),
require("./views/ABViewFormTree"),
require("./views/ABViewFormUrl"),
- require("./views/ABViewGantt"),
+ // require("./views/ABViewGantt"),
require("./views/ABViewGrid"),
// require("./views/ABViewImage"),
- require("./views/ABViewKanban"),
+ // require("./views/ABViewKanban"),
// require("./views/ABViewLabel"),
// require("./views/ABViewLayout"),
// require("./views/ABViewList"),
diff --git a/src/rootPages/Designer/properties/workspaceViews/ABViewGantt.js b/src/rootPages/Designer/properties/workspaceViews/ABViewGantt.js
index 66fbfbfb..bdabda8c 100644
--- a/src/rootPages/Designer/properties/workspaceViews/ABViewGantt.js
+++ b/src/rootPages/Designer/properties/workspaceViews/ABViewGantt.js
@@ -573,7 +573,7 @@ export default function (AB, ibase) {
*/
fromSettings(data) {
for (const key in defaultValues)
- this[v] = data[key] || defaultValues[key];
+ this[key] = data[key] || defaultValues[key];
this.settings = Object.assign(
{},
diff --git a/src/rootPages/Designer/ui_work_object_workspace_popupViewSettings.js b/src/rootPages/Designer/ui_work_object_workspace_popupViewSettings.js
index b20fd45f..b167f6e1 100644
--- a/src/rootPages/Designer/ui_work_object_workspace_popupViewSettings.js
+++ b/src/rootPages/Designer/ui_work_object_workspace_popupViewSettings.js
@@ -7,7 +7,7 @@
import UI_Class from "./ui_class";
import FormABViewGantt from "./properties/workspaceViews/ABViewGantt";
import FormABViewGrid from "./properties/workspaceViews/ABViewGrid";
-import FormABViewKanBan from "./properties/workspaceViews/ABViewKanban";
+import FormABViewKanBan from "../../plugins/web_view_kanban/Abkanbanworkspace.js";
export default function (AB, ibase, isettings) {
ibase = ibase || "abd_work_object_workspace_popupAddView";
diff --git a/src/rootPages/Designer/ui_work_object_workspace_view_kanban.js b/src/rootPages/Designer/ui_work_object_workspace_view_kanban.js
index f13df456..c20a36c5 100644
--- a/src/rootPages/Designer/ui_work_object_workspace_view_kanban.js
+++ b/src/rootPages/Designer/ui_work_object_workspace_view_kanban.js
@@ -9,7 +9,7 @@
*
*/
import UI_Class from "./ui_class";
-import FViewKanbanProperties from "./properties/workspaceViews/ABViewKanban";
+import FViewKanbanProperties from "../../plugins/web_view_kanban/Abkanbanworkspace.js";
export default function (AB, ibase) {
ibase = ibase || "ui_work_object_workspace_view_kanban";
diff --git a/src/rootPages/Designer/ui_work_object_workspace_workspaceviews.js b/src/rootPages/Designer/ui_work_object_workspace_workspaceviews.js
index 556e56e0..da5f3758 100644
--- a/src/rootPages/Designer/ui_work_object_workspace_workspaceviews.js
+++ b/src/rootPages/Designer/ui_work_object_workspace_workspaceviews.js
@@ -18,7 +18,7 @@ import WorkspaceKanban from "./ui_work_object_workspace_view_kanban";
import FViewGanttProperties from "./properties/workspaceViews/ABViewGantt";
import FViewGridProperties from "./properties/workspaceViews/ABViewGrid";
-import FViewKanbanProperties from "./properties/workspaceViews/ABViewKanban";
+import FViewKanbanProperties from "../../plugins/web_view_kanban/Abkanbanworkspace.js";
export default function (AB, ibase, isettings) {
ibase = ibase || "ui_work_object_workspace_workspaceviews";