@memberjunction/ng-dashboards 5.51.0 → 6.1.0-edge.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +7 -0
  2. package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
  3. package/dist/AI/components/agents/agent-configuration.component.js +59 -63
  4. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  5. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +7 -7
  6. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  7. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +21 -21
  8. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  9. package/dist/AI/components/autotagging/shared/classify.types.d.ts +4 -4
  10. package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -1
  11. package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -1
  12. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +14 -19
  13. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -1
  14. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +53 -77
  15. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
  16. package/dist/AI/components/models/model-management.component.d.ts.map +1 -1
  17. package/dist/AI/components/models/model-management.component.js +67 -70
  18. package/dist/AI/components/models/model-management.component.js.map +1 -1
  19. package/dist/AI/components/prompts/prompt-management.component.d.ts.map +1 -1
  20. package/dist/AI/components/prompts/prompt-management.component.js +55 -59
  21. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  22. package/dist/AI/components/system/system-configuration.component.d.ts.map +1 -1
  23. package/dist/AI/components/system/system-configuration.component.js +59 -63
  24. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  25. package/dist/AI/components/tags/tags-resource.component.d.ts +15 -20
  26. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  27. package/dist/AI/components/tags/tags-resource.component.js +51 -77
  28. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  29. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +1 -3
  30. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  31. package/dist/AI/components/vectors/vector-management-resource.component.js +22 -43
  32. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  33. package/dist/Actions/components/explorer/action-card.component.js +6 -6
  34. package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
  35. package/dist/Actions/components/explorer/action-list-item.component.js +3 -3
  36. package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
  37. package/dist/Actions/index.d.ts +0 -1
  38. package/dist/Actions/index.d.ts.map +1 -1
  39. package/dist/Actions/index.js +0 -1
  40. package/dist/Actions/index.js.map +1 -1
  41. package/dist/Admin/admin-dev-tools-resource.component.d.ts.map +1 -1
  42. package/dist/Admin/admin-dev-tools-resource.component.js +14 -0
  43. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
  44. package/dist/Admin/base-admin-container.component.d.ts.map +1 -1
  45. package/dist/Admin/base-admin-container.component.js +15 -0
  46. package/dist/Admin/base-admin-container.component.js.map +1 -1
  47. package/dist/DevTools/grid-width-lab.component.d.ts +78 -0
  48. package/dist/DevTools/grid-width-lab.component.d.ts.map +1 -0
  49. package/dist/DevTools/grid-width-lab.component.js +248 -0
  50. package/dist/DevTools/grid-width-lab.component.js.map +1 -0
  51. package/dist/DevTools/index.d.ts +2 -0
  52. package/dist/DevTools/index.d.ts.map +1 -1
  53. package/dist/DevTools/index.js +2 -0
  54. package/dist/DevTools/index.js.map +1 -1
  55. package/dist/DevTools/tab-strip-lab.component.d.ts +76 -0
  56. package/dist/DevTools/tab-strip-lab.component.d.ts.map +1 -0
  57. package/dist/DevTools/tab-strip-lab.component.js +247 -0
  58. package/dist/DevTools/tab-strip-lab.component.js.map +1 -0
  59. package/dist/Home/home-application.d.ts +5 -0
  60. package/dist/Home/home-application.d.ts.map +1 -1
  61. package/dist/Home/home-application.js +9 -0
  62. package/dist/Home/home-application.js.map +1 -1
  63. package/dist/Home/home-dashboard.component.d.ts.map +1 -1
  64. package/dist/Home/home-dashboard.component.js +0 -6
  65. package/dist/Home/home-dashboard.component.js.map +1 -1
  66. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts +7 -3
  67. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
  68. package/dist/SystemDiagnostics/system-diagnostics.component.js +22 -21
  69. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  70. package/dist/Testing/components/testing-explorer.component.d.ts +9 -0
  71. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  72. package/dist/Testing/components/testing-explorer.component.js +28 -5
  73. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  74. package/dist/actions-dashboards.module.d.ts +23 -24
  75. package/dist/actions-dashboards.module.d.ts.map +1 -1
  76. package/dist/actions-dashboards.module.js +0 -5
  77. package/dist/actions-dashboards.module.js.map +1 -1
  78. package/dist/ai-dashboards.module.d.ts +1 -1
  79. package/dist/ai-dashboards.module.d.ts.map +1 -1
  80. package/dist/ai-dashboards.module.js +4 -1
  81. package/dist/ai-dashboards.module.js.map +1 -1
  82. package/dist/core-dashboards.module.d.ts +46 -42
  83. package/dist/core-dashboards.module.d.ts.map +1 -1
  84. package/dist/core-dashboards.module.js +22 -0
  85. package/dist/core-dashboards.module.js.map +1 -1
  86. package/dist/public-api.d.ts +1 -1
  87. package/dist/public-api.d.ts.map +1 -1
  88. package/dist/public-api.js +1 -1
  89. package/dist/public-api.js.map +1 -1
  90. package/dist/shared/action-scheduled-job.d.ts +58 -0
  91. package/dist/shared/action-scheduled-job.d.ts.map +1 -0
  92. package/dist/shared/action-scheduled-job.js +77 -0
  93. package/dist/shared/action-scheduled-job.js.map +1 -0
  94. package/package.json +73 -70
  95. package/dist/Actions/components/scheduled-actions.component.d.ts +0 -16
  96. package/dist/Actions/components/scheduled-actions.component.d.ts.map +0 -1
  97. package/dist/Actions/components/scheduled-actions.component.js +0 -57
  98. package/dist/Actions/components/scheduled-actions.component.js.map +0 -1
@@ -4,7 +4,7 @@
4
4
  * Self-contained sub-page: owns its header-interior, the source cards grid,
5
5
  * the per-source detail slide-in, and the quick-schedule dialog. Receives the
6
6
  * shared raw data needed to build the cards (sources, items, tags, runs, and
7
- * the cached ScheduledAction + EntityRecordDocument lookups) from the host
7
+ * the cached Scheduled Job + EntityRecordDocument lookups) from the host
8
8
  * orchestrator via `@Input()`. Cross-tab concerns — opening the add/edit slide-in
9
9
  * form, running the pipeline, opening a content-item detail, and reloading the
10
10
  * shared source list after a mutation — bubble up via `@Output()`.
@@ -20,6 +20,7 @@ import { MJNotificationService } from '@memberjunction/ng-notifications';
20
20
  import { MJConfirmService } from '@memberjunction/ng-ui-components';
21
21
  import { AIEngineBase } from '@memberjunction/ai-engine-base';
22
22
  import { KnowledgeHubMetadataEngine } from '@memberjunction/core-entities';
23
+ import { BuildSingleStaticParamConfiguration, ResolveActionJobTypeID } from '../../../../shared/action-scheduled-job';
23
24
  import { formatNumber, formatDate, computeDuration, displayStatus, getSourceTypeIcon, CronToHumanReadable, deriveDisplayName } from '../shared/classify.format';
24
25
  import * as i0 from "@angular/core";
25
26
  import * as i1 from "@angular/forms";
@@ -188,9 +189,9 @@ function ClassifySourcesTabComponent_For_20_Template(rf, ctx) { if (rf & 1) {
188
189
  i0.ɵɵadvance(5);
189
190
  i0.ɵɵtextInterpolate(card_r4.LastRunAgo);
190
191
  i0.ɵɵadvance(3);
191
- i0.ɵɵconditional(card_r4.ScheduledActionID ? 35 : -1);
192
+ i0.ɵɵconditional(card_r4.ScheduledJobID ? 35 : -1);
192
193
  i0.ɵɵadvance(11);
193
- i0.ɵɵconditional(!card_r4.ScheduledActionID ? 46 : -1);
194
+ i0.ɵɵconditional(!card_r4.ScheduledJobID ? 46 : -1);
194
195
  } }
195
196
  function ClassifySourcesTabComponent_Conditional_27_Conditional_9_Template(rf, ctx) { if (rf & 1) {
196
197
  i0.ɵɵelementStart(0, "div", 10);
@@ -655,14 +656,14 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
655
656
  get TotalTagCount() {
656
657
  return this._totalTagCount;
657
658
  }
658
- /** Cached ScheduledAction entities, keyed by normalized ID, supplied by the host. */
659
- _scheduledActions = new Map();
660
- set ScheduledActions(value) {
661
- this._scheduledActions = value ?? new Map();
659
+ /** Cached Scheduled Job entities, keyed by normalized ID, supplied by the host. */
660
+ _scheduledJobs = new Map();
661
+ set ScheduledJobs(value) {
662
+ this._scheduledJobs = value ?? new Map();
662
663
  this.rebuild();
663
664
  }
664
- get ScheduledActions() {
665
- return this._scheduledActions;
665
+ get ScheduledJobs() {
666
+ return this._scheduledJobs;
666
667
  }
667
668
  /** Cache: EntityRecordDocument ID → RecordID, supplied by the host. */
668
669
  _entityRecordDocCache = new Map();
@@ -762,9 +763,9 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
762
763
  const typeName = source['ContentSourceType'] ?? 'Unknown';
763
764
  const lastRunStatus = lastRun ? lastRun['Status']?.toLowerCase() : null;
764
765
  const hasError = lastRunStatus === 'error' || lastRunStatus === 'failed';
765
- const scheduledActionID = source['ScheduledActionID'] ?? null;
766
- const scheduledActionName = source['ScheduledAction'] ?? null;
767
- const cronExpr = scheduledActionID ? this.getScheduledActionCron(scheduledActionID) : null;
766
+ const scheduledJobID = source['ScheduledJobID'] ?? null;
767
+ const scheduledJobName = source['ScheduledJob'] ?? null;
768
+ const cronExpr = scheduledJobID ? this.getScheduledJobCron(scheduledJobID) : null;
768
769
  return {
769
770
  ID: id,
770
771
  Name: source['Name'] ?? 'Unnamed Source',
@@ -787,8 +788,8 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
787
788
  EntityID: source['EntityID'] ?? '',
788
789
  EntityDocumentID: source['EntityDocumentID'] ?? '',
789
790
  RequiresFileType: this.sourceTypeRequiresFileType(source['ContentSourceTypeID']),
790
- ScheduledActionID: scheduledActionID,
791
- ScheduledActionName: scheduledActionName,
791
+ ScheduledJobID: scheduledJobID,
792
+ ScheduledJobName: scheduledJobName,
792
793
  ScheduleDescription: cronExpr ? CronToHumanReadable(cronExpr) : null,
793
794
  };
794
795
  });
@@ -959,9 +960,9 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
959
960
  const diffDays = Math.floor(diffHours / 24);
960
961
  return `${diffDays}d ago`;
961
962
  }
962
- /** Looks up the cron expression for a cached ScheduledAction by ID */
963
- getScheduledActionCron(scheduledActionID) {
964
- const cached = this._scheduledActions.get(NormalizeUUID(scheduledActionID));
963
+ /** Looks up the cron expression for a cached Scheduled Job by ID */
964
+ getScheduledJobCron(scheduledJobID) {
965
+ const cached = this._scheduledJobs.get(NormalizeUUID(scheduledJobID));
965
966
  return cached?.CronExpression ?? null;
966
967
  }
967
968
  /** Returns the CSS class for a pipeline status badge color */
@@ -1013,8 +1014,8 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
1013
1014
  this.cdr.detectChanges();
1014
1015
  }
1015
1016
  /**
1016
- * Saves a new ScheduledAction for the current source, links it via
1017
- * ContentSource.ScheduledActionID, and creates the default action params
1017
+ * Saves a new Scheduled Job (type: Action) for the current source, links it via
1018
+ * ContentSource.ScheduledJobID, and creates the default action params
1018
1019
  * for the Autotag and Vectorize action.
1019
1020
  */
1020
1021
  async SaveSchedule() {
@@ -1031,29 +1032,33 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
1031
1032
  MJNotificationService.Instance.CreateSimpleNotification('Could not find the "Autotag and Vectorize Content" action. Please check action configuration.', 'error', 5000);
1032
1033
  return;
1033
1034
  }
1034
- // 2. Create the ScheduledAction
1035
- const scheduledAction = await p.GetEntityObject('MJ: Scheduled Actions', p.CurrentUser);
1036
- scheduledAction.NewRecord();
1037
- scheduledAction.Name = `Autotag: ${card.Name}`;
1038
- scheduledAction.Description = `Automated classification pipeline for content source "${card.Name}"`;
1039
- scheduledAction.ActionID = actionID;
1040
- scheduledAction.Type = 'Custom';
1041
- scheduledAction.CronExpression = this.ScheduleCron;
1042
- scheduledAction.CustomCronExpression = this.ScheduleCron;
1043
- scheduledAction.Status = this.ScheduleEnabled ? 'Active' : 'Disabled';
1044
- scheduledAction.Timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
1045
- const saved = await scheduledAction.Save();
1035
+ // 2. Resolve the 'Action' scheduled-job type
1036
+ const jobTypeID = await ResolveActionJobTypeID(p);
1037
+ if (!jobTypeID) {
1038
+ MJNotificationService.Instance.CreateSimpleNotification('Could not find the "Action" scheduled job type. Please check scheduling configuration.', 'error', 5000);
1039
+ return;
1040
+ }
1041
+ // 3. Create the Scheduled Job. The action and its parameters ride in Configuration —
1042
+ // ActionScheduledJobDriver reads them from there (no child param rows any more).
1043
+ const scheduledJob = await p.GetEntityObject('MJ: Scheduled Jobs', p.CurrentUser);
1044
+ scheduledJob.NewRecord();
1045
+ scheduledJob.JobTypeID = jobTypeID;
1046
+ scheduledJob.Name = `Autotag: ${card.Name}`;
1047
+ scheduledJob.Description = `Automated classification pipeline for content source "${card.Name}"`;
1048
+ scheduledJob.CronExpression = this.ScheduleCron;
1049
+ scheduledJob.Status = this.ScheduleEnabled ? 'Active' : 'Disabled';
1050
+ scheduledJob.Timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
1051
+ scheduledJob.Configuration = await BuildSingleStaticParamConfiguration(p, actionID, 'EntityNames', card.ID, '[Classify]');
1052
+ const saved = await scheduledJob.Save();
1046
1053
  if (!saved) {
1047
- const errorDetail = scheduledAction.LatestResult?.CompleteMessage ?? 'Unknown error';
1054
+ const errorDetail = scheduledJob.LatestResult?.CompleteMessage ?? 'Unknown error';
1048
1055
  MJNotificationService.Instance.CreateSimpleNotification(`Failed to create schedule: ${errorDetail}`, 'error', 5000);
1049
1056
  return;
1050
1057
  }
1051
- // 3. Create ScheduledActionParam for sourceIDs
1052
- await this.createSourceIDParam(scheduledAction.ID, actionID, card.ID);
1053
- // 4. Link ScheduledAction to ContentSource
1054
- await this.linkScheduleToSource(card.ID, scheduledAction.ID);
1055
- // 5. Cache the new action for cron display
1056
- this._scheduledActions.set(NormalizeUUID(scheduledAction.ID), scheduledAction);
1058
+ // 4. Link the Scheduled Job to the ContentSource
1059
+ await this.linkScheduleToSource(card.ID, scheduledJob.ID);
1060
+ // 5. Cache the new job for cron display
1061
+ this._scheduledJobs.set(NormalizeUUID(scheduledJob.ID), scheduledJob);
1057
1062
  MJNotificationService.Instance.CreateSimpleNotification(`Schedule created: ${CronToHumanReadable(this.ScheduleCron)}`, 'success', 3000);
1058
1063
  this.CloseScheduleDialog();
1059
1064
  this.DataChanged.emit();
@@ -1069,10 +1074,10 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
1069
1074
  }
1070
1075
  }
1071
1076
  /**
1072
- * Removes the schedule from a source card by unlinking the ScheduledActionID.
1077
+ * Removes the schedule from a source card by unlinking the ScheduledJobID.
1073
1078
  */
1074
1079
  async RemoveSchedule(card) {
1075
- if (!card.ScheduledActionID)
1080
+ if (!card.ScheduledJobID)
1076
1081
  return;
1077
1082
  if (!(await this.confirmService.ConfirmDelete({ title: 'Remove Schedule', message: `Remove the schedule "${card.ScheduleDescription ?? 'schedule'}" from "${card.Name}"?`, confirmText: 'Remove' })))
1078
1083
  return;
@@ -1110,43 +1115,14 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
1110
1115
  return null;
1111
1116
  }
1112
1117
  /**
1113
- * Creates a ScheduledActionParam that passes the source ID to the action.
1114
- * Looks up the "EntityNames" action param and sets the source ID as its value.
1115
- */
1116
- async createSourceIDParam(scheduledActionID, actionID, sourceID) {
1117
- const rv = RunView.FromMetadataProvider(this.ProviderToUse);
1118
- const paramResult = await rv.RunView({
1119
- EntityName: 'MJ: Action Params',
1120
- ExtraFilter: `ActionID = '${actionID}' AND Name = 'EntityNames'`,
1121
- Fields: ['ID', 'Name'],
1122
- ResultType: 'simple',
1123
- MaxRows: 1,
1124
- });
1125
- if (!paramResult.Success || paramResult.Results.length === 0) {
1126
- console.warn('[Classify] Could not find EntityNames action param for source ID scheduling');
1127
- return;
1128
- }
1129
- const p = this.ProviderToUse;
1130
- const param = await p.GetEntityObject('MJ: Scheduled Action Params', p.CurrentUser);
1131
- param.NewRecord();
1132
- param.ScheduledActionID = scheduledActionID;
1133
- param.ActionParamID = paramResult.Results[0].ID;
1134
- param.ValueType = 'Static';
1135
- param.Value = sourceID;
1136
- const saved = await param.Save();
1137
- if (!saved) {
1138
- console.warn('[Classify] Failed to save schedule param:', param.LatestResult?.CompleteMessage);
1139
- }
1140
- }
1141
- /**
1142
- * Links (or unlinks) a ScheduledAction to a ContentSource by updating
1143
- * the ContentSource.ScheduledActionID field.
1118
+ * Links (or unlinks) a Scheduled Job to a ContentSource by updating
1119
+ * the ContentSource.ScheduledJobID field.
1144
1120
  */
1145
- async linkScheduleToSource(sourceID, scheduledActionID) {
1121
+ async linkScheduleToSource(sourceID, scheduledJobID) {
1146
1122
  const p = this.ProviderToUse;
1147
1123
  const entity = await p.GetEntityObject('MJ: Content Sources', p.CurrentUser);
1148
1124
  await entity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: sourceID }]));
1149
- entity.ScheduledActionID = scheduledActionID;
1125
+ entity.ScheduledJobID = scheduledJobID;
1150
1126
  const saved = await entity.Save();
1151
1127
  if (!saved) {
1152
1128
  throw new Error(entity.LatestResult?.CompleteMessage ?? 'Failed to update content source');
@@ -1362,7 +1338,7 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
1362
1338
  });
1363
1339
  }
1364
1340
  static ɵfac = /*@__PURE__*/ (() => { let ɵClassifySourcesTabComponent_BaseFactory; return function ClassifySourcesTabComponent_Factory(__ngFactoryType__) { return (ɵClassifySourcesTabComponent_BaseFactory || (ɵClassifySourcesTabComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ClassifySourcesTabComponent)))(__ngFactoryType__ || ClassifySourcesTabComponent); }; })();
1365
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ClassifySourcesTabComponent, selectors: [["classify-sources-tab"]], inputs: { Sources: "Sources", Items: "Items", Tags: "Tags", Runs: "Runs", TotalItemCount: "TotalItemCount", TotalTagCount: "TotalTagCount", ScheduledActions: "ScheduledActions", EntityRecordDocCache: "EntityRecordDocCache" }, outputs: { AddSourceRequested: "AddSourceRequested", AddSourceGuidedRequested: "AddSourceGuidedRequested", EditSourceRequested: "EditSourceRequested", RunSourceRequested: "RunSourceRequested", OpenContentItemRequested: "OpenContentItemRequested", DataChanged: "DataChanged" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 30, vars: 11, consts: [["Title", "Content Sources", "Subtitle", "Configure where content is ingested from"], ["actions", ""], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-wand-magic-sparkles"], [1, "mj-action-label"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-plus"], [3, "Padding", "Flex"], [1, "at-main-area"], [1, "at-loading-overlay"], [1, "at-page-body"], ["Icon", "fa-solid fa-database", "Title", "No content sources yet", "Message", "Use the guided setup to stand up your first source \u2014 pick an entity or URL, configure its document, taxonomy, and domain context in one flow.", 1, "at-sources-empty"], [1, "at-sources-grid"], [1, "at-source-card-full", "at-source-card-clickable"], [1, "at-add-source-card", 3, "click"], [1, "fa-solid", "fa-plus-circle"], [2, "font-size", "0.85rem", "font-weight", "600"], [2, "font-size", "0.72rem"], [1, "at-schedule-overlay"], [3, "Closed", "Provider", "Show", "SourceCard"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-arrows-rotate"], ["text", "Refreshing sources\u2026"], ["ngProjectAs", "[actions]", 5, ["", "actions", ""], 1, "at-sources-empty-actions"], [1, "at-source-card-full", "at-source-card-clickable", 3, "click"], [1, "at-source-card-header"], [1, "at-source-card-icon"], [1, "at-source-card-title"], [1, "at-source-card-type"], [1, "at-source-card-status"], [1, "at-source-mini-status"], [1, "at-source-card-url"], [1, "at-source-card-stats"], [1, "at-source-stat"], [1, "at-source-stat-value"], [1, "at-source-stat-label"], ["title", "Click to remove schedule", 1, "at-schedule-indicator"], [1, "at-source-card-actions"], [1, "at-source-action-btn", 3, "click"], [1, "fa-solid", "fa-pen"], [1, "fa-solid", "fa-play"], [1, "fa-solid", "fa-flask"], [1, "at-source-action-btn", "at-source-schedule-btn"], [1, "at-source-action-btn", "at-source-delete-btn", 3, "click"], [1, "fa-solid", "fa-trash"], ["title", "Click to remove schedule", 1, "at-schedule-indicator", 3, "click"], [1, "fa-regular", "fa-clock"], [1, "at-source-action-btn", "at-source-schedule-btn", 3, "click"], [1, "at-slide-overlay", 3, "click"], [1, "at-slide-panel", "at-detail-panel"], [1, "at-slide-header"], [1, "fa-solid", "fa-database"], ["aria-label", "Close source detail", 1, "at-slide-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "at-slide-body"], ["text", "Loading source details..."], [1, "at-detail-source-header"], [1, "at-detail-item-name"], [1, "at-detail-badges"], [1, "at-detail-badge", "at-detail-badge-type"], [1, "at-detail-badge"], [1, "at-detail-section"], [1, "at-detail-section-label"], [1, "at-detail-meta-grid"], [1, "at-detail-meta-row"], [1, "at-detail-meta-key"], [1, "at-detail-meta-value"], [1, "at-detail-stats-strip"], [1, "at-detail-stat"], [1, "at-detail-stat-value"], [1, "at-detail-stat-label"], [1, "at-detail-section-header-row"], [1, "at-detail-section-controls"], [1, "at-detail-filter-select", 3, "ngModelChange", "ngModel"], [3, "value"], ["title", "Re-queue failed items for processing", 1, "at-action-btn", "at-retry-btn", 3, "click"], [1, "fa-solid", "fa-rotate-right"], [1, "at-detail-content-list"], ["Size", "compact", 3, "Variant", "Title"], [1, "at-detail-content-item"], [1, "at-detail-pagination"], [1, "at-detail-actions"], [1, "at-action-btn", "at-primary-btn", 3, "click"], [1, "at-action-btn", "at-secondary-btn", 3, "click"], [1, "at-action-btn", "at-secondary-btn", "at-source-delete-btn", 3, "click"], ["target", "_blank", 1, "at-detail-link", "at-detail-meta-value", 3, "href"], [1, "at-detail-content-item", 3, "click"], [1, "at-feed-status-dot"], [1, "at-detail-content-item-name"], [1, "at-status-badge"], [1, "at-detail-content-item-tags"], [1, "at-detail-content-item-time"], [1, "at-page-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-left"], [1, "at-page-info"], [1, "fa-solid", "fa-chevron-right"], [1, "at-detail-run-history"], [1, "at-detail-run-row"], [1, "at-run-status-badge"], [1, "at-detail-run-time"], [1, "at-detail-run-duration"], [1, "at-detail-run-items"], [1, "at-schedule-overlay", 3, "click"], [1, "at-schedule-dialog", 3, "click"], [1, "at-schedule-dialog-header"], ["aria-label", "Close", 1, "at-schedule-dialog-close", 3, "click"], [1, "at-schedule-dialog-body"], [1, "at-schedule-field"], [1, "at-schedule-source-name"], [1, "at-schedule-action-name"], ["for", "schedule-cron"], ["id", "schedule-cron", "type", "text", "placeholder", "0 2 * * *", 1, "mj-input", "at-schedule-cron-input", 3, "ngModelChange", "ngModel"], [1, "at-schedule-cron-preview"], [1, "fa-solid", "fa-info-circle"], [1, "at-schedule-field", "at-schedule-toggle-row"], ["for", "schedule-enabled"], ["id", "schedule-enabled", "type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "at-schedule-dialog-footer"], [1, "at-action-btn", "at-primary-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-check"]], template: function ClassifySourcesTabComponent_Template(rf, ctx) { if (rf & 1) {
1341
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ClassifySourcesTabComponent, selectors: [["classify-sources-tab"]], inputs: { Sources: "Sources", Items: "Items", Tags: "Tags", Runs: "Runs", TotalItemCount: "TotalItemCount", TotalTagCount: "TotalTagCount", ScheduledJobs: "ScheduledJobs", EntityRecordDocCache: "EntityRecordDocCache" }, outputs: { AddSourceRequested: "AddSourceRequested", AddSourceGuidedRequested: "AddSourceGuidedRequested", EditSourceRequested: "EditSourceRequested", RunSourceRequested: "RunSourceRequested", OpenContentItemRequested: "OpenContentItemRequested", DataChanged: "DataChanged" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 30, vars: 11, consts: [["Title", "Content Sources", "Subtitle", "Configure where content is ingested from"], ["actions", ""], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-wand-magic-sparkles"], [1, "mj-action-label"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-plus"], [3, "Padding", "Flex"], [1, "at-main-area"], [1, "at-loading-overlay"], [1, "at-page-body"], ["Icon", "fa-solid fa-database", "Title", "No content sources yet", "Message", "Use the guided setup to stand up your first source \u2014 pick an entity or URL, configure its document, taxonomy, and domain context in one flow.", 1, "at-sources-empty"], [1, "at-sources-grid"], [1, "at-source-card-full", "at-source-card-clickable"], [1, "at-add-source-card", 3, "click"], [1, "fa-solid", "fa-plus-circle"], [2, "font-size", "0.85rem", "font-weight", "600"], [2, "font-size", "0.72rem"], [1, "at-schedule-overlay"], [3, "Closed", "Provider", "Show", "SourceCard"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-arrows-rotate"], ["text", "Refreshing sources\u2026"], ["ngProjectAs", "[actions]", 5, ["", "actions", ""], 1, "at-sources-empty-actions"], [1, "at-source-card-full", "at-source-card-clickable", 3, "click"], [1, "at-source-card-header"], [1, "at-source-card-icon"], [1, "at-source-card-title"], [1, "at-source-card-type"], [1, "at-source-card-status"], [1, "at-source-mini-status"], [1, "at-source-card-url"], [1, "at-source-card-stats"], [1, "at-source-stat"], [1, "at-source-stat-value"], [1, "at-source-stat-label"], ["title", "Click to remove schedule", 1, "at-schedule-indicator"], [1, "at-source-card-actions"], [1, "at-source-action-btn", 3, "click"], [1, "fa-solid", "fa-pen"], [1, "fa-solid", "fa-play"], [1, "fa-solid", "fa-flask"], [1, "at-source-action-btn", "at-source-schedule-btn"], [1, "at-source-action-btn", "at-source-delete-btn", 3, "click"], [1, "fa-solid", "fa-trash"], ["title", "Click to remove schedule", 1, "at-schedule-indicator", 3, "click"], [1, "fa-regular", "fa-clock"], [1, "at-source-action-btn", "at-source-schedule-btn", 3, "click"], [1, "at-slide-overlay", 3, "click"], [1, "at-slide-panel", "at-detail-panel"], [1, "at-slide-header"], [1, "fa-solid", "fa-database"], ["aria-label", "Close source detail", 1, "at-slide-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "at-slide-body"], ["text", "Loading source details..."], [1, "at-detail-source-header"], [1, "at-detail-item-name"], [1, "at-detail-badges"], [1, "at-detail-badge", "at-detail-badge-type"], [1, "at-detail-badge"], [1, "at-detail-section"], [1, "at-detail-section-label"], [1, "at-detail-meta-grid"], [1, "at-detail-meta-row"], [1, "at-detail-meta-key"], [1, "at-detail-meta-value"], [1, "at-detail-stats-strip"], [1, "at-detail-stat"], [1, "at-detail-stat-value"], [1, "at-detail-stat-label"], [1, "at-detail-section-header-row"], [1, "at-detail-section-controls"], [1, "at-detail-filter-select", 3, "ngModelChange", "ngModel"], [3, "value"], ["title", "Re-queue failed items for processing", 1, "at-action-btn", "at-retry-btn", 3, "click"], [1, "fa-solid", "fa-rotate-right"], [1, "at-detail-content-list"], ["Size", "compact", 3, "Variant", "Title"], [1, "at-detail-content-item"], [1, "at-detail-pagination"], [1, "at-detail-actions"], [1, "at-action-btn", "at-primary-btn", 3, "click"], [1, "at-action-btn", "at-secondary-btn", 3, "click"], [1, "at-action-btn", "at-secondary-btn", "at-source-delete-btn", 3, "click"], ["target", "_blank", 1, "at-detail-link", "at-detail-meta-value", 3, "href"], [1, "at-detail-content-item", 3, "click"], [1, "at-feed-status-dot"], [1, "at-detail-content-item-name"], [1, "at-status-badge"], [1, "at-detail-content-item-tags"], [1, "at-detail-content-item-time"], [1, "at-page-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-left"], [1, "at-page-info"], [1, "fa-solid", "fa-chevron-right"], [1, "at-detail-run-history"], [1, "at-detail-run-row"], [1, "at-run-status-badge"], [1, "at-detail-run-time"], [1, "at-detail-run-duration"], [1, "at-detail-run-items"], [1, "at-schedule-overlay", 3, "click"], [1, "at-schedule-dialog", 3, "click"], [1, "at-schedule-dialog-header"], ["aria-label", "Close", 1, "at-schedule-dialog-close", 3, "click"], [1, "at-schedule-dialog-body"], [1, "at-schedule-field"], [1, "at-schedule-source-name"], [1, "at-schedule-action-name"], ["for", "schedule-cron"], ["id", "schedule-cron", "type", "text", "placeholder", "0 2 * * *", 1, "mj-input", "at-schedule-cron-input", 3, "ngModelChange", "ngModel"], [1, "at-schedule-cron-preview"], [1, "fa-solid", "fa-info-circle"], [1, "at-schedule-field", "at-schedule-toggle-row"], ["for", "schedule-enabled"], ["id", "schedule-enabled", "type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "at-schedule-dialog-footer"], [1, "at-action-btn", "at-primary-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-check"]], template: function ClassifySourcesTabComponent_Template(rf, ctx) { if (rf & 1) {
1366
1342
  i0.ɵɵelementStart(0, "mj-page-header-interior", 0)(1, "div", 1)(2, "button", 2);
1367
1343
  i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Template_button_click_2_listener() { return ctx.Refresh(); });
1368
1344
  i0.ɵɵconditionalCreate(3, ClassifySourcesTabComponent_Conditional_3_Template, 3, 0)(4, ClassifySourcesTabComponent_Conditional_4_Template, 3, 0);
@@ -1422,7 +1398,7 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
1422
1398
  }
1423
1399
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ClassifySourcesTabComponent, [{
1424
1400
  type: Component,
1425
- args: [{ standalone: false, selector: 'classify-sources-tab', template: "<mj-page-header-interior\n Title=\"Content Sources\"\n Subtitle=\"Configure where content is ingested from\">\n <div actions>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"Refresh()\" [disabled]=\"IsLoading\">\n @if (IsLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> <span class=\"mj-action-label\">Refreshing\u2026</span>\n } @else {\n <i class=\"fa-solid fa-arrows-rotate\"></i> <span class=\"mj-action-label\">Refresh</span>\n }\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"onAddSourceGuided()\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i> <span class=\"mj-action-label\">Add Source (Guided)</span>\n </button>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"onAddSource()\">\n <i class=\"fa-solid fa-plus\"></i> <span class=\"mj-action-label\">Add Source</span>\n </button>\n </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior [Padding]=\"false\" [Flex]=\"true\">\n <div class=\"at-main-area\">\n @if (IsLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Refreshing sources\u2026\"></mj-loading>\n </div>\n }\n <div class=\"at-page-body\">\n @if (SourceCards.length === 0 && !IsLoading) {\n <mj-empty-state class=\"at-sources-empty\" Icon=\"fa-solid fa-database\"\n Title=\"No content sources yet\"\n Message=\"Use the guided setup to stand up your first source \u2014 pick an entity or URL, configure its document, taxonomy, and domain context in one flow.\">\n <div class=\"at-sources-empty-actions\" ngProjectAs=\"[actions]\">\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"onAddSourceGuided()\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i> Add Source (Guided)\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"onAddSource()\">\n <i class=\"fa-solid fa-plus\"></i> Add manually\n </button>\n </div>\n </mj-empty-state>\n }\n\n <div class=\"at-sources-grid\">\n @for (card of SourceCards; track card.ID) {\n <div class=\"at-source-card-full at-source-card-clickable\" (click)=\"OpenSourceDetail(card)\">\n <div class=\"at-source-card-header\">\n <div class=\"at-source-card-icon\"><i [class]=\"card.Icon\"></i></div>\n <div>\n <div class=\"at-source-card-title\">{{ card.Name }}</div>\n <div class=\"at-source-card-type\">{{ card.SourceTypeName }}@if (card.RequiresFileType) { \u00B7 {{ card.FileTypeName }}}</div>\n </div>\n <div class=\"at-source-card-status\" [class]=\"card.StatusClass\">\n <div class=\"at-source-mini-status\" [class]=\"card.StatusClass\"></div>\n {{ card.StatusLabel }}\n </div>\n </div>\n @if (card.URL) {\n <div class=\"at-source-card-url\">{{ card.URL }}</div>\n }\n <div class=\"at-source-card-stats\">\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ formatNumber(card.ItemCount) }}</div>\n <div class=\"at-source-stat-label\">Items</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ formatNumber(card.TagCount) }}</div>\n <div class=\"at-source-stat-label\">Tags</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ card.AvgTags }}</div>\n <div class=\"at-source-stat-label\">Avg Tags</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ card.LastRunAgo }}</div>\n <div class=\"at-source-stat-label\">Last Run</div>\n </div>\n </div>\n <!-- Schedule indicator -->\n @if (card.ScheduledActionID) {\n <div class=\"at-schedule-indicator\" (click)=\"RemoveSchedule(card); $event.stopPropagation()\" title=\"Click to remove schedule\">\n <i class=\"fa-regular fa-clock\"></i>\n <span>{{ GetScheduleLabel(card) }}</span>\n </div>\n }\n <div class=\"at-source-card-actions\">\n <button class=\"at-source-action-btn\" (click)=\"onEditSource(card); $event.stopPropagation()\"><i class=\"fa-solid fa-pen\"></i> Edit</button>\n <button class=\"at-source-action-btn\" (click)=\"onRunSource(card.ID); $event.stopPropagation()\"><i class=\"fa-solid fa-play\"></i> Run</button>\n <button class=\"at-source-action-btn\" (click)=\"OpenDryRunPreview(card); $event.stopPropagation()\"><i class=\"fa-solid fa-flask\"></i> Preview</button>\n @if (!card.ScheduledActionID) {\n <button class=\"at-source-action-btn at-source-schedule-btn\" (click)=\"OpenScheduleDialog(card); $event.stopPropagation()\"><i class=\"fa-regular fa-clock\"></i> Schedule</button>\n }\n <button class=\"at-source-action-btn at-source-delete-btn\" (click)=\"DeleteSource(card); $event.stopPropagation()\"><i class=\"fa-solid fa-trash\"></i> Delete</button>\n </div>\n </div>\n }\n\n <!-- Add Source Card -->\n <div class=\"at-add-source-card\" (click)=\"onAddSource()\">\n <i class=\"fa-solid fa-plus-circle\"></i>\n <span style=\"font-size: 0.85rem; font-weight: 600;\">Add Content Source</span>\n <span style=\"font-size: 0.72rem;\">Web, RSS, Email, Files, API</span>\n </div>\n </div>\n </div>\n </div>\n</mj-page-body-interior>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 SOURCE DETAIL SLIDE-IN \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowSourceDetail) {\n <div class=\"at-slide-overlay\" (click)=\"CloseSourceDetail()\"></div>\n <div class=\"at-slide-panel at-detail-panel\">\n <div class=\"at-slide-header\">\n <h3><i class=\"fa-solid fa-database\"></i> Source Detail</h3>\n <button class=\"at-slide-close\" aria-label=\"Close source detail\" (click)=\"CloseSourceDetail()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n @if (SourceDetailLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Loading source details...\"></mj-loading>\n </div>\n }\n @if (!SourceDetailLoading && SelectedSource) {\n <!-- Source Header -->\n <div class=\"at-detail-source-header\">\n <div class=\"at-source-card-icon\"><i [class]=\"SelectedSource.Icon\"></i></div>\n <div>\n <h4 class=\"at-detail-item-name\">{{ SelectedSource.Name }}</h4>\n <div class=\"at-detail-badges\">\n <span class=\"at-detail-badge at-detail-badge-type\">{{ SelectedSource.SourceTypeName }}</span>\n <span class=\"at-detail-badge\" [class]=\"'at-detail-badge-status-' + SelectedSource.StatusClass\">\n {{ SelectedSource.StatusLabel }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- Configuration -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Configuration</div>\n <div class=\"at-detail-meta-grid\">\n @if (SelectedSource.URL) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">URL</span>\n <a [href]=\"SelectedSource.URL\" target=\"_blank\" class=\"at-detail-link at-detail-meta-value\">{{ SelectedSource.URL }}</a>\n </div>\n }\n @if (SelectedSource.RequiresFileType) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Content Type</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.ContentTypeName }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">File Type</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.FileTypeName }}</span>\n </div>\n }\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Embedding Model</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.EmbeddingModelName }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Vector Index</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.VectorIndexName }}</span>\n </div>\n </div>\n </div>\n\n <!-- Stats -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Statistics</div>\n <div class=\"at-detail-stats-strip\">\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ formatNumber(SelectedSource.ItemCount) }}</div>\n <div class=\"at-detail-stat-label\">Items</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ formatNumber(SelectedSource.TagCount) }}</div>\n <div class=\"at-detail-stat-label\">Tags</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ SelectedSource.AvgTags }}</div>\n <div class=\"at-detail-stat-label\">Avg Tags</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ SelectedSource.LastRunAgo }}</div>\n <div class=\"at-detail-stat-label\">Last Run</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\" [class.at-kpi-error-value]=\"SelectedSource.ErrorCount > 0\">{{ SelectedSource.ErrorCount }}</div>\n <div class=\"at-detail-stat-label\">Errors</div>\n </div>\n </div>\n </div>\n\n <!-- Content Library (status badges, pagination) -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-header-row\">\n <div class=\"at-detail-section-label\">Content Library ({{ FilteredSourceDetailTotal }} of {{ SelectedSource.ItemCount | number }})</div>\n <div class=\"at-detail-section-controls\">\n <select class=\"at-detail-filter-select\" [(ngModel)]=\"SourceDetailStatusFilter\" (ngModelChange)=\"OnSourceDetailStatusFilterChange()\">\n @for (opt of SourceDetailStatusOptions; track opt) {\n <option [value]=\"opt\">{{ opt }}</option>\n }\n </select>\n <button class=\"at-action-btn at-retry-btn\" (click)=\"RetryFailedItems()\" title=\"Re-queue failed items for processing\">\n <i class=\"fa-solid fa-rotate-right\"></i> Retry Failed\n </button>\n </div>\n </div>\n <div class=\"at-detail-content-list\">\n @if (FilteredSourceDetailItems.length === 0) {\n <mj-empty-state Size=\"compact\"\n [Variant]=\"SourceDetailStatusFilter === 'All' ? 'empty' : 'no-results'\"\n [Title]=\"SourceDetailStatusFilter === 'All' ? 'No content items yet.' : 'No items match this filter.'\" />\n }\n @for (ci of FilteredSourceDetailItems; track ci.ID) {\n <div class=\"at-detail-content-item\" (click)=\"OpenContentItemDetail(ci)\">\n <div class=\"at-feed-status-dot\" [class]=\"ci.StatusDot\"></div>\n <span class=\"at-detail-content-item-name\">{{ ci.Name }}</span>\n <span class=\"at-status-badge\" [class]=\"GetStatusBadgeClass(ci.EmbeddingStatus)\">E:{{ ci.EmbeddingStatus }}</span>\n <span class=\"at-status-badge\" [class]=\"GetStatusBadgeClass(ci.TaggingStatus)\">T:{{ ci.TaggingStatus }}</span>\n <span class=\"at-detail-content-item-tags\">{{ ci.TagCount }} tags</span>\n <span class=\"at-detail-content-item-time\">{{ ci.UpdatedAt }}</span>\n </div>\n }\n </div>\n <!-- Pagination -->\n @if (SourceDetailTotalPages > 1) {\n <div class=\"at-detail-pagination\">\n <button class=\"at-page-btn\" [disabled]=\"SourceDetailPage === 0\" (click)=\"SourceDetailPrevPage()\">\n <i class=\"fa-solid fa-chevron-left\"></i> Prev\n </button>\n <span class=\"at-page-info\">Page {{ SourceDetailPage + 1 }} of {{ SourceDetailTotalPages }}</span>\n <button class=\"at-page-btn\" [disabled]=\"SourceDetailPage >= SourceDetailTotalPages - 1\" (click)=\"SourceDetailNextPage()\">\n Next <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n }\n </div>\n\n <!-- Run History -->\n @if (SelectedSource.RunHistory.length > 0) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Recent Runs</div>\n <div class=\"at-detail-run-history\">\n @for (run of SelectedSource.RunHistory; track run.ID) {\n <div class=\"at-detail-run-row\">\n <span class=\"at-run-status-badge\" [class]=\"run.StatusClass\">{{ run.Status }}</span>\n <span class=\"at-detail-run-time\">{{ run.StartedDisplay }}</span>\n <span class=\"at-detail-run-duration\">{{ run.Duration }}</span>\n <span class=\"at-detail-run-items\">{{ run.Items }} items</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"at-detail-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenEditSourceFromDetail()\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"RunSourceFromDetail()\">\n <i class=\"fa-solid fa-play\"></i> Run Now\n </button>\n <button class=\"at-action-btn at-secondary-btn at-source-delete-btn\" (click)=\"DeleteSourceFromDetail()\">\n <i class=\"fa-solid fa-trash\"></i> Delete\n </button>\n </div>\n }\n </div>\n </div>\n}\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 SCHEDULE DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowScheduleDialog && SchedulingSourceCard) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseScheduleDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-regular fa-clock\"></i> Schedule Pipeline</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseScheduleDialog()\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>Source</label>\n <div class=\"at-schedule-source-name\">\n <i [class]=\"SchedulingSourceCard.Icon\"></i>\n {{ SchedulingSourceCard.Name }}\n </div>\n </div>\n <div class=\"at-schedule-field\">\n <label>Action</label>\n <div class=\"at-schedule-action-name\">Autotag and Vectorize Content</div>\n </div>\n <div class=\"at-schedule-field\">\n <label for=\"schedule-cron\">Cron Expression</label>\n <input id=\"schedule-cron\"\n type=\"text\"\n class=\"mj-input at-schedule-cron-input\"\n [(ngModel)]=\"ScheduleCron\"\n placeholder=\"0 2 * * *\" />\n <div class=\"at-schedule-cron-preview\">\n <i class=\"fa-solid fa-info-circle\"></i>\n {{ GetCronPreview(ScheduleCron) }}\n </div>\n </div>\n <div class=\"at-schedule-field at-schedule-toggle-row\">\n <label for=\"schedule-enabled\">Enabled</label>\n <input id=\"schedule-enabled\"\n type=\"checkbox\"\n class=\"mj-checkbox\"\n [(ngModel)]=\"ScheduleEnabled\" />\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveSchedule()\" [disabled]=\"ScheduleSaving\">\n @if (ScheduleSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-check\"></i> Create Schedule\n }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseScheduleDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 DRY-RUN DISPOSITION PREVIEW (in-memory, nothing persisted) \u2550\u2550\u2550\u2550\u2550\u2550 -->\n<classify-dry-run-preview\n [Provider]=\"Provider\"\n [Show]=\"ShowDryRunPreview\"\n [SourceCard]=\"DryRunSourceCard\"\n (Closed)=\"CloseDryRunPreview()\">\n</classify-dry-run-preview>\n", styles: ["/*\n * Content Sources tab styles.\n *\n * The host (AutotaggingPipelineResourceComponent) uses ViewEncapsulation.None,\n * so its `.at-*` rules are global and already style this tab's markup (cards,\n * source-detail slide-in, schedule dialog) while it renders inside the host\n * shell. Tab-specific rules would live here; none are needed during the\n * host-slim step.\n */\n\n.at-sources-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n gap: 10px;\n padding: 48px 24px;\n background: var(--mj-bg-surface-card);\n border: 1px dashed var(--mj-border-default);\n border-radius: 12px;\n}\n.at-sources-empty > i {\n font-size: 2rem;\n color: var(--mj-brand-primary);\n}\n.at-sources-empty h3 {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-primary);\n}\n.at-sources-empty p {\n margin: 0;\n max-width: 460px;\n font-size: 0.85rem;\n color: var(--mj-text-muted);\n line-height: 1.5;\n}\n.at-sources-empty-actions {\n display: flex;\n gap: 8px;\n margin-top: 6px;\n}\n"] }]
1401
+ args: [{ standalone: false, selector: 'classify-sources-tab', template: "<mj-page-header-interior\n Title=\"Content Sources\"\n Subtitle=\"Configure where content is ingested from\">\n <div actions>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"Refresh()\" [disabled]=\"IsLoading\">\n @if (IsLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> <span class=\"mj-action-label\">Refreshing\u2026</span>\n } @else {\n <i class=\"fa-solid fa-arrows-rotate\"></i> <span class=\"mj-action-label\">Refresh</span>\n }\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"onAddSourceGuided()\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i> <span class=\"mj-action-label\">Add Source (Guided)</span>\n </button>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"onAddSource()\">\n <i class=\"fa-solid fa-plus\"></i> <span class=\"mj-action-label\">Add Source</span>\n </button>\n </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior [Padding]=\"false\" [Flex]=\"true\">\n <div class=\"at-main-area\">\n @if (IsLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Refreshing sources\u2026\"></mj-loading>\n </div>\n }\n <div class=\"at-page-body\">\n @if (SourceCards.length === 0 && !IsLoading) {\n <mj-empty-state class=\"at-sources-empty\" Icon=\"fa-solid fa-database\"\n Title=\"No content sources yet\"\n Message=\"Use the guided setup to stand up your first source \u2014 pick an entity or URL, configure its document, taxonomy, and domain context in one flow.\">\n <div class=\"at-sources-empty-actions\" ngProjectAs=\"[actions]\">\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"onAddSourceGuided()\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i> Add Source (Guided)\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"onAddSource()\">\n <i class=\"fa-solid fa-plus\"></i> Add manually\n </button>\n </div>\n </mj-empty-state>\n }\n\n <div class=\"at-sources-grid\">\n @for (card of SourceCards; track card.ID) {\n <div class=\"at-source-card-full at-source-card-clickable\" (click)=\"OpenSourceDetail(card)\">\n <div class=\"at-source-card-header\">\n <div class=\"at-source-card-icon\"><i [class]=\"card.Icon\"></i></div>\n <div>\n <div class=\"at-source-card-title\">{{ card.Name }}</div>\n <div class=\"at-source-card-type\">{{ card.SourceTypeName }}@if (card.RequiresFileType) { \u00B7 {{ card.FileTypeName }}}</div>\n </div>\n <div class=\"at-source-card-status\" [class]=\"card.StatusClass\">\n <div class=\"at-source-mini-status\" [class]=\"card.StatusClass\"></div>\n {{ card.StatusLabel }}\n </div>\n </div>\n @if (card.URL) {\n <div class=\"at-source-card-url\">{{ card.URL }}</div>\n }\n <div class=\"at-source-card-stats\">\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ formatNumber(card.ItemCount) }}</div>\n <div class=\"at-source-stat-label\">Items</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ formatNumber(card.TagCount) }}</div>\n <div class=\"at-source-stat-label\">Tags</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ card.AvgTags }}</div>\n <div class=\"at-source-stat-label\">Avg Tags</div>\n </div>\n <div class=\"at-source-stat\">\n <div class=\"at-source-stat-value\">{{ card.LastRunAgo }}</div>\n <div class=\"at-source-stat-label\">Last Run</div>\n </div>\n </div>\n <!-- Schedule indicator -->\n @if (card.ScheduledJobID) {\n <div class=\"at-schedule-indicator\" (click)=\"RemoveSchedule(card); $event.stopPropagation()\" title=\"Click to remove schedule\">\n <i class=\"fa-regular fa-clock\"></i>\n <span>{{ GetScheduleLabel(card) }}</span>\n </div>\n }\n <div class=\"at-source-card-actions\">\n <button class=\"at-source-action-btn\" (click)=\"onEditSource(card); $event.stopPropagation()\"><i class=\"fa-solid fa-pen\"></i> Edit</button>\n <button class=\"at-source-action-btn\" (click)=\"onRunSource(card.ID); $event.stopPropagation()\"><i class=\"fa-solid fa-play\"></i> Run</button>\n <button class=\"at-source-action-btn\" (click)=\"OpenDryRunPreview(card); $event.stopPropagation()\"><i class=\"fa-solid fa-flask\"></i> Preview</button>\n @if (!card.ScheduledJobID) {\n <button class=\"at-source-action-btn at-source-schedule-btn\" (click)=\"OpenScheduleDialog(card); $event.stopPropagation()\"><i class=\"fa-regular fa-clock\"></i> Schedule</button>\n }\n <button class=\"at-source-action-btn at-source-delete-btn\" (click)=\"DeleteSource(card); $event.stopPropagation()\"><i class=\"fa-solid fa-trash\"></i> Delete</button>\n </div>\n </div>\n }\n\n <!-- Add Source Card -->\n <div class=\"at-add-source-card\" (click)=\"onAddSource()\">\n <i class=\"fa-solid fa-plus-circle\"></i>\n <span style=\"font-size: 0.85rem; font-weight: 600;\">Add Content Source</span>\n <span style=\"font-size: 0.72rem;\">Web, RSS, Email, Files, API</span>\n </div>\n </div>\n </div>\n </div>\n</mj-page-body-interior>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 SOURCE DETAIL SLIDE-IN \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowSourceDetail) {\n <div class=\"at-slide-overlay\" (click)=\"CloseSourceDetail()\"></div>\n <div class=\"at-slide-panel at-detail-panel\">\n <div class=\"at-slide-header\">\n <h3><i class=\"fa-solid fa-database\"></i> Source Detail</h3>\n <button class=\"at-slide-close\" aria-label=\"Close source detail\" (click)=\"CloseSourceDetail()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n @if (SourceDetailLoading) {\n <div class=\"at-loading-overlay\">\n <mj-loading text=\"Loading source details...\"></mj-loading>\n </div>\n }\n @if (!SourceDetailLoading && SelectedSource) {\n <!-- Source Header -->\n <div class=\"at-detail-source-header\">\n <div class=\"at-source-card-icon\"><i [class]=\"SelectedSource.Icon\"></i></div>\n <div>\n <h4 class=\"at-detail-item-name\">{{ SelectedSource.Name }}</h4>\n <div class=\"at-detail-badges\">\n <span class=\"at-detail-badge at-detail-badge-type\">{{ SelectedSource.SourceTypeName }}</span>\n <span class=\"at-detail-badge\" [class]=\"'at-detail-badge-status-' + SelectedSource.StatusClass\">\n {{ SelectedSource.StatusLabel }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- Configuration -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Configuration</div>\n <div class=\"at-detail-meta-grid\">\n @if (SelectedSource.URL) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">URL</span>\n <a [href]=\"SelectedSource.URL\" target=\"_blank\" class=\"at-detail-link at-detail-meta-value\">{{ SelectedSource.URL }}</a>\n </div>\n }\n @if (SelectedSource.RequiresFileType) {\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Content Type</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.ContentTypeName }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">File Type</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.FileTypeName }}</span>\n </div>\n }\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Embedding Model</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.EmbeddingModelName }}</span>\n </div>\n <div class=\"at-detail-meta-row\">\n <span class=\"at-detail-meta-key\">Vector Index</span>\n <span class=\"at-detail-meta-value\">{{ SelectedSource.VectorIndexName }}</span>\n </div>\n </div>\n </div>\n\n <!-- Stats -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Statistics</div>\n <div class=\"at-detail-stats-strip\">\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ formatNumber(SelectedSource.ItemCount) }}</div>\n <div class=\"at-detail-stat-label\">Items</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ formatNumber(SelectedSource.TagCount) }}</div>\n <div class=\"at-detail-stat-label\">Tags</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ SelectedSource.AvgTags }}</div>\n <div class=\"at-detail-stat-label\">Avg Tags</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\">{{ SelectedSource.LastRunAgo }}</div>\n <div class=\"at-detail-stat-label\">Last Run</div>\n </div>\n <div class=\"at-detail-stat\">\n <div class=\"at-detail-stat-value\" [class.at-kpi-error-value]=\"SelectedSource.ErrorCount > 0\">{{ SelectedSource.ErrorCount }}</div>\n <div class=\"at-detail-stat-label\">Errors</div>\n </div>\n </div>\n </div>\n\n <!-- Content Library (status badges, pagination) -->\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-header-row\">\n <div class=\"at-detail-section-label\">Content Library ({{ FilteredSourceDetailTotal }} of {{ SelectedSource.ItemCount | number }})</div>\n <div class=\"at-detail-section-controls\">\n <select class=\"at-detail-filter-select\" [(ngModel)]=\"SourceDetailStatusFilter\" (ngModelChange)=\"OnSourceDetailStatusFilterChange()\">\n @for (opt of SourceDetailStatusOptions; track opt) {\n <option [value]=\"opt\">{{ opt }}</option>\n }\n </select>\n <button class=\"at-action-btn at-retry-btn\" (click)=\"RetryFailedItems()\" title=\"Re-queue failed items for processing\">\n <i class=\"fa-solid fa-rotate-right\"></i> Retry Failed\n </button>\n </div>\n </div>\n <div class=\"at-detail-content-list\">\n @if (FilteredSourceDetailItems.length === 0) {\n <mj-empty-state Size=\"compact\"\n [Variant]=\"SourceDetailStatusFilter === 'All' ? 'empty' : 'no-results'\"\n [Title]=\"SourceDetailStatusFilter === 'All' ? 'No content items yet.' : 'No items match this filter.'\" />\n }\n @for (ci of FilteredSourceDetailItems; track ci.ID) {\n <div class=\"at-detail-content-item\" (click)=\"OpenContentItemDetail(ci)\">\n <div class=\"at-feed-status-dot\" [class]=\"ci.StatusDot\"></div>\n <span class=\"at-detail-content-item-name\">{{ ci.Name }}</span>\n <span class=\"at-status-badge\" [class]=\"GetStatusBadgeClass(ci.EmbeddingStatus)\">E:{{ ci.EmbeddingStatus }}</span>\n <span class=\"at-status-badge\" [class]=\"GetStatusBadgeClass(ci.TaggingStatus)\">T:{{ ci.TaggingStatus }}</span>\n <span class=\"at-detail-content-item-tags\">{{ ci.TagCount }} tags</span>\n <span class=\"at-detail-content-item-time\">{{ ci.UpdatedAt }}</span>\n </div>\n }\n </div>\n <!-- Pagination -->\n @if (SourceDetailTotalPages > 1) {\n <div class=\"at-detail-pagination\">\n <button class=\"at-page-btn\" [disabled]=\"SourceDetailPage === 0\" (click)=\"SourceDetailPrevPage()\">\n <i class=\"fa-solid fa-chevron-left\"></i> Prev\n </button>\n <span class=\"at-page-info\">Page {{ SourceDetailPage + 1 }} of {{ SourceDetailTotalPages }}</span>\n <button class=\"at-page-btn\" [disabled]=\"SourceDetailPage >= SourceDetailTotalPages - 1\" (click)=\"SourceDetailNextPage()\">\n Next <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n }\n </div>\n\n <!-- Run History -->\n @if (SelectedSource.RunHistory.length > 0) {\n <div class=\"at-detail-section\">\n <div class=\"at-detail-section-label\">Recent Runs</div>\n <div class=\"at-detail-run-history\">\n @for (run of SelectedSource.RunHistory; track run.ID) {\n <div class=\"at-detail-run-row\">\n <span class=\"at-run-status-badge\" [class]=\"run.StatusClass\">{{ run.Status }}</span>\n <span class=\"at-detail-run-time\">{{ run.StartedDisplay }}</span>\n <span class=\"at-detail-run-duration\">{{ run.Duration }}</span>\n <span class=\"at-detail-run-items\">{{ run.Items }} items</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"at-detail-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"OpenEditSourceFromDetail()\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"RunSourceFromDetail()\">\n <i class=\"fa-solid fa-play\"></i> Run Now\n </button>\n <button class=\"at-action-btn at-secondary-btn at-source-delete-btn\" (click)=\"DeleteSourceFromDetail()\">\n <i class=\"fa-solid fa-trash\"></i> Delete\n </button>\n </div>\n }\n </div>\n </div>\n}\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 SCHEDULE DIALOG \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (ShowScheduleDialog && SchedulingSourceCard) {\n <div class=\"at-schedule-overlay\" (click)=\"CloseScheduleDialog()\">\n <div class=\"at-schedule-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"at-schedule-dialog-header\">\n <h3><i class=\"fa-regular fa-clock\"></i> Schedule Pipeline</h3>\n <button class=\"at-schedule-dialog-close\" (click)=\"CloseScheduleDialog()\" aria-label=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"at-schedule-dialog-body\">\n <div class=\"at-schedule-field\">\n <label>Source</label>\n <div class=\"at-schedule-source-name\">\n <i [class]=\"SchedulingSourceCard.Icon\"></i>\n {{ SchedulingSourceCard.Name }}\n </div>\n </div>\n <div class=\"at-schedule-field\">\n <label>Action</label>\n <div class=\"at-schedule-action-name\">Autotag and Vectorize Content</div>\n </div>\n <div class=\"at-schedule-field\">\n <label for=\"schedule-cron\">Cron Expression</label>\n <input id=\"schedule-cron\"\n type=\"text\"\n class=\"mj-input at-schedule-cron-input\"\n [(ngModel)]=\"ScheduleCron\"\n placeholder=\"0 2 * * *\" />\n <div class=\"at-schedule-cron-preview\">\n <i class=\"fa-solid fa-info-circle\"></i>\n {{ GetCronPreview(ScheduleCron) }}\n </div>\n </div>\n <div class=\"at-schedule-field at-schedule-toggle-row\">\n <label for=\"schedule-enabled\">Enabled</label>\n <input id=\"schedule-enabled\"\n type=\"checkbox\"\n class=\"mj-checkbox\"\n [(ngModel)]=\"ScheduleEnabled\" />\n </div>\n </div>\n <div class=\"at-schedule-dialog-footer\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveSchedule()\" [disabled]=\"ScheduleSaving\">\n @if (ScheduleSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-check\"></i> Create Schedule\n }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseScheduleDialog()\">Cancel</button>\n </div>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 DRY-RUN DISPOSITION PREVIEW (in-memory, nothing persisted) \u2550\u2550\u2550\u2550\u2550\u2550 -->\n<classify-dry-run-preview\n [Provider]=\"Provider\"\n [Show]=\"ShowDryRunPreview\"\n [SourceCard]=\"DryRunSourceCard\"\n (Closed)=\"CloseDryRunPreview()\">\n</classify-dry-run-preview>\n", styles: ["/*\n * Content Sources tab styles.\n *\n * The host (AutotaggingPipelineResourceComponent) uses ViewEncapsulation.None,\n * so its `.at-*` rules are global and already style this tab's markup (cards,\n * source-detail slide-in, schedule dialog) while it renders inside the host\n * shell. Tab-specific rules would live here; none are needed during the\n * host-slim step.\n */\n\n.at-sources-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n gap: 10px;\n padding: 48px 24px;\n background: var(--mj-bg-surface-card);\n border: 1px dashed var(--mj-border-default);\n border-radius: 12px;\n}\n.at-sources-empty > i {\n font-size: 2rem;\n color: var(--mj-brand-primary);\n}\n.at-sources-empty h3 {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-primary);\n}\n.at-sources-empty p {\n margin: 0;\n max-width: 460px;\n font-size: 0.85rem;\n color: var(--mj-text-muted);\n line-height: 1.5;\n}\n.at-sources-empty-actions {\n display: flex;\n gap: 8px;\n margin-top: 6px;\n}\n"] }]
1426
1402
  }], null, { Sources: [{
1427
1403
  type: Input
1428
1404
  }], Items: [{
@@ -1435,7 +1411,7 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
1435
1411
  type: Input
1436
1412
  }], TotalTagCount: [{
1437
1413
  type: Input
1438
- }], ScheduledActions: [{
1414
+ }], ScheduledJobs: [{
1439
1415
  type: Input
1440
1416
  }], EntityRecordDocCache: [{
1441
1417
  type: Input
@@ -1452,5 +1428,5 @@ export class ClassifySourcesTabComponent extends BaseAngularComponent {
1452
1428
  }], DataChanged: [{
1453
1429
  type: Output
1454
1430
  }] }); })();
1455
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ClassifySourcesTabComponent, { className: "ClassifySourcesTabComponent", filePath: "src/AI/components/autotagging/tabs/sources-tab.component.ts", lineNumber: 35 }); })();
1431
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ClassifySourcesTabComponent, { className: "ClassifySourcesTabComponent", filePath: "src/AI/components/autotagging/tabs/sources-tab.component.ts", lineNumber: 36 }); })();
1456
1432
  //# sourceMappingURL=sources-tab.component.js.map