@memberjunction/ng-artifacts 5.43.0 → 5.45.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/README.md +6 -0
- package/dist/lib/artifacts.module.d.ts +28 -25
- package/dist/lib/artifacts.module.d.ts.map +1 -1
- package/dist/lib/artifacts.module.js +22 -2
- package/dist/lib/artifacts.module.js.map +1 -1
- package/dist/lib/components/artifact-version-history.component.d.ts +1 -0
- package/dist/lib/components/artifact-version-history.component.d.ts.map +1 -1
- package/dist/lib/components/artifact-version-history.component.js +30 -31
- package/dist/lib/components/artifact-version-history.component.js.map +1 -1
- package/dist/lib/components/artifact-viewer-panel.component.d.ts +3 -0
- package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
- package/dist/lib/components/artifact-viewer-panel.component.js +198 -112
- package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
- package/dist/lib/components/plugins/audio-artifact-viewer.component.d.ts +11 -0
- package/dist/lib/components/plugins/audio-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/audio-artifact-viewer.component.js +37 -12
- package/dist/lib/components/plugins/audio-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js +40 -51
- package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js.map +1 -1
- package/dist/lib/components/plugins/data-artifact-viewer.component.js +27 -47
- package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js +89 -95
- package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/ml-experiment-results-viewer.component.d.ts +227 -0
- package/dist/lib/components/plugins/ml-experiment-results-viewer.component.d.ts.map +1 -0
- package/dist/lib/components/plugins/ml-experiment-results-viewer.component.js +630 -0
- package/dist/lib/components/plugins/ml-experiment-results-viewer.component.js.map +1 -0
- package/dist/lib/components/plugins/video-artifact-viewer.component.d.ts +11 -0
- package/dist/lib/components/plugins/video-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/video-artifact-viewer.component.js +37 -12
- package/dist/lib/components/plugins/video-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/previews/audio-artifact-preview.component.d.ts +18 -4
- package/dist/lib/components/previews/audio-artifact-preview.component.d.ts.map +1 -1
- package/dist/lib/components/previews/audio-artifact-preview.component.js +54 -21
- package/dist/lib/components/previews/audio-artifact-preview.component.js.map +1 -1
- package/dist/lib/components/previews/video-artifact-preview.component.d.ts +19 -5
- package/dist/lib/components/previews/video-artifact-preview.component.d.ts.map +1 -1
- package/dist/lib/components/previews/video-artifact-preview.component.js +54 -22
- package/dist/lib/components/previews/video-artifact-preview.component.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +21 -18
- package/dist/__tests__/exports.test.d.ts +0 -2
- package/dist/__tests__/exports.test.d.ts.map +0 -1
- package/dist/__tests__/exports.test.js +0 -17
- package/dist/__tests__/exports.test.js.map +0 -1
- package/dist/__tests__/image-artifact-viewer.test.d.ts +0 -2
- package/dist/__tests__/image-artifact-viewer.test.d.ts.map +0 -1
- package/dist/__tests__/image-artifact-viewer.test.js +0 -62
- package/dist/__tests__/image-artifact-viewer.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/lib/__tests__/artifact-snapshots.test.d.ts +0 -2
- package/dist/lib/__tests__/artifact-snapshots.test.d.ts.map +0 -1
- package/dist/lib/__tests__/artifact-snapshots.test.js +0 -155
- package/dist/lib/__tests__/artifact-snapshots.test.js.map +0 -1
- package/dist/lib/__tests__/interactive-form-apply.service.test.d.ts +0 -2
- package/dist/lib/__tests__/interactive-form-apply.service.test.d.ts.map +0 -1
- package/dist/lib/__tests__/interactive-form-apply.service.test.js +0 -211
- package/dist/lib/__tests__/interactive-form-apply.service.test.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ChangeDetectorRef, Component, inject } from '@angular/core';
|
|
2
2
|
import { BaseArtifactPreviewComponent } from './base-artifact-preview.component';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "@memberjunction/ng-media-player";
|
|
4
5
|
function VideoArtifactPreviewComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
5
6
|
i0.ɵɵelementStart(0, "div", 0);
|
|
6
7
|
i0.ɵɵelement(1, "i", 2);
|
|
@@ -14,30 +15,53 @@ function VideoArtifactPreviewComponent_Conditional_0_Template(rf, ctx) { if (rf
|
|
|
14
15
|
} }
|
|
15
16
|
function VideoArtifactPreviewComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
16
17
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
17
|
-
i0.ɵɵelementStart(0, "
|
|
18
|
-
i0.ɵɵlistener("click", function
|
|
18
|
+
i0.ɵɵelementStart(0, "mj-media-player", 3);
|
|
19
|
+
i0.ɵɵlistener("click", function VideoArtifactPreviewComponent_Conditional_1_Template_mj_media_player_click_0_listener($event) { i0.ɵɵrestoreView(_r2); return i0.ɵɵresetView($event.stopPropagation()); })("Ended", function VideoArtifactPreviewComponent_Conditional_1_Template_mj_media_player_Ended_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onMediaEnded()); });
|
|
19
20
|
i0.ɵɵelementEnd();
|
|
20
21
|
} if (rf & 2) {
|
|
21
22
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
22
|
-
i0.ɵɵproperty("
|
|
23
|
+
i0.ɵɵproperty("Tracks", ctx_r0.MediaTracks)("ShowTranscript", false)("ShowTranscriptToggle", false)("ShowWaveform", false)("ShowSpeedControl", false)("ShowSkipControls", false)("ShowVolume", false);
|
|
23
24
|
} }
|
|
24
25
|
/**
|
|
25
|
-
* Inline preview for video artifacts.
|
|
26
|
-
*
|
|
27
|
-
* propagating so scrubbing / play-pause does
|
|
28
|
-
* regions still open it).
|
|
26
|
+
* Inline preview for video artifacts. Embeds the generic {@link MJMediaPlayerComponent}
|
|
27
|
+
* (`mj-media-player`) in a compact, thumbnail-sized configuration inside the conversation message
|
|
28
|
+
* card. Click events on the player are stopped from propagating so scrubbing / play-pause does
|
|
29
|
+
* NOT open the full-size viewer (the card's other regions still open it).
|
|
30
|
+
*
|
|
31
|
+
* Compact gating: play/pause + scrubber + time (and fullscreen, which is handy for a tiny video
|
|
32
|
+
* surface) are shown. Transcript, waveform, speed, skip and volume chrome are turned OFF so the
|
|
33
|
+
* player reads cleanly at preview size and doesn't crowd the card.
|
|
29
34
|
*/
|
|
30
35
|
export class VideoArtifactPreviewComponent extends BaseArtifactPreviewComponent {
|
|
31
36
|
cdr = inject(ChangeDetectorRef);
|
|
32
|
-
/** Resolved URL
|
|
37
|
+
/** Resolved URL — data URI (inline) or pre-auth URL (file). Funneled through {@link setVideoUrl}. */
|
|
33
38
|
videoUrl = '';
|
|
34
39
|
/** Non-empty hides the player and shows a compact error line. */
|
|
35
40
|
errorMessage = '';
|
|
41
|
+
/**
|
|
42
|
+
* Single-track input for the generic {@link MJMediaPlayerComponent}. Rebuilt in lockstep with
|
|
43
|
+
* {@link videoUrl} via {@link setVideoUrl}; `[]` until a URL exists so the player shows its empty state.
|
|
44
|
+
*/
|
|
45
|
+
MediaTracks = [];
|
|
46
|
+
/** Set the resolved URL and recompute the single-element {@link MediaTracks} array in lockstep. */
|
|
47
|
+
setVideoUrl(url) {
|
|
48
|
+
this.videoUrl = url;
|
|
49
|
+
this.MediaTracks = url
|
|
50
|
+
? [
|
|
51
|
+
{
|
|
52
|
+
Id: this.artifactVersion?.ID ?? 'video',
|
|
53
|
+
Kind: 'video',
|
|
54
|
+
Url: url,
|
|
55
|
+
MimeType: this.artifactVersion?.MimeType ?? undefined,
|
|
56
|
+
},
|
|
57
|
+
]
|
|
58
|
+
: [];
|
|
59
|
+
}
|
|
36
60
|
async ngOnInit() {
|
|
37
61
|
try {
|
|
38
62
|
const url = await this.resolveContentUrl();
|
|
39
63
|
if (url) {
|
|
40
|
-
this.
|
|
64
|
+
this.setVideoUrl(url);
|
|
41
65
|
}
|
|
42
66
|
else {
|
|
43
67
|
this.errorMessage = 'No video content.';
|
|
@@ -50,15 +74,19 @@ export class VideoArtifactPreviewComponent extends BaseArtifactPreviewComponent
|
|
|
50
74
|
}
|
|
51
75
|
onMediaError() {
|
|
52
76
|
this.errorMessage = 'Video could not be played.';
|
|
53
|
-
this.
|
|
77
|
+
this.setVideoUrl('');
|
|
54
78
|
this.cdr.markForCheck();
|
|
55
79
|
}
|
|
80
|
+
/** Fired when the generic player reaches the end of the track. No-op affordance hook. */
|
|
81
|
+
onMediaEnded() {
|
|
82
|
+
// Playback finished — nothing to persist for an inline preview.
|
|
83
|
+
}
|
|
56
84
|
static ɵfac = /*@__PURE__*/ (() => { let ɵVideoArtifactPreviewComponent_BaseFactory; return function VideoArtifactPreviewComponent_Factory(__ngFactoryType__) { return (ɵVideoArtifactPreviewComponent_BaseFactory || (ɵVideoArtifactPreviewComponent_BaseFactory = i0.ɵɵgetInheritedFactory(VideoArtifactPreviewComponent)))(__ngFactoryType__ || VideoArtifactPreviewComponent); }; })();
|
|
57
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: VideoArtifactPreviewComponent, selectors: [["mj-video-artifact-preview"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "video-preview", "video-preview--error"], ["
|
|
58
|
-
i0.ɵɵconditionalCreate(0, VideoArtifactPreviewComponent_Conditional_0_Template, 4, 1, "div", 0)(1, VideoArtifactPreviewComponent_Conditional_1_Template, 1,
|
|
85
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: VideoArtifactPreviewComponent, selectors: [["mj-video-artifact-preview"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "video-preview", "video-preview--error"], [1, "video-preview__player", 3, "Tracks", "ShowTranscript", "ShowTranscriptToggle", "ShowWaveform", "ShowSpeedControl", "ShowSkipControls", "ShowVolume"], [1, "fa-solid", "fa-film"], [1, "video-preview__player", 3, "click", "Ended", "Tracks", "ShowTranscript", "ShowTranscriptToggle", "ShowWaveform", "ShowSpeedControl", "ShowSkipControls", "ShowVolume"]], template: function VideoArtifactPreviewComponent_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
i0.ɵɵconditionalCreate(0, VideoArtifactPreviewComponent_Conditional_0_Template, 4, 1, "div", 0)(1, VideoArtifactPreviewComponent_Conditional_1_Template, 1, 7, "mj-media-player", 1);
|
|
59
87
|
} if (rf & 2) {
|
|
60
88
|
i0.ɵɵconditional(ctx.errorMessage ? 0 : ctx.videoUrl ? 1 : -1);
|
|
61
|
-
} }, styles: ["[_nghost-%COMP%] {\n display: block;\n }\n\n \n\n\n
|
|
89
|
+
} }, dependencies: [i1.MJMediaPlayerComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n }\n\n \n\n\n .video-preview__player[_ngcontent-%COMP%] {\n display: block;\n width: 100%;\n max-width: 100%;\n max-height: 140px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n }\n\n .video-preview--error[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n }"] });
|
|
62
90
|
}
|
|
63
91
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(VideoArtifactPreviewComponent, [{
|
|
64
92
|
type: Component,
|
|
@@ -69,16 +97,20 @@ export class VideoArtifactPreviewComponent extends BaseArtifactPreviewComponent
|
|
|
69
97
|
<span>{{ errorMessage }}</span>
|
|
70
98
|
</div>
|
|
71
99
|
} @else if (videoUrl) {
|
|
72
|
-
<
|
|
73
|
-
class="video-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
[
|
|
100
|
+
<mj-media-player
|
|
101
|
+
class="video-preview__player"
|
|
102
|
+
[Tracks]="MediaTracks"
|
|
103
|
+
[ShowTranscript]="false"
|
|
104
|
+
[ShowTranscriptToggle]="false"
|
|
105
|
+
[ShowWaveform]="false"
|
|
106
|
+
[ShowSpeedControl]="false"
|
|
107
|
+
[ShowSkipControls]="false"
|
|
108
|
+
[ShowVolume]="false"
|
|
77
109
|
(click)="$event.stopPropagation()"
|
|
78
|
-
(
|
|
79
|
-
></
|
|
110
|
+
(Ended)="onMediaEnded()"
|
|
111
|
+
></mj-media-player>
|
|
80
112
|
}
|
|
81
|
-
`, styles: ["\n :host {\n display: block;\n }\n\n /* Compact thumbnail
|
|
113
|
+
`, styles: ["\n :host {\n display: block;\n }\n\n /* Compact thumbnail \u2014 cap the height so the video surface stays consistent with the\n image preview (140px) and neither dominates the conversation card. */\n .video-preview__player {\n display: block;\n width: 100%;\n max-width: 100%;\n max-height: 140px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n }\n\n .video-preview--error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n }\n "] }]
|
|
82
114
|
}], null, null); })();
|
|
83
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(VideoArtifactPreviewComponent, { className: "VideoArtifactPreviewComponent", filePath: "src/lib/components/previews/video-artifact-preview.component.ts", lineNumber:
|
|
115
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(VideoArtifactPreviewComponent, { className: "VideoArtifactPreviewComponent", filePath: "src/lib/components/previews/video-artifact-preview.component.ts", lineNumber: 68 }); })();
|
|
84
116
|
//# sourceMappingURL=video-artifact-preview.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-artifact-preview.component.js","sourceRoot":"","sources":["../../../../src/lib/components/previews/video-artifact-preview.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"video-artifact-preview.component.js","sourceRoot":"","sources":["../../../../src/lib/components/previews/video-artifact-preview.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAE7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;;;;IAiBrE,8BAAgD;IAC5C,uBAAgC;IAChC,4BAAM;IAAA,YAAkB;IAC5B,AAD4B,iBAAO,EAC7B;;;IADI,eAAkB;IAAlB,yCAAkB;;;;IAG5B,0CAWC;IADG,AADA,6KAAS,wBAAwB,KAAC,6LACzB,qBAAc,KAAC;IAC3B,iBAAkB;;;IAHf,AADA,AADA,AADA,AADA,AADA,AADA,2CAAsB,yBACE,+BACM,uBACR,2BACI,2BACA,qBACN;;AA5BpC;;;;;;;;;GASG;AAsDH,MAAM,OAAO,6BAA8B,SAAQ,4BAA4B;IAC1D,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAEjD,qGAAqG;IAC9F,QAAQ,GAAG,EAAE,CAAC;IAErB,iEAAiE;IAC1D,YAAY,GAAG,EAAE,CAAC;IAEzB;;;OAGG;IACI,WAAW,GAAiB,EAAE,CAAC;IAEtC,mGAAmG;IAC3F,WAAW,CAAC,GAAW;QAC3B,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,GAAG;YAClB,CAAC,CAAC;gBACI;oBACI,EAAE,EAAE,IAAI,CAAC,eAAe,EAAE,EAAE,IAAI,OAAO;oBACvC,IAAI,EAAE,OAAO;oBACb,GAAG,EAAE,GAAG;oBACR,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,IAAI,SAAS;iBACxD;aACJ;YACH,CAAC,CAAC,EAAE,CAAC;IACb,CAAC;IAED,KAAK,CAAC,QAAQ;QACV,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3C,IAAI,GAAG,EAAE,CAAC;gBACN,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,YAAY,GAAG,mBAAmB,CAAC;YAC5C,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,IAAI,CAAC,YAAY,GAAG,uBAAuB,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEM,YAAY;QACf,IAAI,CAAC,YAAY,GAAG,4BAA4B,CAAC;QACjD,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACrB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAED,yFAAyF;IAClF,YAAY;QACf,gEAAgE;IACpE,CAAC;iSArDQ,6BAA6B,yBAA7B,6BAA6B;6DAA7B,6BAA6B;YA5ChC,AALF,+FAAoB,qFAKG;;YALvB,8DAkBC;;;iFA+BI,6BAA6B;cArDzC,SAAS;6BACM,KAAK,YACP,2BAA2B,YAC3B;;;;;;;;;;;;;;;;;;;;KAoBT;;kFA8BQ,6BAA6B","sourcesContent":["import { ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';\nimport { MediaTrack } from '@memberjunction/ng-media-player';\nimport { BaseArtifactPreviewComponent } from './base-artifact-preview.component';\n\n/**\n * Inline preview for video artifacts. Embeds the generic {@link MJMediaPlayerComponent}\n * (`mj-media-player`) in a compact, thumbnail-sized configuration inside the conversation message\n * card. Click events on the player are stopped from propagating so scrubbing / play-pause does\n * NOT open the full-size viewer (the card's other regions still open it).\n *\n * Compact gating: play/pause + scrubber + time (and fullscreen, which is handy for a tiny video\n * surface) are shown. Transcript, waveform, speed, skip and volume chrome are turned OFF so the\n * player reads cleanly at preview size and doesn't crowd the card.\n */\n@Component({\n standalone: false,\n selector: 'mj-video-artifact-preview',\n template: `\n @if (errorMessage) {\n <div class=\"video-preview video-preview--error\">\n <i class=\"fa-solid fa-film\"></i>\n <span>{{ errorMessage }}</span>\n </div>\n } @else if (videoUrl) {\n <mj-media-player\n class=\"video-preview__player\"\n [Tracks]=\"MediaTracks\"\n [ShowTranscript]=\"false\"\n [ShowTranscriptToggle]=\"false\"\n [ShowWaveform]=\"false\"\n [ShowSpeedControl]=\"false\"\n [ShowSkipControls]=\"false\"\n [ShowVolume]=\"false\"\n (click)=\"$event.stopPropagation()\"\n (Ended)=\"onMediaEnded()\"\n ></mj-media-player>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n /* Compact thumbnail — cap the height so the video surface stays consistent with the\n image preview (140px) and neither dominates the conversation card. */\n .video-preview__player {\n display: block;\n width: 100%;\n max-width: 100%;\n max-height: 140px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n }\n\n .video-preview--error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n }\n `,\n ],\n})\nexport class VideoArtifactPreviewComponent extends BaseArtifactPreviewComponent implements OnInit {\n private readonly cdr = inject(ChangeDetectorRef);\n\n /** Resolved URL — data URI (inline) or pre-auth URL (file). Funneled through {@link setVideoUrl}. */\n public videoUrl = '';\n\n /** Non-empty hides the player and shows a compact error line. */\n public errorMessage = '';\n\n /**\n * Single-track input for the generic {@link MJMediaPlayerComponent}. Rebuilt in lockstep with\n * {@link videoUrl} via {@link setVideoUrl}; `[]` until a URL exists so the player shows its empty state.\n */\n public MediaTracks: MediaTrack[] = [];\n\n /** Set the resolved URL and recompute the single-element {@link MediaTracks} array in lockstep. */\n private setVideoUrl(url: string): void {\n this.videoUrl = url;\n this.MediaTracks = url\n ? [\n {\n Id: this.artifactVersion?.ID ?? 'video',\n Kind: 'video',\n Url: url,\n MimeType: this.artifactVersion?.MimeType ?? undefined,\n },\n ]\n : [];\n }\n\n async ngOnInit(): Promise<void> {\n try {\n const url = await this.resolveContentUrl();\n if (url) {\n this.setVideoUrl(url);\n } else {\n this.errorMessage = 'No video content.';\n }\n } catch {\n this.errorMessage = 'Could not load video.';\n }\n this.cdr.markForCheck();\n }\n\n public onMediaError(): void {\n this.errorMessage = 'Video could not be played.';\n this.setVideoUrl('');\n this.cdr.markForCheck();\n }\n\n /** Fired when the generic player reaches the end of the track. No-op affordance hook. */\n public onMediaEnded(): void {\n // Playback finished — nothing to persist for an inline preview.\n }\n}\n"]}
|
package/dist/public-api.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export * from './lib/components/plugins/html-artifact-viewer.component';
|
|
|
22
22
|
export * from './lib/components/plugins/svg-artifact-viewer.component';
|
|
23
23
|
export * from './lib/components/plugins/component-artifact-viewer.component';
|
|
24
24
|
export * from './lib/components/plugins/data-artifact-viewer.component';
|
|
25
|
+
export * from './lib/components/plugins/ml-experiment-results-viewer.component';
|
|
25
26
|
export * from './lib/components/plugins/component-feedback-panel/component-feedback-panel.component';
|
|
26
27
|
export * from './lib/components/file-artifact-toolbar.component';
|
|
27
28
|
export * from './lib/components/plugins/pdf-artifact-viewer.component';
|
package/dist/public-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAKA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,kDAAkD,CAAC;AAGjE,cAAc,mDAAmD,CAAC;AAGlE,cAAc,iDAAiD,CAAC;AAGhE,cAAc,2DAA2D,CAAC;AAC1E,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4DAA4D,CAAC;AAG3E,cAAc,wBAAwB,CAAC;AAGvC,cAAc,wDAAwD,CAAC;AAGvE,cAAc,kDAAkD,CAAC;AACjE,cAAc,qDAAqD,CAAC;AACpE,cAAc,kDAAkD,CAAC;AAGjE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,yDAAyD,CAAC;AACxE,cAAc,wDAAwD,CAAC;AACvE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,yDAAyD,CAAC;AACxE,cAAc,sFAAsF,CAAC;AAGrG,cAAc,kDAAkD,CAAC;AACjE,cAAc,wDAAwD,CAAC;AACvE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC"}
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAKA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,kDAAkD,CAAC;AAGjE,cAAc,mDAAmD,CAAC;AAGlE,cAAc,iDAAiD,CAAC;AAGhE,cAAc,2DAA2D,CAAC;AAC1E,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4DAA4D,CAAC;AAG3E,cAAc,wBAAwB,CAAC;AAGvC,cAAc,wDAAwD,CAAC;AAGvE,cAAc,kDAAkD,CAAC;AACjE,cAAc,qDAAqD,CAAC;AACpE,cAAc,kDAAkD,CAAC;AAGjE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,yDAAyD,CAAC;AACxE,cAAc,wDAAwD,CAAC;AACvE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,yDAAyD,CAAC;AACxE,cAAc,iEAAiE,CAAC;AAChF,cAAc,sFAAsF,CAAC;AAGrG,cAAc,kDAAkD,CAAC;AACjE,cAAc,wDAAwD,CAAC;AACvE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC"}
|
package/dist/public-api.js
CHANGED
|
@@ -34,6 +34,7 @@ export * from './lib/components/plugins/html-artifact-viewer.component';
|
|
|
34
34
|
export * from './lib/components/plugins/svg-artifact-viewer.component';
|
|
35
35
|
export * from './lib/components/plugins/component-artifact-viewer.component';
|
|
36
36
|
export * from './lib/components/plugins/data-artifact-viewer.component';
|
|
37
|
+
export * from './lib/components/plugins/ml-experiment-results-viewer.component';
|
|
37
38
|
export * from './lib/components/plugins/component-feedback-panel/component-feedback-panel.component';
|
|
38
39
|
// File viewer toolbar and plugins
|
|
39
40
|
export * from './lib/components/file-artifact-toolbar.component';
|
package/dist/public-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,SAAS;AACT,cAAc,wBAAwB,CAAC;AAEvC,WAAW;AACX,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,kDAAkD,CAAC;AAEjE,aAAa;AACb,cAAc,mDAAmD,CAAC;AAElE,iBAAiB;AACjB,cAAc,iDAAiD,CAAC;AAEhE,mCAAmC;AACnC,cAAc,2DAA2D,CAAC;AAC1E,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4DAA4D,CAAC;AAE3E,qFAAqF;AACrF,cAAc,wBAAwB,CAAC;AAEvC,8EAA8E;AAC9E,cAAc,wDAAwD,CAAC;AAEvE,gCAAgC;AAChC,cAAc,kDAAkD,CAAC;AACjE,cAAc,qDAAqD,CAAC;AACpE,cAAc,kDAAkD,CAAC;AAEjE,oBAAoB;AACpB,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,yDAAyD,CAAC;AACxE,cAAc,wDAAwD,CAAC;AACvE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,yDAAyD,CAAC;AACxE,cAAc,sFAAsF,CAAC;AAErG,kCAAkC;AAClC,cAAc,kDAAkD,CAAC;AACjE,cAAc,wDAAwD,CAAC;AACvE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC","sourcesContent":["/*\n * Public API Surface of @memberjunction/ng-artifacts\n */\n\n// Module\nexport * from './lib/artifacts.module';\n\n// Services\nexport * from './lib/services/artifact-icon.service';\nexport * from './lib/services/artifact-file.service';\nexport * from './lib/services/analyze-artifact.service';\nexport * from './lib/services/interactive-form-apply.service';\nexport * from './lib/services/artifact-preview-resolver.service';\n\n// Interfaces\nexport * from './lib/interfaces/artifact-viewer-plugin.interface';\n\n// Base component\nexport * from './lib/components/base-artifact-viewer.component';\n\n// Inline preview base + components\nexport * from './lib/components/previews/base-artifact-preview.component';\nexport * from './lib/components/previews/image-artifact-preview.component';\nexport * from './lib/components/previews/video-artifact-preview.component';\nexport * from './lib/components/previews/audio-artifact-preview.component';\n\n// Snapshot helpers (pure functions for creating DataSnapshots from artifact content)\nexport * from './lib/snapshot-helpers';\n\n// Artifact type plugin viewer (loads appropriate plugin based on DriverClass)\nexport * from './lib/components/artifact-type-plugin-viewer.component';\n\n// Artifact viewer UI components\nexport * from './lib/components/artifact-viewer-panel.component';\nexport * from './lib/components/artifact-version-history.component';\nexport * from './lib/components/artifact-message-card.component';\n\n// Plugin components\nexport * from './lib/components/plugins/json-artifact-viewer.component';\nexport * from './lib/components/plugins/code-artifact-viewer.component';\nexport * from './lib/components/plugins/markdown-artifact-viewer.component';\nexport * from './lib/components/plugins/html-artifact-viewer.component';\nexport * from './lib/components/plugins/svg-artifact-viewer.component';\nexport * from './lib/components/plugins/component-artifact-viewer.component';\nexport * from './lib/components/plugins/data-artifact-viewer.component';\nexport * from './lib/components/plugins/component-feedback-panel/component-feedback-panel.component';\n\n// File viewer toolbar and plugins\nexport * from './lib/components/file-artifact-toolbar.component';\nexport * from './lib/components/plugins/pdf-artifact-viewer.component';\nexport * from './lib/components/plugins/xlsx-artifact-viewer.component';\nexport * from './lib/components/plugins/docx-artifact-viewer.component';\nexport * from './lib/components/plugins/image-artifact-viewer.component';\nexport * from './lib/components/plugins/video-artifact-viewer.component';\nexport * from './lib/components/plugins/audio-artifact-viewer.component';\n"]}
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,SAAS;AACT,cAAc,wBAAwB,CAAC;AAEvC,WAAW;AACX,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,kDAAkD,CAAC;AAEjE,aAAa;AACb,cAAc,mDAAmD,CAAC;AAElE,iBAAiB;AACjB,cAAc,iDAAiD,CAAC;AAEhE,mCAAmC;AACnC,cAAc,2DAA2D,CAAC;AAC1E,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4DAA4D,CAAC;AAE3E,qFAAqF;AACrF,cAAc,wBAAwB,CAAC;AAEvC,8EAA8E;AAC9E,cAAc,wDAAwD,CAAC;AAEvE,gCAAgC;AAChC,cAAc,kDAAkD,CAAC;AACjE,cAAc,qDAAqD,CAAC;AACpE,cAAc,kDAAkD,CAAC;AAEjE,oBAAoB;AACpB,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,yDAAyD,CAAC;AACxE,cAAc,wDAAwD,CAAC;AACvE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,yDAAyD,CAAC;AACxE,cAAc,iEAAiE,CAAC;AAChF,cAAc,sFAAsF,CAAC;AAErG,kCAAkC;AAClC,cAAc,kDAAkD,CAAC;AACjE,cAAc,wDAAwD,CAAC;AACvE,cAAc,yDAAyD,CAAC;AACxE,cAAc,yDAAyD,CAAC;AACxE,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC","sourcesContent":["/*\n * Public API Surface of @memberjunction/ng-artifacts\n */\n\n// Module\nexport * from './lib/artifacts.module';\n\n// Services\nexport * from './lib/services/artifact-icon.service';\nexport * from './lib/services/artifact-file.service';\nexport * from './lib/services/analyze-artifact.service';\nexport * from './lib/services/interactive-form-apply.service';\nexport * from './lib/services/artifact-preview-resolver.service';\n\n// Interfaces\nexport * from './lib/interfaces/artifact-viewer-plugin.interface';\n\n// Base component\nexport * from './lib/components/base-artifact-viewer.component';\n\n// Inline preview base + components\nexport * from './lib/components/previews/base-artifact-preview.component';\nexport * from './lib/components/previews/image-artifact-preview.component';\nexport * from './lib/components/previews/video-artifact-preview.component';\nexport * from './lib/components/previews/audio-artifact-preview.component';\n\n// Snapshot helpers (pure functions for creating DataSnapshots from artifact content)\nexport * from './lib/snapshot-helpers';\n\n// Artifact type plugin viewer (loads appropriate plugin based on DriverClass)\nexport * from './lib/components/artifact-type-plugin-viewer.component';\n\n// Artifact viewer UI components\nexport * from './lib/components/artifact-viewer-panel.component';\nexport * from './lib/components/artifact-version-history.component';\nexport * from './lib/components/artifact-message-card.component';\n\n// Plugin components\nexport * from './lib/components/plugins/json-artifact-viewer.component';\nexport * from './lib/components/plugins/code-artifact-viewer.component';\nexport * from './lib/components/plugins/markdown-artifact-viewer.component';\nexport * from './lib/components/plugins/html-artifact-viewer.component';\nexport * from './lib/components/plugins/svg-artifact-viewer.component';\nexport * from './lib/components/plugins/component-artifact-viewer.component';\nexport * from './lib/components/plugins/data-artifact-viewer.component';\nexport * from './lib/components/plugins/ml-experiment-results-viewer.component';\nexport * from './lib/components/plugins/component-feedback-panel/component-feedback-panel.component';\n\n// File viewer toolbar and plugins\nexport * from './lib/components/file-artifact-toolbar.component';\nexport * from './lib/components/plugins/pdf-artifact-viewer.component';\nexport * from './lib/components/plugins/xlsx-artifact-viewer.component';\nexport * from './lib/components/plugins/docx-artifact-viewer.component';\nexport * from './lib/components/plugins/image-artifact-viewer.component';\nexport * from './lib/components/plugins/video-artifact-viewer.component';\nexport * from './lib/components/plugins/audio-artifact-viewer.component';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-artifacts",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.45.0",
|
|
4
4
|
"description": "MemberJunction: Artifact viewer plugin system for rendering different artifact types (JSON, Code, Markdown, HTML, SVG, Components)",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@angular/compiler": "21.1.3",
|
|
20
20
|
"@angular/compiler-cli": "21.1.3",
|
|
21
|
+
"@memberjunction/core": "5.45.0",
|
|
22
|
+
"@memberjunction/ng-test-utils": "5.45.0",
|
|
21
23
|
"sass": "^1.97.3",
|
|
22
24
|
"vitest": "^4.0.18"
|
|
23
25
|
},
|
|
@@ -32,23 +34,24 @@
|
|
|
32
34
|
"dependencies": {
|
|
33
35
|
"@angular/cdk": "21.1.3",
|
|
34
36
|
"@angular/forms": "21.1.3",
|
|
35
|
-
"@memberjunction/core": "5.
|
|
36
|
-
"@memberjunction/core-entities": "5.
|
|
37
|
-
"@memberjunction/global": "5.
|
|
38
|
-
"@memberjunction/graphql-dataprovider": "5.
|
|
39
|
-
"@memberjunction/interactive-component-types": "5.
|
|
40
|
-
"@memberjunction/ng-base-forms": "5.
|
|
41
|
-
"@memberjunction/ng-base-types": "5.
|
|
42
|
-
"@memberjunction/ng-code-editor": "5.
|
|
43
|
-
"@memberjunction/ng-export-service": "5.
|
|
44
|
-
"@memberjunction/ng-markdown": "5.
|
|
45
|
-
"@memberjunction/ng-
|
|
46
|
-
"@memberjunction/ng-
|
|
47
|
-
"@memberjunction/ng-
|
|
48
|
-
"@memberjunction/ng-
|
|
49
|
-
"@memberjunction/ng-
|
|
50
|
-
"@memberjunction/ng-
|
|
51
|
-
"@memberjunction/ng-
|
|
37
|
+
"@memberjunction/core": "5.45.0",
|
|
38
|
+
"@memberjunction/core-entities": "5.45.0",
|
|
39
|
+
"@memberjunction/global": "5.45.0",
|
|
40
|
+
"@memberjunction/graphql-dataprovider": "5.45.0",
|
|
41
|
+
"@memberjunction/interactive-component-types": "5.45.0",
|
|
42
|
+
"@memberjunction/ng-base-forms": "5.45.0",
|
|
43
|
+
"@memberjunction/ng-base-types": "5.45.0",
|
|
44
|
+
"@memberjunction/ng-code-editor": "5.45.0",
|
|
45
|
+
"@memberjunction/ng-export-service": "5.45.0",
|
|
46
|
+
"@memberjunction/ng-markdown": "5.45.0",
|
|
47
|
+
"@memberjunction/ng-media-player": "5.45.0",
|
|
48
|
+
"@memberjunction/ng-notifications": "5.45.0",
|
|
49
|
+
"@memberjunction/ng-pagination": "5.45.0",
|
|
50
|
+
"@memberjunction/ng-query-viewer": "5.45.0",
|
|
51
|
+
"@memberjunction/ng-react": "5.45.0",
|
|
52
|
+
"@memberjunction/ng-shared-generic": "5.45.0",
|
|
53
|
+
"@memberjunction/ng-trees": "5.45.0",
|
|
54
|
+
"@memberjunction/ng-ui-components": "5.45.0",
|
|
52
55
|
"mammoth": "^1.8.0",
|
|
53
56
|
"pdfjs-dist": "^4.10.38",
|
|
54
57
|
"rxjs": "^7.8.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exports.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/exports.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { existsSync } from 'fs';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
|
-
describe('@memberjunction/ng-artifacts', () => {
|
|
5
|
-
it('should have a public API entry point', () => {
|
|
6
|
-
const pkgRoot = resolve(__dirname, '../..');
|
|
7
|
-
const hasPublicApi = existsSync(resolve(pkgRoot, 'src/public-api.ts'));
|
|
8
|
-
const hasIndex = existsSync(resolve(pkgRoot, 'src/index.ts'));
|
|
9
|
-
expect(hasPublicApi || hasIndex).toBe(true);
|
|
10
|
-
});
|
|
11
|
-
it('should have a package.json with correct name', () => {
|
|
12
|
-
const pkgRoot = resolve(__dirname, '../..');
|
|
13
|
-
const pkg = require(resolve(pkgRoot, 'package.json'));
|
|
14
|
-
expect(pkg.name).toBe('@memberjunction/ng-artifacts');
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
//# sourceMappingURL=exports.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exports.test.js","sourceRoot":"","sources":["../../src/__tests__/exports.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC;QACvE,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,YAAY,IAAI,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, it, expect } from 'vitest';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\n\ndescribe('@memberjunction/ng-artifacts', () => {\n it('should have a public API entry point', () => {\n const pkgRoot = resolve(__dirname, '../..');\n const hasPublicApi = existsSync(resolve(pkgRoot, 'src/public-api.ts'));\n const hasIndex = existsSync(resolve(pkgRoot, 'src/index.ts'));\n expect(hasPublicApi || hasIndex).toBe(true);\n });\n\n it('should have a package.json with correct name', () => {\n const pkgRoot = resolve(__dirname, '../..');\n const pkg = require(resolve(pkgRoot, 'package.json'));\n expect(pkg.name).toBe('@memberjunction/ng-artifacts');\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"image-artifact-viewer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/image-artifact-viewer.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { IMAGE_MIME_EXTENSION_MAP, buildImageDownloadFileName, } from '../lib/components/plugins/image-artifact-viewer.component';
|
|
3
|
-
/**
|
|
4
|
-
* Unit tests for the pure helpers exported from the image-artifact viewer
|
|
5
|
-
* plugin. The plugin's Angular component itself can't be rendered under the
|
|
6
|
-
* package's `node`-environment vitest config (no DOM, no TestBed), so the
|
|
7
|
-
* tests focus on the deterministic, side-effect-free logic that the component
|
|
8
|
-
* delegates to — exactly the boundary that has historically caused user-visible
|
|
9
|
-
* bugs (filename sanitization, MIME → extension mapping).
|
|
10
|
-
*/
|
|
11
|
-
describe('IMAGE_MIME_EXTENSION_MAP', () => {
|
|
12
|
-
it('covers the MIMEs that the seed Image artifact type advertises', () => {
|
|
13
|
-
// The metadata seed declares ContentType "image/*". These are the
|
|
14
|
-
// common raster MIMEs that Generate Image and uploaded files produce.
|
|
15
|
-
const required = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'];
|
|
16
|
-
for (const mime of required) {
|
|
17
|
-
expect(IMAGE_MIME_EXTENSION_MAP[mime]).toBeTruthy();
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
it('returns the canonical short extension for JPEG (jpg, not jpeg)', () => {
|
|
21
|
-
expect(IMAGE_MIME_EXTENSION_MAP['image/jpeg']).toBe('jpg');
|
|
22
|
-
});
|
|
23
|
-
it('is frozen (read-only) so callers cannot mutate the shared map', () => {
|
|
24
|
-
// Object.freeze guarantees runtime immutability — if a future refactor
|
|
25
|
-
// removes the freeze this test will catch it.
|
|
26
|
-
expect(Object.isFrozen(IMAGE_MIME_EXTENSION_MAP)).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
describe('buildImageDownloadFileName', () => {
|
|
30
|
-
it('combines a clean name and the right extension', () => {
|
|
31
|
-
expect(buildImageDownloadFileName('mountain', 'image/png')).toBe('mountain.png');
|
|
32
|
-
});
|
|
33
|
-
it('uses jpg for jpeg even when input is uppercase', () => {
|
|
34
|
-
expect(buildImageDownloadFileName('photo', 'IMAGE/JPEG')).toBe('photo.jpg');
|
|
35
|
-
});
|
|
36
|
-
it('strips characters that are unsafe on common filesystems', () => {
|
|
37
|
-
// Spaces, slashes, colons, and emoji should all be normalized to underscores.
|
|
38
|
-
expect(buildImageDownloadFileName('Generated image 1', 'image/jpeg')).toBe('Generated_image_1.jpg');
|
|
39
|
-
expect(buildImageDownloadFileName('a/b:c\\d', 'image/png')).toBe('a_b_c_d.png');
|
|
40
|
-
});
|
|
41
|
-
it('preserves dots, dashes, and underscores (filesystem-safe)', () => {
|
|
42
|
-
expect(buildImageDownloadFileName('snapshot_v2-final.draft', 'image/png')).toBe('snapshot_v2-final.draft.png');
|
|
43
|
-
});
|
|
44
|
-
it('falls back to "image" when no name is supplied', () => {
|
|
45
|
-
expect(buildImageDownloadFileName(null, 'image/png')).toBe('image.png');
|
|
46
|
-
expect(buildImageDownloadFileName(undefined, 'image/webp')).toBe('image.webp');
|
|
47
|
-
expect(buildImageDownloadFileName('', 'image/gif')).toBe('image.gif');
|
|
48
|
-
});
|
|
49
|
-
it('falls back to "img" extension when the MIME type is missing or unknown', () => {
|
|
50
|
-
expect(buildImageDownloadFileName('thing', null)).toBe('thing.img');
|
|
51
|
-
expect(buildImageDownloadFileName('thing', undefined)).toBe('thing.img');
|
|
52
|
-
expect(buildImageDownloadFileName('thing', '')).toBe('thing.img');
|
|
53
|
-
expect(buildImageDownloadFileName('thing', 'application/json')).toBe('thing.img');
|
|
54
|
-
});
|
|
55
|
-
it('does not double-append the extension when the name already has it', () => {
|
|
56
|
-
// The agent sometimes hands us labels like "Generated image 1.png" — we
|
|
57
|
-
// shouldn't end up with "Generated_image_1.png.png" in the user's downloads.
|
|
58
|
-
expect(buildImageDownloadFileName('photo.png', 'image/png')).toBe('photo.png');
|
|
59
|
-
expect(buildImageDownloadFileName('shot.JPG', 'image/jpeg')).toBe('shot.JPG');
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
//# sourceMappingURL=image-artifact-viewer.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"image-artifact-viewer.test.js","sourceRoot":"","sources":["../../src/__tests__/image-artifact-viewer.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect } from 'vitest';\nimport {\n IMAGE_MIME_EXTENSION_MAP,\n buildImageDownloadFileName,\n} from '../lib/components/plugins/image-artifact-viewer.component';\n\n/**\n * Unit tests for the pure helpers exported from the image-artifact viewer\n * plugin. The plugin's Angular component itself can't be rendered under the\n * package's `node`-environment vitest config (no DOM, no TestBed), so the\n * tests focus on the deterministic, side-effect-free logic that the component\n * delegates to — exactly the boundary that has historically caused user-visible\n * bugs (filename sanitization, MIME → extension mapping).\n */\n\ndescribe('IMAGE_MIME_EXTENSION_MAP', () => {\n it('covers the MIMEs that the seed Image artifact type advertises', () => {\n // The metadata seed declares ContentType \"image/*\". These are the\n // common raster MIMEs that Generate Image and uploaded files produce.\n const required = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'];\n for (const mime of required) {\n expect(IMAGE_MIME_EXTENSION_MAP[mime]).toBeTruthy();\n }\n });\n\n it('returns the canonical short extension for JPEG (jpg, not jpeg)', () => {\n expect(IMAGE_MIME_EXTENSION_MAP['image/jpeg']).toBe('jpg');\n });\n\n it('is frozen (read-only) so callers cannot mutate the shared map', () => {\n // Object.freeze guarantees runtime immutability — if a future refactor\n // removes the freeze this test will catch it.\n expect(Object.isFrozen(IMAGE_MIME_EXTENSION_MAP)).toBe(true);\n });\n});\n\ndescribe('buildImageDownloadFileName', () => {\n it('combines a clean name and the right extension', () => {\n expect(buildImageDownloadFileName('mountain', 'image/png')).toBe('mountain.png');\n });\n\n it('uses jpg for jpeg even when input is uppercase', () => {\n expect(buildImageDownloadFileName('photo', 'IMAGE/JPEG')).toBe('photo.jpg');\n });\n\n it('strips characters that are unsafe on common filesystems', () => {\n // Spaces, slashes, colons, and emoji should all be normalized to underscores.\n expect(buildImageDownloadFileName('Generated image 1', 'image/jpeg')).toBe('Generated_image_1.jpg');\n expect(buildImageDownloadFileName('a/b:c\\\\d', 'image/png')).toBe('a_b_c_d.png');\n });\n\n it('preserves dots, dashes, and underscores (filesystem-safe)', () => {\n expect(buildImageDownloadFileName('snapshot_v2-final.draft', 'image/png')).toBe(\n 'snapshot_v2-final.draft.png',\n );\n });\n\n it('falls back to \"image\" when no name is supplied', () => {\n expect(buildImageDownloadFileName(null, 'image/png')).toBe('image.png');\n expect(buildImageDownloadFileName(undefined, 'image/webp')).toBe('image.webp');\n expect(buildImageDownloadFileName('', 'image/gif')).toBe('image.gif');\n });\n\n it('falls back to \"img\" extension when the MIME type is missing or unknown', () => {\n expect(buildImageDownloadFileName('thing', null)).toBe('thing.img');\n expect(buildImageDownloadFileName('thing', undefined)).toBe('thing.img');\n expect(buildImageDownloadFileName('thing', '')).toBe('thing.img');\n expect(buildImageDownloadFileName('thing', 'application/json')).toBe('thing.img');\n });\n\n it('does not double-append the extension when the name already has it', () => {\n // The agent sometimes hands us labels like \"Generated image 1.png\" — we\n // shouldn't end up with \"Generated_image_1.png.png\" in the user's downloads.\n expect(buildImageDownloadFileName('photo.png', 'image/png')).toBe('photo.png');\n expect(buildImageDownloadFileName('shot.JPG', 'image/jpeg')).toBe('shot.JPG');\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, it, expect } from 'vitest';\n\ndescribe('@memberjunction/ng-artifacts', () => {\n it('should have a passing test', () => {\n expect(true).toBe(true);\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-snapshots.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/artifact-snapshots.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { DataSnapshot, NormalizeToTables } from '@memberjunction/core';
|
|
3
|
-
import { createJsonSnapshot, createCodeSnapshot, createMarkdownSnapshot, createDataSnapshot, buildMultiTableSql, } from '../snapshot-helpers';
|
|
4
|
-
/**
|
|
5
|
-
* Tests for artifact-level state snapshot logic.
|
|
6
|
-
*
|
|
7
|
-
* These tests exercise the pure snapshot-creation functions that the Angular
|
|
8
|
-
* viewer components delegate to, without requiring Angular TestBed.
|
|
9
|
-
*/
|
|
10
|
-
describe('Artifact Snapshot Helpers', () => {
|
|
11
|
-
describe('createJsonSnapshot', () => {
|
|
12
|
-
it('should return null when content is null', () => {
|
|
13
|
-
const result = createJsonSnapshot(null, 'Test');
|
|
14
|
-
expect(result).toBeNull();
|
|
15
|
-
});
|
|
16
|
-
it('should parse valid JSON and count top-level keys', () => {
|
|
17
|
-
const json = '{"name":"Alice","age":30,"active":true}';
|
|
18
|
-
const result = createJsonSnapshot(json, 'My JSON');
|
|
19
|
-
expect(result).not.toBeNull();
|
|
20
|
-
expect(result.title).toBe('My JSON');
|
|
21
|
-
expect(result.interpretation).toBe('JSON artifact with 3 top-level keys.');
|
|
22
|
-
expect(result.custom).toEqual({ name: 'Alice', age: 30, active: true });
|
|
23
|
-
});
|
|
24
|
-
it('should return null for invalid JSON', () => {
|
|
25
|
-
const result = createJsonSnapshot('not json {{{', 'Bad');
|
|
26
|
-
expect(result).toBeNull();
|
|
27
|
-
});
|
|
28
|
-
it('should handle JSON arrays', () => {
|
|
29
|
-
const json = '[1,2,3]';
|
|
30
|
-
const result = createJsonSnapshot(json, 'Array');
|
|
31
|
-
expect(result).not.toBeNull();
|
|
32
|
-
// Arrays don't have "top-level keys" — no interpretation set
|
|
33
|
-
expect(result.interpretation).toBeUndefined();
|
|
34
|
-
expect(result.custom).toEqual([1, 2, 3]);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
describe('createCodeSnapshot', () => {
|
|
38
|
-
it('should return null when content is null', () => {
|
|
39
|
-
const result = createCodeSnapshot(null, 'Test');
|
|
40
|
-
expect(result).toBeNull();
|
|
41
|
-
});
|
|
42
|
-
it('should count lines and include content in custom', () => {
|
|
43
|
-
const code = 'line1\nline2\nline3';
|
|
44
|
-
const result = createCodeSnapshot(code, 'My Code');
|
|
45
|
-
expect(result).not.toBeNull();
|
|
46
|
-
expect(result.title).toBe('My Code');
|
|
47
|
-
expect(result.interpretation).toBe('Code artifact, 3 lines.');
|
|
48
|
-
expect(result.custom).toEqual({ content: code, lineCount: 3 });
|
|
49
|
-
});
|
|
50
|
-
it('should handle single line content', () => {
|
|
51
|
-
const result = createCodeSnapshot('console.log("hi")', 'One Liner');
|
|
52
|
-
expect(result.interpretation).toBe('Code artifact, 1 lines.');
|
|
53
|
-
expect(result.custom.lineCount).toBe(1);
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
describe('createMarkdownSnapshot', () => {
|
|
57
|
-
it('should return null when content is null', () => {
|
|
58
|
-
const result = createMarkdownSnapshot(null, 'Test');
|
|
59
|
-
expect(result).toBeNull();
|
|
60
|
-
});
|
|
61
|
-
it('should include content in custom', () => {
|
|
62
|
-
const md = '# Hello\n\nWorld';
|
|
63
|
-
const result = createMarkdownSnapshot(md, 'My Doc');
|
|
64
|
-
expect(result).not.toBeNull();
|
|
65
|
-
expect(result.title).toBe('My Doc');
|
|
66
|
-
expect(result.custom).toEqual({ content: md });
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
describe('createDataSnapshot', () => {
|
|
70
|
-
it('should return null when spec is null', () => {
|
|
71
|
-
const result = createDataSnapshot(null);
|
|
72
|
-
expect(result).toBeNull();
|
|
73
|
-
});
|
|
74
|
-
it('should normalize a spec with columns and rows into tables', () => {
|
|
75
|
-
const spec = {
|
|
76
|
-
title: 'Sales Report',
|
|
77
|
-
columns: [
|
|
78
|
-
{ field: 'Name', headerName: 'Customer Name' },
|
|
79
|
-
{ field: 'Amount', headerName: 'Total', sqlBaseType: 'money' },
|
|
80
|
-
],
|
|
81
|
-
rows: [
|
|
82
|
-
{ Name: 'Alice', Amount: 100 },
|
|
83
|
-
{ Name: 'Bob', Amount: 200 },
|
|
84
|
-
],
|
|
85
|
-
};
|
|
86
|
-
const result = createDataSnapshot(spec);
|
|
87
|
-
expect(result).not.toBeNull();
|
|
88
|
-
expect(result.title).toBe('Sales Report');
|
|
89
|
-
expect(result.tables).toBeDefined();
|
|
90
|
-
expect(result.tables.length).toBeGreaterThanOrEqual(1);
|
|
91
|
-
expect(result.tables[0].rows).toHaveLength(2);
|
|
92
|
-
});
|
|
93
|
-
it('should use "Results" as default table name when title is missing', () => {
|
|
94
|
-
const spec = {
|
|
95
|
-
columns: [{ field: 'ID' }],
|
|
96
|
-
rows: [{ ID: 1 }],
|
|
97
|
-
};
|
|
98
|
-
const result = createDataSnapshot(spec);
|
|
99
|
-
expect(result).not.toBeNull();
|
|
100
|
-
expect(result.tables).toBeDefined();
|
|
101
|
-
expect(result.tables[0].name).toBe('Results');
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
describe('buildMultiTableSql', () => {
|
|
106
|
-
it('concatenates SQL from multiple tables with headers', () => {
|
|
107
|
-
const tables = [
|
|
108
|
-
{ name: 'customers', metadata: { sql: 'SELECT * FROM Customers' } },
|
|
109
|
-
{ name: 'orders', metadata: { sql: 'SELECT * FROM Orders' } },
|
|
110
|
-
];
|
|
111
|
-
const result = buildMultiTableSql(tables);
|
|
112
|
-
expect(result).toContain('-- ═══ customers ═══');
|
|
113
|
-
expect(result).toContain('SELECT * FROM Customers');
|
|
114
|
-
expect(result).toContain('-- ═══ orders ═══');
|
|
115
|
-
expect(result).toContain('SELECT * FROM Orders');
|
|
116
|
-
});
|
|
117
|
-
it('skips tables without SQL', () => {
|
|
118
|
-
const tables = [
|
|
119
|
-
{ name: 'has_sql', metadata: { sql: 'SELECT 1' } },
|
|
120
|
-
{ name: 'no_sql', metadata: {} },
|
|
121
|
-
{ name: 'no_meta' },
|
|
122
|
-
];
|
|
123
|
-
const result = buildMultiTableSql(tables);
|
|
124
|
-
expect(result).toContain('-- ═══ has_sql ═══');
|
|
125
|
-
expect(result).not.toContain('no_sql');
|
|
126
|
-
expect(result).not.toContain('no_meta');
|
|
127
|
-
});
|
|
128
|
-
it('returns null when no tables have SQL', () => {
|
|
129
|
-
const tables = [{ name: 'a' }, { name: 'b', metadata: {} }];
|
|
130
|
-
const result = buildMultiTableSql(tables);
|
|
131
|
-
expect(result).toBeNull();
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
describe('NormalizeToTables (core utility)', () => {
|
|
135
|
-
it('should return empty array for empty snapshot', () => {
|
|
136
|
-
const snap = new DataSnapshot();
|
|
137
|
-
expect(NormalizeToTables(snap)).toEqual([]);
|
|
138
|
-
});
|
|
139
|
-
it('should handle a spec with columns and rows (legacy format)', () => {
|
|
140
|
-
const data = {
|
|
141
|
-
columns: [{ field: 'A' }, { field: 'B' }],
|
|
142
|
-
rows: [{ A: 1, B: 2 }],
|
|
143
|
-
};
|
|
144
|
-
const tables = NormalizeToTables(data, 'Sheet1');
|
|
145
|
-
expect(tables).toHaveLength(1);
|
|
146
|
-
expect(tables[0].rows).toHaveLength(1);
|
|
147
|
-
});
|
|
148
|
-
it('should return empty for a context-only snapshot', () => {
|
|
149
|
-
const snap = new DataSnapshot();
|
|
150
|
-
snap.title = 'Just a title';
|
|
151
|
-
const tables = NormalizeToTables(snap);
|
|
152
|
-
expect(tables).toEqual([]);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
//# sourceMappingURL=artifact-snapshots.test.js.map
|