/**
 * @fileoverview Classify · Content Sources tab.
 *
 * Self-contained sub-page: owns its header-interior, the source cards grid,
 * the per-source detail slide-in, and the quick-schedule dialog. Receives the
 * shared raw data needed to build the cards (sources, items, tags, runs, and
 * the cached ScheduledAction + EntityRecordDocument lookups) from the host
 * orchestrator via `@Input()`. Cross-tab concerns — opening the add/edit slide-in
 * form, running the pipeline, opening a content-item detail, and reloading the
 * shared source list after a mutation — bubble up via `@Output()`.
 *
 * Out of scope (stays in the host): the add/edit source slide-in FORM, the
 * pipeline tab, and the Content Duplicates section.
 */
import { Component, ChangeDetectorRef, EventEmitter, Input, Output, inject } from '@angular/core';
import { CompositeKey, RunView } from '@memberjunction/core';
import { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
import { MJNotificationService } from '@memberjunction/ng-notifications';
import { AIEngineBase } from '@memberjunction/ai-engine-base';
import { KnowledgeHubMetadataEngine } from '@memberjunction/core-entities';
import { formatNumber, formatDate, computeDuration, displayStatus, getSourceTypeIcon, CronToHumanReadable, deriveDisplayName } from '../shared/classify.format';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@memberjunction/ng-shared-generic";
import * as i3 from "@memberjunction/ng-ui-components";
import * as i4 from "../dialogs/dry-run-preview.dialog.component";
import * as i5 from "@angular/common";
const _forTrack0 = ($index, $item) => $item.ID;
function ClassifySourcesTabComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "i", 21);
    i0.ɵɵelementStart(1, "span", 5);
    i0.ɵɵtext(2, "Refreshing\u2026");
    i0.ɵɵelementEnd();
} }
function ClassifySourcesTabComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "i", 22);
    i0.ɵɵelementStart(1, "span", 5);
    i0.ɵɵtext(2, "Refresh");
    i0.ɵɵelementEnd();
} }
function ClassifySourcesTabComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 10);
    i0.ɵɵelement(1, "mj-loading", 23);
    i0.ɵɵelementEnd();
} }
function ClassifySourcesTabComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
    const _r1 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 12);
    i0.ɵɵelement(1, "i", 24);
    i0.ɵɵelementStart(2, "h3");
    i0.ɵɵtext(3, "No content sources yet");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "p");
    i0.ɵɵtext(5, "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.");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(6, "div", 25)(7, "button", 6);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_17_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onAddSourceGuided()); });
    i0.ɵɵelement(8, "i", 4);
    i0.ɵɵtext(9, " Add Source (Guided) ");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(10, "button", 3);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_17_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onAddSource()); });
    i0.ɵɵelement(11, "i", 7);
    i0.ɵɵtext(12, " Add manually ");
    i0.ɵɵelementEnd()()();
} }
function ClassifySourcesTabComponent_For_20_Conditional_9_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵtext(0);
} if (rf & 2) {
    const card_r4 = i0.ɵɵnextContext().$implicit;
    i0.ɵɵtextInterpolate1(" \u00B7 ", card_r4.FileTypeName);
} }
function ClassifySourcesTabComponent_For_20_Conditional_13_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 33);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const card_r4 = i0.ɵɵnextContext().$implicit;
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(card_r4.URL);
} }
function ClassifySourcesTabComponent_For_20_Conditional_35_Template(rf, ctx) { if (rf & 1) {
    const _r5 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 47);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_For_20_Conditional_35_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r5); const card_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.RemoveSchedule(card_r4); return i0.ɵɵresetView($event.stopPropagation()); });
    i0.ɵɵelement(1, "i", 48);
    i0.ɵɵelementStart(2, "span");
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const card_r4 = i0.ɵɵnextContext().$implicit;
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(ctx_r1.GetScheduleLabel(card_r4));
} }
function ClassifySourcesTabComponent_For_20_Conditional_46_Template(rf, ctx) { if (rf & 1) {
    const _r6 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "button", 49);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_For_20_Conditional_46_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r6); const card_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.OpenScheduleDialog(card_r4); return i0.ɵɵresetView($event.stopPropagation()); });
    i0.ɵɵelement(1, "i", 48);
    i0.ɵɵtext(2, " Schedule");
    i0.ɵɵelementEnd();
} }
function ClassifySourcesTabComponent_For_20_Template(rf, ctx) { if (rf & 1) {
    const _r3 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 26);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_For_20_Template_div_click_0_listener() { const card_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OpenSourceDetail(card_r4)); });
    i0.ɵɵelementStart(1, "div", 27)(2, "div", 28);
    i0.ɵɵelement(3, "i");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "div")(5, "div", 29);
    i0.ɵɵtext(6);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(7, "div", 30);
    i0.ɵɵtext(8);
    i0.ɵɵconditionalCreate(9, ClassifySourcesTabComponent_For_20_Conditional_9_Template, 1, 1);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(10, "div", 31);
    i0.ɵɵelement(11, "div", 32);
    i0.ɵɵtext(12);
    i0.ɵɵelementEnd()();
    i0.ɵɵconditionalCreate(13, ClassifySourcesTabComponent_For_20_Conditional_13_Template, 2, 1, "div", 33);
    i0.ɵɵelementStart(14, "div", 34)(15, "div", 35)(16, "div", 36);
    i0.ɵɵtext(17);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(18, "div", 37);
    i0.ɵɵtext(19, "Items");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(20, "div", 35)(21, "div", 36);
    i0.ɵɵtext(22);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(23, "div", 37);
    i0.ɵɵtext(24, "Tags");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(25, "div", 35)(26, "div", 36);
    i0.ɵɵtext(27);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(28, "div", 37);
    i0.ɵɵtext(29, "Avg Tags");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(30, "div", 35)(31, "div", 36);
    i0.ɵɵtext(32);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(33, "div", 37);
    i0.ɵɵtext(34, "Last Run");
    i0.ɵɵelementEnd()()();
    i0.ɵɵconditionalCreate(35, ClassifySourcesTabComponent_For_20_Conditional_35_Template, 4, 1, "div", 38);
    i0.ɵɵelementStart(36, "div", 39)(37, "button", 40);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_For_20_Template_button_click_37_listener($event) { const card_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.onEditSource(card_r4); return i0.ɵɵresetView($event.stopPropagation()); });
    i0.ɵɵelement(38, "i", 41);
    i0.ɵɵtext(39, " Edit");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(40, "button", 40);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_For_20_Template_button_click_40_listener($event) { const card_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.onRunSource(card_r4.ID); return i0.ɵɵresetView($event.stopPropagation()); });
    i0.ɵɵelement(41, "i", 42);
    i0.ɵɵtext(42, " Run");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(43, "button", 40);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_For_20_Template_button_click_43_listener($event) { const card_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.OpenDryRunPreview(card_r4); return i0.ɵɵresetView($event.stopPropagation()); });
    i0.ɵɵelement(44, "i", 43);
    i0.ɵɵtext(45, " Preview");
    i0.ɵɵelementEnd();
    i0.ɵɵconditionalCreate(46, ClassifySourcesTabComponent_For_20_Conditional_46_Template, 3, 0, "button", 44);
    i0.ɵɵelementStart(47, "button", 45);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_For_20_Template_button_click_47_listener($event) { const card_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.DeleteSource(card_r4); return i0.ɵɵresetView($event.stopPropagation()); });
    i0.ɵɵelement(48, "i", 46);
    i0.ɵɵtext(49, " Delete");
    i0.ɵɵelementEnd()()();
} if (rf & 2) {
    const card_r4 = ctx.$implicit;
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance(3);
    i0.ɵɵclassMap(card_r4.Icon);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(card_r4.Name);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(card_r4.SourceTypeName);
    i0.ɵɵadvance();
    i0.ɵɵconditional(card_r4.RequiresFileType ? 9 : -1);
    i0.ɵɵadvance();
    i0.ɵɵclassMap(card_r4.StatusClass);
    i0.ɵɵadvance();
    i0.ɵɵclassMap(card_r4.StatusClass);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", card_r4.StatusLabel, " ");
    i0.ɵɵadvance();
    i0.ɵɵconditional(card_r4.URL ? 13 : -1);
    i0.ɵɵadvance(4);
    i0.ɵɵtextInterpolate(ctx_r1.formatNumber(card_r4.ItemCount));
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(ctx_r1.formatNumber(card_r4.TagCount));
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(card_r4.AvgTags);
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(card_r4.LastRunAgo);
    i0.ɵɵadvance(3);
    i0.ɵɵconditional(card_r4.ScheduledActionID ? 35 : -1);
    i0.ɵɵadvance(11);
    i0.ɵɵconditional(!card_r4.ScheduledActionID ? 46 : -1);
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_9_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 10);
    i0.ɵɵelement(1, "mj-loading", 56);
    i0.ɵɵelementEnd();
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_15_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 65)(1, "span", 66);
    i0.ɵɵtext(2, "URL");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "a", 86);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(3);
    i0.ɵɵadvance(3);
    i0.ɵɵproperty("href", ctx_r1.SelectedSource.URL, i0.ɵɵsanitizeUrl);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.URL);
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_16_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 65)(1, "span", 66);
    i0.ɵɵtext(2, "Content Type");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "span", 67);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(5, "div", 65)(6, "span", 66);
    i0.ɵɵtext(7, "File Type");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(8, "span", 67);
    i0.ɵɵtext(9);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(3);
    i0.ɵɵadvance(4);
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.ContentTypeName);
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.FileTypeName);
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_For_64_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "option", 75);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const opt_r9 = ctx.$implicit;
    i0.ɵɵproperty("value", opt_r9);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(opt_r9);
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_69_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 79)(1, "p");
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(3);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r1.SourceDetailStatusFilter === "All" ? "No content items yet." : "No items match this filter.");
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_For_71_Template(rf, ctx) { if (rf & 1) {
    const _r10 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 87);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_For_71_Template_div_click_0_listener() { const ci_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OpenContentItemDetail(ci_r11)); });
    i0.ɵɵelement(1, "div", 88);
    i0.ɵɵelementStart(2, "span", 89);
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "span", 90);
    i0.ɵɵtext(5);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(6, "span", 90);
    i0.ɵɵtext(7);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(8, "span", 91);
    i0.ɵɵtext(9);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(10, "span", 92);
    i0.ɵɵtext(11);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ci_r11 = ctx.$implicit;
    const ctx_r1 = i0.ɵɵnextContext(3);
    i0.ɵɵadvance();
    i0.ɵɵclassMap(ci_r11.StatusDot);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ci_r11.Name);
    i0.ɵɵadvance();
    i0.ɵɵclassMap(ctx_r1.GetStatusBadgeClass(ci_r11.EmbeddingStatus));
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1("E:", ci_r11.EmbeddingStatus);
    i0.ɵɵadvance();
    i0.ɵɵclassMap(ctx_r1.GetStatusBadgeClass(ci_r11.TaggingStatus));
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1("T:", ci_r11.TaggingStatus);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate1("", ci_r11.TagCount, " tags");
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ci_r11.UpdatedAt);
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_72_Template(rf, ctx) { if (rf & 1) {
    const _r12 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 81)(1, "button", 93);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_72_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SourceDetailPrevPage()); });
    i0.ɵɵelement(2, "i", 94);
    i0.ɵɵtext(3, " Prev ");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "span", 95);
    i0.ɵɵtext(5);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(6, "button", 93);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_72_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SourceDetailNextPage()); });
    i0.ɵɵtext(7, " Next ");
    i0.ɵɵelement(8, "i", 96);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(3);
    i0.ɵɵadvance();
    i0.ɵɵproperty("disabled", ctx_r1.SourceDetailPage === 0);
    i0.ɵɵadvance(4);
    i0.ɵɵtextInterpolate2("Page ", ctx_r1.SourceDetailPage + 1, " of ", ctx_r1.SourceDetailTotalPages);
    i0.ɵɵadvance();
    i0.ɵɵproperty("disabled", ctx_r1.SourceDetailPage >= ctx_r1.SourceDetailTotalPages - 1);
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_73_For_5_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 98)(1, "span", 99);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "span", 100);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "span", 101);
    i0.ɵɵtext(6);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(7, "span", 102);
    i0.ɵɵtext(8);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const run_r13 = ctx.$implicit;
    i0.ɵɵadvance();
    i0.ɵɵclassMap(run_r13.StatusClass);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(run_r13.Status);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(run_r13.StartedDisplay);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(run_r13.Duration);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate1("", run_r13.Items, " items");
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_73_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 62)(1, "div", 63);
    i0.ɵɵtext(2, "Recent Runs");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "div", 97);
    i0.ɵɵrepeaterCreate(4, ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_73_For_5_Template, 9, 6, "div", 98, _forTrack0);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(3);
    i0.ɵɵadvance(4);
    i0.ɵɵrepeater(ctx_r1.SelectedSource.RunHistory);
} }
function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Template(rf, ctx) { if (rf & 1) {
    const _r8 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 57)(1, "div", 28);
    i0.ɵɵelement(2, "i");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "div")(4, "h4", 58);
    i0.ɵɵtext(5);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(6, "div", 59)(7, "span", 60);
    i0.ɵɵtext(8);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(9, "span", 61);
    i0.ɵɵtext(10);
    i0.ɵɵelementEnd()()()();
    i0.ɵɵelementStart(11, "div", 62)(12, "div", 63);
    i0.ɵɵtext(13, "Configuration");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(14, "div", 64);
    i0.ɵɵconditionalCreate(15, ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_15_Template, 5, 2, "div", 65);
    i0.ɵɵconditionalCreate(16, ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_16_Template, 10, 2);
    i0.ɵɵelementStart(17, "div", 65)(18, "span", 66);
    i0.ɵɵtext(19, "Embedding Model");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(20, "span", 67);
    i0.ɵɵtext(21);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(22, "div", 65)(23, "span", 66);
    i0.ɵɵtext(24, "Vector Index");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(25, "span", 67);
    i0.ɵɵtext(26);
    i0.ɵɵelementEnd()()()();
    i0.ɵɵelementStart(27, "div", 62)(28, "div", 63);
    i0.ɵɵtext(29, "Statistics");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(30, "div", 68)(31, "div", 69)(32, "div", 70);
    i0.ɵɵtext(33);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(34, "div", 71);
    i0.ɵɵtext(35, "Items");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(36, "div", 69)(37, "div", 70);
    i0.ɵɵtext(38);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(39, "div", 71);
    i0.ɵɵtext(40, "Tags");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(41, "div", 69)(42, "div", 70);
    i0.ɵɵtext(43);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(44, "div", 71);
    i0.ɵɵtext(45, "Avg Tags");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(46, "div", 69)(47, "div", 70);
    i0.ɵɵtext(48);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(49, "div", 71);
    i0.ɵɵtext(50, "Last Run");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(51, "div", 69)(52, "div", 70);
    i0.ɵɵtext(53);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(54, "div", 71);
    i0.ɵɵtext(55, "Errors");
    i0.ɵɵelementEnd()()()();
    i0.ɵɵelementStart(56, "div", 62)(57, "div", 72)(58, "div", 63);
    i0.ɵɵtext(59);
    i0.ɵɵpipe(60, "number");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(61, "div", 73)(62, "select", 74);
    i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Template_select_ngModelChange_62_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.SourceDetailStatusFilter, $event) || (ctx_r1.SourceDetailStatusFilter = $event); return i0.ɵɵresetView($event); });
    i0.ɵɵlistener("ngModelChange", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Template_select_ngModelChange_62_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnSourceDetailStatusFilterChange()); });
    i0.ɵɵrepeaterCreate(63, ClassifySourcesTabComponent_Conditional_27_Conditional_10_For_64_Template, 2, 2, "option", 75, i0.ɵɵrepeaterTrackByIdentity);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(65, "button", 76);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Template_button_click_65_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.RetryFailedItems()); });
    i0.ɵɵelement(66, "i", 77);
    i0.ɵɵtext(67, " Retry Failed ");
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(68, "div", 78);
    i0.ɵɵconditionalCreate(69, ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_69_Template, 3, 1, "div", 79);
    i0.ɵɵrepeaterCreate(70, ClassifySourcesTabComponent_Conditional_27_Conditional_10_For_71_Template, 12, 11, "div", 80, _forTrack0);
    i0.ɵɵelementEnd();
    i0.ɵɵconditionalCreate(72, ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_72_Template, 9, 4, "div", 81);
    i0.ɵɵelementEnd();
    i0.ɵɵconditionalCreate(73, ClassifySourcesTabComponent_Conditional_27_Conditional_10_Conditional_73_Template, 6, 0, "div", 62);
    i0.ɵɵelementStart(74, "div", 82)(75, "button", 83);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Template_button_click_75_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OpenEditSourceFromDetail()); });
    i0.ɵɵelement(76, "i", 41);
    i0.ɵɵtext(77, " Edit ");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(78, "button", 84);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Template_button_click_78_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.RunSourceFromDetail()); });
    i0.ɵɵelement(79, "i", 42);
    i0.ɵɵtext(80, " Run Now ");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(81, "button", 85);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Conditional_10_Template_button_click_81_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.DeleteSourceFromDetail()); });
    i0.ɵɵelement(82, "i", 46);
    i0.ɵɵtext(83, " Delete ");
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(2);
    i0.ɵɵclassMap(ctx_r1.SelectedSource.Icon);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.Name);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.SourceTypeName);
    i0.ɵɵadvance();
    i0.ɵɵclassMap("at-detail-badge-status-" + ctx_r1.SelectedSource.StatusClass);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", ctx_r1.SelectedSource.StatusLabel, " ");
    i0.ɵɵadvance(5);
    i0.ɵɵconditional(ctx_r1.SelectedSource.URL ? 15 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r1.SelectedSource.RequiresFileType ? 16 : -1);
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.EmbeddingModelName);
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.VectorIndexName);
    i0.ɵɵadvance(7);
    i0.ɵɵtextInterpolate(ctx_r1.formatNumber(ctx_r1.SelectedSource.ItemCount));
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(ctx_r1.formatNumber(ctx_r1.SelectedSource.TagCount));
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.AvgTags);
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.LastRunAgo);
    i0.ɵɵadvance(4);
    i0.ɵɵclassProp("at-kpi-error-value", ctx_r1.SelectedSource.ErrorCount > 0);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(ctx_r1.SelectedSource.ErrorCount);
    i0.ɵɵadvance(6);
    i0.ɵɵtextInterpolate2("Content Library (", ctx_r1.FilteredSourceDetailTotal, " of ", i0.ɵɵpipeBind1(60, 24, ctx_r1.SelectedSource.ItemCount), ")");
    i0.ɵɵadvance(3);
    i0.ɵɵtwoWayProperty("ngModel", ctx_r1.SourceDetailStatusFilter);
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r1.SourceDetailStatusOptions);
    i0.ɵɵadvance(6);
    i0.ɵɵconditional(ctx_r1.FilteredSourceDetailItems.length === 0 ? 69 : -1);
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r1.FilteredSourceDetailItems);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r1.SourceDetailTotalPages > 1 ? 72 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r1.SelectedSource.RunHistory.length > 0 ? 73 : -1);
} }
function ClassifySourcesTabComponent_Conditional_27_Template(rf, ctx) { if (rf & 1) {
    const _r7 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 50);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseSourceDetail()); });
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(1, "div", 51)(2, "div", 52)(3, "h3");
    i0.ɵɵelement(4, "i", 24);
    i0.ɵɵtext(5, " Source Detail");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(6, "button", 53);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_27_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseSourceDetail()); });
    i0.ɵɵelement(7, "i", 54);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(8, "div", 55);
    i0.ɵɵconditionalCreate(9, ClassifySourcesTabComponent_Conditional_27_Conditional_9_Template, 2, 0, "div", 10);
    i0.ɵɵconditionalCreate(10, ClassifySourcesTabComponent_Conditional_27_Conditional_10_Template, 84, 26);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance(9);
    i0.ɵɵconditional(ctx_r1.SourceDetailLoading ? 9 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(!ctx_r1.SourceDetailLoading && ctx_r1.SelectedSource ? 10 : -1);
} }
function ClassifySourcesTabComponent_Conditional_28_Conditional_33_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "i", 21);
    i0.ɵɵtext(1, " Saving... ");
} }
function ClassifySourcesTabComponent_Conditional_28_Conditional_34_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "i", 120);
    i0.ɵɵtext(1, " Create Schedule ");
} }
function ClassifySourcesTabComponent_Conditional_28_Template(rf, ctx) { if (rf & 1) {
    const _r14 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 103);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_28_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseScheduleDialog()); });
    i0.ɵɵelementStart(1, "div", 104);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_28_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r14); return i0.ɵɵresetView($event.stopPropagation()); });
    i0.ɵɵelementStart(2, "div", 105)(3, "h3");
    i0.ɵɵelement(4, "i", 48);
    i0.ɵɵtext(5, " Schedule Pipeline");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(6, "button", 106);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_28_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseScheduleDialog()); });
    i0.ɵɵelement(7, "i", 54);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(8, "div", 107)(9, "div", 108)(10, "label");
    i0.ɵɵtext(11, "Source");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(12, "div", 109);
    i0.ɵɵelement(13, "i");
    i0.ɵɵtext(14);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(15, "div", 108)(16, "label");
    i0.ɵɵtext(17, "Action");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(18, "div", 110);
    i0.ɵɵtext(19, "Autotag and Vectorize Content");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(20, "div", 108)(21, "label", 111);
    i0.ɵɵtext(22, "Cron Expression");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(23, "input", 112);
    i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourcesTabComponent_Conditional_28_Template_input_ngModelChange_23_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.ScheduleCron, $event) || (ctx_r1.ScheduleCron = $event); return i0.ɵɵresetView($event); });
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(24, "div", 113);
    i0.ɵɵelement(25, "i", 114);
    i0.ɵɵtext(26);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(27, "div", 115)(28, "label", 116);
    i0.ɵɵtext(29, "Enabled");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(30, "input", 117);
    i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourcesTabComponent_Conditional_28_Template_input_ngModelChange_30_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.ScheduleEnabled, $event) || (ctx_r1.ScheduleEnabled = $event); return i0.ɵɵresetView($event); });
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(31, "div", 118)(32, "button", 119);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_28_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SaveSchedule()); });
    i0.ɵɵconditionalCreate(33, ClassifySourcesTabComponent_Conditional_28_Conditional_33_Template, 2, 0)(34, ClassifySourcesTabComponent_Conditional_28_Conditional_34_Template, 2, 0);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(35, "button", 84);
    i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Conditional_28_Template_button_click_35_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseScheduleDialog()); });
    i0.ɵɵtext(36, "Cancel");
    i0.ɵɵelementEnd()()()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance(13);
    i0.ɵɵclassMap(ctx_r1.SchedulingSourceCard.Icon);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", ctx_r1.SchedulingSourceCard.Name, " ");
    i0.ɵɵadvance(9);
    i0.ɵɵtwoWayProperty("ngModel", ctx_r1.ScheduleCron);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate1(" ", ctx_r1.GetCronPreview(ctx_r1.ScheduleCron), " ");
    i0.ɵɵadvance(4);
    i0.ɵɵtwoWayProperty("ngModel", ctx_r1.ScheduleEnabled);
    i0.ɵɵadvance(2);
    i0.ɵɵproperty("disabled", ctx_r1.ScheduleSaving);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r1.ScheduleSaving ? 33 : 34);
} }
export class ClassifySourcesTabComponent extends BaseAngularComponent {
    cdr = inject(ChangeDetectorRef);
    // ── Shared raw inputs (host is the data orchestrator) ──
    /** Raw `MJ: Content Sources` rows — the primary source for the cards. */
    _sources = [];
    set Sources(value) {
        this._sources = value ?? [];
        this.rebuild();
    }
    get Sources() {
        return this._sources;
    }
    /** Raw `MJ: Content Items` rows — used to count items per source. */
    _items = [];
    set Items(value) {
        this._items = value ?? [];
        this.rebuild();
    }
    get Items() {
        return this._items;
    }
    /** Raw `MJ: Content Item Tags` rows — used to count tags per source. */
    _tags = [];
    set Tags(value) {
        this._tags = value ?? [];
        this.rebuild();
    }
    get Tags() {
        return this._tags;
    }
    /** Raw `MJ: Content Process Runs` rows — used to derive last-run + status. */
    _runs = [];
    set Runs(value) {
        this._runs = value ?? [];
        this.rebuild();
    }
    get Runs() {
        return this._runs;
    }
    /** Accurate total item count from TotalRowCount (used when a single source exists). */
    _totalItemCount = 0;
    set TotalItemCount(value) {
        this._totalItemCount = value ?? 0;
        this.rebuild();
    }
    get TotalItemCount() {
        return this._totalItemCount;
    }
    /** Accurate total tag count from TotalRowCount (used when a single source exists). */
    _totalTagCount = 0;
    set TotalTagCount(value) {
        this._totalTagCount = value ?? 0;
        this.rebuild();
    }
    get TotalTagCount() {
        return this._totalTagCount;
    }
    /** Cached ScheduledAction entities, keyed by normalized ID, supplied by the host. */
    _scheduledActions = new Map();
    set ScheduledActions(value) {
        this._scheduledActions = value ?? new Map();
        this.rebuild();
    }
    get ScheduledActions() {
        return this._scheduledActions;
    }
    /** Cache: EntityRecordDocument ID → RecordID, supplied by the host. */
    _entityRecordDocCache = new Map();
    set EntityRecordDocCache(value) {
        this._entityRecordDocCache = value ?? new Map();
    }
    get EntityRecordDocCache() {
        return this._entityRecordDocCache;
    }
    // ── Tab-local view state ──
    /** Shown while a manual Refresh() recomputes the source cards. */
    IsLoading = false;
    SourceCards = [];
    // Source Detail slide-in
    SelectedSource = null;
    ShowSourceDetail = false;
    SourceDetailLoading = false;
    SourceDetailStatusFilter = 'All';
    SourceDetailStatusOptions = ['All', 'Complete', 'Processing', 'Failed', 'Pending'];
    SourceDetailPage = 0;
    SourceDetailPageSize = 10;
    // Dry-run preview dialog (hosted here, like the schedule + detail dialogs)
    ShowDryRunPreview = false;
    DryRunSourceCard = null;
    // Schedule dialog
    ShowScheduleDialog = false;
    ScheduleSaving = false;
    SchedulingSourceCard = null;
    ScheduleCron = '0 2 * * *';
    ScheduleEnabled = true;
    /** Template-facing formatter. */
    formatNumber = formatNumber;
    // ── Cross-tab intents (host owns the slide-in form, navigation, pipeline) ──
    /** Bubble "add source" up — host opens its slide-in CRUD form. */
    AddSourceRequested = new EventEmitter();
    /** Bubble "add source (guided)" up — host opens the setup wizard. */
    AddSourceGuidedRequested = new EventEmitter();
    /** Bubble "edit source" up — host opens its slide-in CRUD form pre-filled. */
    EditSourceRequested = new EventEmitter();
    /** Bubble "run pipeline for source" up — host runs the pipeline for the given source ID. */
    RunSourceRequested = new EventEmitter();
    /** Bubble "open content item detail" up — host owns the item-detail slide-in. */
    OpenContentItemRequested = new EventEmitter();
    /** Fired after a delete / schedule change so the host reloads the shared source list. */
    DataChanged = new EventEmitter();
    /**
     * Recompute the source cards from the current host-supplied inputs. The data
     * itself is owned by the host (flows in via @Input); Refresh just rebuilds the
     * view models and surfaces a brief loading state for user feedback.
     */
    async Refresh() {
        this.IsLoading = true;
        this.cdr.detectChanges();
        this.rebuild();
        this.IsLoading = false;
        this.cdr.detectChanges();
    }
    onAddSource() {
        this.AddSourceRequested.emit();
    }
    onAddSourceGuided() {
        this.AddSourceGuidedRequested.emit();
    }
    onEditSource(card) {
        this.EditSourceRequested.emit(card);
    }
    onRunSource(sourceID) {
        this.RunSourceRequested.emit(sourceID);
    }
    // ── Dry-run preview (in-memory, nothing persisted) ──
    /** Opens the dry-run disposition preview for a source. */
    OpenDryRunPreview(card) {
        this.DryRunSourceCard = card;
        this.ShowDryRunPreview = true;
        this.cdr.detectChanges();
    }
    CloseDryRunPreview() {
        this.ShowDryRunPreview = false;
        this.DryRunSourceCard = null;
        this.cdr.detectChanges();
    }
    // ════════════════════════════════════════════
    // SOURCE CARDS
    // ════════════════════════════════════════════
    /** Rebuild the source card view models from the current inputs. */
    rebuild() {
        const singleSource = this._sources.length === 1;
        const itemCountBySource = singleSource ? null : this.countItemsBySource();
        const tagCountBySource = singleSource ? null : this.countTagsBySource();
        const lastRunBySource = this.getLastRunBySource();
        this.SourceCards = this._sources.map(source => {
            const id = source['ID'];
            const itemCount = singleSource ? this._totalItemCount : (itemCountBySource.get(id) ?? 0);
            const tagCount = singleSource ? this._totalTagCount : (tagCountBySource.get(id) ?? 0);
            const avgTags = itemCount > 0 ? (tagCount / itemCount).toFixed(1) : '0';
            const lastRun = lastRunBySource.get(id);
            const typeName = source['ContentSourceType'] ?? 'Unknown';
            const lastRunStatus = lastRun ? lastRun['Status']?.toLowerCase() : null;
            const hasError = lastRunStatus === 'error' || lastRunStatus === 'failed';
            const scheduledActionID = source['ScheduledActionID'] ?? null;
            const scheduledActionName = source['ScheduledAction'] ?? null;
            const cronExpr = scheduledActionID ? this.getScheduledActionCron(scheduledActionID) : null;
            return {
                ID: id,
                Name: source['Name'] ?? 'Unnamed Source',
                SourceTypeName: typeName,
                ContentTypeName: source['ContentType'] ?? 'Unknown',
                FileTypeName: source['ContentFileType'] ?? 'Unknown',
                Icon: getSourceTypeIcon(typeName),
                StatusClass: hasError ? 'error' : 'active',
                StatusLabel: hasError ? 'Error' : 'Active',
                URL: source['URL'] ?? '',
                ItemCount: itemCount,
                TagCount: tagCount,
                AvgTags: avgTags,
                LastRunAgo: lastRun ? this.formatRelativeTime(lastRun['StartTime']) : 'Never',
                ContentSourceTypeID: source['ContentSourceTypeID'],
                ContentTypeID: source['ContentTypeID'],
                ContentFileTypeID: source['ContentFileTypeID'],
                EmbeddingModelID: source['EmbeddingModelID'] ?? '',
                VectorIndexID: source['VectorIndexID'] ?? '',
                EntityID: source['EntityID'] ?? '',
                EntityDocumentID: source['EntityDocumentID'] ?? '',
                RequiresFileType: this.sourceTypeRequiresFileType(source['ContentSourceTypeID']),
                ScheduledActionID: scheduledActionID,
                ScheduledActionName: scheduledActionName,
                ScheduleDescription: cronExpr ? CronToHumanReadable(cronExpr) : null,
            };
        });
        this.cdr.detectChanges();
    }
    // ── Aggregation utilities (read only the raw inputs) ──
    countItemsBySource() {
        const counts = new Map();
        for (const item of this._items) {
            const sourceId = item['ContentSourceID'];
            if (sourceId)
                counts.set(sourceId, (counts.get(sourceId) ?? 0) + 1);
        }
        return counts;
    }
    countTagsBySource() {
        const itemSourceMap = new Map();
        for (const item of this._items) {
            itemSourceMap.set(item['ID'], item['ContentSourceID']);
        }
        const counts = new Map();
        for (const tag of this._tags) {
            const sourceId = itemSourceMap.get(tag['ItemID']);
            if (sourceId)
                counts.set(sourceId, (counts.get(sourceId) ?? 0) + 1);
        }
        return counts;
    }
    getLastRunBySource() {
        const map = new Map();
        for (const run of this._runs) {
            const sourceId = run['SourceID'];
            if (sourceId && !map.has(sourceId)) {
                map.set(sourceId, run);
            }
        }
        return map;
    }
    countTagsByItem() {
        const counts = new Map();
        for (const tag of this._tags) {
            const itemId = NormalizeUUID(tag['ItemID']);
            if (itemId)
                counts.set(itemId, (counts.get(itemId) ?? 0) + 1);
        }
        return counts;
    }
    getAllWeightedTagsForItem(itemId) {
        const tags = [];
        for (const tag of this._tags) {
            if (UUIDsEqual(tag['ItemID'], itemId)) {
                tags.push({
                    Tag: tag['Tag'],
                    Weight: Number(tag['Weight'] ?? 1),
                });
            }
        }
        return tags.sort((a, b) => b.Weight - a.Weight);
    }
    /** Check if a source type's Configuration says RequiresFileType !== false */
    sourceTypeRequiresFileType(sourceTypeID) {
        try {
            const engine = KnowledgeHubMetadataEngine.Instance;
            const st = engine.ContentSourceTypes.find(t => UUIDsEqual(t.ID, sourceTypeID));
            return st?.ConfigurationObject?.RequiresFileType !== false;
        }
        catch {
            return true;
        }
    }
    /** Resolve the entity record ID from the EntityRecordDocument for entity-sourced content items */
    resolveEntityRecordID(item) {
        const erdID = item['EntityRecordDocumentID'];
        if (!erdID)
            return null;
        return this._entityRecordDocCache.get(NormalizeUUID(erdID)) ?? null;
    }
    /** Resolve the entity name for an entity-sourced content source */
    resolveEntityName(sourceId) {
        try {
            const engine = KnowledgeHubMetadataEngine.Instance;
            const source = engine.ContentSources.find(cs => UUIDsEqual(cs.ID, sourceId));
            if (!source?.EntityID)
                return null;
            const md = this.ProviderToUse;
            const entityInfo = md.Entities.find(e => UUIDsEqual(e.ID, source.EntityID));
            return entityInfo?.Name ?? null;
        }
        catch {
            return null;
        }
    }
    resolveEmbeddingModelName(modelId) {
        if (!modelId)
            return 'System default';
        const aiEngine = AIEngineBase.Instance;
        const model = aiEngine.Models.find(m => UUIDsEqual(m.ID, modelId));
        return model ? model.Name : 'Unknown';
    }
    resolveVectorIndexName(indexId) {
        if (!indexId)
            return 'System default';
        const engine = KnowledgeHubMetadataEngine.Instance;
        const idx = engine.GetVectorIndexById(indexId);
        return idx ? idx.Name : 'Unknown';
    }
    /**
     * Infer embedding and tagging pipeline statuses for a content item. Uses tag
     * count + run-history heuristics since dedicated status columns are not yet
     * available on the ContentItem entity.
     */
    inferPipelineStatuses(rawItem, tagCount) {
        const explicitEmbedding = rawItem['EmbeddingStatus'];
        const explicitTagging = rawItem['TaggingStatus'];
        if (explicitEmbedding || explicitTagging) {
            return {
                EmbeddingStatus: this.mapStatusString(explicitEmbedding),
                TaggingStatus: this.mapStatusString(explicitTagging),
            };
        }
        const hasChecksum = !!rawItem['Checksum'];
        const hasText = !!(rawItem['Text']?.trim());
        const sourceID = rawItem['ContentSourceID'];
        const lastRun = this._runs.find(r => r['SourceID'] === sourceID);
        const lastRunFailed = lastRun &&
            (lastRun['Status']?.toLowerCase() === 'error' ||
                lastRun['Status']?.toLowerCase() === 'failed');
        let embeddingStatus = 'Pending';
        if (hasChecksum || hasText)
            embeddingStatus = 'Complete';
        else if (lastRunFailed)
            embeddingStatus = 'Failed';
        let taggingStatus = 'Pending';
        if (tagCount > 0)
            taggingStatus = 'Complete';
        else if (embeddingStatus === 'Complete')
            taggingStatus = lastRunFailed ? 'Failed' : 'Pending';
        else if (lastRunFailed)
            taggingStatus = 'Failed';
        return { EmbeddingStatus: embeddingStatus, TaggingStatus: taggingStatus };
    }
    mapStatusString(status) {
        if (!status)
            return 'Pending';
        const lower = status.toLowerCase();
        if (lower === 'complete' || lower === 'completed' || lower === 'done')
            return 'Complete';
        if (lower === 'processing' || lower === 'running')
            return 'Processing';
        if (lower === 'failed' || lower === 'error')
            return 'Failed';
        return 'Pending';
    }
    formatRelativeTime(dateStr) {
        if (!dateStr)
            return 'Never';
        const now = new Date();
        const then = new Date(dateStr);
        const diffMs = now.getTime() - then.getTime();
        const diffMins = Math.floor(diffMs / 60000);
        if (diffMins < 1)
            return 'Just now';
        if (diffMins < 60)
            return `${diffMins}m ago`;
        const diffHours = Math.floor(diffMins / 60);
        if (diffHours < 24)
            return `${diffHours}h ago`;
        const diffDays = Math.floor(diffHours / 24);
        return `${diffDays}d ago`;
    }
    /** Looks up the cron expression for a cached ScheduledAction by ID */
    getScheduledActionCron(scheduledActionID) {
        const cached = this._scheduledActions.get(NormalizeUUID(scheduledActionID));
        return cached?.CronExpression ?? null;
    }
    /** Returns the CSS class for a pipeline status badge color */
    GetStatusBadgeClass(status) {
        switch (status) {
            case 'Complete': return 'at-status-badge-complete';
            case 'Processing': return 'at-status-badge-processing';
            case 'Failed': return 'at-status-badge-failed';
            case 'Pending': return 'at-status-badge-pending';
        }
    }
    // ════════════════════════════════════════════
    // DELETE
    // ════════════════════════════════════════════
    async DeleteSource(card) {
        if (!confirm(`Delete source "${card.Name}"? This cannot be undone.`))
            return;
        try {
            const p = this.ProviderToUse;
            const entity = await p.GetEntityObject('MJ: Content Sources', p.CurrentUser);
            await entity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: card.ID }]));
            const deleted = await entity.Delete();
            if (deleted) {
                MJNotificationService.Instance.CreateSimpleNotification('Source deleted', 'success', 2500);
                this.DataChanged.emit();
            }
            else {
                MJNotificationService.Instance.CreateSimpleNotification('Failed to delete source', 'error', 3000);
            }
        }
        catch (error) {
            const msg = error instanceof Error ? error.message : String(error);
            MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
        }
    }
    // ════════════════════════════════════════════
    // SCHEDULE DIALOG — Quick Schedule for Source
    // ════════════════════════════════════════════
    OpenScheduleDialog(card) {
        this.SchedulingSourceCard = card;
        this.ScheduleCron = '0 2 * * *';
        this.ScheduleEnabled = true;
        this.ShowScheduleDialog = true;
        this.cdr.detectChanges();
    }
    CloseScheduleDialog() {
        this.ShowScheduleDialog = false;
        this.SchedulingSourceCard = null;
        this.cdr.detectChanges();
    }
    /**
     * Saves a new ScheduledAction for the current source, links it via
     * ContentSource.ScheduledActionID, and creates the default action params
     * for the Autotag and Vectorize action.
     */
    async SaveSchedule() {
        if (this.ScheduleSaving || !this.SchedulingSourceCard)
            return;
        this.ScheduleSaving = true;
        this.cdr.detectChanges();
        const card = this.SchedulingSourceCard;
        try {
            const p = this.ProviderToUse;
            // 1. Find the "Autotag and Vectorize Content" action
            const actionID = await this.findAutotagActionID();
            if (!actionID) {
                MJNotificationService.Instance.CreateSimpleNotification('Could not find the "Autotag and Vectorize Content" action. Please check action configuration.', 'error', 5000);
                return;
            }
            // 2. Create the ScheduledAction
            const scheduledAction = await p.GetEntityObject('MJ: Scheduled Actions', p.CurrentUser);
            scheduledAction.NewRecord();
            scheduledAction.Name = `Autotag: ${card.Name}`;
            scheduledAction.Description = `Automated classification pipeline for content source "${card.Name}"`;
            scheduledAction.ActionID = actionID;
            scheduledAction.Type = 'Custom';
            scheduledAction.CronExpression = this.ScheduleCron;
            scheduledAction.CustomCronExpression = this.ScheduleCron;
            scheduledAction.Status = this.ScheduleEnabled ? 'Active' : 'Disabled';
            scheduledAction.Timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
            const saved = await scheduledAction.Save();
            if (!saved) {
                const errorDetail = scheduledAction.LatestResult?.CompleteMessage ?? 'Unknown error';
                MJNotificationService.Instance.CreateSimpleNotification(`Failed to create schedule: ${errorDetail}`, 'error', 5000);
                return;
            }
            // 3. Create ScheduledActionParam for sourceIDs
            await this.createSourceIDParam(scheduledAction.ID, actionID, card.ID);
            // 4. Link ScheduledAction to ContentSource
            await this.linkScheduleToSource(card.ID, scheduledAction.ID);
            // 5. Cache the new action for cron display
            this._scheduledActions.set(NormalizeUUID(scheduledAction.ID), scheduledAction);
            MJNotificationService.Instance.CreateSimpleNotification(`Schedule created: ${CronToHumanReadable(this.ScheduleCron)}`, 'success', 3000);
            this.CloseScheduleDialog();
            this.DataChanged.emit();
        }
        catch (error) {
            const msg = error instanceof Error ? error.message : String(error);
            console.error('[Classify] Schedule creation error:', error);
            MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 5000);
        }
        finally {
            this.ScheduleSaving = false;
            this.cdr.detectChanges();
        }
    }
    /**
     * Removes the schedule from a source card by unlinking the ScheduledActionID.
     */
    async RemoveSchedule(card) {
        if (!card.ScheduledActionID)
            return;
        if (!confirm(`Remove the schedule "${card.ScheduleDescription ?? 'schedule'}" from "${card.Name}"?`))
            return;
        try {
            await this.linkScheduleToSource(card.ID, null);
            MJNotificationService.Instance.CreateSimpleNotification('Schedule removed from source', 'success', 2500);
            this.DataChanged.emit();
        }
        catch (error) {
            const msg = error instanceof Error ? error.message : String(error);
            MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
        }
    }
    /** Returns the human-readable schedule description for a source card. */
    GetScheduleLabel(card) {
        return card.ScheduleDescription ?? 'Scheduled';
    }
    /** Returns a human-readable preview of a cron expression for the schedule dialog. */
    GetCronPreview(cron) {
        return CronToHumanReadable(cron);
    }
    /** Finds the Action ID for "Autotag and Vectorize Content" by querying actions */
    async findAutotagActionID() {
        const rv = RunView.FromMetadataProvider(this.ProviderToUse);
        const result = await rv.RunView({
            EntityName: 'Actions',
            ExtraFilter: `Name = 'Autotag and Vectorize Content'`,
            Fields: ['ID'],
            ResultType: 'simple',
            MaxRows: 1,
        });
        if (result.Success && result.Results.length > 0) {
            return result.Results[0].ID;
        }
        return null;
    }
    /**
     * Creates a ScheduledActionParam that passes the source ID to the action.
     * Looks up the "EntityNames" action param and sets the source ID as its value.
     */
    async createSourceIDParam(scheduledActionID, actionID, sourceID) {
        const rv = RunView.FromMetadataProvider(this.ProviderToUse);
        const paramResult = await rv.RunView({
            EntityName: 'Action Params',
            ExtraFilter: `ActionID = '${actionID}' AND Name = 'EntityNames'`,
            Fields: ['ID', 'Name'],
            ResultType: 'simple',
            MaxRows: 1,
        });
        if (!paramResult.Success || paramResult.Results.length === 0) {
            console.warn('[Classify] Could not find EntityNames action param for source ID scheduling');
            return;
        }
        const p = this.ProviderToUse;
        const param = await p.GetEntityObject('MJ: Scheduled Action Params', p.CurrentUser);
        param.NewRecord();
        param.ScheduledActionID = scheduledActionID;
        param.ActionParamID = paramResult.Results[0].ID;
        param.ValueType = 'Static';
        param.Value = sourceID;
        const saved = await param.Save();
        if (!saved) {
            console.warn('[Classify] Failed to save schedule param:', param.LatestResult?.CompleteMessage);
        }
    }
    /**
     * Links (or unlinks) a ScheduledAction to a ContentSource by updating
     * the ContentSource.ScheduledActionID field.
     */
    async linkScheduleToSource(sourceID, scheduledActionID) {
        const p = this.ProviderToUse;
        const entity = await p.GetEntityObject('MJ: Content Sources', p.CurrentUser);
        await entity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: sourceID }]));
        entity.ScheduledActionID = scheduledActionID;
        const saved = await entity.Save();
        if (!saved) {
            throw new Error(entity.LatestResult?.CompleteMessage ?? 'Failed to update content source');
        }
    }
    // ════════════════════════════════════════════
    // SOURCE DETAIL SLIDE-IN
    // ════════════════════════════════════════════
    async OpenSourceDetail(card) {
        this.SourceDetailLoading = true;
        this.SourceDetailPage = 0;
        this.SourceDetailStatusFilter = 'All';
        this.ShowSourceDetail = true;
        this.cdr.detectChanges();
        try {
            const sourceItems = await this.loadContentItemsForSource(card.ID);
            const sourceRuns = await this.loadRunHistoryForSource(card.ID);
            const embeddingModelName = this.resolveEmbeddingModelName(card.EmbeddingModelID);
            const vectorIndexName = this.resolveVectorIndexName(card.VectorIndexID);
            const errorCount = sourceRuns.filter(r => r.StatusClass === 'failed').length;
            this.SelectedSource = {
                ID: card.ID,
                Name: card.Name,
                SourceTypeName: card.SourceTypeName,
                FileTypeName: card.FileTypeName,
                ContentTypeName: card.ContentTypeName,
                RequiresFileType: card.RequiresFileType,
                StatusClass: card.StatusClass,
                StatusLabel: card.StatusLabel,
                Icon: card.Icon,
                URL: card.URL,
                EmbeddingModelName: embeddingModelName,
                VectorIndexName: vectorIndexName,
                ItemCount: card.ItemCount,
                TagCount: card.TagCount,
                AvgTags: card.AvgTags,
                LastRunAgo: card.LastRunAgo,
                ErrorCount: errorCount,
                ContentItems: sourceItems,
                RunHistory: sourceRuns
            };
        }
        catch (error) {
            console.error('[Autotagging] Error loading source detail:', error);
        }
        finally {
            this.SourceDetailLoading = false;
            this.cdr.detectChanges();
        }
    }
    CloseSourceDetail() {
        this.ShowSourceDetail = false;
        this.SelectedSource = null;
        this.cdr.detectChanges();
    }
    OpenContentItemDetail(item) {
        this.OpenContentItemRequested.emit(item);
    }
    OpenEditSourceFromDetail() {
        if (!this.SelectedSource)
            return;
        const card = this.SourceCards.find(c => UUIDsEqual(c.ID, this.SelectedSource.ID));
        if (card) {
            this.CloseSourceDetail();
            this.EditSourceRequested.emit(card);
        }
    }
    RunSourceFromDetail() {
        if (!this.SelectedSource)
            return;
        const sourceID = this.SelectedSource.ID;
        this.CloseSourceDetail();
        this.RunSourceRequested.emit(sourceID);
    }
    async DeleteSourceFromDetail() {
        if (!this.SelectedSource)
            return;
        const card = this.SourceCards.find(c => UUIDsEqual(c.ID, this.SelectedSource.ID));
        if (card) {
            this.CloseSourceDetail();
            await this.DeleteSource(card);
        }
    }
    // ── Source-detail filtering + pagination ──
    get FilteredSourceDetailItems() {
        if (!this.SelectedSource)
            return [];
        const items = this.SourceDetailStatusFilter === 'All'
            ? this.SelectedSource.ContentItems
            : this.SelectedSource.ContentItems.filter(ci => ci.EmbeddingStatus === this.SourceDetailStatusFilter ||
                ci.TaggingStatus === this.SourceDetailStatusFilter);
        const start = this.SourceDetailPage * this.SourceDetailPageSize;
        return items.slice(start, start + this.SourceDetailPageSize);
    }
    get FilteredSourceDetailTotal() {
        if (!this.SelectedSource)
            return 0;
        if (this.SourceDetailStatusFilter === 'All')
            return this.SelectedSource.ContentItems.length;
        return this.SelectedSource.ContentItems.filter(ci => ci.EmbeddingStatus === this.SourceDetailStatusFilter ||
            ci.TaggingStatus === this.SourceDetailStatusFilter).length;
    }
    get SourceDetailTotalPages() {
        return Math.max(1, Math.ceil(this.FilteredSourceDetailTotal / this.SourceDetailPageSize));
    }
    SourceDetailPrevPage() {
        if (this.SourceDetailPage > 0) {
            this.SourceDetailPage--;
            this.cdr.detectChanges();
        }
    }
    SourceDetailNextPage() {
        if (this.SourceDetailPage < this.SourceDetailTotalPages - 1) {
            this.SourceDetailPage++;
            this.cdr.detectChanges();
        }
    }
    OnSourceDetailStatusFilterChange() {
        this.SourceDetailPage = 0;
        this.cdr.detectChanges();
    }
    /**
     * Placeholder handler for retrying failed items in source detail. Surfaces a
     * notification; the pipeline re-processes failed items on the next run.
     */
    RetryFailedItems() {
        if (!this.SelectedSource)
            return;
        const failedCount = this.SelectedSource.ContentItems.filter(ci => ci.EmbeddingStatus === 'Failed' || ci.TaggingStatus === 'Failed').length;
        if (failedCount === 0) {
            MJNotificationService.Instance.CreateSimpleNotification('No failed items to retry', 'info', 2500);
            return;
        }
        MJNotificationService.Instance.CreateSimpleNotification(`Retry queued for ${failedCount} failed item${failedCount > 1 ? 's' : ''}. Pipeline will re-process on next run.`, 'info', 3000);
    }
    async loadContentItemsForSource(sourceId) {
        const rv = RunView.FromMetadataProvider(this.ProviderToUse);
        const result = await rv.RunView({
            EntityName: 'MJ: Content Items',
            ExtraFilter: `ContentSourceID='${sourceId}'`,
            OrderBy: '__mj_UpdatedAt DESC',
            MaxRows: 100,
            ResultType: 'simple'
        });
        if (!result.Success)
            return [];
        const tagsByItem = this.countTagsByItem();
        return result.Results.map(item => {
            const itemId = item['ID'];
            const allTags = this.getAllWeightedTagsForItem(itemId);
            const tagCount = tagsByItem.get(itemId) ?? allTags.length;
            const contentSourceTypeID = item['ContentSourceTypeID'] ?? '';
            const itemStatuses = this.inferPipelineStatuses(item, tagCount);
            return {
                ID: itemId,
                Name: deriveDisplayName({ Name: item['Name'], Description: item['Description'] }),
                SourceName: item['ContentSource'] ?? '',
                SourceTypeName: item['ContentSourceType'] ?? '',
                ContentTypeName: item['ContentType'] ?? '',
                FileTypeName: item['ContentFileType'] ?? '',
                URL: item['URL'] ?? '',
                TextContent: item['Text'] ?? '',
                Checksum: item['Checksum'] ?? '',
                Tags: allTags,
                CreatedAt: formatDate(item['__mj_CreatedAt'] ?? ''),
                UpdatedAt: formatDate(item['__mj_UpdatedAt'] ?? ''),
                ContentSourceID: sourceId,
                ContentSourceTypeID: contentSourceTypeID,
                StatusDot: tagCount > 0 ? 'complete' : 'processing',
                TagCount: tagCount,
                RequiresContentType: this.sourceTypeRequiresFileType(contentSourceTypeID),
                EntityRecordID: this.resolveEntityRecordID(item),
                EntityName: this.resolveEntityName(sourceId),
                EmbeddingStatus: itemStatuses.EmbeddingStatus,
                TaggingStatus: itemStatuses.TaggingStatus,
            };
        });
    }
    async loadRunHistoryForSource(sourceId) {
        const rv = RunView.FromMetadataProvider(this.ProviderToUse);
        const result = await rv.RunView({
            EntityName: 'MJ: Content Process Runs',
            ExtraFilter: `SourceID='${sourceId}'`,
            OrderBy: 'StartTime DESC',
            MaxRows: 10,
            ResultType: 'simple'
        });
        if (!result.Success)
            return [];
        return result.Results.map(run => {
            const status = run['Status'] ?? 'Unknown';
            const startTime = run['StartTime'];
            const endTime = run['EndTime'];
            const duration = computeDuration(startTime, endTime);
            const processedItems = run['ProcessedItems'];
            const errorCount = run['ErrorCount'];
            const statusLower = status.toLowerCase();
            const isFailed = statusLower === 'error' || statusLower === 'failed';
            const isRunning = statusLower === 'running' || statusLower === 'processing';
            const hasErrors = (errorCount ?? 0) > 0;
            return {
                ID: run['ID'],
                Status: displayStatus(status),
                StatusClass: isFailed ? 'failed' : isRunning ? 'running' : 'complete',
                SourceName: run['Source'] ?? 'Unknown',
                StartedDisplay: startTime ? formatDate(startTime) : '—',
                Duration: duration,
                Items: processedItems != null ? formatNumber(processedItems) : '—',
                Tags: '—',
                Errors: hasErrors ? formatNumber(errorCount) : (isFailed ? status : '0'),
                ErrorClass: isFailed || hasErrors ? 'run-error-text' : ''
            };
        });
    }
    static ɵfac = /*@__PURE__*/ (() => { let ɵClassifySourcesTabComponent_BaseFactory; return function ClassifySourcesTabComponent_Factory(__ngFactoryType__) { return (ɵClassifySourcesTabComponent_BaseFactory || (ɵClassifySourcesTabComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ClassifySourcesTabComponent)))(__ngFactoryType__ || ClassifySourcesTabComponent); }; })();
    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"], [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"], [1, "fa-solid", "fa-database"], [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"], ["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"], [1, "at-empty-state", 2, "padding", "16px"], [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) {
            i0.ɵɵelementStart(0, "mj-page-header-interior", 0)(1, "div", 1)(2, "button", 2);
            i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Template_button_click_2_listener() { return ctx.Refresh(); });
            i0.ɵɵconditionalCreate(3, ClassifySourcesTabComponent_Conditional_3_Template, 3, 0)(4, ClassifySourcesTabComponent_Conditional_4_Template, 3, 0);
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(5, "button", 3);
            i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Template_button_click_5_listener() { return ctx.onAddSourceGuided(); });
            i0.ɵɵelement(6, "i", 4);
            i0.ɵɵelementStart(7, "span", 5);
            i0.ɵɵtext(8, "Add Source (Guided)");
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(9, "button", 6);
            i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Template_button_click_9_listener() { return ctx.onAddSource(); });
            i0.ɵɵelement(10, "i", 7);
            i0.ɵɵelementStart(11, "span", 5);
            i0.ɵɵtext(12, "Add Source");
            i0.ɵɵelementEnd()()()();
            i0.ɵɵelementStart(13, "mj-page-body-interior", 8)(14, "div", 9);
            i0.ɵɵconditionalCreate(15, ClassifySourcesTabComponent_Conditional_15_Template, 2, 0, "div", 10);
            i0.ɵɵelementStart(16, "div", 11);
            i0.ɵɵconditionalCreate(17, ClassifySourcesTabComponent_Conditional_17_Template, 13, 0, "div", 12);
            i0.ɵɵelementStart(18, "div", 13);
            i0.ɵɵrepeaterCreate(19, ClassifySourcesTabComponent_For_20_Template, 50, 17, "div", 14, _forTrack0);
            i0.ɵɵelementStart(21, "div", 15);
            i0.ɵɵlistener("click", function ClassifySourcesTabComponent_Template_div_click_21_listener() { return ctx.onAddSource(); });
            i0.ɵɵelement(22, "i", 16);
            i0.ɵɵelementStart(23, "span", 17);
            i0.ɵɵtext(24, "Add Content Source");
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(25, "span", 18);
            i0.ɵɵtext(26, "Web, RSS, Email, Files, API");
            i0.ɵɵelementEnd()()()()()();
            i0.ɵɵconditionalCreate(27, ClassifySourcesTabComponent_Conditional_27_Template, 11, 2);
            i0.ɵɵconditionalCreate(28, ClassifySourcesTabComponent_Conditional_28_Template, 37, 8, "div", 19);
            i0.ɵɵelementStart(29, "classify-dry-run-preview", 20);
            i0.ɵɵlistener("Closed", function ClassifySourcesTabComponent_Template_classify_dry_run_preview_Closed_29_listener() { return ctx.CloseDryRunPreview(); });
            i0.ɵɵelementEnd();
        } if (rf & 2) {
            i0.ɵɵadvance(2);
            i0.ɵɵproperty("disabled", ctx.IsLoading);
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.IsLoading ? 3 : 4);
            i0.ɵɵadvance(10);
            i0.ɵɵproperty("Padding", false)("Flex", true);
            i0.ɵɵadvance(2);
            i0.ɵɵconditional(ctx.IsLoading ? 15 : -1);
            i0.ɵɵadvance(2);
            i0.ɵɵconditional(ctx.SourceCards.length === 0 && !ctx.IsLoading ? 17 : -1);
            i0.ɵɵadvance(2);
            i0.ɵɵrepeater(ctx.SourceCards);
            i0.ɵɵadvance(8);
            i0.ɵɵconditional(ctx.ShowSourceDetail ? 27 : -1);
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.ShowScheduleDialog && ctx.SchedulingSourceCard ? 28 : -1);
            i0.ɵɵadvance();
            i0.ɵɵproperty("Provider", ctx.Provider)("Show", ctx.ShowDryRunPreview)("SourceCard", ctx.DryRunSourceCard);
        } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.CheckboxControlValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.LoadingComponent, i3.MJButtonDirective, i3.MJPageHeaderInteriorComponent, i3.MJPageBodyInteriorComponent, i4.ClassifyDryRunPreviewDialogComponent, i5.DecimalPipe], styles: ["\n\n\n\n\n\n\n\n\n\n\n.at-sources-empty[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]    > i[_ngcontent-%COMP%] {\n    font-size: 2rem;\n    color: var(--mj-brand-primary);\n}\n.at-sources-empty[_ngcontent-%COMP%]   h3[_ngcontent-%COMP%] {\n    margin: 0;\n    font-size: 1rem;\n    color: var(--mj-text-primary);\n}\n.at-sources-empty[_ngcontent-%COMP%]   p[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n    display: flex;\n    gap: 8px;\n    margin-top: 6px;\n}"] });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ClassifySourcesTabComponent, [{
        type: Component,
        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        <div class=\"at-sources-empty\">\n          <i class=\"fa-solid fa-database\"></i>\n          <h3>No content sources yet</h3>\n          <p>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.</p>\n          <div class=\"at-sources-empty-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        </div>\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              <div class=\"at-empty-state\" style=\"padding: 16px;\">\n                <p>{{ SourceDetailStatusFilter === 'All' ? 'No content items yet.' : 'No items match this filter.' }}</p>\n              </div>\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"] }]
    }], null, { Sources: [{
            type: Input
        }], Items: [{
            type: Input
        }], Tags: [{
            type: Input
        }], Runs: [{
            type: Input
        }], TotalItemCount: [{
            type: Input
        }], TotalTagCount: [{
            type: Input
        }], ScheduledActions: [{
            type: Input
        }], EntityRecordDocCache: [{
            type: Input
        }], AddSourceRequested: [{
            type: Output
        }], AddSourceGuidedRequested: [{
            type: Output
        }], EditSourceRequested: [{
            type: Output
        }], RunSourceRequested: [{
            type: Output
        }], OpenContentItemRequested: [{
            type: Output
        }], DataChanged: [{
            type: Output
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ClassifySourcesTabComponent, { className: "ClassifySourcesTabComponent", filePath: "src/AI/components/autotagging/tabs/sources-tab.component.ts", lineNumber: 34 }); })();
//# sourceMappingURL=sources-tab.component.js.map