@rtsee/ngx 0.0.117 → 0.0.118
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.
|
@@ -54,7 +54,7 @@ import { Tag } from 'primeng/tag';
|
|
|
54
54
|
import { SelectButton } from 'primeng/selectbutton';
|
|
55
55
|
import { RTSeeRoutesList } from '@rtsee/factory';
|
|
56
56
|
import { Avatar } from 'primeng/avatar';
|
|
57
|
-
import { Image } from 'primeng/image';
|
|
57
|
+
import { Image as Image$1 } from 'primeng/image';
|
|
58
58
|
import { PanelMenu } from 'primeng/panelmenu';
|
|
59
59
|
import { Menu } from 'primeng/menu';
|
|
60
60
|
import { Password } from 'primeng/password';
|
|
@@ -1961,11 +1961,11 @@ class RatingComponent {
|
|
|
1961
1961
|
this.init();
|
|
1962
1962
|
}
|
|
1963
1963
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RatingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1964
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RatingComponent, isStandalone: true, selector: "rtsee-rating", inputs: { config: "config", rate: "rate" }, ngImport: i0, template: "<div
|
|
1964
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RatingComponent, isStandalone: true, selector: "rtsee-rating", inputs: { config: "config", rate: "rate" }, ngImport: i0, template: "<div\n class=\"rtsee-rating\"\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"reviewRating\"\n itemscope\n itemtype=\"https://schema.org/Rating\"\n>\n <meta itemprop=\"bestRating\" content=\"5\" />\n <meta itemprop=\"worstRating\" content=\"1\" />\n @for (star of stars; track $index) {\n <span class=\"rtsee-rating-star\"\n [ngClass]=\"{\n 'rtsee-rating-star-full': star === 'full',\n 'rtsee-rating-star-half': star === 'half',\n 'rtsee-rating-star-empty': star === 'empty',\n 'rtsee-rating-star-clickable': mutable\n }\"\n (click)=\"onStarClicked($index)\"\n >\u2605</span>\n }\n @if (rateValue) {\n <span class=\"rtsee-rating-number\" itemprop=\"ratingValue\">{{ rateValue | number:'1.1-1' }}</span>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: DecimalPipe, name: "number" }] }); }
|
|
1965
1965
|
}
|
|
1966
1966
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RatingComponent, decorators: [{
|
|
1967
1967
|
type: Component,
|
|
1968
|
-
args: [{ selector: 'rtsee-rating', imports: [NgClass, DecimalPipe], template: "<div
|
|
1968
|
+
args: [{ selector: 'rtsee-rating', imports: [NgClass, DecimalPipe], template: "<div\n class=\"rtsee-rating\"\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"reviewRating\"\n itemscope\n itemtype=\"https://schema.org/Rating\"\n>\n <meta itemprop=\"bestRating\" content=\"5\" />\n <meta itemprop=\"worstRating\" content=\"1\" />\n @for (star of stars; track $index) {\n <span class=\"rtsee-rating-star\"\n [ngClass]=\"{\n 'rtsee-rating-star-full': star === 'full',\n 'rtsee-rating-star-half': star === 'half',\n 'rtsee-rating-star-empty': star === 'empty',\n 'rtsee-rating-star-clickable': mutable\n }\"\n (click)=\"onStarClicked($index)\"\n >\u2605</span>\n }\n @if (rateValue) {\n <span class=\"rtsee-rating-number\" itemprop=\"ratingValue\">{{ rateValue | number:'1.1-1' }}</span>\n }\n</div>\n" }]
|
|
1969
1969
|
}], propDecorators: { config: [{
|
|
1970
1970
|
type: Input
|
|
1971
1971
|
}], rate: [{
|
|
@@ -2122,7 +2122,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
2122
2122
|
}] } });
|
|
2123
2123
|
|
|
2124
2124
|
class MediaWidgetComponent {
|
|
2125
|
-
constructor() {
|
|
2125
|
+
constructor(cdr) {
|
|
2126
|
+
this.cdr = cdr;
|
|
2126
2127
|
this.showCost = true;
|
|
2127
2128
|
this.visibleImages = [];
|
|
2128
2129
|
this.hiddenCount = 0;
|
|
@@ -2130,6 +2131,7 @@ class MediaWidgetComponent {
|
|
|
2130
2131
|
this.downloadingUrl = null;
|
|
2131
2132
|
this.loadedImageUrls = new Set();
|
|
2132
2133
|
this.erroredImageUrls = new Set();
|
|
2134
|
+
this.preloadingImageUrls = new Set();
|
|
2133
2135
|
this.MAX_GRID = 4;
|
|
2134
2136
|
}
|
|
2135
2137
|
ngOnInit() {
|
|
@@ -2142,26 +2144,102 @@ class MediaWidgetComponent {
|
|
|
2142
2144
|
this.updateVisibleImages();
|
|
2143
2145
|
}
|
|
2144
2146
|
}
|
|
2145
|
-
|
|
2147
|
+
get isAiGenerated() {
|
|
2148
|
+
return Boolean(this.message?.from?.isAgent ||
|
|
2149
|
+
this.message?.cost ||
|
|
2150
|
+
this.message?.data?.flowId ||
|
|
2151
|
+
this.message?.data?.requestId ||
|
|
2152
|
+
this.message?.data?.awaitingGeneration);
|
|
2153
|
+
}
|
|
2154
|
+
get isAwaitingGeneration() {
|
|
2155
|
+
return !this.hasImages && !this.hasVideo;
|
|
2156
|
+
}
|
|
2157
|
+
get awaitingPlaceholderText() {
|
|
2158
|
+
return this.message?.data?.placeholderText || 'Generating image...';
|
|
2159
|
+
}
|
|
2160
|
+
/** Downsized version for rendering/export, the original otherwise */
|
|
2146
2161
|
previewUrl(img) {
|
|
2147
2162
|
return img.smallVersionUrl || img.url;
|
|
2148
2163
|
}
|
|
2164
|
+
/**
|
|
2165
|
+
* URL bound to the <img> element:
|
|
2166
|
+
* - While the full-size image is already loaded and `smallVersionUrl` is being preloaded,
|
|
2167
|
+
* keep displaying the loaded full-size `img.url` so there is no blank flicker,
|
|
2168
|
+
* then swap to `img.smallVersionUrl` as soon as it finishes preloading.
|
|
2169
|
+
*/
|
|
2170
|
+
displayUrl(img) {
|
|
2171
|
+
if (img.smallVersionUrl) {
|
|
2172
|
+
if (this.loadedImageUrls.has(img.smallVersionUrl)) {
|
|
2173
|
+
return img.smallVersionUrl;
|
|
2174
|
+
}
|
|
2175
|
+
if (this.loadedImageUrls.has(img.url)) {
|
|
2176
|
+
this.preloadSmallVersion(img.smallVersionUrl);
|
|
2177
|
+
return img.url;
|
|
2178
|
+
}
|
|
2179
|
+
return img.smallVersionUrl;
|
|
2180
|
+
}
|
|
2181
|
+
return img.url;
|
|
2182
|
+
}
|
|
2183
|
+
/**
|
|
2184
|
+
* True while the full-size image is being compressed/uploaded by ImageCropper/Uploader
|
|
2185
|
+
* or while the resulting `smallVersionUrl` is preloading to replace the full-size image.
|
|
2186
|
+
*/
|
|
2187
|
+
isProcessingImage(img) {
|
|
2188
|
+
const optimizingMessage = Boolean(this.message?.data?.isOptimizingImages ||
|
|
2189
|
+
this.messenger?.isOptimizingMessageImages?.(this.message?.id));
|
|
2190
|
+
if (optimizingMessage && !img.smallVersionUrl) {
|
|
2191
|
+
return true;
|
|
2192
|
+
}
|
|
2193
|
+
if (img.smallVersionUrl &&
|
|
2194
|
+
this.loadedImageUrls.has(img.url) &&
|
|
2195
|
+
!this.loadedImageUrls.has(img.smallVersionUrl) &&
|
|
2196
|
+
!this.erroredImageUrls.has(img.smallVersionUrl)) {
|
|
2197
|
+
return true;
|
|
2198
|
+
}
|
|
2199
|
+
return false;
|
|
2200
|
+
}
|
|
2149
2201
|
isImageLoaded(img) {
|
|
2150
|
-
const url = this.
|
|
2202
|
+
const url = this.displayUrl(img);
|
|
2151
2203
|
return this.loadedImageUrls.has(url);
|
|
2152
2204
|
}
|
|
2153
2205
|
isImageError(img) {
|
|
2154
|
-
const url = this.
|
|
2206
|
+
const url = this.displayUrl(img);
|
|
2155
2207
|
return this.erroredImageUrls.has(url);
|
|
2156
2208
|
}
|
|
2157
2209
|
onImageLoad(img) {
|
|
2158
|
-
const url = this.
|
|
2210
|
+
const url = this.displayUrl(img);
|
|
2159
2211
|
this.loadedImageUrls.add(url);
|
|
2212
|
+
if (img.smallVersionUrl && url === img.url && !this.loadedImageUrls.has(img.smallVersionUrl)) {
|
|
2213
|
+
this.preloadSmallVersion(img.smallVersionUrl);
|
|
2214
|
+
}
|
|
2160
2215
|
}
|
|
2161
2216
|
onImageError(img) {
|
|
2162
|
-
const url = this.
|
|
2217
|
+
const url = this.displayUrl(img);
|
|
2163
2218
|
this.erroredImageUrls.add(url);
|
|
2164
2219
|
}
|
|
2220
|
+
preloadSmallVersion(smallUrl) {
|
|
2221
|
+
if (typeof window === 'undefined' ||
|
|
2222
|
+
!smallUrl ||
|
|
2223
|
+
this.loadedImageUrls.has(smallUrl) ||
|
|
2224
|
+
this.preloadingImageUrls.has(smallUrl)) {
|
|
2225
|
+
return;
|
|
2226
|
+
}
|
|
2227
|
+
this.preloadingImageUrls.add(smallUrl);
|
|
2228
|
+
const preloader = new Image();
|
|
2229
|
+
preloader.onload = () => {
|
|
2230
|
+
this.preloadingImageUrls.delete(smallUrl);
|
|
2231
|
+
this.loadedImageUrls.add(smallUrl);
|
|
2232
|
+
this.cdr.markForCheck();
|
|
2233
|
+
this.cdr.detectChanges();
|
|
2234
|
+
};
|
|
2235
|
+
preloader.onerror = () => {
|
|
2236
|
+
this.preloadingImageUrls.delete(smallUrl);
|
|
2237
|
+
this.erroredImageUrls.add(smallUrl);
|
|
2238
|
+
this.cdr.markForCheck();
|
|
2239
|
+
this.cdr.detectChanges();
|
|
2240
|
+
};
|
|
2241
|
+
preloader.src = smallUrl;
|
|
2242
|
+
}
|
|
2165
2243
|
async downloadOriginal(event, img) {
|
|
2166
2244
|
event.stopPropagation();
|
|
2167
2245
|
event.preventDefault();
|
|
@@ -2215,11 +2293,12 @@ class MediaWidgetComponent {
|
|
|
2215
2293
|
sendToIllustrator(event, img) {
|
|
2216
2294
|
event.stopPropagation();
|
|
2217
2295
|
event.preventDefault();
|
|
2218
|
-
|
|
2219
|
-
|
|
2296
|
+
const targetUrl = this.previewUrl(img);
|
|
2297
|
+
if (typeof window !== 'undefined' && targetUrl) {
|
|
2298
|
+
// Use the web-optimized URL (smallVersionUrl when available) for Illustrator & Story Editor
|
|
2220
2299
|
window.dispatchEvent(new CustomEvent(RTSeeIllustratorEvents.SET_IMAGE_FOR_REVIEW, {
|
|
2221
2300
|
detail: {
|
|
2222
|
-
imageUrl:
|
|
2301
|
+
imageUrl: targetUrl,
|
|
2223
2302
|
prompt: img.name || (typeof this.message.text === 'string' ? this.message.text : '') || '',
|
|
2224
2303
|
source: 'messenger',
|
|
2225
2304
|
},
|
|
@@ -2229,11 +2308,12 @@ class MediaWidgetComponent {
|
|
|
2229
2308
|
addToContext(event, img) {
|
|
2230
2309
|
event.stopPropagation();
|
|
2231
2310
|
event.preventDefault();
|
|
2232
|
-
|
|
2311
|
+
const targetUrl = this.previewUrl(img);
|
|
2312
|
+
if (typeof window !== 'undefined' && targetUrl) {
|
|
2233
2313
|
window.dispatchEvent(new CustomEvent(RTSeeIllustratorEvents.ADD_IMAGE_TO_CONTEXT, {
|
|
2234
2314
|
detail: {
|
|
2235
2315
|
id: 'chat-img-' + Math.random().toString(36).substring(2, 9),
|
|
2236
|
-
imageUrl:
|
|
2316
|
+
imageUrl: targetUrl,
|
|
2237
2317
|
title: img.name || 'Chat image',
|
|
2238
2318
|
description: (typeof this.message.text === 'string' ? this.message.text : '') || '',
|
|
2239
2319
|
visualDescription: '',
|
|
@@ -2244,7 +2324,11 @@ class MediaWidgetComponent {
|
|
|
2244
2324
|
}
|
|
2245
2325
|
}
|
|
2246
2326
|
updateVisibleImages() {
|
|
2247
|
-
const
|
|
2327
|
+
const rawImages = this.message?.images || [];
|
|
2328
|
+
// AI-generated messages only show a single image; user messages can show multiple images
|
|
2329
|
+
const all = this.isAiGenerated && rawImages.length > 1
|
|
2330
|
+
? [rawImages[rawImages.length - 1]]
|
|
2331
|
+
: rawImages;
|
|
2248
2332
|
if (this.showAll || all.length <= this.MAX_GRID) {
|
|
2249
2333
|
this.visibleImages = all;
|
|
2250
2334
|
this.hiddenCount = 0;
|
|
@@ -2253,27 +2337,33 @@ class MediaWidgetComponent {
|
|
|
2253
2337
|
this.visibleImages = all.slice(0, this.MAX_GRID);
|
|
2254
2338
|
this.hiddenCount = all.length - this.MAX_GRID;
|
|
2255
2339
|
}
|
|
2340
|
+
for (const img of this.visibleImages) {
|
|
2341
|
+
if (img.smallVersionUrl && this.loadedImageUrls.has(img.url) && !this.loadedImageUrls.has(img.smallVersionUrl)) {
|
|
2342
|
+
this.preloadSmallVersion(img.smallVersionUrl);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2256
2345
|
}
|
|
2257
2346
|
notifyRequestedGeneration() {
|
|
2258
2347
|
const reqId = this.message?.data?.requestId;
|
|
2259
|
-
|
|
2348
|
+
const optimizedUrl = this.visibleImages[0]?.smallVersionUrl;
|
|
2349
|
+
if (reqId && optimizedUrl && typeof window !== 'undefined') {
|
|
2260
2350
|
window.dispatchEvent(new CustomEvent(RTSeeIllustratorEvents.REQUESTED_GENERATION_SUCCEED, {
|
|
2261
2351
|
detail: {
|
|
2262
2352
|
requestId: reqId,
|
|
2263
|
-
imageUrl:
|
|
2353
|
+
imageUrl: optimizedUrl,
|
|
2264
2354
|
messageId: this.message.id,
|
|
2265
2355
|
chatId: this.chat?.id,
|
|
2266
2356
|
},
|
|
2267
2357
|
}));
|
|
2268
2358
|
}
|
|
2269
2359
|
}
|
|
2270
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MediaWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2271
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MediaWidgetComponent, isStandalone: true, selector: "rtsee-media-widget", inputs: { message: "message", messenger: "messenger", chat: "chat", showCost: "showCost" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-media-widget\">\n <!-- Video player -->\n @if (message.video) {\n <div class=\"rts-media-video\">\n <video\n controls\n playsinline\n preload=\"metadata\"\n [src]=\"message.video.url\"\n class=\"rts-video-player\"\n >\n Your browser does not support video playback.\n </video>\n </div>\n }\n\n <!-- Image grid -->\n @if (hasImages) {\n <div class=\"rts-media-images\" [ngClass]=\"gridClass\">\n @for (img of visibleImages; track img.id || img.url) {\n <div class=\"rts-media-image-wrapper\" [class.rts-image-loaded]=\"isImageLoaded(img)\">\n <!-- Media Placeholder (preview before image loads) -->\n @if (!isImageLoaded(img)) {\n <div class=\"rts-media-placeholder\" [class.rts-placeholder-error]=\"isImageError(img)\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n @if (isImageError(img)) {\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">broken_image</span>\n <span class=\"rts-media-placeholder-text\">Failed to load</span>\n } @else {\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ img.name || 'Loading media preview...' }}</span>\n }\n </div>\n </div>\n }\n\n <img\n [src]=\"previewUrl(img)\"\n [alt]=\"img.name\"\n class=\"rts-media-image\"\n [class.rts-media-image-loaded]=\"isImageLoaded(img)\"\n (load)=\"onImageLoad(img)\"\n (error)=\"onImageError(img)\"\n loading=\"lazy\"\n />\n\n @if (isImageLoaded(img)) {\n <button\n type=\"button\"\n class=\"rts-media-btn-download\"\n [class.rts-downloading]=\"downloadingUrl === img.url\"\n title=\"Download original image\"\n aria-label=\"Download original image\"\n (click)=\"downloadOriginal($event, img)\"\n >\n <i class=\"pi\" [ngClass]=\"downloadingUrl === img.url ? 'pi-spin pi-spinner' : 'pi-download'\"></i>\n </button>\n <div class=\"rts-media-image-actions\">\n <button\n type=\"button\"\n class=\"rts-media-btn-paint\"\n title=\"Send image to Illustrator (Review & Iterate)\"\n (click)=\"sendToIllustrator($event, img)\"\n >\n <i class=\"pi pi-palette\"></i>\n <span>+ paint</span>\n </button>\n <button\n type=\"button\"\n class=\"rts-media-btn-context\"\n title=\"Add image to Illustrator context references\"\n (click)=\"addToContext($event, img)\"\n >\n <i class=\"pi pi-plus\"></i>\n <span>+ context</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Show more / less toggle -->\n @if (hiddenCount > 0 || showAll) {\n <button class=\"rts-media-toggle\" (click)=\"toggleShowAll()\">\n {{ showAll ? 'Show less' : 'Show ' + hiddenCount + ' more' }}\n </button>\n }\n\n <!-- Cost display (optional, disabled when nested inside agentic widget) -->\n @if (showCost && message.cost) {\n <div class=\"rts-media-cost\">\n <rtsee-cost-display [cost]=\"message.cost\"></rtsee-cost-display>\n </div>\n }\n</div>\n", styles: [".rts-media-widget{max-width:100%}.rts-media-video{border-radius:8px;overflow:hidden;margin-bottom:6px;aspect-ratio:16/9;background:#000}.rts-video-player{width:100%;height:100%;max-height:360px;border-radius:8px;background:#000;display:block}.rts-media-images{display:grid;gap:4px;border-radius:8px;overflow:hidden;margin-bottom:4px}.rts-media-grid-1{grid-template-columns:1fr}.rts-media-grid-1 .rts-media-image-wrapper{min-height:220px;aspect-ratio:16/10}.rts-media-grid-1 .rts-media-image-wrapper.rts-image-loaded{min-height:0;aspect-ratio:auto}.rts-media-grid-2{grid-template-columns:1fr 1fr}.rts-media-grid-2 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-grid-4{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}.rts-media-grid-4 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-image-wrapper{position:relative;overflow:hidden;border-radius:6px;background:var(--rts-bg-secondary, #1e1e2e);display:flex;align-items:center;justify-content:center}.rts-media-placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2af5,#12121cfa);border:1px solid rgba(255,255,255,.06);border-radius:6px;z-index:2;overflow:hidden;pointer-events:none}.rts-media-placeholder .rts-media-placeholder-shimmer{position:absolute;top:0;left:-150%;width:150%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.03) 30%,rgba(168,85,247,.12) 50%,rgba(255,255,255,.03) 70%,transparent 100%);animation:rts-media-shimmer 2.2s infinite ease-in-out}.rts-media-placeholder .rts-media-placeholder-content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;text-align:center;max-width:90%}.rts-media-placeholder .rts-media-placeholder-icon-wrap{width:42px;height:42px;border-radius:50%;background:#6c5ce726;border:1px solid rgba(168,85,247,.35);display:flex;align-items:center;justify-content:center;animation:rts-media-pulse 2s infinite ease-in-out;box-shadow:0 4px 16px #6c5ce733}.rts-media-placeholder .rts-media-placeholder-icon{font-size:22px;color:var(--rts-accent-light, #c084fc)}.rts-media-placeholder .rts-media-placeholder-text{font-size:11px;font-weight:500;color:var(--rts-text-muted, #94a3b8);max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon-wrap{background:#ef444426;border-color:#ef444459;animation:none;box-shadow:none}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon{color:#ef4444}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-text{color:#f87171}@keyframes rts-media-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes rts-media-pulse{0%,to{transform:scale(1);opacity:.85}50%{transform:scale(1.08);opacity:1;box-shadow:0 0 16px #a855f766}}.rts-media-image-actions{position:absolute;top:8px;right:8px;z-index:5;display:inline-flex;align-items:center;gap:6px}.rts-media-btn-paint{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#e9d5ff;border:1px solid rgba(168,85,247,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-paint i{font-size:11px;color:#c084fc}.rts-media-btn-paint span{line-height:1}.rts-media-btn-paint:hover{background:#9333eae6;color:#fff;border-color:#a855f7;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #a855f773}.rts-media-btn-paint:hover i{color:#fff}.rts-media-btn-paint:active{transform:translateY(0) scale(.98)}.rts-media-btn-context{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#bae6fd;border:1px solid rgba(56,189,248,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-context i{font-size:11px;color:#38bdf8}.rts-media-btn-context span{line-height:1}.rts-media-btn-context:hover{background:#0ea5e9e6;color:#fff;border-color:#38bdf8;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #38bdf873}.rts-media-btn-context:hover i{color:#fff}.rts-media-btn-context:active{transform:translateY(0) scale(.98)}.rts-media-btn-download{position:absolute;left:8px;bottom:8px;z-index:5;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#d1fae5;border:1px solid rgba(52,211,153,.45);border-radius:50%;cursor:pointer;opacity:.85;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-download i{font-size:12px;color:#34d399}.rts-media-btn-download:hover{opacity:1;background:#10b981e6;border-color:#34d399;transform:translateY(-1px) scale(1.08);box-shadow:0 4px 12px #34d39973}.rts-media-btn-download:hover i{color:#fff}.rts-media-btn-download:active{transform:translateY(0) scale(.96)}.rts-media-btn-download.rts-downloading{cursor:progress;opacity:1}.rts-media-image{width:100%;height:100%;max-height:280px;object-fit:cover;display:block;opacity:0;transition:opacity .25s ease-out,transform .2s ease;cursor:pointer}.rts-media-image.rts-media-image-loaded{opacity:1}.rts-media-image:hover{transform:scale(1.02)}.rts-media-grid-1 .rts-media-image{height:auto;max-height:400px;object-fit:contain}.rts-media-toggle{display:block;width:100%;padding:6px 0;border:none;background:none;color:var(--rts-agent-accent, #8b5cf6);font-size:12px;font-weight:500;cursor:pointer;text-align:center;transition:opacity .15s ease}.rts-media-toggle:hover{opacity:.8}.rts-media-cost{display:flex;justify-content:flex-end;padding-top:4px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CostDisplayComponent, selector: "rtsee-cost-display", inputs: ["cost"] }] }); }
|
|
2360
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MediaWidgetComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2361
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MediaWidgetComponent, isStandalone: true, selector: "rtsee-media-widget", inputs: { message: "message", messenger: "messenger", chat: "chat", showCost: "showCost" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-media-widget\">\n <!-- Video player -->\n @if (message.video) {\n <div class=\"rts-media-video\">\n <video\n controls\n playsinline\n preload=\"metadata\"\n [src]=\"message.video.url\"\n class=\"rts-video-player\"\n >\n Your browser does not support video playback.\n </video>\n </div>\n }\n\n <!-- Awaiting AI image generation preloader -->\n @if (isAwaitingGeneration) {\n <div class=\"rts-media-images rts-media-grid-1\">\n <div class=\"rts-media-image-wrapper\">\n <div class=\"rts-media-placeholder\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ awaitingPlaceholderText }}</span>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Image grid -->\n @if (hasImages) {\n <div class=\"rts-media-images\" [ngClass]=\"gridClass\">\n @for (img of visibleImages; track img.id || $index) {\n <div class=\"rts-media-image-wrapper\" [class.rts-image-loaded]=\"isImageLoaded(img)\">\n <!-- Media Placeholder (preview before image loads) -->\n @if (!isImageLoaded(img)) {\n <div class=\"rts-media-placeholder\" [class.rts-placeholder-error]=\"isImageError(img)\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n @if (isImageError(img)) {\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">broken_image</span>\n <span class=\"rts-media-placeholder-text\">Failed to load</span>\n } @else {\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ img.name || 'Loading media preview...' }}</span>\n }\n </div>\n </div>\n }\n\n <img\n [src]=\"displayUrl(img)\"\n [alt]=\"img.name\"\n class=\"rts-media-image\"\n [class.rts-media-image-loaded]=\"isImageLoaded(img)\"\n [class.rts-media-image-processing]=\"isImageLoaded(img) && isProcessingImage(img)\"\n (load)=\"onImageLoad(img)\"\n (error)=\"onImageError(img)\"\n loading=\"lazy\"\n />\n\n @if (isImageLoaded(img) && isProcessingImage(img)) {\n <div class=\"rts-media-processing-overlay\">\n <div class=\"rts-media-processing-badge\">\n <span class=\"rts-media-processing-spinner\"></span>\n <span class=\"rts-media-processing-text\">processing...</span>\n </div>\n </div>\n }\n\n @if (isImageLoaded(img) && !isProcessingImage(img)) {\n <button\n type=\"button\"\n class=\"rts-media-btn-download\"\n [class.rts-downloading]=\"downloadingUrl === img.url\"\n title=\"Download original image\"\n aria-label=\"Download original image\"\n (click)=\"downloadOriginal($event, img)\"\n >\n <i class=\"pi\" [ngClass]=\"downloadingUrl === img.url ? 'pi-spin pi-spinner' : 'pi-download'\"></i>\n </button>\n <div class=\"rts-media-image-actions\">\n <button\n type=\"button\"\n class=\"rts-media-btn-paint\"\n title=\"Send image to Illustrator (Review & Iterate)\"\n (click)=\"sendToIllustrator($event, img)\"\n >\n <i class=\"pi pi-palette\"></i>\n <span>+ paint</span>\n </button>\n <button\n type=\"button\"\n class=\"rts-media-btn-context\"\n title=\"Add image to Illustrator context references\"\n (click)=\"addToContext($event, img)\"\n >\n <i class=\"pi pi-plus\"></i>\n <span>+ context</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Show more / less toggle -->\n @if (hiddenCount > 0 || showAll) {\n <button class=\"rts-media-toggle\" (click)=\"toggleShowAll()\">\n {{ showAll ? 'Show less' : 'Show ' + hiddenCount + ' more' }}\n </button>\n }\n\n <!-- Cost display (optional, disabled when nested inside agentic widget) -->\n @if (showCost && message.cost) {\n <div class=\"rts-media-cost\">\n <rtsee-cost-display [cost]=\"message.cost\"></rtsee-cost-display>\n </div>\n }\n</div>\n", styles: [".rts-media-widget{max-width:100%}.rts-media-video{border-radius:8px;overflow:hidden;margin-bottom:6px;aspect-ratio:16/9;background:#000}.rts-video-player{width:100%;height:100%;max-height:360px;border-radius:8px;background:#000;display:block}.rts-media-images{display:grid;gap:4px;border-radius:8px;overflow:hidden;margin-bottom:4px}.rts-media-grid-1{grid-template-columns:1fr}.rts-media-grid-1 .rts-media-image-wrapper{min-height:220px;aspect-ratio:16/10}.rts-media-grid-1 .rts-media-image-wrapper.rts-image-loaded{min-height:0;aspect-ratio:auto}.rts-media-grid-2{grid-template-columns:1fr 1fr}.rts-media-grid-2 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-grid-4{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}.rts-media-grid-4 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-image-wrapper{position:relative;overflow:hidden;border-radius:6px;background:var(--rts-bg-secondary, #1e1e2e);display:flex;align-items:center;justify-content:center}.rts-media-placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2af5,#12121cfa);border:1px solid rgba(255,255,255,.06);border-radius:6px;z-index:2;overflow:hidden;pointer-events:none}.rts-media-placeholder .rts-media-placeholder-shimmer{position:absolute;top:0;left:-150%;width:150%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.03) 30%,rgba(168,85,247,.12) 50%,rgba(255,255,255,.03) 70%,transparent 100%);animation:rts-media-shimmer 2.2s infinite ease-in-out}.rts-media-placeholder .rts-media-placeholder-content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;text-align:center;max-width:90%}.rts-media-placeholder .rts-media-placeholder-icon-wrap{width:42px;height:42px;border-radius:50%;background:#6c5ce726;border:1px solid rgba(168,85,247,.35);display:flex;align-items:center;justify-content:center;animation:rts-media-pulse 2s infinite ease-in-out;box-shadow:0 4px 16px #6c5ce733}.rts-media-placeholder .rts-media-placeholder-icon{font-size:22px;color:var(--rts-accent-light, #c084fc)}.rts-media-placeholder .rts-media-placeholder-text{font-size:11px;font-weight:500;color:var(--rts-text-muted, #94a3b8);max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon-wrap{background:#ef444426;border-color:#ef444459;animation:none;box-shadow:none}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon{color:#ef4444}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-text{color:#f87171}@keyframes rts-media-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes rts-media-pulse{0%,to{transform:scale(1);opacity:.85}50%{transform:scale(1.08);opacity:1;box-shadow:0 0 16px #a855f766}}.rts-media-image-actions{position:absolute;top:8px;right:8px;z-index:5;display:inline-flex;align-items:center;gap:6px}.rts-media-btn-paint{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#e9d5ff;border:1px solid rgba(168,85,247,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-paint i{font-size:11px;color:#c084fc}.rts-media-btn-paint span{line-height:1}.rts-media-btn-paint:hover{background:#9333eae6;color:#fff;border-color:#a855f7;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #a855f773}.rts-media-btn-paint:hover i{color:#fff}.rts-media-btn-paint:active{transform:translateY(0) scale(.98)}.rts-media-btn-context{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#bae6fd;border:1px solid rgba(56,189,248,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-context i{font-size:11px;color:#38bdf8}.rts-media-btn-context span{line-height:1}.rts-media-btn-context:hover{background:#0ea5e9e6;color:#fff;border-color:#38bdf8;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #38bdf873}.rts-media-btn-context:hover i{color:#fff}.rts-media-btn-context:active{transform:translateY(0) scale(.98)}.rts-media-btn-download{position:absolute;left:8px;bottom:8px;z-index:5;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#d1fae5;border:1px solid rgba(52,211,153,.45);border-radius:50%;cursor:pointer;opacity:.85;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-download i{font-size:12px;color:#34d399}.rts-media-btn-download:hover{opacity:1;background:#10b981e6;border-color:#34d399;transform:translateY(-1px) scale(1.08);box-shadow:0 4px 12px #34d39973}.rts-media-btn-download:hover i{color:#fff}.rts-media-btn-download:active{transform:translateY(0) scale(.96)}.rts-media-btn-download.rts-downloading{cursor:progress;opacity:1}.rts-media-image{width:100%;height:100%;max-height:280px;object-fit:cover;display:block;opacity:0;transition:opacity .25s ease-out,transform .2s ease;cursor:pointer}.rts-media-image.rts-media-image-loaded{opacity:1}.rts-media-image.rts-media-image-processing{filter:brightness(.75)}.rts-media-image:hover{transform:scale(1.02)}.rts-media-processing-overlay{position:absolute;inset:0;z-index:4;display:flex;align-items:center;justify-content:center;background:#0f0f1959;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);pointer-events:none}.rts-media-processing-badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;background:#12121ce0;border:1px solid rgba(168,85,247,.45);box-shadow:0 4px 16px #00000073}.rts-media-processing-spinner{width:14px;height:14px;border-radius:50%;border:2px solid rgba(192,132,252,.28);border-top-color:#c084fc;animation:rts-media-spin .8s linear infinite}.rts-media-processing-text{font-size:12px;font-weight:600;color:#f3e8ff;letter-spacing:.02em}@keyframes rts-media-spin{to{transform:rotate(360deg)}}.rts-media-grid-1 .rts-media-image{height:auto;max-height:400px;object-fit:contain}.rts-media-toggle{display:block;width:100%;padding:6px 0;border:none;background:none;color:var(--rts-agent-accent, #8b5cf6);font-size:12px;font-weight:500;cursor:pointer;text-align:center;transition:opacity .15s ease}.rts-media-toggle:hover{opacity:.8}.rts-media-cost{display:flex;justify-content:flex-end;padding-top:4px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CostDisplayComponent, selector: "rtsee-cost-display", inputs: ["cost"] }] }); }
|
|
2272
2362
|
}
|
|
2273
2363
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MediaWidgetComponent, decorators: [{
|
|
2274
2364
|
type: Component,
|
|
2275
|
-
args: [{ selector: 'rtsee-media-widget', standalone: true, imports: [NgClass, CostDisplayComponent], template: "<div class=\"rts-media-widget\">\n <!-- Video player -->\n @if (message.video) {\n <div class=\"rts-media-video\">\n <video\n controls\n playsinline\n preload=\"metadata\"\n [src]=\"message.video.url\"\n class=\"rts-video-player\"\n >\n Your browser does not support video playback.\n </video>\n </div>\n }\n\n <!-- Image grid -->\n @if (hasImages) {\n <div class=\"rts-media-images\" [ngClass]=\"gridClass\">\n @for (img of visibleImages; track img.id || img.url) {\n <div class=\"rts-media-image-wrapper\" [class.rts-image-loaded]=\"isImageLoaded(img)\">\n <!-- Media Placeholder (preview before image loads) -->\n @if (!isImageLoaded(img)) {\n <div class=\"rts-media-placeholder\" [class.rts-placeholder-error]=\"isImageError(img)\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n @if (isImageError(img)) {\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">broken_image</span>\n <span class=\"rts-media-placeholder-text\">Failed to load</span>\n } @else {\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ img.name || 'Loading media preview...' }}</span>\n }\n </div>\n </div>\n }\n\n <img\n [src]=\"previewUrl(img)\"\n [alt]=\"img.name\"\n class=\"rts-media-image\"\n [class.rts-media-image-loaded]=\"isImageLoaded(img)\"\n (load)=\"onImageLoad(img)\"\n (error)=\"onImageError(img)\"\n loading=\"lazy\"\n />\n\n @if (isImageLoaded(img)) {\n <button\n type=\"button\"\n class=\"rts-media-btn-download\"\n [class.rts-downloading]=\"downloadingUrl === img.url\"\n title=\"Download original image\"\n aria-label=\"Download original image\"\n (click)=\"downloadOriginal($event, img)\"\n >\n <i class=\"pi\" [ngClass]=\"downloadingUrl === img.url ? 'pi-spin pi-spinner' : 'pi-download'\"></i>\n </button>\n <div class=\"rts-media-image-actions\">\n <button\n type=\"button\"\n class=\"rts-media-btn-paint\"\n title=\"Send image to Illustrator (Review & Iterate)\"\n (click)=\"sendToIllustrator($event, img)\"\n >\n <i class=\"pi pi-palette\"></i>\n <span>+ paint</span>\n </button>\n <button\n type=\"button\"\n class=\"rts-media-btn-context\"\n title=\"Add image to Illustrator context references\"\n (click)=\"addToContext($event, img)\"\n >\n <i class=\"pi pi-plus\"></i>\n <span>+ context</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Show more / less toggle -->\n @if (hiddenCount > 0 || showAll) {\n <button class=\"rts-media-toggle\" (click)=\"toggleShowAll()\">\n {{ showAll ? 'Show less' : 'Show ' + hiddenCount + ' more' }}\n </button>\n }\n\n <!-- Cost display (optional, disabled when nested inside agentic widget) -->\n @if (showCost && message.cost) {\n <div class=\"rts-media-cost\">\n <rtsee-cost-display [cost]=\"message.cost\"></rtsee-cost-display>\n </div>\n }\n</div>\n", styles: [".rts-media-widget{max-width:100%}.rts-media-video{border-radius:8px;overflow:hidden;margin-bottom:6px;aspect-ratio:16/9;background:#000}.rts-video-player{width:100%;height:100%;max-height:360px;border-radius:8px;background:#000;display:block}.rts-media-images{display:grid;gap:4px;border-radius:8px;overflow:hidden;margin-bottom:4px}.rts-media-grid-1{grid-template-columns:1fr}.rts-media-grid-1 .rts-media-image-wrapper{min-height:220px;aspect-ratio:16/10}.rts-media-grid-1 .rts-media-image-wrapper.rts-image-loaded{min-height:0;aspect-ratio:auto}.rts-media-grid-2{grid-template-columns:1fr 1fr}.rts-media-grid-2 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-grid-4{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}.rts-media-grid-4 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-image-wrapper{position:relative;overflow:hidden;border-radius:6px;background:var(--rts-bg-secondary, #1e1e2e);display:flex;align-items:center;justify-content:center}.rts-media-placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2af5,#12121cfa);border:1px solid rgba(255,255,255,.06);border-radius:6px;z-index:2;overflow:hidden;pointer-events:none}.rts-media-placeholder .rts-media-placeholder-shimmer{position:absolute;top:0;left:-150%;width:150%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.03) 30%,rgba(168,85,247,.12) 50%,rgba(255,255,255,.03) 70%,transparent 100%);animation:rts-media-shimmer 2.2s infinite ease-in-out}.rts-media-placeholder .rts-media-placeholder-content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;text-align:center;max-width:90%}.rts-media-placeholder .rts-media-placeholder-icon-wrap{width:42px;height:42px;border-radius:50%;background:#6c5ce726;border:1px solid rgba(168,85,247,.35);display:flex;align-items:center;justify-content:center;animation:rts-media-pulse 2s infinite ease-in-out;box-shadow:0 4px 16px #6c5ce733}.rts-media-placeholder .rts-media-placeholder-icon{font-size:22px;color:var(--rts-accent-light, #c084fc)}.rts-media-placeholder .rts-media-placeholder-text{font-size:11px;font-weight:500;color:var(--rts-text-muted, #94a3b8);max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon-wrap{background:#ef444426;border-color:#ef444459;animation:none;box-shadow:none}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon{color:#ef4444}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-text{color:#f87171}@keyframes rts-media-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes rts-media-pulse{0%,to{transform:scale(1);opacity:.85}50%{transform:scale(1.08);opacity:1;box-shadow:0 0 16px #a855f766}}.rts-media-image-actions{position:absolute;top:8px;right:8px;z-index:5;display:inline-flex;align-items:center;gap:6px}.rts-media-btn-paint{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#e9d5ff;border:1px solid rgba(168,85,247,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-paint i{font-size:11px;color:#c084fc}.rts-media-btn-paint span{line-height:1}.rts-media-btn-paint:hover{background:#9333eae6;color:#fff;border-color:#a855f7;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #a855f773}.rts-media-btn-paint:hover i{color:#fff}.rts-media-btn-paint:active{transform:translateY(0) scale(.98)}.rts-media-btn-context{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#bae6fd;border:1px solid rgba(56,189,248,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-context i{font-size:11px;color:#38bdf8}.rts-media-btn-context span{line-height:1}.rts-media-btn-context:hover{background:#0ea5e9e6;color:#fff;border-color:#38bdf8;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #38bdf873}.rts-media-btn-context:hover i{color:#fff}.rts-media-btn-context:active{transform:translateY(0) scale(.98)}.rts-media-btn-download{position:absolute;left:8px;bottom:8px;z-index:5;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#d1fae5;border:1px solid rgba(52,211,153,.45);border-radius:50%;cursor:pointer;opacity:.85;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-download i{font-size:12px;color:#34d399}.rts-media-btn-download:hover{opacity:1;background:#10b981e6;border-color:#34d399;transform:translateY(-1px) scale(1.08);box-shadow:0 4px 12px #34d39973}.rts-media-btn-download:hover i{color:#fff}.rts-media-btn-download:active{transform:translateY(0) scale(.96)}.rts-media-btn-download.rts-downloading{cursor:progress;opacity:1}.rts-media-image{width:100%;height:100%;max-height:280px;object-fit:cover;display:block;opacity:0;transition:opacity .25s ease-out,transform .2s ease;cursor:pointer}.rts-media-image.rts-media-image-loaded{opacity:1}.rts-media-image:hover{transform:scale(1.02)}.rts-media-grid-1 .rts-media-image{height:auto;max-height:400px;object-fit:contain}.rts-media-toggle{display:block;width:100%;padding:6px 0;border:none;background:none;color:var(--rts-agent-accent, #8b5cf6);font-size:12px;font-weight:500;cursor:pointer;text-align:center;transition:opacity .15s ease}.rts-media-toggle:hover{opacity:.8}.rts-media-cost{display:flex;justify-content:flex-end;padding-top:4px}\n"] }]
|
|
2276
|
-
}], propDecorators: { message: [{
|
|
2365
|
+
args: [{ selector: 'rtsee-media-widget', standalone: true, imports: [NgClass, CostDisplayComponent], template: "<div class=\"rts-media-widget\">\n <!-- Video player -->\n @if (message.video) {\n <div class=\"rts-media-video\">\n <video\n controls\n playsinline\n preload=\"metadata\"\n [src]=\"message.video.url\"\n class=\"rts-video-player\"\n >\n Your browser does not support video playback.\n </video>\n </div>\n }\n\n <!-- Awaiting AI image generation preloader -->\n @if (isAwaitingGeneration) {\n <div class=\"rts-media-images rts-media-grid-1\">\n <div class=\"rts-media-image-wrapper\">\n <div class=\"rts-media-placeholder\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ awaitingPlaceholderText }}</span>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Image grid -->\n @if (hasImages) {\n <div class=\"rts-media-images\" [ngClass]=\"gridClass\">\n @for (img of visibleImages; track img.id || $index) {\n <div class=\"rts-media-image-wrapper\" [class.rts-image-loaded]=\"isImageLoaded(img)\">\n <!-- Media Placeholder (preview before image loads) -->\n @if (!isImageLoaded(img)) {\n <div class=\"rts-media-placeholder\" [class.rts-placeholder-error]=\"isImageError(img)\">\n <div class=\"rts-media-placeholder-shimmer\"></div>\n <div class=\"rts-media-placeholder-content\">\n @if (isImageError(img)) {\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">broken_image</span>\n <span class=\"rts-media-placeholder-text\">Failed to load</span>\n } @else {\n <div class=\"rts-media-placeholder-icon-wrap\">\n <span class=\"material-icons-outlined rts-media-placeholder-icon\">image</span>\n </div>\n <span class=\"rts-media-placeholder-text\">{{ img.name || 'Loading media preview...' }}</span>\n }\n </div>\n </div>\n }\n\n <img\n [src]=\"displayUrl(img)\"\n [alt]=\"img.name\"\n class=\"rts-media-image\"\n [class.rts-media-image-loaded]=\"isImageLoaded(img)\"\n [class.rts-media-image-processing]=\"isImageLoaded(img) && isProcessingImage(img)\"\n (load)=\"onImageLoad(img)\"\n (error)=\"onImageError(img)\"\n loading=\"lazy\"\n />\n\n @if (isImageLoaded(img) && isProcessingImage(img)) {\n <div class=\"rts-media-processing-overlay\">\n <div class=\"rts-media-processing-badge\">\n <span class=\"rts-media-processing-spinner\"></span>\n <span class=\"rts-media-processing-text\">processing...</span>\n </div>\n </div>\n }\n\n @if (isImageLoaded(img) && !isProcessingImage(img)) {\n <button\n type=\"button\"\n class=\"rts-media-btn-download\"\n [class.rts-downloading]=\"downloadingUrl === img.url\"\n title=\"Download original image\"\n aria-label=\"Download original image\"\n (click)=\"downloadOriginal($event, img)\"\n >\n <i class=\"pi\" [ngClass]=\"downloadingUrl === img.url ? 'pi-spin pi-spinner' : 'pi-download'\"></i>\n </button>\n <div class=\"rts-media-image-actions\">\n <button\n type=\"button\"\n class=\"rts-media-btn-paint\"\n title=\"Send image to Illustrator (Review & Iterate)\"\n (click)=\"sendToIllustrator($event, img)\"\n >\n <i class=\"pi pi-palette\"></i>\n <span>+ paint</span>\n </button>\n <button\n type=\"button\"\n class=\"rts-media-btn-context\"\n title=\"Add image to Illustrator context references\"\n (click)=\"addToContext($event, img)\"\n >\n <i class=\"pi pi-plus\"></i>\n <span>+ context</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Show more / less toggle -->\n @if (hiddenCount > 0 || showAll) {\n <button class=\"rts-media-toggle\" (click)=\"toggleShowAll()\">\n {{ showAll ? 'Show less' : 'Show ' + hiddenCount + ' more' }}\n </button>\n }\n\n <!-- Cost display (optional, disabled when nested inside agentic widget) -->\n @if (showCost && message.cost) {\n <div class=\"rts-media-cost\">\n <rtsee-cost-display [cost]=\"message.cost\"></rtsee-cost-display>\n </div>\n }\n</div>\n", styles: [".rts-media-widget{max-width:100%}.rts-media-video{border-radius:8px;overflow:hidden;margin-bottom:6px;aspect-ratio:16/9;background:#000}.rts-video-player{width:100%;height:100%;max-height:360px;border-radius:8px;background:#000;display:block}.rts-media-images{display:grid;gap:4px;border-radius:8px;overflow:hidden;margin-bottom:4px}.rts-media-grid-1{grid-template-columns:1fr}.rts-media-grid-1 .rts-media-image-wrapper{min-height:220px;aspect-ratio:16/10}.rts-media-grid-1 .rts-media-image-wrapper.rts-image-loaded{min-height:0;aspect-ratio:auto}.rts-media-grid-2{grid-template-columns:1fr 1fr}.rts-media-grid-2 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-grid-4{grid-template-columns:1fr 1fr;grid-template-rows:auto auto}.rts-media-grid-4 .rts-media-image-wrapper{aspect-ratio:1/1;min-height:120px}.rts-media-image-wrapper{position:relative;overflow:hidden;border-radius:6px;background:var(--rts-bg-secondary, #1e1e2e);display:flex;align-items:center;justify-content:center}.rts-media-placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#1a1a2af5,#12121cfa);border:1px solid rgba(255,255,255,.06);border-radius:6px;z-index:2;overflow:hidden;pointer-events:none}.rts-media-placeholder .rts-media-placeholder-shimmer{position:absolute;top:0;left:-150%;width:150%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.03) 30%,rgba(168,85,247,.12) 50%,rgba(255,255,255,.03) 70%,transparent 100%);animation:rts-media-shimmer 2.2s infinite ease-in-out}.rts-media-placeholder .rts-media-placeholder-content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;text-align:center;max-width:90%}.rts-media-placeholder .rts-media-placeholder-icon-wrap{width:42px;height:42px;border-radius:50%;background:#6c5ce726;border:1px solid rgba(168,85,247,.35);display:flex;align-items:center;justify-content:center;animation:rts-media-pulse 2s infinite ease-in-out;box-shadow:0 4px 16px #6c5ce733}.rts-media-placeholder .rts-media-placeholder-icon{font-size:22px;color:var(--rts-accent-light, #c084fc)}.rts-media-placeholder .rts-media-placeholder-text{font-size:11px;font-weight:500;color:var(--rts-text-muted, #94a3b8);max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon-wrap{background:#ef444426;border-color:#ef444459;animation:none;box-shadow:none}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-icon{color:#ef4444}.rts-media-placeholder.rts-placeholder-error .rts-media-placeholder-text{color:#f87171}@keyframes rts-media-shimmer{0%{transform:translate(0)}to{transform:translate(200%)}}@keyframes rts-media-pulse{0%,to{transform:scale(1);opacity:.85}50%{transform:scale(1.08);opacity:1;box-shadow:0 0 16px #a855f766}}.rts-media-image-actions{position:absolute;top:8px;right:8px;z-index:5;display:inline-flex;align-items:center;gap:6px}.rts-media-btn-paint{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#e9d5ff;border:1px solid rgba(168,85,247,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-paint i{font-size:11px;color:#c084fc}.rts-media-btn-paint span{line-height:1}.rts-media-btn-paint:hover{background:#9333eae6;color:#fff;border-color:#a855f7;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #a855f773}.rts-media-btn-paint:hover i{color:#fff}.rts-media-btn-paint:active{transform:translateY(0) scale(.98)}.rts-media-btn-context{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#bae6fd;border:1px solid rgba(56,189,248,.45);border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-context i{font-size:11px;color:#38bdf8}.rts-media-btn-context span{line-height:1}.rts-media-btn-context:hover{background:#0ea5e9e6;color:#fff;border-color:#38bdf8;transform:translateY(-1px) scale(1.04);box-shadow:0 4px 12px #38bdf873}.rts-media-btn-context:hover i{color:#fff}.rts-media-btn-context:active{transform:translateY(0) scale(.98)}.rts-media-btn-download{position:absolute;left:8px;bottom:8px;z-index:5;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;background:#12121cd9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#d1fae5;border:1px solid rgba(52,211,153,.45);border-radius:50%;cursor:pointer;opacity:.85;transition:all .2s cubic-bezier(.34,1.56,.64,1);box-shadow:0 2px 8px #00000080}.rts-media-btn-download i{font-size:12px;color:#34d399}.rts-media-btn-download:hover{opacity:1;background:#10b981e6;border-color:#34d399;transform:translateY(-1px) scale(1.08);box-shadow:0 4px 12px #34d39973}.rts-media-btn-download:hover i{color:#fff}.rts-media-btn-download:active{transform:translateY(0) scale(.96)}.rts-media-btn-download.rts-downloading{cursor:progress;opacity:1}.rts-media-image{width:100%;height:100%;max-height:280px;object-fit:cover;display:block;opacity:0;transition:opacity .25s ease-out,transform .2s ease;cursor:pointer}.rts-media-image.rts-media-image-loaded{opacity:1}.rts-media-image.rts-media-image-processing{filter:brightness(.75)}.rts-media-image:hover{transform:scale(1.02)}.rts-media-processing-overlay{position:absolute;inset:0;z-index:4;display:flex;align-items:center;justify-content:center;background:#0f0f1959;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);pointer-events:none}.rts-media-processing-badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;background:#12121ce0;border:1px solid rgba(168,85,247,.45);box-shadow:0 4px 16px #00000073}.rts-media-processing-spinner{width:14px;height:14px;border-radius:50%;border:2px solid rgba(192,132,252,.28);border-top-color:#c084fc;animation:rts-media-spin .8s linear infinite}.rts-media-processing-text{font-size:12px;font-weight:600;color:#f3e8ff;letter-spacing:.02em}@keyframes rts-media-spin{to{transform:rotate(360deg)}}.rts-media-grid-1 .rts-media-image{height:auto;max-height:400px;object-fit:contain}.rts-media-toggle{display:block;width:100%;padding:6px 0;border:none;background:none;color:var(--rts-agent-accent, #8b5cf6);font-size:12px;font-weight:500;cursor:pointer;text-align:center;transition:opacity .15s ease}.rts-media-toggle:hover{opacity:.8}.rts-media-cost{display:flex;justify-content:flex-end;padding-top:4px}\n"] }]
|
|
2366
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { message: [{
|
|
2277
2367
|
type: Input
|
|
2278
2368
|
}], messenger: [{
|
|
2279
2369
|
type: Input
|
|
@@ -2639,6 +2729,9 @@ class StorytellerStoryLinkStepComponent {
|
|
|
2639
2729
|
return this.story.storyId ? `/story/${this.story.storyId}` : '';
|
|
2640
2730
|
}
|
|
2641
2731
|
get kicker() {
|
|
2732
|
+
if (this.story.repairedGrammar !== undefined || this.story.updatedSlidesCount !== undefined) {
|
|
2733
|
+
return 'Story repaired';
|
|
2734
|
+
}
|
|
2642
2735
|
const language = this.story.language ? getStoryTranslatorLanguage(this.story.language) : undefined;
|
|
2643
2736
|
return language ? `Translated to ${language.nativeName}` : 'Your story is ready';
|
|
2644
2737
|
}
|
|
@@ -2658,7 +2751,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
2658
2751
|
type: Input
|
|
2659
2752
|
}] } });
|
|
2660
2753
|
|
|
2661
|
-
const SEARCH_DEBOUNCE_MS = 250;
|
|
2754
|
+
const SEARCH_DEBOUNCE_MS$1 = 250;
|
|
2662
2755
|
/**
|
|
2663
2756
|
* Story Translator step 1: pick a story (autocomplete by name) and the target language.
|
|
2664
2757
|
*/
|
|
@@ -2672,10 +2765,13 @@ class StoryTranslatorFormStepComponent {
|
|
|
2672
2765
|
storyQuery: new FormControl(''),
|
|
2673
2766
|
storyId: new FormControl('', Validators.required),
|
|
2674
2767
|
language: new FormControl('', Validators.required),
|
|
2768
|
+
fromScratch: new FormControl(false),
|
|
2675
2769
|
agentId: new FormControl('', Validators.required),
|
|
2676
2770
|
/* eslint-enable */
|
|
2677
2771
|
});
|
|
2678
2772
|
this.selectedStory = null;
|
|
2773
|
+
this.hasExistingTranslation = false;
|
|
2774
|
+
this.checkingTranslations = false;
|
|
2679
2775
|
this.suggestions = [];
|
|
2680
2776
|
this.suggestionsOpened = false;
|
|
2681
2777
|
this.highlightedIndex = 0;
|
|
@@ -2683,6 +2779,7 @@ class StoryTranslatorFormStepComponent {
|
|
|
2683
2779
|
this.searchError = null;
|
|
2684
2780
|
this.searchTimer = null;
|
|
2685
2781
|
this.searchRequestId = 0;
|
|
2782
|
+
this.translationCheckRequestId = 0;
|
|
2686
2783
|
this.onChangedBound = () => this.onWorkflowChanged();
|
|
2687
2784
|
}
|
|
2688
2785
|
get agents() {
|
|
@@ -2722,10 +2819,11 @@ class StoryTranslatorFormStepComponent {
|
|
|
2722
2819
|
// typing invalidates the previous selection
|
|
2723
2820
|
if (this.selectedStory) {
|
|
2724
2821
|
this.selectedStory = null;
|
|
2725
|
-
this.
|
|
2822
|
+
this.hasExistingTranslation = false;
|
|
2823
|
+
this.form.patchValue({ storyId: '', fromScratch: false }, { emitEvent: false });
|
|
2726
2824
|
}
|
|
2727
2825
|
this.suggestionsOpened = true;
|
|
2728
|
-
this.scheduleSearch(SEARCH_DEBOUNCE_MS);
|
|
2826
|
+
this.scheduleSearch(SEARCH_DEBOUNCE_MS$1);
|
|
2729
2827
|
}
|
|
2730
2828
|
onStoryKeydown(event) {
|
|
2731
2829
|
if (!this.suggestionsOpened || !this.suggestions.length) {
|
|
@@ -2759,20 +2857,29 @@ class StoryTranslatorFormStepComponent {
|
|
|
2759
2857
|
return;
|
|
2760
2858
|
}
|
|
2761
2859
|
this.selectedStory = story;
|
|
2762
|
-
this.form.patchValue({ storyId: story.id, storyQuery: story.name }, { emitEvent: false });
|
|
2860
|
+
this.form.patchValue({ storyId: story.id, storyQuery: story.name, fromScratch: false }, { emitEvent: false });
|
|
2763
2861
|
this.form.get('storyId')?.markAsTouched();
|
|
2764
2862
|
this.suggestionsOpened = false;
|
|
2863
|
+
void this.checkExistingTranslation();
|
|
2765
2864
|
}
|
|
2766
2865
|
clearStory() {
|
|
2767
2866
|
if (this.readonly) {
|
|
2768
2867
|
return;
|
|
2769
2868
|
}
|
|
2770
2869
|
this.selectedStory = null;
|
|
2771
|
-
this.
|
|
2870
|
+
this.hasExistingTranslation = false;
|
|
2871
|
+
this.form.patchValue({ storyId: '', storyQuery: '', fromScratch: false }, { emitEvent: false });
|
|
2772
2872
|
this.suggestionsOpened = true;
|
|
2773
2873
|
this.scheduleSearch(0);
|
|
2774
2874
|
setTimeout(() => this.storyInput?.nativeElement.focus());
|
|
2775
2875
|
}
|
|
2876
|
+
onLanguageChange() {
|
|
2877
|
+
if (this.readonly) {
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2880
|
+
this.form.get('fromScratch')?.setValue(false, { emitEvent: false });
|
|
2881
|
+
void this.checkExistingTranslation();
|
|
2882
|
+
}
|
|
2776
2883
|
onDocumentMouseDown(event) {
|
|
2777
2884
|
if (this.suggestionsOpened && !this.host.nativeElement.contains(event.target)) {
|
|
2778
2885
|
this.suggestionsOpened = false;
|
|
@@ -2791,6 +2898,7 @@ class StoryTranslatorFormStepComponent {
|
|
|
2791
2898
|
storyName: this.selectedStory.name,
|
|
2792
2899
|
language: this.form.get('language')?.value,
|
|
2793
2900
|
agentId: this.form.get('agentId')?.value,
|
|
2901
|
+
fromScratch: this.hasExistingTranslation ? !!this.form.get('fromScratch')?.value : false,
|
|
2794
2902
|
});
|
|
2795
2903
|
}
|
|
2796
2904
|
cancel() {
|
|
@@ -2852,7 +2960,19 @@ class StoryTranslatorFormStepComponent {
|
|
|
2852
2960
|
const output = this.step?.output;
|
|
2853
2961
|
if (output?.storyId) {
|
|
2854
2962
|
this.selectedStory = { id: output.storyId, name: output.storyName || output.storyId };
|
|
2855
|
-
this.form.patchValue({
|
|
2963
|
+
this.form.patchValue({
|
|
2964
|
+
storyId: output.storyId,
|
|
2965
|
+
storyQuery: output.storyName || '',
|
|
2966
|
+
language: output.language,
|
|
2967
|
+
fromScratch: !!output.fromScratch,
|
|
2968
|
+
agentId: output.agentId,
|
|
2969
|
+
}, { emitEvent: false });
|
|
2970
|
+
if (output.fromScratch) {
|
|
2971
|
+
this.hasExistingTranslation = true;
|
|
2972
|
+
}
|
|
2973
|
+
else {
|
|
2974
|
+
void this.checkExistingTranslation(true);
|
|
2975
|
+
}
|
|
2856
2976
|
}
|
|
2857
2977
|
if (this.readonly) {
|
|
2858
2978
|
this.suggestionsOpened = false;
|
|
@@ -2862,12 +2982,315 @@ class StoryTranslatorFormStepComponent {
|
|
|
2862
2982
|
this.form.enable({ emitEvent: false });
|
|
2863
2983
|
}
|
|
2864
2984
|
}
|
|
2985
|
+
async checkExistingTranslation(preserveCheckboxValue = false) {
|
|
2986
|
+
const storyId = this.selectedStory?.id;
|
|
2987
|
+
const rawLang = this.form.get('language')?.value || '';
|
|
2988
|
+
const langInfo = getStoryTranslatorLanguage(rawLang);
|
|
2989
|
+
const languageKey = langInfo?.code || rawLang;
|
|
2990
|
+
if (!storyId || !languageKey) {
|
|
2991
|
+
this.hasExistingTranslation = false;
|
|
2992
|
+
this.checkingTranslations = false;
|
|
2993
|
+
if (!preserveCheckboxValue) {
|
|
2994
|
+
this.form.get('fromScratch')?.setValue(false, { emitEvent: false });
|
|
2995
|
+
}
|
|
2996
|
+
this.cdr.markForCheck();
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
const requestId = ++this.translationCheckRequestId;
|
|
3000
|
+
this.checkingTranslations = true;
|
|
3001
|
+
const aliases = this.selectedStory?.aliases || [];
|
|
3002
|
+
const hasAliasForLang = aliases.some((a) => {
|
|
3003
|
+
const norm = getStoryTranslatorLanguage(a.languageKey)?.code || a.languageKey;
|
|
3004
|
+
return norm === languageKey;
|
|
3005
|
+
});
|
|
3006
|
+
try {
|
|
3007
|
+
const translations = this.messenger?.ozzy
|
|
3008
|
+
? await this.messenger.ozzy.getStoryTranslations(storyId)
|
|
3009
|
+
: [];
|
|
3010
|
+
if (requestId !== this.translationCheckRequestId) {
|
|
3011
|
+
return;
|
|
3012
|
+
}
|
|
3013
|
+
const hasStoryTranslation = translations.some((t) => {
|
|
3014
|
+
const norm = getStoryTranslatorLanguage(t.languageKey)?.code || t.languageKey;
|
|
3015
|
+
return norm === languageKey;
|
|
3016
|
+
});
|
|
3017
|
+
this.hasExistingTranslation = hasAliasForLang || hasStoryTranslation;
|
|
3018
|
+
if (!this.hasExistingTranslation && !preserveCheckboxValue) {
|
|
3019
|
+
this.form.get('fromScratch')?.setValue(false, { emitEvent: false });
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
catch {
|
|
3023
|
+
if (requestId !== this.translationCheckRequestId) {
|
|
3024
|
+
return;
|
|
3025
|
+
}
|
|
3026
|
+
this.hasExistingTranslation = hasAliasForLang;
|
|
3027
|
+
}
|
|
3028
|
+
finally {
|
|
3029
|
+
if (requestId === this.translationCheckRequestId) {
|
|
3030
|
+
this.checkingTranslations = false;
|
|
3031
|
+
this.cdr.detectChanges();
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
2865
3035
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryTranslatorFormStepComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2866
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryTranslatorFormStepComponent, isStandalone: true, selector: "rtsee-story-translator-form-step", inputs: { step: "step", workflow: "workflow", chat: "chat", messenger: "messenger" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" } }, viewQueries: [{ propertyName: "storyInput", first: true, predicate: ["storyInput"], descendants: true }], ngImport: i0, template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-translator-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-translator-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-translator-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Translate to</span>\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('language')\"\n formControlName=\"language\"\n id=\"story-translator-language-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select a language</option>\n @for (language of languages; track language.code) {\n <option [value]=\"language.code\">{{ language.nativeName }}</option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n </label>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-translator-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-translator-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length\"\n id=\"story-translator-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Translating\u2026\n } @else {\n \uD83C\uDF10 Translate{{ selectedLanguage ? ' to ' + selectedLanguage.nativeName : '' }}\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
|
|
3036
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryTranslatorFormStepComponent, isStandalone: true, selector: "rtsee-story-translator-form-step", inputs: { step: "step", workflow: "workflow", chat: "chat", messenger: "messenger" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" } }, viewQueries: [{ propertyName: "storyInput", first: true, predicate: ["storyInput"], descendants: true }], ngImport: i0, template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-translator-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-translator-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-translator-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Translate to</span>\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('language')\"\n formControlName=\"language\"\n id=\"story-translator-language-{{ step.id }}\"\n (change)=\"onLanguageChange()\"\n >\n <option value=\"\" disabled>Select a language</option>\n @for (language of languages; track language.code) {\n <option [value]=\"language.code\">{{ language.nativeName }}</option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n </label>\n\n @if (hasExistingTranslation) {\n <label class=\"rts-st-checkbox-row\" for=\"story-translator-from-scratch-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"fromScratch\"\n id=\"story-translator-from-scratch-{{ step.id }}\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">From scratch</span>\n <span class=\"rts-st-checkbox-desc\">Overwrite existing {{ selectedLanguage?.nativeName || '' }} translations for all story elements</span>\n </span>\n </label>\n }\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-translator-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-translator-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length\"\n id=\"story-translator-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Translating\u2026\n } @else {\n \uD83C\uDF10 Translate{{ selectedLanguage ? ' to ' + selectedLanguage.nativeName : '' }}\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-checkbox-row{display:flex;align-items:flex-start;gap:10px;padding:9px 11px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));cursor:pointer;-webkit-user-select:none;user-select:none;transition:border-color .15s ease,background .15s ease}.rts-st-checkbox-row:hover{border-color:#8b5cf673;background:#8b5cf60f}.rts-st-checkbox-input{margin-top:2px;width:15px;height:15px;flex-shrink:0;accent-color:var(--rts-st-accent, #8b5cf6);cursor:pointer}.rts-st-checkbox-body{display:flex;flex-direction:column;gap:2px;min-width:0}.rts-st-checkbox-title{font-size:13px;font-weight:600;color:var(--rts-text-primary)}.rts-st-checkbox-desc{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
|
|
2867
3037
|
}
|
|
2868
3038
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryTranslatorFormStepComponent, decorators: [{
|
|
2869
3039
|
type: Component,
|
|
2870
|
-
args: [{ selector: 'rtsee-story-translator-form-step', standalone: true, imports: [ReactiveFormsModule], template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-translator-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-translator-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-translator-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Translate to</span>\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('language')\"\n formControlName=\"language\"\n id=\"story-translator-language-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select a language</option>\n @for (language of languages; track language.code) {\n <option [value]=\"language.code\">{{ language.nativeName }}</option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n </label>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-translator-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-translator-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length\"\n id=\"story-translator-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Translating\u2026\n } @else {\n \uD83C\uDF10 Translate{{ selectedLanguage ? ' to ' + selectedLanguage.nativeName : '' }}\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"] }]
|
|
3040
|
+
args: [{ selector: 'rtsee-story-translator-form-step', standalone: true, imports: [ReactiveFormsModule], template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-translator-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-translator-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-translator-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Translate to</span>\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('language')\"\n formControlName=\"language\"\n id=\"story-translator-language-{{ step.id }}\"\n (change)=\"onLanguageChange()\"\n >\n <option value=\"\" disabled>Select a language</option>\n @for (language of languages; track language.code) {\n <option [value]=\"language.code\">{{ language.nativeName }}</option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n </label>\n\n @if (hasExistingTranslation) {\n <label class=\"rts-st-checkbox-row\" for=\"story-translator-from-scratch-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"fromScratch\"\n id=\"story-translator-from-scratch-{{ step.id }}\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">From scratch</span>\n <span class=\"rts-st-checkbox-desc\">Overwrite existing {{ selectedLanguage?.nativeName || '' }} translations for all story elements</span>\n </span>\n </label>\n }\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-translator-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-translator-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length\"\n id=\"story-translator-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Translating\u2026\n } @else {\n \uD83C\uDF10 Translate{{ selectedLanguage ? ' to ' + selectedLanguage.nativeName : '' }}\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-checkbox-row{display:flex;align-items:flex-start;gap:10px;padding:9px 11px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));cursor:pointer;-webkit-user-select:none;user-select:none;transition:border-color .15s ease,background .15s ease}.rts-st-checkbox-row:hover{border-color:#8b5cf673;background:#8b5cf60f}.rts-st-checkbox-input{margin-top:2px;width:15px;height:15px;flex-shrink:0;accent-color:var(--rts-st-accent, #8b5cf6);cursor:pointer}.rts-st-checkbox-body{display:flex;flex-direction:column;gap:2px;min-width:0}.rts-st-checkbox-title{font-size:13px;font-weight:600;color:var(--rts-text-primary)}.rts-st-checkbox-desc{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"] }]
|
|
3041
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { step: [{
|
|
3042
|
+
type: Input
|
|
3043
|
+
}], workflow: [{
|
|
3044
|
+
type: Input
|
|
3045
|
+
}], chat: [{
|
|
3046
|
+
type: Input
|
|
3047
|
+
}], messenger: [{
|
|
3048
|
+
type: Input
|
|
3049
|
+
}], storyInput: [{
|
|
3050
|
+
type: ViewChild,
|
|
3051
|
+
args: ['storyInput']
|
|
3052
|
+
}], onDocumentMouseDown: [{
|
|
3053
|
+
type: HostListener,
|
|
3054
|
+
args: ['document:mousedown', ['$event']]
|
|
3055
|
+
}] } });
|
|
3056
|
+
|
|
3057
|
+
const SEARCH_DEBOUNCE_MS = 250;
|
|
3058
|
+
/**
|
|
3059
|
+
* Story Repair step 1 (#RepairStory):
|
|
3060
|
+
* - Pick a story (autocomplete by name)
|
|
3061
|
+
* - Choose repair options via 4 checkboxes (Grammar & Flow, Characters, Artifacts, Locations), all checked by default
|
|
3062
|
+
* - Pick an agent
|
|
3063
|
+
*/
|
|
3064
|
+
class StoryRepairFormStepComponent {
|
|
3065
|
+
constructor(cdr, host) {
|
|
3066
|
+
this.cdr = cdr;
|
|
3067
|
+
this.host = host;
|
|
3068
|
+
this.form = new FormGroup({
|
|
3069
|
+
/* eslint-disable */
|
|
3070
|
+
storyQuery: new FormControl(''),
|
|
3071
|
+
storyId: new FormControl('', Validators.required),
|
|
3072
|
+
grammarAndFlow: new FormControl(true),
|
|
3073
|
+
characters: new FormControl(true),
|
|
3074
|
+
artifacts: new FormControl(true),
|
|
3075
|
+
locations: new FormControl(true),
|
|
3076
|
+
agentId: new FormControl('', Validators.required),
|
|
3077
|
+
/* eslint-enable */
|
|
3078
|
+
});
|
|
3079
|
+
this.selectedStory = null;
|
|
3080
|
+
this.suggestions = [];
|
|
3081
|
+
this.suggestionsOpened = false;
|
|
3082
|
+
this.highlightedIndex = 0;
|
|
3083
|
+
this.searchInProgress = false;
|
|
3084
|
+
this.searchError = null;
|
|
3085
|
+
this.optionsTouched = false;
|
|
3086
|
+
this.searchTimer = null;
|
|
3087
|
+
this.searchRequestId = 0;
|
|
3088
|
+
this.onChangedBound = () => this.onWorkflowChanged();
|
|
3089
|
+
}
|
|
3090
|
+
get agents() {
|
|
3091
|
+
return (this.chat?.members || []).filter((m) => m.isAgent);
|
|
3092
|
+
}
|
|
3093
|
+
get readonly() {
|
|
3094
|
+
return !this.step?.isActive || !!this.workflow?.submitInProgress;
|
|
3095
|
+
}
|
|
3096
|
+
get canCancel() {
|
|
3097
|
+
return !!this.workflow?.isDraft && !this.workflow?.submitInProgress && !!this.messenger;
|
|
3098
|
+
}
|
|
3099
|
+
get hasAtLeastOneOption() {
|
|
3100
|
+
const opts = this.currentOptions;
|
|
3101
|
+
return opts.grammarAndFlow || opts.characters || opts.artifacts || opts.locations;
|
|
3102
|
+
}
|
|
3103
|
+
get currentOptions() {
|
|
3104
|
+
return {
|
|
3105
|
+
grammarAndFlow: !!this.form.get('grammarAndFlow')?.value,
|
|
3106
|
+
characters: !!this.form.get('characters')?.value,
|
|
3107
|
+
artifacts: !!this.form.get('artifacts')?.value,
|
|
3108
|
+
locations: !!this.form.get('locations')?.value,
|
|
3109
|
+
};
|
|
3110
|
+
}
|
|
3111
|
+
ngOnInit() {
|
|
3112
|
+
this.workflow?.on(OzzyWorkflowClientEvents.CHANGED, this.onChangedBound);
|
|
3113
|
+
const agents = this.agents;
|
|
3114
|
+
if (agents.length === 1) {
|
|
3115
|
+
this.form.get('agentId')?.setValue(agents[0].id);
|
|
3116
|
+
}
|
|
3117
|
+
this.syncWithStep();
|
|
3118
|
+
}
|
|
3119
|
+
ngOnDestroy() {
|
|
3120
|
+
this.workflow?.off(OzzyWorkflowClientEvents.CHANGED, this.onChangedBound);
|
|
3121
|
+
this.clearSearchTimer();
|
|
3122
|
+
}
|
|
3123
|
+
onStoryFocus() {
|
|
3124
|
+
if (this.readonly) {
|
|
3125
|
+
return;
|
|
3126
|
+
}
|
|
3127
|
+
this.suggestionsOpened = true;
|
|
3128
|
+
if (!this.suggestions.length) {
|
|
3129
|
+
this.scheduleSearch(0);
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
onStoryInput() {
|
|
3133
|
+
if (this.selectedStory) {
|
|
3134
|
+
this.selectedStory = null;
|
|
3135
|
+
this.form.get('storyId')?.setValue('');
|
|
3136
|
+
}
|
|
3137
|
+
this.suggestionsOpened = true;
|
|
3138
|
+
this.scheduleSearch(SEARCH_DEBOUNCE_MS);
|
|
3139
|
+
}
|
|
3140
|
+
onStoryKeydown(event) {
|
|
3141
|
+
if (!this.suggestionsOpened || !this.suggestions.length) {
|
|
3142
|
+
if (event.key === 'ArrowDown') {
|
|
3143
|
+
this.suggestionsOpened = true;
|
|
3144
|
+
this.scheduleSearch(0);
|
|
3145
|
+
}
|
|
3146
|
+
return;
|
|
3147
|
+
}
|
|
3148
|
+
switch (event.key) {
|
|
3149
|
+
case 'ArrowDown':
|
|
3150
|
+
event.preventDefault();
|
|
3151
|
+
this.highlightedIndex = (this.highlightedIndex + 1) % this.suggestions.length;
|
|
3152
|
+
break;
|
|
3153
|
+
case 'ArrowUp':
|
|
3154
|
+
event.preventDefault();
|
|
3155
|
+
this.highlightedIndex =
|
|
3156
|
+
(this.highlightedIndex - 1 + this.suggestions.length) % this.suggestions.length;
|
|
3157
|
+
break;
|
|
3158
|
+
case 'Enter':
|
|
3159
|
+
event.preventDefault();
|
|
3160
|
+
this.selectStory(this.suggestions[this.highlightedIndex]);
|
|
3161
|
+
break;
|
|
3162
|
+
case 'Escape':
|
|
3163
|
+
event.preventDefault();
|
|
3164
|
+
this.suggestionsOpened = false;
|
|
3165
|
+
break;
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
selectStory(story) {
|
|
3169
|
+
if (!story || this.readonly) {
|
|
3170
|
+
return;
|
|
3171
|
+
}
|
|
3172
|
+
this.selectedStory = story;
|
|
3173
|
+
this.form.patchValue({ storyId: story.id, storyQuery: story.name }, { emitEvent: false });
|
|
3174
|
+
this.form.get('storyId')?.markAsTouched();
|
|
3175
|
+
this.suggestionsOpened = false;
|
|
3176
|
+
}
|
|
3177
|
+
clearStory() {
|
|
3178
|
+
if (this.readonly) {
|
|
3179
|
+
return;
|
|
3180
|
+
}
|
|
3181
|
+
this.selectedStory = null;
|
|
3182
|
+
this.form.patchValue({ storyId: '', storyQuery: '' }, { emitEvent: false });
|
|
3183
|
+
this.suggestionsOpened = true;
|
|
3184
|
+
this.scheduleSearch(0);
|
|
3185
|
+
setTimeout(() => this.storyInput?.nativeElement.focus());
|
|
3186
|
+
}
|
|
3187
|
+
onOptionChanged() {
|
|
3188
|
+
this.optionsTouched = true;
|
|
3189
|
+
}
|
|
3190
|
+
onDocumentMouseDown(event) {
|
|
3191
|
+
if (this.suggestionsOpened && !this.host.nativeElement.contains(event.target)) {
|
|
3192
|
+
this.suggestionsOpened = false;
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
submit() {
|
|
3196
|
+
if (this.readonly) {
|
|
3197
|
+
return;
|
|
3198
|
+
}
|
|
3199
|
+
this.optionsTouched = true;
|
|
3200
|
+
if (this.form.invalid || !this.selectedStory || !this.hasAtLeastOneOption) {
|
|
3201
|
+
this.form.markAllAsTouched();
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
void this.workflow.submitStep({
|
|
3205
|
+
storyId: this.selectedStory.id,
|
|
3206
|
+
storyName: this.selectedStory.name,
|
|
3207
|
+
agentId: this.form.get('agentId')?.value,
|
|
3208
|
+
options: this.currentOptions,
|
|
3209
|
+
});
|
|
3210
|
+
}
|
|
3211
|
+
cancel() {
|
|
3212
|
+
if (!this.canCancel) {
|
|
3213
|
+
return;
|
|
3214
|
+
}
|
|
3215
|
+
this.messenger?.discardDraftWorkflow(this.workflow);
|
|
3216
|
+
}
|
|
3217
|
+
isInvalid(name) {
|
|
3218
|
+
const control = this.form.get(name);
|
|
3219
|
+
return !!control && control.invalid && control.touched;
|
|
3220
|
+
}
|
|
3221
|
+
scheduleSearch(delay) {
|
|
3222
|
+
this.clearSearchTimer();
|
|
3223
|
+
this.searchTimer = setTimeout(() => void this.search(), delay);
|
|
3224
|
+
}
|
|
3225
|
+
clearSearchTimer() {
|
|
3226
|
+
if (this.searchTimer) {
|
|
3227
|
+
clearTimeout(this.searchTimer);
|
|
3228
|
+
this.searchTimer = null;
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
async search() {
|
|
3232
|
+
if (!this.messenger) {
|
|
3233
|
+
return;
|
|
3234
|
+
}
|
|
3235
|
+
const requestId = ++this.searchRequestId;
|
|
3236
|
+
const query = this.form.get('storyQuery')?.value || '';
|
|
3237
|
+
this.searchInProgress = true;
|
|
3238
|
+
this.searchError = null;
|
|
3239
|
+
this.cdr.markForCheck();
|
|
3240
|
+
try {
|
|
3241
|
+
const stories = await this.messenger.ozzy.searchStories(query);
|
|
3242
|
+
if (requestId !== this.searchRequestId) {
|
|
3243
|
+
return;
|
|
3244
|
+
}
|
|
3245
|
+
this.suggestions = stories;
|
|
3246
|
+
this.highlightedIndex = 0;
|
|
3247
|
+
}
|
|
3248
|
+
catch (e) {
|
|
3249
|
+
if (requestId !== this.searchRequestId) {
|
|
3250
|
+
return;
|
|
3251
|
+
}
|
|
3252
|
+
this.suggestions = [];
|
|
3253
|
+
this.searchError = e?.friendlyMessage || e?.message || 'Failed to load stories.';
|
|
3254
|
+
}
|
|
3255
|
+
finally {
|
|
3256
|
+
if (requestId === this.searchRequestId) {
|
|
3257
|
+
this.searchInProgress = false;
|
|
3258
|
+
this.cdr.detectChanges();
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
onWorkflowChanged() {
|
|
3263
|
+
this.syncWithStep();
|
|
3264
|
+
this.cdr.detectChanges();
|
|
3265
|
+
}
|
|
3266
|
+
syncWithStep() {
|
|
3267
|
+
const output = this.step?.output;
|
|
3268
|
+
if (output?.storyId) {
|
|
3269
|
+
this.selectedStory = { id: output.storyId, name: output.storyName || output.storyId };
|
|
3270
|
+
this.form.patchValue({
|
|
3271
|
+
storyId: output.storyId,
|
|
3272
|
+
storyQuery: output.storyName || '',
|
|
3273
|
+
grammarAndFlow: output.options ? !!output.options.grammarAndFlow : true,
|
|
3274
|
+
characters: output.options ? !!output.options.characters : true,
|
|
3275
|
+
artifacts: output.options ? !!output.options.artifacts : true,
|
|
3276
|
+
locations: output.options ? !!output.options.locations : true,
|
|
3277
|
+
agentId: output.agentId,
|
|
3278
|
+
}, { emitEvent: false });
|
|
3279
|
+
}
|
|
3280
|
+
if (this.readonly) {
|
|
3281
|
+
this.suggestionsOpened = false;
|
|
3282
|
+
this.form.disable({ emitEvent: false });
|
|
3283
|
+
}
|
|
3284
|
+
else {
|
|
3285
|
+
this.form.enable({ emitEvent: false });
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryRepairFormStepComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3289
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryRepairFormStepComponent, isStandalone: true, selector: "rtsee-story-repair-form-step", inputs: { step: "step", workflow: "workflow", chat: "chat", messenger: "messenger" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" } }, viewQueries: [{ propertyName: "storyInput", first: true, predicate: ["storyInput"], descendants: true }], ngImport: i0, template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-repair-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-repair-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-repair-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n @if (selectedStory) {\n <div class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Repair options</span>\n <div class=\"rts-st-repair-options-grid\">\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-grammar-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"grammarAndFlow\"\n id=\"story-repair-grammar-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Grammar & Flow</span>\n <span class=\"rts-st-checkbox-desc\">Fix typos, punctuation & improve readability across story, slides & entities</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-characters-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"characters\"\n id=\"story-repair-characters-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Characters</span>\n <span class=\"rts-st-checkbox-desc\">Add missing important characters and link them to slides</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-artifacts-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"artifacts\"\n id=\"story-repair-artifacts-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Artifacts</span>\n <span class=\"rts-st-checkbox-desc\">Add missing memorable objects and link them to slides</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-locations-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"locations\"\n id=\"story-repair-locations-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Locations</span>\n <span class=\"rts-st-checkbox-desc\">Add missing story locations and link them to slides</span>\n </span>\n </label>\n </div>\n @if (!hasAtLeastOneOption) {\n <div class=\"rts-storyteller-error\">Please select at least one option to repair.</div>\n }\n </div>\n }\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-repair-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-repair-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length || !selectedStory || !hasAtLeastOneOption\"\n id=\"story-repair-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Repairing\u2026\n } @else {\n \uD83D\uDEE0\uFE0F Repair Story\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-checkbox-row{display:flex;align-items:flex-start;gap:10px;padding:9px 11px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));cursor:pointer;-webkit-user-select:none;user-select:none;transition:border-color .15s ease,background .15s ease}.rts-st-checkbox-row:hover{border-color:#8b5cf673;background:#8b5cf60f}.rts-st-checkbox-input{margin-top:2px;width:15px;height:15px;flex-shrink:0;accent-color:var(--rts-st-accent, #8b5cf6);cursor:pointer}.rts-st-checkbox-body{display:flex;flex-direction:column;gap:2px;min-width:0}.rts-st-checkbox-title{font-size:13px;font-weight:600;color:var(--rts-text-primary)}.rts-st-checkbox-desc{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n", ".rts-st-repair-options-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}@media (max-width: 480px){.rts-st-repair-options-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
|
|
3290
|
+
}
|
|
3291
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryRepairFormStepComponent, decorators: [{
|
|
3292
|
+
type: Component,
|
|
3293
|
+
args: [{ selector: 'rtsee-story-repair-form-step', standalone: true, imports: [ReactiveFormsModule], template: "<form class=\"rts-storyteller-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\" autocomplete=\"off\">\n <div class=\"rts-storyteller-field\">\n <label class=\"rts-storyteller-label\" for=\"story-repair-story-{{ step.id }}\">Story</label>\n <div class=\"rts-st-autocomplete\">\n <span class=\"rts-st-autocomplete-icon pi\" [class.pi-search]=\"!searchInProgress\" [class.pi-spin]=\"searchInProgress\" [class.pi-spinner]=\"searchInProgress\"></span>\n <input #storyInput\n class=\"rts-storyteller-input rts-st-autocomplete-input\"\n [class.rts-storyteller-invalid]=\"isInvalid('storyId')\"\n [class.rts-st-autocomplete-selected]=\"!!selectedStory\"\n formControlName=\"storyQuery\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"suggestionsOpened\"\n placeholder=\"Search stories by name\u2026\"\n id=\"story-repair-story-{{ step.id }}\"\n (focus)=\"onStoryFocus()\"\n (input)=\"onStoryInput()\"\n (keydown)=\"onStoryKeydown($event)\"\n />\n @if (selectedStory && !readonly) {\n <button type=\"button\"\n class=\"rts-st-autocomplete-clear pi pi-times\"\n aria-label=\"Clear story\"\n id=\"story-repair-clear-{{ step.id }}\"\n (click)=\"clearStory()\"\n ></button>\n }\n\n @if (suggestionsOpened && !readonly) {\n <ul class=\"rts-st-autocomplete-panel\" role=\"listbox\">\n @if (searchError) {\n <li class=\"rts-st-autocomplete-empty rts-st-autocomplete-error\">{{ searchError }}</li>\n } @else if (!suggestions.length && !searchInProgress) {\n <li class=\"rts-st-autocomplete-empty\">No stories found</li>\n }\n @for (story of suggestions; track story.id; let i = $index) {\n <li class=\"rts-st-autocomplete-option\"\n role=\"option\"\n [class.rts-st-autocomplete-option-active]=\"i === highlightedIndex\"\n [attr.aria-selected]=\"story.id === selectedStory?.id\"\n (mouseenter)=\"highlightedIndex = i\"\n (mousedown)=\"$event.preventDefault(); selectStory(story)\"\n >\n @if (story.imageUrl) {\n <img class=\"rts-st-autocomplete-thumb\" [src]=\"story.imageUrl\" [alt]=\"story.name\" loading=\"lazy\" />\n } @else {\n <span class=\"rts-st-autocomplete-thumb rts-st-autocomplete-thumb-empty\">\uD83D\uDCD6</span>\n }\n <span class=\"rts-st-autocomplete-option-body\">\n <span class=\"rts-st-autocomplete-option-name\">{{ story.name }}</span>\n @if (story.totalSlides) {\n <span class=\"rts-st-autocomplete-option-meta\">{{ story.totalSlides }} slides</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n </div>\n </div>\n\n @if (selectedStory) {\n <div class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Repair options</span>\n <div class=\"rts-st-repair-options-grid\">\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-grammar-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"grammarAndFlow\"\n id=\"story-repair-grammar-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Grammar & Flow</span>\n <span class=\"rts-st-checkbox-desc\">Fix typos, punctuation & improve readability across story, slides & entities</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-characters-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"characters\"\n id=\"story-repair-characters-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Characters</span>\n <span class=\"rts-st-checkbox-desc\">Add missing important characters and link them to slides</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-artifacts-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"artifacts\"\n id=\"story-repair-artifacts-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Artifacts</span>\n <span class=\"rts-st-checkbox-desc\">Add missing memorable objects and link them to slides</span>\n </span>\n </label>\n\n <label class=\"rts-st-checkbox-row\" for=\"story-repair-locations-{{ step.id }}\">\n <input type=\"checkbox\"\n class=\"rts-st-checkbox-input\"\n formControlName=\"locations\"\n id=\"story-repair-locations-{{ step.id }}\"\n (change)=\"onOptionChanged()\"\n />\n <span class=\"rts-st-checkbox-body\">\n <span class=\"rts-st-checkbox-title\">Locations</span>\n <span class=\"rts-st-checkbox-desc\">Add missing story locations and link them to slides</span>\n </span>\n </label>\n </div>\n @if (!hasAtLeastOneOption) {\n <div class=\"rts-storyteller-error\">Please select at least one option to repair.</div>\n }\n </div>\n }\n\n <label class=\"rts-storyteller-field\">\n <span class=\"rts-storyteller-label\">Agent</span>\n @if (agents.length) {\n <div class=\"rts-storyteller-select-wrap\">\n <select class=\"rts-storyteller-input rts-storyteller-select\"\n [class.rts-storyteller-invalid]=\"isInvalid('agentId')\"\n formControlName=\"agentId\"\n id=\"story-repair-agent-{{ step.id }}\"\n >\n <option value=\"\" disabled>Select an agent</option>\n @for (agent of agents; track agent.id) {\n <option [value]=\"agent.id\">\n {{ agent.name }}{{ agent.agentConfiguration?.model?.model ? ' \u00B7 ' + agent.agentConfiguration?.model?.model : '' }}\n </option>\n }\n </select>\n <span class=\"rts-storyteller-select-caret pi pi-chevron-down\"></span>\n </div>\n } @else {\n <div class=\"rts-storyteller-hint\">There are no agentic members in this chat. Add an agent to continue.</div>\n }\n </label>\n\n @if (workflow.submitError) {\n <div class=\"rts-storyteller-error\">{{ workflow.submitError }}</div>\n }\n\n @if (step.isActive) {\n <div class=\"rts-storyteller-actions rts-st-translator-actions\">\n @if (canCancel) {\n <button class=\"rts-st-cancel\"\n type=\"button\"\n id=\"story-repair-cancel-{{ step.id }}\"\n (click)=\"cancel()\"\n >Cancel</button>\n }\n <button class=\"rts-storyteller-submit\"\n type=\"submit\"\n [disabled]=\"workflow.submitInProgress || !agents.length || !selectedStory || !hasAtLeastOneOption\"\n id=\"story-repair-submit-{{ step.id }}\"\n >\n @if (workflow.submitInProgress) {\n <span class=\"rts-storyteller-spinner\"></span> Repairing\u2026\n } @else {\n \uD83D\uDEE0\uFE0F Repair Story\n }\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block;--rts-st-accent: #8b5cf6;--rts-st-accent-2: #6366f1}.rts-storyteller-form{display:flex;flex-direction:column;gap:12px}.rts-storyteller-field{display:flex;flex-direction:column;gap:5px}.rts-storyteller-label{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-counter{font-weight:500;letter-spacing:0;text-transform:none}.rts-storyteller-input{width:100%;box-sizing:border-box;padding:9px 12px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));color:var(--rts-text-primary);font:inherit;font-size:13px;outline:none;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.rts-storyteller-input:focus{border-color:var(--rts-st-accent);box-shadow:0 0 0 3px #8b5cf62e}.rts-storyteller-input:disabled{opacity:.75;cursor:default}.rts-storyteller-input.rts-storyteller-invalid{border-color:#f43f5e;box-shadow:0 0 0 3px #f43f5e1f}.rts-storyteller-textarea{min-height:80px;resize:vertical;line-height:1.5}.rts-storyteller-textarea-lg{min-height:160px;max-height:480px}.rts-storyteller-select-wrap{position:relative}.rts-storyteller-select{appearance:none;padding-right:32px;cursor:pointer}.rts-storyteller-select-caret{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:10px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-hint{font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-storyteller-error{padding:6px 10px;border-radius:6px;font-size:12px;color:#f43f5e;background:#f43f5e14;border:1px solid rgba(244,63,94,.25)}.rts-storyteller-actions{display:flex;justify-content:flex-end}.rts-storyteller-submit{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:none;border-radius:9px;color:#fff;font-weight:600;font-size:13px;cursor:pointer;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent) 60%,#a78bfa);background-size:160% 160%;box-shadow:0 4px 14px -4px #6366f199;transition:transform .15s ease,box-shadow .15s ease,background-position .4s ease}.rts-storyteller-submit:hover:not(:disabled){transform:translateY(-1px);background-position:100% 0;box-shadow:0 6px 18px -4px #6366f1bf}.rts-storyteller-submit:disabled{opacity:.6;cursor:default;box-shadow:none}.rts-storyteller-spinner{width:11px;height:11px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:rts-st-spin .8s linear infinite}.rts-story-link-card{display:flex;align-items:center;gap:12px;padding:14px;border-radius:12px;text-decoration:none;color:inherit;background:linear-gradient(135deg,#6366f11a,#8b5cf60f);border:1px solid rgba(139,92,246,.3);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;animation:rts-st-pop .4s cubic-bezier(.2,.9,.3,1.3)}.rts-story-link-card:hover{transform:translateY(-2px);border-color:var(--rts-st-accent);box-shadow:0 10px 28px -12px #8b5cf699}.rts-story-link-card:hover .rts-story-link-arrow{transform:translate(3px)}.rts-story-link-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:42px;height:42px;border-radius:12px;font-size:20px;background:linear-gradient(135deg,var(--rts-st-accent-2),var(--rts-st-accent))}.rts-story-link-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.rts-story-link-kicker{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--rts-st-accent)}.rts-story-link-title{font-size:15px;font-weight:600;color:var(--rts-text-primary)}.rts-story-link-description{font-size:12px;color:var(--rts-text-secondary, #8a8fa3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.rts-story-link-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-story-link-arrow{color:var(--rts-st-accent);transition:transform .2s ease}@keyframes rts-st-spin{to{transform:rotate(360deg)}}@keyframes rts-st-pop{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}\n", ".rts-st-autocomplete{position:relative}.rts-st-autocomplete-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:12px;pointer-events:none;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-input{padding-left:32px;padding-right:32px}.rts-st-autocomplete-input.rts-st-autocomplete-selected{font-weight:600}.rts-st-autocomplete-clear{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:22px;height:22px;padding:0;border:none;border-radius:50%;font-size:10px;cursor:pointer;color:var(--rts-text-secondary, #8a8fa3);background:transparent;transition:background .15s ease,color .15s ease}.rts-st-autocomplete-clear:hover{color:var(--rts-text-primary);background:#8b5cf626}.rts-st-autocomplete-panel{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);max-height:240px;margin:0;padding:4px;overflow-y:auto;list-style:none;border-radius:10px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-secondary, var(--rts-bg-primary, #1d1f2b));-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 14px 32px -12px #00000073;animation:rts-st-panel-in .14s ease-out}.rts-st-autocomplete-option{display:flex;align-items:center;gap:10px;padding:6px 8px;border-radius:7px;cursor:pointer;transition:background .12s ease}.rts-st-autocomplete-option.rts-st-autocomplete-option-active{background:linear-gradient(135deg,#6366f129,#8b5cf61a)}.rts-st-autocomplete-option[aria-selected=true] .rts-st-autocomplete-option-name{color:var(--rts-st-accent)}.rts-st-autocomplete-thumb{flex-shrink:0;width:30px;height:30px;border-radius:7px;object-fit:cover}.rts-st-autocomplete-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:15px;background:#8b5cf624}.rts-st-autocomplete-option-body{display:flex;flex-direction:column;min-width:0}.rts-st-autocomplete-option-name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;color:var(--rts-text-primary)}.rts-st-autocomplete-option-meta{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-empty{padding:8px;font-size:12px;font-style:italic;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-autocomplete-error{font-style:normal;color:#f43f5e}.rts-st-translator-actions{gap:8px}.rts-st-checkbox-row{display:flex;align-items:flex-start;gap:10px;padding:9px 11px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:var(--rts-bg-primary, rgba(127, 127, 160, .06));cursor:pointer;-webkit-user-select:none;user-select:none;transition:border-color .15s ease,background .15s ease}.rts-st-checkbox-row:hover{border-color:#8b5cf673;background:#8b5cf60f}.rts-st-checkbox-input{margin-top:2px;width:15px;height:15px;flex-shrink:0;accent-color:var(--rts-st-accent, #8b5cf6);cursor:pointer}.rts-st-checkbox-body{display:flex;flex-direction:column;gap:2px;min-width:0}.rts-st-checkbox-title{font-size:13px;font-weight:600;color:var(--rts-text-primary)}.rts-st-checkbox-desc{font-size:11px;color:var(--rts-text-secondary, #8a8fa3)}.rts-st-cancel{padding:8px 16px;border-radius:9px;border:1px solid var(--rts-border-dim, rgba(120, 120, 160, .25));background:transparent;color:var(--rts-text-secondary, #8a8fa3);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .15s ease,border-color .15s ease,background .15s ease}.rts-st-cancel:hover{color:var(--rts-text-primary);border-color:#f43f5e73;background:#f43f5e0f}@keyframes rts-st-panel-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n", ".rts-st-repair-options-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}@media (max-width: 480px){.rts-st-repair-options-grid{grid-template-columns:1fr}}\n"] }]
|
|
2871
3294
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { step: [{
|
|
2872
3295
|
type: Input
|
|
2873
3296
|
}], workflow: [{
|
|
@@ -2894,6 +3317,7 @@ class WorkflowStepsService {
|
|
|
2894
3317
|
{ name: 'storyteller-form-step', component: StorytellerFormStepComponent },
|
|
2895
3318
|
{ name: 'storyteller-story-link-step', component: StorytellerStoryLinkStepComponent },
|
|
2896
3319
|
{ name: 'story-translator-form-step', component: StoryTranslatorFormStepComponent },
|
|
3320
|
+
{ name: 'story-repair-form-step', component: StoryRepairFormStepComponent },
|
|
2897
3321
|
];
|
|
2898
3322
|
}
|
|
2899
3323
|
register(widget) {
|
|
@@ -3071,29 +3495,47 @@ class MessageComponent {
|
|
|
3071
3495
|
this.timeFormatService = timeFormatService;
|
|
3072
3496
|
this.widgetRef = null;
|
|
3073
3497
|
this.widgetHasMessageInput = false;
|
|
3498
|
+
this.currentWidgetName = null;
|
|
3074
3499
|
}
|
|
3075
3500
|
ngOnInit() { }
|
|
3076
3501
|
ngOnChanges(changes) {
|
|
3077
|
-
// The message instance can be replaced (e.g.
|
|
3078
|
-
if (changes['message'] && !changes['message'].firstChange
|
|
3079
|
-
if (this.
|
|
3080
|
-
this.
|
|
3502
|
+
// The message instance or widget type can be replaced (e.g. stream start -> media widget -> downsized versions)
|
|
3503
|
+
if (changes['message'] && !changes['message'].firstChange) {
|
|
3504
|
+
if (this.widgetHost && this.message?.widget !== this.currentWidgetName) {
|
|
3505
|
+
this.renderWidget();
|
|
3506
|
+
return;
|
|
3081
3507
|
}
|
|
3082
|
-
|
|
3083
|
-
this.
|
|
3084
|
-
|
|
3508
|
+
if (this.widgetRef) {
|
|
3509
|
+
if (this.widgetHasMessageInput) {
|
|
3510
|
+
this.widgetRef.setInput('message', this.message);
|
|
3511
|
+
}
|
|
3512
|
+
else {
|
|
3513
|
+
this.widgetRef.instance.message = this.message;
|
|
3514
|
+
if (typeof this.widgetRef.instance.ngOnChanges === 'function') {
|
|
3515
|
+
this.widgetRef.instance.ngOnChanges(changes);
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
this.widgetRef.changeDetectorRef.detectChanges();
|
|
3085
3519
|
}
|
|
3086
3520
|
}
|
|
3087
3521
|
}
|
|
3088
3522
|
ngAfterViewInit() {
|
|
3523
|
+
this.renderWidget();
|
|
3524
|
+
}
|
|
3525
|
+
renderWidget() {
|
|
3089
3526
|
/* eslint-disable */
|
|
3090
|
-
if (this.
|
|
3527
|
+
if (!this.widgetHost) {
|
|
3528
|
+
return;
|
|
3529
|
+
}
|
|
3530
|
+
const viewContainerRef = this.widgetHost.viewContainerRef;
|
|
3531
|
+
viewContainerRef.clear();
|
|
3532
|
+
this.widgetRef = null;
|
|
3533
|
+
this.currentWidgetName = this.message?.widget || null;
|
|
3534
|
+
if (this.message?.widget) {
|
|
3091
3535
|
const widget = this.widgetsService.getWidgetComponentByName(this.message.widget);
|
|
3092
3536
|
if (!widget) {
|
|
3093
3537
|
return;
|
|
3094
3538
|
}
|
|
3095
|
-
const viewContainerRef = this.widgetHost.viewContainerRef;
|
|
3096
|
-
viewContainerRef.clear();
|
|
3097
3539
|
const componentToShow = this.componentFactoryResolver.resolveComponentFactory(widget);
|
|
3098
3540
|
const componentRef = viewContainerRef.createComponent(componentToShow);
|
|
3099
3541
|
componentRef.instance.message = this.message;
|
|
@@ -3106,7 +3548,7 @@ class MessageComponent {
|
|
|
3106
3548
|
/* eslint-enable */
|
|
3107
3549
|
}
|
|
3108
3550
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MessageComponent, deps: [{ token: MessageWidgetsService }, { token: i0.ComponentFactoryResolver }, { token: TimeFormatHelperService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3109
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MessageComponent, isStandalone: true, selector: "rtsee-message", inputs: { chat: "chat", message: "message", member: "member", messenger: "messenger" }, viewQueries: [{ propertyName: "widgetHost", first: true, predicate: WidgetDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-message-container\" #rtsMessageContainer\n [ngClass]=\"{\n 'rts-message-from-me': message.from.id === messenger.clientId,\n 'rts-message-is-widget': !!message.widget\n }\">\n <div class=\"rts-messenger-message\">\n @if (message.widget) {\n <ng-template widgetHost></ng-template>\n }\n @if (!message.widget) {\n <p class=\"rts-messenger-message-text\"\n >{{ message.text }}</p>\n }\n <div class=\"rts-messenger-message-info\" #rtsMessageInfo>\n <rtsee-message-time-and-status [message]=\"message\"\n [inChat]=\"true\"\n [hideStatus]=\"message.from.id !== messenger.clientId\"\n ></rtsee-message-time-and-status>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MessageTimeAndStatusComponent, selector: "rtsee-message-time-and-status", inputs: ["message", "hideStatus", "inChat"] }, { kind: "directive", type: WidgetDirective, selector: "[widgetHost]" }] }); }
|
|
3551
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MessageComponent, isStandalone: true, selector: "rtsee-message", inputs: { chat: "chat", message: "message", member: "member", messenger: "messenger" }, viewQueries: [{ propertyName: "widgetHost", first: true, predicate: WidgetDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-message-container\" #rtsMessageContainer\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"comment\"\n itemscope\n itemtype=\"https://schema.org/Comment\"\n [ngClass]=\"{\n 'rts-message-from-me': message.from.id === messenger.clientId,\n 'rts-message-is-widget': !!message.widget\n }\">\n <div class=\"rts-messenger-message\">\n @if (message.widget) {\n <ng-template widgetHost></ng-template>\n }\n @if (!message.widget) {\n <p class=\"rts-messenger-message-text\"\n itemprop=\"text\"\n data-ugc=\"true\"\n rel=\"ugc\"\n >{{ message.text }}</p>\n }\n <div class=\"rts-messenger-message-info\" #rtsMessageInfo>\n <rtsee-message-time-and-status [message]=\"message\"\n [inChat]=\"true\"\n [hideStatus]=\"message.from.id !== messenger.clientId\"\n ></rtsee-message-time-and-status>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MessageTimeAndStatusComponent, selector: "rtsee-message-time-and-status", inputs: ["message", "hideStatus", "inChat"] }, { kind: "directive", type: WidgetDirective, selector: "[widgetHost]" }] }); }
|
|
3110
3552
|
}
|
|
3111
3553
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MessageComponent, decorators: [{
|
|
3112
3554
|
type: Component,
|
|
@@ -3115,7 +3557,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
3115
3557
|
MessageTimeAndStatusComponent,
|
|
3116
3558
|
WidgetDirective,
|
|
3117
3559
|
RatingComponent,
|
|
3118
|
-
], standalone: true, template: "<div class=\"rts-message-container\" #rtsMessageContainer\n [ngClass]=\"{\n 'rts-message-from-me': message.from.id === messenger.clientId,\n 'rts-message-is-widget': !!message.widget\n }\">\n <div class=\"rts-messenger-message\">\n @if (message.widget) {\n <ng-template widgetHost></ng-template>\n }\n @if (!message.widget) {\n <p class=\"rts-messenger-message-text\"\n >{{ message.text }}</p>\n }\n <div class=\"rts-messenger-message-info\" #rtsMessageInfo>\n <rtsee-message-time-and-status [message]=\"message\"\n [inChat]=\"true\"\n [hideStatus]=\"message.from.id !== messenger.clientId\"\n ></rtsee-message-time-and-status>\n </div>\n </div>\n</div>\n" }]
|
|
3560
|
+
], standalone: true, template: "<div class=\"rts-message-container\" #rtsMessageContainer\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"comment\"\n itemscope\n itemtype=\"https://schema.org/Comment\"\n [ngClass]=\"{\n 'rts-message-from-me': message.from.id === messenger.clientId,\n 'rts-message-is-widget': !!message.widget\n }\">\n <div class=\"rts-messenger-message\">\n @if (message.widget) {\n <ng-template widgetHost></ng-template>\n }\n @if (!message.widget) {\n <p class=\"rts-messenger-message-text\"\n itemprop=\"text\"\n data-ugc=\"true\"\n rel=\"ugc\"\n >{{ message.text }}</p>\n }\n <div class=\"rts-messenger-message-info\" #rtsMessageInfo>\n <rtsee-message-time-and-status [message]=\"message\"\n [inChat]=\"true\"\n [hideStatus]=\"message.from.id !== messenger.clientId\"\n ></rtsee-message-time-and-status>\n </div>\n </div>\n</div>\n" }]
|
|
3119
3561
|
}], ctorParameters: () => [{ type: MessageWidgetsService }, { type: i0.ComponentFactoryResolver }, { type: TimeFormatHelperService }], propDecorators: { chat: [{
|
|
3120
3562
|
type: Input
|
|
3121
3563
|
}], message: [{
|
|
@@ -3384,11 +3826,11 @@ class MessagesListComponent {
|
|
|
3384
3826
|
this.lastGroupedMessage = this.chat.messages[this.chat.messages.length - 1];
|
|
3385
3827
|
}
|
|
3386
3828
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MessagesListComponent, deps: [{ token: TimeFormatHelperService }, { token: i2$1.ViewportScroller }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3387
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MessagesListComponent, isStandalone: true, selector: "rtsee-messages-list", inputs: { chat: "chat", messenger: "messenger" }, host: { listeners: { "window:scroll": "onWindowScroll($event)", "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollBlock"], descendants: true }, { propertyName: "contentBlock", first: true, predicate: ["contentBlock"], descendants: true }, { propertyName: "bottomAnchor", first: true, predicate: ["bottomAnchor"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-messages-list\"\n #scrollBlock\n infiniteScroll\n [infiniteScrollUpDistance]=\"2\"\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [scrollWindow]=\"false\"\n (scrolledUp)=\"onScrolledToTop()\"\n (scroll)=\"onContainerScroll($event)\"\n [style.padding-bottom]=\"messenger.chatInputHeight + 'px'\"\n>\n <div class=\"rts-messages-list-inner\" #contentBlock>\n @for (messageGroup of messagesGroups; track messageGroup.id) {\n <div
|
|
3829
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: MessagesListComponent, isStandalone: true, selector: "rtsee-messages-list", inputs: { chat: "chat", messenger: "messenger" }, host: { listeners: { "window:scroll": "onWindowScroll($event)", "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollBlock"], descendants: true }, { propertyName: "contentBlock", first: true, predicate: ["contentBlock"], descendants: true }, { propertyName: "bottomAnchor", first: true, predicate: ["bottomAnchor"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rts-messages-list\"\n #scrollBlock\n infiniteScroll\n [infiniteScrollUpDistance]=\"2\"\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [scrollWindow]=\"false\"\n (scrolledUp)=\"onScrolledToTop()\"\n (scroll)=\"onContainerScroll($event)\"\n [style.padding-bottom]=\"messenger.chatInputHeight + 'px'\"\n>\n <div class=\"rts-messages-list-inner\" #contentBlock>\n @for (messageGroup of messagesGroups; track messageGroup.id) {\n <div\n class=\"rts-messenger-message-wrapper\"\n data-ugc=\"true\"\n rel=\"ugc\"\n [ngClass]=\"{\n 'rts-messenger-message-wrapper-with-sender': messageGroup.senderVisible\n }\"\n >\n <div class=\"rts-messenger-message-inset\">\n <img [src]=\"messageGroup.sender.imageUrl\"\n class=\"rts-messenger-message-sender-image\"\n >\n </div>\n\n <div\n class=\"rts-messenger-message-sender-name\"\n itemprop=\"author\"\n itemscope\n itemtype=\"https://schema.org/Person\"\n >\n <p itemprop=\"name\">{{messageGroup.sender.name}}</p>\n </div>\n\n @for (message of messageGroup.messages; track message.id) {\n <rtsee-message [message]=\"message\"\n [messenger]=\"messenger\"\n [chat]=\"chat\"\n ></rtsee-message>\n }\n </div>\n }\n <div class=\"rts-messages-list-bottom-anchor\" #bottomAnchor></div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "component", type: MessageComponent, selector: "rtsee-message", inputs: ["chat", "message", "member", "messenger"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
|
3388
3830
|
}
|
|
3389
3831
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: MessagesListComponent, decorators: [{
|
|
3390
3832
|
type: Component,
|
|
3391
|
-
args: [{ selector: 'rtsee-messages-list', imports: [InfiniteScrollDirective, MessageComponent, NgClass], standalone: true, template: "<div class=\"rts-messages-list\"\n #scrollBlock\n infiniteScroll\n [infiniteScrollUpDistance]=\"2\"\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [scrollWindow]=\"false\"\n (scrolledUp)=\"onScrolledToTop()\"\n (scroll)=\"onContainerScroll($event)\"\n [style.padding-bottom]=\"messenger.chatInputHeight + 'px'\"\n>\n <div class=\"rts-messages-list-inner\" #contentBlock>\n @for (messageGroup of messagesGroups; track messageGroup.id) {\n <div
|
|
3833
|
+
args: [{ selector: 'rtsee-messages-list', imports: [InfiniteScrollDirective, MessageComponent, NgClass], standalone: true, template: "<div class=\"rts-messages-list\"\n #scrollBlock\n infiniteScroll\n [infiniteScrollUpDistance]=\"2\"\n [infiniteScrollDistance]=\"2\"\n [infiniteScrollThrottle]=\"50\"\n [scrollWindow]=\"false\"\n (scrolledUp)=\"onScrolledToTop()\"\n (scroll)=\"onContainerScroll($event)\"\n [style.padding-bottom]=\"messenger.chatInputHeight + 'px'\"\n>\n <div class=\"rts-messages-list-inner\" #contentBlock>\n @for (messageGroup of messagesGroups; track messageGroup.id) {\n <div\n class=\"rts-messenger-message-wrapper\"\n data-ugc=\"true\"\n rel=\"ugc\"\n [ngClass]=\"{\n 'rts-messenger-message-wrapper-with-sender': messageGroup.senderVisible\n }\"\n >\n <div class=\"rts-messenger-message-inset\">\n <img [src]=\"messageGroup.sender.imageUrl\"\n class=\"rts-messenger-message-sender-image\"\n >\n </div>\n\n <div\n class=\"rts-messenger-message-sender-name\"\n itemprop=\"author\"\n itemscope\n itemtype=\"https://schema.org/Person\"\n >\n <p itemprop=\"name\">{{messageGroup.sender.name}}</p>\n </div>\n\n @for (message of messageGroup.messages; track message.id) {\n <rtsee-message [message]=\"message\"\n [messenger]=\"messenger\"\n [chat]=\"chat\"\n ></rtsee-message>\n }\n </div>\n }\n <div class=\"rts-messages-list-bottom-anchor\" #bottomAnchor></div>\n </div>\n</div>\n" }]
|
|
3392
3834
|
}], ctorParameters: () => [{ type: TimeFormatHelperService }, { type: i2$1.ViewportScroller }, { type: Document, decorators: [{
|
|
3393
3835
|
type: Inject,
|
|
3394
3836
|
args: [DOCUMENT]
|
|
@@ -5210,8 +5652,9 @@ class StoryElementsSectionComponent {
|
|
|
5210
5652
|
if (this._illustrator) {
|
|
5211
5653
|
this._illustrator.off('changed', this.onIllustratorChanged);
|
|
5212
5654
|
}
|
|
5213
|
-
for (const [
|
|
5214
|
-
window.removeEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED,
|
|
5655
|
+
for (const [, listeners] of this.activeGenerationListeners.entries()) {
|
|
5656
|
+
window.removeEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, listeners.succeed);
|
|
5657
|
+
window.removeEventListener(RTSeeIllustratorEvents.GENERATION_COMPLETED, listeners.completed);
|
|
5215
5658
|
}
|
|
5216
5659
|
this.activeGenerationListeners.clear();
|
|
5217
5660
|
}
|
|
@@ -5260,15 +5703,29 @@ class StoryElementsSectionComponent {
|
|
|
5260
5703
|
this.batchMode = false;
|
|
5261
5704
|
this.selectedItemIds.clear();
|
|
5262
5705
|
this.batchAdditionalPrompt = '';
|
|
5263
|
-
this.cdr.markForCheck();
|
|
5264
5706
|
for (const item of selectedItems) {
|
|
5265
|
-
const requestId = RTSeeCore.uuidv4();
|
|
5266
5707
|
this.generatingItemIds.add(item.id);
|
|
5267
|
-
|
|
5708
|
+
}
|
|
5709
|
+
this.cdr.markForCheck();
|
|
5710
|
+
const batchSpacingMs = 1200;
|
|
5711
|
+
for (let i = 0; i < selectedItems.length; i++) {
|
|
5712
|
+
const item = selectedItems[i];
|
|
5713
|
+
if (i > 0) {
|
|
5714
|
+
await new Promise((resolve) => setTimeout(resolve, batchSpacingMs));
|
|
5715
|
+
}
|
|
5716
|
+
const requestId = RTSeeCore.uuidv4();
|
|
5717
|
+
const cleanupListeners = () => {
|
|
5718
|
+
const entry = this.activeGenerationListeners.get(requestId);
|
|
5719
|
+
if (entry) {
|
|
5720
|
+
window.removeEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, entry.succeed);
|
|
5721
|
+
window.removeEventListener(RTSeeIllustratorEvents.GENERATION_COMPLETED, entry.completed);
|
|
5722
|
+
this.activeGenerationListeners.delete(requestId);
|
|
5723
|
+
}
|
|
5724
|
+
};
|
|
5725
|
+
const succeedListener = async (e) => {
|
|
5268
5726
|
const customEvent = e;
|
|
5269
5727
|
if (customEvent.detail?.requestId === requestId && customEvent.detail?.imageUrl) {
|
|
5270
|
-
|
|
5271
|
-
this.activeGenerationListeners.delete(requestId);
|
|
5728
|
+
cleanupListeners();
|
|
5272
5729
|
this.generatingItemIds.delete(item.id);
|
|
5273
5730
|
const cleanUrl = sanitizeImageUrl(customEvent.detail.imageUrl);
|
|
5274
5731
|
try {
|
|
@@ -5293,8 +5750,20 @@ class StoryElementsSectionComponent {
|
|
|
5293
5750
|
}
|
|
5294
5751
|
}
|
|
5295
5752
|
};
|
|
5296
|
-
|
|
5297
|
-
|
|
5753
|
+
const completedListener = (e) => {
|
|
5754
|
+
const customEvent = e;
|
|
5755
|
+
if (customEvent.detail?.requestId === requestId && customEvent.detail?.success === false) {
|
|
5756
|
+
cleanupListeners();
|
|
5757
|
+
this.generatingItemIds.delete(item.id);
|
|
5758
|
+
this.cdr.markForCheck();
|
|
5759
|
+
}
|
|
5760
|
+
};
|
|
5761
|
+
window.addEventListener(RTSeeIllustrator.REQUESTED_GENERATION_SUCCEED, succeedListener);
|
|
5762
|
+
window.addEventListener(RTSeeIllustratorEvents.GENERATION_COMPLETED, completedListener);
|
|
5763
|
+
this.activeGenerationListeners.set(requestId, {
|
|
5764
|
+
succeed: succeedListener,
|
|
5765
|
+
completed: completedListener,
|
|
5766
|
+
});
|
|
5298
5767
|
const promptParts = [];
|
|
5299
5768
|
promptParts.push(`${this.editor.label}: ${item.name || ''}`);
|
|
5300
5769
|
if (item.visualDescription) {
|
|
@@ -5319,7 +5788,7 @@ class StoryElementsSectionComponent {
|
|
|
5319
5788
|
chatId: this.illustrator?.activeChatId || undefined,
|
|
5320
5789
|
agentId: this.illustrator?.activeAgentId || '',
|
|
5321
5790
|
prompt: entityPrompt,
|
|
5322
|
-
config: { ...config },
|
|
5791
|
+
config: { ...config, numberOfImages: 1 },
|
|
5323
5792
|
contextImages: [],
|
|
5324
5793
|
requestId,
|
|
5325
5794
|
};
|
|
@@ -6084,11 +6553,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
6084
6553
|
|
|
6085
6554
|
class RtseeEntityCommentsComponent {
|
|
6086
6555
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RtseeEntityCommentsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6087
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RtseeEntityCommentsComponent, isStandalone: true, selector: "rtsee-entity-comments", inputs: { messenger: "messenger", chat: "chat", entity: "entity" }, ngImport: i0, template: "<div class=\"rtsee-entity-comments\">\n @if (messenger && chat) {\n <rtsee-chat [messenger]=\"messenger\"\n [chatData]=\"chat\"\n [entity]=\"entity\"\n ></rtsee-chat>\n }\n</div>\n", dependencies: [{ kind: "component", type: ChatComponent, selector: "rtsee-chat", inputs: ["chat", "chatData", "entity", "messenger"] }] }); }
|
|
6556
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RtseeEntityCommentsComponent, isStandalone: true, selector: "rtsee-entity-comments", inputs: { messenger: "messenger", chat: "chat", entity: "entity" }, ngImport: i0, template: "<div class=\"rtsee-entity-comments\" data-ugc=\"true\" rel=\"ugc\" aria-label=\"User comments\">\n @if (messenger && chat) {\n <rtsee-chat [messenger]=\"messenger\"\n [chatData]=\"chat\"\n [entity]=\"entity\"\n ></rtsee-chat>\n }\n</div>\n", dependencies: [{ kind: "component", type: ChatComponent, selector: "rtsee-chat", inputs: ["chat", "chatData", "entity", "messenger"] }] }); }
|
|
6088
6557
|
}
|
|
6089
6558
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RtseeEntityCommentsComponent, decorators: [{
|
|
6090
6559
|
type: Component,
|
|
6091
|
-
args: [{ selector: 'rtsee-entity-comments', imports: [ChatComponent], template: "<div class=\"rtsee-entity-comments\">\n @if (messenger && chat) {\n <rtsee-chat [messenger]=\"messenger\"\n [chatData]=\"chat\"\n [entity]=\"entity\"\n ></rtsee-chat>\n }\n</div>\n" }]
|
|
6560
|
+
args: [{ selector: 'rtsee-entity-comments', imports: [ChatComponent], template: "<div class=\"rtsee-entity-comments\" data-ugc=\"true\" rel=\"ugc\" aria-label=\"User comments\">\n @if (messenger && chat) {\n <rtsee-chat [messenger]=\"messenger\"\n [chatData]=\"chat\"\n [entity]=\"entity\"\n ></rtsee-chat>\n }\n</div>\n" }]
|
|
6092
6561
|
}], propDecorators: { messenger: [{
|
|
6093
6562
|
type: Input
|
|
6094
6563
|
}], chat: [{
|
|
@@ -6175,11 +6644,11 @@ class RateItemComponent {
|
|
|
6175
6644
|
return config ? config.name : '';
|
|
6176
6645
|
}
|
|
6177
6646
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RateItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6178
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RateItemComponent, isStandalone: true, selector: "rtsee-rate-item", inputs: { group: "group", rater: "rater", showActions: "showActions" }, outputs: { edit: "edit", delete: "delete" }, ngImport: i0, template: "<div
|
|
6647
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RateItemComponent, isStandalone: true, selector: "rtsee-rate-item", inputs: { group: "group", rater: "rater", showActions: "showActions" }, outputs: { edit: "edit", delete: "delete" }, ngImport: i0, template: "<div\n class=\"rtsee-rates-group-item\"\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"review\"\n itemscope\n itemtype=\"https://schema.org/Review\"\n>\n <div class=\"rtsee-rates-group-header\">\n <div\n class=\"rtsee-rates-group-user-info\"\n itemprop=\"author\"\n itemscope\n itemtype=\"https://schema.org/Person\"\n >\n @if (group.peer?.imageUrl) {\n <img\n class=\"rtsee-rates-group-avatar\"\n [src]=\"group.peer.imageUrl\"\n alt=\"User avatar\"\n itemprop=\"image\"\n />\n } @else {\n <div class=\"rtsee-rates-group-avatar-fallback\">\n {{ (group.peer?.name || \"?\").substring(0, 1) }}\n </div>\n }\n <span class=\"rtsee-rates-group-peer-name\" itemprop=\"name\">{{\n group.peer?.name || group.peerId\n }}</span>\n </div>\n\n <div class=\"rtsee-rates-group-right-header\">\n <span\n class=\"rtsee-rates-group-date\"\n itemprop=\"datePublished\"\n [attr.content]=\"group.createdAt\"\n >{{\n group.createdAt | date: \"short\"\n }}</span>\n\n @if (showActions) {\n <div class=\"rtsee-rates-group-actions\">\n <p-button\n (click)=\"onEdit($event)\"\n [severity]=\"'secondary'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-edit\"\n >\n <span class=\"pi pi-pencil\"></span>\n </p-button>\n <p-button\n (click)=\"onDelete($event)\"\n [severity]=\"'danger'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-delete\"\n >\n <span class=\"pi pi-trash\"></span>\n </p-button>\n </div>\n }\n </div>\n </div>\n <div class=\"rtsee-rates-group-body\">\n @for (rate of group.rates; track rate.id) {\n <div class=\"rtsee-rates-group-rate-item-container\">\n <div class=\"rtsee-rates-group-rate-item\">\n <span class=\"rtsee-rates-group-rate-config-name\">{{\n getRatingConfigName(rate.configurationId)\n }}</span>\n <rtsee-rating [rate]=\"rate\"></rtsee-rating>\n </div>\n @if (rate.text) {\n <p class=\"rtsee-rates-group-rate-comment\" itemprop=\"reviewBody\" data-ugc=\"true\" rel=\"ugc\">\"{{ rate.text }}\"</p>\n }\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: RatingComponent, selector: "rtsee-rating", inputs: ["config", "rate"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: DatePipe, name: "date" }] }); }
|
|
6179
6648
|
}
|
|
6180
6649
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RateItemComponent, decorators: [{
|
|
6181
6650
|
type: Component,
|
|
6182
|
-
args: [{ selector: 'rtsee-rate-item', imports: [RatingComponent, DatePipe, Button], template: "<div
|
|
6651
|
+
args: [{ selector: 'rtsee-rate-item', imports: [RatingComponent, DatePipe, Button], template: "<div\n class=\"rtsee-rates-group-item\"\n data-ugc=\"true\"\n rel=\"ugc\"\n itemprop=\"review\"\n itemscope\n itemtype=\"https://schema.org/Review\"\n>\n <div class=\"rtsee-rates-group-header\">\n <div\n class=\"rtsee-rates-group-user-info\"\n itemprop=\"author\"\n itemscope\n itemtype=\"https://schema.org/Person\"\n >\n @if (group.peer?.imageUrl) {\n <img\n class=\"rtsee-rates-group-avatar\"\n [src]=\"group.peer.imageUrl\"\n alt=\"User avatar\"\n itemprop=\"image\"\n />\n } @else {\n <div class=\"rtsee-rates-group-avatar-fallback\">\n {{ (group.peer?.name || \"?\").substring(0, 1) }}\n </div>\n }\n <span class=\"rtsee-rates-group-peer-name\" itemprop=\"name\">{{\n group.peer?.name || group.peerId\n }}</span>\n </div>\n\n <div class=\"rtsee-rates-group-right-header\">\n <span\n class=\"rtsee-rates-group-date\"\n itemprop=\"datePublished\"\n [attr.content]=\"group.createdAt\"\n >{{\n group.createdAt | date: \"short\"\n }}</span>\n\n @if (showActions) {\n <div class=\"rtsee-rates-group-actions\">\n <p-button\n (click)=\"onEdit($event)\"\n [severity]=\"'secondary'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-edit\"\n >\n <span class=\"pi pi-pencil\"></span>\n </p-button>\n <p-button\n (click)=\"onDelete($event)\"\n [severity]=\"'danger'\"\n [text]=\"true\"\n class=\"rtsee-rates-group-btn-delete\"\n >\n <span class=\"pi pi-trash\"></span>\n </p-button>\n </div>\n }\n </div>\n </div>\n <div class=\"rtsee-rates-group-body\">\n @for (rate of group.rates; track rate.id) {\n <div class=\"rtsee-rates-group-rate-item-container\">\n <div class=\"rtsee-rates-group-rate-item\">\n <span class=\"rtsee-rates-group-rate-config-name\">{{\n getRatingConfigName(rate.configurationId)\n }}</span>\n <rtsee-rating [rate]=\"rate\"></rtsee-rating>\n </div>\n @if (rate.text) {\n <p class=\"rtsee-rates-group-rate-comment\" itemprop=\"reviewBody\" data-ugc=\"true\" rel=\"ugc\">\"{{ rate.text }}\"</p>\n }\n </div>\n }\n </div>\n</div>\n" }]
|
|
6183
6652
|
}], propDecorators: { group: [{
|
|
6184
6653
|
type: Input
|
|
6185
6654
|
}], rater: [{
|
|
@@ -6296,11 +6765,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
6296
6765
|
|
|
6297
6766
|
class RatingSectionComponent {
|
|
6298
6767
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RatingSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6299
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: RatingSectionComponent, isStandalone: true, selector: "rtsee-rating-section", inputs: { rater: "rater", entity: "entity" }, ngImport: i0, template: "<div class=\"rtsee-rating-section\">\n <rtsee-rater [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rater>\n <rtsee-rates-list [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rates-list>\n</div>\n", dependencies: [{ kind: "component", type: RaterComponent, selector: "rtsee-rater", inputs: ["entity", "rater"] }, { kind: "component", type: RatesListComponent, selector: "rtsee-rates-list", inputs: ["rater", "entity"] }] }); }
|
|
6768
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: RatingSectionComponent, isStandalone: true, selector: "rtsee-rating-section", inputs: { rater: "rater", entity: "entity" }, ngImport: i0, template: "<div class=\"rtsee-rating-section\" data-ugc=\"true\" rel=\"ugc\" aria-label=\"User ratings and reviews\">\n <rtsee-rater [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rater>\n <rtsee-rates-list [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rates-list>\n</div>\n", dependencies: [{ kind: "component", type: RaterComponent, selector: "rtsee-rater", inputs: ["entity", "rater"] }, { kind: "component", type: RatesListComponent, selector: "rtsee-rates-list", inputs: ["rater", "entity"] }] }); }
|
|
6300
6769
|
}
|
|
6301
6770
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RatingSectionComponent, decorators: [{
|
|
6302
6771
|
type: Component,
|
|
6303
|
-
args: [{ selector: 'rtsee-rating-section', imports: [RaterComponent, RatesListComponent], template: "<div class=\"rtsee-rating-section\">\n <rtsee-rater [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rater>\n <rtsee-rates-list [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rates-list>\n</div>\n" }]
|
|
6772
|
+
args: [{ selector: 'rtsee-rating-section', imports: [RaterComponent, RatesListComponent], template: "<div class=\"rtsee-rating-section\" data-ugc=\"true\" rel=\"ugc\" aria-label=\"User ratings and reviews\">\n <rtsee-rater [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rater>\n <rtsee-rates-list [rater]=\"rater\"\n [entity]=\"entity\"\n ></rtsee-rates-list>\n</div>\n" }]
|
|
6304
6773
|
}], propDecorators: { rater: [{
|
|
6305
6774
|
type: Input
|
|
6306
6775
|
}], entity: [{
|
|
@@ -6539,11 +7008,11 @@ class StoryDetailsComponent {
|
|
|
6539
7008
|
return stars;
|
|
6540
7009
|
}
|
|
6541
7010
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6542
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryDetailsComponent, isStandalone: true, selector: "rtsee-story-details", inputs: { story: "story", presentation: "presentation", messenger: "messenger" }, ngImport: i0, template: "<div\n class=\"rtsee-story-details\"\n itemscope\n itemtype=\"https://schema.org/CreativeWork\"\n>\n @if (story.imageUrl) {\n <meta itemprop=\"image\" [attr.content]=\"story.imageUrl\" />\n }\n <section\n class=\"rtsee-story-details-cover\"\n [style.background-image]=\"'url(' + story.imageUrl + ')'\"\n >\n <button\n class=\"rtsee-story-details-btn-close\"\n [routerLink]=\"[presentation.homePage]\"\n (click)=\"presentation.closeStoryDetails()\"\n aria-label=\"Close\"\n >\n <span class=\"pi pi-times\"></span>\n </button>\n <div class=\"rtsee-story-details-cover-overlay\"></div>\n <div class=\"rtsee-story-details-cover-content\">\n <div class=\"rtsee-story-details-cover-badges\">\n @if (story.categories?.length && false) {\n @for (category of story.categories; track category.id) {\n <span class=\"rtsee-story-details-tag-pill\">\n {{ category.name }}\n </span>\n }\n }\n @if (story.tags?.length) {\n @for (tag of story.tags; track tag.id) {\n <span\n class=\"rtsee-story-details-tag-pill rtsee-story-details-tag-pill-label\"\n >\n @if (tag.symbol) {\n <span class=\"symbol\">{{ tag.symbol }}</span>\n }\n {{ tag.name }}\n </span>\n }\n }\n </div>\n\n <h1 class=\"rtsee-story-details-cover-title\" itemprop=\"name\">{{ story.name }}</h1>\n\n <div class=\"rtsee-story-details-cover-meta\">\n @if (story.rating !== null) {\n <div class=\"rtsee-story-details-cover-rating\">\n <span class=\"rtsee-story-details-stars\">\n @for (star of getStarArray(story.rating); track $index) {\n <span\n class=\"rtsee-story-details-star\"\n [class.rtsee-story-details-star-full]=\"star === 'full'\"\n [class.rtsee-story-details-star-half]=\"star === 'half'\"\n [class.rtsee-story-details-star-empty]=\"star === 'empty'\"\n >\n @if (star === \"full\") {\n \u2605\n } @else if (star === \"half\") {\n \u2605\n } @else {\n \u2606\n }\n </span>\n }\n </span>\n <span class=\"rtsee-story-details-rating-number\">{{\n story.rating\n }}</span>\n @if (story.ratesCount !== null) {\n <span class=\"rtsee-story-details-rating-count\">\n <span>(</span>\n <span>{{ presentation.labels[RTSeeTextLabelKeys.FEEDBACKS_LABEL] }}:</span>\n <span> </span>\n <span>{{ story.ratesCount }}</span>\n <span>)</span>\n </span\n >\n }\n </div>\n }\n </div>\n </div>\n </section>\n\n <!-- CONTENT AREA -->\n <div class=\"rtsee-story-details-content-wrapper\">\n <!-- Reading panel: what the user is about to read + the main CTA -->\n <section class=\"rtsee-story-details-reading-panel\" aria-label=\"{{ story.name }}\">\n @if (story.totalSlides) {\n <rtsee-story-slides-preview\n [story]=\"story\"\n [slidesLabel]=\"presentation.labels[RTSeeTextLabelKeys.STORY_PAGES_LABEL]\"\n [minuteLabel]=\"presentation.labels[RTSeeTextLabelKeys.MINUTE_LABEL]\"\n ></rtsee-story-slides-preview>\n }\n <p-button\n (click)=\"presentation.setActiveStory(story)\"\n [severity]=\"'primary'\"\n [label]=\"story.preselectedSlideNumber ? presentation.labels[RTSeeTextLabelKeys.CONTINUE_READING_BUTTON] : presentation.labels[RTSeeTextLabelKeys.START_READING_BUTTON]\"\n icon=\"pi pi-book\"\n iconPos=\"left\"\n class=\"rtsee-story-details-start-reading rts-action-button\"\n >\n </p-button>\n </section>\n <div class=\"rtsee-story-details-content-grid\">\n <!-- Description Card -->\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_ABOUT_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"description\">\n {{ story.description }}\n </p>\n </article>\n\n @if (story.history) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 14 14\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_HISTORY_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\">\n {{ story.history }}\n </p>\n </article>\n }\n\n @if (story.moralMeaning) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_MORAL_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\">\n {{ story.moralMeaning }}\n </p>\n </article>\n }\n </div>\n\n <!-- Author -->\n @if (story.author) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-author-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n <h2 id=\"rtsee-story-details-author-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.STORY_AUTHOR_LABEL] }}\n </h2>\n </header>\n <div class=\"rtsee-story-details-elements-featured\">\n <rtsee-story-element-thumbnail\n [name]=\"story.author.name\"\n [description]=\"story.author.description\"\n [imageUrl]=\"story.author.imageUrl\"\n itemProp=\"author\"\n schemaType=\"Person\"\n [horizontal]=\"true\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </div>\n </section>\n }\n\n <!-- Characters -->\n @if (story.characters.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-characters-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n <h2 id=\"rtsee-story-details-characters-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.CHARACTERS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (character of story.characters; track character.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"character.name\"\n [description]=\"character.description\"\n [imageUrl]=\"character.imageUrl\"\n itemProp=\"character\"\n schemaType=\"Person\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Artifacts -->\n @if (story.artifacts.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-artifacts-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h12l4 6-10 13L2 9z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n <h2 id=\"rtsee-story-details-artifacts-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.ARTIFACTS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (artifact of story.artifacts; track artifact.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"artifact.name\"\n [description]=\"artifact.description\"\n [imageUrl]=\"artifact.imageUrl\"\n itemProp=\"mentions\"\n schemaType=\"Thing\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Places -->\n @if (story.locations.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-places-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n <h2 id=\"rtsee-story-details-places-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.LOCATIONS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (place of story.locations; track place.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"place.name\"\n [description]=\"place.description\"\n [imageUrl]=\"place.imageUrl\"\n itemProp=\"contentLocation\"\n schemaType=\"Place\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n @if (messenger) {\n <rtsee-entity-preview\n [entity]=\"story\"\n [messenger]=\"messenger\"\n ></rtsee-entity-preview>\n }\n\n @if (story.categories?.length && false) {\n <div class=\"rtsee-story-details-categories\">\n @for (category of story.categories; track category.id) {\n <p-tag [value]=\"category.name\"></p-tag>\n }\n </div>\n }\n\n @if (story.tags?.length && false) {\n <div class=\"rtsee-story-details-labels\">\n @for (tag of story.tags; track tag.id) {\n <p-chip class=\"rtsee-story-details-label\">\n @if (tag.symbol) {\n <span class=\"rtsee-story-details-label-left\">{{\n tag.symbol\n }}</span>\n }\n <span class=\"rtsee-story-details-label-right\">{{\n tag.name\n }}</span>\n </p-chip>\n }\n </div>\n }\n\n <div class=\"rtsee-story-details-description-history\"></div>\n @if (story.isPublished && false) {\n <div class=\"rtsee-story-details-feedback\">\n <p>feedback here</p>\n </div>\n } @else if (messenger && story.discussion && false) {\n <div class=\"rtsee-story-details-votes\">\n <p class=\"rtsee-story-details-comments-label\">Comments</p>\n <rtsee-chat\n [messenger]=\"messenger\"\n [chatData]=\"story.discussion\"\n ></rtsee-chat>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ChatComponent, selector: "rtsee-chat", inputs: ["chat", "chatData", "entity", "messenger"] }, { kind: "component", type: RtseeEntityPreviewComponent, selector: "rtsee-entity-preview", inputs: ["entity", "messenger"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: StoryElementThumbnailComponent, selector: "rtsee-story-element-thumbnail", inputs: ["name", "description", "imageUrl", "itemProp", "schemaType", "horizontal", "showMoreLabel", "showLessLabel"] }, { kind: "component", type: StorySlidesPreviewComponent, selector: "rtsee-story-slides-preview", inputs: ["story", "slidesLabel", "minuteLabel", "count"] }] }); }
|
|
7011
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: StoryDetailsComponent, isStandalone: true, selector: "rtsee-story-details", inputs: { story: "story", presentation: "presentation", messenger: "messenger" }, ngImport: i0, template: "<div\n class=\"rtsee-story-details\"\n itemscope\n itemtype=\"https://schema.org/ShortStory\"\n>\n @if (story.imageUrl) {\n <meta itemprop=\"image\" [attr.content]=\"story.imageUrl\" />\n }\n @if (story.languageKey) {\n <meta itemprop=\"inLanguage\" [attr.content]=\"story.languageKey === 'ua' ? 'uk' : 'en'\" />\n }\n @if (story.totalSlides) {\n <meta itemprop=\"numberOfPages\" [attr.content]=\"story.totalSlides\" />\n }\n <section\n class=\"rtsee-story-details-cover\"\n [style.background-image]=\"'url(' + story.imageUrl + ')'\"\n >\n <button\n class=\"rtsee-story-details-btn-close\"\n [routerLink]=\"[presentation.homePage]\"\n (click)=\"presentation.closeStoryDetails()\"\n aria-label=\"Close\"\n >\n <span class=\"pi pi-times\"></span>\n </button>\n <div class=\"rtsee-story-details-cover-overlay\"></div>\n <div class=\"rtsee-story-details-cover-content\">\n <div class=\"rtsee-story-details-cover-badges\">\n @if (story.categories?.length && false) {\n @for (category of story.categories; track category.id) {\n <span class=\"rtsee-story-details-tag-pill\">\n {{ category.name }}\n </span>\n }\n }\n @if (story.tags?.length) {\n @for (tag of story.tags; track tag.id) {\n <span\n class=\"rtsee-story-details-tag-pill rtsee-story-details-tag-pill-label\"\n >\n @if (tag.symbol) {\n <span class=\"symbol\">{{ tag.symbol }}</span>\n }\n {{ tag.name }}\n </span>\n }\n }\n </div>\n\n <h1 class=\"rtsee-story-details-cover-title\" itemprop=\"name\">{{ story.name }}</h1>\n\n <div class=\"rtsee-story-details-cover-meta\">\n @if (story.rating !== null) {\n <div\n class=\"rtsee-story-details-cover-rating\"\n itemprop=\"aggregateRating\"\n itemscope\n itemtype=\"https://schema.org/AggregateRating\"\n >\n <meta itemprop=\"bestRating\" content=\"5\" />\n <meta itemprop=\"worstRating\" content=\"1\" />\n <span class=\"rtsee-story-details-stars\">\n @for (star of getStarArray(story.rating); track $index) {\n <span\n class=\"rtsee-story-details-star\"\n [class.rtsee-story-details-star-full]=\"star === 'full'\"\n [class.rtsee-story-details-star-half]=\"star === 'half'\"\n [class.rtsee-story-details-star-empty]=\"star === 'empty'\"\n >\n @if (star === \"full\") {\n \u2605\n } @else if (star === \"half\") {\n \u2605\n } @else {\n \u2606\n }\n </span>\n }\n </span>\n <span class=\"rtsee-story-details-rating-number\" itemprop=\"ratingValue\">{{\n story.rating\n }}</span>\n @if (story.ratesCount !== null) {\n <meta itemprop=\"ratingCount\" [attr.content]=\"story.ratesCount\" />\n <span class=\"rtsee-story-details-rating-count\">\n <span>(</span>\n <span>{{ presentation.labels[RTSeeTextLabelKeys.FEEDBACKS_LABEL] }}:</span>\n <span> </span>\n <span itemprop=\"reviewCount\">{{ story.ratesCount }}</span>\n <span>)</span>\n </span\n >\n }\n </div>\n }\n </div>\n </div>\n </section>\n\n <!-- CONTENT AREA -->\n <div class=\"rtsee-story-details-content-wrapper\">\n <!-- Reading panel: what the user is about to read + the main CTA -->\n <section class=\"rtsee-story-details-reading-panel\" aria-label=\"{{ story.name }}\">\n @if (story.totalSlides) {\n <rtsee-story-slides-preview\n [story]=\"story\"\n [slidesLabel]=\"presentation.labels[RTSeeTextLabelKeys.STORY_PAGES_LABEL]\"\n [minuteLabel]=\"presentation.labels[RTSeeTextLabelKeys.MINUTE_LABEL]\"\n ></rtsee-story-slides-preview>\n }\n <p-button\n (click)=\"presentation.setActiveStory(story)\"\n [severity]=\"'primary'\"\n [label]=\"story.preselectedSlideNumber ? presentation.labels[RTSeeTextLabelKeys.CONTINUE_READING_BUTTON] : presentation.labels[RTSeeTextLabelKeys.START_READING_BUTTON]\"\n icon=\"pi pi-book\"\n iconPos=\"left\"\n class=\"rtsee-story-details-start-reading rts-action-button\"\n >\n </p-button>\n </section>\n <div class=\"rtsee-story-details-content-grid\">\n <!-- Description Card -->\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_ABOUT_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"description\">\n {{ story.description }}\n </p>\n </article>\n\n @if (story.history) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 14 14\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_HISTORY_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"backstory\">\n {{ story.history }}\n </p>\n </article>\n }\n\n @if (story.moralMeaning) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_MORAL_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"teaches\">\n {{ story.moralMeaning }}\n </p>\n </article>\n }\n </div>\n\n <!-- Author -->\n @if (story.author) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-author-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n <h2 id=\"rtsee-story-details-author-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.STORY_AUTHOR_LABEL] }}\n </h2>\n </header>\n <div class=\"rtsee-story-details-elements-featured\">\n <rtsee-story-element-thumbnail\n [name]=\"story.author.name\"\n [description]=\"story.author.description\"\n [imageUrl]=\"story.author.imageUrl\"\n itemProp=\"author\"\n schemaType=\"Person\"\n [horizontal]=\"true\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </div>\n </section>\n }\n\n <!-- Characters -->\n @if (story.characters.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-characters-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n <h2 id=\"rtsee-story-details-characters-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.CHARACTERS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (character of story.characters; track character.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"character.name\"\n [description]=\"character.description\"\n [imageUrl]=\"character.imageUrl\"\n itemProp=\"character\"\n schemaType=\"Person\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Artifacts -->\n @if (story.artifacts.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-artifacts-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h12l4 6-10 13L2 9z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n <h2 id=\"rtsee-story-details-artifacts-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.ARTIFACTS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (artifact of story.artifacts; track artifact.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"artifact.name\"\n [description]=\"artifact.description\"\n [imageUrl]=\"artifact.imageUrl\"\n itemProp=\"mentions\"\n schemaType=\"Thing\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Places -->\n @if (story.locations.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-places-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n <h2 id=\"rtsee-story-details-places-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.LOCATIONS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (place of story.locations; track place.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"place.name\"\n [description]=\"place.description\"\n [imageUrl]=\"place.imageUrl\"\n itemProp=\"contentLocation\"\n schemaType=\"Place\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n @if (messenger) {\n <rtsee-entity-preview\n [entity]=\"story\"\n [messenger]=\"messenger\"\n ></rtsee-entity-preview>\n }\n\n @if (story.categories?.length && false) {\n <div class=\"rtsee-story-details-categories\">\n @for (category of story.categories; track category.id) {\n <p-tag [value]=\"category.name\"></p-tag>\n }\n </div>\n }\n\n @if (story.tags?.length && false) {\n <div class=\"rtsee-story-details-labels\">\n @for (tag of story.tags; track tag.id) {\n <p-chip class=\"rtsee-story-details-label\">\n @if (tag.symbol) {\n <span class=\"rtsee-story-details-label-left\">{{\n tag.symbol\n }}</span>\n }\n <span class=\"rtsee-story-details-label-right\">{{\n tag.name\n }}</span>\n </p-chip>\n }\n </div>\n }\n\n <div class=\"rtsee-story-details-description-history\"></div>\n @if (story.isPublished && false) {\n <div class=\"rtsee-story-details-feedback\">\n <p>feedback here</p>\n </div>\n } @else if (messenger && story.discussion && false) {\n <div class=\"rtsee-story-details-votes\">\n <p class=\"rtsee-story-details-comments-label\">Comments</p>\n <rtsee-chat\n [messenger]=\"messenger\"\n [chatData]=\"story.discussion\"\n ></rtsee-chat>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ChatComponent, selector: "rtsee-chat", inputs: ["chat", "chatData", "entity", "messenger"] }, { kind: "component", type: RtseeEntityPreviewComponent, selector: "rtsee-entity-preview", inputs: ["entity", "messenger"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: StoryElementThumbnailComponent, selector: "rtsee-story-element-thumbnail", inputs: ["name", "description", "imageUrl", "itemProp", "schemaType", "horizontal", "showMoreLabel", "showLessLabel"] }, { kind: "component", type: StorySlidesPreviewComponent, selector: "rtsee-story-slides-preview", inputs: ["story", "slidesLabel", "minuteLabel", "count"] }] }); }
|
|
6543
7012
|
}
|
|
6544
7013
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: StoryDetailsComponent, decorators: [{
|
|
6545
7014
|
type: Component,
|
|
6546
|
-
args: [{ selector: 'rtsee-story-details', imports: [Chip, Tag, Button, ChatComponent, RtseeEntityPreviewComponent, RouterLink, StoryElementThumbnailComponent, StorySlidesPreviewComponent], template: "<div\n class=\"rtsee-story-details\"\n itemscope\n itemtype=\"https://schema.org/CreativeWork\"\n>\n @if (story.imageUrl) {\n <meta itemprop=\"image\" [attr.content]=\"story.imageUrl\" />\n }\n <section\n class=\"rtsee-story-details-cover\"\n [style.background-image]=\"'url(' + story.imageUrl + ')'\"\n >\n <button\n class=\"rtsee-story-details-btn-close\"\n [routerLink]=\"[presentation.homePage]\"\n (click)=\"presentation.closeStoryDetails()\"\n aria-label=\"Close\"\n >\n <span class=\"pi pi-times\"></span>\n </button>\n <div class=\"rtsee-story-details-cover-overlay\"></div>\n <div class=\"rtsee-story-details-cover-content\">\n <div class=\"rtsee-story-details-cover-badges\">\n @if (story.categories?.length && false) {\n @for (category of story.categories; track category.id) {\n <span class=\"rtsee-story-details-tag-pill\">\n {{ category.name }}\n </span>\n }\n }\n @if (story.tags?.length) {\n @for (tag of story.tags; track tag.id) {\n <span\n class=\"rtsee-story-details-tag-pill rtsee-story-details-tag-pill-label\"\n >\n @if (tag.symbol) {\n <span class=\"symbol\">{{ tag.symbol }}</span>\n }\n {{ tag.name }}\n </span>\n }\n }\n </div>\n\n <h1 class=\"rtsee-story-details-cover-title\" itemprop=\"name\">{{ story.name }}</h1>\n\n <div class=\"rtsee-story-details-cover-meta\">\n @if (story.rating !== null) {\n <div class=\"rtsee-story-details-cover-rating\">\n <span class=\"rtsee-story-details-stars\">\n @for (star of getStarArray(story.rating); track $index) {\n <span\n class=\"rtsee-story-details-star\"\n [class.rtsee-story-details-star-full]=\"star === 'full'\"\n [class.rtsee-story-details-star-half]=\"star === 'half'\"\n [class.rtsee-story-details-star-empty]=\"star === 'empty'\"\n >\n @if (star === \"full\") {\n \u2605\n } @else if (star === \"half\") {\n \u2605\n } @else {\n \u2606\n }\n </span>\n }\n </span>\n <span class=\"rtsee-story-details-rating-number\">{{\n story.rating\n }}</span>\n @if (story.ratesCount !== null) {\n <span class=\"rtsee-story-details-rating-count\">\n <span>(</span>\n <span>{{ presentation.labels[RTSeeTextLabelKeys.FEEDBACKS_LABEL] }}:</span>\n <span> </span>\n <span>{{ story.ratesCount }}</span>\n <span>)</span>\n </span\n >\n }\n </div>\n }\n </div>\n </div>\n </section>\n\n <!-- CONTENT AREA -->\n <div class=\"rtsee-story-details-content-wrapper\">\n <!-- Reading panel: what the user is about to read + the main CTA -->\n <section class=\"rtsee-story-details-reading-panel\" aria-label=\"{{ story.name }}\">\n @if (story.totalSlides) {\n <rtsee-story-slides-preview\n [story]=\"story\"\n [slidesLabel]=\"presentation.labels[RTSeeTextLabelKeys.STORY_PAGES_LABEL]\"\n [minuteLabel]=\"presentation.labels[RTSeeTextLabelKeys.MINUTE_LABEL]\"\n ></rtsee-story-slides-preview>\n }\n <p-button\n (click)=\"presentation.setActiveStory(story)\"\n [severity]=\"'primary'\"\n [label]=\"story.preselectedSlideNumber ? presentation.labels[RTSeeTextLabelKeys.CONTINUE_READING_BUTTON] : presentation.labels[RTSeeTextLabelKeys.START_READING_BUTTON]\"\n icon=\"pi pi-book\"\n iconPos=\"left\"\n class=\"rtsee-story-details-start-reading rts-action-button\"\n >\n </p-button>\n </section>\n <div class=\"rtsee-story-details-content-grid\">\n <!-- Description Card -->\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_ABOUT_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"description\">\n {{ story.description }}\n </p>\n </article>\n\n @if (story.history) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 14 14\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_HISTORY_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\">\n {{ story.history }}\n </p>\n </article>\n }\n\n @if (story.moralMeaning) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_MORAL_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\">\n {{ story.moralMeaning }}\n </p>\n </article>\n }\n </div>\n\n <!-- Author -->\n @if (story.author) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-author-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n <h2 id=\"rtsee-story-details-author-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.STORY_AUTHOR_LABEL] }}\n </h2>\n </header>\n <div class=\"rtsee-story-details-elements-featured\">\n <rtsee-story-element-thumbnail\n [name]=\"story.author.name\"\n [description]=\"story.author.description\"\n [imageUrl]=\"story.author.imageUrl\"\n itemProp=\"author\"\n schemaType=\"Person\"\n [horizontal]=\"true\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </div>\n </section>\n }\n\n <!-- Characters -->\n @if (story.characters.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-characters-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n <h2 id=\"rtsee-story-details-characters-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.CHARACTERS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (character of story.characters; track character.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"character.name\"\n [description]=\"character.description\"\n [imageUrl]=\"character.imageUrl\"\n itemProp=\"character\"\n schemaType=\"Person\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Artifacts -->\n @if (story.artifacts.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-artifacts-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h12l4 6-10 13L2 9z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n <h2 id=\"rtsee-story-details-artifacts-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.ARTIFACTS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (artifact of story.artifacts; track artifact.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"artifact.name\"\n [description]=\"artifact.description\"\n [imageUrl]=\"artifact.imageUrl\"\n itemProp=\"mentions\"\n schemaType=\"Thing\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Places -->\n @if (story.locations.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-places-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n <h2 id=\"rtsee-story-details-places-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.LOCATIONS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (place of story.locations; track place.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"place.name\"\n [description]=\"place.description\"\n [imageUrl]=\"place.imageUrl\"\n itemProp=\"contentLocation\"\n schemaType=\"Place\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n @if (messenger) {\n <rtsee-entity-preview\n [entity]=\"story\"\n [messenger]=\"messenger\"\n ></rtsee-entity-preview>\n }\n\n @if (story.categories?.length && false) {\n <div class=\"rtsee-story-details-categories\">\n @for (category of story.categories; track category.id) {\n <p-tag [value]=\"category.name\"></p-tag>\n }\n </div>\n }\n\n @if (story.tags?.length && false) {\n <div class=\"rtsee-story-details-labels\">\n @for (tag of story.tags; track tag.id) {\n <p-chip class=\"rtsee-story-details-label\">\n @if (tag.symbol) {\n <span class=\"rtsee-story-details-label-left\">{{\n tag.symbol\n }}</span>\n }\n <span class=\"rtsee-story-details-label-right\">{{\n tag.name\n }}</span>\n </p-chip>\n }\n </div>\n }\n\n <div class=\"rtsee-story-details-description-history\"></div>\n @if (story.isPublished && false) {\n <div class=\"rtsee-story-details-feedback\">\n <p>feedback here</p>\n </div>\n } @else if (messenger && story.discussion && false) {\n <div class=\"rtsee-story-details-votes\">\n <p class=\"rtsee-story-details-comments-label\">Comments</p>\n <rtsee-chat\n [messenger]=\"messenger\"\n [chatData]=\"story.discussion\"\n ></rtsee-chat>\n </div>\n }\n </div>\n</div>\n" }]
|
|
7015
|
+
args: [{ selector: 'rtsee-story-details', imports: [Chip, Tag, Button, ChatComponent, RtseeEntityPreviewComponent, RouterLink, StoryElementThumbnailComponent, StorySlidesPreviewComponent], template: "<div\n class=\"rtsee-story-details\"\n itemscope\n itemtype=\"https://schema.org/ShortStory\"\n>\n @if (story.imageUrl) {\n <meta itemprop=\"image\" [attr.content]=\"story.imageUrl\" />\n }\n @if (story.languageKey) {\n <meta itemprop=\"inLanguage\" [attr.content]=\"story.languageKey === 'ua' ? 'uk' : 'en'\" />\n }\n @if (story.totalSlides) {\n <meta itemprop=\"numberOfPages\" [attr.content]=\"story.totalSlides\" />\n }\n <section\n class=\"rtsee-story-details-cover\"\n [style.background-image]=\"'url(' + story.imageUrl + ')'\"\n >\n <button\n class=\"rtsee-story-details-btn-close\"\n [routerLink]=\"[presentation.homePage]\"\n (click)=\"presentation.closeStoryDetails()\"\n aria-label=\"Close\"\n >\n <span class=\"pi pi-times\"></span>\n </button>\n <div class=\"rtsee-story-details-cover-overlay\"></div>\n <div class=\"rtsee-story-details-cover-content\">\n <div class=\"rtsee-story-details-cover-badges\">\n @if (story.categories?.length && false) {\n @for (category of story.categories; track category.id) {\n <span class=\"rtsee-story-details-tag-pill\">\n {{ category.name }}\n </span>\n }\n }\n @if (story.tags?.length) {\n @for (tag of story.tags; track tag.id) {\n <span\n class=\"rtsee-story-details-tag-pill rtsee-story-details-tag-pill-label\"\n >\n @if (tag.symbol) {\n <span class=\"symbol\">{{ tag.symbol }}</span>\n }\n {{ tag.name }}\n </span>\n }\n }\n </div>\n\n <h1 class=\"rtsee-story-details-cover-title\" itemprop=\"name\">{{ story.name }}</h1>\n\n <div class=\"rtsee-story-details-cover-meta\">\n @if (story.rating !== null) {\n <div\n class=\"rtsee-story-details-cover-rating\"\n itemprop=\"aggregateRating\"\n itemscope\n itemtype=\"https://schema.org/AggregateRating\"\n >\n <meta itemprop=\"bestRating\" content=\"5\" />\n <meta itemprop=\"worstRating\" content=\"1\" />\n <span class=\"rtsee-story-details-stars\">\n @for (star of getStarArray(story.rating); track $index) {\n <span\n class=\"rtsee-story-details-star\"\n [class.rtsee-story-details-star-full]=\"star === 'full'\"\n [class.rtsee-story-details-star-half]=\"star === 'half'\"\n [class.rtsee-story-details-star-empty]=\"star === 'empty'\"\n >\n @if (star === \"full\") {\n \u2605\n } @else if (star === \"half\") {\n \u2605\n } @else {\n \u2606\n }\n </span>\n }\n </span>\n <span class=\"rtsee-story-details-rating-number\" itemprop=\"ratingValue\">{{\n story.rating\n }}</span>\n @if (story.ratesCount !== null) {\n <meta itemprop=\"ratingCount\" [attr.content]=\"story.ratesCount\" />\n <span class=\"rtsee-story-details-rating-count\">\n <span>(</span>\n <span>{{ presentation.labels[RTSeeTextLabelKeys.FEEDBACKS_LABEL] }}:</span>\n <span> </span>\n <span itemprop=\"reviewCount\">{{ story.ratesCount }}</span>\n <span>)</span>\n </span\n >\n }\n </div>\n }\n </div>\n </div>\n </section>\n\n <!-- CONTENT AREA -->\n <div class=\"rtsee-story-details-content-wrapper\">\n <!-- Reading panel: what the user is about to read + the main CTA -->\n <section class=\"rtsee-story-details-reading-panel\" aria-label=\"{{ story.name }}\">\n @if (story.totalSlides) {\n <rtsee-story-slides-preview\n [story]=\"story\"\n [slidesLabel]=\"presentation.labels[RTSeeTextLabelKeys.STORY_PAGES_LABEL]\"\n [minuteLabel]=\"presentation.labels[RTSeeTextLabelKeys.MINUTE_LABEL]\"\n ></rtsee-story-slides-preview>\n }\n <p-button\n (click)=\"presentation.setActiveStory(story)\"\n [severity]=\"'primary'\"\n [label]=\"story.preselectedSlideNumber ? presentation.labels[RTSeeTextLabelKeys.CONTINUE_READING_BUTTON] : presentation.labels[RTSeeTextLabelKeys.START_READING_BUTTON]\"\n icon=\"pi pi-book\"\n iconPos=\"left\"\n class=\"rtsee-story-details-start-reading rts-action-button\"\n >\n </p-button>\n </section>\n <div class=\"rtsee-story-details-content-grid\">\n <!-- Description Card -->\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_ABOUT_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"description\">\n {{ story.description }}\n </p>\n </article>\n\n @if (story.history) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 14 14\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_HISTORY_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"backstory\">\n {{ story.history }}\n </p>\n </article>\n }\n\n @if (story.moralMeaning) {\n <article class=\"rtsee-story-details-glass-card\">\n <div class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n <h2>{{presentation.labels[RTSeeTextLabelKeys.STORY_MORAL_LABEL]}}</h2>\n </div>\n <p class=\"rtsee-story-details-glass-card-text\" itemprop=\"teaches\">\n {{ story.moralMeaning }}\n </p>\n </article>\n }\n </div>\n\n <!-- Author -->\n @if (story.author) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-author-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n <h2 id=\"rtsee-story-details-author-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.STORY_AUTHOR_LABEL] }}\n </h2>\n </header>\n <div class=\"rtsee-story-details-elements-featured\">\n <rtsee-story-element-thumbnail\n [name]=\"story.author.name\"\n [description]=\"story.author.description\"\n [imageUrl]=\"story.author.imageUrl\"\n itemProp=\"author\"\n schemaType=\"Person\"\n [horizontal]=\"true\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </div>\n </section>\n }\n\n <!-- Characters -->\n @if (story.characters.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-characters-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n <h2 id=\"rtsee-story-details-characters-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.CHARACTERS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (character of story.characters; track character.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"character.name\"\n [description]=\"character.description\"\n [imageUrl]=\"character.imageUrl\"\n itemProp=\"character\"\n schemaType=\"Person\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Artifacts -->\n @if (story.artifacts.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-artifacts-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h12l4 6-10 13L2 9z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n <h2 id=\"rtsee-story-details-artifacts-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.ARTIFACTS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (artifact of story.artifacts; track artifact.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"artifact.name\"\n [description]=\"artifact.description\"\n [imageUrl]=\"artifact.imageUrl\"\n itemProp=\"mentions\"\n schemaType=\"Thing\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n <!-- Places -->\n @if (story.locations.length) {\n <section\n class=\"rtsee-story-details-elements\"\n aria-labelledby=\"rtsee-story-details-places-heading\"\n >\n <header class=\"rtsee-story-details-glass-card-header\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n <h2 id=\"rtsee-story-details-places-heading\">\n {{ presentation.labels[RTSeeTextLabelKeys.LOCATIONS_LABEL] }}\n </h2>\n </header>\n <ul class=\"rtsee-story-details-elements-grid\" role=\"list\">\n @for (place of story.locations; track place.id) {\n <li class=\"rtsee-story-details-elements-item\">\n <rtsee-story-element-thumbnail\n [name]=\"place.name\"\n [description]=\"place.description\"\n [imageUrl]=\"place.imageUrl\"\n itemProp=\"contentLocation\"\n schemaType=\"Place\"\n [showMoreLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_MORE_LABEL]\"\n [showLessLabel]=\"presentation.labels[RTSeeTextLabelKeys.SHOW_LESS_LABEL]\"\n ></rtsee-story-element-thumbnail>\n </li>\n }\n </ul>\n </section>\n }\n\n @if (messenger) {\n <rtsee-entity-preview\n [entity]=\"story\"\n [messenger]=\"messenger\"\n ></rtsee-entity-preview>\n }\n\n @if (story.categories?.length && false) {\n <div class=\"rtsee-story-details-categories\">\n @for (category of story.categories; track category.id) {\n <p-tag [value]=\"category.name\"></p-tag>\n }\n </div>\n }\n\n @if (story.tags?.length && false) {\n <div class=\"rtsee-story-details-labels\">\n @for (tag of story.tags; track tag.id) {\n <p-chip class=\"rtsee-story-details-label\">\n @if (tag.symbol) {\n <span class=\"rtsee-story-details-label-left\">{{\n tag.symbol\n }}</span>\n }\n <span class=\"rtsee-story-details-label-right\">{{\n tag.name\n }}</span>\n </p-chip>\n }\n </div>\n }\n\n <div class=\"rtsee-story-details-description-history\"></div>\n @if (story.isPublished && false) {\n <div class=\"rtsee-story-details-feedback\">\n <p>feedback here</p>\n </div>\n } @else if (messenger && story.discussion && false) {\n <div class=\"rtsee-story-details-votes\">\n <p class=\"rtsee-story-details-comments-label\">Comments</p>\n <rtsee-chat\n [messenger]=\"messenger\"\n [chatData]=\"story.discussion\"\n ></rtsee-chat>\n </div>\n }\n </div>\n</div>\n" }]
|
|
6547
7016
|
}], propDecorators: { story: [{
|
|
6548
7017
|
type: Input
|
|
6549
7018
|
}], presentation: [{
|
|
@@ -6623,7 +7092,7 @@ class RtseeNavComponent {
|
|
|
6623
7092
|
return false;
|
|
6624
7093
|
}
|
|
6625
7094
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RtseeNavComponent, deps: [{ token: RTSeeAuthService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6626
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RtseeNavComponent, isStandalone: true, selector: "rtsee-nav", inputs: { config: "config", rtsee: "rtsee" }, ngImport: i0, template: "<div class=\"rtsee-nav\">\n @if (config.siteLogo) {\n <div class=\"rtsee-site-logo\">\n <p-image [src]=\"config.siteLogo.src\" class=\"rtsee-site-logo-image\"></p-image>\n <p-divider class=\"rtsee-site-logo-divider\" />\n </div>\n }\n <div class=\"rtsee-nav-bar\">\n @for (route of config.routes; track route.name) {\n <a [routerLink]=\"route.link\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [ngClass]=\"{'rtsee-nav-item-hidden': !route.isEnabled || !route.iconClassName}\"\n [routerLinkActiveOptions]=\"{ exact: route.exactActiveLinkMatcher || false }\"\n class=\"rtsee-nav-item\"\n [pTooltip]=\"route.name\"\n >\n <span [ngClass]=\"route.iconClassName\"\n class=\"rtsee-nav-item-icon\" >\n </span>\n </a>\n }\n <p-avatar [image]=\"rtsee.socketConnection?.myPeer?.imageUrl\"\n class=\"rtsee-nav-item rtsee-nav-image rtsee-nav-profile\"\n [routerLink]=\"profileLink\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [routerLinkActiveOptions]=\"{exact: true}\"\n [queryParams]=\"queryParams\"\n ></p-avatar>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "component", type: Image, selector: "p-image", inputs: ["imageClass", "imageStyle", "styleClass", "src", "srcSet", "sizes", "previewImageSrc", "previewImageSrcSet", "previewImageSizes", "alt", "width", "height", "loading", "preview", "showTransitionOptions", "hideTransitionOptions", "appendTo"], outputs: ["onShow", "onHide", "onImageError"] }, { kind: "component", type: Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }] }); }
|
|
7095
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: RtseeNavComponent, isStandalone: true, selector: "rtsee-nav", inputs: { config: "config", rtsee: "rtsee" }, ngImport: i0, template: "<div class=\"rtsee-nav\">\n @if (config.siteLogo) {\n <div class=\"rtsee-site-logo\">\n <p-image [src]=\"config.siteLogo.src\" class=\"rtsee-site-logo-image\"></p-image>\n <p-divider class=\"rtsee-site-logo-divider\" />\n </div>\n }\n <div class=\"rtsee-nav-bar\">\n @for (route of config.routes; track route.name) {\n <a [routerLink]=\"route.link\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [ngClass]=\"{'rtsee-nav-item-hidden': !route.isEnabled || !route.iconClassName}\"\n [routerLinkActiveOptions]=\"{ exact: route.exactActiveLinkMatcher || false }\"\n class=\"rtsee-nav-item\"\n [pTooltip]=\"route.name\"\n >\n <span [ngClass]=\"route.iconClassName\"\n class=\"rtsee-nav-item-icon\" >\n </span>\n </a>\n }\n <p-avatar [image]=\"rtsee.socketConnection?.myPeer?.imageUrl\"\n class=\"rtsee-nav-item rtsee-nav-image rtsee-nav-profile\"\n [routerLink]=\"profileLink\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [routerLinkActiveOptions]=\"{exact: true}\"\n [queryParams]=\"queryParams\"\n ></p-avatar>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "component", type: Image$1, selector: "p-image", inputs: ["imageClass", "imageStyle", "styleClass", "src", "srcSet", "sizes", "previewImageSrc", "previewImageSrcSet", "previewImageSizes", "alt", "width", "height", "loading", "preview", "showTransitionOptions", "hideTransitionOptions", "appendTo"], outputs: ["onShow", "onHide", "onImageError"] }, { kind: "component", type: Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }] }); }
|
|
6627
7096
|
}
|
|
6628
7097
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: RtseeNavComponent, decorators: [{
|
|
6629
7098
|
type: Component,
|
|
@@ -6632,7 +7101,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
6632
7101
|
RouterLinkActive,
|
|
6633
7102
|
NgClass,
|
|
6634
7103
|
Avatar,
|
|
6635
|
-
Image,
|
|
7104
|
+
Image$1,
|
|
6636
7105
|
Divider,
|
|
6637
7106
|
Tooltip,
|
|
6638
7107
|
], standalone: true, template: "<div class=\"rtsee-nav\">\n @if (config.siteLogo) {\n <div class=\"rtsee-site-logo\">\n <p-image [src]=\"config.siteLogo.src\" class=\"rtsee-site-logo-image\"></p-image>\n <p-divider class=\"rtsee-site-logo-divider\" />\n </div>\n }\n <div class=\"rtsee-nav-bar\">\n @for (route of config.routes; track route.name) {\n <a [routerLink]=\"route.link\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [ngClass]=\"{'rtsee-nav-item-hidden': !route.isEnabled || !route.iconClassName}\"\n [routerLinkActiveOptions]=\"{ exact: route.exactActiveLinkMatcher || false }\"\n class=\"rtsee-nav-item\"\n [pTooltip]=\"route.name\"\n >\n <span [ngClass]=\"route.iconClassName\"\n class=\"rtsee-nav-item-icon\" >\n </span>\n </a>\n }\n <p-avatar [image]=\"rtsee.socketConnection?.myPeer?.imageUrl\"\n class=\"rtsee-nav-item rtsee-nav-image rtsee-nav-profile\"\n [routerLink]=\"profileLink\"\n routerLinkActive=\"rtsee-nav-item-active\"\n [routerLinkActiveOptions]=\"{exact: true}\"\n [queryParams]=\"queryParams\"\n ></p-avatar>\n </div>\n</div>\n" }]
|