@memberjunction/ng-artifacts 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/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.map +1 -1
- package/dist/lib/components/artifact-version-history.component.js +26 -29
- 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
|
@@ -12,6 +12,7 @@ import { ArtifactFileService } from '../../services/artifact-file.service';
|
|
|
12
12
|
import { AudioArtifactPreviewComponent } from '../previews/audio-artifact-preview.component';
|
|
13
13
|
import * as i0 from "@angular/core";
|
|
14
14
|
import * as i1 from "@angular/common";
|
|
15
|
+
import * as i2 from "@memberjunction/ng-media-player";
|
|
15
16
|
function AudioArtifactViewerComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
16
17
|
i0.ɵɵelementStart(0, "div", 1);
|
|
17
18
|
i0.ɵɵelement(1, "i", 4);
|
|
@@ -25,12 +26,12 @@ function AudioArtifactViewerComponent_Conditional_1_Template(rf, ctx) { if (rf &
|
|
|
25
26
|
} }
|
|
26
27
|
function AudioArtifactViewerComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
27
28
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
28
|
-
i0.ɵɵelementStart(0, "
|
|
29
|
-
i0.ɵɵlistener("
|
|
29
|
+
i0.ɵɵelementStart(0, "mj-media-player", 5);
|
|
30
|
+
i0.ɵɵlistener("Ended", function AudioArtifactViewerComponent_Conditional_2_Template_mj_media_player_Ended_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onMediaEnded()); });
|
|
30
31
|
i0.ɵɵelementEnd();
|
|
31
32
|
} if (rf & 2) {
|
|
32
33
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
33
|
-
i0.ɵɵproperty("
|
|
34
|
+
i0.ɵɵproperty("Tracks", ctx_r0.MediaTracks);
|
|
34
35
|
} }
|
|
35
36
|
function AudioArtifactViewerComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
36
37
|
i0.ɵɵelementStart(0, "div", 3);
|
|
@@ -51,6 +52,26 @@ let AudioArtifactViewerComponent = class AudioArtifactViewerComponent extends Ba
|
|
|
51
52
|
cdr = inject(ChangeDetectorRef);
|
|
52
53
|
audioUrl = '';
|
|
53
54
|
errorMessage = '';
|
|
55
|
+
/**
|
|
56
|
+
* Single-track input for the generic {@link MJMediaPlayerComponent}. Rebuilt whenever
|
|
57
|
+
* {@link audioUrl} is (re)resolved via {@link setAudioUrl}; empty until a URL exists so the
|
|
58
|
+
* player shows its own empty state.
|
|
59
|
+
*/
|
|
60
|
+
MediaTracks = [];
|
|
61
|
+
/** Set the resolved URL and recompute the single-element {@link MediaTracks} array in lockstep. */
|
|
62
|
+
setAudioUrl(url) {
|
|
63
|
+
this.audioUrl = url;
|
|
64
|
+
this.MediaTracks = url
|
|
65
|
+
? [
|
|
66
|
+
{
|
|
67
|
+
Id: this.artifactVersion?.ID ?? 'audio',
|
|
68
|
+
Kind: 'audio',
|
|
69
|
+
Url: url,
|
|
70
|
+
MimeType: this.artifactVersion?.MimeType ?? undefined,
|
|
71
|
+
},
|
|
72
|
+
]
|
|
73
|
+
: [];
|
|
74
|
+
}
|
|
54
75
|
/**
|
|
55
76
|
* Inline-preview component for audio artifacts ({@link IArtifactViewerPluginPreviewStatics}).
|
|
56
77
|
* STATIC so the resolver reads it off the constructor without instantiating this DI-using component.
|
|
@@ -70,12 +91,12 @@ let AudioArtifactViewerComponent = class AudioArtifactViewerComponent extends Ba
|
|
|
70
91
|
async ngOnInit() {
|
|
71
92
|
try {
|
|
72
93
|
if (this.artifactVersion?.ContentMode === 'File' && this.artifactVersion.ID) {
|
|
73
|
-
this.
|
|
94
|
+
this.setAudioUrl(await this.fileService.getDownloadUrl(this.artifactVersion.ID));
|
|
74
95
|
}
|
|
75
96
|
else {
|
|
76
97
|
const content = this.artifactVersion?.Content;
|
|
77
98
|
if (content) {
|
|
78
|
-
this.
|
|
99
|
+
this.setAudioUrl(content);
|
|
79
100
|
}
|
|
80
101
|
else {
|
|
81
102
|
this.errorMessage = 'This artifact has no audio content.';
|
|
@@ -90,9 +111,13 @@ let AudioArtifactViewerComponent = class AudioArtifactViewerComponent extends Ba
|
|
|
90
111
|
}
|
|
91
112
|
onMediaError() {
|
|
92
113
|
this.errorMessage = 'The audio could not be played. It may be corrupt or in an unsupported format.';
|
|
93
|
-
this.
|
|
114
|
+
this.setAudioUrl('');
|
|
94
115
|
this.cdr.markForCheck();
|
|
95
116
|
}
|
|
117
|
+
/** Fired when the generic player reaches the end of the track. No-op affordance hook. */
|
|
118
|
+
onMediaEnded() {
|
|
119
|
+
// Playback finished — nothing to persist for a one-shot artifact viewer.
|
|
120
|
+
}
|
|
96
121
|
GetCurrentStateSnapshot() {
|
|
97
122
|
if (!this.artifactVersion) {
|
|
98
123
|
return null;
|
|
@@ -108,15 +133,15 @@ let AudioArtifactViewerComponent = class AudioArtifactViewerComponent extends Ba
|
|
|
108
133
|
return snap;
|
|
109
134
|
}
|
|
110
135
|
static ɵfac = /*@__PURE__*/ (() => { let ɵAudioArtifactViewerComponent_BaseFactory; return function AudioArtifactViewerComponent_Factory(__ngFactoryType__) { return (ɵAudioArtifactViewerComponent_BaseFactory || (ɵAudioArtifactViewerComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AudioArtifactViewerComponent)))(__ngFactoryType__ || AudioArtifactViewerComponent); }; })();
|
|
111
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AudioArtifactViewerComponent, selectors: [["mj-audio-artifact-viewer"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [[1, "audio-viewer", 3, "ngClass"], [1, "audio-viewer__state", "audio-viewer__state--error"], [
|
|
136
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AudioArtifactViewerComponent, selectors: [["mj-audio-artifact-viewer"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [[1, "audio-viewer", 3, "ngClass"], [1, "audio-viewer__state", "audio-viewer__state--error"], [1, "audio-viewer__player", 3, "Tracks"], [1, "audio-viewer__state"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "audio-viewer__player", 3, "Ended", "Tracks"], [1, "fa-solid", "fa-spinner", "fa-spin"]], template: function AudioArtifactViewerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
112
137
|
i0.ɵɵelementStart(0, "div", 0);
|
|
113
|
-
i0.ɵɵconditionalCreate(1, AudioArtifactViewerComponent_Conditional_1_Template, 4, 1, "div", 1)(2, AudioArtifactViewerComponent_Conditional_2_Template, 1, 1, "
|
|
138
|
+
i0.ɵɵconditionalCreate(1, AudioArtifactViewerComponent_Conditional_1_Template, 4, 1, "div", 1)(2, AudioArtifactViewerComponent_Conditional_2_Template, 1, 1, "mj-media-player", 2)(3, AudioArtifactViewerComponent_Conditional_3_Template, 4, 0, "div", 3);
|
|
114
139
|
i0.ɵɵelementEnd();
|
|
115
140
|
} if (rf & 2) {
|
|
116
141
|
i0.ɵɵproperty("ngClass", ctx.cssClass);
|
|
117
142
|
i0.ɵɵadvance();
|
|
118
143
|
i0.ɵɵconditional(ctx.errorMessage ? 1 : ctx.audioUrl ? 2 : 3);
|
|
119
|
-
} }, dependencies: [i1.NgClass], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n }\n\n .audio-viewer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n }\n\n .audio-
|
|
144
|
+
} }, dependencies: [i1.NgClass, i2.MJMediaPlayerComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n }\n\n .audio-viewer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n }\n\n .audio-viewer__player[_ngcontent-%COMP%] {\n display: block;\n width: 100%;\n max-width: 640px;\n }\n\n .audio-viewer__state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .audio-viewer__state--error[_ngcontent-%COMP%] {\n color: var(--mj-status-error-text);\n }"] });
|
|
120
145
|
};
|
|
121
146
|
AudioArtifactViewerComponent = __decorate([
|
|
122
147
|
RegisterClass(BaseArtifactViewerPluginComponent, 'AudioArtifactViewerPlugin')
|
|
@@ -132,7 +157,7 @@ export { AudioArtifactViewerComponent };
|
|
|
132
157
|
<span>{{ errorMessage }}</span>
|
|
133
158
|
</div>
|
|
134
159
|
} @else if (audioUrl) {
|
|
135
|
-
<
|
|
160
|
+
<mj-media-player class="audio-viewer__player" [Tracks]="MediaTracks" (Ended)="onMediaEnded()"></mj-media-player>
|
|
136
161
|
} @else {
|
|
137
162
|
<div class="audio-viewer__state">
|
|
138
163
|
<i class="fa-solid fa-spinner fa-spin"></i>
|
|
@@ -140,7 +165,7 @@ export { AudioArtifactViewerComponent };
|
|
|
140
165
|
</div>
|
|
141
166
|
}
|
|
142
167
|
</div>
|
|
143
|
-
`, styles: ["\n :host {\n display: block;\n height: 100%;\n }\n\n .audio-viewer {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n }\n\n .audio-
|
|
168
|
+
`, styles: ["\n :host {\n display: block;\n height: 100%;\n }\n\n .audio-viewer {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n }\n\n .audio-viewer__player {\n display: block;\n width: 100%;\n max-width: 640px;\n }\n\n .audio-viewer__state {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .audio-viewer__state--error {\n color: var(--mj-status-error-text);\n }\n "] }]
|
|
144
169
|
}], null, null); })();
|
|
145
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AudioArtifactViewerComponent, { className: "AudioArtifactViewerComponent", filePath: "src/lib/components/plugins/audio-artifact-viewer.component.ts", lineNumber:
|
|
170
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AudioArtifactViewerComponent, { className: "AudioArtifactViewerComponent", filePath: "src/lib/components/plugins/audio-artifact-viewer.component.ts", lineNumber: 75 }); })();
|
|
146
171
|
//# sourceMappingURL=audio-artifact-viewer.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/audio-artifact-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, inject, OnInit, Type } from '@angular/core';\nimport { DataSnapshot } from '@memberjunction/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';\nimport { ArtifactFileService } from '../../services/artifact-file.service';\nimport { IArtifactPreviewComponent } from '../../interfaces/artifact-viewer-plugin.interface';\nimport { AudioArtifactPreviewComponent } from '../previews/audio-artifact-preview.component';\n\n/**\n * Minimal full-size viewer plugin for audio artifacts. Renders an `<audio controls>` player.\n * Supports both storage modes (see {@link VideoArtifactViewerComponent} for the same contract).\n *\n * Deliberately minimal — the inline experience lives in {@link AudioArtifactPreviewComponent}\n * (exposed via {@link previewComponentType}); this satisfies the required `componentType`.\n */\n@Component({\n standalone: false,\n selector: 'mj-audio-artifact-viewer',\n template: `\n <div class=\"audio-viewer\" [ngClass]=\"cssClass\">\n @if (errorMessage) {\n <div class=\"audio-viewer__state audio-viewer__state--error\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage }}</span>\n </div>\n } @else if (audioUrl) {\n <audio class=\"audio-viewer__audio\" controls preload=\"metadata\" [src]=\"audioUrl\" (error)=\"onMediaError()\"></audio>\n } @else {\n <div class=\"audio-viewer__state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading audio…</span>\n </div>\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n height: 100%;\n }\n\n .audio-viewer {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n }\n\n .audio-viewer__audio {\n width: 100%;\n max-width: 480px;\n }\n\n .audio-viewer__state {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .audio-viewer__state--error {\n color: var(--mj-status-error-text);\n }\n `,\n ],\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'AudioArtifactViewerPlugin')\nexport class AudioArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit {\n private readonly fileService = inject(ArtifactFileService);\n private readonly cdr = inject(ChangeDetectorRef);\n\n public audioUrl = '';\n public errorMessage = '';\n\n /**\n * Inline-preview component for audio artifacts ({@link IArtifactViewerPluginPreviewStatics}).\n * STATIC so the resolver reads it off the constructor without instantiating this DI-using component.\n */\n public static readonly PreviewComponentType: Type<IArtifactPreviewComponent> = AudioArtifactPreviewComponent;\n\n /** Matches audio artifacts by type name or `audio/*` MIME. STATIC — drives preview resolution. */\n public static CanHandlePreview(artifactTypeName: string, contentType?: string): boolean {\n const mime = (contentType ?? '').toLowerCase();\n if (mime.startsWith('audio/')) {\n return true;\n }\n return (artifactTypeName ?? '').trim().toLowerCase() === 'audio';\n }\n\n public override get hasDisplayContent(): boolean {\n return true;\n }\n\n async ngOnInit(): Promise<void> {\n try {\n if (this.artifactVersion?.ContentMode === 'File' && this.artifactVersion.ID) {\n this.audioUrl = await this.fileService.getDownloadUrl(this.artifactVersion.ID);\n } else {\n const content = this.artifactVersion?.Content;\n if (content) {\n this.audioUrl = content;\n } else {\n this.errorMessage = 'This artifact has no audio content.';\n }\n }\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n this.errorMessage = `Could not load audio: ${detail}`;\n }\n this.cdr.markForCheck();\n }\n\n public onMediaError(): void {\n this.errorMessage = 'The audio could not be played. It may be corrupt or in an unsupported format.';\n this.audioUrl = '';\n this.cdr.markForCheck();\n }\n\n public override GetCurrentStateSnapshot(): DataSnapshot | null {\n if (!this.artifactVersion) {\n return null;\n }\n const snap = new DataSnapshot();\n snap.title = this.getDisplayTitle() ?? undefined;\n snap.interpretation = `Audio (${this.artifactVersion.MimeType ?? 'audio'}).`;\n snap.custom = {\n mimeType: this.artifactVersion.MimeType ?? undefined,\n fileName: this.artifactVersion.FileName ?? undefined,\n contentMode: this.artifactVersion.ContentMode,\n };\n return snap;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"audio-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/audio-artifact-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, inject, OnInit, Type } from '@angular/core';\nimport { DataSnapshot } from '@memberjunction/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';\nimport { ArtifactFileService } from '../../services/artifact-file.service';\nimport { IArtifactPreviewComponent } from '../../interfaces/artifact-viewer-plugin.interface';\nimport { AudioArtifactPreviewComponent } from '../previews/audio-artifact-preview.component';\nimport { MJMediaPlayerComponent, MediaTrack } from '@memberjunction/ng-media-player';\n\n/**\n * Minimal full-size viewer plugin for audio artifacts. Renders an `<audio controls>` player.\n * Supports both storage modes (see {@link VideoArtifactViewerComponent} for the same contract).\n *\n * Deliberately minimal — the inline experience lives in {@link AudioArtifactPreviewComponent}\n * (exposed via {@link previewComponentType}); this satisfies the required `componentType`.\n */\n@Component({\n standalone: false,\n selector: 'mj-audio-artifact-viewer',\n template: `\n <div class=\"audio-viewer\" [ngClass]=\"cssClass\">\n @if (errorMessage) {\n <div class=\"audio-viewer__state audio-viewer__state--error\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage }}</span>\n </div>\n } @else if (audioUrl) {\n <mj-media-player class=\"audio-viewer__player\" [Tracks]=\"MediaTracks\" (Ended)=\"onMediaEnded()\"></mj-media-player>\n } @else {\n <div class=\"audio-viewer__state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading audio…</span>\n </div>\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n height: 100%;\n }\n\n .audio-viewer {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n }\n\n .audio-viewer__player {\n display: block;\n width: 100%;\n max-width: 640px;\n }\n\n .audio-viewer__state {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .audio-viewer__state--error {\n color: var(--mj-status-error-text);\n }\n `,\n ],\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'AudioArtifactViewerPlugin')\nexport class AudioArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit {\n private readonly fileService = inject(ArtifactFileService);\n private readonly cdr = inject(ChangeDetectorRef);\n\n public audioUrl = '';\n public errorMessage = '';\n\n /**\n * Single-track input for the generic {@link MJMediaPlayerComponent}. Rebuilt whenever\n * {@link audioUrl} is (re)resolved via {@link setAudioUrl}; empty until a URL exists so the\n * player shows its own 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 setAudioUrl(url: string): void {\n this.audioUrl = url;\n this.MediaTracks = url\n ? [\n {\n Id: this.artifactVersion?.ID ?? 'audio',\n Kind: 'audio',\n Url: url,\n MimeType: this.artifactVersion?.MimeType ?? undefined,\n },\n ]\n : [];\n }\n\n /**\n * Inline-preview component for audio artifacts ({@link IArtifactViewerPluginPreviewStatics}).\n * STATIC so the resolver reads it off the constructor without instantiating this DI-using component.\n */\n public static readonly PreviewComponentType: Type<IArtifactPreviewComponent> = AudioArtifactPreviewComponent;\n\n /** Matches audio artifacts by type name or `audio/*` MIME. STATIC — drives preview resolution. */\n public static CanHandlePreview(artifactTypeName: string, contentType?: string): boolean {\n const mime = (contentType ?? '').toLowerCase();\n if (mime.startsWith('audio/')) {\n return true;\n }\n return (artifactTypeName ?? '').trim().toLowerCase() === 'audio';\n }\n\n public override get hasDisplayContent(): boolean {\n return true;\n }\n\n async ngOnInit(): Promise<void> {\n try {\n if (this.artifactVersion?.ContentMode === 'File' && this.artifactVersion.ID) {\n this.setAudioUrl(await this.fileService.getDownloadUrl(this.artifactVersion.ID));\n } else {\n const content = this.artifactVersion?.Content;\n if (content) {\n this.setAudioUrl(content);\n } else {\n this.errorMessage = 'This artifact has no audio content.';\n }\n }\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n this.errorMessage = `Could not load audio: ${detail}`;\n }\n this.cdr.markForCheck();\n }\n\n public onMediaError(): void {\n this.errorMessage = 'The audio could not be played. It may be corrupt or in an unsupported format.';\n this.setAudioUrl('');\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 a one-shot artifact viewer.\n }\n\n public override GetCurrentStateSnapshot(): DataSnapshot | null {\n if (!this.artifactVersion) {\n return null;\n }\n const snap = new DataSnapshot();\n snap.title = this.getDisplayTitle() ?? undefined;\n snap.interpretation = `Audio (${this.artifactVersion.MimeType ?? 'audio'}).`;\n snap.custom = {\n mimeType: this.artifactVersion.MimeType ?? undefined,\n fileName: this.artifactVersion.FileName ?? undefined,\n contentMode: this.artifactVersion.ContentMode,\n };\n return snap;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-feedback-panel.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,SAAS,EAA6B,MAAM,eAAe,CAAC;AAC7G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAIrE,OAAO,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;;
|
|
1
|
+
{"version":3,"file":"component-feedback-panel.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,SAAS,EAA6B,MAAM,eAAe,CAAC;AAC7G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAIrE,OAAO,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;;AAI5E;;GAEG;AACH,UAAU,QAAQ;IAChB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,qBAOa,+BAAgC,SAAQ,oBAAqB,YAAW,SAAS;IACnF,aAAa,EAAE,aAAa,GAAG,IAAI,CAAQ;IAC3C,qBAAqB,EAAE,WAAW,GAAG,IAAI,CAAQ;IACjD,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IACrC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C,MAAM,qBAA4B;IAGrC,YAAY,EAAE,aAAa,GAAG,IAAI,CAAQ;IAC1C,UAAU,SAAK;IACf,WAAW,SAAK;IAChB,gBAAgB,SAAM;IACtB,YAAY,UAAS;IACrB,aAAa,UAAS;IACtB,WAAW,SAAM;IAGjB,aAAa,cAAqB;IAGzC,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,qBAAqB,CAA0C;IAEvE,OAAO,CAAC,GAAG,CAA6B;IAIxC,YAAY,IAAI,QAAQ,EAAE;IAQ1B,OAAO,CAAC,SAAS;IAcjB,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IASxD,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAI5C,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAM1C,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAIxC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAMrC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI9B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAInC,gBAAgB,IAAI,IAAI;IAIxB,gBAAgB,IAAI,MAAM;IAI1B,yEAAyE;IACzE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;IAOtD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAMpC,SAAS,IAAI,IAAI;IAQjB,SAAS,IAAI,OAAO;IAId,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IA8CrC,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAKxC,kBAAkB,IAAI,IAAI;IAI1B,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,kBAAkB;IAuC1B,OAAO,CAAC,yBAAyB;IAQjC;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,6BAA6B;IA0BrC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,cAAc;IAWtB,UAAU,IAAI,IAAI;IAKlB,WAAW,IAAI,IAAI;yCAhXR,+BAA+B;2CAA/B,+BAA+B;CAmX3C"}
|
package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js
CHANGED
|
@@ -3,6 +3,7 @@ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
|
3
3
|
import { CommonModule } from '@angular/common';
|
|
4
4
|
import { FormsModule } from '@angular/forms';
|
|
5
5
|
import { MarkdownModule } from '@memberjunction/ng-markdown';
|
|
6
|
+
import { MJEmptyStateComponent, MJAlertComponent } from '@memberjunction/ng-ui-components';
|
|
6
7
|
import * as i0 from "@angular/core";
|
|
7
8
|
import * as i1 from "@angular/forms";
|
|
8
9
|
import * as i2 from "@memberjunction/ng-markdown";
|
|
@@ -59,36 +60,32 @@ function ComponentFeedbackPanelComponent_Conditional_15_Template(rf, ctx) { if (
|
|
|
59
60
|
i0.ɵɵrepeater(ctx_r2.GetTreeItems());
|
|
60
61
|
} }
|
|
61
62
|
function ComponentFeedbackPanelComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
62
|
-
i0.ɵɵ
|
|
63
|
-
i0.ɵɵelement(1, "i", 25);
|
|
64
|
-
i0.ɵɵelementStart(2, "span");
|
|
65
|
-
i0.ɵɵtext(3, "No component hierarchy available");
|
|
66
|
-
i0.ɵɵelementEnd()();
|
|
63
|
+
i0.ɵɵelement(0, "mj-empty-state", 12);
|
|
67
64
|
} }
|
|
68
65
|
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
69
|
-
i0.ɵɵelement(0, "mj-markdown",
|
|
66
|
+
i0.ɵɵelement(0, "mj-markdown", 26);
|
|
70
67
|
} if (rf & 2) {
|
|
71
68
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
72
69
|
i0.ɵɵproperty("data", ctx_r2.SelectedSpec.description);
|
|
73
70
|
} }
|
|
74
71
|
function ComponentFeedbackPanelComponent_Conditional_18_For_11_Case_3_Template(rf, ctx) { if (rf & 1) {
|
|
75
|
-
i0.ɵɵelement(0, "i",
|
|
72
|
+
i0.ɵɵelement(0, "i", 43);
|
|
76
73
|
} }
|
|
77
74
|
function ComponentFeedbackPanelComponent_Conditional_18_For_11_Case_4_Template(rf, ctx) { if (rf & 1) {
|
|
78
|
-
i0.ɵɵelement(0, "i",
|
|
75
|
+
i0.ɵɵelement(0, "i", 44);
|
|
79
76
|
} }
|
|
80
77
|
function ComponentFeedbackPanelComponent_Conditional_18_For_11_Case_5_Template(rf, ctx) { if (rf & 1) {
|
|
81
|
-
i0.ɵɵelement(0, "i",
|
|
78
|
+
i0.ɵɵelement(0, "i", 45);
|
|
82
79
|
} }
|
|
83
80
|
function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template(rf, ctx) { if (rf & 1) {
|
|
84
81
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
85
|
-
i0.ɵɵelementStart(0, "span",
|
|
82
|
+
i0.ɵɵelementStart(0, "span", 30)(1, "span", 41);
|
|
86
83
|
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template_span_click_1_listener() { const star_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.SetRating(star_r7 - 0.5)); })("mouseenter", function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template_span_mouseenter_1_listener() { const star_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.SetHoverRating(star_r7 - 0.5)); });
|
|
87
84
|
i0.ɵɵelementEnd();
|
|
88
|
-
i0.ɵɵelementStart(2, "span",
|
|
85
|
+
i0.ɵɵelementStart(2, "span", 42);
|
|
89
86
|
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template_span_click_2_listener() { const star_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.SetRating(star_r7)); })("mouseenter", function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template_span_mouseenter_2_listener() { const star_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.SetHoverRating(star_r7)); });
|
|
90
87
|
i0.ɵɵelementEnd();
|
|
91
|
-
i0.ɵɵconditionalCreate(3, ComponentFeedbackPanelComponent_Conditional_18_For_11_Case_3_Template, 1, 0, "i",
|
|
88
|
+
i0.ɵɵconditionalCreate(3, ComponentFeedbackPanelComponent_Conditional_18_For_11_Case_3_Template, 1, 0, "i", 43)(4, ComponentFeedbackPanelComponent_Conditional_18_For_11_Case_4_Template, 1, 0, "i", 44)(5, ComponentFeedbackPanelComponent_Conditional_18_For_11_Case_5_Template, 1, 0, "i", 45);
|
|
92
89
|
i0.ɵɵelementEnd();
|
|
93
90
|
} if (rf & 2) {
|
|
94
91
|
let tmp_11_0;
|
|
@@ -98,12 +95,12 @@ function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template(rf, ctx)
|
|
|
98
95
|
i0.ɵɵconditional((tmp_11_0 = ctx_r2.GetStarState(star_r7)) === "full" ? 3 : tmp_11_0 === "half" ? 4 : 5);
|
|
99
96
|
} }
|
|
100
97
|
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
101
|
-
i0.ɵɵelementStart(0, "span",
|
|
98
|
+
i0.ɵɵelementStart(0, "span", 31);
|
|
102
99
|
i0.ɵɵtext(1, "Click to rate");
|
|
103
100
|
i0.ɵɵelementEnd();
|
|
104
101
|
} }
|
|
105
102
|
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
106
|
-
i0.ɵɵelementStart(0, "span",
|
|
103
|
+
i0.ɵɵelementStart(0, "span", 36);
|
|
107
104
|
i0.ɵɵtext(1);
|
|
108
105
|
i0.ɵɵelementEnd();
|
|
109
106
|
} if (rf & 2) {
|
|
@@ -112,69 +109,65 @@ function ComponentFeedbackPanelComponent_Conditional_18_Conditional_20_Template(
|
|
|
112
109
|
i0.ɵɵtextInterpolate1("", ctx_r2.FeedbackComments.length, "/1000");
|
|
113
110
|
} }
|
|
114
111
|
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
115
|
-
i0.ɵɵelement(0, "i",
|
|
112
|
+
i0.ɵɵelement(0, "i", 46);
|
|
116
113
|
i0.ɵɵelementStart(1, "span");
|
|
117
114
|
i0.ɵɵtext(2, "Submitting...");
|
|
118
115
|
i0.ɵɵelementEnd();
|
|
119
116
|
} }
|
|
120
117
|
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_24_Template(rf, ctx) { if (rf & 1) {
|
|
121
|
-
i0.ɵɵelement(0, "i",
|
|
118
|
+
i0.ɵɵelement(0, "i", 47);
|
|
122
119
|
i0.ɵɵelementStart(1, "span");
|
|
123
120
|
i0.ɵɵtext(2, "Submit Feedback");
|
|
124
121
|
i0.ɵɵelementEnd();
|
|
125
122
|
} }
|
|
126
123
|
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
127
|
-
i0.ɵɵelementStart(0, "
|
|
128
|
-
i0.ɵɵ
|
|
129
|
-
i0.ɵɵ
|
|
130
|
-
i0.ɵɵtext(3, "Feedback submitted successfully!");
|
|
131
|
-
i0.ɵɵelementEnd()();
|
|
124
|
+
i0.ɵɵelementStart(0, "mj-alert", 39);
|
|
125
|
+
i0.ɵɵtext(1, "Feedback submitted successfully!");
|
|
126
|
+
i0.ɵɵelementEnd();
|
|
132
127
|
} }
|
|
133
128
|
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
134
|
-
i0.ɵɵelementStart(0, "
|
|
135
|
-
i0.ɵɵ
|
|
136
|
-
i0.ɵɵ
|
|
137
|
-
i0.ɵɵtext(3);
|
|
138
|
-
i0.ɵɵelementEnd()();
|
|
129
|
+
i0.ɵɵelementStart(0, "mj-alert", 40);
|
|
130
|
+
i0.ɵɵtext(1);
|
|
131
|
+
i0.ɵɵelementEnd();
|
|
139
132
|
} if (rf & 2) {
|
|
140
133
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
141
|
-
i0.ɵɵadvance(
|
|
134
|
+
i0.ɵɵadvance();
|
|
142
135
|
i0.ɵɵtextInterpolate(ctx_r2.SubmitError);
|
|
143
136
|
} }
|
|
144
137
|
function ComponentFeedbackPanelComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
145
138
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
146
139
|
i0.ɵɵelementStart(0, "div", 14)(1, "div", 9);
|
|
147
|
-
i0.ɵɵelement(2, "i",
|
|
140
|
+
i0.ɵɵelement(2, "i", 25);
|
|
148
141
|
i0.ɵɵelementStart(3, "span");
|
|
149
142
|
i0.ɵɵtext(4);
|
|
150
143
|
i0.ɵɵelementEnd()();
|
|
151
|
-
i0.ɵɵconditionalCreate(5, ComponentFeedbackPanelComponent_Conditional_18_Conditional_5_Template, 1, 1, "mj-markdown",
|
|
152
|
-
i0.ɵɵelementStart(6, "div",
|
|
144
|
+
i0.ɵɵconditionalCreate(5, ComponentFeedbackPanelComponent_Conditional_18_Conditional_5_Template, 1, 1, "mj-markdown", 26);
|
|
145
|
+
i0.ɵɵelementStart(6, "div", 27)(7, "label", 28);
|
|
153
146
|
i0.ɵɵtext(8, "Your Rating");
|
|
154
147
|
i0.ɵɵelementEnd();
|
|
155
|
-
i0.ɵɵelementStart(9, "div",
|
|
148
|
+
i0.ɵɵelementStart(9, "div", 29);
|
|
156
149
|
i0.ɵɵlistener("mouseleave", function ComponentFeedbackPanelComponent_Conditional_18_Template_div_mouseleave_9_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ClearHoverRating()); });
|
|
157
|
-
i0.ɵɵrepeaterCreate(10, ComponentFeedbackPanelComponent_Conditional_18_For_11_Template, 6, 1, "span",
|
|
150
|
+
i0.ɵɵrepeaterCreate(10, ComponentFeedbackPanelComponent_Conditional_18_For_11_Template, 6, 1, "span", 30, i0.ɵɵrepeaterTrackByIdentity);
|
|
158
151
|
i0.ɵɵelementEnd();
|
|
159
|
-
i0.ɵɵconditionalCreate(12, ComponentFeedbackPanelComponent_Conditional_18_Conditional_12_Template, 2, 0, "span",
|
|
152
|
+
i0.ɵɵconditionalCreate(12, ComponentFeedbackPanelComponent_Conditional_18_Conditional_12_Template, 2, 0, "span", 31);
|
|
160
153
|
i0.ɵɵelementEnd();
|
|
161
|
-
i0.ɵɵelementStart(13, "div",
|
|
154
|
+
i0.ɵɵelementStart(13, "div", 32)(14, "label", 33);
|
|
162
155
|
i0.ɵɵtext(15, " Comments ");
|
|
163
|
-
i0.ɵɵelementStart(16, "span",
|
|
156
|
+
i0.ɵɵelementStart(16, "span", 34);
|
|
164
157
|
i0.ɵɵtext(17, "(optional)");
|
|
165
158
|
i0.ɵɵelementEnd()();
|
|
166
|
-
i0.ɵɵelementStart(18, "textarea",
|
|
159
|
+
i0.ɵɵelementStart(18, "textarea", 35);
|
|
167
160
|
i0.ɵɵtwoWayListener("ngModelChange", function ComponentFeedbackPanelComponent_Conditional_18_Template_textarea_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.FeedbackComments, $event) || (ctx_r2.FeedbackComments = $event); return i0.ɵɵresetView($event); });
|
|
168
161
|
i0.ɵɵtext(19, " ");
|
|
169
162
|
i0.ɵɵelementEnd();
|
|
170
|
-
i0.ɵɵconditionalCreate(20, ComponentFeedbackPanelComponent_Conditional_18_Conditional_20_Template, 2, 1, "span",
|
|
163
|
+
i0.ɵɵconditionalCreate(20, ComponentFeedbackPanelComponent_Conditional_18_Conditional_20_Template, 2, 1, "span", 36);
|
|
171
164
|
i0.ɵɵelementEnd();
|
|
172
|
-
i0.ɵɵelementStart(21, "div",
|
|
165
|
+
i0.ɵɵelementStart(21, "div", 37)(22, "button", 38);
|
|
173
166
|
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Conditional_18_Template_button_click_22_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SubmitFeedback()); });
|
|
174
167
|
i0.ɵɵconditionalCreate(23, ComponentFeedbackPanelComponent_Conditional_18_Conditional_23_Template, 3, 0)(24, ComponentFeedbackPanelComponent_Conditional_18_Conditional_24_Template, 3, 0);
|
|
175
168
|
i0.ɵɵelementEnd()();
|
|
176
|
-
i0.ɵɵconditionalCreate(25, ComponentFeedbackPanelComponent_Conditional_18_Conditional_25_Template,
|
|
177
|
-
i0.ɵɵconditionalCreate(26, ComponentFeedbackPanelComponent_Conditional_18_Conditional_26_Template,
|
|
169
|
+
i0.ɵɵconditionalCreate(25, ComponentFeedbackPanelComponent_Conditional_18_Conditional_25_Template, 2, 0, "mj-alert", 39);
|
|
170
|
+
i0.ɵɵconditionalCreate(26, ComponentFeedbackPanelComponent_Conditional_18_Conditional_26_Template, 2, 1, "mj-alert", 40);
|
|
178
171
|
i0.ɵɵelementEnd();
|
|
179
172
|
} if (rf & 2) {
|
|
180
173
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
@@ -200,11 +193,7 @@ function ComponentFeedbackPanelComponent_Conditional_18_Template(rf, ctx) { if (
|
|
|
200
193
|
i0.ɵɵconditional(ctx_r2.SubmitError ? 26 : -1);
|
|
201
194
|
} }
|
|
202
195
|
function ComponentFeedbackPanelComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
203
|
-
i0.ɵɵ
|
|
204
|
-
i0.ɵɵelement(1, "i", 51);
|
|
205
|
-
i0.ɵɵelementStart(2, "p");
|
|
206
|
-
i0.ɵɵtext(3, "Select a component from the tree to provide feedback");
|
|
207
|
-
i0.ɵɵelementEnd()();
|
|
196
|
+
i0.ɵɵelement(0, "mj-empty-state", 15);
|
|
208
197
|
} }
|
|
209
198
|
/**
|
|
210
199
|
* Component feedback panel that displays component hierarchy tree
|
|
@@ -536,7 +525,7 @@ export class ComponentFeedbackPanelComponent extends BaseAngularComponent {
|
|
|
536
525
|
this.ClearHighlight();
|
|
537
526
|
}
|
|
538
527
|
static ɵfac = /*@__PURE__*/ (() => { let ɵComponentFeedbackPanelComponent_BaseFactory; return function ComponentFeedbackPanelComponent_Factory(__ngFactoryType__) { return (ɵComponentFeedbackPanelComponent_BaseFactory || (ɵComponentFeedbackPanelComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ComponentFeedbackPanelComponent)))(__ngFactoryType__ || ComponentFeedbackPanelComponent); }; })();
|
|
539
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ComponentFeedbackPanelComponent, selectors: [["mj-component-feedback-panel"]], inputs: { ComponentSpec: "ComponentSpec", ReactContainerElement: "ReactContainerElement", ConversationId: "ConversationId", ConversationDetailId: "ConversationDetailId" }, outputs: { Closed: "Closed" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 20, vars: 2, consts: [[1, "feedback-panel-overlay", 3, "click"], [1, "feedback-panel", 3, "click"], [1, "panel-header"], [1, "panel-title"], [1, "fa-solid", "fa-magnifying-glass"], [1, "close-button", 3, "click"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "tree-section"], [1, "section-header"], [1, "fa-solid", "fa-sitemap"], [1, "component-tree"], [
|
|
528
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ComponentFeedbackPanelComponent, selectors: [["mj-component-feedback-panel"]], inputs: { ComponentSpec: "ComponentSpec", ReactContainerElement: "ReactContainerElement", ConversationId: "ConversationId", ConversationDetailId: "ConversationDetailId" }, outputs: { Closed: "Closed" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 20, vars: 2, consts: [[1, "feedback-panel-overlay", 3, "click"], [1, "feedback-panel", 3, "click"], [1, "panel-header"], [1, "panel-title"], [1, "fa-solid", "fa-magnifying-glass"], [1, "close-button", 3, "click"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "tree-section"], [1, "section-header"], [1, "fa-solid", "fa-sitemap"], [1, "component-tree"], ["Icon", "fa-solid fa-circle-info", "Title", "No component hierarchy available", "Size", "compact"], [1, "feedback-section"], [1, "selected-component-info"], ["Icon", "fa-solid fa-hand-pointer", "Title", "Select a component from the tree to provide feedback", "Size", "compact"], [1, "tree-item", 3, "selected", "padding-left"], [1, "tree-item", 3, "click", "mouseenter", "mouseleave"], [1, "tree-toggle", "fa-solid", 3, "fa-chevron-right", "fa-chevron-down"], [1, "tree-spacer"], [1, "fa-solid", "fa-cube", "component-icon"], [1, "component-info"], [1, "component-name"], [1, "component-badge", "registry"], [1, "tree-toggle", "fa-solid", 3, "click"], [1, "fa-solid", "fa-star"], [1, "component-description", 3, "data"], [1, "star-rating-container"], [1, "rating-label"], [1, "star-rating", 3, "mouseleave"], [1, "star-wrapper"], [1, "rating-text", "placeholder"], [1, "comment-container"], [1, "comment-label"], [1, "optional-label"], ["placeholder", "Share your thoughts about this component...", "rows", "4", "maxlength", "1000", 1, "comment-input", 3, "ngModelChange", "ngModel"], [1, "char-count"], [1, "submit-container"], [1, "submit-button", 3, "click", "disabled"], ["Variant", "success"], ["Variant", "error"], [1, "star-zone", "star-zone-left", 3, "click", "mouseenter"], [1, "star-zone", "star-zone-right", 3, "click", "mouseenter"], [1, "star", "fa-solid", "fa-star"], [1, "star", "fa-solid", "fa-star-half-stroke"], [1, "star", "fa-regular", "fa-star"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-paper-plane"]], template: function ComponentFeedbackPanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
540
529
|
i0.ɵɵelementStart(0, "div", 0);
|
|
541
530
|
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Template_div_click_0_listener() { return ctx.ClosePanel(); });
|
|
542
531
|
i0.ɵɵelementStart(1, "div", 1);
|
|
@@ -555,21 +544,21 @@ export class ComponentFeedbackPanelComponent extends BaseAngularComponent {
|
|
|
555
544
|
i0.ɵɵelementStart(13, "span");
|
|
556
545
|
i0.ɵɵtext(14, "Select Component");
|
|
557
546
|
i0.ɵɵelementEnd()();
|
|
558
|
-
i0.ɵɵconditionalCreate(15, ComponentFeedbackPanelComponent_Conditional_15_Template, 3, 0, "div", 11)(16, ComponentFeedbackPanelComponent_Conditional_16_Template,
|
|
547
|
+
i0.ɵɵconditionalCreate(15, ComponentFeedbackPanelComponent_Conditional_15_Template, 3, 0, "div", 11)(16, ComponentFeedbackPanelComponent_Conditional_16_Template, 1, 0, "mj-empty-state", 12);
|
|
559
548
|
i0.ɵɵelementEnd();
|
|
560
549
|
i0.ɵɵelementStart(17, "div", 13);
|
|
561
|
-
i0.ɵɵconditionalCreate(18, ComponentFeedbackPanelComponent_Conditional_18_Template, 27, 10, "div", 14)(19, ComponentFeedbackPanelComponent_Conditional_19_Template,
|
|
550
|
+
i0.ɵɵconditionalCreate(18, ComponentFeedbackPanelComponent_Conditional_18_Template, 27, 10, "div", 14)(19, ComponentFeedbackPanelComponent_Conditional_19_Template, 1, 0, "mj-empty-state", 15);
|
|
562
551
|
i0.ɵɵelementEnd()()()();
|
|
563
552
|
} if (rf & 2) {
|
|
564
553
|
i0.ɵɵadvance(15);
|
|
565
554
|
i0.ɵɵconditional(ctx.ComponentSpec ? 15 : 16);
|
|
566
555
|
i0.ɵɵadvance(3);
|
|
567
556
|
i0.ɵɵconditional(ctx.SelectedSpec ? 18 : 19);
|
|
568
|
-
} }, dependencies: [CommonModule, FormsModule, i1.DefaultValueAccessor, i1.NgControlStatus, i1.MaxLengthValidator, i1.NgModel, MarkdownModule, i2.MarkdownComponent], styles: ["\n\n.feedback-panel-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--mj-bg-overlay);\n z-index: 9999;\n display: flex;\n justify-content: flex-start;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease-in-out;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.feedback-panel[_ngcontent-%COMP%] {\n width: 540px;\n height: 100%;\n background-color: var(--mj-bg-surface);\n \n\n\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n animation: _ngcontent-%COMP%_slideInFromLeft 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slideInFromLeft {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-card);\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}\n\n.close-button[_ngcontent-%COMP%] {\n min-width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n background: none;\n border-radius: 4px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-button[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-hover);\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 20px;\n}\n\n\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 2px solid var(--mj-brand-primary);\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n\n\n.tree-section[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 16px;\n}\n\n.component-tree[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.tree-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n}\n\n.tree-item[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.tree-item.selected[_ngcontent-%COMP%] {\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-weight: 500;\n}\n\n.tree-item.selected[_ngcontent-%COMP%] .component-icon[_ngcontent-%COMP%], \n.tree-item.selected[_ngcontent-%COMP%] .tree-toggle[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n.tree-item.selected[_ngcontent-%COMP%] .component-badge[_ngcontent-%COMP%] {\n background-color: rgba(255, 255, 255, 0.2);\n color: var(--mj-text-inverse);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.tree-toggle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: transform 0.2s ease;\n width: 16px;\n text-align: center;\n}\n\n.tree-spacer[_ngcontent-%COMP%] {\n width: 16px;\n display: inline-block;\n}\n\n.component-icon[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-brand-primary);\n}\n\n.component-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n overflow: hidden;\n}\n\n.component-name[_ngcontent-%COMP%] {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 14px;\n}\n\n.component-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 10px;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n white-space: nowrap;\n font-weight: 500;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: var(--mj-text-disabled);\n font-size: 14px;\n}\n\n\n\n.feedback-section[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n padding: 16px;\n min-height: 300px;\n}\n\n.selected-component-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.component-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0;\n padding: 12px;\n background-color: var(--mj-bg-surface-card);\n border-radius: 6px;\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n\n\n.star-rating-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.rating-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.star-rating[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.star-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: inline-block;\n cursor: pointer;\n}\n\n.star-wrapper[_ngcontent-%COMP%]:hover .star[_ngcontent-%COMP%] {\n transform: scale(1.2);\n filter: brightness(1.1);\n}\n\n.star-zone[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n height: 100%;\n width: 50%;\n z-index: 1;\n}\n\n.star-zone-left[_ngcontent-%COMP%] {\n left: 0;\n}\n\n.star-zone-right[_ngcontent-%COMP%] {\n right: 0;\n}\n\n.star[_ngcontent-%COMP%] {\n font-size: 32px;\n \n\n color: #ffd700;\n transition: all 0.2s ease;\n pointer-events: none;\n}\n\n.star.fa-regular[_ngcontent-%COMP%] {\n color: var(--mj-border-strong);\n}\n\n.rating-text[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n}\n\n.rating-text.placeholder[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-style: italic;\n}\n\n\n\n.comment-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.comment-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.optional-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: normal;\n color: var(--mj-text-disabled);\n}\n\n.comment-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n transition: border-color 0.2s ease;\n background-color: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n\n.comment-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.char-count[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 8px;\n right: 12px;\n font-size: 11px;\n color: var(--mj-text-disabled);\n background-color: var(--mj-bg-surface);\n padding: 2px 4px;\n}\n\n\n\n.submit-container[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n}\n\n.submit-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transition: background-color 0.2s ease;\n}\n\n.submit-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover);\n}\n\n.submit-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-radius: 6px;\n font-size: 14px;\n animation: _ngcontent-%COMP%_slideDown 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.success-message[_ngcontent-%COMP%] {\n background-color: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.success-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.error-message[_ngcontent-%COMP%] {\n background-color: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.error-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.no-selection-message[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--mj-text-disabled);\n text-align: center;\n}\n\n.no-selection-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n color: var(--mj-border-strong);\n}\n\n.no-selection-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n line-height: 1.5;\n}\n\n\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background-color: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background-color: var(--mj-text-disabled);\n}"] });
|
|
557
|
+
} }, dependencies: [CommonModule, FormsModule, i1.DefaultValueAccessor, i1.NgControlStatus, i1.MaxLengthValidator, i1.NgModel, MarkdownModule, i2.MarkdownComponent, MJEmptyStateComponent, MJAlertComponent], styles: ["\n\n.feedback-panel-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--mj-bg-overlay);\n z-index: 9999;\n display: flex;\n justify-content: flex-start;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease-in-out;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.feedback-panel[_ngcontent-%COMP%] {\n width: 540px;\n height: 100%;\n background-color: var(--mj-bg-surface);\n \n\n\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n animation: _ngcontent-%COMP%_slideInFromLeft 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slideInFromLeft {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-card);\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}\n\n.close-button[_ngcontent-%COMP%] {\n min-width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n background: none;\n border-radius: 4px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-button[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-hover);\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 20px;\n}\n\n\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 2px solid var(--mj-brand-primary);\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n\n\n.tree-section[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 16px;\n}\n\n.component-tree[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.tree-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n}\n\n.tree-item[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.tree-item.selected[_ngcontent-%COMP%] {\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-weight: 500;\n}\n\n.tree-item.selected[_ngcontent-%COMP%] .component-icon[_ngcontent-%COMP%], \n.tree-item.selected[_ngcontent-%COMP%] .tree-toggle[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n.tree-item.selected[_ngcontent-%COMP%] .component-badge[_ngcontent-%COMP%] {\n background-color: rgba(255, 255, 255, 0.2);\n color: var(--mj-text-inverse);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.tree-toggle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: transform 0.2s ease;\n width: 16px;\n text-align: center;\n}\n\n.tree-spacer[_ngcontent-%COMP%] {\n width: 16px;\n display: inline-block;\n}\n\n.component-icon[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-brand-primary);\n}\n\n.component-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n overflow: hidden;\n}\n\n.component-name[_ngcontent-%COMP%] {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 14px;\n}\n\n.component-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 10px;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n white-space: nowrap;\n font-weight: 500;\n}\n\n\n\n.feedback-section[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n padding: 16px;\n min-height: 300px;\n}\n\n.selected-component-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.component-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0;\n padding: 12px;\n background-color: var(--mj-bg-surface-card);\n border-radius: 6px;\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n\n\n.star-rating-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.rating-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.star-rating[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.star-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: inline-block;\n cursor: pointer;\n}\n\n.star-wrapper[_ngcontent-%COMP%]:hover .star[_ngcontent-%COMP%] {\n transform: scale(1.2);\n filter: brightness(1.1);\n}\n\n.star-zone[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n height: 100%;\n width: 50%;\n z-index: 1;\n}\n\n.star-zone-left[_ngcontent-%COMP%] {\n left: 0;\n}\n\n.star-zone-right[_ngcontent-%COMP%] {\n right: 0;\n}\n\n.star[_ngcontent-%COMP%] {\n font-size: 32px;\n \n\n color: #ffd700;\n transition: all 0.2s ease;\n pointer-events: none;\n}\n\n.star.fa-regular[_ngcontent-%COMP%] {\n color: var(--mj-border-strong);\n}\n\n.rating-text[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n}\n\n.rating-text.placeholder[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-style: italic;\n}\n\n\n\n.comment-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.comment-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.optional-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: normal;\n color: var(--mj-text-disabled);\n}\n\n.comment-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n transition: border-color 0.2s ease;\n background-color: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n\n.comment-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.char-count[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 8px;\n right: 12px;\n font-size: 11px;\n color: var(--mj-text-disabled);\n background-color: var(--mj-bg-surface);\n padding: 2px 4px;\n}\n\n\n\n.submit-container[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n}\n\n.submit-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transition: background-color 0.2s ease;\n}\n\n.submit-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover);\n}\n\n.submit-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n\n\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background-color: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background-color: var(--mj-text-disabled);\n}"] });
|
|
569
558
|
}
|
|
570
559
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentFeedbackPanelComponent, [{
|
|
571
560
|
type: Component,
|
|
572
|
-
args: [{ selector: 'mj-component-feedback-panel', standalone: true, imports: [CommonModule, FormsModule, MarkdownModule], template: "<div class=\"feedback-panel-overlay\" (click)=\"ClosePanel()\">\n <div class=\"feedback-panel\" (click)=\"$event.stopPropagation()\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n <span>Inspect & Rate</span>\n </div>\n <button class=\"close-button\" (click)=\"ClosePanel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Component Tree Section -->\n <div class=\"tree-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-sitemap\"></i>\n <span>Select Component</span>\n </div>\n\n @if (ComponentSpec) {\n <div class=\"component-tree\">\n @for (item of GetTreeItems(); track item.spec.name) {\n <div\n class=\"tree-item\"\n [class.selected]=\"IsSelected(item.spec)\"\n [style.padding-left]=\"GetIndentation(item.depth)\"\n (click)=\"SelectComponent(item.spec)\"\n (mouseenter)=\"HoverTreeItem(item.spec)\"\n (mouseleave)=\"ClearTreeItemHover()\">\n\n @if (item.hasChildren) {\n <i\n class=\"tree-toggle fa-solid\"\n [class.fa-chevron-right]=\"!IsNodeExpanded(item.spec)\"\n [class.fa-chevron-down]=\"IsNodeExpanded(item.spec)\"\n (click)=\"ToggleNode(item.spec, $event)\">\n </i>\n } @else {\n <span class=\"tree-spacer\"></span>\n }\n\n <i class=\"fa-solid fa-cube component-icon\"></i>\n\n <div class=\"component-info\">\n <span class=\"component-name\">{{ item.spec.title || item.spec.name }}</span>\n @if (item.spec.location === 'registry') {\n <span class=\"component-badge registry\">Registry</span>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>No component hierarchy available</span>\n </div>\n }\n </div>\n\n <!-- Feedback Form Section -->\n <div class=\"feedback-section\">\n @if (SelectedSpec) {\n <div class=\"selected-component-info\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-star\"></i>\n <span>Rate: {{ SelectedSpec.title || SelectedSpec.name }}</span>\n </div>\n\n @if (SelectedSpec.description) {\n <mj-markdown [data]=\"SelectedSpec.description\" class=\"component-description\"></mj-markdown>\n }\n\n <!-- Star Rating (half-star support) -->\n <div class=\"star-rating-container\">\n <label class=\"rating-label\">Your Rating</label>\n <div class=\"star-rating\" (mouseleave)=\"ClearHoverRating()\">\n @for (star of [1, 2, 3, 4, 5]; track star) {\n <span class=\"star-wrapper\">\n <!-- Left half (sets X.5 for previous half) -->\n <span class=\"star-zone star-zone-left\"\n (click)=\"SetRating(star - 0.5)\"\n (mouseenter)=\"SetHoverRating(star - 0.5)\"></span>\n <!-- Right half (sets full star) -->\n <span class=\"star-zone star-zone-right\"\n (click)=\"SetRating(star)\"\n (mouseenter)=\"SetHoverRating(star)\"></span>\n <!-- Star icon -->\n @switch (GetStarState(star)) {\n @case ('full') {\n <i class=\"star fa-solid fa-star\"></i>\n }\n @case ('half') {\n <i class=\"star fa-solid fa-star-half-stroke\"></i>\n }\n @default {\n <i class=\"star fa-regular fa-star\"></i>\n }\n }\n </span>\n }\n </div>\n @if (StarRating === 0) {\n <span class=\"rating-text placeholder\">Click to rate</span>\n }\n </div>\n\n <!-- Comment Input -->\n <div class=\"comment-container\">\n <label class=\"comment-label\">\n Comments\n <span class=\"optional-label\">(optional)</span>\n </label>\n <textarea\n class=\"comment-input\"\n [(ngModel)]=\"FeedbackComments\"\n placeholder=\"Share your thoughts about this component...\"\n rows=\"4\"\n maxlength=\"1000\">\n </textarea>\n @if (FeedbackComments.length > 0) {\n <span class=\"char-count\">{{ FeedbackComments.length }}/1000</span>\n }\n </div>\n\n <!-- Submit Button -->\n <div class=\"submit-container\">\n <button\n class=\"submit-button\"\n [disabled]=\"!CanSubmit()\"\n (click)=\"SubmitFeedback()\">\n @if (IsSubmitting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Submitting...</span>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n <span>Submit Feedback</span>\n }\n </button>\n </div>\n\n <!-- Success/Error Messages -->\n @if (SubmitSuccess) {\n <div class=\"message success-message\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <span>Feedback submitted successfully!</span>\n </div>\n }\n @if (SubmitError) {\n <div class=\"message error-message\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n <span>{{ SubmitError }}</span>\n </div>\n }\n </div>\n } @else {\n <div class=\"no-selection-message\">\n <i class=\"fa-solid fa-hand-pointer\"></i>\n <p>Select a component from the tree to provide feedback</p>\n </div>\n }\n </div>\n </div>\n </div>\n</div>\n", styles: ["/* Overlay */\n.feedback-panel-overlay {\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--mj-bg-overlay);\n z-index: 9999;\n display: flex;\n justify-content: flex-start;\n animation: fadeIn 0.2s ease-in-out;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Panel Container */\n.feedback-panel {\n width: 540px;\n height: 100%;\n background-color: var(--mj-bg-surface);\n /* Side-panel shadow (horizontal): no semantic token covers a horizontal panel shadow,\n and the alpha keeps it readable in both light and dark themes. */\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n animation: slideInFromLeft 0.3s ease-out;\n}\n\n@keyframes slideInFromLeft {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n\n/* Header */\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-card);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.panel-title i {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}\n\n.close-button {\n min-width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n background: none;\n border-radius: 4px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-button:hover {\n background-color: var(--mj-bg-surface-hover);\n}\n\n/* Content */\n.panel-content {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 20px;\n}\n\n/* Section Headers */\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 2px solid var(--mj-brand-primary);\n}\n\n.section-header i {\n color: var(--mj-brand-primary);\n}\n\n/* Component Tree */\n.tree-section {\n background-color: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 16px;\n}\n\n.component-tree {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.tree-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n}\n\n.tree-item:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.tree-item.selected {\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-weight: 500;\n}\n\n.tree-item.selected .component-icon,\n.tree-item.selected .tree-toggle {\n color: var(--mj-text-inverse);\n}\n\n.tree-item.selected .component-badge {\n background-color: rgba(255, 255, 255, 0.2);\n color: var(--mj-text-inverse);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.tree-toggle {\n font-size: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: transform 0.2s ease;\n width: 16px;\n text-align: center;\n}\n\n.tree-spacer {\n width: 16px;\n display: inline-block;\n}\n\n.component-icon {\n font-size: 16px;\n color: var(--mj-brand-primary);\n}\n\n.component-info {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n overflow: hidden;\n}\n\n.component-name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 14px;\n}\n\n.component-badge {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 10px;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n white-space: nowrap;\n font-weight: 500;\n}\n\n.empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: var(--mj-text-disabled);\n font-size: 14px;\n}\n\n/* Feedback Form Section */\n.feedback-section {\n background-color: var(--mj-bg-surface);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n padding: 16px;\n min-height: 300px;\n}\n\n.selected-component-info {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.component-description {\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0;\n padding: 12px;\n background-color: var(--mj-bg-surface-card);\n border-radius: 6px;\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n/* Star Rating */\n.star-rating-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.rating-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.star-rating {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.star-wrapper {\n position: relative;\n display: inline-block;\n cursor: pointer;\n}\n\n.star-wrapper:hover .star {\n transform: scale(1.2);\n filter: brightness(1.1);\n}\n\n.star-zone {\n position: absolute;\n top: 0;\n height: 100%;\n width: 50%;\n z-index: 1;\n}\n\n.star-zone-left {\n left: 0;\n}\n\n.star-zone-right {\n right: 0;\n}\n\n.star {\n font-size: 32px;\n /* Iconic gold star \u2014 categorical/branding color, not theme-dependent */\n color: #ffd700;\n transition: all 0.2s ease;\n pointer-events: none;\n}\n\n.star.fa-regular {\n color: var(--mj-border-strong);\n}\n\n.rating-text {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n}\n\n.rating-text.placeholder {\n color: var(--mj-text-disabled);\n font-style: italic;\n}\n\n/* Comment Input */\n.comment-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.comment-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.optional-label {\n font-size: 12px;\n font-weight: normal;\n color: var(--mj-text-disabled);\n}\n\n.comment-input {\n width: 100%;\n padding: 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n transition: border-color 0.2s ease;\n background-color: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n\n.comment-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.char-count {\n position: absolute;\n bottom: 8px;\n right: 12px;\n font-size: 11px;\n color: var(--mj-text-disabled);\n background-color: var(--mj-bg-surface);\n padding: 2px 4px;\n}\n\n/* Submit Button */\n.submit-container {\n display: flex;\n justify-content: flex-start;\n}\n\n.submit-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transition: background-color 0.2s ease;\n}\n\n.submit-button:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover);\n}\n\n.submit-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Messages */\n.message {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-radius: 6px;\n font-size: 14px;\n animation: slideDown 0.3s ease-out;\n}\n\n@keyframes slideDown {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.success-message {\n background-color: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.success-message i {\n color: var(--mj-status-success);\n}\n\n.error-message {\n background-color: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.error-message i {\n color: var(--mj-status-error);\n}\n\n/* No Selection Message */\n.no-selection-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--mj-text-disabled);\n text-align: center;\n}\n\n.no-selection-message i {\n font-size: 48px;\n color: var(--mj-border-strong);\n}\n\n.no-selection-message p {\n margin: 0;\n font-size: 14px;\n line-height: 1.5;\n}\n\n/* Scrollbar Styling */\n.panel-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.panel-content::-webkit-scrollbar-track {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.panel-content::-webkit-scrollbar-thumb {\n background-color: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.panel-content::-webkit-scrollbar-thumb:hover {\n background-color: var(--mj-text-disabled);\n}\n"] }]
|
|
561
|
+
args: [{ selector: 'mj-component-feedback-panel', standalone: true, imports: [CommonModule, FormsModule, MarkdownModule, MJEmptyStateComponent, MJAlertComponent], template: "<div class=\"feedback-panel-overlay\" (click)=\"ClosePanel()\">\n <div class=\"feedback-panel\" (click)=\"$event.stopPropagation()\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n <span>Inspect & Rate</span>\n </div>\n <button class=\"close-button\" (click)=\"ClosePanel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Component Tree Section -->\n <div class=\"tree-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-sitemap\"></i>\n <span>Select Component</span>\n </div>\n\n @if (ComponentSpec) {\n <div class=\"component-tree\">\n @for (item of GetTreeItems(); track item.spec.name) {\n <div\n class=\"tree-item\"\n [class.selected]=\"IsSelected(item.spec)\"\n [style.padding-left]=\"GetIndentation(item.depth)\"\n (click)=\"SelectComponent(item.spec)\"\n (mouseenter)=\"HoverTreeItem(item.spec)\"\n (mouseleave)=\"ClearTreeItemHover()\">\n\n @if (item.hasChildren) {\n <i\n class=\"tree-toggle fa-solid\"\n [class.fa-chevron-right]=\"!IsNodeExpanded(item.spec)\"\n [class.fa-chevron-down]=\"IsNodeExpanded(item.spec)\"\n (click)=\"ToggleNode(item.spec, $event)\">\n </i>\n } @else {\n <span class=\"tree-spacer\"></span>\n }\n\n <i class=\"fa-solid fa-cube component-icon\"></i>\n\n <div class=\"component-info\">\n <span class=\"component-name\">{{ item.spec.title || item.spec.name }}</span>\n @if (item.spec.location === 'registry') {\n <span class=\"component-badge registry\">Registry</span>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <mj-empty-state\n Icon=\"fa-solid fa-circle-info\"\n Title=\"No component hierarchy available\"\n Size=\"compact\" />\n }\n </div>\n\n <!-- Feedback Form Section -->\n <div class=\"feedback-section\">\n @if (SelectedSpec) {\n <div class=\"selected-component-info\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-star\"></i>\n <span>Rate: {{ SelectedSpec.title || SelectedSpec.name }}</span>\n </div>\n\n @if (SelectedSpec.description) {\n <mj-markdown [data]=\"SelectedSpec.description\" class=\"component-description\"></mj-markdown>\n }\n\n <!-- Star Rating (half-star support) -->\n <div class=\"star-rating-container\">\n <label class=\"rating-label\">Your Rating</label>\n <div class=\"star-rating\" (mouseleave)=\"ClearHoverRating()\">\n @for (star of [1, 2, 3, 4, 5]; track star) {\n <span class=\"star-wrapper\">\n <!-- Left half (sets X.5 for previous half) -->\n <span class=\"star-zone star-zone-left\"\n (click)=\"SetRating(star - 0.5)\"\n (mouseenter)=\"SetHoverRating(star - 0.5)\"></span>\n <!-- Right half (sets full star) -->\n <span class=\"star-zone star-zone-right\"\n (click)=\"SetRating(star)\"\n (mouseenter)=\"SetHoverRating(star)\"></span>\n <!-- Star icon -->\n @switch (GetStarState(star)) {\n @case ('full') {\n <i class=\"star fa-solid fa-star\"></i>\n }\n @case ('half') {\n <i class=\"star fa-solid fa-star-half-stroke\"></i>\n }\n @default {\n <i class=\"star fa-regular fa-star\"></i>\n }\n }\n </span>\n }\n </div>\n @if (StarRating === 0) {\n <span class=\"rating-text placeholder\">Click to rate</span>\n }\n </div>\n\n <!-- Comment Input -->\n <div class=\"comment-container\">\n <label class=\"comment-label\">\n Comments\n <span class=\"optional-label\">(optional)</span>\n </label>\n <textarea\n class=\"comment-input\"\n [(ngModel)]=\"FeedbackComments\"\n placeholder=\"Share your thoughts about this component...\"\n rows=\"4\"\n maxlength=\"1000\">\n </textarea>\n @if (FeedbackComments.length > 0) {\n <span class=\"char-count\">{{ FeedbackComments.length }}/1000</span>\n }\n </div>\n\n <!-- Submit Button -->\n <div class=\"submit-container\">\n <button\n class=\"submit-button\"\n [disabled]=\"!CanSubmit()\"\n (click)=\"SubmitFeedback()\">\n @if (IsSubmitting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Submitting...</span>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n <span>Submit Feedback</span>\n }\n </button>\n </div>\n\n <!-- Success/Error Messages -->\n @if (SubmitSuccess) {\n <mj-alert Variant=\"success\">Feedback submitted successfully!</mj-alert>\n }\n @if (SubmitError) {\n <mj-alert Variant=\"error\">{{ SubmitError }}</mj-alert>\n }\n </div>\n } @else {\n <mj-empty-state\n Icon=\"fa-solid fa-hand-pointer\"\n Title=\"Select a component from the tree to provide feedback\"\n Size=\"compact\" />\n }\n </div>\n </div>\n </div>\n</div>\n", styles: ["/* Overlay */\n.feedback-panel-overlay {\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--mj-bg-overlay);\n z-index: 9999;\n display: flex;\n justify-content: flex-start;\n animation: fadeIn 0.2s ease-in-out;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Panel Container */\n.feedback-panel {\n width: 540px;\n height: 100%;\n background-color: var(--mj-bg-surface);\n /* Side-panel shadow (horizontal): no semantic token covers a horizontal panel shadow,\n and the alpha keeps it readable in both light and dark themes. */\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n animation: slideInFromLeft 0.3s ease-out;\n}\n\n@keyframes slideInFromLeft {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n\n/* Header */\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-card);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.panel-title i {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}\n\n.close-button {\n min-width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n background: none;\n border-radius: 4px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-button:hover {\n background-color: var(--mj-bg-surface-hover);\n}\n\n/* Content */\n.panel-content {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 20px;\n}\n\n/* Section Headers */\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 2px solid var(--mj-brand-primary);\n}\n\n.section-header i {\n color: var(--mj-brand-primary);\n}\n\n/* Component Tree */\n.tree-section {\n background-color: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 16px;\n}\n\n.component-tree {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.tree-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n}\n\n.tree-item:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.tree-item.selected {\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-weight: 500;\n}\n\n.tree-item.selected .component-icon,\n.tree-item.selected .tree-toggle {\n color: var(--mj-text-inverse);\n}\n\n.tree-item.selected .component-badge {\n background-color: rgba(255, 255, 255, 0.2);\n color: var(--mj-text-inverse);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.tree-toggle {\n font-size: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: transform 0.2s ease;\n width: 16px;\n text-align: center;\n}\n\n.tree-spacer {\n width: 16px;\n display: inline-block;\n}\n\n.component-icon {\n font-size: 16px;\n color: var(--mj-brand-primary);\n}\n\n.component-info {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n overflow: hidden;\n}\n\n.component-name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 14px;\n}\n\n.component-badge {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 10px;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n white-space: nowrap;\n font-weight: 500;\n}\n\n/* Feedback Form Section */\n.feedback-section {\n background-color: var(--mj-bg-surface);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n padding: 16px;\n min-height: 300px;\n}\n\n.selected-component-info {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.component-description {\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0;\n padding: 12px;\n background-color: var(--mj-bg-surface-card);\n border-radius: 6px;\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n/* Star Rating */\n.star-rating-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.rating-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.star-rating {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.star-wrapper {\n position: relative;\n display: inline-block;\n cursor: pointer;\n}\n\n.star-wrapper:hover .star {\n transform: scale(1.2);\n filter: brightness(1.1);\n}\n\n.star-zone {\n position: absolute;\n top: 0;\n height: 100%;\n width: 50%;\n z-index: 1;\n}\n\n.star-zone-left {\n left: 0;\n}\n\n.star-zone-right {\n right: 0;\n}\n\n.star {\n font-size: 32px;\n /* Iconic gold star \u2014 categorical/branding color, not theme-dependent */\n color: #ffd700;\n transition: all 0.2s ease;\n pointer-events: none;\n}\n\n.star.fa-regular {\n color: var(--mj-border-strong);\n}\n\n.rating-text {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-top: 4px;\n}\n\n.rating-text.placeholder {\n color: var(--mj-text-disabled);\n font-style: italic;\n}\n\n/* Comment Input */\n.comment-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.comment-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.optional-label {\n font-size: 12px;\n font-weight: normal;\n color: var(--mj-text-disabled);\n}\n\n.comment-input {\n width: 100%;\n padding: 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n transition: border-color 0.2s ease;\n background-color: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n\n.comment-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.char-count {\n position: absolute;\n bottom: 8px;\n right: 12px;\n font-size: 11px;\n color: var(--mj-text-disabled);\n background-color: var(--mj-bg-surface);\n padding: 2px 4px;\n}\n\n/* Submit Button */\n.submit-container {\n display: flex;\n justify-content: flex-start;\n}\n\n.submit-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n background-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transition: background-color 0.2s ease;\n}\n\n.submit-button:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover);\n}\n\n.submit-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n@keyframes slideDown {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n\n/* Scrollbar Styling */\n.panel-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.panel-content::-webkit-scrollbar-track {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.panel-content::-webkit-scrollbar-thumb {\n background-color: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.panel-content::-webkit-scrollbar-thumb:hover {\n background-color: var(--mj-text-disabled);\n}\n"] }]
|
|
573
562
|
}], null, { ComponentSpec: [{
|
|
574
563
|
type: Input
|
|
575
564
|
}], ReactContainerElement: [{
|
|
@@ -581,5 +570,5 @@ export class ComponentFeedbackPanelComponent extends BaseAngularComponent {
|
|
|
581
570
|
}], Closed: [{
|
|
582
571
|
type: Output
|
|
583
572
|
}] }); })();
|
|
584
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ComponentFeedbackPanelComponent, { className: "ComponentFeedbackPanelComponent", filePath: "src/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.ts", lineNumber:
|
|
573
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ComponentFeedbackPanelComponent, { className: "ComponentFeedbackPanelComponent", filePath: "src/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.ts", lineNumber: 31 }); })();
|
|
585
574
|
//# sourceMappingURL=component-feedback-panel.component.js.map
|