@memberjunction/ng-explorer-settings 1.8.1 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,23 +6,23 @@ export declare class ApplicationEntityEntity_Ext extends ApplicationEntityEntity
6
6
  private _selected;
7
7
  get Selected(): boolean;
8
8
  set Selected(value: boolean);
9
- private _applicationName;
10
- get SavedApplicationName(): string;
11
- set SavedApplicationName(value: string);
9
+ private _applicationID;
10
+ get SavedApplicationID(): string;
11
+ set SavedApplicationID(value: string);
12
12
  private _entityID;
13
- get SavedEntityID(): number;
14
- set SavedEntityID(value: number);
13
+ get SavedEntityID(): string;
14
+ set SavedEntityID(value: string);
15
15
  }
16
16
  export declare class ApplicationEntitiesGridComponent implements OnInit, OnChanges {
17
17
  private router;
18
18
  /**
19
19
  * The name of the application we are working with, required if Mode is 'Applications'
20
20
  */
21
- ApplicationName: string;
21
+ ApplicationID: string;
22
22
  /**
23
23
  * The ID of the entity we are working with, required if Mode is 'Entities'
24
24
  */
25
- EntityID: number;
25
+ EntityID: string;
26
26
  isLoading: boolean;
27
27
  rows: ApplicationEntityEntity_Ext[];
28
28
  Mode: 'Applications' | 'Entities';
@@ -45,5 +45,5 @@ export declare class ApplicationEntitiesGridComponent implements OnInit, OnChang
45
45
  protected IsReallyDirty(ae: ApplicationEntityEntity_Ext): boolean;
46
46
  flipState($event: MouseEvent | undefined, ur: ApplicationEntityEntity_Ext, flipState: boolean): void;
47
47
  static ɵfac: i0.ɵɵFactoryDeclaration<ApplicationEntitiesGridComponent, never>;
48
- static ɵcmp: i0.ɵɵComponentDeclaration<ApplicationEntitiesGridComponent, "mj-application-entities-grid", never, { "ApplicationName": { "alias": "ApplicationName"; "required": false; }; "EntityID": { "alias": "EntityID"; "required": false; }; "Mode": { "alias": "Mode"; "required": false; }; "ApplicationRecord": { "alias": "ApplicationRecord"; "required": false; }; "EntityRecord": { "alias": "EntityRecord"; "required": false; }; }, {}, never, never, false, never>;
48
+ static ɵcmp: i0.ɵɵComponentDeclaration<ApplicationEntitiesGridComponent, "mj-application-entities-grid", never, { "ApplicationID": { "alias": "ApplicationID"; "required": false; }; "EntityID": { "alias": "EntityID"; "required": false; }; "Mode": { "alias": "Mode"; "required": false; }; "ApplicationRecord": { "alias": "ApplicationRecord"; "required": false; }; "EntityRecord": { "alias": "EntityRecord"; "required": false; }; }, {}, never, never, false, never>;
49
49
  }
@@ -121,8 +121,8 @@ let ApplicationEntityEntity_Ext = class ApplicationEntityEntity_Ext extends Appl
121
121
  constructor() {
122
122
  super(...arguments);
123
123
  this._selected = false;
124
- this._applicationName = '';
125
- this._entityID = 0;
124
+ this._applicationID = '';
125
+ this._entityID = "";
126
126
  }
127
127
  get Selected() {
128
128
  return this._selected;
@@ -130,11 +130,11 @@ let ApplicationEntityEntity_Ext = class ApplicationEntityEntity_Ext extends Appl
130
130
  set Selected(value) {
131
131
  this._selected = value;
132
132
  }
133
- get SavedApplicationName() {
134
- return this._applicationName;
133
+ get SavedApplicationID() {
134
+ return this._applicationID;
135
135
  }
136
- set SavedApplicationName(value) {
137
- this._applicationName = value;
136
+ set SavedApplicationID(value) {
137
+ this._applicationID = value;
138
138
  }
139
139
  get SavedEntityID() {
140
140
  return this._entityID;
@@ -171,16 +171,17 @@ export class ApplicationEntitiesGridComponent {
171
171
  }
172
172
  Refresh() {
173
173
  return __awaiter(this, void 0, void 0, function* () {
174
+ var _a, _b;
174
175
  if (this.Mode === 'Applications')
175
- if (!this.ApplicationName || this.ApplicationName.length === 0 || !this.ApplicationRecord)
176
- throw new Error("ApplicationName and ApplicationRecord are required when Mode is 'Applications'");
176
+ if (!this.ApplicationID || this.ApplicationID.length === 0 || !this.ApplicationRecord)
177
+ throw new Error("ApplicationID and ApplicationRecord are required when Mode is 'Applications'");
177
178
  if (this.Mode === 'Entities')
178
179
  if (!this.EntityID || !this.EntityRecord)
179
180
  throw new Error("EntityID and EntityRecord are required when Mode is 'Entities'");
180
181
  const md = new Metadata();
181
182
  this.isLoading = true;
182
183
  const rv = new RunView();
183
- const filter = this.Mode === 'Applications' ? `Application='${this.ApplicationName}'` : `EntityID=${this.EntityID}`;
184
+ const filter = this.Mode === 'Applications' ? `ApplicationID='${this.ApplicationID}'` : `EntityID='${this.EntityID}'`;
184
185
  const result = yield rv.RunView({
185
186
  EntityName: 'Application Entities',
186
187
  ExtraFilter: filter,
@@ -192,7 +193,7 @@ export class ApplicationEntitiesGridComponent {
192
193
  existing.forEach(ae => {
193
194
  ae.Selected = true; // flip this on for all records that come from the DB
194
195
  ae.SavedEntityID = ae.EntityID; // stash this in an extra property so we can later set it if we have a delete operation
195
- ae.SavedApplicationName = ae.Application; // stash this in an extra property so we can later set it if we have a delete operation
196
+ ae.SavedApplicationID = ae.ApplicationID; // stash this in an extra property so we can later set it if we have a delete operation
196
197
  });
197
198
  if (this.Mode === 'Applications') {
198
199
  const entitiesToAdd = md.Entities.filter(e => !existing.some(ee => ee.EntityID === e.ID));
@@ -201,9 +202,9 @@ export class ApplicationEntitiesGridComponent {
201
202
  ae.NewRecord();
202
203
  ae.Sequence = 1000; // default value, isn't used anywhere
203
204
  ae.DefaultForNewUser = false; // not used anywhere
204
- ae.ApplicationName = this.ApplicationName;
205
- ae.Set('Application', this.ApplicationName); // use weak typing to get around the readonly property
206
- ae.SavedApplicationName = this.ApplicationName; // stash this in an extra property so we can later set it if we have a delete operation
205
+ ae.ApplicationID = this.ApplicationID;
206
+ ae.Set('Application', (_a = this.ApplicationRecord) === null || _a === void 0 ? void 0 : _a.Name); // use weak typing to get around the readonly property
207
+ ae.SavedApplicationID = this.ApplicationID; // stash this in an extra property so we can later set it if we have a delete operation
207
208
  ae.EntityID = e.ID;
208
209
  ae.SavedEntityID = e.ID; // stash this in an extra property so we can later set it if we have a delete operation
209
210
  ae.Set('Entity', e.Name); // use weak typing to get around the readonly property
@@ -219,12 +220,12 @@ export class ApplicationEntitiesGridComponent {
219
220
  const ae = yield md.GetEntityObject('Application Entities');
220
221
  ae.NewRecord();
221
222
  ae.Sequence = 1000; // default value, isn't used anywhere
222
- ae.ApplicationName = a.Name;
223
+ ae.ApplicationID = a.ID;
223
224
  ae.Set('Application', a.Name); // use weak typing to get around the readonly property
224
- ae.SavedApplicationName = a.Name; // stash this in an extra property so we can later set it if we have a delete operation
225
+ ae.SavedApplicationID = a.ID; // stash this in an extra property so we can later set it if we have a delete operation
225
226
  ae.EntityID = this.EntityID;
226
227
  ae.SavedEntityID = this.EntityID; // stash this in an extra property so we can later set it if we have a delete operation
227
- ae.Set('Entity', this.EntityRecord.Name); // use weak typing to get around the readonly property
228
+ ae.Set('Entity', (_b = this.EntityRecord) === null || _b === void 0 ? void 0 : _b.Name); // use weak typing to get around the readonly property
228
229
  existing.push(ae);
229
230
  }
230
231
  // finally sort the array
@@ -260,9 +261,10 @@ export class ApplicationEntitiesGridComponent {
260
261
  if (yield tg.Submit()) {
261
262
  // for any items in the above that were deleted, we would have had the ApplicationName/Application and Entity property wiped out so we need to go check to see if we have a null ID and if so, copy the values back in
262
263
  this.rows.forEach(r => {
263
- if (r.Application === null || r.ApplicationName === null) {
264
- r.Set('Application', r.SavedApplicationName); // get around the read-only property
265
- r.ApplicationName = r.SavedApplicationName;
264
+ if (r.Application === null || r.ApplicationID === null) {
265
+ const a = md.Applications.find(aa => aa.ID === r.SavedApplicationID);
266
+ r.Set('Application', a === null || a === void 0 ? void 0 : a.Name); // get around the read-only property
267
+ r.ApplicationID = r.SavedApplicationID;
266
268
  }
267
269
  if (r.Entity === null || r.EntityID === null) {
268
270
  r.EntityID = r.SavedEntityID; // get around the read-only property
@@ -306,9 +308,9 @@ export class ApplicationEntitiesGridComponent {
306
308
  }
307
309
  IsReallyDirty(ae) {
308
310
  // logic is simple, if we are in the database, but the checkbox is not checked (or vice versa), then we are dirty
309
- if (ae.Selected && ae.ID > 0)
311
+ if (ae.Selected && ae.IsSaved)
310
312
  return false; // if we are in the database and the checkbox is checked, we are not dirty
311
- else if (!ae.Selected && ae.ID > 0)
313
+ else if (!ae.Selected && ae.IsSaved)
312
314
  return true; // if we are in the database and the checkbox is not checked, we are dirty because we'd have to be removed
313
315
  else if (ae.Selected)
314
316
  return true; // if we are NOT in the database and the checkbox is checked, we are dirty because we'd have to be added
@@ -323,7 +325,7 @@ export class ApplicationEntitiesGridComponent {
323
325
  }
324
326
  }
325
327
  ApplicationEntitiesGridComponent.ɵfac = function ApplicationEntitiesGridComponent_Factory(t) { return new (t || ApplicationEntitiesGridComponent)(i0.ɵɵdirectiveInject(i1.Router)); };
326
- ApplicationEntitiesGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ApplicationEntitiesGridComponent, selectors: [["mj-application-entities-grid"]], inputs: { ApplicationName: "ApplicationName", EntityID: "EntityID", Mode: "Mode", ApplicationRecord: "ApplicationRecord", EntityRecord: "EntityRecord" }, features: [i0.ɵɵNgOnChangesFeature], decls: 2, vars: 2, consts: [[4, "ngIf"], ["class", "content", 4, "ngIf"], [1, "content"], ["kendoButton", "", 3, "click", "disabled"], ["class", "grid", 4, "ngIf"], [1, "grid"], [3, "click"], [4, "ngFor", "ngForOf"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModelChange", "click", "ngModel"]], template: function ApplicationEntitiesGridComponent_Template(rf, ctx) { if (rf & 1) {
328
+ ApplicationEntitiesGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ApplicationEntitiesGridComponent, selectors: [["mj-application-entities-grid"]], inputs: { ApplicationID: "ApplicationID", EntityID: "EntityID", Mode: "Mode", ApplicationRecord: "ApplicationRecord", EntityRecord: "EntityRecord" }, features: [i0.ɵɵNgOnChangesFeature], decls: 2, vars: 2, consts: [[4, "ngIf"], ["class", "content", 4, "ngIf"], [1, "content"], ["kendoButton", "", 3, "click", "disabled"], ["class", "grid", 4, "ngIf"], [1, "grid"], [3, "click"], [4, "ngFor", "ngForOf"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModelChange", "click", "ngModel"]], template: function ApplicationEntitiesGridComponent_Template(rf, ctx) { if (rf & 1) {
327
329
  i0.ɵɵtemplate(0, ApplicationEntitiesGridComponent_div_0_Template, 2, 0, "div", 0)(1, ApplicationEntitiesGridComponent_div_1_Template, 6, 3, "div", 1);
328
330
  } if (rf & 2) {
329
331
  i0.ɵɵproperty("ngIf", ctx.isLoading);
@@ -333,7 +335,7 @@ ApplicationEntitiesGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({
333
335
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ApplicationEntitiesGridComponent, [{
334
336
  type: Component,
335
337
  args: [{ selector: 'mj-application-entities-grid', template: "<div *ngIf=\"isLoading\"><kendo-loader></kendo-loader></div>\n<div class=\"content\" *ngIf=\"!isLoading\">\n <button [disabled]=\"NumDirty === 0\" kendoButton (click)=\"save()\">Save</button>\n <button [disabled]=\"NumDirty === 0\" kendoButton (click)=\"cancelEdit()\">Cancel</button>\n <table *ngIf=\"!isLoading\" class=\"grid\">\n <thead>\n <tr>\n <th *ngIf=\"Mode === 'Applications'\">Entity</th>\n <th *ngIf=\"Mode === 'Entities'\">Application</th>\n <th (click)=\"flipAll()\">In Application</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let r of rows\">\n <td *ngIf=\"Mode === 'Applications'\">{{ r.Entity }}</td>\n <td *ngIf=\"Mode === 'Entities'\">{{ r.Application }}</td>\n <td (click)=\"flipState($event, r, true)\">\n <input type=\"checkbox\" kendoCheckBox [(ngModel)]=\"r.Selected\" (click)=\"flipState($event, r, false)\">\n </td>\n </tr>\n </tbody>\n </table> \n</div>", styles: ["button {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n/* Styles for the table with the 'grid' class */\n.grid {\n margin-left: 5px;\n margin-top: 5px;\n border-collapse: collapse;\n}\n\n/* Styles for th elements within the table with the 'grid' class */\n.grid th {\n background-color: #f2f2f2;\n color: black;\n font-weight: bold;\n text-align: center;\n border: 1px solid gray;\n padding: 0 8px;\n cursor: pointer;\n}\n\n/* Styles for td elements within the table with the 'grid' class */\n.grid td {\n border: 1px solid gray;\n height: 36px;\n text-align: center;\n padding: 0 8px;\n}\n\n/* Styles for the first child th and td within the table with the 'grid' class */\n.grid th:first-child,\n.grid td:first-child {\n min-width: 150px;\n text-align: left;\n}\n\n/* Styles for non-first-child th and td elements within the table with the 'grid' class */\n.grid th:not(:first-child),\n.grid td:not(:first-child) {\n width: 100px;\n}\n\n/* Alternating row background colors for the table with the 'grid' class */\n.grid tr:nth-child(odd) {\n background-color: white;\n}\n\n.grid tr:nth-child(even) {\n background-color: #e7f4ff;\n}\n\n"] }]
336
- }], () => [{ type: i1.Router }], { ApplicationName: [{
338
+ }], () => [{ type: i1.Router }], { ApplicationID: [{
337
339
  type: Input
338
340
  }], EntityID: [{
339
341
  type: Input
@@ -1,6 +1,7 @@
1
1
  import { OnInit } from '@angular/core';
2
2
  import { ActivatedRoute, Router } from '@angular/router';
3
3
  import { BaseEntity } from '@memberjunction/core';
4
+ import { BaseNavigationComponent } from '@memberjunction/ng-shared';
4
5
  import * as i0 from "@angular/core";
5
6
  export declare enum SettingsItem {
6
7
  EntityPermissions = "EntityPermissions",
@@ -11,14 +12,15 @@ export declare enum SettingsItem {
11
12
  Applications = "Applications",
12
13
  Application = "Application"
13
14
  }
14
- export declare class SettingsComponent implements OnInit {
15
+ export declare class SettingsComponent extends BaseNavigationComponent implements OnInit {
15
16
  private router;
16
17
  private activatedRoute;
17
18
  currentItem: SettingsItem;
18
19
  baseRoute: string;
19
- selectedRoleName: string;
20
- selectedUserID: number;
20
+ selectedRoleID: string;
21
+ selectedUserID: string;
21
22
  selectedApplicationName: string;
23
+ selectedApplicationID: string;
22
24
  options: {
23
25
  label: string;
24
26
  value: SettingsItem;
@@ -30,7 +32,7 @@ export declare class SettingsComponent implements OnInit {
30
32
  updateComponentStateBasedOnPath(): void;
31
33
  selectApplication(a: BaseEntity): void;
32
34
  selectRole(r: BaseEntity): void;
33
- selectUser(r: BaseEntity): void;
35
+ selectUser(u: BaseEntity): void;
34
36
  selectRoute(route: string, value: any): void;
35
37
  leftNavItemSelected(option: {
36
38
  label: string;
@@ -1,5 +1,14 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
1
7
  import { Component } from '@angular/core';
2
8
  import { NavigationEnd } from '@angular/router';
9
+ import { Metadata } from '@memberjunction/core';
10
+ import { RegisterClass } from '@memberjunction/global';
11
+ import { BaseNavigationComponent } from '@memberjunction/ng-shared';
3
12
  import { filter } from 'rxjs/operators';
4
13
  import * as i0 from "@angular/core";
5
14
  import * as i1 from "@angular/router";
@@ -54,7 +63,7 @@ function SettingsComponent_Case_8_Template(rf, ctx) { if (rf & 1) {
54
63
  i0.ɵɵelement(0, "mj-single-role", 7);
55
64
  } if (rf & 2) {
56
65
  const ctx_r2 = i0.ɵɵnextContext();
57
- i0.ɵɵproperty("RoleName", ctx_r2.selectedRoleName);
66
+ i0.ɵɵproperty("RoleID", ctx_r2.selectedRoleID);
58
67
  } }
59
68
  function SettingsComponent_Case_9_Template(rf, ctx) { if (rf & 1) {
60
69
  const _r6 = i0.ɵɵgetCurrentView();
@@ -68,7 +77,7 @@ function SettingsComponent_Case_10_Template(rf, ctx) { if (rf & 1) {
68
77
  i0.ɵɵelement(0, "mj-single-application", 9);
69
78
  } if (rf & 2) {
70
79
  const ctx_r2 = i0.ɵɵnextContext();
71
- i0.ɵɵproperty("ApplicationName", ctx_r2.selectedApplicationName);
80
+ i0.ɵɵproperty("ApplicationID", ctx_r2.selectedApplicationID);
72
81
  } }
73
82
  export var SettingsItem;
74
83
  (function (SettingsItem) {
@@ -80,7 +89,7 @@ export var SettingsItem;
80
89
  SettingsItem["Applications"] = "Applications";
81
90
  SettingsItem["Application"] = "Application";
82
91
  })(SettingsItem || (SettingsItem = {}));
83
- export class SettingsComponent {
92
+ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent {
84
93
  selectItem(item, changeRoute = true) {
85
94
  if (typeof item === 'string')
86
95
  this.currentItem = SettingsItem[item];
@@ -94,13 +103,15 @@ export class SettingsComponent {
94
103
  this.router.navigate([this.baseRoute, subPath]);
95
104
  }
96
105
  constructor(router, activatedRoute) {
106
+ super();
97
107
  this.router = router;
98
108
  this.activatedRoute = activatedRoute;
99
109
  this.currentItem = SettingsItem.Users;
100
110
  this.baseRoute = '/settings';
101
- this.selectedRoleName = '';
102
- this.selectedUserID = 0;
111
+ this.selectedRoleID = '';
112
+ this.selectedUserID = "";
103
113
  this.selectedApplicationName = '';
114
+ this.selectedApplicationID = '';
104
115
  this.options = [
105
116
  { label: 'Users', value: SettingsItem.Users },
106
117
  { label: 'Roles', value: SettingsItem.Roles },
@@ -117,6 +128,7 @@ export class SettingsComponent {
117
128
  });
118
129
  }
119
130
  updateComponentStateBasedOnPath() {
131
+ var _a, _b;
120
132
  // On each navigation end, access the current URL from window.location
121
133
  const fullPath = window.location.pathname + window.location.search;
122
134
  // Split the fullPath into segments and query string as needed
@@ -132,20 +144,22 @@ export class SettingsComponent {
132
144
  break;
133
145
  case 'application':
134
146
  this.selectedApplicationName = segments.length > 2 ? segments[2] : '';
147
+ const md = new Metadata();
148
+ this.selectedApplicationID = (_b = (_a = md.Applications.find(a => a.Name === this.selectedApplicationName)) === null || _a === void 0 ? void 0 : _a.ID) !== null && _b !== void 0 ? _b : '';
135
149
  this.selectItem(SettingsItem.Application, false);
136
150
  break;
137
151
  case 'users':
138
152
  this.selectItem(SettingsItem.Users, false);
139
153
  break;
140
154
  case 'user':
141
- this.selectedUserID = segments.length > 2 ? parseInt(segments[2]) : 0;
155
+ this.selectedUserID = segments.length > 2 ? segments[2] : "";
142
156
  this.selectItem(SettingsItem.User, false);
143
157
  break;
144
158
  case 'roles':
145
159
  this.selectItem(SettingsItem.Roles, false);
146
160
  break;
147
161
  case 'role':
148
- this.selectedRoleName = segments.length > 2 ? segments[2] : '';
162
+ this.selectedRoleID = segments.length > 2 ? segments[2] : '';
149
163
  this.selectItem(SettingsItem.Role, false);
150
164
  break;
151
165
  default:
@@ -156,10 +170,10 @@ export class SettingsComponent {
156
170
  this.selectRoute('/settings/application', a.Name);
157
171
  }
158
172
  selectRole(r) {
159
- this.selectRoute('/settings/role', r.Name);
173
+ this.selectRoute('/settings/role', r.ID);
160
174
  }
161
- selectUser(r) {
162
- this.selectRoute('/settings/user', r.ID);
175
+ selectUser(u) {
176
+ this.selectRoute('/settings/user', u.ID);
163
177
  }
164
178
  selectRoute(route, value) {
165
179
  this.router.navigate([route, value]);
@@ -169,9 +183,9 @@ export class SettingsComponent {
169
183
  // for example for Application/Applications we want to match so the left nav item is highlighted
170
184
  return option.value === this.currentItem || option.value === this.currentItem + 's';
171
185
  }
172
- }
186
+ };
173
187
  SettingsComponent.ɵfac = function SettingsComponent_Factory(t) { return new (t || SettingsComponent)(i0.ɵɵdirectiveInject(i1.Router), i0.ɵɵdirectiveInject(i1.ActivatedRoute)); };
174
- SettingsComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsComponent, selectors: [["mj-settings"]], decls: 11, vars: 6, consts: [["mjFillContainer", "", 1, "container", 3, "bottomMargin", "rightMargin"], ["mjFillContainer", "", 1, "options-container", 3, "fillWidth"], ["class", "option-item", 3, "selected", "click", 4, "ngFor", "ngForOf"], ["mjFillContainer", "", 1, "display-container", 3, "fillWidth"], ["EntityName", "Users", "SortBy", "Name", 3, "Columns"], [3, "UserID"], ["EntityName", "Roles", "SortBy", "Name", 3, "Columns"], ["mjFillContainer", "", 3, "RoleName"], ["EntityName", "Applications", "SortBy", "Name", 3, "Columns"], [3, "ApplicationName"], [1, "option-item", 3, "click"], ["EntityName", "Users", "SortBy", "Name", 3, "RecordSelected", "Columns"], ["EntityName", "Roles", "SortBy", "Name", 3, "RecordSelected", "Columns"], ["EntityName", "Applications", "SortBy", "Name", 3, "RecordSelected", "Columns"]], template: function SettingsComponent_Template(rf, ctx) { if (rf & 1) {
188
+ SettingsComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsComponent, selectors: [["mj-settings"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 11, vars: 6, consts: [["mjFillContainer", "", 1, "container", 3, "bottomMargin", "rightMargin"], ["mjFillContainer", "", 1, "options-container", 3, "fillWidth"], ["class", "option-item", 3, "selected", "click", 4, "ngFor", "ngForOf"], ["mjFillContainer", "", 1, "display-container", 3, "fillWidth"], ["EntityName", "Users", "SortBy", "Name", 3, "Columns"], [3, "UserID"], ["EntityName", "Roles", "SortBy", "Name", 3, "Columns"], ["mjFillContainer", "", 3, "RoleID"], ["EntityName", "Applications", "SortBy", "Name", 3, "Columns"], [3, "ApplicationID"], [1, "option-item", 3, "click"], ["EntityName", "Users", "SortBy", "Name", 3, "RecordSelected", "Columns"], ["EntityName", "Roles", "SortBy", "Name", 3, "RecordSelected", "Columns"], ["EntityName", "Applications", "SortBy", "Name", 3, "RecordSelected", "Columns"]], template: function SettingsComponent_Template(rf, ctx) { if (rf & 1) {
175
189
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1);
176
190
  i0.ɵɵtemplate(2, SettingsComponent_div_2_Template, 2, 3, "div", 2);
177
191
  i0.ɵɵelementEnd();
@@ -190,8 +204,12 @@ SettingsComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsC
190
204
  i0.ɵɵadvance();
191
205
  i0.ɵɵconditional((tmp_5_0 = ctx.currentItem) === "EntityPermissions" ? 4 : tmp_5_0 === "Users" ? 5 : tmp_5_0 === "User" ? 6 : tmp_5_0 === "Roles" ? 7 : tmp_5_0 === "Role" ? 8 : tmp_5_0 === "Applications" ? 9 : tmp_5_0 === "Application" ? 10 : -1);
192
206
  } }, dependencies: [i2.NgForOf, i3.FillContainer, i4.EntityPermissionsSelectorWithGridComponent, i5.SimpleRecordListComponent, i6.SingleRoleComponent, i7.SingleUserComponent, i8.SingleApplicationComponent], styles: [".container[_ngcontent-%COMP%] {\n display: block;\n width: 100%;\n overflow: hidden; \n}\n\n.options-container[_ngcontent-%COMP%] {\n float: left; \n\n width: 150px; \n\n flex: 0 0 150px;\n padding: 10px;\n border-right: solid 1px lightgray;\n box-sizing: border-box; \n\n}\n\n.option-item[_ngcontent-%COMP%] {\n cursor: pointer;\n margin-bottom: 10px; \n\n padding: 5px 10px; \n\n border-radius: 4px; \n\n}\n\n.display-container[_ngcontent-%COMP%] {\n display: block; \n\n margin-left: 160px; \n\n padding: 10px;\n box-sizing: border-box; \n\n}\n\n.selected[_ngcontent-%COMP%] {\n background-color: #007bff; \n\n color: white; \n\n padding: 5px 10px; \n\n border-radius: 4px; \n\n}"] });
207
+ SettingsComponent = __decorate([
208
+ RegisterClass(BaseNavigationComponent, 'Settings')
209
+ ], SettingsComponent);
210
+ export { SettingsComponent };
193
211
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SettingsComponent, [{
194
212
  type: Component,
195
- args: [{ selector: 'mj-settings', template: "<div class=\"container\" mjFillContainer [bottomMargin]=\"5\" [rightMargin]=\"0\">\n <!-- Options container -->\n <div class=\"options-container\" mjFillContainer [fillWidth]=\"false\">\n <div *ngFor=\"let o of options\"\n class=\"option-item\"\n [class.selected]=\"leftNavItemSelected(o)\"\n (click)=\"selectItem(o.value)\"\n >{{o.label}}</div>\n </div>\n\n <!-- Display container -->\n <div class=\"display-container\" mjFillContainer [fillWidth]=\"false\">\n <!-- <mj-join-grid\n RowsEntityName=\"Entities\"\n RowsEntityDisplayField=\"Name\"\n RowsEntityDataSource=\"FullEntity\"\n RowsExtraFilter=\"SchemaName <> '__mj' AND (Name like 'a%' or Name like 'p%')\"\n RowsOrderBy=\"Name\"\n ColumnsEntityName=\"Actions\"\n ColumnsEntityDisplayField=\"Name\"\n ColumnsEntityDataSource= \"FullEntity\"\n ColumnsMode=\"Entity\"\n ColumnsExtraFilter=\"Name like 'v%' or Name like 'd%' or Name like 'test%'\"\n ColumnsOrderBy=\"Name\"\n JoinEntityName=\"Entity Actions\"\n JoinEntityRowForeignKey=\"EntityID\"\n JoinEntityColumnForeignKey=\"ActionID\"\n CheckBoxValueMode=\"RecordExists\"\n \n style=\"height: 750px; width: 800px;\"\n >\n\n </mj-join-grid> -->\n @switch (currentItem) {\n @case ('EntityPermissions') {\n <mj-entity-permissions-selector-with-grid></mj-entity-permissions-selector-with-grid>\n }\n @case ('Users') {\n <mj-simple-record-list\n EntityName=\"Users\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Email', 'IsActive', 'Type']\"\n (RecordSelected)=\"selectUser($event)\"\n ></mj-simple-record-list>\n }\n @case ('User') {\n <mj-single-user [UserID]=\"selectedUserID\"></mj-single-user>\n }\n @case ('Roles') {\n <mj-simple-record-list\n EntityName=\"Roles\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Description']\"\n (RecordSelected)=\"selectRole($event)\"\n ></mj-simple-record-list>\n }\n @case ('Role') {\n <mj-single-role [RoleName]=\"selectedRoleName\" mjFillContainer></mj-single-role>\n }\n @case ('Applications') {\n <mj-simple-record-list\n EntityName=\"Applications\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Description']\"\n (RecordSelected)=\"selectApplication($event)\"\n ></mj-simple-record-list>\n }\n @case ('Application') {\n <mj-single-application [ApplicationName]=\"selectedApplicationName\"></mj-single-application>\n }\n }\n </div>\n</div>", styles: [".container {\n display: block;\n width: 100%;\n overflow: hidden; \n}\n\n.options-container {\n float: left; /* Float to the left */\n width: 150px; /* Fixed width as specified */\n flex: 0 0 150px;\n padding: 10px;\n border-right: solid 1px lightgray;\n box-sizing: border-box; /* Ensures padding is included in the width */\n}\n\n.option-item {\n cursor: pointer;\n margin-bottom: 10px; /* Adds space between the options for better readability */\n padding: 5px 10px; /* Optional: Adds some padding for a better visual appearance */\n border-radius: 4px; /* Optional: Adds rounded corners for a more polished look */\n}\n\n.display-container {\n display: block; /* Ensures it's treated as a block-level element */\n margin-left: 160px; /* Width of the options-container plus its padding */\n padding: 10px;\n box-sizing: border-box; /* Ensures padding doesn't add to the width */\n}\n\n.selected {\n background-color: #007bff; /* A blue background for selected item */\n color: white; /* White text color for better contrast */\n padding: 5px 10px; /* Optional: Adds some padding for a better visual appearance */\n border-radius: 4px; /* Optional: Adds rounded corners for a more polished look */\n}\n"] }]
213
+ args: [{ selector: 'mj-settings', template: "<div class=\"container\" mjFillContainer [bottomMargin]=\"5\" [rightMargin]=\"0\">\n <!-- Options container -->\n <div class=\"options-container\" mjFillContainer [fillWidth]=\"false\">\n <div *ngFor=\"let o of options\"\n class=\"option-item\"\n [class.selected]=\"leftNavItemSelected(o)\"\n (click)=\"selectItem(o.value)\"\n >{{o.label}}</div>\n </div>\n\n <!-- Display container -->\n <div class=\"display-container\" mjFillContainer [fillWidth]=\"false\">\n <!-- <mj-join-grid\n RowsEntityName=\"Entities\"\n RowsEntityDisplayField=\"Name\"\n RowsEntityDataSource=\"FullEntity\"\n RowsExtraFilter=\"SchemaName <> '__mj' AND (Name like 'a%' or Name like 'p%')\"\n RowsOrderBy=\"Name\"\n ColumnsEntityName=\"Actions\"\n ColumnsEntityDisplayField=\"Name\"\n ColumnsEntityDataSource= \"FullEntity\"\n ColumnsMode=\"Entity\"\n ColumnsExtraFilter=\"Name like 'v%' or Name like 'd%' or Name like 'test%'\"\n ColumnsOrderBy=\"Name\"\n JoinEntityName=\"Entity Actions\"\n JoinEntityRowForeignKey=\"EntityID\"\n JoinEntityColumnForeignKey=\"ActionID\"\n CheckBoxValueMode=\"RecordExists\"\n \n style=\"height: 750px; width: 800px;\"\n >\n\n </mj-join-grid> -->\n @switch (currentItem) {\n @case ('EntityPermissions') {\n <mj-entity-permissions-selector-with-grid></mj-entity-permissions-selector-with-grid>\n }\n @case ('Users') {\n <mj-simple-record-list\n EntityName=\"Users\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Email', 'IsActive', 'Type']\"\n (RecordSelected)=\"selectUser($event)\"\n ></mj-simple-record-list>\n }\n @case ('User') {\n <mj-single-user [UserID]=\"selectedUserID\"></mj-single-user>\n }\n @case ('Roles') {\n <mj-simple-record-list\n EntityName=\"Roles\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Description']\"\n (RecordSelected)=\"selectRole($event)\"\n ></mj-simple-record-list>\n }\n @case ('Role') {\n <mj-single-role [RoleID]=\"selectedRoleID\" mjFillContainer></mj-single-role>\n }\n @case ('Applications') {\n <mj-simple-record-list\n EntityName=\"Applications\"\n SortBy=\"Name\"\n [Columns]=\"['Name', 'Description']\"\n (RecordSelected)=\"selectApplication($event)\"\n ></mj-simple-record-list>\n }\n @case ('Application') {\n <mj-single-application [ApplicationID]=\"selectedApplicationID\"></mj-single-application>\n }\n }\n </div>\n</div>", styles: [".container {\n display: block;\n width: 100%;\n overflow: hidden; \n}\n\n.options-container {\n float: left; /* Float to the left */\n width: 150px; /* Fixed width as specified */\n flex: 0 0 150px;\n padding: 10px;\n border-right: solid 1px lightgray;\n box-sizing: border-box; /* Ensures padding is included in the width */\n}\n\n.option-item {\n cursor: pointer;\n margin-bottom: 10px; /* Adds space between the options for better readability */\n padding: 5px 10px; /* Optional: Adds some padding for a better visual appearance */\n border-radius: 4px; /* Optional: Adds rounded corners for a more polished look */\n}\n\n.display-container {\n display: block; /* Ensures it's treated as a block-level element */\n margin-left: 160px; /* Width of the options-container plus its padding */\n padding: 10px;\n box-sizing: border-box; /* Ensures padding doesn't add to the width */\n}\n\n.selected {\n background-color: #007bff; /* A blue background for selected item */\n color: white; /* White text color for better contrast */\n padding: 5px 10px; /* Optional: Adds some padding for a better visual appearance */\n border-radius: 4px; /* Optional: Adds rounded corners for a more polished look */\n}\n"] }]
196
214
  }], () => [{ type: i1.Router }, { type: i1.ActivatedRoute }], null); })();
197
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SettingsComponent, { className: "SettingsComponent", filePath: "src/lib/settings/settings.component.ts", lineNumber: 22 }); })();
215
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SettingsComponent, { className: "SettingsComponent", filePath: "src/lib/settings/settings.component.ts", lineNumber: 25 }); })();
@@ -4,7 +4,7 @@ import { EntityFormDialogComponent } from '@memberjunction/ng-entity-form-dialog
4
4
  import * as i0 from "@angular/core";
5
5
  export declare class SingleApplicationComponent implements OnInit {
6
6
  private cdRef;
7
- ApplicationName: string;
7
+ ApplicationID: string;
8
8
  entityFormComponent: EntityFormDialogComponent;
9
9
  gridHeight: number;
10
10
  isLoading: boolean;
@@ -16,5 +16,5 @@ export declare class SingleApplicationComponent implements OnInit {
16
16
  EditRecord(): Promise<void>;
17
17
  onEntityFormClosed(result: 'Save' | 'Cancel'): Promise<void>;
18
18
  static ɵfac: i0.ɵɵFactoryDeclaration<SingleApplicationComponent, never>;
19
- static ɵcmp: i0.ɵɵComponentDeclaration<SingleApplicationComponent, "mj-single-application", never, { "ApplicationName": { "alias": "ApplicationName"; "required": false; }; }, {}, never, never, false, never>;
19
+ static ɵcmp: i0.ɵɵComponentDeclaration<SingleApplicationComponent, "mj-single-application", never, { "ApplicationID": { "alias": "ApplicationID"; "required": false; }; }, {}, never, never, false, never>;
20
20
  }
@@ -24,7 +24,7 @@ function SingleApplicationComponent_Conditional_2_mj_application_entities_grid_1
24
24
  i0.ɵɵelement(0, "mj-application-entities-grid", 8);
25
25
  } if (rf & 2) {
26
26
  const ctx_r2 = i0.ɵɵnextContext(2);
27
- i0.ɵɵproperty("ApplicationName", ctx_r2.ApplicationName)("ApplicationRecord", ctx_r2.Record);
27
+ i0.ɵɵproperty("ApplicationID", ctx_r2.ApplicationID)("ApplicationRecord", ctx_r2.Record);
28
28
  } }
29
29
  function SingleApplicationComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
30
30
  const _r2 = i0.ɵɵgetCurrentView();
@@ -57,7 +57,7 @@ function SingleApplicationComponent_Conditional_2_Template(rf, ctx) { if (rf & 1
57
57
  i0.ɵɵadvance(2);
58
58
  i0.ɵɵproperty("TabSelected", true);
59
59
  i0.ɵɵadvance(3);
60
- i0.ɵɵproperty("ngIf", ctx_r2.ApplicationName && ctx_r2.Record);
60
+ i0.ɵɵproperty("ngIf", ctx_r2.ApplicationID && ctx_r2.Record);
61
61
  } }
62
62
  export class SingleApplicationComponent {
63
63
  constructor(cdRef) {
@@ -72,16 +72,16 @@ export class SingleApplicationComponent {
72
72
  }
73
73
  Refresh() {
74
74
  return __awaiter(this, void 0, void 0, function* () {
75
- if (this.ApplicationName && this.ApplicationName.length > 0) {
75
+ if (this.ApplicationID && this.ApplicationID.length > 0) {
76
76
  this.isLoading = true;
77
77
  const md = new Metadata();
78
- let a = md.Applications.find(a => a.Name === this.ApplicationName);
78
+ let a = md.Applications.find(a => a.ID === this.ApplicationID);
79
79
  if (!a) {
80
80
  // sometime we are creating a new role, so attempt to refresh our metadata
81
81
  yield md.Refresh();
82
- a = md.Applications.find(aa => aa.Name === this.ApplicationName);
82
+ a = md.Applications.find(aa => aa.ID === this.ApplicationID);
83
83
  if (!a)
84
- throw new Error(`Application ${this.ApplicationName} not found`);
84
+ throw new Error(`Application ID: ${this.ApplicationID} not found`);
85
85
  }
86
86
  this.Record = yield md.GetEntityObject('Applications');
87
87
  yield this.Record.Load(a.ID);
@@ -107,7 +107,7 @@ SingleApplicationComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type:
107
107
  } if (rf & 2) {
108
108
  let _t;
109
109
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.entityFormComponent = _t.first);
110
- } }, inputs: { ApplicationName: "ApplicationName" }, decls: 5, vars: 8, consts: [["entityForm", ""], ["mjFillContainer", ""], ["SectionName", "details", "Mode", "section", 3, "DialogClosed", "Record", "Visible", "AutoRevertOnCancel", "HandleSave", "Width", "Height"], [1, "info-table"], ["scope", "row"], [1, "edit-icon", "fa-solid", "fa-pen-to-square", 3, "click"], [3, "TabSelected"], ["Mode", "Applications", 3, "ApplicationName", "ApplicationRecord", 4, "ngIf"], ["Mode", "Applications", 3, "ApplicationName", "ApplicationRecord"]], template: function SingleApplicationComponent_Template(rf, ctx) { if (rf & 1) {
110
+ } }, inputs: { ApplicationID: "ApplicationID" }, decls: 5, vars: 8, consts: [["entityForm", ""], ["mjFillContainer", ""], ["SectionName", "details", "Mode", "section", 3, "DialogClosed", "Record", "Visible", "AutoRevertOnCancel", "HandleSave", "Width", "Height"], [1, "info-table"], ["scope", "row"], [1, "edit-icon", "fa-solid", "fa-pen-to-square", 3, "click"], [3, "TabSelected"], ["Mode", "Applications", 3, "ApplicationID", "ApplicationRecord", 4, "ngIf"], ["Mode", "Applications", 3, "ApplicationID", "ApplicationRecord"]], template: function SingleApplicationComponent_Template(rf, ctx) { if (rf & 1) {
111
111
  const _r1 = i0.ɵɵgetCurrentView();
112
112
  i0.ɵɵelementStart(0, "div", 1);
113
113
  i0.ɵɵtemplate(1, SingleApplicationComponent_Conditional_1_Template, 1, 0, "kendo-loader")(2, SingleApplicationComponent_Conditional_2_Template, 18, 4);
@@ -125,8 +125,8 @@ SingleApplicationComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type:
125
125
  } }, dependencies: [i1.NgIf, i2.FillContainer, i3.MJTabStripComponent, i3.MJTabBodyComponent, i3.MJTabComponent, i4.EntityFormDialogComponent, i5.LoaderComponent, i6.ApplicationEntitiesGridComponent], styles: ["button[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n\n\n.name[_ngcontent-%COMP%] {\n font-weight: bold;\n font-size: 20px;\n margin-left: 5px;\n margin-top: 5px;\n}\n\n.info-table[_ngcontent-%COMP%] {\n width: 100%; \n\n border-collapse: collapse; \n\n margin-bottom: 10px;\n}\n\n.info-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n width: 150px; \n\n font-weight: bold; \n\n text-align: left; \n\n padding: 8px; \n\n border: none; \n\n background-color: transparent; \n\n}\n\n.info-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n text-align: left; \n\n padding: 8px; \n\n border: none; \n\n background-color: transparent; \n\n overflow: hidden; \n\n text-overflow: ellipsis; \n\n}\n\n\n\n.edit-icon[_ngcontent-%COMP%] {\n margin-left: 20px; \n vertical-align: middle;;\n cursor: pointer; \n\n}\n\n.edit-icon[_ngcontent-%COMP%]:hover {\n fill: #007bff; \n\n}"] });
126
126
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SingleApplicationComponent, [{
127
127
  type: Component,
128
- args: [{ selector: 'mj-single-application', template: "<div mjFillContainer>\n @if(isLoading) {\n <kendo-loader></kendo-loader>\n }\n @if(!isLoading && Record) {\n <table class=\"info-table\">\n <tbody>\n <tr>\n <th scope=\"row\">Application</th>\n <td>{{Record.Name}}\n <span class=\"edit-icon fa-solid fa-pen-to-square\" (click)=\"EditRecord()\"></span>\n </td>\n </tr>\n <tr>\n <th scope=\"row\">Description</th>\n <td>{{Record.Description}}</td>\n </tr>\n </tbody>\n </table> \n <mj-tabstrip mjFillContainer>\n <mj-tab [TabSelected]=\"true\">\n Entities\n </mj-tab>\n <mj-tab-body>\n <mj-application-entities-grid *ngIf=\"ApplicationName && Record\" Mode=\"Applications\" [ApplicationName]=\"ApplicationName\" [ApplicationRecord]=\"Record\"></mj-application-entities-grid>\n </mj-tab-body>\n </mj-tabstrip>\n }\n</div>\n\n\n<mj-entity-form-dialog #entityForm \n [Record]=\"Record\" \n SectionName=\"details\" \n Mode=\"section\" \n [Visible]=\"showEntityEditingForm\" \n [AutoRevertOnCancel]=\"true\"\n [HandleSave]=\"true\"\n [Width]=\"550\"\n [Height]=\"450\"\n (DialogClosed)=\"onEntityFormClosed($event)\">\n</mj-entity-form-dialog>\n", styles: ["button {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n\n\n.name {\n font-weight: bold;\n font-size: 20px;\n margin-left: 5px;\n margin-top: 5px;\n}\n\n.info-table {\n width: 100%; /* Take up the full width of the container */\n border-collapse: collapse; /* For a cleaner look */\n margin-bottom: 10px;\n}\n\n.info-table th {\n width: 150px; /* Adjust this fixed width as needed */\n font-weight: bold; /* Make header labels bold */\n text-align: left; /* Align text to the left */\n padding: 8px; /* Add some padding for spacing */\n border: none; /* Removes the borders */\n background-color: transparent; /* Removes any background color */\n}\n\n.info-table td {\n text-align: left; /* Align text to the left */\n padding: 8px; /* Add some padding for spacing */\n border: none; /* Removes the borders */\n background-color: transparent; /* Removes any background color */\n overflow: hidden; /* Prevents content from overflowing */\n text-overflow: ellipsis; /* Adds an ellipsis if the text overflows */\n}\n\n/* Style for SVG icon */\n.edit-icon {\n margin-left: 20px; \n vertical-align: middle;;\n cursor: pointer; /* Changes the cursor to a pointer */\n}\n\n.edit-icon:hover {\n fill: #007bff; /* Changes the color on hover, set to the color you prefer */\n}"] }]
129
- }], () => [{ type: i0.ChangeDetectorRef }], { ApplicationName: [{
128
+ args: [{ selector: 'mj-single-application', template: "<div mjFillContainer>\n @if(isLoading) {\n <kendo-loader></kendo-loader>\n }\n @if(!isLoading && Record) {\n <table class=\"info-table\">\n <tbody>\n <tr>\n <th scope=\"row\">Application</th>\n <td>{{Record.Name}}\n <span class=\"edit-icon fa-solid fa-pen-to-square\" (click)=\"EditRecord()\"></span>\n </td>\n </tr>\n <tr>\n <th scope=\"row\">Description</th>\n <td>{{Record.Description}}</td>\n </tr>\n </tbody>\n </table> \n <mj-tabstrip mjFillContainer>\n <mj-tab [TabSelected]=\"true\">\n Entities\n </mj-tab>\n <mj-tab-body>\n <mj-application-entities-grid *ngIf=\"ApplicationID && Record\" Mode=\"Applications\" [ApplicationID]=\"ApplicationID\" [ApplicationRecord]=\"Record\"></mj-application-entities-grid>\n </mj-tab-body>\n </mj-tabstrip>\n }\n</div>\n\n\n<mj-entity-form-dialog #entityForm \n [Record]=\"Record\" \n SectionName=\"details\" \n Mode=\"section\" \n [Visible]=\"showEntityEditingForm\" \n [AutoRevertOnCancel]=\"true\"\n [HandleSave]=\"true\"\n [Width]=\"550\"\n [Height]=\"450\"\n (DialogClosed)=\"onEntityFormClosed($event)\">\n</mj-entity-form-dialog>\n", styles: ["button {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n\n\n.name {\n font-weight: bold;\n font-size: 20px;\n margin-left: 5px;\n margin-top: 5px;\n}\n\n.info-table {\n width: 100%; /* Take up the full width of the container */\n border-collapse: collapse; /* For a cleaner look */\n margin-bottom: 10px;\n}\n\n.info-table th {\n width: 150px; /* Adjust this fixed width as needed */\n font-weight: bold; /* Make header labels bold */\n text-align: left; /* Align text to the left */\n padding: 8px; /* Add some padding for spacing */\n border: none; /* Removes the borders */\n background-color: transparent; /* Removes any background color */\n}\n\n.info-table td {\n text-align: left; /* Align text to the left */\n padding: 8px; /* Add some padding for spacing */\n border: none; /* Removes the borders */\n background-color: transparent; /* Removes any background color */\n overflow: hidden; /* Prevents content from overflowing */\n text-overflow: ellipsis; /* Adds an ellipsis if the text overflows */\n}\n\n/* Style for SVG icon */\n.edit-icon {\n margin-left: 20px; \n vertical-align: middle;;\n cursor: pointer; /* Changes the cursor to a pointer */\n}\n\n.edit-icon:hover {\n fill: #007bff; /* Changes the color on hover, set to the color you prefer */\n}"] }]
129
+ }], () => [{ type: i0.ChangeDetectorRef }], { ApplicationID: [{
130
130
  type: Input
131
131
  }], entityFormComponent: [{
132
132
  type: ViewChild,
@@ -10,15 +10,15 @@ export declare class UserRoleEntity_Ext extends UserRoleEntity {
10
10
  get SavedUserName(): string;
11
11
  set SavedUserName(value: string);
12
12
  private _userID;
13
- get SavedUserID(): number;
14
- set SavedUserID(value: number);
15
- private _savedRoleName;
16
- get SavedRoleName(): string;
17
- set SavedRoleName(value: string);
13
+ get SavedUserID(): string;
14
+ set SavedUserID(value: string);
15
+ private _savedRoleID;
16
+ get SavedRoleID(): string;
17
+ set SavedRoleID(value: string);
18
18
  }
19
19
  export declare class SingleRoleComponent implements OnInit {
20
20
  private cdRef;
21
- RoleName: string;
21
+ RoleID: string;
22
22
  entityFormComponent: EntityFormDialogComponent;
23
23
  gridHeight: number;
24
24
  isLoading: boolean;
@@ -30,5 +30,5 @@ export declare class SingleRoleComponent implements OnInit {
30
30
  EditRecord(): Promise<void>;
31
31
  onEntityFormClosed(result: 'Save' | 'Cancel'): Promise<void>;
32
32
  static ɵfac: i0.ɵɵFactoryDeclaration<SingleRoleComponent, never>;
33
- static ɵcmp: i0.ɵɵComponentDeclaration<SingleRoleComponent, "mj-single-role", never, { "RoleName": { "alias": "RoleName"; "required": false; }; }, {}, never, never, false, never>;
33
+ static ɵcmp: i0.ɵɵComponentDeclaration<SingleRoleComponent, "mj-single-role", never, { "RoleID": { "alias": "RoleID"; "required": false; }; }, {}, never, never, false, never>;
34
34
  }
@@ -81,7 +81,7 @@ function SingleRoleComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
81
81
  i0.ɵɵadvance();
82
82
  i0.ɵɵproperty("bottomMargin", 150);
83
83
  i0.ɵɵadvance(4);
84
- i0.ɵɵproperty("RoleName", ctx_r2.RoleName)("RoleRecord", ctx_r2.RoleRecord);
84
+ i0.ɵɵproperty("RoleID", ctx_r2.RoleID)("RoleRecord", ctx_r2.RoleRecord);
85
85
  i0.ɵɵadvance(4);
86
86
  i0.ɵɵproperty("ngIf", ctx_r2.RoleRecord && ctx_r2.RoleRecord.Name);
87
87
  } }
@@ -90,8 +90,8 @@ let UserRoleEntity_Ext = class UserRoleEntity_Ext extends UserRoleEntity {
90
90
  super(...arguments);
91
91
  this._selected = false;
92
92
  this._userName = '';
93
- this._userID = 0;
94
- this._savedRoleName = '';
93
+ this._userID = "";
94
+ this._savedRoleID = '';
95
95
  }
96
96
  get Selected() {
97
97
  return this._selected;
@@ -111,11 +111,11 @@ let UserRoleEntity_Ext = class UserRoleEntity_Ext extends UserRoleEntity {
111
111
  set SavedUserID(value) {
112
112
  this._userID = value;
113
113
  }
114
- get SavedRoleName() {
115
- return this._savedRoleName;
114
+ get SavedRoleID() {
115
+ return this._savedRoleID;
116
116
  }
117
- set SavedRoleName(value) {
118
- this._savedRoleName = value;
117
+ set SavedRoleID(value) {
118
+ this._savedRoleID = value;
119
119
  }
120
120
  };
121
121
  UserRoleEntity_Ext = __decorate([
@@ -137,13 +137,13 @@ export class SingleRoleComponent {
137
137
  return __awaiter(this, void 0, void 0, function* () {
138
138
  this.isLoading = true;
139
139
  const md = new Metadata();
140
- let r = md.Roles.find(r => r.Name === this.RoleName);
140
+ let r = md.Roles.find(r => r.ID === this.RoleID);
141
141
  if (!r) {
142
142
  // sometime we are creating a new role, so attempt to refresh our metadata
143
143
  yield md.Refresh();
144
- r = md.Roles.find(r => r.Name === this.RoleName);
144
+ r = md.Roles.find(r => r.ID === this.RoleID);
145
145
  if (!r)
146
- throw new Error(`Role ${this.RoleName} not found`);
146
+ throw new Error(`Role ${this.RoleID} not found`);
147
147
  }
148
148
  this.RoleRecord = yield md.GetEntityObject('Roles');
149
149
  yield this.RoleRecord.Load(r.ID);
@@ -168,7 +168,7 @@ SingleRoleComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SingleR
168
168
  } if (rf & 2) {
169
169
  let _t;
170
170
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.entityFormComponent = _t.first);
171
- } }, inputs: { RoleName: "RoleName" }, decls: 5, vars: 8, consts: [["entityForm", ""], ["mjFillContainer", "", 1, "wrapper"], ["SectionName", "details", "Mode", "section", 3, "DialogClosed", "Record", "Visible", "AutoRevertOnCancel", "HandleSave", "Width", "Height"], [1, "role-info-table"], ["scope", "row"], [1, "fa-solid", "fa-pen-to-square", 3, "click"], ["mjFillContainer", "", 3, "bottomMargin"], ["Mode", "Roles", 3, "RoleName", "RoleRecord"], ["Mode", "Role", "mjFillContainer", "", 3, "RoleName", 4, "ngIf"], ["Mode", "Role", "mjFillContainer", "", 3, "RoleName"]], template: function SingleRoleComponent_Template(rf, ctx) { if (rf & 1) {
171
+ } }, inputs: { RoleID: "RoleID" }, decls: 5, vars: 8, consts: [["entityForm", ""], ["mjFillContainer", "", 1, "wrapper"], ["SectionName", "details", "Mode", "section", 3, "DialogClosed", "Record", "Visible", "AutoRevertOnCancel", "HandleSave", "Width", "Height"], [1, "role-info-table"], ["scope", "row"], [1, "fa-solid", "fa-pen-to-square", 3, "click"], ["mjFillContainer", "", 3, "bottomMargin"], ["Mode", "Roles", 3, "RoleID", "RoleRecord"], ["Mode", "Role", "mjFillContainer", "", 3, "RoleName", 4, "ngIf"], ["Mode", "Role", "mjFillContainer", "", 3, "RoleName"]], template: function SingleRoleComponent_Template(rf, ctx) { if (rf & 1) {
172
172
  const _r1 = i0.ɵɵgetCurrentView();
173
173
  i0.ɵɵelementStart(0, "div", 1);
174
174
  i0.ɵɵtemplate(1, SingleRoleComponent_Conditional_1_Template, 1, 0, "kendo-loader")(2, SingleRoleComponent_Conditional_2_Template, 32, 8);
@@ -186,8 +186,8 @@ SingleRoleComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SingleR
186
186
  } }, styles: [".wrapper[_ngcontent-%COMP%] {\n display: block;\n}\n\nbutton[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n\n\n.role-name[_ngcontent-%COMP%] {\n font-weight: bold;\n font-size: 20px;\n margin-left: 5px;\n margin-top: 5px;\n}\n\n.role-info-table[_ngcontent-%COMP%] {\n width: 100%; \n\n border-collapse: collapse; \n\n margin-bottom: 10px;\n}\n\n.role-info-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n width: 150px; \n\n font-weight: bold; \n\n text-align: left; \n\n padding: 8px; \n\n border: none; \n\n background-color: transparent; \n\n}\n\n.role-info-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n text-align: left; \n\n padding: 8px; \n\n border: none; \n\n background-color: transparent; \n\n overflow: hidden; \n\n text-overflow: ellipsis; \n\n}\n\n\n\n.edit-icon[_ngcontent-%COMP%] {\n margin-left: 20px; \n vertical-align: middle;;\n cursor: pointer; \n\n}\n\n.edit-icon[_ngcontent-%COMP%]:hover {\n fill: #007bff; \n\n}"] });
187
187
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SingleRoleComponent, [{
188
188
  type: Component,
189
- args: [{ selector: 'mj-single-role', template: "<div mjFillContainer class=\"wrapper\">\n @if(isLoading) {\n <kendo-loader></kendo-loader> \n }\n @if(!isLoading && RoleRecord) {\n <table class=\"role-info-table\">\n <tbody>\n <tr>\n <th scope=\"row\">Role</th>\n <td>\n {{RoleRecord.Name}}\n <span class=\"fa-solid fa-pen-to-square\" (click)=\"EditRecord()\"></span>\n </td>\n </tr>\n <tr>\n <th scope=\"row\">Description</th>\n <td>{{RoleRecord.Description}}</td>\n </tr>\n <tr>\n <th scope=\"row\">Directory ID</th>\n <td>{{RoleRecord.DirectoryID}}</td>\n </tr>\n <tr>\n <th scope=\"row\">SQL Name</th>\n <td>{{RoleRecord.SQLName}}</td>\n </tr>\n </tbody>\n </table> \n\n <mj-tabstrip mjFillContainer [bottomMargin]=\"150\">\n <mj-tab>\n Users\n </mj-tab>\n <mj-tab-body>\n <mj-user-roles-grid Mode=\"Roles\" [RoleName]=\"RoleName\" [RoleRecord]=\"RoleRecord\"></mj-user-roles-grid>\n </mj-tab-body>\n\n <mj-tab>\n Entity Permissions\n </mj-tab>\n <mj-tab-body>\n <mj-entity-permissions-grid *ngIf=\"RoleRecord && RoleRecord.Name\" Mode=\"Role\" [RoleName]=\"RoleRecord.Name\" mjFillContainer></mj-entity-permissions-grid>\n </mj-tab-body>\n </mj-tabstrip>\n }\n</div>\n \n<mj-entity-form-dialog #entityForm \n [Record]=\"RoleRecord\" \n SectionName=\"details\" \n Mode=\"section\" \n [Visible]=\"showEntityEditingForm\" \n [AutoRevertOnCancel]=\"true\"\n [HandleSave]=\"true\"\n [Width]=\"550\"\n [Height]=\"450\"\n (DialogClosed)=\"onEntityFormClosed($event)\">\n</mj-entity-form-dialog>\n", styles: [".wrapper {\n display: block;\n}\n\nbutton {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n\n\n.role-name {\n font-weight: bold;\n font-size: 20px;\n margin-left: 5px;\n margin-top: 5px;\n}\n\n.role-info-table {\n width: 100%; /* Take up the full width of the container */\n border-collapse: collapse; /* For a cleaner look */\n margin-bottom: 10px;\n}\n\n.role-info-table th {\n width: 150px; /* Adjust this fixed width as needed */\n font-weight: bold; /* Make header labels bold */\n text-align: left; /* Align text to the left */\n padding: 8px; /* Add some padding for spacing */\n border: none; /* Removes the borders */\n background-color: transparent; /* Removes any background color */\n}\n\n.role-info-table td {\n text-align: left; /* Align text to the left */\n padding: 8px; /* Add some padding for spacing */\n border: none; /* Removes the borders */\n background-color: transparent; /* Removes any background color */\n overflow: hidden; /* Prevents content from overflowing */\n text-overflow: ellipsis; /* Adds an ellipsis if the text overflows */\n}\n\n/* Style for SVG icon */\n.edit-icon {\n margin-left: 20px; \n vertical-align: middle;;\n cursor: pointer; /* Changes the cursor to a pointer */\n}\n\n.edit-icon:hover {\n fill: #007bff; /* Changes the color on hover, set to the color you prefer */\n}"] }]
190
- }], () => [{ type: i0.ChangeDetectorRef }], { RoleName: [{
189
+ args: [{ selector: 'mj-single-role', template: "<div mjFillContainer class=\"wrapper\">\n @if(isLoading) {\n <kendo-loader></kendo-loader> \n }\n @if(!isLoading && RoleRecord) {\n <table class=\"role-info-table\">\n <tbody>\n <tr>\n <th scope=\"row\">Role</th>\n <td>\n {{RoleRecord.Name}}\n <span class=\"fa-solid fa-pen-to-square\" (click)=\"EditRecord()\"></span>\n </td>\n </tr>\n <tr>\n <th scope=\"row\">Description</th>\n <td>{{RoleRecord.Description}}</td>\n </tr>\n <tr>\n <th scope=\"row\">Directory ID</th>\n <td>{{RoleRecord.DirectoryID}}</td>\n </tr>\n <tr>\n <th scope=\"row\">SQL Name</th>\n <td>{{RoleRecord.SQLName}}</td>\n </tr>\n </tbody>\n </table> \n\n <mj-tabstrip mjFillContainer [bottomMargin]=\"150\">\n <mj-tab>\n Users\n </mj-tab>\n <mj-tab-body>\n <mj-user-roles-grid Mode=\"Roles\" [RoleID]=\"RoleID\" [RoleRecord]=\"RoleRecord\"></mj-user-roles-grid>\n </mj-tab-body>\n\n <mj-tab>\n Entity Permissions\n </mj-tab>\n <mj-tab-body>\n <mj-entity-permissions-grid *ngIf=\"RoleRecord && RoleRecord.Name\" Mode=\"Role\" [RoleName]=\"RoleRecord.Name\" mjFillContainer></mj-entity-permissions-grid>\n </mj-tab-body>\n </mj-tabstrip>\n }\n</div>\n \n<mj-entity-form-dialog #entityForm \n [Record]=\"RoleRecord\" \n SectionName=\"details\" \n Mode=\"section\" \n [Visible]=\"showEntityEditingForm\" \n [AutoRevertOnCancel]=\"true\"\n [HandleSave]=\"true\"\n [Width]=\"550\"\n [Height]=\"450\"\n (DialogClosed)=\"onEntityFormClosed($event)\">\n</mj-entity-form-dialog>\n", styles: [".wrapper {\n display: block;\n}\n\nbutton {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n\n\n.role-name {\n font-weight: bold;\n font-size: 20px;\n margin-left: 5px;\n margin-top: 5px;\n}\n\n.role-info-table {\n width: 100%; /* Take up the full width of the container */\n border-collapse: collapse; /* For a cleaner look */\n margin-bottom: 10px;\n}\n\n.role-info-table th {\n width: 150px; /* Adjust this fixed width as needed */\n font-weight: bold; /* Make header labels bold */\n text-align: left; /* Align text to the left */\n padding: 8px; /* Add some padding for spacing */\n border: none; /* Removes the borders */\n background-color: transparent; /* Removes any background color */\n}\n\n.role-info-table td {\n text-align: left; /* Align text to the left */\n padding: 8px; /* Add some padding for spacing */\n border: none; /* Removes the borders */\n background-color: transparent; /* Removes any background color */\n overflow: hidden; /* Prevents content from overflowing */\n text-overflow: ellipsis; /* Adds an ellipsis if the text overflows */\n}\n\n/* Style for SVG icon */\n.edit-icon {\n margin-left: 20px; \n vertical-align: middle;;\n cursor: pointer; /* Changes the cursor to a pointer */\n}\n\n.edit-icon:hover {\n fill: #007bff; /* Changes the color on hover, set to the color you prefer */\n}"] }]
190
+ }], () => [{ type: i0.ChangeDetectorRef }], { RoleID: [{
191
191
  type: Input
192
192
  }], entityFormComponent: [{
193
193
  type: ViewChild,
@@ -5,7 +5,7 @@ import { EntityFormDialogComponent } from '@memberjunction/ng-entity-form-dialog
5
5
  import * as i0 from "@angular/core";
6
6
  export declare class SingleUserComponent implements OnInit {
7
7
  private cdRef;
8
- UserID: number;
8
+ UserID: string;
9
9
  entityFormComponent: EntityFormDialogComponent;
10
10
  gridHeight: number;
11
11
  isLoading: boolean;
@@ -123,13 +123,13 @@ export class SingleUserComponent {
123
123
  }
124
124
  Refresh() {
125
125
  return __awaiter(this, void 0, void 0, function* () {
126
- if (this.UserID > 0) {
126
+ if (this.UserID && this.UserID.length > 0) {
127
127
  const md = new Metadata();
128
128
  this.UserRecord = yield md.GetEntityObject('Users');
129
129
  yield this.UserRecord.Load(this.UserID);
130
130
  this.UserViewsParams = {
131
131
  EntityName: 'User Views',
132
- ExtraFilter: `UserID = ${this.UserID}`,
132
+ ExtraFilter: `UserID = '${this.UserID}'`,
133
133
  };
134
134
  }
135
135
  });
@@ -8,11 +8,11 @@ export declare class UserRolesGridComponent implements OnInit, OnChanges {
8
8
  /**
9
9
  * The name of the role we are working with, required if Mode is 'Roles'
10
10
  */
11
- RoleName: string;
11
+ RoleID: string;
12
12
  /**
13
13
  * The ID of the user we are working with, required if Mode is 'Users'
14
14
  */
15
- UserID: number;
15
+ UserID: string;
16
16
  isLoading: boolean;
17
17
  userRoles: UserRoleEntity_Ext[];
18
18
  Mode: 'Users' | 'Roles';
@@ -25,9 +25,11 @@ export declare class UserRolesGridComponent implements OnInit, OnChanges {
25
25
  */
26
26
  UserRecord: UserEntity | null;
27
27
  constructor(router: Router);
28
+ get RoleName(): string;
28
29
  ngOnInit(): void;
29
30
  ngOnChanges(changes: SimpleChanges): void;
30
31
  Refresh(): Promise<void>;
32
+ getRoleName(roleID: string): string;
31
33
  saveUserRoles(): Promise<void>;
32
34
  cancelEdit(): void;
33
35
  flipAll(): void;
@@ -35,5 +37,5 @@ export declare class UserRolesGridComponent implements OnInit, OnChanges {
35
37
  protected IsReallyDirty(ur: UserRoleEntity_Ext): boolean;
36
38
  flipState($event: MouseEvent | undefined, ur: UserRoleEntity_Ext, flipState: boolean): void;
37
39
  static ɵfac: i0.ɵɵFactoryDeclaration<UserRolesGridComponent, never>;
38
- static ɵcmp: i0.ɵɵComponentDeclaration<UserRolesGridComponent, "mj-user-roles-grid", never, { "RoleName": { "alias": "RoleName"; "required": false; }; "UserID": { "alias": "UserID"; "required": false; }; "Mode": { "alias": "Mode"; "required": false; }; "RoleRecord": { "alias": "RoleRecord"; "required": false; }; "UserRecord": { "alias": "UserRecord"; "required": false; }; }, {}, never, never, false, never>;
40
+ static ɵcmp: i0.ɵɵComponentDeclaration<UserRolesGridComponent, "mj-user-roles-grid", never, { "RoleID": { "alias": "RoleID"; "required": false; }; "UserID": { "alias": "UserID"; "required": false; }; "Mode": { "alias": "Mode"; "required": false; }; "RoleRecord": { "alias": "RoleRecord"; "required": false; }; "UserRecord": { "alias": "UserRecord"; "required": false; }; }, {}, never, never, false, never>;
39
41
  }
@@ -45,8 +45,9 @@ function UserRolesGridComponent_div_1_table_5_tr_8_td_2_Template(rf, ctx) { if (
45
45
  i0.ɵɵelementEnd();
46
46
  } if (rf & 2) {
47
47
  const ur_r5 = i0.ɵɵnextContext().$implicit;
48
+ const ctx_r1 = i0.ɵɵnextContext(3);
48
49
  i0.ɵɵadvance();
49
- i0.ɵɵtextInterpolate(ur_r5.RoleName);
50
+ i0.ɵɵtextInterpolate(ctx_r1.getRoleName(ur_r5.RoleID));
50
51
  } }
51
52
  function UserRolesGridComponent_div_1_table_5_tr_8_Template(rf, ctx) { if (rf & 1) {
52
53
  const _r4 = i0.ɵɵgetCurrentView();
@@ -124,6 +125,11 @@ export class UserRolesGridComponent {
124
125
  */
125
126
  this.UserRecord = null;
126
127
  }
128
+ get RoleName() {
129
+ const md = new Metadata();
130
+ const role = md.Roles.find(r => r.ID === this.RoleID);
131
+ return role ? role.Name : '';
132
+ }
127
133
  ngOnInit() {
128
134
  this.Refresh();
129
135
  }
@@ -134,15 +140,15 @@ export class UserRolesGridComponent {
134
140
  Refresh() {
135
141
  return __awaiter(this, void 0, void 0, function* () {
136
142
  if (this.Mode === 'Roles')
137
- if (!this.RoleName || this.RoleName.length === 0 || !this.RoleRecord)
138
- throw new Error("RoleName and RoleRecord are required when Mode is 'Roles'");
143
+ if (!this.RoleID || this.RoleID.length === 0 || !this.RoleRecord)
144
+ throw new Error("RoleID and RoleRecord are required when Mode is 'Roles'");
139
145
  if (this.Mode === 'Users')
140
146
  if (!this.UserID || !this.UserRecord)
141
147
  throw new Error("UserID and UserRecord are required when Mode is 'Users'");
142
148
  const md = new Metadata();
143
149
  this.isLoading = true;
144
150
  const rv = new RunView();
145
- const filter = this.Mode === 'Roles' ? `RoleName='${this.RoleName}'` : `UserID=${this.UserID}`;
151
+ const filter = this.Mode === 'Roles' ? `RoleID='${this.RoleID}'` : `UserID='${this.UserID}'`;
146
152
  const result = yield rv.RunView({
147
153
  EntityName: 'User Roles',
148
154
  ExtraFilter: filter,
@@ -158,7 +164,7 @@ export class UserRolesGridComponent {
158
164
  ur.Selected = true; // flip this on for all records that come from the DB
159
165
  ur.SavedUserID = ur.UserID; // stash this in an extra property so we can later set it if we have a delete operation
160
166
  ur.SavedUserName = ur.User; // stash this in an extra property so we can later set it if we have a delete operation
161
- ur.SavedRoleName = ur.RoleName; // stash this in an extra property so we can later set it if we have a delete operation
167
+ ur.SavedRoleID = ur.RoleID; // stash this in an extra property so we can later set it if we have a delete operation
162
168
  });
163
169
  if (this.Mode === 'Roles') {
164
170
  // for the mode of Roles, we want to bring in all of the possible users and then add any that are not in the existingUserRoles array
@@ -173,8 +179,8 @@ export class UserRolesGridComponent {
173
179
  for (const u of usersNotInRole) {
174
180
  const ur = yield md.GetEntityObject('User Roles');
175
181
  ur.NewRecord();
176
- ur.RoleName = this.RoleName;
177
- ur.SavedRoleName = this.RoleName; // stash this in an extra property so we can later set it if we have a delete operation
182
+ ur.RoleID = this.RoleID;
183
+ ur.SavedRoleID = this.RoleID; // stash this in an extra property so we can later set it if we have a delete operation
178
184
  ur.UserID = u.ID;
179
185
  ur.Set('User', u.Name); // use weak typing to get around the readonly property
180
186
  ur.SavedUserName = u.Name; // stash this in an extra property so we can later set it if we have a delete operation
@@ -189,21 +195,21 @@ export class UserRolesGridComponent {
189
195
  else {
190
196
  // for the mode of Users, we want to bring in all of the possible roles and then add any that are not in the existingUserRoles array
191
197
  const roles = md.Roles;
192
- const rolesNotInUser = roles.filter(r => !existingUserRoles.some(p => p.RoleName === r.Name));
198
+ const rolesNotInUser = roles.filter(r => !existingUserRoles.some(p => p.RoleID === r.ID));
193
199
  for (const r of rolesNotInUser) {
194
200
  const ur = yield md.GetEntityObject('User Roles');
195
201
  ur.NewRecord();
196
- ur.RoleName = r.Name;
202
+ ur.RoleID = r.ID;
197
203
  ur.UserID = this.UserID;
198
204
  ur.Set('User', this.UserRecord.Name); // use weak typing to get around the readonly property
199
205
  ur.SavedUserName = this.UserRecord.Name; // stash this in an extra property so we can later set it if we have a delete operation
200
206
  ur.SavedUserID = this.UserID; // stash this in an extra property so we can later set it if we have a delete operation
201
- ur.SavedRoleName = r.Name; // stash this in an extra property so we can later set it if we have a delete operation
207
+ ur.SavedRoleID = r.ID; // stash this in an extra property so we can later set it if we have a delete operation
202
208
  ur.Selected = false;
203
209
  existingUserRoles.push(ur);
204
210
  }
205
211
  // finally sort the array
206
- this.userRoles = existingUserRoles.sort((a, b) => a.RoleName.localeCompare(b.RoleName));
212
+ this.userRoles = existingUserRoles;
207
213
  }
208
214
  }
209
215
  else {
@@ -212,6 +218,11 @@ export class UserRolesGridComponent {
212
218
  this.isLoading = false;
213
219
  });
214
220
  }
221
+ getRoleName(roleID) {
222
+ const md = new Metadata();
223
+ const role = md.Roles.find(r => r.ID === roleID);
224
+ return role ? role.Name : '';
225
+ }
215
226
  saveUserRoles() {
216
227
  return __awaiter(this, void 0, void 0, function* () {
217
228
  // iterate through each permisison and for the ones that are dirty, add to transaction group then commit at once
@@ -238,7 +249,7 @@ export class UserRolesGridComponent {
238
249
  if (ur.User === null) {
239
250
  ur.Set('User', ur.SavedUserName); // get around the read-only property
240
251
  ur.UserID = ur.SavedUserID;
241
- ur.RoleName = this.Mode === 'Roles' ? this.RoleName : ur.SavedRoleName;
252
+ ur.RoleID = this.Mode === 'Roles' ? this.RoleID : ur.SavedRoleID;
242
253
  }
243
254
  });
244
255
  }
@@ -277,9 +288,9 @@ export class UserRolesGridComponent {
277
288
  }
278
289
  IsReallyDirty(ur) {
279
290
  // logic is simple, if we are in the database, but the checkbox is not checked (or vice versa), then we are dirty
280
- if (ur.Selected && ur.ID > 0)
291
+ if (ur.Selected && ur.IsSaved)
281
292
  return false; // if we are in the database and the checkbox is checked, we are not dirty
282
- else if (!ur.Selected && ur.ID > 0)
293
+ else if (!ur.Selected && ur.IsSaved)
283
294
  return true; // if we are in the database and the checkbox is not checked, we are dirty because we'd have to be removed
284
295
  else if (ur.Selected)
285
296
  return true; // if we are NOT in the database and the checkbox is checked, we are dirty because we'd have to be added
@@ -294,7 +305,7 @@ export class UserRolesGridComponent {
294
305
  }
295
306
  }
296
307
  UserRolesGridComponent.ɵfac = function UserRolesGridComponent_Factory(t) { return new (t || UserRolesGridComponent)(i0.ɵɵdirectiveInject(i1.Router)); };
297
- UserRolesGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserRolesGridComponent, selectors: [["mj-user-roles-grid"]], inputs: { RoleName: "RoleName", UserID: "UserID", Mode: "Mode", RoleRecord: "RoleRecord", UserRecord: "UserRecord" }, features: [i0.ɵɵNgOnChangesFeature], decls: 2, vars: 2, consts: [[4, "ngIf"], ["class", "content", 4, "ngIf"], [1, "content"], ["kendoButton", "", 3, "click", "disabled"], ["class", "grid", 4, "ngIf"], [1, "grid"], [3, "click"], [4, "ngFor", "ngForOf"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModelChange", "click", "ngModel"]], template: function UserRolesGridComponent_Template(rf, ctx) { if (rf & 1) {
308
+ UserRolesGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserRolesGridComponent, selectors: [["mj-user-roles-grid"]], inputs: { RoleID: "RoleID", UserID: "UserID", Mode: "Mode", RoleRecord: "RoleRecord", UserRecord: "UserRecord" }, features: [i0.ɵɵNgOnChangesFeature], decls: 2, vars: 2, consts: [[4, "ngIf"], ["class", "content", 4, "ngIf"], [1, "content"], ["kendoButton", "", 3, "click", "disabled"], ["class", "grid", 4, "ngIf"], [1, "grid"], [3, "click"], [4, "ngFor", "ngForOf"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModelChange", "click", "ngModel"]], template: function UserRolesGridComponent_Template(rf, ctx) { if (rf & 1) {
298
309
  i0.ɵɵtemplate(0, UserRolesGridComponent_div_0_Template, 2, 0, "div", 0)(1, UserRolesGridComponent_div_1_Template, 6, 3, "div", 1);
299
310
  } if (rf & 2) {
300
311
  i0.ɵɵproperty("ngIf", ctx.isLoading);
@@ -303,8 +314,8 @@ UserRolesGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: User
303
314
  } }, dependencies: [i2.NgForOf, i2.NgIf, i3.CheckboxControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.ButtonComponent, i5.LoaderComponent], styles: ["button[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n\n\n.grid[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-top: 5px;\n border-collapse: collapse;\n}\n\n\n\n.grid[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: #f2f2f2;\n color: black;\n font-weight: bold;\n text-align: center;\n border: 1px solid gray;\n padding: 0 8px;\n cursor: pointer;\n}\n\n\n\n.grid[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n border: 1px solid gray;\n height: 36px;\n text-align: center;\n padding: 0 8px;\n}\n\n\n\n.grid[_ngcontent-%COMP%] th[_ngcontent-%COMP%]:first-child, \n.grid[_ngcontent-%COMP%] td[_ngcontent-%COMP%]:first-child {\n min-width: 150px;\n text-align: left;\n}\n\n\n\n.grid[_ngcontent-%COMP%] th[_ngcontent-%COMP%]:not(:first-child), \n.grid[_ngcontent-%COMP%] td[_ngcontent-%COMP%]:not(:first-child) {\n width: 100px;\n}\n\n\n\n.grid[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:nth-child(odd) {\n background-color: white;\n}\n\n.grid[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:nth-child(even) {\n background-color: #e7f4ff;\n}"] });
304
315
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserRolesGridComponent, [{
305
316
  type: Component,
306
- args: [{ selector: 'mj-user-roles-grid', template: "<div *ngIf=\"isLoading\"><kendo-loader></kendo-loader></div>\n<div class=\"content\" *ngIf=\"!isLoading\">\n <button [disabled]=\"NumDirty === 0\" kendoButton (click)=\"saveUserRoles()\">Save</button>\n <button [disabled]=\"NumDirty === 0\" kendoButton (click)=\"cancelEdit()\">Cancel</button>\n <table *ngIf=\"!isLoading\" class=\"grid\">\n <thead>\n <tr>\n <th *ngIf=\"Mode === 'Roles'\">User</th>\n <th *ngIf=\"Mode === 'Users'\">Role</th>\n <th (click)=\"flipAll()\">In Role</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let ur of userRoles\">\n <td *ngIf=\"Mode === 'Roles'\">{{ ur.User }}</td>\n <td *ngIf=\"Mode === 'Users'\">{{ ur.RoleName }}</td>\n <td (click)=\"flipState($event, ur, true)\">\n <input type=\"checkbox\" kendoCheckBox [(ngModel)]=\"ur.Selected\" (click)=\"flipState($event, ur, false)\">\n </td>\n </tr>\n </tbody>\n </table> \n</div>", styles: ["button {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n/* Styles for the table with the 'grid' class */\n.grid {\n margin-left: 5px;\n margin-top: 5px;\n border-collapse: collapse;\n}\n\n/* Styles for th elements within the table with the 'grid' class */\n.grid th {\n background-color: #f2f2f2;\n color: black;\n font-weight: bold;\n text-align: center;\n border: 1px solid gray;\n padding: 0 8px;\n cursor: pointer;\n}\n\n/* Styles for td elements within the table with the 'grid' class */\n.grid td {\n border: 1px solid gray;\n height: 36px;\n text-align: center;\n padding: 0 8px;\n}\n\n/* Styles for the first child th and td within the table with the 'grid' class */\n.grid th:first-child,\n.grid td:first-child {\n min-width: 150px;\n text-align: left;\n}\n\n/* Styles for non-first-child th and td elements within the table with the 'grid' class */\n.grid th:not(:first-child),\n.grid td:not(:first-child) {\n width: 100px;\n}\n\n/* Alternating row background colors for the table with the 'grid' class */\n.grid tr:nth-child(odd) {\n background-color: white;\n}\n\n.grid tr:nth-child(even) {\n background-color: #e7f4ff;\n}\n\n"] }]
307
- }], () => [{ type: i1.Router }], { RoleName: [{
317
+ args: [{ selector: 'mj-user-roles-grid', template: "<div *ngIf=\"isLoading\"><kendo-loader></kendo-loader></div>\n<div class=\"content\" *ngIf=\"!isLoading\">\n <button [disabled]=\"NumDirty === 0\" kendoButton (click)=\"saveUserRoles()\">Save</button>\n <button [disabled]=\"NumDirty === 0\" kendoButton (click)=\"cancelEdit()\">Cancel</button>\n <table *ngIf=\"!isLoading\" class=\"grid\">\n <thead>\n <tr>\n <th *ngIf=\"Mode === 'Roles'\">User</th>\n <th *ngIf=\"Mode === 'Users'\">Role</th>\n <th (click)=\"flipAll()\">In Role</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let ur of userRoles\">\n <td *ngIf=\"Mode === 'Roles'\">{{ ur.User }}</td>\n <td *ngIf=\"Mode === 'Users'\">{{ getRoleName(ur.RoleID) }}</td>\n <td (click)=\"flipState($event, ur, true)\">\n <input type=\"checkbox\" kendoCheckBox [(ngModel)]=\"ur.Selected\" (click)=\"flipState($event, ur, false)\">\n </td>\n </tr>\n </tbody>\n </table> \n</div>", styles: ["button {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n\n/* Styles for the table with the 'grid' class */\n.grid {\n margin-left: 5px;\n margin-top: 5px;\n border-collapse: collapse;\n}\n\n/* Styles for th elements within the table with the 'grid' class */\n.grid th {\n background-color: #f2f2f2;\n color: black;\n font-weight: bold;\n text-align: center;\n border: 1px solid gray;\n padding: 0 8px;\n cursor: pointer;\n}\n\n/* Styles for td elements within the table with the 'grid' class */\n.grid td {\n border: 1px solid gray;\n height: 36px;\n text-align: center;\n padding: 0 8px;\n}\n\n/* Styles for the first child th and td within the table with the 'grid' class */\n.grid th:first-child,\n.grid td:first-child {\n min-width: 150px;\n text-align: left;\n}\n\n/* Styles for non-first-child th and td elements within the table with the 'grid' class */\n.grid th:not(:first-child),\n.grid td:not(:first-child) {\n width: 100px;\n}\n\n/* Alternating row background colors for the table with the 'grid' class */\n.grid tr:nth-child(odd) {\n background-color: white;\n}\n\n.grid tr:nth-child(even) {\n background-color: #e7f4ff;\n}\n\n"] }]
318
+ }], () => [{ type: i1.Router }], { RoleID: [{
308
319
  type: Input
309
320
  }], UserID: [{
310
321
  type: Input
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-explorer-settings",
3
- "version": "1.8.1",
3
+ "version": "2.1.1",
4
4
  "description": "MemberJunction: Reusable Angular components for the settings section of the MJ Explorer App",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -25,17 +25,17 @@
25
25
  "@angular/router": "18.0.2"
26
26
  },
27
27
  "dependencies": {
28
- "@memberjunction/core-entities": "1.8.1",
29
- "@memberjunction/global": "1.8.1",
30
- "@memberjunction/core": "1.8.1",
31
- "@memberjunction/ng-container-directives": "1.8.1",
32
- "@memberjunction/ng-shared": "1.8.1",
33
- "@memberjunction/ng-entity-permissions": "1.8.1",
34
- "@memberjunction/ng-base-forms": "1.8.1",
35
- "@memberjunction/ng-entity-form-dialog": "1.8.1",
36
- "@memberjunction/ng-user-view-grid": "1.8.1",
37
- "@memberjunction/ng-simple-record-list": "1.8.1",
38
- "@memberjunction/ng-tabstrip": "1.8.1",
28
+ "@memberjunction/core-entities": "2.1.1",
29
+ "@memberjunction/global": "2.1.1",
30
+ "@memberjunction/core": "2.1.1",
31
+ "@memberjunction/ng-container-directives": "2.1.1",
32
+ "@memberjunction/ng-shared": "2.1.1",
33
+ "@memberjunction/ng-entity-permissions": "2.1.1",
34
+ "@memberjunction/ng-base-forms": "2.1.1",
35
+ "@memberjunction/ng-entity-form-dialog": "2.1.1",
36
+ "@memberjunction/ng-user-view-grid": "2.1.1",
37
+ "@memberjunction/ng-simple-record-list": "2.1.1",
38
+ "@memberjunction/ng-tabstrip": "2.1.1",
39
39
  "@progress/kendo-angular-dropdowns": "16.2.0",
40
40
  "@progress/kendo-angular-grid": "16.2.0",
41
41
  "@progress/kendo-angular-buttons": "16.2.0",