From d4360681f1d778b8d56c5861560a3a2283216b9e Mon Sep 17 00:00:00 2001 From: maxwell-jordan Date: Wed, 22 Jul 2026 13:59:38 -0700 Subject: [PATCH 1/8] start --- core/document-resources.js | 7 ++++++- .../organization-cascading-list-ui-descriptor.mjson | 10 ++++++++++ data/model/party/organization.mjson | 3 +++ ui/action-target.mod/action-target.js | 4 ++++ ui/cascading-list.mod/cascading-list.js | 8 ++++++++ 5 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 data/model/party/organization-cascading-list-ui-descriptor.mjson diff --git a/core/document-resources.js b/core/document-resources.js index 1c39f2243..bc096d290 100644 --- a/core/document-resources.js +++ b/core/document-resources.js @@ -130,7 +130,12 @@ exports.DocumentResources = class DocumentResources extends Montage { const classListScope = cssContext.classListScope; const cssLayerName = cssContext.cssLayerName; const stylesheet = target.sheet; - const cssRules = stylesheet.cssRules; + let cssRules; + try { + cssRules = stylesheet.cssRules; + } catch (e) { + cssRules = []; + } /** * Adding CSS Layers, and Scoping for components in dev mode. diff --git a/data/model/party/organization-cascading-list-ui-descriptor.mjson b/data/model/party/organization-cascading-list-ui-descriptor.mjson new file mode 100644 index 000000000..2e9a9f463 --- /dev/null +++ b/data/model/party/organization-cascading-list-ui-descriptor.mjson @@ -0,0 +1,10 @@ +{ + "root": { + "prototype": "core/meta/user-interface-descriptor", + "values": { + "cascadingListItemHeaderRightCollectionNameExpression": "'Add'", + "cascadingListItemHeaderRightNameExpression": "isNew ? '' : 'Edit'", + "cascadingListItemFooterMiddleCollectionNameExpression": "length + ' item' + (length == 1 ? '' : 's')" + } + } +} diff --git a/data/model/party/organization.mjson b/data/model/party/organization.mjson index e63267000..5b72e22e4 100644 --- a/data/model/party/organization.mjson +++ b/data/model/party/organization.mjson @@ -26,6 +26,9 @@ "userInterfaceDescriptorModules": { "*": { "%": "./organization-ui-descriptor.mjson" + }, + "mod/ui/cascading-list.mod": { + "%": "./organization-cascading-list-ui-descriptor.mjson" } } diff --git a/ui/action-target.mod/action-target.js b/ui/action-target.mod/action-target.js index d0f37bd9a..72a9a0b29 100644 --- a/ui/action-target.mod/action-target.js +++ b/ui/action-target.mod/action-target.js @@ -22,6 +22,10 @@ var ActionTarget = exports.ActionTarget = Control.specialize( /** @lends ActionT value: false }, + hasTemplate: { + value: false + }, + /** * @private * @property {Map} value diff --git a/ui/cascading-list.mod/cascading-list.js b/ui/cascading-list.mod/cascading-list.js index 7db634a8d..7afa96561 100644 --- a/ui/cascading-list.mod/cascading-list.js +++ b/ui/cascading-list.mod/cascading-list.js @@ -244,6 +244,14 @@ CascadingList.addClassProperties( { if (!this._populatePromise && object) { var self = this; + if(Array.isArray(object)){ + //1) Find the highest common ancestor with existing object descriptor among all instances in the array + //2) Grab UI descriptor for that ancestor + } + else{ + //1) Refactor below to be used in both cases once UI descriptor is obtained + + } this._populatePromise = this.loadUserInterfaceDescriptor(object).then(function (UIDescriptor) { var context = self._createCascadingListContextWithObjectAndColumnIndex( object, From 2c72e03005552948bea4e72a7ba5eea9b71b32c4 Mon Sep 17 00:00:00 2001 From: maxwell-jordan Date: Tue, 28 Jul 2026 10:53:32 -0700 Subject: [PATCH 2/8] organization inspector start --- .../organization.mod/organization.css | 30 ++++++++++++ .../organization.mod/organization.html | 48 +++++++++++++++++++ .../organization.mod/organization.js | 38 +++++++++++++++ .../party/organization-ui-descriptor.mjson | 3 ++ 4 files changed, 119 insertions(+) create mode 100644 data/model/inspectors/organization.mod/organization.css create mode 100644 data/model/inspectors/organization.mod/organization.html create mode 100644 data/model/inspectors/organization.mod/organization.js diff --git a/data/model/inspectors/organization.mod/organization.css b/data/model/inspectors/organization.mod/organization.css new file mode 100644 index 000000000..3a810e71b --- /dev/null +++ b/data/model/inspectors/organization.mod/organization.css @@ -0,0 +1,30 @@ + +.OrganizationInspector { + height: 100%; + + + + .field { + height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + align-items: start; + background: white; + } + .roleListItem { + border: 1px solid #eeeeee; + align-content: center; + padding: 12px 8px; + } + .roleListItem.selected { + background: #d9d9d9; + } + .roleList { + width: 100%; + height: 100%; + } + +} + + diff --git a/data/model/inspectors/organization.mod/organization.html b/data/model/inspectors/organization.mod/organization.html new file mode 100644 index 000000000..76b89ce4f --- /dev/null +++ b/data/model/inspectors/organization.mod/organization.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+
+
+
+ + diff --git a/data/model/inspectors/organization.mod/organization.js b/data/model/inspectors/organization.mod/organization.js new file mode 100644 index 000000000..ba79b3647 --- /dev/null +++ b/data/model/inspectors/organization.mod/organization.js @@ -0,0 +1,38 @@ +var Component = require("../../../../ui/component").Component; + +const DataService = require("../../../../data/service/data-service").DataService; + + +exports.Organization = class Organization extends Component { + enterDocument(firstTime) { + if (firstTime) { + if (!this.data){ + throw new Error("Department context is required for Organization inspector"); + } + this.#buildJobRolesFromDepartment(this.data).then((roles) => { + this.roles = roles; + }); + + } + } + + + #buildJobRolesFromDepartment(department) { + return DataService.mainService + .updateObjectProperties(department, "suborganizations") + .then(() => { + return Promise.all( + department.suborganizations.map((suborg) => { + return DataService.mainService.updateObjectProperties(suborg, "jobRoles").then(() => { + return suborg.jobRoles; + }); + }) + ); + }) + .then((results) => { + return results.flat(); + }); + // const { suborganizations = [] } = department; + // return suborganizations.flatMap((suborg) => suborg.jobRoles || []); + } +}; diff --git a/data/model/party/organization-ui-descriptor.mjson b/data/model/party/organization-ui-descriptor.mjson index a3b4e2d76..a762d5dc7 100644 --- a/data/model/party/organization-ui-descriptor.mjson +++ b/data/model/party/organization-ui-descriptor.mjson @@ -2,6 +2,9 @@ "root": { "prototype": "core/meta/user-interface-descriptor", "values": { + "inspectorComponentModule": { + "%": "data/model/inspectors/organization.mod" + }, "collectionNameExpression": "'Organization'", "collectionInspectorComponentModule": { "%": "ui/list.mod" From 183bb969fa635a0c3ceefcc1cfa7df93bb39cb4a Mon Sep 17 00:00:00 2001 From: maxwell-jordan Date: Fri, 31 Jul 2026 09:14:55 -0700 Subject: [PATCH 3/8] roleSelection --- .../inspectors/organization.mod/organization.html | 3 ++- .../inspectors/organization.mod/organization.js | 14 ++++++++++++++ ui/action-target.mod/action-target.js | 3 --- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/data/model/inspectors/organization.mod/organization.html b/data/model/inspectors/organization.mod/organization.html index 76b89ce4f..42fc87174 100644 --- a/data/model/inspectors/organization.mod/organization.html +++ b/data/model/inspectors/organization.mod/organization.html @@ -6,7 +6,8 @@ { "owner": { "values": { - "element": {"#": "owner"} + "element": {"#": "owner"}, + "roleSelection": {"<-": "@roleList.selection.0"} } }, "roleList": { diff --git a/data/model/inspectors/organization.mod/organization.js b/data/model/inspectors/organization.mod/organization.js index ba79b3647..60ca82382 100644 --- a/data/model/inspectors/organization.mod/organization.js +++ b/data/model/inspectors/organization.mod/organization.js @@ -4,6 +4,20 @@ const DataService = require("../../../../data/service/data-service").DataService exports.Organization = class Organization extends Component { + + _roleSelection; + + get roleSelection() { + return this._roleSelection; + } + + set roleSelection(value) { + if (this._roleSelection !== value) { + this._roleSelection = value; + } + this.dispatchEventNamed("cascadingListPush", true, false, value); + } + enterDocument(firstTime) { if (firstTime) { if (!this.data){ diff --git a/ui/action-target.mod/action-target.js b/ui/action-target.mod/action-target.js index 72a9a0b29..f7f71410b 100644 --- a/ui/action-target.mod/action-target.js +++ b/ui/action-target.mod/action-target.js @@ -18,9 +18,6 @@ var Component = require("../component").Component, */ var ActionTarget = exports.ActionTarget = Control.specialize( /** @lends ActionTarget.prototype # */ { - hasTemplate: { - value: false - }, hasTemplate: { value: false From 1f6ccda49e93580eb0247e9e28242089ee3b46ea Mon Sep 17 00:00:00 2001 From: maxwell-jordan Date: Fri, 31 Jul 2026 11:07:38 -0700 Subject: [PATCH 4/8] proper context is sent --- .../organization.mod/organization.html | 2 +- .../inspectors/organization.mod/organization.js | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/data/model/inspectors/organization.mod/organization.html b/data/model/inspectors/organization.mod/organization.html index 42fc87174..ff17d1345 100644 --- a/data/model/inspectors/organization.mod/organization.html +++ b/data/model/inspectors/organization.mod/organization.html @@ -7,7 +7,7 @@ "owner": { "values": { "element": {"#": "owner"}, - "roleSelection": {"<-": "@roleList.selection.0"} + "roleSelection": {"<-": "@roleList.selection"} } }, "roleList": { diff --git a/data/model/inspectors/organization.mod/organization.js b/data/model/inspectors/organization.mod/organization.js index 60ca82382..f5259283b 100644 --- a/data/model/inspectors/organization.mod/organization.js +++ b/data/model/inspectors/organization.mod/organization.js @@ -5,6 +5,13 @@ const DataService = require("../../../../data/service/data-service").DataService exports.Organization = class Organization extends Component { + context = null; + + getContext() { + const grandparent = this.parentComponent && this.parentComponent.parentComponent; + return grandparent && grandparent.context; + } + _roleSelection; get roleSelection() { @@ -15,7 +22,6 @@ exports.Organization = class Organization extends Component { if (this._roleSelection !== value) { this._roleSelection = value; } - this.dispatchEventNamed("cascadingListPush", true, false, value); } enterDocument(firstTime) { @@ -26,10 +32,17 @@ exports.Organization = class Organization extends Component { this.#buildJobRolesFromDepartment(this.data).then((roles) => { this.roles = roles; }); - + this.context = this.getContext(); + this.addRangeAtPathChangeListener("roleSelection", this, "_handleSelectionChange"); } } + _handleSelectionChange(plus, minus, index) { + console.log("Organization inspector role selection changed:", this.roleSelection); + var obj = {plus: plus, context: this.context}; + this.dispatchEventNamed("cascadingListPush", true, false, obj); + } + #buildJobRolesFromDepartment(department) { return DataService.mainService From 5e8d224c8f0c5da76fa0eda166848ec2a85f26f5 Mon Sep 17 00:00:00 2001 From: maxwell-jordan Date: Fri, 31 Jul 2026 11:08:18 -0700 Subject: [PATCH 5/8] remove console log --- data/model/inspectors/organization.mod/organization.js | 1 - 1 file changed, 1 deletion(-) diff --git a/data/model/inspectors/organization.mod/organization.js b/data/model/inspectors/organization.mod/organization.js index f5259283b..272fae377 100644 --- a/data/model/inspectors/organization.mod/organization.js +++ b/data/model/inspectors/organization.mod/organization.js @@ -38,7 +38,6 @@ exports.Organization = class Organization extends Component { } _handleSelectionChange(plus, minus, index) { - console.log("Organization inspector role selection changed:", this.roleSelection); var obj = {plus: plus, context: this.context}; this.dispatchEventNamed("cascadingListPush", true, false, obj); } From 2897a00da521ba42c284c69e1ad9d699d4a44527 Mon Sep 17 00:00:00 2001 From: maxwell-jordan Date: Thu, 6 Aug 2026 14:08:29 -0700 Subject: [PATCH 6/8] flatten roles --- data/model/inspectors/organization.mod/organization.html | 2 +- data/model/inspectors/organization.mod/organization.js | 1 - .../party/organization-cascading-list-ui-descriptor.mjson | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/data/model/inspectors/organization.mod/organization.html b/data/model/inspectors/organization.mod/organization.html index ff17d1345..d5a7e9567 100644 --- a/data/model/inspectors/organization.mod/organization.html +++ b/data/model/inspectors/organization.mod/organization.html @@ -21,7 +21,7 @@ "roleListController": { "prototype": "../../../../core/range-controller", "values": { - "content": {"<-": "@owner.roles"} + "content": {"<-": "@owner.data.suborganizations.map{jobRoles}.flatten()"} } }, "roleListItem": { diff --git a/data/model/inspectors/organization.mod/organization.js b/data/model/inspectors/organization.mod/organization.js index 272fae377..088da10d7 100644 --- a/data/model/inspectors/organization.mod/organization.js +++ b/data/model/inspectors/organization.mod/organization.js @@ -42,7 +42,6 @@ exports.Organization = class Organization extends Component { this.dispatchEventNamed("cascadingListPush", true, false, obj); } - #buildJobRolesFromDepartment(department) { return DataService.mainService .updateObjectProperties(department, "suborganizations") diff --git a/data/model/party/organization-cascading-list-ui-descriptor.mjson b/data/model/party/organization-cascading-list-ui-descriptor.mjson index 2e9a9f463..bead058b3 100644 --- a/data/model/party/organization-cascading-list-ui-descriptor.mjson +++ b/data/model/party/organization-cascading-list-ui-descriptor.mjson @@ -2,8 +2,8 @@ "root": { "prototype": "core/meta/user-interface-descriptor", "values": { - "cascadingListItemHeaderRightCollectionNameExpression": "'Add'", - "cascadingListItemHeaderRightNameExpression": "isNew ? '' : 'Edit'", + "cascadingListItemHeaderRightCollectionNameExpression": "", + "cascadingListItemHeaderRightNameExpression": "'Add'", "cascadingListItemFooterMiddleCollectionNameExpression": "length + ' item' + (length == 1 ? '' : 's')" } } From 9359e17cc0b16c3a5847367a3dac07fe66753cd4 Mon Sep 17 00:00:00 2001 From: Benoit Marchant Date: Mon, 10 Aug 2026 23:34:18 -0700 Subject: [PATCH 7/8] remove extraneous line --- ui/action-target.mod/action-target.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/action-target.mod/action-target.js b/ui/action-target.mod/action-target.js index f7f71410b..04f4a93ff 100644 --- a/ui/action-target.mod/action-target.js +++ b/ui/action-target.mod/action-target.js @@ -17,7 +17,6 @@ var Component = require("../component").Component, * @extends Control */ var ActionTarget = exports.ActionTarget = Control.specialize( /** @lends ActionTarget.prototype # */ { - hasTemplate: { value: false From 9d4fa8853a07b10ced2cd055a46eec502a2482b8 Mon Sep 17 00:00:00 2001 From: Benoit Marchant Date: Mon, 10 Aug 2026 23:36:25 -0700 Subject: [PATCH 8/8] add TODO to comment --- ui/cascading-list.mod/cascading-list.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/cascading-list.mod/cascading-list.js b/ui/cascading-list.mod/cascading-list.js index 7afa96561..11ecf24af 100644 --- a/ui/cascading-list.mod/cascading-list.js +++ b/ui/cascading-list.mod/cascading-list.js @@ -245,10 +245,12 @@ CascadingList.addClassProperties( { var self = this; if(Array.isArray(object)){ + //TODO: //1) Find the highest common ancestor with existing object descriptor among all instances in the array //2) Grab UI descriptor for that ancestor } else{ + //TODO: //1) Refactor below to be used in both cases once UI descriptor is obtained }