@memberjunction/ng-entity-viewer 5.43.0 → 5.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/aggregate-panel/aggregate-panel.component.d.ts +5 -0
- package/dist/lib/aggregate-panel/aggregate-panel.component.d.ts.map +1 -1
- package/dist/lib/aggregate-panel/aggregate-panel.component.js +45 -47
- package/dist/lib/aggregate-panel/aggregate-panel.component.js.map +1 -1
- package/dist/lib/entity-cards/entity-cards.component.js +7 -10
- package/dist/lib/entity-cards/entity-cards.component.js.map +1 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.d.ts +10 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.d.ts.map +1 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.js +35 -34
- package/dist/lib/entity-data-grid/entity-data-grid.component.js.map +1 -1
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.d.ts +0 -4
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.d.ts.map +1 -1
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js +166 -207
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js.map +1 -1
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts +109 -5
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts.map +1 -1
- package/dist/lib/entity-viewer/entity-viewer.component.js +287 -42
- package/dist/lib/entity-viewer/entity-viewer.component.js.map +1 -1
- package/dist/lib/recycle-bin/recycle-bin.component.js +21 -44
- package/dist/lib/recycle-bin/recycle-bin.component.js.map +1 -1
- package/dist/lib/shared-view-warning-dialog/shared-view-warning-dialog.component.js +19 -20
- package/dist/lib/shared-view-warning-dialog/shared-view-warning-dialog.component.js.map +1 -1
- package/dist/lib/view-config-panel/view-config-panel.component.js +268 -301
- package/dist/lib/view-config-panel/view-config-panel.component.js.map +1 -1
- package/dist/lib/view-selector/view-selector.component.d.ts +26 -1
- package/dist/lib/view-selector/view-selector.component.d.ts.map +1 -1
- package/dist/lib/view-selector/view-selector.component.js +118 -76
- package/dist/lib/view-selector/view-selector.component.js.map +1 -1
- package/dist/lib/view-types/descriptors/grid-view-type.d.ts +7 -0
- package/dist/lib/view-types/descriptors/grid-view-type.d.ts.map +1 -1
- package/dist/lib/view-types/descriptors/grid-view-type.js +7 -0
- package/dist/lib/view-types/descriptors/grid-view-type.js.map +1 -1
- package/dist/lib/view-types/renderers/grid-view-renderer.component.d.ts +18 -1
- package/dist/lib/view-types/renderers/grid-view-renderer.component.d.ts.map +1 -1
- package/dist/lib/view-types/renderers/grid-view-renderer.component.js +29 -3
- package/dist/lib/view-types/renderers/grid-view-renderer.component.js.map +1 -1
- package/dist/lib/view-types/renderers/map-view-renderer.component.d.ts.map +1 -1
- package/dist/lib/view-types/renderers/map-view-renderer.component.js +11 -14
- package/dist/lib/view-types/renderers/map-view-renderer.component.js.map +1 -1
- package/dist/lib/view-types/renderers/timeline-view-renderer.component.d.ts.map +1 -1
- package/dist/lib/view-types/renderers/timeline-view-renderer.component.js +12 -14
- package/dist/lib/view-types/renderers/timeline-view-renderer.component.js.map +1 -1
- package/dist/lib/view-types/view-type.contracts.d.ts +44 -0
- package/dist/lib/view-types/view-type.contracts.d.ts.map +1 -1
- package/dist/lib/view-types/view-type.contracts.js +6 -0
- package/dist/lib/view-types/view-type.contracts.js.map +1 -1
- package/dist/lib/view-workspace/view-workspace.component.d.ts +32 -1
- package/dist/lib/view-workspace/view-workspace.component.d.ts.map +1 -1
- package/dist/lib/view-workspace/view-workspace.component.js +68 -7
- package/dist/lib/view-workspace/view-workspace.component.js.map +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +10 -1
- package/dist/module.js.map +1 -1
- package/package.json +18 -17
- package/dist/__tests__/entity-cards-selection.test.d.ts +0 -2
- package/dist/__tests__/entity-cards-selection.test.d.ts.map +0 -1
- package/dist/__tests__/entity-cards-selection.test.js +0 -149
- package/dist/__tests__/entity-cards-selection.test.js.map +0 -1
- package/dist/__tests__/entity-cards-viewmodel.test.d.ts +0 -2
- package/dist/__tests__/entity-cards-viewmodel.test.d.ts.map +0 -1
- package/dist/__tests__/entity-cards-viewmodel.test.js +0 -208
- package/dist/__tests__/entity-cards-viewmodel.test.js.map +0 -1
- package/dist/__tests__/highlight.test.d.ts +0 -2
- package/dist/__tests__/highlight.test.d.ts.map +0 -1
- package/dist/__tests__/highlight.test.js +0 -67
- package/dist/__tests__/highlight.test.js.map +0 -1
- package/dist/__tests__/index.test.d.ts +0 -2
- package/dist/__tests__/index.test.d.ts.map +0 -1
- package/dist/__tests__/index.test.js +0 -7
- package/dist/__tests__/index.test.js.map +0 -1
- package/dist/__tests__/view-types.test.d.ts +0 -2
- package/dist/__tests__/view-types.test.d.ts.map +0 -1
- package/dist/__tests__/view-types.test.js +0 -102
- package/dist/__tests__/view-types.test.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-view-renderer.component.js","sourceRoot":"","sources":["../../../../src/lib/view-types/renderers/timeline-view-renderer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectorRef,\n OnInit,\n ViewEncapsulation,\n inject,\n} from '@angular/core';\nimport { EntityInfo, EntityFieldInfo, EntityFieldTSType } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport {\n TimelineGroup,\n TimeSegmentGrouping,\n TimelineSortOrder,\n AfterEventClickArgs,\n} from '@memberjunction/ng-timeline';\nimport { TimelineOrientation } from '../../types';\nimport { IViewRenderer } from '../view-type.contracts';\n\n/**\n * The persisted configuration shape for the Timeline view type.\n *\n * This is the `config` payload the host hands to the renderer on mount and that the\n * renderer emits back (in full) via {@link TimelineViewRendererComponent.configChanged}\n * whenever the user changes any of the timeline chrome controls. The host treats it as an\n * opaque blob — only this renderer (and an eventual prop-sheet) understands its keys — and\n * persists it per `MJ: View Types` row.\n *\n * All fields are optional: on first mount the renderer falls back to sensible defaults\n * (first available date field, vertical orientation, descending sort, monthly segments).\n */\nexport interface TimelineViewConfig {\n /** The entity date-field used to place records on the timeline (e.g. `__mj_CreatedAt`). */\n dateFieldName?: string;\n /** Vertical (alternating) vs. horizontal (single-row) timeline layout. */\n orientation?: TimelineOrientation;\n /** Newest-first (`desc`) vs. oldest-first (`asc`) event ordering. */\n sortOrder?: TimelineSortOrder;\n /** How events are bucketed into collapsible segments (day/week/month/...). */\n segmentGrouping?: TimeSegmentGrouping;\n}\n\n/**\n * TimelineViewRendererComponent\n * -----------------------------\n * The Timeline **view type** as a self-contained {@link IViewRenderer} plug-in. Where the\n * Timeline view used to be hard-wired into the generic `mj-entity-viewer` host (which owned\n * the date-field detection, the record→{@link TimelineGroup} transformation, and the\n * date-field / orientation / sort chrome), this component now OWNS all of it. The host simply\n * dynamic-mounts this renderer when Timeline is the active view type and feeds it the standard\n * renderer inputs (`entity` / `records` / `selectedRecordId` / `filterText` / `config`).\n *\n * It renders a small chrome header row (date-field selector + orientation toggle + sort toggle)\n * above a flex-filling `<mj-timeline>`, exactly reproducing the host's previous timeline chrome\n * and bindings. Because the host only mounts this plug-in when Timeline is active, the chrome\n * always renders — no extra `EffectiveViewMode === 'timeline'` guard is needed.\n *\n * **What was absorbed from the host** (`EntityViewerComponent`): `detectDateFields()`,\n * `sortDateFieldsByPriority()`, `AvailableDateFields`/`HasDateFields`, `configureTimeline()`,\n * `updateTimelineGroups()` (+ `findTitleField`/`findDescriptionField`/`findSubtitleField`),\n * `ToggleTimelineOrientation()`, `ToggleTimelineSortOrder()`, `SetTimelineDateField()`,\n * `SelectedDateFieldDisplayName`, `OnTimelineEventClick()`, and the `TimelineSelectedEventID`\n * composite-key→raw-id derivation.\n *\n * Inputs use the camelCase names mandated by the {@link IViewRenderer} contract (the host binds\n * them by those exact names) rather than MJ's usual PascalCase for public members.\n */\n@Component({\n standalone: false,\n selector: 'mj-timeline-view-renderer',\n encapsulation: ViewEncapsulation.None,\n template: `\n <!-- Chrome row: date-field selector + orientation toggle + sort toggle.\n Always rendered — this plug-in only mounts when Timeline is the active view. -->\n <div class=\"timeline-view-chrome\">\n <!-- Date Field Selector -->\n <div class=\"timeline-date-selector\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n @if (AvailableDateFields.length === 1) {\n <span class=\"date-field-label\">{{ SelectedDateFieldDisplayName }}</span>\n } @else if (AvailableDateFields.length > 1) {\n <select\n class=\"date-field-select\"\n [value]=\"SelectedTimelineDateField\"\n (change)=\"SetTimelineDateField($any($event.target).value)\">\n @for (field of AvailableDateFields; track field.Name) {\n <option [value]=\"field.Name\">{{ field.DisplayNameOrName }}</option>\n }\n </select>\n }\n </div>\n\n <!-- Orientation Toggle -->\n <div class=\"timeline-orientation-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"ToggleTimelineOrientation()\"\n [title]=\"TimelineOrientationState === 'vertical' ? 'Switch to Horizontal' : 'Switch to Vertical'\">\n <i [class]=\"TimelineOrientationState === 'vertical' ? 'fa-solid fa-ellipsis-vertical' : 'fa-solid fa-ellipsis'\"></i>\n </button>\n </div>\n\n <!-- Sort Order Toggle -->\n <div class=\"timeline-sort-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"ToggleTimelineSortOrder()\"\n [title]=\"TimelineSortOrderState === 'desc' ? 'Showing Newest First (click for Oldest First)' : 'Showing Oldest First (click for Newest First)'\">\n <i [class]=\"TimelineSortOrderState === 'desc' ? 'fa-solid fa-arrow-down-wide-short' : 'fa-solid fa-arrow-up-wide-short'\"></i>\n </button>\n </div>\n </div>\n\n @if (HasDateFields) {\n <mj-timeline\n [groups]=\"TimelineGroups\"\n [orientation]=\"TimelineOrientationState\"\n [layout]=\"TimelineOrientationState === 'vertical' ? 'alternating' : 'single'\"\n [sortOrder]=\"TimelineSortOrderState\"\n [segmentGrouping]=\"TimelineSegmentGrouping\"\n [segmentsCollapsible]=\"true\"\n [segmentsDefaultExpanded]=\"true\"\n [selectedEventId]=\"TimelineSelectedEventID\"\n (afterEventClick)=\"OnTimelineEventClick($event)\">\n </mj-timeline>\n } @else {\n <div class=\"timeline-view-empty\">\n <i class=\"fa-solid fa-calendar-xmark\"></i>\n <span>This entity has no date fields to plot on a timeline.</span>\n </div>\n }\n `,\n styles: [\n `\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .timeline-view-chrome {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 12px;\n flex: 0 0 auto;\n }\n\n .timeline-view-renderer mj-timeline,\n :host mj-timeline {\n flex: 1 1 auto;\n min-height: 0;\n }\n\n /* Timeline Date Field Selector */\n .timeline-date-selector {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n }\n\n .timeline-date-selector i {\n color: var(--mj-text-disabled);\n }\n\n .date-field-label {\n color: var(--mj-text-secondary);\n font-weight: 500;\n }\n\n .date-field-select {\n padding: 4px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 13px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n outline: none;\n transition: border-color 0.15s ease;\n }\n\n .date-field-select:hover {\n border-color: var(--mj-border-strong);\n }\n\n .date-field-select:focus {\n border-color: var(--mj-brand-primary);\n }\n\n /* Orientation / Sort toggles */\n .timeline-orientation-toggle,\n .timeline-sort-toggle {\n display: flex;\n background: var(--mj-bg-surface-card);\n border-radius: 6px;\n padding: 2px;\n }\n\n .toggle-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n }\n\n .toggle-btn:hover {\n color: var(--mj-text-secondary);\n }\n\n .toggle-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n }\n\n .timeline-view-empty {\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n color: var(--mj-text-muted);\n padding: 32px;\n text-align: center;\n }\n\n .timeline-view-empty i {\n font-size: 32px;\n opacity: 0.6;\n }\n `,\n ],\n})\nexport class TimelineViewRendererComponent\n extends BaseAngularComponent\n implements IViewRenderer<TimelineViewConfig>, OnInit\n{\n // ========================================\n // IViewRenderer inputs (camelCase per the host contract)\n // ========================================\n\n private _entity: EntityInfo | null = null;\n /** The entity whose records are being rendered. Re-detects date fields + rebuilds groups on change. */\n @Input()\n set entity(value: EntityInfo | null) {\n const changed = !UUIDsEqual(value?.ID, this._entity?.ID);\n this._entity = value;\n if (changed) {\n this.detectDateFields();\n this.cdr.detectChanges();\n }\n }\n get entity(): EntityInfo | null {\n return this._entity;\n }\n\n private _records: Record<string, unknown>[] = [];\n /** The records to render (already loaded/filtered by the host). Rebuilds groups on change. */\n @Input()\n set records(value: Record<string, unknown>[]) {\n this._records = value ?? [];\n this.updateTimelineGroups();\n this.cdr.detectChanges();\n }\n get records(): Record<string, unknown>[] {\n return this._records;\n }\n\n /** Primary-key string of the currently selected record, if any (composite-key encoded). */\n @Input() selectedRecordId: string | null = null;\n\n /** Active filter text — accepted for contract uniformity; the host pre-filters `records`. */\n @Input() filterText: string | null = null;\n\n private _config: TimelineViewConfig = {};\n /**\n * This view's persisted configuration. Seeding the chrome controls from it is deferred to\n * {@link applyConfigToState}, called both here (for late updates) and in {@link ngOnInit}\n * (for the initial mount, where the host sets `config` via `setInput` before init runs).\n */\n @Input()\n set config(value: TimelineViewConfig) {\n this._config = value ?? {};\n if (this._initialized) {\n this.applyConfigToState();\n this.cdr.detectChanges();\n }\n }\n get config(): TimelineViewConfig {\n return this._config;\n }\n\n // ========================================\n // IViewRenderer outputs\n // ========================================\n\n /** Emitted when a timeline event is clicked — payload is the RAW record object. */\n @Output() recordSelected = new EventEmitter<unknown>();\n\n /** Emitted when a record should be opened — payload is the RAW record object. */\n @Output() recordOpened = new EventEmitter<unknown>();\n\n /** Emitted (with the FULL updated config) whenever the user changes a chrome control. */\n @Output() configChanged = new EventEmitter<TimelineViewConfig>();\n\n // ========================================\n // RENDER STATE (absorbed from the host)\n // ========================================\n\n /** Whether the current entity has any date fields available for timeline view. */\n public HasDateFields = false;\n\n /** Available date fields from the entity, sorted by priority. */\n public AvailableDateFields: EntityFieldInfo[] = [];\n\n /** The currently selected date field name for the timeline. */\n public SelectedTimelineDateField: string | null = null;\n\n /** The built timeline groups handed to `<mj-timeline>`. */\n public TimelineGroups: TimelineGroup<Record<string, unknown>>[] = [];\n\n /**\n * Timeline sort order. Named `…State` (not `TimelineSortOrder`) to avoid colliding with the\n * imported {@link TimelineSortOrder} type symbol used in the template / signatures.\n */\n public TimelineSortOrderState: TimelineSortOrder = 'desc';\n\n /** Timeline segment grouping (day/week/month/...). */\n public TimelineSegmentGrouping: TimeSegmentGrouping = 'month';\n\n /**\n * Timeline orientation. Named `…State` to avoid colliding with the imported\n * {@link TimelineOrientation} type symbol.\n */\n public TimelineOrientationState: TimelineOrientation = 'vertical';\n\n private _initialized = false;\n private cdr = inject(ChangeDetectorRef);\n\n // ========================================\n // LIFECYCLE\n // ========================================\n\n ngOnInit(): void {\n // The host sets entity/records/config via setInput BEFORE ngOnInit, so detection may have\n // already run. Apply the seeded config now (controls + defaults), then (re)build groups.\n this._initialized = true;\n this.applyConfigToState();\n this.detectDateFields();\n this.cdr.detectChanges();\n }\n\n // ========================================\n // COMPUTED\n // ========================================\n\n /** Display name of the currently selected timeline date field. */\n get SelectedDateFieldDisplayName(): string {\n if (!this.SelectedTimelineDateField) {\n return '';\n }\n const field = this.AvailableDateFields.find((f) => f.Name === this.SelectedTimelineDateField);\n return field?.DisplayNameOrName || this.SelectedTimelineDateField;\n }\n\n /**\n * The raw ID value derived from {@link selectedRecordId} for timeline selection. The host\n * passes the selection in composite-key format (`ID|abc-123` or `ID=abc-123`), but the\n * timeline stores just the raw ID value — so strip the field-name prefix.\n */\n get TimelineSelectedEventID(): string | null {\n if (!this.selectedRecordId) {\n return null;\n }\n if (this.selectedRecordId.includes('|')) {\n const parts = this.selectedRecordId.split('|');\n return parts.length > 1 ? parts[1] : this.selectedRecordId;\n }\n if (this.selectedRecordId.includes('=')) {\n const parts = this.selectedRecordId.split('=');\n return parts.length > 1 ? parts[1] : this.selectedRecordId;\n }\n return this.selectedRecordId;\n }\n\n // ========================================\n // CHROME ACTIONS (absorbed from the host)\n // ========================================\n\n /** Toggle timeline orientation between vertical and horizontal, then persist via config. */\n ToggleTimelineOrientation(): void {\n this.TimelineOrientationState = this.TimelineOrientationState === 'vertical' ? 'horizontal' : 'vertical';\n this.emitConfigChange();\n this.cdr.detectChanges();\n }\n\n /** Toggle timeline sort order between newest-first (desc) and oldest-first (asc), then persist. */\n ToggleTimelineSortOrder(): void {\n this.TimelineSortOrderState = this.TimelineSortOrderState === 'desc' ? 'asc' : 'desc';\n this.emitConfigChange();\n this.cdr.detectChanges();\n }\n\n /** Change the date field used for the timeline, rebuild groups, then persist via config. */\n SetTimelineDateField(fieldName: string): void {\n if (this.AvailableDateFields.some((f) => f.Name === fieldName)) {\n this.SelectedTimelineDateField = fieldName;\n this.updateTimelineGroups();\n this.emitConfigChange();\n this.cdr.detectChanges();\n }\n }\n\n // ========================================\n // TIMELINE EVENT → RECORD MAPPING\n // ========================================\n\n /**\n * Handle a timeline event click. Maps the {@link AfterEventClickArgs} to the underlying raw\n * record (`event.event.entity`) and emits it on {@link recordSelected}. The host's dynamic\n * handler builds the composite key from the raw record, so we emit the record object as-is.\n */\n OnTimelineEventClick(event: AfterEventClickArgs): void {\n const record = event.event.entity as Record<string, unknown> | undefined;\n if (record) {\n this.recordSelected.emit(record);\n }\n }\n\n // ========================================\n // CONFIG <-> STATE\n // ========================================\n\n /**\n * Seed the chrome control state from {@link config}, applying sensible defaults where the\n * config is silent (vertical orientation, descending sort, monthly segments). The selected\n * date field is resolved against the currently-available date fields in {@link detectDateFields}.\n */\n private applyConfigToState(): void {\n const c = this._config;\n this.TimelineOrientationState = c.orientation ?? 'vertical';\n this.TimelineSortOrderState = c.sortOrder ?? 'desc';\n this.TimelineSegmentGrouping = c.segmentGrouping ?? 'month';\n }\n\n /** Emit the FULL current config object so the host can persist the change. */\n private emitConfigChange(): void {\n this._config = {\n dateFieldName: this.SelectedTimelineDateField ?? undefined,\n orientation: this.TimelineOrientationState,\n sortOrder: this.TimelineSortOrderState,\n segmentGrouping: this.TimelineSegmentGrouping,\n };\n this.configChanged.emit(this._config);\n }\n\n // ========================================\n // DATE-FIELD DETECTION (absorbed from the host)\n // ========================================\n\n /**\n * Detect the entity's date fields and configure the timeline. Resolves the selected date\n * field (preferring the configured one, falling back to the highest-priority available field)\n * and rebuilds the groups. No-ops to an empty state when the entity has no date fields.\n */\n private detectDateFields(): void {\n if (!this._entity) {\n this.HasDateFields = false;\n this.AvailableDateFields = [];\n this.TimelineGroups = [];\n return;\n }\n\n const dateFields = this._entity.Fields.filter((f) => f.TSType === EntityFieldTSType.Date);\n if (dateFields.length === 0) {\n this.HasDateFields = false;\n this.AvailableDateFields = [];\n this.TimelineGroups = [];\n return;\n }\n\n this.AvailableDateFields = this.sortDateFieldsByPriority(dateFields);\n this.HasDateFields = true;\n this.SelectedTimelineDateField = this.getEffectiveTimelineDateField();\n this.updateTimelineGroups();\n }\n\n /**\n * Sort date fields by priority: `DefaultInView` fields first (by Sequence), then the rest\n * (by Sequence).\n */\n private sortDateFieldsByPriority(dateFields: EntityFieldInfo[]): EntityFieldInfo[] {\n const defaultInView = dateFields.filter((f) => f.DefaultInView).sort((a, b) => a.Sequence - b.Sequence);\n const others = dateFields.filter((f) => !f.DefaultInView).sort((a, b) => a.Sequence - b.Sequence);\n return [...defaultInView, ...others];\n }\n\n /**\n * Resolve which date field to use: the configured `dateFieldName` when it's still a valid\n * available field, otherwise the first (highest-priority) available date field.\n */\n private getEffectiveTimelineDateField(): string {\n if (this._config.dateFieldName) {\n const configField = this.AvailableDateFields.find((f) => f.Name === this._config.dateFieldName);\n if (configField) {\n return configField.Name;\n }\n }\n return this.AvailableDateFields[0].Name;\n }\n\n // ========================================\n // GROUP BUILDING (absorbed from the host)\n // ========================================\n\n /**\n * Build the single {@link TimelineGroup} for the current entity + records + selected date\n * field, mirroring the host's previous `updateTimelineGroups()`. No-ops to an empty state\n * when there is no entity or no selected date field.\n */\n private updateTimelineGroups(): void {\n // Emit NO group until there is an entity, a resolved date field, AND records. Emitting an empty\n // group (records not loaded yet) makes the inner <mj-timeline> run its first refresh with zero\n // events and mark itself loaded; the later records-populated update can then be dropped by its\n // concurrent-refresh / already-loaded guards, leaving \"No events to display\". Waiting for records\n // means its first real load happens with data.\n if (!this._entity || !this.SelectedTimelineDateField || this._records.length === 0) {\n this.TimelineGroups = [];\n return;\n }\n\n const titleField = this.findTitleField();\n\n const group = new TimelineGroup<Record<string, unknown>>();\n group.DataSourceType = 'array';\n group.EntityObjects = this._records;\n group.TitleFieldName = titleField;\n group.DateFieldName = this.SelectedTimelineDateField;\n group.IdFieldName = 'ID';\n group.GroupLabel = this._entity.Name;\n\n const descField = this.findDescriptionField();\n if (descField) {\n group.DescriptionFieldName = descField;\n }\n\n const subtitleField = this.findSubtitleField(titleField);\n if (subtitleField) {\n group.SubtitleFieldName = subtitleField;\n }\n\n group.CardConfig = {\n collapsible: true,\n defaultExpanded: false,\n showDate: true,\n dateFormat: 'MMM d, yyyy h:mm a',\n };\n\n this.TimelineGroups = [group];\n }\n\n /**\n * Find the best field to use as the event title: the entity's NameField, then a\n * `DefaultInView` string field matching a common name pattern, then the first string field.\n */\n private findTitleField(): string {\n if (!this._entity) {\n return 'ID';\n }\n if (this._entity.NameField) {\n return this._entity.NameField.Name;\n }\n\n const stringFields = this._entity.Fields.filter(\n (f) => f.TSType === EntityFieldTSType.String && f.DefaultInView && !f.Name.startsWith('__mj_'),\n ).sort((a, b) => a.Sequence - b.Sequence);\n\n const namePatterns = ['name', 'title', 'subject', 'label'];\n for (const pattern of namePatterns) {\n const match = stringFields.find((f) => f.Name.toLowerCase().includes(pattern));\n if (match) {\n return match.Name;\n }\n }\n\n return stringFields.length > 0 ? stringFields[0].Name : 'ID';\n }\n\n /** Find a suitable description field by common naming pattern, or null. */\n private findDescriptionField(): string | null {\n if (!this._entity) {\n return null;\n }\n const descPatterns = ['description', 'notes', 'summary', 'content', 'body', 'details'];\n const textFields = this._entity.Fields.filter(\n (f) => f.TSType === EntityFieldTSType.String && !f.Name.startsWith('__mj_'),\n );\n for (const pattern of descPatterns) {\n const match = textFields.find((f) => f.Name.toLowerCase().includes(pattern));\n if (match) {\n return match.Name;\n }\n }\n return null;\n }\n\n /**\n * Find a suitable subtitle field (different from the title): a `DefaultInView` string field\n * matching a classification pattern (status/type/category/...), else the first other string\n * field, else null.\n */\n private findSubtitleField(excludeField: string): string | null {\n if (!this._entity) {\n return null;\n }\n const patterns = ['status', 'type', 'category', 'state', 'priority'];\n const fields = this._entity.Fields.filter(\n (f) =>\n f.TSType === EntityFieldTSType.String &&\n f.DefaultInView &&\n f.Name !== excludeField &&\n !f.Name.startsWith('__mj_'),\n ).sort((a, b) => a.Sequence - b.Sequence);\n\n for (const pattern of patterns) {\n const match = fields.find((f) => f.Name.toLowerCase().includes(pattern));\n if (match) {\n return match.Name;\n }\n }\n\n const firstOther = fields.find((f) => f.Name !== excludeField);\n return firstOther?.Name || null;\n }\n}\n\n/**\n * Tree-shaking guard. Force-references the component class so bundlers don't drop this module\n * when it's only mounted dynamically via the view-type descriptor's `RendererComponent`.\n */\nexport function LoadTimelineViewRenderer(): void {\n // no-op; presence prevents tree-shaking of the dynamically-mounted renderer\n void TimelineViewRendererComponent;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"timeline-view-renderer.component.js","sourceRoot":"","sources":["../../../../src/lib/view-types/renderers/timeline-view-renderer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,YAAY,EACZ,iBAAiB,EAEjB,iBAAiB,EACjB,MAAM,GACP,MAAM,eAAe,CAAC;AACvB,OAAO,EAA+B,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EACL,aAAa,GAId,MAAM,6BAA6B,CAAC;;;;;;;IAgE3B,+BAA+B;IAAA,YAAkC;IAAA,iBAAO;;;IAAzC,cAAkC;IAAlC,yDAAkC;;;IAO7D,kCAA6B;IAAA,YAA6B;IAAA,iBAAS;;;IAA3D,qCAAoB;IAAC,cAA6B;IAA7B,gDAA6B;;;;IAL9D,kCAG6D;IAA3D,yMAAU,gDAA+C,KAAC;IAC1D,kHAEC;IACH,iBAAS;;;IALP,wDAAmC;IAEnC,cAEC;IAFD,yCAEC;;;;IA2BP,uCASmD;IAAjD,iOAAmB,mCAA4B,KAAC;IAClD,iBAAc;;;IAFZ,AADA,AADA,AADA,AADA,AADA,AADA,AADA,8CAAyB,gDACe,qFACqC,4CACzC,mDACO,6BACf,iCACI,mDACW;;;IAI7C,oCAIkE;;AAxFxE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAwKH,MAAM,OAAO,6BACX,SAAQ,oBAAoB;IAG5B,2CAA2C;IAC3C,yDAAyD;IACzD,2CAA2C;IAEnC,OAAO,GAAsB,IAAI,CAAC;IAC1C,uGAAuG;IACvG,IACI,MAAM,CAAC,KAAwB;QACjC,MAAM,OAAO,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAEO,QAAQ,GAA8B,EAAE,CAAC;IACjD,8FAA8F;IAC9F,IACI,OAAO,CAAC,KAAgC;QAC1C,IAAI,CAAC,QAAQ,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,2FAA2F;IAClF,gBAAgB,GAAkB,IAAI,CAAC;IAEhD,6FAA6F;IACpF,UAAU,GAAkB,IAAI,CAAC;IAElC,OAAO,GAAuB,EAAE,CAAC;IACzC;;;;OAIG;IACH,IACI,MAAM,CAAC,KAAyB;QAClC,IAAI,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,2CAA2C;IAC3C,wBAAwB;IACxB,2CAA2C;IAE3C,mFAAmF;IACzE,cAAc,GAAG,IAAI,YAAY,EAAW,CAAC;IAEvD,iFAAiF;IACvE,YAAY,GAAG,IAAI,YAAY,EAAW,CAAC;IAErD,yFAAyF;IAC/E,aAAa,GAAG,IAAI,YAAY,EAAsB,CAAC;IAEjE,2CAA2C;IAC3C,wCAAwC;IACxC,2CAA2C;IAE3C,kFAAkF;IAC3E,aAAa,GAAG,KAAK,CAAC;IAE7B,iEAAiE;IAC1D,mBAAmB,GAAsB,EAAE,CAAC;IAEnD,+DAA+D;IACxD,yBAAyB,GAAkB,IAAI,CAAC;IAEvD,2DAA2D;IACpD,cAAc,GAA6C,EAAE,CAAC;IAErE;;;OAGG;IACI,sBAAsB,GAAsB,MAAM,CAAC;IAE1D,sDAAsD;IAC/C,uBAAuB,GAAwB,OAAO,CAAC;IAE9D;;;OAGG;IACI,wBAAwB,GAAwB,UAAU,CAAC;IAE1D,YAAY,GAAG,KAAK,CAAC;IACrB,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAExC,2CAA2C;IAC3C,YAAY;IACZ,2CAA2C;IAE3C,QAAQ;QACN,0FAA0F;QAC1F,yFAAyF;QACzF,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,2CAA2C;IAC3C,WAAW;IACX,2CAA2C;IAE3C,kEAAkE;IAClE,IAAI,4BAA4B;QAC9B,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC;YACpC,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAC9F,OAAO,KAAK,EAAE,iBAAiB,IAAI,IAAI,CAAC,yBAAyB,CAAC;IACpE,CAAC;IAED;;;;OAIG;IACH,IAAI,uBAAuB;QACzB,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC;QAC7D,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC;QAC7D,CAAC;QACD,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,2CAA2C;IAC3C,0CAA0C;IAC1C,2CAA2C;IAE3C,4FAA4F;IAC5F,yBAAyB;QACvB,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC,wBAAwB,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC;QACzG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,mGAAmG;IACnG,uBAAuB;QACrB,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,sBAAsB,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACtF,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,4FAA4F;IAC5F,oBAAoB,CAAC,SAAiB;QACpC,IAAI,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,yBAAyB,GAAG,SAAS,CAAC;YAC3C,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC5B,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,kCAAkC;IAClC,2CAA2C;IAE3C;;;;OAIG;IACH,oBAAoB,CAAC,KAA0B;QAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAA6C,CAAC;QACzE,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,mBAAmB;IACnB,2CAA2C;IAE3C;;;;OAIG;IACK,kBAAkB;QACxB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QACvB,IAAI,CAAC,wBAAwB,GAAG,CAAC,CAAC,WAAW,IAAI,UAAU,CAAC;QAC5D,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC;QACpD,IAAI,CAAC,uBAAuB,GAAG,CAAC,CAAC,eAAe,IAAI,OAAO,CAAC;IAC9D,CAAC;IAED,8EAA8E;IACtE,gBAAgB;QACtB,IAAI,CAAC,OAAO,GAAG;YACb,aAAa,EAAE,IAAI,CAAC,yBAAyB,IAAI,SAAS;YAC1D,WAAW,EAAE,IAAI,CAAC,wBAAwB;YAC1C,SAAS,EAAE,IAAI,CAAC,sBAAsB;YACtC,eAAe,EAAE,IAAI,CAAC,uBAAuB;SAC9C,CAAC;QACF,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,2CAA2C;IAC3C,gDAAgD;IAChD,2CAA2C;IAE3C;;;;OAIG;IACK,gBAAgB;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;YAC9B,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC1F,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC;YAC9B,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC;QACrE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC,6BAA6B,EAAE,CAAC;QACtE,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACK,wBAAwB,CAAC,UAA6B;QAC5D,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QACxG,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,aAAa,EAAE,GAAG,MAAM,CAAC,CAAC;IACvC,CAAC;IAED;;;OAGG;IACK,6BAA6B;QACnC,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAChG,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,WAAW,CAAC,IAAI,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,CAAC;IAED,2CAA2C;IAC3C,0CAA0C;IAC1C,2CAA2C;IAE3C;;;;OAIG;IACK,oBAAoB;QAC1B,gGAAgG;QAChG,+FAA+F;QAC/F,+FAA+F;QAC/F,kGAAkG;QAClG,+CAA+C;QAC/C,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,yBAAyB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnF,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAEzC,MAAM,KAAK,GAAG,IAAI,aAAa,EAA2B,CAAC;QAC3D,KAAK,CAAC,cAAc,GAAG,OAAO,CAAC;QAC/B,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC;QACpC,KAAK,CAAC,cAAc,GAAG,UAAU,CAAC;QAClC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,yBAAyB,CAAC;QACrD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;QACzB,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAErC,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9C,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,CAAC,oBAAoB,GAAG,SAAS,CAAC;QACzC,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,aAAa,EAAE,CAAC;YAClB,KAAK,CAAC,iBAAiB,GAAG,aAAa,CAAC;QAC1C,CAAC;QAED,KAAK,CAAC,UAAU,GAAG;YACjB,WAAW,EAAE,IAAI;YACjB,eAAe,EAAE,KAAK;YACtB,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,oBAAoB;SACjC,CAAC;QAEF,IAAI,CAAC,cAAc,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED;;;OAGG;IACK,cAAc;QACpB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;QACrC,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,iBAAiB,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAC/F,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAE1C,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3D,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/E,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC,IAAI,CAAC;YACpB,CAAC;QACH,CAAC;QAED,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,CAAC;IAED,2EAA2E;IACnE,oBAAoB;QAC1B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,YAAY,GAAG,CAAC,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QACvF,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,iBAAiB,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAC5E,CAAC;QACF,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7E,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC,IAAI,CAAC;YACpB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACK,iBAAiB,CAAC,YAAoB;QAC5C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CACvC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,MAAM,KAAK,iBAAiB,CAAC,MAAM;YACrC,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,IAAI,KAAK,YAAY;YACvB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAC9B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAE1C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YACzE,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC,IAAI,CAAC;YACpB,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;QAC/D,OAAO,UAAU,EAAE,IAAI,IAAI,IAAI,CAAC;IAClC,CAAC;iSAhZU,6BAA6B,yBAA7B,6BAA6B;6DAA7B,6BAA6B;YA9JpC,AAFF,8BAAkC,aAEI;YAClC,uBAAyC;YAGvC,AAFF,gGAAwC,4EAEK;YAU/C,iBAAM;YAIJ,AADF,8BAAyC,gBAI6D;YADlG,0GAAS,+BAA2B,IAAC;YAErC,oBAAoH;YAExH,AADE,iBAAS,EACL;YAIJ,AADF,8BAAkC,gBAIkH;YADhJ,0GAAS,6BAAyB,IAAC;YAEnC,qBAA6H;YAGnI,AADE,AADE,iBAAS,EACL,EACF;YAcJ,AAZF,yGAAqB,sFAYZ;;YA/CL,eAWC;YAXD,wGAWC;YAQC,eAAiG;YAAjG,mHAAiG;YAC9F,cAA4G;YAA5G,qHAA4G;YAS/G,eAA+I;YAA/I,iKAA+I;YAC5I,cAAqH;YAArH,8HAAqH;YAK9H,cAkBC;YAlBD,6CAkBC;;;iFAuGQ,6BAA6B;cAvKzC,SAAS;6BACI,KAAK,YACP,2BAA2B,iBACtB,iBAAiB,CAAC,IAAI,YAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DT;;kBAgHA,KAAK;;kBAeL,KAAK;;kBAWL,KAAK;;kBAGL,KAAK;;kBAQL,KAAK;;kBAiBL,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kFAtEI,6BAA6B;AAmZ1C;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,4EAA4E;IAC5E,KAAK,6BAA6B,CAAC;AACrC,CAAC","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectorRef,\n OnInit,\n ViewEncapsulation,\n inject,\n} from '@angular/core';\nimport { EntityInfo, EntityFieldInfo, EntityFieldTSType } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport {\n TimelineGroup,\n TimeSegmentGrouping,\n TimelineSortOrder,\n AfterEventClickArgs,\n} from '@memberjunction/ng-timeline';\nimport { TimelineOrientation } from '../../types';\nimport { IViewRenderer } from '../view-type.contracts';\n\n/**\n * The persisted configuration shape for the Timeline view type.\n *\n * This is the `config` payload the host hands to the renderer on mount and that the\n * renderer emits back (in full) via {@link TimelineViewRendererComponent.configChanged}\n * whenever the user changes any of the timeline chrome controls. The host treats it as an\n * opaque blob — only this renderer (and an eventual prop-sheet) understands its keys — and\n * persists it per `MJ: View Types` row.\n *\n * All fields are optional: on first mount the renderer falls back to sensible defaults\n * (first available date field, vertical orientation, descending sort, monthly segments).\n */\nexport interface TimelineViewConfig {\n /** The entity date-field used to place records on the timeline (e.g. `__mj_CreatedAt`). */\n dateFieldName?: string;\n /** Vertical (alternating) vs. horizontal (single-row) timeline layout. */\n orientation?: TimelineOrientation;\n /** Newest-first (`desc`) vs. oldest-first (`asc`) event ordering. */\n sortOrder?: TimelineSortOrder;\n /** How events are bucketed into collapsible segments (day/week/month/...). */\n segmentGrouping?: TimeSegmentGrouping;\n}\n\n/**\n * TimelineViewRendererComponent\n * -----------------------------\n * The Timeline **view type** as a self-contained {@link IViewRenderer} plug-in. Where the\n * Timeline view used to be hard-wired into the generic `mj-entity-viewer` host (which owned\n * the date-field detection, the record→{@link TimelineGroup} transformation, and the\n * date-field / orientation / sort chrome), this component now OWNS all of it. The host simply\n * dynamic-mounts this renderer when Timeline is the active view type and feeds it the standard\n * renderer inputs (`entity` / `records` / `selectedRecordId` / `filterText` / `config`).\n *\n * It renders a small chrome header row (date-field selector + orientation toggle + sort toggle)\n * above a flex-filling `<mj-timeline>`, exactly reproducing the host's previous timeline chrome\n * and bindings. Because the host only mounts this plug-in when Timeline is active, the chrome\n * always renders — no extra `EffectiveViewMode === 'timeline'` guard is needed.\n *\n * **What was absorbed from the host** (`EntityViewerComponent`): `detectDateFields()`,\n * `sortDateFieldsByPriority()`, `AvailableDateFields`/`HasDateFields`, `configureTimeline()`,\n * `updateTimelineGroups()` (+ `findTitleField`/`findDescriptionField`/`findSubtitleField`),\n * `ToggleTimelineOrientation()`, `ToggleTimelineSortOrder()`, `SetTimelineDateField()`,\n * `SelectedDateFieldDisplayName`, `OnTimelineEventClick()`, and the `TimelineSelectedEventID`\n * composite-key→raw-id derivation.\n *\n * Inputs use the camelCase names mandated by the {@link IViewRenderer} contract (the host binds\n * them by those exact names) rather than MJ's usual PascalCase for public members.\n */\n@Component({\n standalone: false,\n selector: 'mj-timeline-view-renderer',\n encapsulation: ViewEncapsulation.None,\n template: `\n <!-- Chrome row: date-field selector + orientation toggle + sort toggle.\n Always rendered — this plug-in only mounts when Timeline is the active view. -->\n <div class=\"timeline-view-chrome\">\n <!-- Date Field Selector -->\n <div class=\"timeline-date-selector\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n @if (AvailableDateFields.length === 1) {\n <span class=\"date-field-label\">{{ SelectedDateFieldDisplayName }}</span>\n } @else if (AvailableDateFields.length > 1) {\n <select\n class=\"date-field-select\"\n [value]=\"SelectedTimelineDateField\"\n (change)=\"SetTimelineDateField($any($event.target).value)\">\n @for (field of AvailableDateFields; track field.Name) {\n <option [value]=\"field.Name\">{{ field.DisplayNameOrName }}</option>\n }\n </select>\n }\n </div>\n\n <!-- Orientation Toggle -->\n <div class=\"timeline-orientation-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"ToggleTimelineOrientation()\"\n [title]=\"TimelineOrientationState === 'vertical' ? 'Switch to Horizontal' : 'Switch to Vertical'\">\n <i [class]=\"TimelineOrientationState === 'vertical' ? 'fa-solid fa-ellipsis-vertical' : 'fa-solid fa-ellipsis'\"></i>\n </button>\n </div>\n\n <!-- Sort Order Toggle -->\n <div class=\"timeline-sort-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"ToggleTimelineSortOrder()\"\n [title]=\"TimelineSortOrderState === 'desc' ? 'Showing Newest First (click for Oldest First)' : 'Showing Oldest First (click for Newest First)'\">\n <i [class]=\"TimelineSortOrderState === 'desc' ? 'fa-solid fa-arrow-down-wide-short' : 'fa-solid fa-arrow-up-wide-short'\"></i>\n </button>\n </div>\n </div>\n\n @if (HasDateFields) {\n <mj-timeline\n [groups]=\"TimelineGroups\"\n [orientation]=\"TimelineOrientationState\"\n [layout]=\"TimelineOrientationState === 'vertical' ? 'alternating' : 'single'\"\n [sortOrder]=\"TimelineSortOrderState\"\n [segmentGrouping]=\"TimelineSegmentGrouping\"\n [segmentsCollapsible]=\"true\"\n [segmentsDefaultExpanded]=\"true\"\n [selectedEventId]=\"TimelineSelectedEventID\"\n (afterEventClick)=\"OnTimelineEventClick($event)\">\n </mj-timeline>\n } @else {\n <mj-empty-state\n class=\"timeline-view-empty-fill\"\n Variant=\"warning\"\n Icon=\"fa-solid fa-calendar-xmark\"\n Title=\"This entity has no date fields to plot on a timeline.\" />\n }\n `,\n styles: [\n `\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .timeline-view-chrome {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 12px;\n flex: 0 0 auto;\n }\n\n .timeline-view-renderer mj-timeline,\n :host mj-timeline {\n flex: 1 1 auto;\n min-height: 0;\n }\n\n /* Timeline Date Field Selector */\n .timeline-date-selector {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n }\n\n .timeline-date-selector i {\n color: var(--mj-text-disabled);\n }\n\n .date-field-label {\n color: var(--mj-text-secondary);\n font-weight: 500;\n }\n\n .date-field-select {\n padding: 4px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 13px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n outline: none;\n transition: border-color 0.15s ease;\n }\n\n .date-field-select:hover {\n border-color: var(--mj-border-strong);\n }\n\n .date-field-select:focus {\n border-color: var(--mj-brand-primary);\n }\n\n /* Orientation / Sort toggles */\n .timeline-orientation-toggle,\n .timeline-sort-toggle {\n display: flex;\n background: var(--mj-bg-surface-card);\n border-radius: 6px;\n padding: 2px;\n }\n\n .toggle-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n }\n\n .toggle-btn:hover {\n color: var(--mj-text-secondary);\n }\n\n .toggle-btn.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n }\n\n /* Flex-fill so the empty-state placeholder occupies the timeline area\n (the host centers its content but does not grow to fill the parent). */\n .timeline-view-empty-fill {\n flex: 1 1 auto;\n }\n `,\n ],\n})\nexport class TimelineViewRendererComponent\n extends BaseAngularComponent\n implements IViewRenderer<TimelineViewConfig>, OnInit\n{\n // ========================================\n // IViewRenderer inputs (camelCase per the host contract)\n // ========================================\n\n private _entity: EntityInfo | null = null;\n /** The entity whose records are being rendered. Re-detects date fields + rebuilds groups on change. */\n @Input()\n set entity(value: EntityInfo | null) {\n const changed = !UUIDsEqual(value?.ID, this._entity?.ID);\n this._entity = value;\n if (changed) {\n this.detectDateFields();\n this.cdr.detectChanges();\n }\n }\n get entity(): EntityInfo | null {\n return this._entity;\n }\n\n private _records: Record<string, unknown>[] = [];\n /** The records to render (already loaded/filtered by the host). Rebuilds groups on change. */\n @Input()\n set records(value: Record<string, unknown>[]) {\n this._records = value ?? [];\n this.updateTimelineGroups();\n this.cdr.detectChanges();\n }\n get records(): Record<string, unknown>[] {\n return this._records;\n }\n\n /** Primary-key string of the currently selected record, if any (composite-key encoded). */\n @Input() selectedRecordId: string | null = null;\n\n /** Active filter text — accepted for contract uniformity; the host pre-filters `records`. */\n @Input() filterText: string | null = null;\n\n private _config: TimelineViewConfig = {};\n /**\n * This view's persisted configuration. Seeding the chrome controls from it is deferred to\n * {@link applyConfigToState}, called both here (for late updates) and in {@link ngOnInit}\n * (for the initial mount, where the host sets `config` via `setInput` before init runs).\n */\n @Input()\n set config(value: TimelineViewConfig) {\n this._config = value ?? {};\n if (this._initialized) {\n this.applyConfigToState();\n this.cdr.detectChanges();\n }\n }\n get config(): TimelineViewConfig {\n return this._config;\n }\n\n // ========================================\n // IViewRenderer outputs\n // ========================================\n\n /** Emitted when a timeline event is clicked — payload is the RAW record object. */\n @Output() recordSelected = new EventEmitter<unknown>();\n\n /** Emitted when a record should be opened — payload is the RAW record object. */\n @Output() recordOpened = new EventEmitter<unknown>();\n\n /** Emitted (with the FULL updated config) whenever the user changes a chrome control. */\n @Output() configChanged = new EventEmitter<TimelineViewConfig>();\n\n // ========================================\n // RENDER STATE (absorbed from the host)\n // ========================================\n\n /** Whether the current entity has any date fields available for timeline view. */\n public HasDateFields = false;\n\n /** Available date fields from the entity, sorted by priority. */\n public AvailableDateFields: EntityFieldInfo[] = [];\n\n /** The currently selected date field name for the timeline. */\n public SelectedTimelineDateField: string | null = null;\n\n /** The built timeline groups handed to `<mj-timeline>`. */\n public TimelineGroups: TimelineGroup<Record<string, unknown>>[] = [];\n\n /**\n * Timeline sort order. Named `…State` (not `TimelineSortOrder`) to avoid colliding with the\n * imported {@link TimelineSortOrder} type symbol used in the template / signatures.\n */\n public TimelineSortOrderState: TimelineSortOrder = 'desc';\n\n /** Timeline segment grouping (day/week/month/...). */\n public TimelineSegmentGrouping: TimeSegmentGrouping = 'month';\n\n /**\n * Timeline orientation. Named `…State` to avoid colliding with the imported\n * {@link TimelineOrientation} type symbol.\n */\n public TimelineOrientationState: TimelineOrientation = 'vertical';\n\n private _initialized = false;\n private cdr = inject(ChangeDetectorRef);\n\n // ========================================\n // LIFECYCLE\n // ========================================\n\n ngOnInit(): void {\n // The host sets entity/records/config via setInput BEFORE ngOnInit, so detection may have\n // already run. Apply the seeded config now (controls + defaults), then (re)build groups.\n this._initialized = true;\n this.applyConfigToState();\n this.detectDateFields();\n this.cdr.detectChanges();\n }\n\n // ========================================\n // COMPUTED\n // ========================================\n\n /** Display name of the currently selected timeline date field. */\n get SelectedDateFieldDisplayName(): string {\n if (!this.SelectedTimelineDateField) {\n return '';\n }\n const field = this.AvailableDateFields.find((f) => f.Name === this.SelectedTimelineDateField);\n return field?.DisplayNameOrName || this.SelectedTimelineDateField;\n }\n\n /**\n * The raw ID value derived from {@link selectedRecordId} for timeline selection. The host\n * passes the selection in composite-key format (`ID|abc-123` or `ID=abc-123`), but the\n * timeline stores just the raw ID value — so strip the field-name prefix.\n */\n get TimelineSelectedEventID(): string | null {\n if (!this.selectedRecordId) {\n return null;\n }\n if (this.selectedRecordId.includes('|')) {\n const parts = this.selectedRecordId.split('|');\n return parts.length > 1 ? parts[1] : this.selectedRecordId;\n }\n if (this.selectedRecordId.includes('=')) {\n const parts = this.selectedRecordId.split('=');\n return parts.length > 1 ? parts[1] : this.selectedRecordId;\n }\n return this.selectedRecordId;\n }\n\n // ========================================\n // CHROME ACTIONS (absorbed from the host)\n // ========================================\n\n /** Toggle timeline orientation between vertical and horizontal, then persist via config. */\n ToggleTimelineOrientation(): void {\n this.TimelineOrientationState = this.TimelineOrientationState === 'vertical' ? 'horizontal' : 'vertical';\n this.emitConfigChange();\n this.cdr.detectChanges();\n }\n\n /** Toggle timeline sort order between newest-first (desc) and oldest-first (asc), then persist. */\n ToggleTimelineSortOrder(): void {\n this.TimelineSortOrderState = this.TimelineSortOrderState === 'desc' ? 'asc' : 'desc';\n this.emitConfigChange();\n this.cdr.detectChanges();\n }\n\n /** Change the date field used for the timeline, rebuild groups, then persist via config. */\n SetTimelineDateField(fieldName: string): void {\n if (this.AvailableDateFields.some((f) => f.Name === fieldName)) {\n this.SelectedTimelineDateField = fieldName;\n this.updateTimelineGroups();\n this.emitConfigChange();\n this.cdr.detectChanges();\n }\n }\n\n // ========================================\n // TIMELINE EVENT → RECORD MAPPING\n // ========================================\n\n /**\n * Handle a timeline event click. Maps the {@link AfterEventClickArgs} to the underlying raw\n * record (`event.event.entity`) and emits it on {@link recordSelected}. The host's dynamic\n * handler builds the composite key from the raw record, so we emit the record object as-is.\n */\n OnTimelineEventClick(event: AfterEventClickArgs): void {\n const record = event.event.entity as Record<string, unknown> | undefined;\n if (record) {\n this.recordSelected.emit(record);\n }\n }\n\n // ========================================\n // CONFIG <-> STATE\n // ========================================\n\n /**\n * Seed the chrome control state from {@link config}, applying sensible defaults where the\n * config is silent (vertical orientation, descending sort, monthly segments). The selected\n * date field is resolved against the currently-available date fields in {@link detectDateFields}.\n */\n private applyConfigToState(): void {\n const c = this._config;\n this.TimelineOrientationState = c.orientation ?? 'vertical';\n this.TimelineSortOrderState = c.sortOrder ?? 'desc';\n this.TimelineSegmentGrouping = c.segmentGrouping ?? 'month';\n }\n\n /** Emit the FULL current config object so the host can persist the change. */\n private emitConfigChange(): void {\n this._config = {\n dateFieldName: this.SelectedTimelineDateField ?? undefined,\n orientation: this.TimelineOrientationState,\n sortOrder: this.TimelineSortOrderState,\n segmentGrouping: this.TimelineSegmentGrouping,\n };\n this.configChanged.emit(this._config);\n }\n\n // ========================================\n // DATE-FIELD DETECTION (absorbed from the host)\n // ========================================\n\n /**\n * Detect the entity's date fields and configure the timeline. Resolves the selected date\n * field (preferring the configured one, falling back to the highest-priority available field)\n * and rebuilds the groups. No-ops to an empty state when the entity has no date fields.\n */\n private detectDateFields(): void {\n if (!this._entity) {\n this.HasDateFields = false;\n this.AvailableDateFields = [];\n this.TimelineGroups = [];\n return;\n }\n\n const dateFields = this._entity.Fields.filter((f) => f.TSType === EntityFieldTSType.Date);\n if (dateFields.length === 0) {\n this.HasDateFields = false;\n this.AvailableDateFields = [];\n this.TimelineGroups = [];\n return;\n }\n\n this.AvailableDateFields = this.sortDateFieldsByPriority(dateFields);\n this.HasDateFields = true;\n this.SelectedTimelineDateField = this.getEffectiveTimelineDateField();\n this.updateTimelineGroups();\n }\n\n /**\n * Sort date fields by priority: `DefaultInView` fields first (by Sequence), then the rest\n * (by Sequence).\n */\n private sortDateFieldsByPriority(dateFields: EntityFieldInfo[]): EntityFieldInfo[] {\n const defaultInView = dateFields.filter((f) => f.DefaultInView).sort((a, b) => a.Sequence - b.Sequence);\n const others = dateFields.filter((f) => !f.DefaultInView).sort((a, b) => a.Sequence - b.Sequence);\n return [...defaultInView, ...others];\n }\n\n /**\n * Resolve which date field to use: the configured `dateFieldName` when it's still a valid\n * available field, otherwise the first (highest-priority) available date field.\n */\n private getEffectiveTimelineDateField(): string {\n if (this._config.dateFieldName) {\n const configField = this.AvailableDateFields.find((f) => f.Name === this._config.dateFieldName);\n if (configField) {\n return configField.Name;\n }\n }\n return this.AvailableDateFields[0].Name;\n }\n\n // ========================================\n // GROUP BUILDING (absorbed from the host)\n // ========================================\n\n /**\n * Build the single {@link TimelineGroup} for the current entity + records + selected date\n * field, mirroring the host's previous `updateTimelineGroups()`. No-ops to an empty state\n * when there is no entity or no selected date field.\n */\n private updateTimelineGroups(): void {\n // Emit NO group until there is an entity, a resolved date field, AND records. Emitting an empty\n // group (records not loaded yet) makes the inner <mj-timeline> run its first refresh with zero\n // events and mark itself loaded; the later records-populated update can then be dropped by its\n // concurrent-refresh / already-loaded guards, leaving \"No events to display\". Waiting for records\n // means its first real load happens with data.\n if (!this._entity || !this.SelectedTimelineDateField || this._records.length === 0) {\n this.TimelineGroups = [];\n return;\n }\n\n const titleField = this.findTitleField();\n\n const group = new TimelineGroup<Record<string, unknown>>();\n group.DataSourceType = 'array';\n group.EntityObjects = this._records;\n group.TitleFieldName = titleField;\n group.DateFieldName = this.SelectedTimelineDateField;\n group.IdFieldName = 'ID';\n group.GroupLabel = this._entity.Name;\n\n const descField = this.findDescriptionField();\n if (descField) {\n group.DescriptionFieldName = descField;\n }\n\n const subtitleField = this.findSubtitleField(titleField);\n if (subtitleField) {\n group.SubtitleFieldName = subtitleField;\n }\n\n group.CardConfig = {\n collapsible: true,\n defaultExpanded: false,\n showDate: true,\n dateFormat: 'MMM d, yyyy h:mm a',\n };\n\n this.TimelineGroups = [group];\n }\n\n /**\n * Find the best field to use as the event title: the entity's NameField, then a\n * `DefaultInView` string field matching a common name pattern, then the first string field.\n */\n private findTitleField(): string {\n if (!this._entity) {\n return 'ID';\n }\n if (this._entity.NameField) {\n return this._entity.NameField.Name;\n }\n\n const stringFields = this._entity.Fields.filter(\n (f) => f.TSType === EntityFieldTSType.String && f.DefaultInView && !f.Name.startsWith('__mj_'),\n ).sort((a, b) => a.Sequence - b.Sequence);\n\n const namePatterns = ['name', 'title', 'subject', 'label'];\n for (const pattern of namePatterns) {\n const match = stringFields.find((f) => f.Name.toLowerCase().includes(pattern));\n if (match) {\n return match.Name;\n }\n }\n\n return stringFields.length > 0 ? stringFields[0].Name : 'ID';\n }\n\n /** Find a suitable description field by common naming pattern, or null. */\n private findDescriptionField(): string | null {\n if (!this._entity) {\n return null;\n }\n const descPatterns = ['description', 'notes', 'summary', 'content', 'body', 'details'];\n const textFields = this._entity.Fields.filter(\n (f) => f.TSType === EntityFieldTSType.String && !f.Name.startsWith('__mj_'),\n );\n for (const pattern of descPatterns) {\n const match = textFields.find((f) => f.Name.toLowerCase().includes(pattern));\n if (match) {\n return match.Name;\n }\n }\n return null;\n }\n\n /**\n * Find a suitable subtitle field (different from the title): a `DefaultInView` string field\n * matching a classification pattern (status/type/category/...), else the first other string\n * field, else null.\n */\n private findSubtitleField(excludeField: string): string | null {\n if (!this._entity) {\n return null;\n }\n const patterns = ['status', 'type', 'category', 'state', 'priority'];\n const fields = this._entity.Fields.filter(\n (f) =>\n f.TSType === EntityFieldTSType.String &&\n f.DefaultInView &&\n f.Name !== excludeField &&\n !f.Name.startsWith('__mj_'),\n ).sort((a, b) => a.Sequence - b.Sequence);\n\n for (const pattern of patterns) {\n const match = fields.find((f) => f.Name.toLowerCase().includes(pattern));\n if (match) {\n return match.Name;\n }\n }\n\n const firstOther = fields.find((f) => f.Name !== excludeField);\n return firstOther?.Name || null;\n }\n}\n\n/**\n * Tree-shaking guard. Force-references the component class so bundlers don't drop this module\n * when it's only mounted dynamically via the view-type descriptor's `RendererComponent`.\n */\nexport function LoadTimelineViewRenderer(): void {\n // no-op; presence prevents tree-shaking of the dynamically-mounted renderer\n void TimelineViewRendererComponent;\n}\n"]}
|
|
@@ -50,6 +50,20 @@ export interface IViewTypeDescriptor {
|
|
|
50
50
|
* options.
|
|
51
51
|
*/
|
|
52
52
|
readonly PropSheetComponent?: Type<unknown>;
|
|
53
|
+
/**
|
|
54
|
+
* When `true`, this view type's `config.gridState` is backed by the **canonical**
|
|
55
|
+
* `UserView.GridState` column (the single, framework-wide store for a view's
|
|
56
|
+
* columns / sort / filter / aggregates — also read by `MJUserViewEntity.Columns`,
|
|
57
|
+
* the GraphQL data provider's field list, and export) rather than by an opaque
|
|
58
|
+
* per-view-type blob in `DisplayState.viewTypeConfigs`.
|
|
59
|
+
*
|
|
60
|
+
* The container honors this by (a) seeding the renderer's `config.gridState` from
|
|
61
|
+
* the canonical store and (b) routing the renderer's `configChanged.gridState`
|
|
62
|
+
* back to it on persist. This keeps the grid, the config panel, the server query,
|
|
63
|
+
* and export all reading/writing one source of truth. Defaults to `false`, so
|
|
64
|
+
* non-grid view types (Cards/Timeline/Map) keep their opaque per-type config.
|
|
65
|
+
*/
|
|
66
|
+
readonly UsesCanonicalGridState?: boolean;
|
|
53
67
|
/**
|
|
54
68
|
* Predicate that decides whether this view type is available for a given entity.
|
|
55
69
|
* For example, Timeline requires a date field; Map requires geocoding support.
|
|
@@ -143,6 +157,30 @@ export interface IViewRenderer<TConfig = unknown> {
|
|
|
143
157
|
* NOT a signal that drives the outer app.)
|
|
144
158
|
*/
|
|
145
159
|
dataRequest?: EventEmitter<ViewDataRequest>;
|
|
160
|
+
/**
|
|
161
|
+
* Optional: ask the host to open this view's configuration UI (e.g. the workspace's config
|
|
162
|
+
* panel). Generic — every view type has configurable settings (the descriptor's
|
|
163
|
+
* {@link IViewTypeDescriptor.PropSheetComponent}); a plug-in raises this when the user invokes
|
|
164
|
+
* an in-renderer affordance for it (e.g. the grid's "Manage Columns" toolbar item). The
|
|
165
|
+
* container forwards it to the host, which owns the config UI; no per-view-type branching.
|
|
166
|
+
* (Container ↔ plug-in coordination — NOT a signal that drives the outer app.)
|
|
167
|
+
*/
|
|
168
|
+
configureRequested?: EventEmitter<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Optional IMPERATIVE export entry point. A renderer that owns a self-contained export
|
|
171
|
+
* affordance (e.g. the grid's export dialog) may expose this so an external driver — the
|
|
172
|
+
* host's programmatic API, ultimately the AI agent — can trigger an export of the current
|
|
173
|
+
* record set WITHOUT going through the renderer's own toolbar UI. Renderers that don't
|
|
174
|
+
* support export simply don't implement it (the host treats absence as "not exportable").
|
|
175
|
+
*
|
|
176
|
+
* This is NOT a navigation/UI-coordination signal — it's a direct method call the host makes
|
|
177
|
+
* on the active renderer, mirroring how export is otherwise self-contained in the plug-in.
|
|
178
|
+
*
|
|
179
|
+
* @param format optional output format ('csv' | 'excel' | 'json'); the renderer picks a sensible
|
|
180
|
+
* default (typically 'excel') when omitted.
|
|
181
|
+
* @returns true when the export was initiated, false when it couldn't be (no data / unsupported).
|
|
182
|
+
*/
|
|
183
|
+
exportRecords?(format?: 'csv' | 'excel' | 'json'): Promise<boolean>;
|
|
146
184
|
}
|
|
147
185
|
/**
|
|
148
186
|
* A generic, view-type-agnostic request from a renderer for the host to change how it loads the
|
|
@@ -214,6 +252,12 @@ export declare abstract class BaseViewTypeDescriptor implements IViewTypeDescrip
|
|
|
214
252
|
abstract readonly Icon: string;
|
|
215
253
|
abstract readonly RendererComponent: Type<unknown>;
|
|
216
254
|
readonly PropSheetComponent?: Type<unknown>;
|
|
255
|
+
/**
|
|
256
|
+
* Default: this view type uses its own opaque per-view-type config (stored in
|
|
257
|
+
* `DisplayState.viewTypeConfigs`). Override to `true` in a view type that renders the
|
|
258
|
+
* canonical grid columns (see {@link IViewTypeDescriptor.UsesCanonicalGridState}).
|
|
259
|
+
*/
|
|
260
|
+
readonly UsesCanonicalGridState: boolean;
|
|
217
261
|
/**
|
|
218
262
|
* Default availability: available for every entity. Override in subclasses that have
|
|
219
263
|
* requirements (e.g. Timeline needs a date field, Map needs geocoding).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-type.contracts.d.ts","sourceRoot":"","sources":["../../../src/lib/view-types/view-type.contracts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGrE;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAE1C;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5C;;;;;;;OAOG;IACH,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAE1E;;;;;;;;;OASG;IACH,sBAAsB,CAAC,CAAC,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa,CAAC,OAAO,GAAG,OAAO;IAC9C,mDAAmD;IACnD,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAE1B,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAEnC,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,oEAAoE;IACpE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B,wCAAwC;IACxC,MAAM,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAEpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,0FAA0F;IAC1F,cAAc,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAEtC;;;;;OAKG;IACH,YAAY,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAEpC;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,YAAY,CAAC,2BAA2B,CAAC,CAAC;IAEvE;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;OAKG;IACH,aAAa,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAErC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"view-type.contracts.d.ts","sourceRoot":"","sources":["../../../src/lib/view-types/view-type.contracts.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,12 @@ import { RegisterClass } from '@memberjunction/global';
|
|
|
23
23
|
*/
|
|
24
24
|
export class BaseViewTypeDescriptor {
|
|
25
25
|
PropSheetComponent;
|
|
26
|
+
/**
|
|
27
|
+
* Default: this view type uses its own opaque per-view-type config (stored in
|
|
28
|
+
* `DisplayState.viewTypeConfigs`). Override to `true` in a view type that renders the
|
|
29
|
+
* canonical grid columns (see {@link IViewTypeDescriptor.UsesCanonicalGridState}).
|
|
30
|
+
*/
|
|
31
|
+
UsesCanonicalGridState = false;
|
|
26
32
|
/**
|
|
27
33
|
* Default availability: available for every entity. Override in subclasses that have
|
|
28
34
|
* requirements (e.g. Timeline needs a date field, Map needs geocoding).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-type.contracts.js","sourceRoot":"","sources":["../../../src/lib/view-types/view-type.contracts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAmNvD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAgB,sBAAsB;IAKjC,kBAAkB,CAAiB;IAE5C;;;OAGG;IACH,cAAc,CAAC,OAAmB,EAAE,SAA6B;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,sBAAsB,CAAC,SAA6B;QACxD,mBAAmB;IACrB,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB;IACnC,kFAAkF;IAClF,KAAK,aAAa,CAAC;AACrB,CAAC","sourcesContent":["import { Type, EventEmitter } from '@angular/core';\nimport { EntityInfo, IMetadataProvider } from '@memberjunction/core';\nimport { RegisterClass } from '@memberjunction/global';\n\n/**\n * View-Type Plugin Architecture — Contracts\n * -----------------------------------------\n * This file defines the framework-level contracts for the entity-viewer's pluggable\n * view-type system. A \"view type\" is a way of rendering a set of entity records — the\n * built-in ones being Grid, Cards, Timeline, and Map, with future additions like\n * Cluster and Tag Cloud.\n *\n * The design separates three concerns:\n * 1. {@link IViewTypeDescriptor} — metadata + availability + the component types to mount.\n * Descriptors are discovered at runtime via the {@link https MemberJunction ClassFactory}\n * keyed off the `DriverClass` stored in the `MJ: View Types` entity.\n * 2. {@link IViewRenderer} — the contract a renderer component honors so the host can\n * feed it data and listen for selection/open/config events uniformly.\n * 3. {@link IViewPropSheet} — the contract a configuration prop-sheet component honors.\n *\n * Because this lives in an Angular package, it is acceptable for the descriptor to reference\n * Angular's `Type<T>` (it points at the concrete component classes to instantiate).\n */\n\n/**\n * Framework-agnostic-ish descriptor for a single view type.\n *\n * A descriptor is the bridge between the `MJ: View Types` metadata row (which stores\n * the `DriverClass` name) and the concrete Angular components that actually render the\n * view and edit its configuration. Descriptors are registered with the ClassFactory via\n * `@RegisterClass(BaseViewTypeDescriptor, '<DriverClass>')` so they can be discovered by\n * name without a hard import from the host.\n */\nexport interface IViewTypeDescriptor {\n /**\n * Stable internal key for the view type — matches the `DriverClass` column on the\n * `MJ: View Types` entity and the `@RegisterClass` registration key\n * (e.g. \"GridViewType\", \"CardsViewType\").\n */\n readonly Name: string;\n\n /** User-facing label shown in the view-mode switcher (e.g. \"Grid\", \"Tag Cloud\"). */\n readonly DisplayName: string;\n\n /** Font Awesome icon class shown in the switcher (e.g. \"fa-solid fa-table\"). */\n readonly Icon: string;\n\n /**\n * The Angular component class that renders this view type. The host instantiates /\n * mounts this component and feeds it data per the {@link IViewRenderer} contract.\n */\n readonly RendererComponent: Type<unknown>;\n\n /**\n * Optional Angular component class for this view type's configuration prop-sheet\n * (honors {@link IViewPropSheet}). Undefined when the view type has no configurable\n * options.\n */\n readonly PropSheetComponent?: Type<unknown>;\n\n /**\n * Predicate that decides whether this view type is available for a given entity.\n * For example, Timeline requires a date field; Map requires geocoding support.\n * Grid and Cards are always available.\n *\n * @param entity the entity the viewer is currently displaying\n * @param provider optional metadata provider (for multi-provider scenarios)\n */\n IsAvailableFor(entity: EntityInfo, provider?: IMetadataProvider): boolean;\n\n /**\n * Optional async hook to load any data this descriptor's {@link IsAvailableFor} predicate\n * depends on (e.g. the Cluster view type needs the set of entities that have an active\n * Entity Document with vectors). The host awaits this once — before computing availability —\n * so the synchronous predicate can read from a now-populated cache. Implementations should\n * be cheap/idempotent (typically `await SomeEngine.Instance.Config(false, ...)`). Omit when\n * availability is computable purely from the {@link EntityInfo} (Grid/Cards/Timeline/Map).\n *\n * @param provider optional metadata provider (for multi-provider scenarios)\n */\n EnsureAvailabilityData?(provider?: IMetadataProvider): Promise<void>;\n}\n\n/**\n * Contract honored by a view renderer component. The host binds these inputs and\n * subscribes to these outputs uniformly across all view types.\n *\n * @typeParam TConfig the shape of this view type's configuration object\n */\nexport interface IViewRenderer<TConfig = unknown> {\n /** The entity whose records are being rendered. */\n entity: EntityInfo | null;\n\n /** The records to render (already loaded/filtered by the host). */\n records: Record<string, unknown>[];\n\n /** Primary-key string of the currently selected record, if any. */\n selectedRecordId: string | null;\n\n /** Active filter text (for highlighting / client-side concerns). */\n filterText: string | null;\n\n /** View-type-specific configuration. */\n config: TConfig;\n\n /**\n * Optional: the metadata provider, handed to plug-ins that issue their own data calls\n * (multi-provider safety). Generic — not specific to any one view type.\n */\n provider?: IMetadataProvider | null;\n\n /**\n * Optional generic data-context the host supplies alongside {@link records}. These are\n * universal \"a view of records\" concepts (counts, current page, loading) — NOT specific to any\n * view type — so a renderer that paginates or shows a total can read them, and one that doesn't\n * simply ignores them. The host owns the actual data fetch; these describe its current result.\n */\n totalRecordCount?: number;\n /** One-based current page of {@link records} when the host is paginating. */\n page?: number;\n /** Page size the host is using. */\n pageSize?: number;\n /** Whether the host is currently (re)loading the record set. */\n isLoading?: boolean;\n\n /** Emitted when a record is selected (single click). Payload is the raw record object. */\n recordSelected: EventEmitter<unknown>;\n\n /**\n * Emitted when THIS entity's record should be opened (double-click / open). Payload is the raw\n * record. This is a NAVIGATION request — the only category of signal that legitimately bubbles\n * to the outer app (routing lives there). Everything else a view does (export, add-to-list,\n * delete, …) is self-contained in the plug-in via Generic dialogs and never bubbles up.\n */\n recordOpened: EventEmitter<unknown>;\n\n /**\n * Optional: NAVIGATION request to open a *related* record on a DIFFERENT entity (e.g. a\n * foreign-key drill-through in a grid cell). Bubbles to the outer app for routing. Generic —\n * the container forwards it without acting on it.\n */\n openRelatedRecordRequested?: EventEmitter<ViewRelatedRecordNavigation>;\n\n /**\n * Optional: NAVIGATION request to create a new record of the current entity (e.g. a grid's\n * \"New\" button) — opening the create form is a routing concern owned by the outer app. Bubbles\n * up; the container forwards it without acting on it.\n */\n createRecordRequested?: EventEmitter<void>;\n\n /**\n * Emitted when the renderer mutates its own opaque {@link config} (e.g. timeline date field,\n * grid columns/sort/widths, map render mode). The container persists the blob verbatim against\n * the active `ViewTypeID` and never inspects it. (Container ↔ plug-in coordination inside the\n * Generic layer — NOT a signal that drives the outer app.)\n */\n configChanged: EventEmitter<TConfig>;\n\n /**\n * Optional: ask the container to (re)load the record set differently. The ONLY data-access\n * channel a plug-in has, fully generic — the container honors the request (sort / page /\n * load-all) without knowing which plug-in asked or why. A grid emits sort/page; a map emits\n * `{ loadAll: true }`; a plug-in happy with the records it's given emits nothing. The container\n * owns the actual `RunView`; no per-view-type branching. (Container ↔ plug-in coordination —\n * NOT a signal that drives the outer app.)\n */\n dataRequest?: EventEmitter<ViewDataRequest>;\n}\n\n/**\n * A generic, view-type-agnostic request from a renderer for the host to change how it loads the\n * record set. Every field is optional; the host applies whatever is present. No field names a\n * specific view type — these are universal data-access concepts.\n */\nexport interface ViewDataRequest {\n /** Desired sort, applied to the host's RunView OrderBy. Empty/omitted clears sorting. */\n sort?: Array<{ field: string; direction: 'asc' | 'desc' }>;\n /** One-based page to load (for paginated views). */\n page?: number;\n /** Page size to load. */\n pageSize?: number;\n /** When true, the host loads the full result set (up to its safety cap) instead of paginating. */\n loadAll?: boolean;\n}\n\n/**\n * A NAVIGATION request to open a record on a (possibly different) entity — the generic payload\n * for {@link IViewRenderer.openRelatedRecordRequested}. Routing lives in the outer app, so this\n * is one of the few signals that legitimately bubbles up. The container forwards it untouched.\n */\nexport interface ViewRelatedRecordNavigation {\n /** The entity whose record should be opened. */\n entityName: string;\n /** The record's key — a composite-key string or the raw key value(s). Opaque to the container. */\n recordKey: unknown;\n}\n\n/**\n * Contract honored by a view-type configuration prop-sheet component.\n *\n * @typeParam TConfig the shape of the configuration object being edited\n */\nexport interface IViewPropSheet<TConfig = unknown> {\n /** The entity the configuration applies to. */\n entity: EntityInfo | null;\n\n /** The current configuration being edited. */\n config: TConfig;\n\n /** Emitted when the user changes the configuration. */\n configChange: EventEmitter<TConfig>;\n}\n\n/**\n * Abstract base class for all view-type descriptors.\n *\n * Concrete descriptors extend this and register themselves with the ClassFactory:\n *\n * ```typescript\n * @RegisterClass(BaseViewTypeDescriptor, 'GridViewType')\n * export class GridViewType extends BaseViewTypeDescriptor {\n * readonly Name = 'GridViewType';\n * readonly DisplayName = 'Grid';\n * readonly Icon = 'fa-solid fa-table';\n * readonly RendererComponent = EntityDataGridComponent;\n * IsAvailableFor(): boolean { return true; }\n * }\n * ```\n *\n * The {@link ViewTypeEngine} resolves descriptors by `DriverClass` name using\n * `MJGlobal.Instance.ClassFactory.CreateInstance(BaseViewTypeDescriptor, driverClass)`.\n *\n * NOTE: This class is registered with the ClassFactory itself (via subclasses) and is\n * intentionally NOT decorated — only concrete subclasses carry `@RegisterClass`.\n */\nexport abstract class BaseViewTypeDescriptor implements IViewTypeDescriptor {\n abstract readonly Name: string;\n abstract readonly DisplayName: string;\n abstract readonly Icon: string;\n abstract readonly RendererComponent: Type<unknown>;\n readonly PropSheetComponent?: Type<unknown>;\n\n /**\n * Default availability: available for every entity. Override in subclasses that have\n * requirements (e.g. Timeline needs a date field, Map needs geocoding).\n */\n IsAvailableFor(_entity: EntityInfo, _provider?: IMetadataProvider): boolean {\n return true;\n }\n\n /**\n * Default: nothing to preload. Override in subclasses whose availability predicate needs\n * async data (e.g. the Cluster view type loading which entities have Entity Documents).\n */\n async EnsureAvailabilityData(_provider?: IMetadataProvider): Promise<void> {\n // no-op by default\n }\n}\n\n/**\n * Tree-shaking guard. Force-references {@link RegisterClass} so bundlers don't drop the\n * decorator import in builds that only touch this contracts module. Concrete descriptor\n * modules each carry their own `@RegisterClass` and load guard, but this keeps the base\n * module self-consistent.\n */\nexport function LoadViewTypeContracts(): void {\n // no-op; presence prevents tree-shaking of this module's side-effect-free exports\n void RegisterClass;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"view-type.contracts.js","sourceRoot":"","sources":["../../../src/lib/view-types/view-type.contracts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AA4PvD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAgB,sBAAsB;IAKjC,kBAAkB,CAAiB;IAE5C;;;;OAIG;IACM,sBAAsB,GAAY,KAAK,CAAC;IAEjD;;;OAGG;IACH,cAAc,CAAC,OAAmB,EAAE,SAA6B;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,sBAAsB,CAAC,SAA6B;QACxD,mBAAmB;IACrB,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB;IACnC,kFAAkF;IAClF,KAAK,aAAa,CAAC;AACrB,CAAC","sourcesContent":["import { Type, EventEmitter } from '@angular/core';\nimport { EntityInfo, IMetadataProvider } from '@memberjunction/core';\nimport { RegisterClass } from '@memberjunction/global';\n\n/**\n * View-Type Plugin Architecture — Contracts\n * -----------------------------------------\n * This file defines the framework-level contracts for the entity-viewer's pluggable\n * view-type system. A \"view type\" is a way of rendering a set of entity records — the\n * built-in ones being Grid, Cards, Timeline, and Map, with future additions like\n * Cluster and Tag Cloud.\n *\n * The design separates three concerns:\n * 1. {@link IViewTypeDescriptor} — metadata + availability + the component types to mount.\n * Descriptors are discovered at runtime via the {@link https MemberJunction ClassFactory}\n * keyed off the `DriverClass` stored in the `MJ: View Types` entity.\n * 2. {@link IViewRenderer} — the contract a renderer component honors so the host can\n * feed it data and listen for selection/open/config events uniformly.\n * 3. {@link IViewPropSheet} — the contract a configuration prop-sheet component honors.\n *\n * Because this lives in an Angular package, it is acceptable for the descriptor to reference\n * Angular's `Type<T>` (it points at the concrete component classes to instantiate).\n */\n\n/**\n * Framework-agnostic-ish descriptor for a single view type.\n *\n * A descriptor is the bridge between the `MJ: View Types` metadata row (which stores\n * the `DriverClass` name) and the concrete Angular components that actually render the\n * view and edit its configuration. Descriptors are registered with the ClassFactory via\n * `@RegisterClass(BaseViewTypeDescriptor, '<DriverClass>')` so they can be discovered by\n * name without a hard import from the host.\n */\nexport interface IViewTypeDescriptor {\n /**\n * Stable internal key for the view type — matches the `DriverClass` column on the\n * `MJ: View Types` entity and the `@RegisterClass` registration key\n * (e.g. \"GridViewType\", \"CardsViewType\").\n */\n readonly Name: string;\n\n /** User-facing label shown in the view-mode switcher (e.g. \"Grid\", \"Tag Cloud\"). */\n readonly DisplayName: string;\n\n /** Font Awesome icon class shown in the switcher (e.g. \"fa-solid fa-table\"). */\n readonly Icon: string;\n\n /**\n * The Angular component class that renders this view type. The host instantiates /\n * mounts this component and feeds it data per the {@link IViewRenderer} contract.\n */\n readonly RendererComponent: Type<unknown>;\n\n /**\n * Optional Angular component class for this view type's configuration prop-sheet\n * (honors {@link IViewPropSheet}). Undefined when the view type has no configurable\n * options.\n */\n readonly PropSheetComponent?: Type<unknown>;\n\n /**\n * When `true`, this view type's `config.gridState` is backed by the **canonical**\n * `UserView.GridState` column (the single, framework-wide store for a view's\n * columns / sort / filter / aggregates — also read by `MJUserViewEntity.Columns`,\n * the GraphQL data provider's field list, and export) rather than by an opaque\n * per-view-type blob in `DisplayState.viewTypeConfigs`.\n *\n * The container honors this by (a) seeding the renderer's `config.gridState` from\n * the canonical store and (b) routing the renderer's `configChanged.gridState`\n * back to it on persist. This keeps the grid, the config panel, the server query,\n * and export all reading/writing one source of truth. Defaults to `false`, so\n * non-grid view types (Cards/Timeline/Map) keep their opaque per-type config.\n */\n readonly UsesCanonicalGridState?: boolean;\n\n /**\n * Predicate that decides whether this view type is available for a given entity.\n * For example, Timeline requires a date field; Map requires geocoding support.\n * Grid and Cards are always available.\n *\n * @param entity the entity the viewer is currently displaying\n * @param provider optional metadata provider (for multi-provider scenarios)\n */\n IsAvailableFor(entity: EntityInfo, provider?: IMetadataProvider): boolean;\n\n /**\n * Optional async hook to load any data this descriptor's {@link IsAvailableFor} predicate\n * depends on (e.g. the Cluster view type needs the set of entities that have an active\n * Entity Document with vectors). The host awaits this once — before computing availability —\n * so the synchronous predicate can read from a now-populated cache. Implementations should\n * be cheap/idempotent (typically `await SomeEngine.Instance.Config(false, ...)`). Omit when\n * availability is computable purely from the {@link EntityInfo} (Grid/Cards/Timeline/Map).\n *\n * @param provider optional metadata provider (for multi-provider scenarios)\n */\n EnsureAvailabilityData?(provider?: IMetadataProvider): Promise<void>;\n}\n\n/**\n * Contract honored by a view renderer component. The host binds these inputs and\n * subscribes to these outputs uniformly across all view types.\n *\n * @typeParam TConfig the shape of this view type's configuration object\n */\nexport interface IViewRenderer<TConfig = unknown> {\n /** The entity whose records are being rendered. */\n entity: EntityInfo | null;\n\n /** The records to render (already loaded/filtered by the host). */\n records: Record<string, unknown>[];\n\n /** Primary-key string of the currently selected record, if any. */\n selectedRecordId: string | null;\n\n /** Active filter text (for highlighting / client-side concerns). */\n filterText: string | null;\n\n /** View-type-specific configuration. */\n config: TConfig;\n\n /**\n * Optional: the metadata provider, handed to plug-ins that issue their own data calls\n * (multi-provider safety). Generic — not specific to any one view type.\n */\n provider?: IMetadataProvider | null;\n\n /**\n * Optional generic data-context the host supplies alongside {@link records}. These are\n * universal \"a view of records\" concepts (counts, current page, loading) — NOT specific to any\n * view type — so a renderer that paginates or shows a total can read them, and one that doesn't\n * simply ignores them. The host owns the actual data fetch; these describe its current result.\n */\n totalRecordCount?: number;\n /** One-based current page of {@link records} when the host is paginating. */\n page?: number;\n /** Page size the host is using. */\n pageSize?: number;\n /** Whether the host is currently (re)loading the record set. */\n isLoading?: boolean;\n\n /** Emitted when a record is selected (single click). Payload is the raw record object. */\n recordSelected: EventEmitter<unknown>;\n\n /**\n * Emitted when THIS entity's record should be opened (double-click / open). Payload is the raw\n * record. This is a NAVIGATION request — the only category of signal that legitimately bubbles\n * to the outer app (routing lives there). Everything else a view does (export, add-to-list,\n * delete, …) is self-contained in the plug-in via Generic dialogs and never bubbles up.\n */\n recordOpened: EventEmitter<unknown>;\n\n /**\n * Optional: NAVIGATION request to open a *related* record on a DIFFERENT entity (e.g. a\n * foreign-key drill-through in a grid cell). Bubbles to the outer app for routing. Generic —\n * the container forwards it without acting on it.\n */\n openRelatedRecordRequested?: EventEmitter<ViewRelatedRecordNavigation>;\n\n /**\n * Optional: NAVIGATION request to create a new record of the current entity (e.g. a grid's\n * \"New\" button) — opening the create form is a routing concern owned by the outer app. Bubbles\n * up; the container forwards it without acting on it.\n */\n createRecordRequested?: EventEmitter<void>;\n\n /**\n * Emitted when the renderer mutates its own opaque {@link config} (e.g. timeline date field,\n * grid columns/sort/widths, map render mode). The container persists the blob verbatim against\n * the active `ViewTypeID` and never inspects it. (Container ↔ plug-in coordination inside the\n * Generic layer — NOT a signal that drives the outer app.)\n */\n configChanged: EventEmitter<TConfig>;\n\n /**\n * Optional: ask the container to (re)load the record set differently. The ONLY data-access\n * channel a plug-in has, fully generic — the container honors the request (sort / page /\n * load-all) without knowing which plug-in asked or why. A grid emits sort/page; a map emits\n * `{ loadAll: true }`; a plug-in happy with the records it's given emits nothing. The container\n * owns the actual `RunView`; no per-view-type branching. (Container ↔ plug-in coordination —\n * NOT a signal that drives the outer app.)\n */\n dataRequest?: EventEmitter<ViewDataRequest>;\n\n /**\n * Optional: ask the host to open this view's configuration UI (e.g. the workspace's config\n * panel). Generic — every view type has configurable settings (the descriptor's\n * {@link IViewTypeDescriptor.PropSheetComponent}); a plug-in raises this when the user invokes\n * an in-renderer affordance for it (e.g. the grid's \"Manage Columns\" toolbar item). The\n * container forwards it to the host, which owns the config UI; no per-view-type branching.\n * (Container ↔ plug-in coordination — NOT a signal that drives the outer app.)\n */\n configureRequested?: EventEmitter<void>;\n\n /**\n * Optional IMPERATIVE export entry point. A renderer that owns a self-contained export\n * affordance (e.g. the grid's export dialog) may expose this so an external driver — the\n * host's programmatic API, ultimately the AI agent — can trigger an export of the current\n * record set WITHOUT going through the renderer's own toolbar UI. Renderers that don't\n * support export simply don't implement it (the host treats absence as \"not exportable\").\n *\n * This is NOT a navigation/UI-coordination signal — it's a direct method call the host makes\n * on the active renderer, mirroring how export is otherwise self-contained in the plug-in.\n *\n * @param format optional output format ('csv' | 'excel' | 'json'); the renderer picks a sensible\n * default (typically 'excel') when omitted.\n * @returns true when the export was initiated, false when it couldn't be (no data / unsupported).\n */\n exportRecords?(format?: 'csv' | 'excel' | 'json'): Promise<boolean>;\n}\n\n/**\n * A generic, view-type-agnostic request from a renderer for the host to change how it loads the\n * record set. Every field is optional; the host applies whatever is present. No field names a\n * specific view type — these are universal data-access concepts.\n */\nexport interface ViewDataRequest {\n /** Desired sort, applied to the host's RunView OrderBy. Empty/omitted clears sorting. */\n sort?: Array<{ field: string; direction: 'asc' | 'desc' }>;\n /** One-based page to load (for paginated views). */\n page?: number;\n /** Page size to load. */\n pageSize?: number;\n /** When true, the host loads the full result set (up to its safety cap) instead of paginating. */\n loadAll?: boolean;\n}\n\n/**\n * A NAVIGATION request to open a record on a (possibly different) entity — the generic payload\n * for {@link IViewRenderer.openRelatedRecordRequested}. Routing lives in the outer app, so this\n * is one of the few signals that legitimately bubbles up. The container forwards it untouched.\n */\nexport interface ViewRelatedRecordNavigation {\n /** The entity whose record should be opened. */\n entityName: string;\n /** The record's key — a composite-key string or the raw key value(s). Opaque to the container. */\n recordKey: unknown;\n}\n\n/**\n * Contract honored by a view-type configuration prop-sheet component.\n *\n * @typeParam TConfig the shape of the configuration object being edited\n */\nexport interface IViewPropSheet<TConfig = unknown> {\n /** The entity the configuration applies to. */\n entity: EntityInfo | null;\n\n /** The current configuration being edited. */\n config: TConfig;\n\n /** Emitted when the user changes the configuration. */\n configChange: EventEmitter<TConfig>;\n}\n\n/**\n * Abstract base class for all view-type descriptors.\n *\n * Concrete descriptors extend this and register themselves with the ClassFactory:\n *\n * ```typescript\n * @RegisterClass(BaseViewTypeDescriptor, 'GridViewType')\n * export class GridViewType extends BaseViewTypeDescriptor {\n * readonly Name = 'GridViewType';\n * readonly DisplayName = 'Grid';\n * readonly Icon = 'fa-solid fa-table';\n * readonly RendererComponent = EntityDataGridComponent;\n * IsAvailableFor(): boolean { return true; }\n * }\n * ```\n *\n * The {@link ViewTypeEngine} resolves descriptors by `DriverClass` name using\n * `MJGlobal.Instance.ClassFactory.CreateInstance(BaseViewTypeDescriptor, driverClass)`.\n *\n * NOTE: This class is registered with the ClassFactory itself (via subclasses) and is\n * intentionally NOT decorated — only concrete subclasses carry `@RegisterClass`.\n */\nexport abstract class BaseViewTypeDescriptor implements IViewTypeDescriptor {\n abstract readonly Name: string;\n abstract readonly DisplayName: string;\n abstract readonly Icon: string;\n abstract readonly RendererComponent: Type<unknown>;\n readonly PropSheetComponent?: Type<unknown>;\n\n /**\n * Default: this view type uses its own opaque per-view-type config (stored in\n * `DisplayState.viewTypeConfigs`). Override to `true` in a view type that renders the\n * canonical grid columns (see {@link IViewTypeDescriptor.UsesCanonicalGridState}).\n */\n readonly UsesCanonicalGridState: boolean = false;\n\n /**\n * Default availability: available for every entity. Override in subclasses that have\n * requirements (e.g. Timeline needs a date field, Map needs geocoding).\n */\n IsAvailableFor(_entity: EntityInfo, _provider?: IMetadataProvider): boolean {\n return true;\n }\n\n /**\n * Default: nothing to preload. Override in subclasses whose availability predicate needs\n * async data (e.g. the Cluster view type loading which entities have Entity Documents).\n */\n async EnsureAvailabilityData(_provider?: IMetadataProvider): Promise<void> {\n // no-op by default\n }\n}\n\n/**\n * Tree-shaking guard. Force-references {@link RegisterClass} so bundlers don't drop the\n * decorator import in builds that only touch this contracts module. Concrete descriptor\n * modules each carry their own `@RegisterClass` and load guard, but this keeps the base\n * module self-consistent.\n */\nexport function LoadViewTypeContracts(): void {\n // no-op; presence prevents tree-shaking of this module's side-effect-free exports\n void RegisterClass;\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
|
3
3
|
import { EntityInfo } from '@memberjunction/core';
|
|
4
4
|
import { MJUserViewEntityExtended, ViewGridState } from '@memberjunction/core-entities';
|
|
5
5
|
import { CompositeFilterDescriptor, FilterFieldInfo } from '@memberjunction/ng-filter-builder';
|
|
6
|
-
import { RecordSelectedEvent, RecordOpenedEvent, ViewConfigSummary, QuickSaveEvent, QuickSaveAdvancedEvent, DataLoadedEvent, FilteredCountChangedEvent, EntityViewerConfig } from '../types';
|
|
6
|
+
import { RecordSelectedEvent, RecordOpenedEvent, ViewConfigSummary, QuickSaveEvent, QuickSaveAdvancedEvent, DataLoadedEvent, FilteredCountChangedEvent, EntityViewerConfig, SortState, SortDirection } from '../types';
|
|
7
7
|
import { EntityViewerComponent } from '../entity-viewer/entity-viewer.component';
|
|
8
8
|
import { ViewRelatedRecordNavigation } from '../view-types';
|
|
9
9
|
import { ViewSelectorComponent, ViewSelectedEvent, SaveViewRequestedEvent } from '../view-selector/view-selector.component';
|
|
@@ -337,6 +337,37 @@ export declare class ViewWorkspaceComponent extends BaseAngularComponent impleme
|
|
|
337
337
|
onCreateNewRecordRequested(): void;
|
|
338
338
|
/** Handle the selector's "configure view" request — open the config panel. */
|
|
339
339
|
onConfigureViewRequested(): void;
|
|
340
|
+
/** Live pagination/sort snapshot from the inner viewer, or null when not mounted. */
|
|
341
|
+
GetGridState(): {
|
|
342
|
+
CurrentPage: number;
|
|
343
|
+
PageSize: number;
|
|
344
|
+
TotalRecords: number;
|
|
345
|
+
TotalPages: number;
|
|
346
|
+
Sort: SortState | null;
|
|
347
|
+
} | null;
|
|
348
|
+
/** Navigate to a 1-based page on the inner grid. Returns the page applied, or null. */
|
|
349
|
+
GoToPage(pageNumber: number): number | null;
|
|
350
|
+
/** Advance the inner grid to the next page. Returns the new 1-based page, or null. */
|
|
351
|
+
NextPage(): number | null;
|
|
352
|
+
/** Move the inner grid to the previous page. Returns the new 1-based page, or null. */
|
|
353
|
+
PreviousPage(): number | null;
|
|
354
|
+
/** Set the inner grid's server-side page size (reloads from page 1). Returns the size applied, or null. */
|
|
355
|
+
SetPageSize(pageSize: number): number | null;
|
|
356
|
+
/** Apply a server-side sort to the inner grid. Returns true when applied, false otherwise. */
|
|
357
|
+
SetSort(field: string, direction: SortDirection): boolean;
|
|
358
|
+
/**
|
|
359
|
+
* Programmatically select a record in the inner grid — highlights the row and emits
|
|
360
|
+
* {@link RecordSelected} for the host (the no-UI equivalent of a user row-click). Returns
|
|
361
|
+
* false when the viewer isn't mounted or has no entity context. The record must be one of
|
|
362
|
+
* the loaded rows; the host resolves it (e.g. from {@link loadedRecords}).
|
|
363
|
+
*/
|
|
364
|
+
SelectRecord(record: Record<string, unknown>): boolean;
|
|
365
|
+
/**
|
|
366
|
+
* Export the current view's records via the inner viewer's active renderer. Returns false
|
|
367
|
+
* when the viewer isn't mounted or the active view type doesn't support export. The grid
|
|
368
|
+
* renderer downloads the file itself.
|
|
369
|
+
*/
|
|
370
|
+
ExportRecords(format?: 'csv' | 'excel' | 'json'): Promise<boolean>;
|
|
340
371
|
/** Handle the selector's "save view" request — open the config panel in the requested mode. */
|
|
341
372
|
onSaveViewRequested(event: SaveViewRequestedEvent): void;
|
|
342
373
|
/** Close the config panel and clear any pending new-view carry-over state. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-workspace.component.d.ts","sourceRoot":"","sources":["../../../src/lib/view-workspace/view-workspace.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,EACZ,MAAM,EACN,iBAAiB,EAElB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,UAAU,EAAY,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EACL,wBAAwB,EAExB,aAAa,EAKd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAE/F,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,yBAAyB,EACzB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"view-workspace.component.d.ts","sourceRoot":"","sources":["../../../src/lib/view-workspace/view-workspace.component.ts"],"names":[],"mappings":"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"}
|