@memberjunction/ng-conversations 5.30.1 → 5.32.0
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.
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts +2 -1
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js +9 -6
- package/dist/lib/components/collection/artifact-collection-picker-modal.component.js.map +1 -1
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts +2 -1
- package/dist/lib/components/collection/artifact-create-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/artifact-create-modal.component.js +9 -6
- package/dist/lib/components/collection/artifact-create-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.d.ts +2 -1
- package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-form-modal.component.js +8 -5
- package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts +2 -1
- package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-tree.component.js +9 -6
- package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
- package/dist/lib/components/collection/collection-view.component.d.ts +2 -1
- package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-view.component.js +12 -10
- package/dist/lib/components/collection/collection-view.component.js.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.d.ts +2 -1
- package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collections-full-view.component.js +18 -12
- package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +2 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +22 -11
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/library/library-full-view.component.d.ts +2 -1
- package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/library/library-full-view.component.js +8 -5
- package/dist/lib/components/library/library-full-view.component.js.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts +2 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.js +9 -7
- package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +2 -1
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +12 -5
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +6 -1
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts +2 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.js +6 -6
- package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
- package/dist/lib/components/project/project-form-modal.component.d.ts +2 -1
- package/dist/lib/components/project/project-form-modal.component.d.ts.map +1 -1
- package/dist/lib/components/project/project-form-modal.component.js +6 -5
- package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
- package/dist/lib/components/project/project-selector.component.d.ts +2 -1
- package/dist/lib/components/project/project-selector.component.d.ts.map +1 -1
- package/dist/lib/components/project/project-selector.component.js +8 -6
- package/dist/lib/components/project/project-selector.component.js.map +1 -1
- package/dist/lib/components/share/share-modal.component.d.ts +2 -1
- package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
- package/dist/lib/components/share/share-modal.component.js +11 -9
- package/dist/lib/components/share/share-modal.component.js.map +1 -1
- package/dist/lib/components/shared/user-picker.component.d.ts +2 -1
- package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
- package/dist/lib/components/shared/user-picker.component.js +6 -4
- package/dist/lib/components/shared/user-picker.component.js.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.d.ts +2 -1
- package/dist/lib/components/task/tasks-full-view.component.d.ts.map +1 -1
- package/dist/lib/components/task/tasks-full-view.component.js +9 -8
- package/dist/lib/components/task/tasks-full-view.component.js.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
- package/dist/lib/components/tasks/tasks-dropdown.component.js +5 -0
- package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
- package/dist/lib/components/thread/thread-panel.component.d.ts +2 -1
- package/dist/lib/components/thread/thread-panel.component.d.ts.map +1 -1
- package/dist/lib/components/thread/thread-panel.component.js +7 -4
- package/dist/lib/components/thread/thread-panel.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +8 -4
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/models/lazy-artifact-info.js +1 -1
- package/dist/lib/models/lazy-artifact-info.js.map +1 -1
- package/dist/lib/services/active-tasks.service.d.ts +7 -1
- package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
- package/dist/lib/services/active-tasks.service.js +12 -2
- package/dist/lib/services/active-tasks.service.js.map +1 -1
- package/dist/lib/services/agent-state.service.d.ts +7 -1
- package/dist/lib/services/agent-state.service.d.ts.map +1 -1
- package/dist/lib/services/agent-state.service.js +12 -2
- package/dist/lib/services/agent-state.service.js.map +1 -1
- package/dist/lib/services/artifact-permission.service.d.ts +8 -1
- package/dist/lib/services/artifact-permission.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-permission.service.js +21 -7
- package/dist/lib/services/artifact-permission.service.js.map +1 -1
- package/dist/lib/services/artifact-state.service.d.ts +8 -1
- package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-state.service.js +25 -11
- package/dist/lib/services/artifact-state.service.js.map +1 -1
- package/dist/lib/services/artifact-use-tracking.service.d.ts +7 -1
- package/dist/lib/services/artifact-use-tracking.service.d.ts.map +1 -1
- package/dist/lib/services/artifact-use-tracking.service.js +12 -2
- package/dist/lib/services/artifact-use-tracking.service.js.map +1 -1
- package/dist/lib/services/collection-permission.service.d.ts +7 -1
- package/dist/lib/services/collection-permission.service.d.ts.map +1 -1
- package/dist/lib/services/collection-permission.service.js +19 -9
- package/dist/lib/services/collection-permission.service.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +8 -0
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +15 -3
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-attachment.service.d.ts +7 -1
- package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-attachment.service.js +12 -2
- package/dist/lib/services/conversation-attachment.service.js.map +1 -1
- package/dist/lib/services/data-cache.service.d.ts +7 -1
- package/dist/lib/services/data-cache.service.d.ts.map +1 -1
- package/dist/lib/services/data-cache.service.js +16 -7
- package/dist/lib/services/data-cache.service.js.map +1 -1
- package/dist/lib/services/export.service.d.ts +7 -1
- package/dist/lib/services/export.service.d.ts.map +1 -1
- package/dist/lib/services/export.service.js +12 -2
- package/dist/lib/services/export.service.js.map +1 -1
- package/dist/lib/services/search.service.d.ts +7 -1
- package/dist/lib/services/search.service.d.ts.map +1 -1
- package/dist/lib/services/search.service.js +16 -6
- package/dist/lib/services/search.service.js.map +1 -1
- package/package.json +22 -22
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
3
|
+
import { RunView } from '@memberjunction/core';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
import * as i1 from "../../services/dialog.service";
|
|
5
6
|
import * as i2 from "../../services/toast.service";
|
|
@@ -116,7 +117,7 @@ function ShareModalComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
|
116
117
|
i0.ɵɵadvance(3);
|
|
117
118
|
i0.ɵɵconditional(ctx_r1.isPublicLink ? 23 : -1);
|
|
118
119
|
} }
|
|
119
|
-
export class ShareModalComponent {
|
|
120
|
+
export class ShareModalComponent extends BaseAngularComponent {
|
|
120
121
|
dialogService;
|
|
121
122
|
toastService;
|
|
122
123
|
cdr;
|
|
@@ -135,6 +136,7 @@ export class ShareModalComponent {
|
|
|
135
136
|
];
|
|
136
137
|
CONVERSATIONS_RESOURCE_TYPE_ID = '81D4BC3D-9FEB-EF11-B01A-286B35C04427';
|
|
137
138
|
constructor(dialogService, toastService, cdr) {
|
|
139
|
+
super();
|
|
138
140
|
this.dialogService = dialogService;
|
|
139
141
|
this.toastService = toastService;
|
|
140
142
|
this.cdr = cdr;
|
|
@@ -147,7 +149,7 @@ export class ShareModalComponent {
|
|
|
147
149
|
}
|
|
148
150
|
async loadPermissions() {
|
|
149
151
|
try {
|
|
150
|
-
const rv =
|
|
152
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
151
153
|
const result = await rv.RunView({
|
|
152
154
|
EntityName: 'MJ: Resource Permissions',
|
|
153
155
|
ExtraFilter: `ResourceTypeID='${this.CONVERSATIONS_RESOURCE_TYPE_ID}' AND ResourceRecordID='${this.conversation.ID}' AND Status='Approved'`,
|
|
@@ -156,7 +158,7 @@ export class ShareModalComponent {
|
|
|
156
158
|
if (result.Success && result.Results) {
|
|
157
159
|
const permissionPromises = result.Results.map(async (perm) => {
|
|
158
160
|
if (perm.UserID) {
|
|
159
|
-
const userRv =
|
|
161
|
+
const userRv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
160
162
|
const userResult = await userRv.RunView({
|
|
161
163
|
EntityName: 'MJ: Users',
|
|
162
164
|
ExtraFilter: `ID='${perm.UserID}'`,
|
|
@@ -209,7 +211,7 @@ export class ShareModalComponent {
|
|
|
209
211
|
}
|
|
210
212
|
try {
|
|
211
213
|
// Look up user by email
|
|
212
|
-
const rv =
|
|
214
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
213
215
|
const userResult = await rv.RunView({
|
|
214
216
|
EntityName: 'MJ: Users',
|
|
215
217
|
ExtraFilter: `Email='${email}'`,
|
|
@@ -249,7 +251,7 @@ export class ShareModalComponent {
|
|
|
249
251
|
return;
|
|
250
252
|
try {
|
|
251
253
|
if (permission.permissionId) {
|
|
252
|
-
const md =
|
|
254
|
+
const md = this.ProviderToUse;
|
|
253
255
|
const permEntity = await md.GetEntityObject('MJ: Resource Permissions');
|
|
254
256
|
await permEntity.Load(permission.permissionId);
|
|
255
257
|
const deleteResult = await permEntity.Delete();
|
|
@@ -267,7 +269,7 @@ export class ShareModalComponent {
|
|
|
267
269
|
}
|
|
268
270
|
async savePermission(permission) {
|
|
269
271
|
try {
|
|
270
|
-
const md =
|
|
272
|
+
const md = this.ProviderToUse;
|
|
271
273
|
const permEntity = await md.GetEntityObject('MJ: Resource Permissions');
|
|
272
274
|
if (permission.permissionId) {
|
|
273
275
|
// Update existing permission
|
|
@@ -333,7 +335,7 @@ export class ShareModalComponent {
|
|
|
333
335
|
this.closed.emit();
|
|
334
336
|
}
|
|
335
337
|
static ɵfac = function ShareModalComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ShareModalComponent)(i0.ɵɵdirectiveInject(i1.DialogService), i0.ɵɵdirectiveInject(i2.ToastService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
336
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ShareModalComponent, selectors: [["mj-share-modal"]], inputs: { conversation: "conversation", currentUser: "currentUser", isOpen: "isOpen" }, outputs: { closed: "closed" }, standalone: false, decls: 1, vars: 1, consts: [[3, "Title", "Width", "Height", "Visible"], [3, "Close", "Title", "Width", "Height", "Visible"], [1, "share-content"], [1, "add-user-section"], [1, "add-user-form"], ["type", "text", "placeholder", "Enter email address", 1, "mj-textbox", 2, "flex", "1", 3, "ngModelChange", "ngModel"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "permissions-section"], [1, "permission-list"], [1, "empty-state"], [1, "permission-item"], [1, "link-section"], [1, "link-controls"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], [1, "link-display"], ["mjButton", "", 3, "click"], [1, "user-info"], [1, "fas", "fa-user-circle"], [1, "user-details"], [1, "user-name"], [1, "user-email"], [1, "permission-controls"], [1, "mj-select", 2, "width", "120px", 3, "ngModelChange", "ngModel"], [3, "value"], ["title", "Remove access", 1, "btn-remove", 3, "click"], [1, "fas", "fa-times"], ["type", "text", "readonly", "", 1, "mj-textbox", 2, "flex", "1", 3, "value"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", "fa-copy"]], template: function ShareModalComponent_Template(rf, ctx) { if (rf & 1) {
|
|
338
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ShareModalComponent, selectors: [["mj-share-modal"]], inputs: { conversation: "conversation", currentUser: "currentUser", isOpen: "isOpen" }, outputs: { closed: "closed" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[3, "Title", "Width", "Height", "Visible"], [3, "Close", "Title", "Width", "Height", "Visible"], [1, "share-content"], [1, "add-user-section"], [1, "add-user-form"], ["type", "text", "placeholder", "Enter email address", 1, "mj-textbox", 2, "flex", "1", 3, "ngModelChange", "ngModel"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "permissions-section"], [1, "permission-list"], [1, "empty-state"], [1, "permission-item"], [1, "link-section"], [1, "link-controls"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], [1, "link-display"], ["mjButton", "", 3, "click"], [1, "user-info"], [1, "fas", "fa-user-circle"], [1, "user-details"], [1, "user-name"], [1, "user-email"], [1, "permission-controls"], [1, "mj-select", 2, "width", "120px", 3, "ngModelChange", "ngModel"], [3, "value"], ["title", "Remove access", 1, "btn-remove", 3, "click"], [1, "fas", "fa-times"], ["type", "text", "readonly", "", 1, "mj-textbox", 2, "flex", "1", 3, "value"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", "fa-copy"]], template: function ShareModalComponent_Template(rf, ctx) { if (rf & 1) {
|
|
337
339
|
i0.ɵɵconditionalCreate(0, ShareModalComponent_Conditional_0_Template, 27, 8, "mj-dialog", 0);
|
|
338
340
|
} if (rf & 2) {
|
|
339
341
|
i0.ɵɵconditional(ctx.isOpen ? 0 : -1);
|
|
@@ -440,5 +442,5 @@ export class ShareModalComponent {
|
|
|
440
442
|
}], closed: [{
|
|
441
443
|
type: Output
|
|
442
444
|
}] }); })();
|
|
443
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ShareModalComponent, { className: "ShareModalComponent", filePath: "src/lib/components/share/share-modal.component.ts", lineNumber:
|
|
445
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ShareModalComponent, { className: "ShareModalComponent", filePath: "src/lib/components/share/share-modal.component.ts", lineNumber: 141 }); })();
|
|
444
446
|
//# sourceMappingURL=share-modal.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share-modal.component.js","sourceRoot":"","sources":["../../../../src/lib/components/share/share-modal.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, ChangeDetectorRef } from '@angular/core';\nimport { MJConversationEntity, MJResourcePermissionEntity, MJUserEntity } from '@memberjunction/core-entities';\nimport { UserInfo, RunView, Metadata } from '@memberjunction/core';\nimport { DialogService } from '../../services/dialog.service';\nimport { ToastService } from '../../services/toast.service';\n\ninterface SharePermission {\n permissionId: string | null;\n userId: string;\n userEmail: string;\n userName: string;\n permissionLevel: 'View' | 'Edit' | 'Owner';\n}\n\n@Component({\n standalone: false,\n selector: 'mj-share-modal',\n template: `\n @if (isOpen) {\n <mj-dialog\n [Title]=\"'Share: ' + (conversation.Name || '')\"\n [Width]=\"500\"\n [Height]=\"600\"\n [Visible]=\"true\"\n (Close)=\"onClose()\">\n <div class=\"share-content\">\n <div class=\"add-user-section\">\n <h4>Add People</h4>\n <div class=\"add-user-form\">\n <input\n type=\"text\"\n [(ngModel)]=\"newUserEmail\"\n placeholder=\"Enter email address\"\n class=\"mj-textbox\"\n style=\"flex: 1;\">\n <button mjButton variant=\"primary\" (click)=\"onAddUser()\">\n Add\n </button>\n </div>\n </div>\n <div class=\"permissions-section\">\n <h4>People with Access</h4>\n <div class=\"permission-list\">\n @if (permissions.length === 0) {\n <div class=\"empty-state\">\n <p>No one has been given access yet</p>\n </div>\n }\n @for (permission of permissions; track permission) {\n <div class=\"permission-item\">\n <div class=\"user-info\">\n <i class=\"fas fa-user-circle\"></i>\n <div class=\"user-details\">\n <div class=\"user-name\">{{ permission.userName }}</div>\n <div class=\"user-email\">{{ permission.userEmail }}</div>\n </div>\n </div>\n <div class=\"permission-controls\">\n <select\n [ngModel]=\"permission.permissionLevel\"\n (ngModelChange)=\"onAccessLevelChange(permission, $event)\"\n style=\"width: 120px;\" class=\"mj-select\">\n @for (level of accessLevels; track level.value) {\n <option [value]=\"level.value\">{{ level.label }}</option>\n }\n </select>\n <button\n class=\"btn-remove\"\n (click)=\"onRemoveUser(permission)\"\n title=\"Remove access\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n <div class=\"link-section\">\n <h4>Share Link</h4>\n <div class=\"link-controls\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"isPublicLink\"\n (ngModelChange)=\"onTogglePublicLink()\">\n <label>Anyone with the link can view</label>\n </div>\n @if (isPublicLink) {\n <div class=\"link-display\">\n <input\n type=\"text\"\n [value]=\"shareLink\"\n readonly\n class=\"mj-textbox\"\n style=\"flex: 1;\">\n <button mjButton variant=\"flat\" (click)=\"onCopyLink()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n }\n </div>\n </div>\n <mj-dialog-actions>\n <button mjButton (click)=\"onClose()\">Close</button>\n </mj-dialog-actions>\n </mj-dialog>\n }\n `,\n styles: [`\n .share-content { display: flex; flex-direction: column; gap: 24px; }\n\n .add-user-section h4,\n .permissions-section h4,\n .link-section h4 { margin: 0 0 12px 0; font-size: 14px; font-weight: 600; }\n\n .add-user-form { display: flex; gap: 8px; }\n\n .permission-list { border: 1px solid #D9D9D9; border-radius: 4px; max-height: 300px; overflow-y: auto; }\n .permission-item { padding: 12px; border-bottom: 1px solid #E8E8E8; display: flex; justify-content: space-between; align-items: center; }\n .permission-item:last-child { border-bottom: none; }\n\n .user-info { display: flex; align-items: center; gap: 12px; flex: 1; }\n .user-info i { font-size: 32px; color: #999; }\n .user-details { display: flex; flex-direction: column; }\n .user-name { font-size: 14px; font-weight: 500; }\n .user-email { font-size: 12px; color: #666; }\n\n .permission-controls { display: flex; align-items: center; gap: 8px; }\n .btn-remove { padding: 6px 8px; background: transparent; border: none; cursor: pointer; border-radius: 3px; color: #999; }\n .btn-remove:hover { background: #FFEBEE; color: #D32F2F; }\n\n .empty-state { padding: 24px; text-align: center; color: #999; }\n .empty-state p { margin: 0; font-size: 13px; }\n\n .link-controls { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }\n .link-controls label { font-size: 13px; }\n\n .link-display { display: flex; gap: 8px; }\n `]\n})\nexport class ShareModalComponent implements OnInit {\n @Input() conversation!: MJConversationEntity;\n @Input() currentUser!: UserInfo;\n @Input() isOpen: boolean = false;\n\n @Output() closed = new EventEmitter<void>();\n\n public permissions: SharePermission[] = [];\n public newUserEmail: string = '';\n public isPublicLink: boolean = false;\n public shareLink: string = '';\n\n public accessLevels = [\n { label: 'Can View', value: 'View' },\n { label: 'Can Edit', value: 'Edit' },\n { label: 'Owner', value: 'Owner' }\n ];\n\n private readonly CONVERSATIONS_RESOURCE_TYPE_ID = '81D4BC3D-9FEB-EF11-B01A-286B35C04427';\n\n constructor(\n private dialogService: DialogService,\n private toastService: ToastService,\n private cdr: ChangeDetectorRef\n ) {}\n\n ngOnInit() {\n if (this.conversation) {\n this.loadPermissions();\n this.updateShareLink();\n }\n }\n\n private async loadPermissions(): Promise<void> {\n try {\n const rv = new RunView();\n const result = await rv.RunView<MJResourcePermissionEntity>({\n EntityName: 'MJ: Resource Permissions',\n ExtraFilter: `ResourceTypeID='${this.CONVERSATIONS_RESOURCE_TYPE_ID}' AND ResourceRecordID='${this.conversation.ID}' AND Status='Approved'`,\n ResultType: 'entity_object'\n });\n\n if (result.Success && result.Results) {\n const permissionPromises = result.Results.map(async (perm) => {\n if (perm.UserID) {\n const userRv = new RunView();\n const userResult = await userRv.RunView<MJUserEntity>({\n EntityName: 'MJ: Users',\n ExtraFilter: `ID='${perm.UserID}'`,\n ResultType: 'entity_object'\n });\n\n if (userResult.Success && userResult.Results && userResult.Results.length > 0) {\n const user = userResult.Results[0];\n return {\n permissionId: perm.ID,\n userId: perm.UserID,\n userEmail: user.Email,\n userName: user.Name,\n permissionLevel: perm.PermissionLevel || 'View'\n } as SharePermission;\n }\n }\n return null;\n });\n\n const resolvedPermissions = await Promise.all(permissionPromises);\n this.permissions = resolvedPermissions.filter(p => p !== null) as SharePermission[];\n }\n } catch (error) {\n console.error('Failed to load permissions:', error);\n } finally {\n this.cdr.detectChanges();\n }\n }\n\n getAccessLevel(permission: SharePermission): string {\n return permission.permissionLevel;\n }\n\n async onAccessLevelChange(permission: SharePermission, level: 'View' | 'Edit' | 'Owner'): Promise<void> {\n permission.permissionLevel = level;\n await this.savePermission(permission);\n }\n\n async onAddUser(): Promise<void> {\n const email = this.newUserEmail.trim();\n if (!email) return;\n\n // Simple email validation\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\n await this.dialogService.alert('Invalid Email', 'Please enter a valid email address');\n return;\n }\n\n // Check if user already has access\n if (this.permissions.some(p => p.userEmail === email)) {\n await this.dialogService.alert('User Already Has Access', 'This user already has access');\n return;\n }\n\n try {\n // Look up user by email\n const rv = new RunView();\n const userResult = await rv.RunView<MJUserEntity>({\n EntityName: 'MJ: Users',\n ExtraFilter: `Email='${email}'`,\n ResultType: 'entity_object'\n });\n\n if (!userResult.Success || !userResult.Results || userResult.Results.length === 0) {\n await this.dialogService.alert('User Not Found', 'No user found with that email address');\n return;\n }\n\n const user = userResult.Results[0];\n const newPermission: SharePermission = {\n permissionId: null,\n userId: user.ID,\n userEmail: user.Email,\n userName: user.Name,\n permissionLevel: 'View'\n };\n\n await this.savePermission(newPermission);\n this.permissions.push(newPermission);\n this.newUserEmail = '';\n this.toastService.success(`Access granted to ${user.Email}`);\n this.cdr.detectChanges();\n } catch (error) {\n console.error('Failed to add user:', error);\n this.toastService.error('Failed to add user');\n }\n }\n\n async onRemoveUser(permission: SharePermission): Promise<void> {\n const confirmed = await this.dialogService.confirm({\n title: 'Remove Access',\n message: `Remove access for ${permission.userEmail}?`,\n okText: 'Remove',\n cancelText: 'Cancel'\n });\n\n if (!confirmed) return;\n\n try {\n if (permission.permissionId) {\n const md = new Metadata();\n const permEntity = await md.GetEntityObject<MJResourcePermissionEntity>('MJ: Resource Permissions');\n await permEntity.Load(permission.permissionId);\n\n const deleteResult = await permEntity.Delete();\n if (!deleteResult) {\n throw new Error('Failed to delete permission');\n }\n }\n\n this.permissions = this.permissions.filter(p => p.userId !== permission.userId);\n this.toastService.success(`Access removed for ${permission.userEmail}`);\n } catch (error) {\n console.error('Failed to remove user:', error);\n this.toastService.error('Failed to remove user');\n }\n }\n\n private async savePermission(permission: SharePermission): Promise<void> {\n try {\n const md = new Metadata();\n const permEntity = await md.GetEntityObject<MJResourcePermissionEntity>('MJ: Resource Permissions');\n\n if (permission.permissionId) {\n // Update existing permission\n await permEntity.Load(permission.permissionId);\n permEntity.PermissionLevel = permission.permissionLevel;\n } else {\n // Create new permission\n permEntity.ResourceTypeID = this.CONVERSATIONS_RESOURCE_TYPE_ID;\n permEntity.ResourceRecordID = this.conversation.ID;\n permEntity.Type = 'User';\n permEntity.UserID = permission.userId;\n permEntity.PermissionLevel = permission.permissionLevel;\n permEntity.Status = 'Approved';\n }\n\n const saveResult = await permEntity.Save();\n if (!saveResult) {\n throw new Error('Failed to save permission');\n }\n\n // Update the permission ID if it was a new permission\n if (!permission.permissionId) {\n permission.permissionId = permEntity.ID;\n }\n } catch (error) {\n console.error('Failed to save permission:', error);\n throw error;\n }\n }\n\n async onTogglePublicLink(): Promise<void> {\n try {\n // Note: Public link functionality uses the conversation ID directly.\n // For enhanced security with unique tokens, password protection, and expiration,\n // future migration should add: PublicAccessToken, PublicAccessPassword, PublicAccessExpiresAt fields\n this.updateShareLink();\n } catch (error) {\n console.error('Failed to toggle public link:', error);\n await this.dialogService.alert('Error', 'Failed to update sharing settings');\n }\n }\n\n private updateShareLink(): void {\n if (this.isPublicLink && this.conversation) {\n // Generate shareable link\n const baseUrl = window.location.origin;\n this.shareLink = `${baseUrl}/chat/${this.conversation.ID}`;\n } else {\n this.shareLink = '';\n }\n }\n\n async onCopyLink(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.shareLink);\n this.toastService.success('Link copied to clipboard');\n } catch (err) {\n console.error('Failed to copy link:', err);\n this.toastService.error('Failed to copy link');\n }\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"share-modal.component.js","sourceRoot":"","sources":["../../../../src/lib/components/share/share-modal.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, ChangeDetectorRef } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MJConversationEntity, MJResourcePermissionEntity, MJUserEntity } from '@memberjunction/core-entities';\nimport { UserInfo, RunView, Metadata } from '@memberjunction/core';\nimport { DialogService } from '../../services/dialog.service';\nimport { ToastService } from '../../services/toast.service';\n\ninterface SharePermission {\n permissionId: string | null;\n userId: string;\n userEmail: string;\n userName: string;\n permissionLevel: 'View' | 'Edit' | 'Owner';\n}\n\n@Component({\n standalone: false,\n selector: 'mj-share-modal',\n template: `\n @if (isOpen) {\n <mj-dialog\n [Title]=\"'Share: ' + (conversation.Name || '')\"\n [Width]=\"500\"\n [Height]=\"600\"\n [Visible]=\"true\"\n (Close)=\"onClose()\">\n <div class=\"share-content\">\n <div class=\"add-user-section\">\n <h4>Add People</h4>\n <div class=\"add-user-form\">\n <input\n type=\"text\"\n [(ngModel)]=\"newUserEmail\"\n placeholder=\"Enter email address\"\n class=\"mj-textbox\"\n style=\"flex: 1;\">\n <button mjButton variant=\"primary\" (click)=\"onAddUser()\">\n Add\n </button>\n </div>\n </div>\n <div class=\"permissions-section\">\n <h4>People with Access</h4>\n <div class=\"permission-list\">\n @if (permissions.length === 0) {\n <div class=\"empty-state\">\n <p>No one has been given access yet</p>\n </div>\n }\n @for (permission of permissions; track permission) {\n <div class=\"permission-item\">\n <div class=\"user-info\">\n <i class=\"fas fa-user-circle\"></i>\n <div class=\"user-details\">\n <div class=\"user-name\">{{ permission.userName }}</div>\n <div class=\"user-email\">{{ permission.userEmail }}</div>\n </div>\n </div>\n <div class=\"permission-controls\">\n <select\n [ngModel]=\"permission.permissionLevel\"\n (ngModelChange)=\"onAccessLevelChange(permission, $event)\"\n style=\"width: 120px;\" class=\"mj-select\">\n @for (level of accessLevels; track level.value) {\n <option [value]=\"level.value\">{{ level.label }}</option>\n }\n </select>\n <button\n class=\"btn-remove\"\n (click)=\"onRemoveUser(permission)\"\n title=\"Remove access\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n <div class=\"link-section\">\n <h4>Share Link</h4>\n <div class=\"link-controls\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"isPublicLink\"\n (ngModelChange)=\"onTogglePublicLink()\">\n <label>Anyone with the link can view</label>\n </div>\n @if (isPublicLink) {\n <div class=\"link-display\">\n <input\n type=\"text\"\n [value]=\"shareLink\"\n readonly\n class=\"mj-textbox\"\n style=\"flex: 1;\">\n <button mjButton variant=\"flat\" (click)=\"onCopyLink()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n }\n </div>\n </div>\n <mj-dialog-actions>\n <button mjButton (click)=\"onClose()\">Close</button>\n </mj-dialog-actions>\n </mj-dialog>\n }\n `,\n styles: [`\n .share-content { display: flex; flex-direction: column; gap: 24px; }\n\n .add-user-section h4,\n .permissions-section h4,\n .link-section h4 { margin: 0 0 12px 0; font-size: 14px; font-weight: 600; }\n\n .add-user-form { display: flex; gap: 8px; }\n\n .permission-list { border: 1px solid #D9D9D9; border-radius: 4px; max-height: 300px; overflow-y: auto; }\n .permission-item { padding: 12px; border-bottom: 1px solid #E8E8E8; display: flex; justify-content: space-between; align-items: center; }\n .permission-item:last-child { border-bottom: none; }\n\n .user-info { display: flex; align-items: center; gap: 12px; flex: 1; }\n .user-info i { font-size: 32px; color: #999; }\n .user-details { display: flex; flex-direction: column; }\n .user-name { font-size: 14px; font-weight: 500; }\n .user-email { font-size: 12px; color: #666; }\n\n .permission-controls { display: flex; align-items: center; gap: 8px; }\n .btn-remove { padding: 6px 8px; background: transparent; border: none; cursor: pointer; border-radius: 3px; color: #999; }\n .btn-remove:hover { background: #FFEBEE; color: #D32F2F; }\n\n .empty-state { padding: 24px; text-align: center; color: #999; }\n .empty-state p { margin: 0; font-size: 13px; }\n\n .link-controls { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }\n .link-controls label { font-size: 13px; }\n\n .link-display { display: flex; gap: 8px; }\n `]\n})\nexport class ShareModalComponent extends BaseAngularComponent implements OnInit {\n @Input() conversation!: MJConversationEntity;\n @Input() currentUser!: UserInfo;\n @Input() isOpen: boolean = false;\n\n @Output() closed = new EventEmitter<void>();\n\n public permissions: SharePermission[] = [];\n public newUserEmail: string = '';\n public isPublicLink: boolean = false;\n public shareLink: string = '';\n\n public accessLevels = [\n { label: 'Can View', value: 'View' },\n { label: 'Can Edit', value: 'Edit' },\n { label: 'Owner', value: 'Owner' }\n ];\n\n private readonly CONVERSATIONS_RESOURCE_TYPE_ID = '81D4BC3D-9FEB-EF11-B01A-286B35C04427';\n\n constructor(\n private dialogService: DialogService,\n private toastService: ToastService,\n private cdr: ChangeDetectorRef\n ) {\n super();}\n\n ngOnInit() {\n if (this.conversation) {\n this.loadPermissions();\n this.updateShareLink();\n }\n }\n\n private async loadPermissions(): Promise<void> {\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJResourcePermissionEntity>({\n EntityName: 'MJ: Resource Permissions',\n ExtraFilter: `ResourceTypeID='${this.CONVERSATIONS_RESOURCE_TYPE_ID}' AND ResourceRecordID='${this.conversation.ID}' AND Status='Approved'`,\n ResultType: 'entity_object'\n });\n\n if (result.Success && result.Results) {\n const permissionPromises = result.Results.map(async (perm) => {\n if (perm.UserID) {\n const userRv = RunView.FromMetadataProvider(this.ProviderToUse);\n const userResult = await userRv.RunView<MJUserEntity>({\n EntityName: 'MJ: Users',\n ExtraFilter: `ID='${perm.UserID}'`,\n ResultType: 'entity_object'\n });\n\n if (userResult.Success && userResult.Results && userResult.Results.length > 0) {\n const user = userResult.Results[0];\n return {\n permissionId: perm.ID,\n userId: perm.UserID,\n userEmail: user.Email,\n userName: user.Name,\n permissionLevel: perm.PermissionLevel || 'View'\n } as SharePermission;\n }\n }\n return null;\n });\n\n const resolvedPermissions = await Promise.all(permissionPromises);\n this.permissions = resolvedPermissions.filter(p => p !== null) as SharePermission[];\n }\n } catch (error) {\n console.error('Failed to load permissions:', error);\n } finally {\n this.cdr.detectChanges();\n }\n }\n\n getAccessLevel(permission: SharePermission): string {\n return permission.permissionLevel;\n }\n\n async onAccessLevelChange(permission: SharePermission, level: 'View' | 'Edit' | 'Owner'): Promise<void> {\n permission.permissionLevel = level;\n await this.savePermission(permission);\n }\n\n async onAddUser(): Promise<void> {\n const email = this.newUserEmail.trim();\n if (!email) return;\n\n // Simple email validation\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\n await this.dialogService.alert('Invalid Email', 'Please enter a valid email address');\n return;\n }\n\n // Check if user already has access\n if (this.permissions.some(p => p.userEmail === email)) {\n await this.dialogService.alert('User Already Has Access', 'This user already has access');\n return;\n }\n\n try {\n // Look up user by email\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const userResult = await rv.RunView<MJUserEntity>({\n EntityName: 'MJ: Users',\n ExtraFilter: `Email='${email}'`,\n ResultType: 'entity_object'\n });\n\n if (!userResult.Success || !userResult.Results || userResult.Results.length === 0) {\n await this.dialogService.alert('User Not Found', 'No user found with that email address');\n return;\n }\n\n const user = userResult.Results[0];\n const newPermission: SharePermission = {\n permissionId: null,\n userId: user.ID,\n userEmail: user.Email,\n userName: user.Name,\n permissionLevel: 'View'\n };\n\n await this.savePermission(newPermission);\n this.permissions.push(newPermission);\n this.newUserEmail = '';\n this.toastService.success(`Access granted to ${user.Email}`);\n this.cdr.detectChanges();\n } catch (error) {\n console.error('Failed to add user:', error);\n this.toastService.error('Failed to add user');\n }\n }\n\n async onRemoveUser(permission: SharePermission): Promise<void> {\n const confirmed = await this.dialogService.confirm({\n title: 'Remove Access',\n message: `Remove access for ${permission.userEmail}?`,\n okText: 'Remove',\n cancelText: 'Cancel'\n });\n\n if (!confirmed) return;\n\n try {\n if (permission.permissionId) {\n const md = this.ProviderToUse;\n const permEntity = await md.GetEntityObject<MJResourcePermissionEntity>('MJ: Resource Permissions');\n await permEntity.Load(permission.permissionId);\n\n const deleteResult = await permEntity.Delete();\n if (!deleteResult) {\n throw new Error('Failed to delete permission');\n }\n }\n\n this.permissions = this.permissions.filter(p => p.userId !== permission.userId);\n this.toastService.success(`Access removed for ${permission.userEmail}`);\n } catch (error) {\n console.error('Failed to remove user:', error);\n this.toastService.error('Failed to remove user');\n }\n }\n\n private async savePermission(permission: SharePermission): Promise<void> {\n try {\n const md = this.ProviderToUse;\n const permEntity = await md.GetEntityObject<MJResourcePermissionEntity>('MJ: Resource Permissions');\n\n if (permission.permissionId) {\n // Update existing permission\n await permEntity.Load(permission.permissionId);\n permEntity.PermissionLevel = permission.permissionLevel;\n } else {\n // Create new permission\n permEntity.ResourceTypeID = this.CONVERSATIONS_RESOURCE_TYPE_ID;\n permEntity.ResourceRecordID = this.conversation.ID;\n permEntity.Type = 'User';\n permEntity.UserID = permission.userId;\n permEntity.PermissionLevel = permission.permissionLevel;\n permEntity.Status = 'Approved';\n }\n\n const saveResult = await permEntity.Save();\n if (!saveResult) {\n throw new Error('Failed to save permission');\n }\n\n // Update the permission ID if it was a new permission\n if (!permission.permissionId) {\n permission.permissionId = permEntity.ID;\n }\n } catch (error) {\n console.error('Failed to save permission:', error);\n throw error;\n }\n }\n\n async onTogglePublicLink(): Promise<void> {\n try {\n // Note: Public link functionality uses the conversation ID directly.\n // For enhanced security with unique tokens, password protection, and expiration,\n // future migration should add: PublicAccessToken, PublicAccessPassword, PublicAccessExpiresAt fields\n this.updateShareLink();\n } catch (error) {\n console.error('Failed to toggle public link:', error);\n await this.dialogService.alert('Error', 'Failed to update sharing settings');\n }\n }\n\n private updateShareLink(): void {\n if (this.isPublicLink && this.conversation) {\n // Generate shareable link\n const baseUrl = window.location.origin;\n this.shareLink = `${baseUrl}/chat/${this.conversation.ID}`;\n } else {\n this.shareLink = '';\n }\n }\n\n async onCopyLink(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.shareLink);\n this.toastService.success('Link copied to clipboard');\n } catch (err) {\n console.error('Failed to copy link:', err);\n this.toastService.error('Failed to copy link');\n }\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EventEmitter, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
|
2
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
2
3
|
import { UserInfo } from '@memberjunction/core';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
export interface UserSearchResult {
|
|
@@ -8,7 +9,7 @@ export interface UserSearchResult {
|
|
|
8
9
|
firstName: string;
|
|
9
10
|
lastName: string;
|
|
10
11
|
}
|
|
11
|
-
export declare class UserPickerComponent implements OnInit, OnDestroy {
|
|
12
|
+
export declare class UserPickerComponent extends BaseAngularComponent implements OnInit, OnDestroy {
|
|
12
13
|
private cdr;
|
|
13
14
|
currentUser: UserInfo;
|
|
14
15
|
excludeUserIds: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-picker.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/shared/user-picker.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"user-picker.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/shared/user-picker.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC7G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,EAAE,QAAQ,EAAW,MAAM,sBAAsB,CAAC;;AAGzD,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBA4La,mBAAoB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAK1E,OAAO,CAAC,GAAG;IAJd,WAAW,EAAG,QAAQ,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAM;IAC9B,WAAW,EAAE,MAAM,CAAwC;gBAEhD,GAAG,EAAE,iBAAiB;IAGhC,YAAY,iCAAwC;IAE9D,WAAW,EAAE,MAAM,CAAM;IACzB,aAAa,EAAE,gBAAgB,EAAE,CAAM;IACvC,WAAW,EAAE,OAAO,CAAS;IAC7B,WAAW,EAAE,OAAO,CAAS;IAE7B,QAAQ,IAAI,IAAI;IAKhB,WAAW,IAAI,IAAI;IAInB,OAAO,CAAC,kBAAkB;IAO1B,QAAQ,IAAI,IAAI;IAShB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI;YAO5B,aAAa;yCA/ClB,mBAAmB;2CAAnB,mBAAmB;CAiH/B"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
2
3
|
import { FormsModule } from '@angular/forms';
|
|
3
4
|
import { RunView } from '@memberjunction/core';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
@@ -46,12 +47,13 @@ function UserPickerComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
|
46
47
|
i0.ɵɵtext(4, "No users found");
|
|
47
48
|
i0.ɵɵelementEnd()()();
|
|
48
49
|
} }
|
|
49
|
-
export class UserPickerComponent {
|
|
50
|
+
export class UserPickerComponent extends BaseAngularComponent {
|
|
50
51
|
cdr;
|
|
51
52
|
currentUser;
|
|
52
53
|
excludeUserIds = [];
|
|
53
54
|
placeholder = 'Search for a user (press Enter)...';
|
|
54
55
|
constructor(cdr) {
|
|
56
|
+
super();
|
|
55
57
|
this.cdr = cdr;
|
|
56
58
|
}
|
|
57
59
|
userSelected = new EventEmitter();
|
|
@@ -94,7 +96,7 @@ export class UserPickerComponent {
|
|
|
94
96
|
this.isSearching = true;
|
|
95
97
|
this.showResults = true;
|
|
96
98
|
try {
|
|
97
|
-
const rv =
|
|
99
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
98
100
|
// Escape single quotes in query to prevent SQL errors
|
|
99
101
|
const escapedQuery = query.replace(/'/g, "''");
|
|
100
102
|
// Build exclude filter
|
|
@@ -147,7 +149,7 @@ export class UserPickerComponent {
|
|
|
147
149
|
}
|
|
148
150
|
}
|
|
149
151
|
static ɵfac = function UserPickerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UserPickerComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
150
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserPickerComponent, selectors: [["mj-user-picker"]], inputs: { currentUser: "currentUser", excludeUserIds: "excludeUserIds", placeholder: "placeholder" }, outputs: { userSelected: "userSelected" }, decls: 8, vars: 7, consts: [[1, "user-picker"], [1, "search-input-wrapper"], ["type", "text", 1, "user-search-input", 3, "ngModelChange", "keydown.enter", "ngModel", "placeholder", "disabled"], [1, "search-button", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-search"], [1, "search-results-dropdown"], [1, "user-search-item"], [1, "user-search-item", 3, "click"], [1, "user-avatar"], [1, "fa-solid", "fa-user"], [1, "user-info"], [1, "user-name"], [1, "user-email"], [1, "no-results"], [1, "fa-solid", "fa-user-slash"]], template: function UserPickerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
152
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserPickerComponent, selectors: [["mj-user-picker"]], inputs: { currentUser: "currentUser", excludeUserIds: "excludeUserIds", placeholder: "placeholder" }, outputs: { userSelected: "userSelected" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 8, vars: 7, consts: [[1, "user-picker"], [1, "search-input-wrapper"], ["type", "text", 1, "user-search-input", 3, "ngModelChange", "keydown.enter", "ngModel", "placeholder", "disabled"], [1, "search-button", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-search"], [1, "search-results-dropdown"], [1, "user-search-item"], [1, "user-search-item", 3, "click"], [1, "user-avatar"], [1, "fa-solid", "fa-user"], [1, "user-info"], [1, "user-name"], [1, "user-email"], [1, "no-results"], [1, "fa-solid", "fa-user-slash"]], template: function UserPickerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
151
153
|
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "input", 2);
|
|
152
154
|
i0.ɵɵtwoWayListener("ngModelChange", function UserPickerComponent_Template_input_ngModelChange_2_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.searchQuery, $event) || (ctx.searchQuery = $event); return $event; });
|
|
153
155
|
i0.ɵɵlistener("keydown.enter", function UserPickerComponent_Template_input_keydown_enter_2_listener() { return ctx.onSearch(); });
|
|
@@ -230,5 +232,5 @@ export class UserPickerComponent {
|
|
|
230
232
|
}], userSelected: [{
|
|
231
233
|
type: Output
|
|
232
234
|
}] }); })();
|
|
233
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserPickerComponent, { className: "UserPickerComponent", filePath: "src/lib/components/shared/user-picker.component.ts", lineNumber:
|
|
235
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserPickerComponent, { className: "UserPickerComponent", filePath: "src/lib/components/shared/user-picker.component.ts", lineNumber: 204 }); })();
|
|
234
236
|
//# sourceMappingURL=user-picker.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-picker.component.js","sourceRoot":"","sources":["../../../../src/lib/components/shared/user-picker.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\nimport { UserInfo, RunView } from '@memberjunction/core';\nimport { MJUserEntity } from '@memberjunction/core-entities';\n\nexport interface UserSearchResult {\n id: string;\n name: string;\n email: string;\n firstName: string;\n lastName: string;\n}\n\n@Component({\n selector: 'mj-user-picker',\n standalone: true,\n imports: [FormsModule],\n template: `\n <div class=\"user-picker\">\n <div class=\"search-input-wrapper\">\n <input\n type=\"text\"\n class=\"user-search-input\"\n [(ngModel)]=\"searchQuery\"\n [placeholder]=\"placeholder\"\n (keydown.enter)=\"onSearch()\"\n [disabled]=\"isSearching\"\n />\n <button class=\"search-button\" (click)=\"onSearch()\" [disabled]=\"isSearching\">\n @if (isSearching) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-search\"></i>\n }\n </button>\n </div>\n\n @if (showResults && searchResults.length > 0) {\n <div class=\"search-results-dropdown\">\n @for (user of searchResults; track user.id) {\n <div class=\"user-search-item\" (click)=\"onSelectUser(user)\">\n <div class=\"user-avatar\">\n <i class=\"fa-solid fa-user\"></i>\n </div>\n <div class=\"user-info\">\n <div class=\"user-name\">{{ user.name }}</div>\n <div class=\"user-email\">{{ user.email }}</div>\n </div>\n </div>\n }\n </div>\n }\n\n @if (showResults && searchResults.length === 0 && searchQuery.length >= 2 && !isSearching) {\n <div class=\"search-results-dropdown\">\n <div class=\"no-results\">\n <i class=\"fa-solid fa-user-slash\"></i>\n <span>No users found</span>\n </div>\n </div>\n }\n </div>\n `,\n styles: [`\n .user-picker {\n width: 100%;\n position: relative;\n }\n\n .search-input-wrapper {\n display: flex;\n gap: 8px;\n width: 100%;\n }\n\n .user-search-input {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #E5E7EB;\n border-radius: 6px;\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n }\n\n .user-search-input:focus {\n border-color: #6366F1;\n }\n\n .user-search-input:disabled {\n background: #F3F4F6;\n cursor: not-allowed;\n }\n\n .search-button {\n padding: 8px 16px;\n background: #6366F1;\n color: white;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .search-button:hover:not(:disabled) {\n background: #5558E3;\n }\n\n .search-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n .search-button i {\n font-size: 14px;\n }\n\n .search-results-dropdown {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 6px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-height: 300px;\n overflow-y: auto;\n z-index: 1000;\n }\n\n .user-search-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .user-search-item:hover {\n background-color: #F3F4F6;\n }\n\n .user-avatar {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667EEA 0%, #764BA2 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 16px;\n flex-shrink: 0;\n }\n\n .user-info {\n flex: 1;\n min-width: 0;\n }\n\n .user-name {\n font-size: 14px;\n font-weight: 500;\n color: #1F2937;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .user-email {\n font-size: 12px;\n color: #6B7280;\n margin-top: 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .no-results {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 24px;\n color: #9CA3AF;\n }\n\n .no-results i {\n font-size: 32px;\n }\n\n .no-results span {\n font-size: 14px;\n }\n `]\n})\nexport class UserPickerComponent implements OnInit, OnDestroy {\n @Input() currentUser!: UserInfo;\n @Input() excludeUserIds: string[] = [];\n @Input() placeholder: string = 'Search for a user (press Enter)...';\n\n constructor(private cdr: ChangeDetectorRef) {}\n\n @Output() userSelected = new EventEmitter<UserSearchResult>();\n\n searchQuery: string = '';\n searchResults: UserSearchResult[] = [];\n isSearching: boolean = false;\n showResults: boolean = false;\n\n ngOnInit(): void {\n // Add click outside listener to close dropdown\n document.addEventListener('click', this.handleClickOutside.bind(this));\n }\n\n ngOnDestroy(): void {\n document.removeEventListener('click', this.handleClickOutside.bind(this));\n }\n\n private handleClickOutside(event: MouseEvent): void {\n const target = event.target as HTMLElement;\n if (!target.closest('.user-picker')) {\n this.showResults = false;\n }\n }\n\n onSearch(): void {\n if (!this.searchQuery || this.searchQuery.trim().length < 2) {\n this.showResults = false;\n return;\n }\n\n this.performSearch(this.searchQuery.trim());\n }\n\n onSelectUser(user: UserSearchResult): void {\n this.userSelected.emit(user);\n this.searchQuery = '';\n this.searchResults = [];\n this.showResults = false;\n }\n\n private async performSearch(query: string): Promise<void> {\n if (!query || query.length < 2) {\n this.searchResults = [];\n this.showResults = false;\n return;\n }\n\n this.isSearching = true;\n this.showResults = true;\n\n try {\n const rv = new RunView();\n\n // Escape single quotes in query to prevent SQL errors\n const escapedQuery = query.replace(/'/g, \"''\");\n\n // Build exclude filter\n let excludeFilter = '';\n if (this.excludeUserIds.length > 0) {\n const ids = this.excludeUserIds.map(id => `'${id}'`).join(',');\n excludeFilter = ` AND ID NOT IN (${ids})`;\n }\n\n // Search in Name, Email, FirstName, and LastName (case-insensitive)\n const searchFilter = `(\n Name LIKE '%${escapedQuery}%' OR\n Email LIKE '%${escapedQuery}%' OR\n FirstName LIKE '%${escapedQuery}%' OR\n LastName LIKE '%${escapedQuery}%'\n )${excludeFilter}`;\n\n const result = await rv.RunView<MJUserEntity>({\n EntityName: 'MJ: Users',\n ExtraFilter: searchFilter,\n OrderBy: 'Name ASC',\n MaxRows: 20,\n ResultType: 'entity_object'\n }, this.currentUser);\n\n console.log('User search result:', {\n query,\n success: result.Success,\n count: result.Results?.length,\n error: result.ErrorMessage\n });\n\n if (result.Success && result.Results) {\n this.searchResults = result.Results.map(user => ({\n id: user.ID,\n name: user.Name,\n email: user.Email,\n firstName: user.FirstName || '',\n lastName: user.LastName || ''\n }));\n } else {\n console.warn('User search returned no results or failed:', result.ErrorMessage);\n this.searchResults = [];\n }\n } catch (error) {\n console.error('Error searching users:', error);\n this.searchResults = [];\n } finally {\n this.isSearching = false;\n this.cdr.detectChanges();\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"user-picker.component.js","sourceRoot":"","sources":["../../../../src/lib/components/shared/user-picker.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAwC,MAAM,eAAe,CAAC;AAC7G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAY,OAAO,EAAE,MAAM,sBAAsB,CAAC;;;;;IA4BjC,uBAA2C;;;IAE3C,uBAAkC;;;;IAQlC,8BAA2D;IAA7B,qNAAS,4BAAkB,KAAC;IACtD,8BAAyB;IACrB,wBAAgC;IACpC,iBAAM;IAEF,AADJ,+BAAuB,cACI;IAAA,YAAe;IAAA,iBAAM;IAC5C,+BAAwB;IAAA,YAAgB;IAEhD,AADI,AAD4C,iBAAM,EAC5C,EACJ;;;IAHyB,eAAe;IAAf,kCAAe;IACd,eAAgB;IAAhB,mCAAgB;;;IARxD,8BAAqC;IACjC,oGAUC;IACL,iBAAM;;;IAXF,cAUC;IAVD,mCAUC;;;IAMD,AADJ,8BAAqC,cACT;IACpB,wBAAsC;IACtC,4BAAM;IAAA,8BAAc;IAE5B,AADI,AADwB,iBAAO,EACzB,EACJ;;AA8ItB,MAAM,OAAO,mBAAoB,SAAQ,oBAAoB;IAKrC;IAJX,WAAW,CAAY;IACvB,cAAc,GAAa,EAAE,CAAC;IAC9B,WAAW,GAAW,oCAAoC,CAAC;IAEpE,YAAoB,GAAsB;QAC1C,KAAK,EAAE,CAAC;QADY,QAAG,GAAH,GAAG,CAAmB;IAClC,CAAC;IAEC,YAAY,GAAG,IAAI,YAAY,EAAoB,CAAC;IAE9D,WAAW,GAAW,EAAE,CAAC;IACzB,aAAa,GAAuB,EAAE,CAAC;IACvC,WAAW,GAAY,KAAK,CAAC;IAC7B,WAAW,GAAY,KAAK,CAAC;IAE7B,QAAQ;QACJ,+CAA+C;QAC/C,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,WAAW;QACP,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9E,CAAC;IAEO,kBAAkB,CAAC,KAAiB;QACxC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QAC7B,CAAC;IACL,CAAC;IAED,QAAQ;QACJ,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,OAAO;QACX,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,YAAY,CAAC,IAAsB;QAC/B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,KAAa;QACrC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;YACxB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,OAAO;QACX,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAExB,IAAI,CAAC;YACD,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAE5D,sDAAsD;YACtD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAE/C,uBAAuB;YACvB,IAAI,aAAa,GAAG,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC/D,aAAa,GAAG,mBAAmB,GAAG,GAAG,CAAC;YAC9C,CAAC;YAED,oEAAoE;YACpE,MAAM,YAAY,GAAG;8BACH,YAAY;+BACX,YAAY;mCACR,YAAY;kCACb,YAAY;eAC/B,aAAa,EAAE,CAAC;YAEnB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAe;gBAC1C,UAAU,EAAE,WAAW;gBACvB,WAAW,EAAE,YAAY;gBACzB,OAAO,EAAE,UAAU;gBACnB,OAAO,EAAE,EAAE;gBACX,UAAU,EAAE,eAAe;aAC9B,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YAErB,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE;gBAC/B,KAAK;gBACL,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM;gBAC7B,KAAK,EAAE,MAAM,CAAC,YAAY;aAC7B,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBAC7C,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;oBAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;iBAChC,CAAC,CAAC,CAAC;YACR,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;gBAChF,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;YAC5B,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;YAC/C,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QAC5B,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC7B,CAAC;IACL,CAAC;6GAhHQ,mBAAmB;6DAAnB,mBAAmB;YArLhB,AADJ,AADJ,8BAAyB,aACa,eAQ5B;YAJE,mNAAyB;YAEzB,+GAAiB,cAAU,IAAC;YALhC,iBAOE;YACF,iCAA4E;YAA9C,gGAAS,cAAU,IAAC;YAG5C,AAFF,mFAAmB,6DAEV;YAIjB,AADI,iBAAS,EACP;YAEN,qFAA+C;YAgB/C,qFAA4F;YAQhG,iBAAM;;YAtCM,eAAyB;YAAzB,+CAAyB;YAGzB,AAFA,6CAA2B,6BAEH;YAEuB,cAAwB;YAAxB,0CAAwB;YACvE,cAIC;YAJD,yCAIC;YAIT,eAcC;YAdD,0EAcC;YAED,cAOC;YAPD,+HAOC;4BA5CC,WAAW;;iFAyLZ,mBAAmB;cA5L/B,SAAS;2BACI,gBAAgB,cACd,IAAI,WACP,CAAC,WAAW,CAAC,YACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6CT;;kBA4IA,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAKL,MAAM;;kFARE,mBAAmB","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\nimport { FormsModule } from '@angular/forms';\nimport { UserInfo, RunView } from '@memberjunction/core';\nimport { MJUserEntity } from '@memberjunction/core-entities';\n\nexport interface UserSearchResult {\n id: string;\n name: string;\n email: string;\n firstName: string;\n lastName: string;\n}\n\n@Component({\n selector: 'mj-user-picker',\n standalone: true,\n imports: [FormsModule],\n template: `\n <div class=\"user-picker\">\n <div class=\"search-input-wrapper\">\n <input\n type=\"text\"\n class=\"user-search-input\"\n [(ngModel)]=\"searchQuery\"\n [placeholder]=\"placeholder\"\n (keydown.enter)=\"onSearch()\"\n [disabled]=\"isSearching\"\n />\n <button class=\"search-button\" (click)=\"onSearch()\" [disabled]=\"isSearching\">\n @if (isSearching) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-search\"></i>\n }\n </button>\n </div>\n\n @if (showResults && searchResults.length > 0) {\n <div class=\"search-results-dropdown\">\n @for (user of searchResults; track user.id) {\n <div class=\"user-search-item\" (click)=\"onSelectUser(user)\">\n <div class=\"user-avatar\">\n <i class=\"fa-solid fa-user\"></i>\n </div>\n <div class=\"user-info\">\n <div class=\"user-name\">{{ user.name }}</div>\n <div class=\"user-email\">{{ user.email }}</div>\n </div>\n </div>\n }\n </div>\n }\n\n @if (showResults && searchResults.length === 0 && searchQuery.length >= 2 && !isSearching) {\n <div class=\"search-results-dropdown\">\n <div class=\"no-results\">\n <i class=\"fa-solid fa-user-slash\"></i>\n <span>No users found</span>\n </div>\n </div>\n }\n </div>\n `,\n styles: [`\n .user-picker {\n width: 100%;\n position: relative;\n }\n\n .search-input-wrapper {\n display: flex;\n gap: 8px;\n width: 100%;\n }\n\n .user-search-input {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #E5E7EB;\n border-radius: 6px;\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n }\n\n .user-search-input:focus {\n border-color: #6366F1;\n }\n\n .user-search-input:disabled {\n background: #F3F4F6;\n cursor: not-allowed;\n }\n\n .search-button {\n padding: 8px 16px;\n background: #6366F1;\n color: white;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .search-button:hover:not(:disabled) {\n background: #5558E3;\n }\n\n .search-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n .search-button i {\n font-size: 14px;\n }\n\n .search-results-dropdown {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 6px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-height: 300px;\n overflow-y: auto;\n z-index: 1000;\n }\n\n .user-search-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .user-search-item:hover {\n background-color: #F3F4F6;\n }\n\n .user-avatar {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667EEA 0%, #764BA2 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 16px;\n flex-shrink: 0;\n }\n\n .user-info {\n flex: 1;\n min-width: 0;\n }\n\n .user-name {\n font-size: 14px;\n font-weight: 500;\n color: #1F2937;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .user-email {\n font-size: 12px;\n color: #6B7280;\n margin-top: 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .no-results {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding: 24px;\n color: #9CA3AF;\n }\n\n .no-results i {\n font-size: 32px;\n }\n\n .no-results span {\n font-size: 14px;\n }\n `]\n})\nexport class UserPickerComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n @Input() currentUser!: UserInfo;\n @Input() excludeUserIds: string[] = [];\n @Input() placeholder: string = 'Search for a user (press Enter)...';\n\n constructor(private cdr: ChangeDetectorRef) {\n super();}\n\n @Output() userSelected = new EventEmitter<UserSearchResult>();\n\n searchQuery: string = '';\n searchResults: UserSearchResult[] = [];\n isSearching: boolean = false;\n showResults: boolean = false;\n\n ngOnInit(): void {\n // Add click outside listener to close dropdown\n document.addEventListener('click', this.handleClickOutside.bind(this));\n }\n\n ngOnDestroy(): void {\n document.removeEventListener('click', this.handleClickOutside.bind(this));\n }\n\n private handleClickOutside(event: MouseEvent): void {\n const target = event.target as HTMLElement;\n if (!target.closest('.user-picker')) {\n this.showResults = false;\n }\n }\n\n onSearch(): void {\n if (!this.searchQuery || this.searchQuery.trim().length < 2) {\n this.showResults = false;\n return;\n }\n\n this.performSearch(this.searchQuery.trim());\n }\n\n onSelectUser(user: UserSearchResult): void {\n this.userSelected.emit(user);\n this.searchQuery = '';\n this.searchResults = [];\n this.showResults = false;\n }\n\n private async performSearch(query: string): Promise<void> {\n if (!query || query.length < 2) {\n this.searchResults = [];\n this.showResults = false;\n return;\n }\n\n this.isSearching = true;\n this.showResults = true;\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n // Escape single quotes in query to prevent SQL errors\n const escapedQuery = query.replace(/'/g, \"''\");\n\n // Build exclude filter\n let excludeFilter = '';\n if (this.excludeUserIds.length > 0) {\n const ids = this.excludeUserIds.map(id => `'${id}'`).join(',');\n excludeFilter = ` AND ID NOT IN (${ids})`;\n }\n\n // Search in Name, Email, FirstName, and LastName (case-insensitive)\n const searchFilter = `(\n Name LIKE '%${escapedQuery}%' OR\n Email LIKE '%${escapedQuery}%' OR\n FirstName LIKE '%${escapedQuery}%' OR\n LastName LIKE '%${escapedQuery}%'\n )${excludeFilter}`;\n\n const result = await rv.RunView<MJUserEntity>({\n EntityName: 'MJ: Users',\n ExtraFilter: searchFilter,\n OrderBy: 'Name ASC',\n MaxRows: 20,\n ResultType: 'entity_object'\n }, this.currentUser);\n\n console.log('User search result:', {\n query,\n success: result.Success,\n count: result.Results?.length,\n error: result.ErrorMessage\n });\n\n if (result.Success && result.Results) {\n this.searchResults = result.Results.map(user => ({\n id: user.ID,\n name: user.Name,\n email: user.Email,\n firstName: user.FirstName || '',\n lastName: user.LastName || ''\n }));\n } else {\n console.warn('User search returned no results or failed:', result.ErrorMessage);\n this.searchResults = [];\n }\n } catch (error) {\n console.error('Error searching users:', error);\n this.searchResults = [];\n } finally {\n this.isSearching = false;\n this.cdr.detectChanges();\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';
|
|
2
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
2
3
|
import { UserInfo } from '@memberjunction/core';
|
|
3
4
|
import { MJTaskEntity, MJTaskDependencyEntity } from '@memberjunction/core-entities';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
@@ -7,7 +8,7 @@ import * as i0 from "@angular/core";
|
|
|
7
8
|
* Generic component that displays tasks based on provided filter
|
|
8
9
|
* Supports drilling into individual tasks to see sub-tasks
|
|
9
10
|
*/
|
|
10
|
-
export declare class TasksFullViewComponent implements OnInit, OnChanges {
|
|
11
|
+
export declare class TasksFullViewComponent extends BaseAngularComponent implements OnInit, OnChanges {
|
|
11
12
|
environmentId: string;
|
|
12
13
|
currentUser: UserInfo;
|
|
13
14
|
baseFilter: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks-full-view.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/task/tasks-full-view.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"tasks-full-view.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/task/tasks-full-view.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAAE,QAAQ,EAAW,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAsB,MAAM,+BAA+B,CAAC;;AAKzG;;;;GAIG;AACH,qBA2Ha,sBAAuB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAClF,aAAa,EAAG,MAAM,CAAC;IACvB,WAAW,EAAG,QAAQ,CAAC;IACvB,UAAU,EAAE,MAAM,CAAS;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB;oBAAkC,MAAM;kBAAY,MAAM;OAAM;IAChF,YAAY,8BAAqC;IAEpD,QAAQ,EAAE,YAAY,EAAE,CAAM;IAC9B,aAAa,EAAE,YAAY,EAAE,CAAM;IACnC,QAAQ,EAAE,YAAY,EAAE,CAAM;IAC9B,kBAAkB,EAAE,YAAY,EAAE,CAAM;IACxC,gBAAgB,EAAE,sBAAsB,EAAE,CAAM;IAChD,WAAW,sBAA6B;IACxC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IACzC,mBAAmB,EAAE,OAAO,CAAS;IACrC,SAAS,EAAE,OAAO,CAAS;IAClC,OAAO,CAAC,kBAAkB,CAAkB;IAE5C,QAAQ;IAIR,WAAW,CAAC,OAAO,EAAE,aAAa;IAerB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA4D1B,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;YAY7C,iBAAiB;YAgDjB,oBAAoB;YAkCpB,aAAa;IA0EpB,cAAc,IAAI,IAAI;IAYtB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAK3C,kBAAkB,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKzE,cAAc,IAAI,MAAM;IAMxB,wBAAwB,IAAI,MAAM;yCAtS9B,sBAAsB;2CAAtB,sBAAsB;CA8SlC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
2
3
|
import { RunView } from '@memberjunction/core';
|
|
3
4
|
import { TaskComponent } from '@memberjunction/ng-tasks';
|
|
4
5
|
import { AIEngineBase } from '@memberjunction/ai-engine-base';
|
|
@@ -43,7 +44,7 @@ function TasksFullViewComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
43
44
|
* Generic component that displays tasks based on provided filter
|
|
44
45
|
* Supports drilling into individual tasks to see sub-tasks
|
|
45
46
|
*/
|
|
46
|
-
export class TasksFullViewComponent {
|
|
47
|
+
export class TasksFullViewComponent extends BaseAngularComponent {
|
|
47
48
|
environmentId;
|
|
48
49
|
currentUser;
|
|
49
50
|
baseFilter = '1=1'; // SQL filter for tasks (default: show all)
|
|
@@ -84,7 +85,7 @@ export class TasksFullViewComponent {
|
|
|
84
85
|
await AIEngineBase.Instance.Config(false);
|
|
85
86
|
this.aiEngineConfigured = true;
|
|
86
87
|
}
|
|
87
|
-
const rv =
|
|
88
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
88
89
|
console.log('📝 Tasks filter SQL:', this.baseFilter);
|
|
89
90
|
// Load all tasks with the provided filter
|
|
90
91
|
const tasksResult = await rv.RunView({
|
|
@@ -141,7 +142,7 @@ export class TasksFullViewComponent {
|
|
|
141
142
|
}
|
|
142
143
|
async loadTaskHierarchy(task) {
|
|
143
144
|
try {
|
|
144
|
-
const rv =
|
|
145
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
145
146
|
// Use RootParentID to load all tasks in this hierarchy
|
|
146
147
|
// If task has no RootParentID, it's the root itself, so use its ID
|
|
147
148
|
const rootId = task.RootParentID || task.ID;
|
|
@@ -179,7 +180,7 @@ export class TasksFullViewComponent {
|
|
|
179
180
|
}
|
|
180
181
|
async loadTaskDependencies(rootId) {
|
|
181
182
|
try {
|
|
182
|
-
const rv =
|
|
183
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
183
184
|
// Load task dependencies where either TaskID or DependsOnTaskID is in this hierarchy
|
|
184
185
|
// Use subquery to find all tasks with this RootParentID
|
|
185
186
|
// Note: Using __mj as the default schema - this is the standard MJ schema
|
|
@@ -219,7 +220,7 @@ export class TasksFullViewComponent {
|
|
|
219
220
|
console.log('💡 No tasks with ConversationDetailID');
|
|
220
221
|
return;
|
|
221
222
|
}
|
|
222
|
-
const rv =
|
|
223
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
223
224
|
const schema = '__mj';
|
|
224
225
|
// Build filter to find agent runs for these conversation details
|
|
225
226
|
// Use a subquery to avoid passing large ID lists
|
|
@@ -302,8 +303,8 @@ export class TasksFullViewComponent {
|
|
|
302
303
|
const completedCount = this.subTasks.filter(t => t.Status === 'Complete').length;
|
|
303
304
|
return `${activeCount} active, ${completedCount} completed, ${this.subTasks.length} sub-tasks`;
|
|
304
305
|
}
|
|
305
|
-
static ɵfac = function TasksFullViewComponent_Factory(__ngFactoryType__) { return
|
|
306
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TasksFullViewComponent, selectors: [["mj-tasks-full-view"]], inputs: { environmentId: "environmentId", currentUser: "currentUser", baseFilter: "baseFilter", activeTaskId: "activeTaskId" }, outputs: { openEntityRecord: "openEntityRecord", taskSelected: "taskSelected" }, features: [i0.ɵɵNgOnChangesFeature], decls: 3, vars: 1, consts: [[1, "tasks-full-view"], [3, "tasks", "title", "description", "showHeader", "showViewToggle", "viewMode"], [1, "task-detail-view", 3, "swoosh-in"], [3, "taskClicked", "tasks", "title", "description", "showHeader", "showViewToggle", "viewMode"], [1, "task-detail-view"], [1, "breadcrumb-nav"], [1, "breadcrumb-back", 3, "click"], [1, "fas", "fa-arrow-left"], [1, "breadcrumb-divider"], [1, "breadcrumb-current"], [3, "taskClicked", "openEntityRecord", "tasks", "ganttTasks", "taskDependencies", "agentRunMap", "title", "description", "showHeader", "showViewToggle", "viewMode"]], template: function TasksFullViewComponent_Template(rf, ctx) { if (rf & 1) {
|
|
306
|
+
static ɵfac = /*@__PURE__*/ (() => { let ɵTasksFullViewComponent_BaseFactory; return function TasksFullViewComponent_Factory(__ngFactoryType__) { return (ɵTasksFullViewComponent_BaseFactory || (ɵTasksFullViewComponent_BaseFactory = i0.ɵɵgetInheritedFactory(TasksFullViewComponent)))(__ngFactoryType__ || TasksFullViewComponent); }; })();
|
|
307
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TasksFullViewComponent, selectors: [["mj-tasks-full-view"]], inputs: { environmentId: "environmentId", currentUser: "currentUser", baseFilter: "baseFilter", activeTaskId: "activeTaskId" }, outputs: { openEntityRecord: "openEntityRecord", taskSelected: "taskSelected" }, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 3, vars: 1, consts: [[1, "tasks-full-view"], [3, "tasks", "title", "description", "showHeader", "showViewToggle", "viewMode"], [1, "task-detail-view", 3, "swoosh-in"], [3, "taskClicked", "tasks", "title", "description", "showHeader", "showViewToggle", "viewMode"], [1, "task-detail-view"], [1, "breadcrumb-nav"], [1, "breadcrumb-back", 3, "click"], [1, "fas", "fa-arrow-left"], [1, "breadcrumb-divider"], [1, "breadcrumb-current"], [3, "taskClicked", "openEntityRecord", "tasks", "ganttTasks", "taskDependencies", "agentRunMap", "title", "description", "showHeader", "showViewToggle", "viewMode"]], template: function TasksFullViewComponent_Template(rf, ctx) { if (rf & 1) {
|
|
307
308
|
i0.ɵɵelementStart(0, "div", 0);
|
|
308
309
|
i0.ɵɵconditionalCreate(1, TasksFullViewComponent_Conditional_1_Template, 1, 6, "mj-task", 1)(2, TasksFullViewComponent_Conditional_2_Template, 11, 12, "div", 2);
|
|
309
310
|
i0.ɵɵelementEnd();
|
|
@@ -371,5 +372,5 @@ export class TasksFullViewComponent {
|
|
|
371
372
|
}], taskSelected: [{
|
|
372
373
|
type: Output
|
|
373
374
|
}] }); })();
|
|
374
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TasksFullViewComponent, { className: "TasksFullViewComponent", filePath: "src/lib/components/task/tasks-full-view.component.ts", lineNumber:
|
|
375
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TasksFullViewComponent, { className: "TasksFullViewComponent", filePath: "src/lib/components/task/tasks-full-view.component.ts", lineNumber: 138 }); })();
|
|
375
376
|
//# sourceMappingURL=tasks-full-view.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks-full-view.component.js","sourceRoot":"","sources":["../../../../src/lib/components/task/tasks-full-view.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';\n\nimport { UserInfo, RunView } from '@memberjunction/core';\nimport { MJTaskEntity, MJTaskDependencyEntity, MJAIAgentRunEntity } from '@memberjunction/core-entities';\nimport { TaskComponent } from '@memberjunction/ng-tasks';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Full-page tasks view with task list and Gantt chart\n * Generic component that displays tasks based on provided filter\n * Supports drilling into individual tasks to see sub-tasks\n */\n@Component({\n selector: 'mj-tasks-full-view',\n standalone: true,\n imports: [TaskComponent],\n template: `\n <div class=\"tasks-full-view\">\n @if (!selectedTask) {\n <!-- Task List View -->\n <mj-task\n [tasks]=\"filteredTasks\"\n [title]=\"'Tasks'\"\n [description]=\"getDescription()\"\n [showHeader]=\"true\"\n [showViewToggle]=\"false\"\n [viewMode]=\"'simple'\"\n (taskClicked)=\"onTaskClick($event)\">\n </mj-task>\n } @else {\n <!-- Task Detail View with Sub-tasks -->\n <div class=\"task-detail-view\" [class.swoosh-in]=\"showDetailAnimation\">\n <!-- Breadcrumb -->\n <div class=\"breadcrumb-nav\">\n <button class=\"breadcrumb-back\" (click)=\"backToTaskList()\">\n <i class=\"fas fa-arrow-left\"></i>\n <span>Back to Tasks</span>\n </button>\n <div class=\"breadcrumb-divider\">/</div>\n <span class=\"breadcrumb-current\">{{ selectedTask.Name }}</span>\n </div>\n\n <!-- Task Details & Sub-tasks with Gantt Toggle -->\n <mj-task\n [tasks]=\"subTasks\"\n [ganttTasks]=\"subTasksWithParent\"\n [taskDependencies]=\"taskDependencies\"\n [agentRunMap]=\"agentRunMap\"\n [title]=\"selectedTask.Name\"\n [description]=\"getTaskDetailDescription()\"\n [showHeader]=\"true\"\n [showViewToggle]=\"true\"\n [viewMode]=\"'gantt'\"\n (taskClicked)=\"onSubTaskClick($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-task>\n </div>\n }\n </div>\n `,\n styles: [`\n .tasks-full-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n }\n\n .task-detail-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n }\n\n .swoosh-in {\n animation: swooshIn 0.3s ease-out;\n }\n\n @keyframes swooshIn {\n from {\n opacity: 0;\n transform: translateX(50px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n }\n\n .breadcrumb-nav {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .breadcrumb-back {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .breadcrumb-back:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-text-disabled);\n }\n\n .breadcrumb-back i {\n font-size: 12px;\n }\n\n .breadcrumb-divider {\n color: var(--mj-text-disabled);\n font-size: 14px;\n }\n\n .breadcrumb-current {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n `]\n})\nexport class TasksFullViewComponent implements OnInit, OnChanges {\n @Input() environmentId!: string;\n @Input() currentUser!: UserInfo;\n @Input() baseFilter: string = '1=1'; // SQL filter for tasks (default: show all)\n @Input() activeTaskId?: string; // Task ID to auto-select and drill into\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n @Output() taskSelected = new EventEmitter<string | null>(); // Emits task ID when drill-down occurs, null when returning to list\n\n public allTasks: MJTaskEntity[] = [];\n public filteredTasks: MJTaskEntity[] = [];\n public subTasks: MJTaskEntity[] = [];\n public subTasksWithParent: MJTaskEntity[] = []; // Includes parent for Gantt hierarchy\n public taskDependencies: MJTaskDependencyEntity[] = []; // Dependencies for Gantt links\n public agentRunMap = new Map<string, string>(); // Maps TaskID -> AgentRunID\n public selectedTask: MJTaskEntity | null = null;\n public showDetailAnimation: boolean = false;\n public isLoading: boolean = false;\n private aiEngineConfigured: boolean = false;\n\n ngOnInit() {\n this.loadTasks();\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // Reload tasks if baseFilter changes\n if (changes['baseFilter'] && !changes['baseFilter'].firstChange) {\n this.loadTasks();\n }\n\n // Auto-drill into task if activeTaskId changes\n if (changes['activeTaskId'] && this.activeTaskId) {\n const task = this.allTasks.find(t => UUIDsEqual(t.ID, this.activeTaskId));\n if (task) {\n this.onTaskClick(task);\n }\n }\n }\n\n public async loadTasks(): Promise<void> {\n this.isLoading = true;\n\n try {\n // Configure AIEngineBase on first load (false = don't force refresh)\n if (!this.aiEngineConfigured) {\n await AIEngineBase.Instance.Config(false);\n this.aiEngineConfigured = true;\n }\n\n const rv = new RunView();\n\n console.log('📝 Tasks filter SQL:', this.baseFilter);\n\n // Load all tasks with the provided filter\n const tasksResult = await rv.RunView<MJTaskEntity>(\n {\n EntityName: 'MJ: Tasks',\n ExtraFilter: this.baseFilter,\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 1000,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n console.log('📊 Tasks query result:', {\n success: tasksResult.Success,\n resultCount: tasksResult.Results?.length || 0,\n errorMessage: tasksResult.ErrorMessage\n });\n\n if (tasksResult.Success) {\n this.allTasks = tasksResult.Results || [];\n this.filteredTasks = this.allTasks;\n console.log(`📋 Loaded ${this.allTasks.length} tasks`);\n if (this.allTasks.length === 0) {\n console.log('💡 No tasks found with current filter');\n } else {\n console.log('✅ Sample task:', {\n id: this.allTasks[0].ID,\n name: this.allTasks[0].Name,\n status: this.allTasks[0].Status,\n conversationDetailID: this.allTasks[0].ConversationDetailID\n });\n }\n } else {\n console.error('❌ Failed to load tasks:', tasksResult.ErrorMessage);\n this.allTasks = [];\n this.filteredTasks = [];\n }\n } catch (error) {\n console.error('Failed to load tasks:', error);\n this.allTasks = [];\n this.filteredTasks = [];\n } finally {\n this.isLoading = false;\n }\n }\n\n public async onTaskClick(task: MJTaskEntity): Promise<void> {\n console.log('Task clicked:', task);\n this.selectedTask = task;\n this.showDetailAnimation = true;\n\n // Emit task selection event for URL tracking\n this.taskSelected.emit(task.ID);\n\n // Load all tasks in the hierarchy using RootParentID\n await this.loadTaskHierarchy(task);\n }\n\n private async loadTaskHierarchy(task: MJTaskEntity): Promise<void> {\n try {\n const rv = new RunView();\n\n // Use RootParentID to load all tasks in this hierarchy\n // If task has no RootParentID, it's the root itself, so use its ID\n const rootId = task.RootParentID || task.ID;\n\n // Load all tasks where RootParentID matches, or tasks that are the root itself\n const hierarchyResult = await rv.RunView<MJTaskEntity>(\n {\n EntityName: 'MJ: Tasks',\n ExtraFilter: `RootParentID='${rootId}' OR ID='${rootId}'`,\n OrderBy: '__mj_CreatedAt ASC',\n MaxRows: 1000,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n if (hierarchyResult.Success) {\n const allHierarchy = hierarchyResult.Results || [];\n\n // For list view: Filter out the clicked task itself - only show its children/descendants\n this.subTasks = allHierarchy.filter(t => !UUIDsEqual(t.ID, task.ID));\n\n // For Gantt view: Include the parent task so hierarchy works correctly\n this.subTasksWithParent = allHierarchy;\n\n console.log(`📋 Loaded ${this.subTasks.length} tasks in hierarchy for root ${rootId}`);\n\n // Load task dependencies for this hierarchy\n await this.loadTaskDependencies(rootId);\n\n // Load agent runs for this hierarchy\n await this.loadAgentRuns(allHierarchy);\n } else {\n console.error('❌ Failed to load task hierarchy:', hierarchyResult.ErrorMessage);\n this.subTasks = [];\n this.subTasksWithParent = [];\n this.taskDependencies = [];\n }\n } catch (error) {\n console.error('Failed to load task hierarchy:', error);\n this.subTasks = [];\n }\n }\n\n private async loadTaskDependencies(rootId: string): Promise<void> {\n try {\n const rv = new RunView();\n\n // Load task dependencies where either TaskID or DependsOnTaskID is in this hierarchy\n // Use subquery to find all tasks with this RootParentID\n // Note: Using __mj as the default schema - this is the standard MJ schema\n const schema = '__mj';\n const depsResult = await rv.RunView<MJTaskDependencyEntity>(\n {\n EntityName: 'MJ: Task Dependencies',\n ExtraFilter: `\n TaskID IN (SELECT ID FROM [${schema}].[vwTasks] WHERE RootParentID='${rootId}' OR ID='${rootId}')\n OR\n DependsOnTaskID IN (SELECT ID FROM [${schema}].[vwTasks] WHERE RootParentID='${rootId}' OR ID='${rootId}')\n `,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n if (depsResult.Success) {\n this.taskDependencies = depsResult.Results || [];\n console.log(`🔗 Loaded ${this.taskDependencies.length} task dependencies`);\n } else {\n console.error('❌ Failed to load task dependencies:', depsResult.ErrorMessage);\n this.taskDependencies = [];\n }\n } catch (error) {\n console.error('Failed to load task dependencies:', error);\n this.taskDependencies = [];\n }\n }\n\n private async loadAgentRuns(tasks: MJTaskEntity[]): Promise<void> {\n try {\n // Clear existing map\n this.agentRunMap.clear();\n\n // Get all unique ConversationDetailIDs from tasks (filter out nulls)\n const conversationDetailIds = tasks\n .filter(t => t.ConversationDetailID != null)\n .map(t => t.ConversationDetailID!);\n\n if (conversationDetailIds.length === 0) {\n console.log('💡 No tasks with ConversationDetailID');\n return;\n }\n\n const rv = new RunView();\n const schema = '__mj';\n\n // Build filter to find agent runs for these conversation details\n // Use a subquery to avoid passing large ID lists\n const taskIds = tasks.map(t => `'${t.ID}'`).join(',');\n\n const agentRunsResult = await rv.RunView<MJAIAgentRunEntity>(\n {\n EntityName: 'MJ: AI Agent Runs',\n ExtraFilter: `\n ConversationDetailID IN (\n SELECT DISTINCT ConversationDetailID\n FROM [${schema}].[vwTasks]\n WHERE ID IN (${taskIds})\n AND ConversationDetailID IS NOT NULL\n )\n `,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n if (agentRunsResult.Success) {\n const agentRuns = agentRunsResult.Results || [];\n console.log(`🤖 Loaded ${agentRuns.length} agent runs`, agentRuns);\n\n // Build map: ConversationDetailID -> AgentRunID\n const convoToRunMap = new Map<string, string>();\n agentRuns.forEach(run => {\n if (run.ConversationDetailID) {\n convoToRunMap.set(run.ConversationDetailID, run.ID);\n console.log(`📝 Mapping ConvoDetailID ${run.ConversationDetailID} -> RunID ${run.ID}`);\n }\n });\n\n // Map TaskID -> AgentRunID using ConversationDetailID as the link\n tasks.forEach(task => {\n console.log(`🔍 Task ${task.Name} - ConvoDetailID: ${task.ConversationDetailID}, AgentID: ${task.AgentID}`);\n if (task.ConversationDetailID) {\n const agentRunId = convoToRunMap.get(task.ConversationDetailID);\n if (agentRunId) {\n this.agentRunMap.set(task.ID, agentRunId);\n console.log(`✅ Mapped Task ${task.ID} -> AgentRun ${agentRunId}`);\n } else {\n console.log(`⚠️ No agent run found for ConvoDetailID ${task.ConversationDetailID}`);\n }\n }\n });\n\n console.log(`🔗 Mapped ${this.agentRunMap.size} tasks to agent runs`, Array.from(this.agentRunMap.entries()));\n } else {\n console.error('❌ Failed to load agent runs:', agentRunsResult.ErrorMessage);\n }\n } catch (error) {\n console.error('Failed to load agent runs:', error);\n }\n }\n\n public backToTaskList(): void {\n this.selectedTask = null;\n this.subTasks = [];\n this.subTasksWithParent = [];\n this.taskDependencies = [];\n this.agentRunMap.clear();\n this.showDetailAnimation = false;\n\n // Emit null to indicate returning to task list (for URL tracking)\n this.taskSelected.emit(null);\n }\n\n public onSubTaskClick(subTask: MJTaskEntity): void {\n console.log('Sub-task clicked:', subTask);\n // Could drill down further if needed\n }\n\n public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {\n // Bubble up the event to parent component\n this.openEntityRecord.emit(event);\n }\n\n public getDescription(): string {\n const activeCount = this.allTasks.filter(t => t.Status === 'Pending' || t.Status === 'In Progress').length;\n const completedCount = this.allTasks.filter(t => t.Status === 'Complete').length;\n return `${activeCount} active, ${completedCount} completed, ${this.allTasks.length} total`;\n }\n\n public getTaskDetailDescription(): string {\n if (this.subTasks.length === 0) {\n return 'No sub-tasks';\n }\n const activeCount = this.subTasks.filter(t => t.Status === 'Pending' || t.Status === 'In Progress').length;\n const completedCount = this.subTasks.filter(t => t.Status === 'Complete').length;\n return `${activeCount} active, ${completedCount} completed, ${this.subTasks.length} sub-tasks`;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tasks-full-view.component.js","sourceRoot":"","sources":["../../../../src/lib/components/task/tasks-full-view.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\nimport { UserInfo, RunView } from '@memberjunction/core';\nimport { MJTaskEntity, MJTaskDependencyEntity, MJAIAgentRunEntity } from '@memberjunction/core-entities';\nimport { TaskComponent } from '@memberjunction/ng-tasks';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Full-page tasks view with task list and Gantt chart\n * Generic component that displays tasks based on provided filter\n * Supports drilling into individual tasks to see sub-tasks\n */\n@Component({\n selector: 'mj-tasks-full-view',\n standalone: true,\n imports: [TaskComponent],\n template: `\n <div class=\"tasks-full-view\">\n @if (!selectedTask) {\n <!-- Task List View -->\n <mj-task\n [tasks]=\"filteredTasks\"\n [title]=\"'Tasks'\"\n [description]=\"getDescription()\"\n [showHeader]=\"true\"\n [showViewToggle]=\"false\"\n [viewMode]=\"'simple'\"\n (taskClicked)=\"onTaskClick($event)\">\n </mj-task>\n } @else {\n <!-- Task Detail View with Sub-tasks -->\n <div class=\"task-detail-view\" [class.swoosh-in]=\"showDetailAnimation\">\n <!-- Breadcrumb -->\n <div class=\"breadcrumb-nav\">\n <button class=\"breadcrumb-back\" (click)=\"backToTaskList()\">\n <i class=\"fas fa-arrow-left\"></i>\n <span>Back to Tasks</span>\n </button>\n <div class=\"breadcrumb-divider\">/</div>\n <span class=\"breadcrumb-current\">{{ selectedTask.Name }}</span>\n </div>\n\n <!-- Task Details & Sub-tasks with Gantt Toggle -->\n <mj-task\n [tasks]=\"subTasks\"\n [ganttTasks]=\"subTasksWithParent\"\n [taskDependencies]=\"taskDependencies\"\n [agentRunMap]=\"agentRunMap\"\n [title]=\"selectedTask.Name\"\n [description]=\"getTaskDetailDescription()\"\n [showHeader]=\"true\"\n [showViewToggle]=\"true\"\n [viewMode]=\"'gantt'\"\n (taskClicked)=\"onSubTaskClick($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-task>\n </div>\n }\n </div>\n `,\n styles: [`\n .tasks-full-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n }\n\n .task-detail-view {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n }\n\n .swoosh-in {\n animation: swooshIn 0.3s ease-out;\n }\n\n @keyframes swooshIn {\n from {\n opacity: 0;\n transform: translateX(50px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n }\n\n .breadcrumb-nav {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .breadcrumb-back {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .breadcrumb-back:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-text-disabled);\n }\n\n .breadcrumb-back i {\n font-size: 12px;\n }\n\n .breadcrumb-divider {\n color: var(--mj-text-disabled);\n font-size: 14px;\n }\n\n .breadcrumb-current {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n `]\n})\nexport class TasksFullViewComponent extends BaseAngularComponent implements OnInit, OnChanges {\n @Input() environmentId!: string;\n @Input() currentUser!: UserInfo;\n @Input() baseFilter: string = '1=1'; // SQL filter for tasks (default: show all)\n @Input() activeTaskId?: string; // Task ID to auto-select and drill into\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n @Output() taskSelected = new EventEmitter<string | null>(); // Emits task ID when drill-down occurs, null when returning to list\n\n public allTasks: MJTaskEntity[] = [];\n public filteredTasks: MJTaskEntity[] = [];\n public subTasks: MJTaskEntity[] = [];\n public subTasksWithParent: MJTaskEntity[] = []; // Includes parent for Gantt hierarchy\n public taskDependencies: MJTaskDependencyEntity[] = []; // Dependencies for Gantt links\n public agentRunMap = new Map<string, string>(); // Maps TaskID -> AgentRunID\n public selectedTask: MJTaskEntity | null = null;\n public showDetailAnimation: boolean = false;\n public isLoading: boolean = false;\n private aiEngineConfigured: boolean = false;\n\n ngOnInit() {\n this.loadTasks();\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // Reload tasks if baseFilter changes\n if (changes['baseFilter'] && !changes['baseFilter'].firstChange) {\n this.loadTasks();\n }\n\n // Auto-drill into task if activeTaskId changes\n if (changes['activeTaskId'] && this.activeTaskId) {\n const task = this.allTasks.find(t => UUIDsEqual(t.ID, this.activeTaskId));\n if (task) {\n this.onTaskClick(task);\n }\n }\n }\n\n public async loadTasks(): Promise<void> {\n this.isLoading = true;\n\n try {\n // Configure AIEngineBase on first load (false = don't force refresh)\n if (!this.aiEngineConfigured) {\n await AIEngineBase.Instance.Config(false);\n this.aiEngineConfigured = true;\n }\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n console.log('📝 Tasks filter SQL:', this.baseFilter);\n\n // Load all tasks with the provided filter\n const tasksResult = await rv.RunView<MJTaskEntity>(\n {\n EntityName: 'MJ: Tasks',\n ExtraFilter: this.baseFilter,\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 1000,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n console.log('📊 Tasks query result:', {\n success: tasksResult.Success,\n resultCount: tasksResult.Results?.length || 0,\n errorMessage: tasksResult.ErrorMessage\n });\n\n if (tasksResult.Success) {\n this.allTasks = tasksResult.Results || [];\n this.filteredTasks = this.allTasks;\n console.log(`📋 Loaded ${this.allTasks.length} tasks`);\n if (this.allTasks.length === 0) {\n console.log('💡 No tasks found with current filter');\n } else {\n console.log('✅ Sample task:', {\n id: this.allTasks[0].ID,\n name: this.allTasks[0].Name,\n status: this.allTasks[0].Status,\n conversationDetailID: this.allTasks[0].ConversationDetailID\n });\n }\n } else {\n console.error('❌ Failed to load tasks:', tasksResult.ErrorMessage);\n this.allTasks = [];\n this.filteredTasks = [];\n }\n } catch (error) {\n console.error('Failed to load tasks:', error);\n this.allTasks = [];\n this.filteredTasks = [];\n } finally {\n this.isLoading = false;\n }\n }\n\n public async onTaskClick(task: MJTaskEntity): Promise<void> {\n console.log('Task clicked:', task);\n this.selectedTask = task;\n this.showDetailAnimation = true;\n\n // Emit task selection event for URL tracking\n this.taskSelected.emit(task.ID);\n\n // Load all tasks in the hierarchy using RootParentID\n await this.loadTaskHierarchy(task);\n }\n\n private async loadTaskHierarchy(task: MJTaskEntity): Promise<void> {\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n // Use RootParentID to load all tasks in this hierarchy\n // If task has no RootParentID, it's the root itself, so use its ID\n const rootId = task.RootParentID || task.ID;\n\n // Load all tasks where RootParentID matches, or tasks that are the root itself\n const hierarchyResult = await rv.RunView<MJTaskEntity>(\n {\n EntityName: 'MJ: Tasks',\n ExtraFilter: `RootParentID='${rootId}' OR ID='${rootId}'`,\n OrderBy: '__mj_CreatedAt ASC',\n MaxRows: 1000,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n if (hierarchyResult.Success) {\n const allHierarchy = hierarchyResult.Results || [];\n\n // For list view: Filter out the clicked task itself - only show its children/descendants\n this.subTasks = allHierarchy.filter(t => !UUIDsEqual(t.ID, task.ID));\n\n // For Gantt view: Include the parent task so hierarchy works correctly\n this.subTasksWithParent = allHierarchy;\n\n console.log(`📋 Loaded ${this.subTasks.length} tasks in hierarchy for root ${rootId}`);\n\n // Load task dependencies for this hierarchy\n await this.loadTaskDependencies(rootId);\n\n // Load agent runs for this hierarchy\n await this.loadAgentRuns(allHierarchy);\n } else {\n console.error('❌ Failed to load task hierarchy:', hierarchyResult.ErrorMessage);\n this.subTasks = [];\n this.subTasksWithParent = [];\n this.taskDependencies = [];\n }\n } catch (error) {\n console.error('Failed to load task hierarchy:', error);\n this.subTasks = [];\n }\n }\n\n private async loadTaskDependencies(rootId: string): Promise<void> {\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n // Load task dependencies where either TaskID or DependsOnTaskID is in this hierarchy\n // Use subquery to find all tasks with this RootParentID\n // Note: Using __mj as the default schema - this is the standard MJ schema\n const schema = '__mj';\n const depsResult = await rv.RunView<MJTaskDependencyEntity>(\n {\n EntityName: 'MJ: Task Dependencies',\n ExtraFilter: `\n TaskID IN (SELECT ID FROM [${schema}].[vwTasks] WHERE RootParentID='${rootId}' OR ID='${rootId}')\n OR\n DependsOnTaskID IN (SELECT ID FROM [${schema}].[vwTasks] WHERE RootParentID='${rootId}' OR ID='${rootId}')\n `,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n if (depsResult.Success) {\n this.taskDependencies = depsResult.Results || [];\n console.log(`🔗 Loaded ${this.taskDependencies.length} task dependencies`);\n } else {\n console.error('❌ Failed to load task dependencies:', depsResult.ErrorMessage);\n this.taskDependencies = [];\n }\n } catch (error) {\n console.error('Failed to load task dependencies:', error);\n this.taskDependencies = [];\n }\n }\n\n private async loadAgentRuns(tasks: MJTaskEntity[]): Promise<void> {\n try {\n // Clear existing map\n this.agentRunMap.clear();\n\n // Get all unique ConversationDetailIDs from tasks (filter out nulls)\n const conversationDetailIds = tasks\n .filter(t => t.ConversationDetailID != null)\n .map(t => t.ConversationDetailID!);\n\n if (conversationDetailIds.length === 0) {\n console.log('💡 No tasks with ConversationDetailID');\n return;\n }\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const schema = '__mj';\n\n // Build filter to find agent runs for these conversation details\n // Use a subquery to avoid passing large ID lists\n const taskIds = tasks.map(t => `'${t.ID}'`).join(',');\n\n const agentRunsResult = await rv.RunView<MJAIAgentRunEntity>(\n {\n EntityName: 'MJ: AI Agent Runs',\n ExtraFilter: `\n ConversationDetailID IN (\n SELECT DISTINCT ConversationDetailID\n FROM [${schema}].[vwTasks]\n WHERE ID IN (${taskIds})\n AND ConversationDetailID IS NOT NULL\n )\n `,\n ResultType: 'entity_object'\n },\n this.currentUser\n );\n\n if (agentRunsResult.Success) {\n const agentRuns = agentRunsResult.Results || [];\n console.log(`🤖 Loaded ${agentRuns.length} agent runs`, agentRuns);\n\n // Build map: ConversationDetailID -> AgentRunID\n const convoToRunMap = new Map<string, string>();\n agentRuns.forEach(run => {\n if (run.ConversationDetailID) {\n convoToRunMap.set(run.ConversationDetailID, run.ID);\n console.log(`📝 Mapping ConvoDetailID ${run.ConversationDetailID} -> RunID ${run.ID}`);\n }\n });\n\n // Map TaskID -> AgentRunID using ConversationDetailID as the link\n tasks.forEach(task => {\n console.log(`🔍 Task ${task.Name} - ConvoDetailID: ${task.ConversationDetailID}, AgentID: ${task.AgentID}`);\n if (task.ConversationDetailID) {\n const agentRunId = convoToRunMap.get(task.ConversationDetailID);\n if (agentRunId) {\n this.agentRunMap.set(task.ID, agentRunId);\n console.log(`✅ Mapped Task ${task.ID} -> AgentRun ${agentRunId}`);\n } else {\n console.log(`⚠️ No agent run found for ConvoDetailID ${task.ConversationDetailID}`);\n }\n }\n });\n\n console.log(`🔗 Mapped ${this.agentRunMap.size} tasks to agent runs`, Array.from(this.agentRunMap.entries()));\n } else {\n console.error('❌ Failed to load agent runs:', agentRunsResult.ErrorMessage);\n }\n } catch (error) {\n console.error('Failed to load agent runs:', error);\n }\n }\n\n public backToTaskList(): void {\n this.selectedTask = null;\n this.subTasks = [];\n this.subTasksWithParent = [];\n this.taskDependencies = [];\n this.agentRunMap.clear();\n this.showDetailAnimation = false;\n\n // Emit null to indicate returning to task list (for URL tracking)\n this.taskSelected.emit(null);\n }\n\n public onSubTaskClick(subTask: MJTaskEntity): void {\n console.log('Sub-task clicked:', subTask);\n // Could drill down further if needed\n }\n\n public onOpenEntityRecord(event: { entityName: string; recordId: string }): void {\n // Bubble up the event to parent component\n this.openEntityRecord.emit(event);\n }\n\n public getDescription(): string {\n const activeCount = this.allTasks.filter(t => t.Status === 'Pending' || t.Status === 'In Progress').length;\n const completedCount = this.allTasks.filter(t => t.Status === 'Complete').length;\n return `${activeCount} active, ${completedCount} completed, ${this.allTasks.length} total`;\n }\n\n public getTaskDetailDescription(): string {\n if (this.subTasks.length === 0) {\n return 'No sub-tasks';\n }\n const activeCount = this.subTasks.filter(t => t.Status === 'Pending' || t.Status === 'In Progress').length;\n const completedCount = this.subTasks.filter(t => t.Status === 'Complete').length;\n return `${activeCount} active, ${completedCount} completed, ${this.subTasks.length} sub-tasks`;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks-dropdown.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/tasks/tasks-dropdown.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;;AAKrF;;;GAGG;AACH,qBAifa,sBAAuB,YAAW,MAAM,EAAE,SAAS;IAc5D,OAAO,CAAC,kBAAkB;IAbnB,WAAW,EAAG,QAAQ,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IACpC,WAAW,2BAAkC;IAC7C,sBAAsB;wBAAqC,MAAM;gBAAU,MAAM;OAAK;IAEzF,MAAM,EAAE,OAAO,CAAS;IACxB,QAAQ,EAAE,UAAU,EAAE,CAAM;IAC5B,wBAAwB,EAAE,UAAU,EAAE,CAAM;IAC5C,sBAAsB,EAAE,UAAU,EAAE,CAAM;IAEjD,OAAO,CAAC,QAAQ,CAAuB;gBAG7B,kBAAkB,EAAE,kBAAkB;IAGhD,QAAQ;
|
|
1
|
+
{"version":3,"file":"tasks-dropdown.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/tasks/tasks-dropdown.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;;AAKrF;;;GAGG;AACH,qBAifa,sBAAuB,YAAW,MAAM,EAAE,SAAS;IAc5D,OAAO,CAAC,kBAAkB;IAbnB,WAAW,EAAG,QAAQ,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IACpC,WAAW,2BAAkC;IAC7C,sBAAsB;wBAAqC,MAAM;gBAAU,MAAM;OAAK;IAEzF,MAAM,EAAE,OAAO,CAAS;IACxB,QAAQ,EAAE,UAAU,EAAE,CAAM;IAC5B,wBAAwB,EAAE,UAAU,EAAE,CAAM;IAC5C,sBAAsB,EAAE,UAAU,EAAE,CAAM;IAEjD,OAAO,CAAC,QAAQ,CAAuB;gBAG7B,kBAAkB,EAAE,kBAAkB;IAGhD,QAAQ;IAgBR,WAAW;IAKX,OAAO,CAAC,UAAU;IAUlB,cAAc,IAAI,IAAI;IAItB,aAAa,IAAI,IAAI;IAIrB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAanC,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAaxC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQxC;;;OAGG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAa5C;;;OAGG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;yCA/GtC,sBAAsB;2CAAtB,sBAAsB;CA0HlC"}
|
|
@@ -210,6 +210,11 @@ export class TasksDropdownComponent {
|
|
|
210
210
|
this.activeTasksService = activeTasksService;
|
|
211
211
|
}
|
|
212
212
|
ngOnInit() {
|
|
213
|
+
// AIEngineBase is deferred at startup; kick off the load early so the
|
|
214
|
+
// template helpers (getAgentIconClass / getAgentLogoUrl) find populated
|
|
215
|
+
// .Agents data when they're called from the template. Fire-and-forget —
|
|
216
|
+
// the helpers fall back to defaults until it's loaded.
|
|
217
|
+
AIEngineBase.Instance.EnsureLoaded();
|
|
213
218
|
// Subscribe to ALL active tasks across ALL conversations
|
|
214
219
|
this.activeTasksService.tasks$
|
|
215
220
|
.pipe(takeUntil(this.destroy$))
|