@dataclouder/ngx-lessons 0.1.3 → 0.1.4

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.
Files changed (42) hide show
  1. package/fesm2022/dataclouder-ngx-lessons.mjs +543 -537
  2. package/fesm2022/dataclouder-ngx-lessons.mjs.map +1 -1
  3. package/index.d.ts +643 -5
  4. package/package.json +1 -1
  5. package/lib/components/courses/course-detail/course-detail.component.d.ts +0 -5
  6. package/lib/components/courses/course-form/course-form.component.d.ts +0 -35
  7. package/lib/components/courses/course-list/course-list.component.d.ts +0 -25
  8. package/lib/components/courses/courses.component.d.ts +0 -5
  9. package/lib/components/courses/courses.service.d.ts +0 -14
  10. package/lib/components/courses/models/courses.model.d.ts +0 -24
  11. package/lib/components/courses-admin/courses-admin.component.d.ts +0 -8
  12. package/lib/components/dc-lessons/dc-lesson-card/dc-lesson-card.component.d.ts +0 -25
  13. package/lib/components/dc-lessons/dc-lesson-component-adder/dc-lesson-component-adder.component.d.ts +0 -11
  14. package/lib/components/dc-lessons/dc-lesson-editor/dc-lesson-editor.component.d.ts +0 -67
  15. package/lib/components/dc-lessons/dc-lesson-metadata-editor/dc-lesson-metadata-editor.component.d.ts +0 -43
  16. package/lib/components/dc-lessons/dc-lesson-renderer/dc-lesson-renderer.component.d.ts +0 -51
  17. package/lib/components/dc-lessons/dc-lesson-renderer/eval-agents-skills.d.ts +0 -1
  18. package/lib/components/dc-lessons/lesson-form/lesson-form.component.d.ts +0 -5
  19. package/lib/components/dc-lessons/lesson-list/dc-lesson-list.component.d.ts +0 -36
  20. package/lib/components/dynamic-components/dynamic-components-builder.service.d.ts +0 -8
  21. package/lib/components/dynamic-components/dynamic-components.service.d.ts +0 -30
  22. package/lib/components/dynamic-components/selector/selector-builder/selector-builder.component.d.ts +0 -16
  23. package/lib/components/dynamic-components/selector/selector.component.d.ts +0 -12
  24. package/lib/components/lesson-mini-components/components/ComponentBuilder.d.ts +0 -33
  25. package/lib/components/lesson-mini-components/components/ComponentWithForm.d.ts +0 -12
  26. package/lib/components/lesson-mini-components/components/lesson-dynamic.component.d.ts +0 -7
  27. package/lib/components/lesson-mini-components/components/lessons.clases.d.ts +0 -159
  28. package/lib/components/lesson-mini-components/components/speaker/speaker-builder/speaker-builder.component.d.ts +0 -14
  29. package/lib/components/lesson-mini-components/components/speaker/speaker.component.d.ts +0 -12
  30. package/lib/components/lesson-mini-components/components/text-writer/text-writer-buider/text-writer-buider.component.d.ts +0 -7
  31. package/lib/components/lesson-mini-components/components/text-writer/text-writer.component.d.ts +0 -16
  32. package/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcher.component.d.ts +0 -11
  33. package/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcherBuilder/translationSwitcherBuilder.component.d.ts +0 -7
  34. package/lib/models/lessons.pipes.d.ts +0 -28
  35. package/lib/models/notion.models.d.ts +0 -41
  36. package/lib/models/simple-agents.d.ts +0 -2
  37. package/lib/services/courses.service.d.ts +0 -7
  38. package/lib/services/default-lessons.service.d.ts +0 -20
  39. package/lib/services/lesson-ai.service.d.ts +0 -32
  40. package/lib/services/lesson-notion.service.d.ts +0 -35
  41. package/lib/services/lesson-utils.service.d.ts +0 -56
  42. package/public-api.d.ts +0 -27
@@ -1,11 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Pipe, InjectionToken, inject, Input, Component, ChangeDetectionStrategy, signal, EventEmitter, Output, ChangeDetectorRef, ViewChildren, Injectable, input, Renderer2, ViewContainerRef, computed, effect, ViewChild, output } from '@angular/core';
3
- import * as i1$2 from 'primeng/paginator';
4
- import { PaginatorModule } from 'primeng/paginator';
2
+ import { Pipe, InjectionToken, inject, Input, Component, ChangeDetectionStrategy, signal, EventEmitter, Output, Injectable, effect, ViewChildren, input, Renderer2, ViewContainerRef, computed, ViewChild, ChangeDetectorRef, output } from '@angular/core';
5
3
  import { DatePipe, NgComponentOutlet, KeyValuePipe, CommonModule, SlicePipe } from '@angular/common';
6
4
  import * as i1$3 from '@angular/router';
7
5
  import { RouterModule, ActivatedRoute, Router } from '@angular/router';
8
- import { PaginationBase, TOAST_ALERTS_TOKEN, DCFilterBarComponent, QuickTableComponent, LoadingBarService, HttpCoreService, PromptService } from '@dataclouder/ngx-core';
6
+ import { EntityCommunicationService, EntityBaseListComponent, DCFilterBarComponent, QuickTableComponent, TOAST_ALERTS_TOKEN, UiStateService, EModelQuality, LoadingBarService, PromptService, DcExtensionsViewerComponent, DcLearnableViewerComponent, DcAuditableViewerComponent, DcManageableViewerComponent, DcReactionsViewerComponent, HttpCoreService, PaginationBase, EntityBaseFormComponent, getSupportedLanguageOptions } from '@dataclouder/ngx-core';
9
7
  import * as i1 from '@angular/forms';
10
8
  import { FormBuilder, FormControl, FormArray, FormsModule, ReactiveFormsModule, UntypedFormControl, FormGroup, Validators } from '@angular/forms';
11
9
  import * as i1$1 from 'primeng/button';
@@ -14,12 +12,11 @@ import * as i3 from 'primeng/inputtext';
14
12
  import { InputTextModule } from 'primeng/inputtext';
15
13
  import { DynamicDialogRef, DialogService } from 'primeng/dynamicdialog';
16
14
  import { nanoid } from 'nanoid';
17
- import { DropdownModule } from 'primeng/dropdown';
18
- import { NgxTtsComponent, getRandomQuickVoice } from '@dataclouder/ngx-tts';
19
- import * as i4 from 'primeng/message';
20
- import { MessageModule } from 'primeng/message';
21
15
  import * as i2 from 'primeng/select';
22
16
  import { SelectModule } from 'primeng/select';
17
+ import { TTSPlayground, getRandomQuickVoice, NgxVertexService, ChatRoleVertex } from '@dataclouder/ngx-vertex';
18
+ import * as i4 from 'primeng/message';
19
+ import { MessageModule } from 'primeng/message';
23
20
  import { PopoverModule } from 'primeng/popover';
24
21
  import * as i4$1 from 'primeng/tag';
25
22
  import { TagModule } from 'primeng/tag';
@@ -27,6 +24,8 @@ import * as i2$1 from 'primeng/speeddial';
27
24
  import { SpeedDialModule } from 'primeng/speeddial';
28
25
  import * as i3$1 from 'primeng/card';
29
26
  import { CardModule } from 'primeng/card';
27
+ import * as i1$2 from 'primeng/paginator';
28
+ import { PaginatorModule } from 'primeng/paginator';
30
29
  import { toSignal } from '@angular/core/rxjs-interop';
31
30
  import { map } from 'rxjs';
32
31
  import BalloonEditor from '@ckeditor/ckeditor5-build-balloon-block';
@@ -34,10 +33,10 @@ import * as i3$2 from '@ckeditor/ckeditor5-angular';
34
33
  import { CKEditorModule } from '@ckeditor/ckeditor5-angular';
35
34
  import * as i5$1 from 'primeng/splitter';
36
35
  import { SplitterModule } from 'primeng/splitter';
37
- import * as i6 from 'primeng/tooltip';
36
+ import * as i2$3 from 'primeng/tooltip';
38
37
  import { TooltipModule } from 'primeng/tooltip';
39
- import { ResolutionType, AspectType, CropperComponentModal } from '@dataclouder/ngx-cloud-storage';
40
- import { TextEngines, ConversationType, USER_DATA_EXCHANGE, ChatRole, EvalResultStringDefinition, ConversationEvents, ChatEventType, DCChatComponent, CONVERSATION_AI_TOKEN } from '@dataclouder/ngx-agent-cards';
38
+ import { ResolutionType, AspectType, AssetsLoaderComponent, CropperComponentModal } from '@dataclouder/ngx-cloud-storage';
39
+ import { TextEngines, ConversationType, USER_DATA_EXCHANGE, SystemPromptType, ChatRole, EvalResultStringDefinition, EDoActionType, ConditionOperator, ConditionType, ConversationEvents, ChatEventType, DCChatComponent, CONVERSATION_AI_TOKEN } from '@dataclouder/ngx-agent-cards';
41
40
  import * as i2$2 from 'primeng/drawer';
42
41
  import { DrawerModule } from 'primeng/drawer';
43
42
  import * as i7 from 'primeng/dialog';
@@ -46,17 +45,15 @@ import TurndownService from 'turndown';
46
45
  import { marked } from 'marked';
47
46
  import * as i5 from 'primeng/inputgroup';
48
47
  import { InputGroupModule } from 'primeng/inputgroup';
49
- import * as i6$1 from 'primeng/divider';
48
+ import * as i6 from 'primeng/divider';
50
49
  import { DividerModule } from 'primeng/divider';
51
- import { NgxVertexService, ChatRoleVertex } from '@dataclouder/ngx-vertex';
52
- import * as i2$3 from 'primeng/api';
50
+ import * as i2$4 from 'primeng/api';
51
+ import { TableModule } from 'primeng/table';
53
52
  import * as i3$3 from 'primeng/textarea';
54
53
  import { TextareaModule } from 'primeng/textarea';
55
54
  import { ChipModule } from 'primeng/chip';
56
55
  import { FormlyModule } from '@ngx-formly/core';
57
- import { TableModule } from 'primeng/table';
58
56
 
59
- // import { LangCodeDescription, LangCodeDescriptionEs } from '../components/lesson-mini-components/components/lessons.clases';
60
57
  // This pipe should not be here in the lessons, refactor when is posible and remove LangCodeDescription
61
58
  const LangCodeDescription = {
62
59
  es: 'Spanish',
@@ -83,10 +80,10 @@ class LangDescTranslationPipe {
83
80
  return LangCodeDescription[value];
84
81
  }
85
82
  }
86
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LangDescTranslationPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
87
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.4", ngImport: i0, type: LangDescTranslationPipe, isStandalone: true, name: "langDesc" }); }
83
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LangDescTranslationPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
84
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.6", ngImport: i0, type: LangDescTranslationPipe, isStandalone: true, name: "langDesc" }); }
88
85
  }
89
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LangDescTranslationPipe, decorators: [{
86
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LangDescTranslationPipe, decorators: [{
90
87
  type: Pipe,
91
88
  args: [{
92
89
  name: 'langDesc',
@@ -114,10 +111,10 @@ class FlagLanguagePipe {
114
111
  return '';
115
112
  }
116
113
  }
117
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: FlagLanguagePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
118
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.4", ngImport: i0, type: FlagLanguagePipe, isStandalone: true, name: "flagEmoji" }); }
114
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: FlagLanguagePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
115
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.6", ngImport: i0, type: FlagLanguagePipe, isStandalone: true, name: "flagEmoji" }); }
119
116
  }
120
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: FlagLanguagePipe, decorators: [{
117
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: FlagLanguagePipe, decorators: [{
121
118
  type: Pipe,
122
119
  args: [{
123
120
  name: 'flagEmoji',
@@ -289,10 +286,10 @@ class ComponentBuilder {
289
286
  await navigator.clipboard.writeText(data.str);
290
287
  this.ref.close(data);
291
288
  }
292
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ComponentBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
293
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: ComponentBuilder, isStandalone: true, selector: "app-component-builder", inputs: { inputs: "inputs", id: "id" }, ngImport: i0, template: '<div>no template</div>', isInline: true }); }
289
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ComponentBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
290
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ComponentBuilder, isStandalone: true, selector: "app-component-builder", inputs: { inputs: "inputs", id: "id" }, ngImport: i0, template: '<div>no template</div>', isInline: true }); }
294
291
  }
295
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ComponentBuilder, decorators: [{
292
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ComponentBuilder, decorators: [{
296
293
  type: Component,
297
294
  args: [{
298
295
  selector: 'app-component-builder',
@@ -309,10 +306,10 @@ class TextWriterBuiderComponent extends ComponentBuilder {
309
306
  super(...arguments);
310
307
  this.componentName = 'TextWriter';
311
308
  }
312
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterBuiderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
313
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: TextWriterBuiderComponent, isStandalone: true, selector: "app-text-writer-buider", usesInheritance: true, ngImport: i0, template: "<div>\r\n <div>\r\n <h5>Constructor de formulario con texto</h5>\r\n </div>\r\n\r\n <div>\r\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\r\n <input pInputText type=\"text\" nbInput fullWidth formControlName=\"response\" placeholder=\"Respuesta\" />\r\n\r\n <input pInputText class=\"form-input\" type=\"\" nbInput fullWidth formControlName=\"hint\"\r\n placeholder=\"Escribe una pista para esta pregunta\" />\r\n\r\n <input pInputText class=\"form-input\" type=\"text\" nbInput fullWidth formControlName=\"explanation\"\r\n placeholder=\"Excribe una explicaci\u00F3n para la respuesta\" />\r\n </form>\r\n </div>\r\n\r\n <div>\r\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\"\r\n [rounded]=\"true\"></p-button>\r\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\"\r\n severity=\"secondary\"></p-button>\r\n </div>\r\n</div>", styles: ["nb-card{width:60vw}.builder-form{padding:5px}.form-input{margin-top:10px}.mar-top{margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }] }); }
309
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: TextWriterBuiderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
310
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: TextWriterBuiderComponent, isStandalone: true, selector: "app-text-writer-buider", usesInheritance: true, ngImport: i0, template: "<div>\r\n <div>\r\n <h5>Constructor de formulario con texto</h5>\r\n </div>\r\n\r\n <div>\r\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\r\n <input pInputText type=\"text\" nbInput fullWidth formControlName=\"response\" placeholder=\"Respuesta\" />\r\n\r\n <input pInputText class=\"form-input\" type=\"\" nbInput fullWidth formControlName=\"hint\"\r\n placeholder=\"Escribe una pista para esta pregunta\" />\r\n\r\n <input pInputText class=\"form-input\" type=\"text\" nbInput fullWidth formControlName=\"explanation\"\r\n placeholder=\"Excribe una explicaci\u00F3n para la respuesta\" />\r\n </form>\r\n </div>\r\n\r\n <div>\r\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\"\r\n [rounded]=\"true\"></p-button>\r\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\"\r\n severity=\"secondary\"></p-button>\r\n </div>\r\n</div>", styles: ["nb-card{width:60vw}.builder-form{padding:5px}.form-input{margin-top:10px}.mar-top{margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }] }); }
314
311
  }
315
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterBuiderComponent, decorators: [{
312
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: TextWriterBuiderComponent, decorators: [{
316
313
  type: Component,
317
314
  args: [{ selector: 'app-text-writer-buider', standalone: true, imports: [FormsModule, ReactiveFormsModule, ButtonModule, InputTextModule], template: "<div>\r\n <div>\r\n <h5>Constructor de formulario con texto</h5>\r\n </div>\r\n\r\n <div>\r\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\r\n <input pInputText type=\"text\" nbInput fullWidth formControlName=\"response\" placeholder=\"Respuesta\" />\r\n\r\n <input pInputText class=\"form-input\" type=\"\" nbInput fullWidth formControlName=\"hint\"\r\n placeholder=\"Escribe una pista para esta pregunta\" />\r\n\r\n <input pInputText class=\"form-input\" type=\"text\" nbInput fullWidth formControlName=\"explanation\"\r\n placeholder=\"Excribe una explicaci\u00F3n para la respuesta\" />\r\n </form>\r\n </div>\r\n\r\n <div>\r\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\"\r\n [rounded]=\"true\"></p-button>\r\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\"\r\n severity=\"secondary\"></p-button>\r\n </div>\r\n</div>", styles: ["nb-card{width:60vw}.builder-form{padding:5px}.form-input{margin-top:10px}.mar-top{margin:5px}\n"] }]
318
315
  }] });
@@ -330,10 +327,10 @@ class ComponentWithForm {
330
327
  validate() {
331
328
  // TODO: generic method to evaluate
332
329
  }
333
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ComponentWithForm, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
334
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: ComponentWithForm, isStandalone: true, selector: "app-component-form", ngImport: i0, template: '<div>no template</div>', isInline: true }); }
330
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ComponentWithForm, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
331
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: ComponentWithForm, isStandalone: true, selector: "app-component-form", ngImport: i0, template: '<div>no template</div>', isInline: true }); }
335
332
  }
336
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ComponentWithForm, decorators: [{
333
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: ComponentWithForm, decorators: [{
337
334
  type: Component,
338
335
  args: [{
339
336
  selector: 'app-component-form',
@@ -376,10 +373,10 @@ class TextWriterComponent extends ComponentWithForm {
376
373
  }
377
374
  return true;
378
375
  }
379
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
380
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: TextWriterComponent, isStandalone: true, selector: "app-text-writer", inputs: { config: "config" }, usesInheritance: true, ngImport: i0, template: "<input [class]=\"this.status\" pInputText [formControl]=\"control\" fieldSize=\"small\" type=\"text\" placeholder=\"Respuesta\"\n [size]=\"size\" />\n\n<!-- [ngClass]=\"{ 'selected-radio': 'true']}\" -->", styles: [".warning{border-color:#f0ad4e}.danger{border-color:#e1211b}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }] }); }
376
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: TextWriterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
377
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: TextWriterComponent, isStandalone: true, selector: "app-text-writer", inputs: { config: "config" }, usesInheritance: true, ngImport: i0, template: "<input [class]=\"this.status\" pInputText [formControl]=\"control\" fieldSize=\"small\" type=\"text\" placeholder=\"Respuesta\"\n [size]=\"size\" />\n\n<!-- [ngClass]=\"{ 'selected-radio': 'true']}\" -->", styles: [".warning{border-color:#f0ad4e}.danger{border-color:#e1211b}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }] }); }
381
378
  }
382
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterComponent, decorators: [{
379
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: TextWriterComponent, decorators: [{
383
380
  type: Component,
384
381
  args: [{ selector: 'app-text-writer', standalone: true, imports: [FormsModule, ReactiveFormsModule, InputTextModule], template: "<input [class]=\"this.status\" pInputText [formControl]=\"control\" fieldSize=\"small\" type=\"text\" placeholder=\"Respuesta\"\n [size]=\"size\" />\n\n<!-- [ngClass]=\"{ 'selected-radio': 'true']}\" -->", styles: [".warning{border-color:#f0ad4e}.danger{border-color:#e1211b}\n"] }]
385
382
  }], ctorParameters: () => [], propDecorators: { config: [{
@@ -391,10 +388,10 @@ class TranslationSwitcherBuilderComponent extends ComponentBuilder {
391
388
  super(...arguments);
392
389
  this.componentName = 'TranslationSwitcher';
393
390
  }
394
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TranslationSwitcherBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
395
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: TranslationSwitcherBuilderComponent, isStandalone: true, selector: "app-translation-switcher-builder", usesInheritance: true, ngImport: i0, template: "<div>\n <div>\n <h5>Constructor de translation switcher</h5>\n </div>\n\n <div>\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\n <input style=\"width: 100%\" pInputText type=\"text\" nbInput fullWidth formControlName=\"text\" placeholder=\"Texto para visualizar\" />\n\n <br /><br />\n\n <input\n style=\"width: 100%\"\n pInputText\n class=\"form-input\"\n type=\"\"\n nbInput\n fullWidth\n formControlName=\"response\"\n placeholder=\"Traducci\u00F3n al hacer clic\" />\n </form>\n </div>\n <br />\n <div>\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\n </div>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
391
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: TranslationSwitcherBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
392
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: TranslationSwitcherBuilderComponent, isStandalone: true, selector: "app-translation-switcher-builder", usesInheritance: true, ngImport: i0, template: "<div>\n <div>\n <h5>Constructor de translation switcher</h5>\n </div>\n\n <div>\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\n <input style=\"width: 100%\" pInputText type=\"text\" nbInput fullWidth formControlName=\"text\" placeholder=\"Texto para visualizar\" />\n\n <br /><br />\n\n <input\n style=\"width: 100%\"\n pInputText\n class=\"form-input\"\n type=\"\"\n nbInput\n fullWidth\n formControlName=\"response\"\n placeholder=\"Traducci\u00F3n al hacer clic\" />\n </form>\n </div>\n <br />\n <div>\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\n </div>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
396
393
  }
397
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TranslationSwitcherBuilderComponent, decorators: [{
394
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: TranslationSwitcherBuilderComponent, decorators: [{
398
395
  type: Component,
399
396
  args: [{ selector: 'app-translation-switcher-builder', standalone: true, imports: [FormsModule, ReactiveFormsModule, ButtonModule, InputTextModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div>\n <div>\n <h5>Constructor de translation switcher</h5>\n </div>\n\n <div>\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\n <input style=\"width: 100%\" pInputText type=\"text\" nbInput fullWidth formControlName=\"text\" placeholder=\"Texto para visualizar\" />\n\n <br /><br />\n\n <input\n style=\"width: 100%\"\n pInputText\n class=\"form-input\"\n type=\"\"\n nbInput\n fullWidth\n formControlName=\"response\"\n placeholder=\"Traducci\u00F3n al hacer clic\" />\n </form>\n </div>\n <br />\n <div>\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
400
397
  }] });
@@ -415,10 +412,10 @@ class TranslationSwitcherComponent {
415
412
  this.visibleText = this.config.settings.text;
416
413
  }
417
414
  }
418
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TranslationSwitcherComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
419
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: TranslationSwitcherComponent, isStandalone: true, selector: "app-translation-switcher", inputs: { config: "config" }, ngImport: i0, template: "<button\n pButton\n style=\"padding: 0px 2px\"\n severity=\"help\"\n size=\"small\"\n (click)=\"switchTranslation()\"\n [label]=\"visibleText\"\n [text]=\"true\"\n [rounded]=\"true\"></button>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }], changeDetection: i0.ChangeDetectionStrategy.Default }); }
415
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: TranslationSwitcherComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
416
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: TranslationSwitcherComponent, isStandalone: true, selector: "app-translation-switcher", inputs: { config: "config" }, ngImport: i0, template: "<button\n pButton\n style=\"padding: 0px 2px\"\n severity=\"help\"\n size=\"small\"\n (click)=\"switchTranslation()\"\n [label]=\"visibleText\"\n [text]=\"true\"\n [rounded]=\"true\"></button>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }], changeDetection: i0.ChangeDetectionStrategy.Default }); }
420
417
  }
421
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TranslationSwitcherComponent, decorators: [{
418
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: TranslationSwitcherComponent, decorators: [{
422
419
  type: Component,
423
420
  args: [{ selector: 'app-translation-switcher', standalone: true, imports: [ButtonModule], changeDetection: ChangeDetectionStrategy.Default, template: "<button\n pButton\n style=\"padding: 0px 2px\"\n severity=\"help\"\n size=\"small\"\n (click)=\"switchTranslation()\"\n [label]=\"visibleText\"\n [text]=\"true\"\n [rounded]=\"true\"></button>\n", styles: [":host{display:block}\n"] }]
424
421
  }], propDecorators: { config: [{
@@ -429,7 +426,7 @@ class SpeakerBuilderComponent extends ComponentBuilder {
429
426
  constructor() {
430
427
  super(...arguments);
431
428
  this.componentName = 'Speaker';
432
- this.tts = signal(undefined);
429
+ this.tts = signal(undefined, ...(ngDevMode ? [{ debugName: "tts" }] : []));
433
430
  }
434
431
  handleTtsGenerated(event) {
435
432
  console.log('TTS generated:', event);
@@ -450,16 +447,15 @@ class SpeakerBuilderComponent extends ComponentBuilder {
450
447
  };
451
448
  return code;
452
449
  }
453
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SpeakerBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
454
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: SpeakerBuilderComponent, isStandalone: true, selector: "app-speaker-builder", usesInheritance: true, ngImport: i0, template: "<div>\r\n <div>\r\n <h5>Constructor de Speaker</h5>\r\n </div>\r\n\r\n <lib-ngx-tts (ttsGenerated)=\"handleTtsGenerated($event)\"></lib-ngx-tts>\r\n\r\n <br />\r\n <div>\r\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\r\n <p-button (click)=\"showCode()\" [disabled]=\"!tts()\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: NgxTtsComponent, selector: "lib-ngx-tts", inputs: ["path"], outputs: ["ttsGenerated"] }] }); }
450
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: SpeakerBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
451
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: SpeakerBuilderComponent, isStandalone: true, selector: "app-speaker-builder", usesInheritance: true, ngImport: i0, template: "<div>\r\n <div>\r\n <h5>Constructor de Speaker</h5>\r\n </div>\r\n\r\n <tts-playground (ttsGenerated)=\"handleTtsGenerated($event)\"></tts-playground>\r\n\r\n <br />\r\n <div>\r\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\r\n <p-button (click)=\"showCode()\" [disabled]=\"!tts()\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: "ngmodule", type: SelectModule }, { kind: "component", type: TTSPlayground, selector: "tts-playground", inputs: ["path"], outputs: ["ttsGenerated"] }] }); }
455
452
  }
456
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SpeakerBuilderComponent, decorators: [{
453
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: SpeakerBuilderComponent, decorators: [{
457
454
  type: Component,
458
- args: [{ selector: 'app-speaker-builder', standalone: true, imports: [FormsModule, ReactiveFormsModule, InputTextModule, ButtonModule, DropdownModule, NgxTtsComponent], template: "<div>\r\n <div>\r\n <h5>Constructor de Speaker</h5>\r\n </div>\r\n\r\n <lib-ngx-tts (ttsGenerated)=\"handleTtsGenerated($event)\"></lib-ngx-tts>\r\n\r\n <br />\r\n <div>\r\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\r\n <p-button (click)=\"showCode()\" [disabled]=\"!tts()\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\r\n </div>\r\n</div>\r\n" }]
455
+ args: [{ selector: 'app-speaker-builder', standalone: true, imports: [FormsModule, ReactiveFormsModule, InputTextModule, ButtonModule, SelectModule, TTSPlayground], template: "<div>\r\n <div>\r\n <h5>Constructor de Speaker</h5>\r\n </div>\r\n\r\n <tts-playground (ttsGenerated)=\"handleTtsGenerated($event)\"></tts-playground>\r\n\r\n <br />\r\n <div>\r\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\r\n <p-button (click)=\"showCode()\" [disabled]=\"!tts()\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\r\n </div>\r\n</div>\r\n" }]
459
456
  }] });
460
457
 
461
458
  // ❌ can use this until i copy services to this lib
462
- // import { CONVERSATION_AI_TOKEN } from '@dataclouder/ngx-agent-cards';
463
459
  class SpeakerComponent {
464
460
  ngOnInit() {
465
461
  // throw new Error('Method not implemented.');
@@ -469,16 +465,11 @@ class SpeakerComponent {
469
465
  // ngOnInit(): void {}
470
466
  speach() {
471
467
  console.log('should speech but will do in next version');
472
- // if (this.config.audio) {
473
- // this.audioService.playAudio(this.config.audio.url);
474
- // } else {
475
- // this.speachService.speach(this.config.settings.text);
476
- // }
477
468
  }
478
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SpeakerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
479
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: SpeakerComponent, isStandalone: true, selector: "app-speaker", inputs: { config: "config", tts: "tts" }, ngImport: i0, template: "<button\r\n pButton\r\n style=\"padding: 0px 2px\"\r\n severity=\"help\"\r\n size=\"small\"\r\n (click)=\"speach()\"\r\n [label]=\"config?.settings?.text\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"></button>\r\n", styles: [".lisen{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }] }); }
469
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: SpeakerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
470
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: SpeakerComponent, isStandalone: true, selector: "app-speaker", inputs: { config: "config", tts: "tts" }, ngImport: i0, template: "<button\r\n pButton\r\n style=\"padding: 0px 2px\"\r\n severity=\"help\"\r\n size=\"small\"\r\n (click)=\"speach()\"\r\n [label]=\"config?.settings?.text\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"></button>\r\n", styles: [".lisen{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }] }); }
480
471
  }
481
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SpeakerComponent, decorators: [{
472
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: SpeakerComponent, decorators: [{
482
473
  type: Component,
483
474
  args: [{ selector: 'app-speaker', standalone: true, imports: [ButtonModule], template: "<button\r\n pButton\r\n style=\"padding: 0px 2px\"\r\n severity=\"help\"\r\n size=\"small\"\r\n (click)=\"speach()\"\r\n [label]=\"config?.settings?.text\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"></button>\r\n", styles: [".lisen{cursor:pointer}\n"] }]
484
475
  }], propDecorators: { config: [{
@@ -515,10 +506,10 @@ class SelectorComponent extends ComponentWithForm {
515
506
  }
516
507
  return true;
517
508
  }
518
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
519
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: SelectorComponent, isStandalone: true, selector: "app-selector", inputs: { config: "config" }, usesInheritance: true, ngImport: i0, template: "<p-select [class]=\"status\" placeholder=\"Selecciona\" [options]=\"config.settings.options\" [formControl]=\"control\"></p-select>\r\n", styles: ["::ng-deep .comp-selector button{min-width:80px}.warning{border-color:#f0ad4e}.danger{border-color:#e1211b}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "size", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }] }); }
509
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: SelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
510
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: SelectorComponent, isStandalone: true, selector: "app-selector", inputs: { config: "config" }, usesInheritance: true, ngImport: i0, template: "<p-select [class]=\"status\" placeholder=\"Selecciona\" [options]=\"config.settings.options\" [formControl]=\"control\"></p-select>\r\n", styles: ["::ng-deep .comp-selector button{min-width:80px}.warning{border-color:#f0ad4e}.danger{border-color:#e1211b}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }] }); }
520
511
  }
521
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorComponent, decorators: [{
512
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: SelectorComponent, decorators: [{
522
513
  type: Component,
523
514
  args: [{ selector: 'app-selector', standalone: true, imports: [FormsModule, ReactiveFormsModule, SelectModule], template: "<p-select [class]=\"status\" placeholder=\"Selecciona\" [options]=\"config.settings.options\" [formControl]=\"control\"></p-select>\r\n", styles: ["::ng-deep .comp-selector button{min-width:80px}.warning{border-color:#f0ad4e}.danger{border-color:#e1211b}\n"] }]
524
515
  }], ctorParameters: () => [], propDecorators: { config: [{
@@ -563,10 +554,10 @@ class SelectorBuilderComponent extends ComponentBuilder {
563
554
  get optionsForm() {
564
555
  return this.formGroup.get('options');
565
556
  }
566
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
567
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: SelectorBuilderComponent, isStandalone: true, selector: "app-selector-builder", usesInheritance: true, ngImport: i0, template: "<div>\n <div>\n <p-message>Construcci\u00F3n del componente de Selecci\u00F3n, sirve para hacer una pregunta y mostrar varias opciones, ejemplo:</p-message>\n </div>\n\n <div>\n <span>En que a\u00F1o lleg\u00F3 cristobal colon a america?</span>\n <app-selector [config]=\"sampleConfig\"></app-selector>\n </div>\n\n <hr />\n\n <div>\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\n <input class=\"form-input\" type=\"text\" pInputText fullWidth formControlName=\"response\" placeholder=\"Respuesta Correcta...\" />\n <br />\n\n <input class=\"form-input\" type=\"\" pInputText fullWidth formControlName=\"hint\" placeholder=\"Escribe una pista para esta pregunta\" />\n\n <br />\n <input\n class=\"form-input\"\n type=\"text\"\n pInputText\n fullWidth\n formControlName=\"explanation\"\n placeholder=\"Excribe una explicaci\u00F3n para la respuesta\" />\n\n <hr />\n <h6>Opciones</h6>\n\n <div class=\"form-group\" formArrayName=\"options\">\n @for (item of optionsForm.controls; track item; let i = $index) {\n <div\n style=\"display: flex; gap: 10px; align-items: center; justify-content: space-between; margin-bottom: 10px; flex-direction: column\"\n >\n <div>\n <input type=\"text\" pInputText fullWidth [formControlName]=\"i\" />\n <p-button (click)=\"deleteFormArrayByIndex('options', i)\" icon=\"pi pi-times\" severity=\"danger\"></p-button>\n </div>\n </div>\n }\n </div>\n\n <p-button (click)=\"pushControlToFormArray('options')\" label=\"Agregar Opci\u00F3n\" [text]=\"true\" severity=\"help\"></p-button>\n </form>\n\n <!-- <button nbButton (click)=\"isRendered = !isRendered\"> Renderizar </button> -->\n\n @if (isRendered) {\n <div>\n <!-- TODO: probably i need to pass some params -->\n <app-selector></app-selector>\n </div>\n }\n </div>\n\n <div>\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\n </div>\n </div>\n", styles: ["nb-card{width:60vw}.builder-form{padding:5px}.form-input{margin-top:10px}.mar-top{margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: SelectorComponent, selector: "app-selector", inputs: ["config"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i4.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant"], outputs: ["onClose"] }] }); }
557
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: SelectorBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
558
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: SelectorBuilderComponent, isStandalone: true, selector: "app-selector-builder", usesInheritance: true, ngImport: i0, template: "<div>\n <div>\n <p-message>Construcci\u00F3n del componente de Selecci\u00F3n, sirve para hacer una pregunta y mostrar varias opciones, ejemplo:</p-message>\n </div>\n\n <div>\n <span>En que a\u00F1o lleg\u00F3 cristobal colon a america?</span>\n <app-selector [config]=\"sampleConfig\"></app-selector>\n </div>\n\n <hr />\n\n <div>\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\n <input class=\"form-input\" type=\"text\" pInputText fullWidth formControlName=\"response\" placeholder=\"Respuesta Correcta...\" />\n <br />\n\n <input class=\"form-input\" type=\"\" pInputText fullWidth formControlName=\"hint\" placeholder=\"Escribe una pista para esta pregunta\" />\n\n <br />\n <input\n class=\"form-input\"\n type=\"text\"\n pInputText\n fullWidth\n formControlName=\"explanation\"\n placeholder=\"Excribe una explicaci\u00F3n para la respuesta\" />\n\n <hr />\n <h6>Opciones</h6>\n\n <div class=\"form-group\" formArrayName=\"options\">\n @for (item of optionsForm.controls; track item; let i = $index) {\n <div\n style=\"display: flex; gap: 10px; align-items: center; justify-content: space-between; margin-bottom: 10px; flex-direction: column\"\n >\n <div>\n <input type=\"text\" pInputText fullWidth [formControlName]=\"i\" />\n <p-button (click)=\"deleteFormArrayByIndex('options', i)\" icon=\"pi pi-times\" severity=\"danger\"></p-button>\n </div>\n </div>\n }\n </div>\n\n <p-button (click)=\"pushControlToFormArray('options')\" label=\"Agregar Opci\u00F3n\" [text]=\"true\" severity=\"help\"></p-button>\n </form>\n\n <!-- <button nbButton (click)=\"isRendered = !isRendered\"> Renderizar </button> -->\n\n @if (isRendered) {\n <div>\n <!-- TODO: probably i need to pass some params -->\n <app-selector></app-selector>\n </div>\n }\n </div>\n\n <div>\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\n </div>\n </div>\n", styles: ["nb-card{width:60vw}.builder-form{padding:5px}.form-input{margin-top:10px}.mar-top{margin:5px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: SelectorComponent, selector: "app-selector", inputs: ["config"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: "ngmodule", type: MessageModule }, { kind: "component", type: i4.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant"], outputs: ["onClose"] }] }); }
568
559
  }
569
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorBuilderComponent, decorators: [{
560
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: SelectorBuilderComponent, decorators: [{
570
561
  type: Component,
571
562
  args: [{ selector: 'app-selector-builder', standalone: true, imports: [FormsModule, ReactiveFormsModule, SelectorComponent, InputTextModule, ButtonModule, MessageModule], template: "<div>\n <div>\n <p-message>Construcci\u00F3n del componente de Selecci\u00F3n, sirve para hacer una pregunta y mostrar varias opciones, ejemplo:</p-message>\n </div>\n\n <div>\n <span>En que a\u00F1o lleg\u00F3 cristobal colon a america?</span>\n <app-selector [config]=\"sampleConfig\"></app-selector>\n </div>\n\n <hr />\n\n <div>\n <form class=\"builder-form\" [formGroup]=\"formGroup\">\n <input class=\"form-input\" type=\"text\" pInputText fullWidth formControlName=\"response\" placeholder=\"Respuesta Correcta...\" />\n <br />\n\n <input class=\"form-input\" type=\"\" pInputText fullWidth formControlName=\"hint\" placeholder=\"Escribe una pista para esta pregunta\" />\n\n <br />\n <input\n class=\"form-input\"\n type=\"text\"\n pInputText\n fullWidth\n formControlName=\"explanation\"\n placeholder=\"Excribe una explicaci\u00F3n para la respuesta\" />\n\n <hr />\n <h6>Opciones</h6>\n\n <div class=\"form-group\" formArrayName=\"options\">\n @for (item of optionsForm.controls; track item; let i = $index) {\n <div\n style=\"display: flex; gap: 10px; align-items: center; justify-content: space-between; margin-bottom: 10px; flex-direction: column\"\n >\n <div>\n <input type=\"text\" pInputText fullWidth [formControlName]=\"i\" />\n <p-button (click)=\"deleteFormArrayByIndex('options', i)\" icon=\"pi pi-times\" severity=\"danger\"></p-button>\n </div>\n </div>\n }\n </div>\n\n <p-button (click)=\"pushControlToFormArray('options')\" label=\"Agregar Opci\u00F3n\" [text]=\"true\" severity=\"help\"></p-button>\n </form>\n\n <!-- <button nbButton (click)=\"isRendered = !isRendered\"> Renderizar </button> -->\n\n @if (isRendered) {\n <div>\n <!-- TODO: probably i need to pass some params -->\n <app-selector></app-selector>\n </div>\n }\n </div>\n\n <div>\n <p-button (click)=\"copyToClipboard()\" [disabled]=\"formGroup.invalid\" label=\"Copia C\u00F3digo\" [rounded]=\"true\"></p-button>\n <p-button (click)=\"showCode()\" [disabled]=\"formGroup.invalid\" label=\"Mostrar\" [rounded]=\"true\" severity=\"secondary\"></p-button>\n </div>\n </div>\n", styles: ["nb-card{width:60vw}.builder-form{padding:5px}.form-input{margin-top:10px}.mar-top{margin:5px}\n"] }]
572
563
  }] });
@@ -603,8 +594,19 @@ function getLessonComponentClass(type) {
603
594
  return LessonComponents[type];
604
595
  }
605
596
  const LESSONS_TOKEN = new InjectionToken('Lessons Service');
606
- class LessonsAbstractService {
607
- }
597
+ // export abstract class LessonsAbstractService extends EntityCommunicationService<ILesson> {
598
+ // abstract getLessons(paginator?: any): Promise<any>;
599
+ // abstract getLesson(id: string): Promise<any>;
600
+ // abstract postLesson(lesson: ILesson): Promise<any>;
601
+ // abstract updateLesson(lesson: ILesson): Promise<any>;
602
+ // abstract deleteLesson(id: string): Promise<any>;
603
+ // abstract generateLesson(lesson: ILesson): Promise<any>;
604
+ // abstract postGenerateByAI(id: string): Promise<any>;
605
+ // abstract extractTextFromHtml(html: string): string;
606
+ // abstract postImproveMDWithAI(lessonId: string, markdownText: string): Promise<any>; // Added for AI Markdown improvement
607
+ // abstract saveTakenLesson(lesson: ILessonTaken): Promise<any>;
608
+ // abstract getPrompts(): LessonPrompts;
609
+ // }
608
610
  // my-service.provider.ts
609
611
  function provideLessonsService(serviceImplementation) {
610
612
  return [
@@ -621,6 +623,7 @@ var EventCard;
621
623
  EventCard["Delete"] = "delete";
622
624
  EventCard["Select"] = "select";
623
625
  EventCard["Qr"] = "qr";
626
+ EventCard["Clone"] = "clone";
624
627
  })(EventCard || (EventCard = {}));
625
628
  class DcLessonCardComponent {
626
629
  constructor() {
@@ -630,27 +633,9 @@ class DcLessonCardComponent {
630
633
  this.coverUrl = 'assets/background/default-background.webp';
631
634
  this.eventType = EventCard;
632
635
  this.items = [
633
- {
634
- label: 'Editar',
635
- icon: 'pi pi-pencil',
636
- command: () => {
637
- this.eventCard(EventCard.Edit);
638
- },
639
- },
640
- {
641
- label: 'Eliminar',
642
- icon: 'pi pi-trash',
643
- command: () => {
644
- this.eventCard(EventCard.Delete);
645
- },
646
- },
647
- {
648
- label: 'Tomar lección',
649
- icon: 'pi pi-play',
650
- command: () => {
651
- this.eventCard(EventCard.Select);
652
- },
653
- },
636
+ { label: 'Clonar', icon: 'pi pi-copy', command: () => this.eventCard(EventCard.Clone) },
637
+ { label: 'Editar', icon: 'pi pi-pencil', command: () => this.eventCard(EventCard.Edit) },
638
+ { label: 'Eliminar', icon: 'pi pi-trash', command: () => this.eventCard(EventCard.Delete) },
654
639
  ];
655
640
  }
656
641
  ngOnInit() {
@@ -658,27 +643,14 @@ class DcLessonCardComponent {
658
643
  this.lesson?.banner?.url || this.lesson?.metadata?.banner?.url || this.lesson?.media?.images?.[0]?.url || 'assets/background/default-background.webp';
659
644
  }
660
645
  eventCard(eventType) {
661
- switch (eventType) {
662
- case EventCard.Edit:
663
- this.onAction.emit({ action: 'edit', item: this.lesson });
664
- break;
665
- case EventCard.Delete:
666
- this.onAction.emit({ action: 'delete', item: this.lesson });
667
- break;
668
- case EventCard.Select:
669
- this.onAction.emit({ action: 'select', item: this.lesson });
670
- break;
671
- case EventCard.Qr:
672
- this.onAction.emit({ action: 'qr', item: this.lesson });
673
- break;
674
- }
646
+ this.onAction.emit({ action: eventType, item: this.lesson });
675
647
  }
676
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DcLessonCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
677
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: DcLessonCardComponent, isStandalone: true, selector: "dc-lesson-card", inputs: { lesson: "lesson", showOptions: "showOptions", cardHeight: "cardHeight" }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<div class=\"card-container\">\n @if(showOptions){\n <p-speeddial\n class=\"dial-button\"\n [model]=\"items\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\" />\n }\n <p-card>\n <div class=\"lesson-card\" [style.height]=\"cardHeight\">\n <div class=\"photo\">\n <img [src]=\"coverUrl\" alt=\"\" />\n </div>\n\n <span class=\"date\">{{ lesson.createdAt | date : 'dd/MM/yyyy' }}</span>\n\n <div class=\"description\">\n <h1>{{ lesson.title || lesson.metadata?.title || 'No title available' }}</h1>\n <p>{{ lesson.description || lesson.metadata?.description || 'No description available' }}</p>\n <div class=\"card-footer\">\n <div class=\"status-tags\">\n <span class=\"level-tag\">Nivel {{ lesson.level }}</span>\n @if (lesson.taken?.status == 'passed') {\n <p-tag severity=\"success\" value=\"Tomada\" [rounded]=\"true\" />\n } @if (lesson.taken?.status == 'failed') {\n <p-tag severity=\"danger\" value=\"Fallida\" [rounded]=\"true\" />\n } @if (lesson.taken) {\n <p-tag severity=\"success\" value=\"Tomada \uD83D\uDCD6\" [rounded]=\"true\" />\n } @if (!lesson.metadata?.isPublished) {\n <p-tag severity=\"danger\" value=\"No publicada\" [rounded]=\"true\" />\n }\n </div>\n\n <div style=\"position: absolute; bottom: 0px; right: 0px\">\n <p-button label=\"Tomar lecci\u00F3n\" (onClick)=\"eventCard(eventType.Select)\" severity=\"primary\"> </p-button>\n </div>\n </div>\n </div>\n </div>\n </p-card>\n</div>\n", styles: [".card-container{position:relative;margin-bottom:20px;margin-left:10px}.dial-button{position:absolute;top:10px;right:20px;z-index:10}.lesson-card{border-radius:.5rem;height:100%}.lesson-card .photo{position:absolute;inset:0;z-index:1}.lesson-card .photo img{width:100%;height:100%;object-fit:cover;object-position:center}.lesson-card .photo:after{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(to bottom,rgb(0,0,0) 50%,var(--p-primary-color) 100%);opacity:.4;z-index:2;pointer-events:none}.description{position:relative;z-index:2;color:#fff;height:100%;display:flex;flex-direction:column}.description h1{margin-top:0;margin-bottom:.5rem;font-size:1.5rem;font-weight:900;text-shadow:1px 1px 2px rgba(0,0,0,.7)}.description p{margin-bottom:1rem;flex-grow:1;font-weight:500;text-shadow:1px 1px 2px rgba(0,0,0,.9)}.date{position:absolute;top:1rem;left:1rem;z-index:3;background-color:#000000b3;color:#fff;padding:.3rem .6rem;border-radius:.25rem;font-size:.8rem}.card-footer{display:flex;justify-content:space-between;align-items:center;margin-top:auto}.status-tags{display:flex;gap:.5rem}.status-tags .level-tag,.status-tags .status-tag{padding:.3rem .6rem;border-radius:.25rem;font-size:.8rem}.status-tags .level-tag{background-color:#fff3}.status-tags .status-tag.success{background-color:#28a745b3}.status-tags .status-tag.danger{background-color:#dc3545b3}\n"], dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i2$1.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i4$1.Tag, selector: "p-tag", inputs: ["style", "styleClass", "severity", "value", "icon", "rounded"] }] }); }
648
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcLessonCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
649
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DcLessonCardComponent, isStandalone: true, selector: "dc-lesson-card", inputs: { lesson: "lesson", showOptions: "showOptions", cardHeight: "cardHeight" }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<div class=\"card-container\">\n @if(showOptions){\n <p-speeddial\n class=\"dial-button\"\n [model]=\"items\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\"\n [tooltipOptions]=\"{ tooltipPosition: 'top' }\" />\n }\n <p-card>\n <div class=\"lesson-card\" [style.height]=\"cardHeight\">\n <div class=\"photo\">\n <img [src]=\"coverUrl\" alt=\"\" />\n </div>\n\n <span class=\"date\">{{ lesson.createdAt | date : 'dd/MM/yyyy' }}</span>\n\n <div class=\"description\">\n <h1>{{ lesson.title || lesson.metadata?.title || 'No title available' }}</h1>\n <p>{{ lesson.description || lesson.metadata?.description || 'No description available' }}</p>\n <div class=\"card-footer\">\n <div class=\"status-tags\">\n <span class=\"level-tag\">Nivel {{ lesson.level }}</span>\n @if (lesson.taken?.status == 'passed') {\n <p-tag severity=\"success\" value=\"Tomada\" [rounded]=\"true\" />\n } @if (lesson.taken?.status == 'failed') {\n <p-tag severity=\"danger\" value=\"Fallida\" [rounded]=\"true\" />\n } @if (lesson.taken) {\n <p-tag severity=\"success\" value=\"Tomada \uD83D\uDCD6\" [rounded]=\"true\" />\n } @if (!lesson.metadata?.isPublished) {\n <p-tag severity=\"danger\" value=\"No publicada\" [rounded]=\"true\" />\n }\n </div>\n\n <div style=\"position: absolute; bottom: 0px; right: 0px\">\n <p-button label=\"Tomar lecci\u00F3n\" (onClick)=\"eventCard(eventType.Select)\" severity=\"primary\"> </p-button>\n </div>\n </div>\n </div>\n </div>\n </p-card>\n</div>\n", styles: [".card-container{position:relative;margin-bottom:20px;margin-left:10px}.dial-button{position:absolute;top:10px;right:20px;z-index:10}.lesson-card{border-radius:.5rem;height:100%}.lesson-card .photo{position:absolute;inset:0;z-index:1}.lesson-card .photo img{width:100%;height:100%;object-fit:cover;object-position:center}.lesson-card .photo:after{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(to bottom,rgb(0,0,0) 50%,var(--p-primary-color) 100%);opacity:.4;z-index:2;pointer-events:none}.description{position:relative;z-index:2;color:#fff;height:100%;display:flex;flex-direction:column}.description h1{margin-top:0;margin-bottom:.5rem;font-size:1.5rem;font-weight:900;text-shadow:1px 1px 2px rgba(0,0,0,.7)}.description p{margin-bottom:1rem;flex-grow:1;font-weight:500;text-shadow:1px 1px 2px rgba(0,0,0,.9)}.date{position:absolute;top:1rem;left:1rem;z-index:3;background-color:#000000b3;color:#fff;padding:.3rem .6rem;border-radius:.25rem;font-size:.8rem}.card-footer{display:flex;justify-content:space-between;align-items:center;margin-top:auto}.status-tags{display:flex;gap:.5rem}.status-tags .level-tag,.status-tags .status-tag{padding:.3rem .6rem;border-radius:.25rem;font-size:.8rem}.status-tags .level-tag{background-color:#fff3}.status-tags .status-tag.success{background-color:#28a745b3}.status-tags .status-tag.danger{background-color:#dc3545b3}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i2$1.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i4$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "pipe", type: DatePipe, name: "date" }] }); }
678
650
  }
679
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DcLessonCardComponent, decorators: [{
651
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcLessonCardComponent, decorators: [{
680
652
  type: Component,
681
- args: [{ selector: 'dc-lesson-card', standalone: true, imports: [DatePipe, ButtonModule, PopoverModule, SpeedDialModule, CardModule, TagModule], template: "<div class=\"card-container\">\n @if(showOptions){\n <p-speeddial\n class=\"dial-button\"\n [model]=\"items\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\" />\n }\n <p-card>\n <div class=\"lesson-card\" [style.height]=\"cardHeight\">\n <div class=\"photo\">\n <img [src]=\"coverUrl\" alt=\"\" />\n </div>\n\n <span class=\"date\">{{ lesson.createdAt | date : 'dd/MM/yyyy' }}</span>\n\n <div class=\"description\">\n <h1>{{ lesson.title || lesson.metadata?.title || 'No title available' }}</h1>\n <p>{{ lesson.description || lesson.metadata?.description || 'No description available' }}</p>\n <div class=\"card-footer\">\n <div class=\"status-tags\">\n <span class=\"level-tag\">Nivel {{ lesson.level }}</span>\n @if (lesson.taken?.status == 'passed') {\n <p-tag severity=\"success\" value=\"Tomada\" [rounded]=\"true\" />\n } @if (lesson.taken?.status == 'failed') {\n <p-tag severity=\"danger\" value=\"Fallida\" [rounded]=\"true\" />\n } @if (lesson.taken) {\n <p-tag severity=\"success\" value=\"Tomada \uD83D\uDCD6\" [rounded]=\"true\" />\n } @if (!lesson.metadata?.isPublished) {\n <p-tag severity=\"danger\" value=\"No publicada\" [rounded]=\"true\" />\n }\n </div>\n\n <div style=\"position: absolute; bottom: 0px; right: 0px\">\n <p-button label=\"Tomar lecci\u00F3n\" (onClick)=\"eventCard(eventType.Select)\" severity=\"primary\"> </p-button>\n </div>\n </div>\n </div>\n </div>\n </p-card>\n</div>\n", styles: [".card-container{position:relative;margin-bottom:20px;margin-left:10px}.dial-button{position:absolute;top:10px;right:20px;z-index:10}.lesson-card{border-radius:.5rem;height:100%}.lesson-card .photo{position:absolute;inset:0;z-index:1}.lesson-card .photo img{width:100%;height:100%;object-fit:cover;object-position:center}.lesson-card .photo:after{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(to bottom,rgb(0,0,0) 50%,var(--p-primary-color) 100%);opacity:.4;z-index:2;pointer-events:none}.description{position:relative;z-index:2;color:#fff;height:100%;display:flex;flex-direction:column}.description h1{margin-top:0;margin-bottom:.5rem;font-size:1.5rem;font-weight:900;text-shadow:1px 1px 2px rgba(0,0,0,.7)}.description p{margin-bottom:1rem;flex-grow:1;font-weight:500;text-shadow:1px 1px 2px rgba(0,0,0,.9)}.date{position:absolute;top:1rem;left:1rem;z-index:3;background-color:#000000b3;color:#fff;padding:.3rem .6rem;border-radius:.25rem;font-size:.8rem}.card-footer{display:flex;justify-content:space-between;align-items:center;margin-top:auto}.status-tags{display:flex;gap:.5rem}.status-tags .level-tag,.status-tags .status-tag{padding:.3rem .6rem;border-radius:.25rem;font-size:.8rem}.status-tags .level-tag{background-color:#fff3}.status-tags .status-tag.success{background-color:#28a745b3}.status-tags .status-tag.danger{background-color:#dc3545b3}\n"] }]
653
+ args: [{ selector: 'dc-lesson-card', standalone: true, imports: [DatePipe, ButtonModule, PopoverModule, SpeedDialModule, CardModule, TagModule], template: "<div class=\"card-container\">\n @if(showOptions){\n <p-speeddial\n class=\"dial-button\"\n [model]=\"items\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\"\n [tooltipOptions]=\"{ tooltipPosition: 'top' }\" />\n }\n <p-card>\n <div class=\"lesson-card\" [style.height]=\"cardHeight\">\n <div class=\"photo\">\n <img [src]=\"coverUrl\" alt=\"\" />\n </div>\n\n <span class=\"date\">{{ lesson.createdAt | date : 'dd/MM/yyyy' }}</span>\n\n <div class=\"description\">\n <h1>{{ lesson.title || lesson.metadata?.title || 'No title available' }}</h1>\n <p>{{ lesson.description || lesson.metadata?.description || 'No description available' }}</p>\n <div class=\"card-footer\">\n <div class=\"status-tags\">\n <span class=\"level-tag\">Nivel {{ lesson.level }}</span>\n @if (lesson.taken?.status == 'passed') {\n <p-tag severity=\"success\" value=\"Tomada\" [rounded]=\"true\" />\n } @if (lesson.taken?.status == 'failed') {\n <p-tag severity=\"danger\" value=\"Fallida\" [rounded]=\"true\" />\n } @if (lesson.taken) {\n <p-tag severity=\"success\" value=\"Tomada \uD83D\uDCD6\" [rounded]=\"true\" />\n } @if (!lesson.metadata?.isPublished) {\n <p-tag severity=\"danger\" value=\"No publicada\" [rounded]=\"true\" />\n }\n </div>\n\n <div style=\"position: absolute; bottom: 0px; right: 0px\">\n <p-button label=\"Tomar lecci\u00F3n\" (onClick)=\"eventCard(eventType.Select)\" severity=\"primary\"> </p-button>\n </div>\n </div>\n </div>\n </div>\n </p-card>\n</div>\n", styles: [".card-container{position:relative;margin-bottom:20px;margin-left:10px}.dial-button{position:absolute;top:10px;right:20px;z-index:10}.lesson-card{border-radius:.5rem;height:100%}.lesson-card .photo{position:absolute;inset:0;z-index:1}.lesson-card .photo img{width:100%;height:100%;object-fit:cover;object-position:center}.lesson-card .photo:after{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(to bottom,rgb(0,0,0) 50%,var(--p-primary-color) 100%);opacity:.4;z-index:2;pointer-events:none}.description{position:relative;z-index:2;color:#fff;height:100%;display:flex;flex-direction:column}.description h1{margin-top:0;margin-bottom:.5rem;font-size:1.5rem;font-weight:900;text-shadow:1px 1px 2px rgba(0,0,0,.7)}.description p{margin-bottom:1rem;flex-grow:1;font-weight:500;text-shadow:1px 1px 2px rgba(0,0,0,.9)}.date{position:absolute;top:1rem;left:1rem;z-index:3;background-color:#000000b3;color:#fff;padding:.3rem .6rem;border-radius:.25rem;font-size:.8rem}.card-footer{display:flex;justify-content:space-between;align-items:center;margin-top:auto}.status-tags{display:flex;gap:.5rem}.status-tags .level-tag,.status-tags .status-tag{padding:.3rem .6rem;border-radius:.25rem;font-size:.8rem}.status-tags .level-tag{background-color:#fff3}.status-tags .status-tag.success{background-color:#28a745b3}.status-tags .status-tag.danger{background-color:#dc3545b3}\n"] }]
682
654
  }], propDecorators: { lesson: [{
683
655
  type: Input
684
656
  }], showOptions: [{
@@ -689,141 +661,209 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
689
661
  type: Output
690
662
  }] } });
691
663
 
664
+ class DefaultLessonsService extends EntityCommunicationService {
665
+ constructor() {
666
+ super('lesson');
667
+ // --- Endpoint Definitions for methods not in EntityCommunicationService ---
668
+ this.endpoints = {
669
+ saveTakenLesson: `api/user/saveLesson`,
670
+ generateLesson: `api/lesson/generate`,
671
+ generateByAI: `api/lesson/generate-ai`,
672
+ improveMDWithAI: `api/lesson/improve-markdown-ai`,
673
+ GenerateBanner: 'api/lesson/generate-banner',
674
+ };
675
+ }
676
+ // --- Method Implementations from LessonsAbstractService ---
677
+ async getLessons(filters = {}) {
678
+ if (!filters.returnProps) {
679
+ filters.returnProps = {
680
+ level: 1,
681
+ title: 1,
682
+ description: 1,
683
+ createdDate: 1,
684
+ banner: 1,
685
+ metadata: 1,
686
+ appExtensions: 1,
687
+ media: 1,
688
+ };
689
+ }
690
+ return this.query(filters);
691
+ }
692
+ async getLesson(id) {
693
+ return this.findOne(id);
694
+ }
695
+ async postLesson(lesson) {
696
+ return this.createOrUpdate(lesson);
697
+ }
698
+ async updateLesson(lesson) {
699
+ if (!lesson._id) {
700
+ throw new Error('Lesson ID is required for update.');
701
+ }
702
+ return this.createOrUpdate(lesson);
703
+ }
704
+ async deleteLesson(id) {
705
+ await this.remove(id);
706
+ }
707
+ // --- Methods specific to lessons ---
708
+ saveTakenLesson(lesson) {
709
+ return this.httpService.post(this.endpoints.saveTakenLesson, lesson);
710
+ }
711
+ async generateLesson(lesson) {
712
+ return this.httpService.post(this.endpoints.generateLesson, lesson);
713
+ }
714
+ async postGenerateByAI(id) {
715
+ return this.httpService.post(this.endpoints.generateByAI, { id });
716
+ }
717
+ async postImproveMDWithAI(lessonId, markdownText) {
718
+ return this.httpService.post(this.endpoints.improveMDWithAI, { id: lessonId, markdown: markdownText });
719
+ }
720
+ generateBanner(prompt, lessonId) {
721
+ return this.httpService.post(this.endpoints.GenerateBanner, { prompt, lessonId });
722
+ }
723
+ extractTextFromHtml(html) {
724
+ const r1 = new RegExp('~(.+?)~', 'g');
725
+ const lessonHtml = html.replace(r1, (_matching, jsonCoded) => {
726
+ try {
727
+ const data = JSON.parse(jsonCoded);
728
+ return `<span>${data?.settings?.text || ''}</span>`;
729
+ }
730
+ catch (e) {
731
+ console.error('Error parsing JSON in extractTextFromHtml:', jsonCoded, e);
732
+ return '';
733
+ }
734
+ });
735
+ let text = lessonHtml.replace(/<[^>]*>/g, ' ');
736
+ text = text.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, ' ');
737
+ text = text.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, ' ');
738
+ text = text.replace(/&nbsp;/g, ' ');
739
+ text = text.replace(/&/g, '&');
740
+ text = text.replace(/</g, '<');
741
+ text = text.replace(/>/g, '>');
742
+ text = text.replace(/\s+/g, ' ').trim();
743
+ return text;
744
+ }
745
+ getPrompts() {
746
+ return null;
747
+ }
748
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DefaultLessonsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
749
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DefaultLessonsService, providedIn: 'root' }); }
750
+ }
751
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DefaultLessonsService, decorators: [{
752
+ type: Injectable,
753
+ args: [{
754
+ providedIn: 'root',
755
+ }]
756
+ }], ctorParameters: () => [] });
757
+
692
758
  const tableViewColumns = [
693
759
  { field: 'media.images[0].url', header: 'Image', type: 'image' },
694
760
  { field: 'title', header: 'Título' },
695
761
  { field: 'description', header: 'Descripción' },
696
762
  ];
697
- const TableViewActions = [
698
- { title: 'select', label: 'Select', icon: 'pi pi-check', severity: 'primary' },
699
- { title: 'qr', label: 'QR', icon: 'pi pi-qrcode', severity: 'info' },
700
- { title: 'edit', label: 'Edit', icon: 'pi pi-pencil', severity: 'info' },
701
- { title: 'delete', label: 'Delete', icon: 'pi pi-trash', severity: 'danger' },
702
- ];
703
- const returnProperties = { id: 1, title: 1, assets: 1 };
704
- class DCLessonListComponent extends PaginationBase {
763
+ class DCLessonListComponent extends EntityBaseListComponent {
705
764
  constructor() {
706
- super(...arguments);
707
- this.showOptions = true;
765
+ super();
708
766
  this.customFilters = [];
709
- this.viewType = 'cards';
710
767
  // Injected Services
711
- this.cdr = inject(ChangeDetectorRef);
712
- this.lessonsService = inject(LESSONS_TOKEN);
713
- this.toastrService = inject(TOAST_ALERTS_TOKEN);
768
+ // I dont rename so use the same in EntityBaseListComponent and Pagination
769
+ this.entityCommunicationService = inject(LESSONS_TOKEN, { optional: true }) ?? inject(DefaultLessonsService);
714
770
  this.columns = tableViewColumns;
715
- this.cardComponent = null;
771
+ // Private properties
716
772
  this.cardEventSubs = [];
717
- this.lessons = [];
718
- this.isLoadingLessons = false;
773
+ this.filterConfig.returnProps = {
774
+ title: 1,
775
+ description: 1,
776
+ media: 1,
777
+ _id: 1,
778
+ id: 1,
779
+ };
780
+ effect(() => {
781
+ // When items signal changes, re-subscribe to card events
782
+ this.items(); // a little hack to make the effect run when items change
783
+ setTimeout(() => this.subscribeToCardEvents());
784
+ });
719
785
  }
720
- ngOnInit() {
721
- this.filterConfig.returnProps = returnProperties;
786
+ async ngOnInit() {
722
787
  this.cardComponent = this.customCardComponent || DcLessonCardComponent;
723
- // TODO: i think show options is for admin, but refactor to add ListFilterBarOptions
724
- this.filterBarOptions = { showCreateButton: this.showOptions, showViewButton: this.showOptions, showActions: this.showOptions };
725
- this.getPaginatedLessons(this.filterConfig);
726
- }
727
- subscribeDinamicInstantToEvents() {
728
- this.clearcardEventSubs();
729
- this.subscribeToCardEvents();
730
- }
731
- subscribeToCardEvents() {
732
- this.outlets.forEach((outlet) => {
733
- const instance = outlet.componentInstance;
734
- this.cardEventSubs.push(instance.onAction.subscribe((lesson) => {
735
- this.doOrEmitAction(lesson);
736
- }));
737
- });
788
+ await super.ngOnInit();
738
789
  }
739
- clearcardEventSubs() {
740
- this.cardEventSubs.forEach((sub) => sub.unsubscribe());
741
- this.cardEventSubs = [];
790
+ ngAfterViewInit() {
791
+ this.outlets.changes.subscribe(() => this.subscribeToCardEvents());
742
792
  }
743
793
  ngOnDestroy() {
744
- this.clearcardEventSubs();
794
+ this.clearCardEventSubs();
745
795
  }
746
- async getPaginatedLessons(paginator) {
747
- try {
748
- this.lessons = null;
749
- this.isLoadingLessons = true;
750
- this.cdr.detectChanges();
751
- const lessons = await this.lessonsService.getLessons(paginator);
752
- this.lessons = lessons['rows'] || lessons;
753
- this.totalRecords = lessons['count'] || this.lessons.length;
754
- console.log('lessons', lessons);
755
- setTimeout(() => {
756
- this.subscribeDinamicInstantToEvents();
757
- });
758
- }
759
- finally {
760
- this.isLoadingLessons = false;
761
- this.cdr.detectChanges();
762
- }
763
- }
764
- search(searchText) {
765
- this.filterConfig['text'] = searchText;
766
- this.getPaginatedLessons(this.filterConfig);
796
+ getCustomButtons(item) {
797
+ return [
798
+ { label: 'Select', icon: 'pi pi-check', command: () => this.handleAction({ action: 'select', item }) },
799
+ { label: 'QR', icon: 'pi pi-qrcode', command: () => this.handleAction({ action: 'qr', item }) },
800
+ ];
767
801
  }
768
- removeLesson(lesson) {
769
- const response = confirm('¿Estás seguro de querer eliminar esta lección?');
770
- if (response) {
771
- this.lessonsService.deleteLesson(lesson._id);
772
- this.lessons = this.lessons.filter((l) => l._id !== lesson._id);
773
- this.cdr.detectChanges();
774
- this.toastrService.success({ title: 'Adios a la lección', subtitle: 'La lección ha sido eliminada correctamente' });
802
+ handleAction(actionEvent) {
803
+ if (['select', 'qr'].includes(actionEvent.action)) {
804
+ this.onAction.emit(actionEvent);
805
+ }
806
+ else {
807
+ super.doAction(actionEvent);
775
808
  }
776
- }
777
- newLesson() {
778
- this.onAction.emit({ action: 'new' });
779
809
  }
780
810
  applyFilterBarEvent(filterEvent) {
781
- if (filterEvent.action == 'changeView') {
782
- this.viewType = this.viewType === 'table' ? 'cards' : 'table';
811
+ if (filterEvent.action === 'changeView') {
812
+ this.toggleView();
783
813
  return;
784
814
  }
785
- else {
786
- console.log('filterChanged in dc-lesson-list', filterEvent);
787
- this.filterConfig = filterEvent.item;
788
- this.filterConfig.returnProps = returnProperties;
789
- this.getPaginatedLessons(this.filterConfig);
790
- }
815
+ this.filterConfig = { ...this.filterConfig, ...filterEvent.item };
816
+ this.loadData();
791
817
  }
792
- loadData() {
793
- return this.getPaginatedLessons(this.filterConfig);
818
+ subscribeToCardEvents() {
819
+ this.clearCardEventSubs();
820
+ this.outlets.forEach((outlet) => {
821
+ const instance = outlet.componentInstance;
822
+ if (instance?.onAction) {
823
+ this.cardEventSubs.push(instance.onAction.subscribe((event) => {
824
+ this.handleAction(event);
825
+ }));
826
+ }
827
+ });
794
828
  }
795
- doOrEmitAction(actionEvent) {
796
- if (actionEvent.action === 'delete') {
797
- this.removeLesson(actionEvent.item);
829
+ clearCardEventSubs() {
830
+ this.cardEventSubs.forEach((sub) => sub.unsubscribe());
831
+ this.cardEventSubs = [];
832
+ }
833
+ async loadData() {
834
+ try {
835
+ this.isLoading = true;
836
+ const response = await this.entityCommunicationService.getLessons(this.filterConfig);
837
+ this.items.set(response.rows);
838
+ this.totalRecordsSignal.set(response.count);
798
839
  }
799
- else {
800
- this.onAction.emit(actionEvent);
840
+ catch (error) {
841
+ console.error('Error loading data', error);
842
+ }
843
+ finally {
844
+ this.isLoading = false;
801
845
  }
802
846
  }
803
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
804
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: DCLessonListComponent, isStandalone: true, selector: "dc-lesson-list", inputs: { showOptions: "showOptions", customCardComponent: "customCardComponent", customFilters: "customFilters", viewType: "viewType" }, viewQueries: [{ propertyName: "outlets", predicate: ["outlet"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<dc-filter-bar\n [options]=\"filterBarOptions\"\n [customFilters]=\"customFilters\"\n (onFilterAction)=\"applyFilterBarEvent($event)\"\n (onNew)=\"newLesson()\"></dc-filter-bar>\n@if(viewType === 'table') {\n\n<app-quick-table [tableData]=\"lessons\" (onAction)=\"doOrEmitAction($event)\"></app-quick-table>\n\n} @else {\n<div class=\"lesson-list-container\">\n @if (!isLoadingLessons && lessons?.length > 0) { @for (lesson of lessons; track lesson._id) {\n <ng-container\n #outlet=\"ngComponentOutlet\"\n [ngComponentOutlet]=\"cardComponent\"\n [ngComponentOutletInputs]=\"{\n lesson: lesson,\n showOptions: showOptions\n }\">\n </ng-container>\n } } @else {\n <p>No se encontraron lecciones disponibles</p>\n }\n</div>\n}\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} lecciones\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [":host{display:flex;flex-direction:column;height:100%}.lesson-list-container{padding:1.5rem;flex:1;overflow-y:auto;min-height:0}@media (max-width: 768px){.lesson-list-container{margin-top:1rem;padding:0rem}}p-paginator{margin-top:auto;padding:.5rem 1rem}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters"], outputs: ["onFilterAction", "onChangeSort", "onNew"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i1$2.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "style", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "appendTo", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first"], outputs: ["onPageChange"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }] }); }
847
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
848
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DCLessonListComponent, isStandalone: true, selector: "dc-lesson-list", inputs: { customCardComponent: "customCardComponent", customFilters: "customFilters" }, viewQueries: [{ propertyName: "outlets", predicate: ["outlet"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<dc-filter-bar [options]=\"filterBarOptions\" [customFilters]=\"customFilters\" (onFilterAction)=\"applyFilterBarEvent($event)\" (onNew)=\"onNew()\"></dc-filter-bar>\n@if(viewType() === 'table') {\n\n<app-quick-table [tableData]=\"items()\" (onAction)=\"doAction($event)\"></app-quick-table>\n\n} @else {\n<div class=\"lesson-list-container\">\n @if (items()?.length > 0) { @for (lesson of items(); track lesson._id) {\n <ng-container\n #outlet=\"ngComponentOutlet\"\n [ngComponentOutlet]=\"cardComponent\"\n [ngComponentOutletInputs]=\"{\n lesson: lesson,\n showOptions: true\n }\">\n </ng-container>\n\n } } @else {\n <p>No se encontraron lecciones disponibles</p>\n }\n</div>\n}\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} lecciones\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [totalRecords]=\"totalRecords\"\n [first]=\"first\"\n [rows]=\"rows\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [":host{display:flex;flex-direction:column;height:100%}.lesson-list-container{padding:1.5rem;flex:1;overflow-y:auto;min-height:0}@media (max-width: 768px){.lesson-list-container{margin-top:1rem;padding:0rem}}p-paginator{margin-top:auto;padding:.5rem 1rem}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters"], outputs: ["onFilterAction", "onChangeSort", "onNew"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i1$2.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }] }); }
805
849
  }
806
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonListComponent, decorators: [{
850
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonListComponent, decorators: [{
807
851
  type: Component,
808
- args: [{ selector: 'dc-lesson-list', standalone: true, imports: [RouterModule, DCFilterBarComponent, PaginatorModule, NgComponentOutlet, QuickTableComponent], template: "<dc-filter-bar\n [options]=\"filterBarOptions\"\n [customFilters]=\"customFilters\"\n (onFilterAction)=\"applyFilterBarEvent($event)\"\n (onNew)=\"newLesson()\"></dc-filter-bar>\n@if(viewType === 'table') {\n\n<app-quick-table [tableData]=\"lessons\" (onAction)=\"doOrEmitAction($event)\"></app-quick-table>\n\n} @else {\n<div class=\"lesson-list-container\">\n @if (!isLoadingLessons && lessons?.length > 0) { @for (lesson of lessons; track lesson._id) {\n <ng-container\n #outlet=\"ngComponentOutlet\"\n [ngComponentOutlet]=\"cardComponent\"\n [ngComponentOutletInputs]=\"{\n lesson: lesson,\n showOptions: showOptions\n }\">\n </ng-container>\n } } @else {\n <p>No se encontraron lecciones disponibles</p>\n }\n</div>\n}\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} lecciones\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [":host{display:flex;flex-direction:column;height:100%}.lesson-list-container{padding:1.5rem;flex:1;overflow-y:auto;min-height:0}@media (max-width: 768px){.lesson-list-container{margin-top:1rem;padding:0rem}}p-paginator{margin-top:auto;padding:.5rem 1rem}\n"] }]
809
- }], propDecorators: { showOptions: [{
810
- type: Input
811
- }], customCardComponent: [{
852
+ args: [{ selector: 'dc-lesson-list', standalone: true, imports: [RouterModule, DCFilterBarComponent, NgComponentOutlet, QuickTableComponent, PaginatorModule], template: "<dc-filter-bar [options]=\"filterBarOptions\" [customFilters]=\"customFilters\" (onFilterAction)=\"applyFilterBarEvent($event)\" (onNew)=\"onNew()\"></dc-filter-bar>\n@if(viewType() === 'table') {\n\n<app-quick-table [tableData]=\"items()\" (onAction)=\"doAction($event)\"></app-quick-table>\n\n} @else {\n<div class=\"lesson-list-container\">\n @if (items()?.length > 0) { @for (lesson of items(); track lesson._id) {\n <ng-container\n #outlet=\"ngComponentOutlet\"\n [ngComponentOutlet]=\"cardComponent\"\n [ngComponentOutletInputs]=\"{\n lesson: lesson,\n showOptions: true\n }\">\n </ng-container>\n\n } } @else {\n <p>No se encontraron lecciones disponibles</p>\n }\n</div>\n}\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} lecciones\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [totalRecords]=\"totalRecords\"\n [first]=\"first\"\n [rows]=\"rows\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [":host{display:flex;flex-direction:column;height:100%}.lesson-list-container{padding:1.5rem;flex:1;overflow-y:auto;min-height:0}@media (max-width: 768px){.lesson-list-container{margin-top:1rem;padding:0rem}}p-paginator{margin-top:auto;padding:.5rem 1rem}\n"] }]
853
+ }], ctorParameters: () => [], propDecorators: { customCardComponent: [{
812
854
  type: Input
813
855
  }], customFilters: [{
814
856
  type: Input
815
- }], viewType: [{
816
- type: Input
817
857
  }], outlets: [{
818
858
  type: ViewChildren,
819
859
  args: ['outlet']
820
860
  }] } });
821
861
 
822
862
  class DCLessonFormComponent {
823
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
824
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: DCLessonFormComponent, isStandalone: true, selector: "dc-lesson-form", ngImport: i0, template: "<div class=\"lesson-form-container\">\n <h2>Lesson Form</h2>\n <p>Esto es dentro del componente de la leccion</p>\n <!-- Form implementation will go here -->\n</div>\n", styles: [".lesson-form-container{padding:1rem}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }] }); }
863
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
864
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: DCLessonFormComponent, isStandalone: true, selector: "dc-lesson-form", ngImport: i0, template: "<div class=\"lesson-form-container\">\n <h2>Lesson Form</h2>\n <p>Esto es dentro del componente de la leccion</p>\n <!-- Form implementation will go here -->\n</div>\n", styles: [".lesson-form-container{padding:1rem}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }] }); }
825
865
  }
826
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonFormComponent, decorators: [{
866
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonFormComponent, decorators: [{
827
867
  type: Component,
828
868
  args: [{ selector: 'dc-lesson-form', standalone: true, imports: [ReactiveFormsModule], template: "<div class=\"lesson-form-container\">\n <h2>Lesson Form</h2>\n <p>Esto es dentro del componente de la leccion</p>\n <!-- Form implementation will go here -->\n</div>\n", styles: [".lesson-form-container{padding:1rem}\n"] }]
829
869
  }] });
@@ -843,7 +883,6 @@ const DEFAULT_LESSON_AGENT_CARD = {
843
883
  post_history_instructions: 'Your reply should be always short, 1 or 2 paragraphs at most, and to the point, and you should ask friendly questions all the time',
844
884
  },
845
885
  },
846
- model: { provider: 'google' },
847
886
  };
848
887
  const AppRolePlaySkill = `
849
888
  You are an app role play assistant from Polilan App. The user is reading lessons through this app interface. They will now talk with you, and you need to evaluate their understanding of the lesson.
@@ -854,14 +893,13 @@ You are an engagement assistant, start by greeting the user, asking something ab
854
893
  that makes sense for the lesson.
855
894
  `;
856
895
  function getDefaultLessonEvaluatorAgentCard(lessonText) {
896
+ // TODO: probably i need to build in order to add the sources to the task or system.
857
897
  return {
858
898
  expectedResponseType: `interface EvalResult {
859
899
  score: number; // Score of the user's response 0 to 3
860
900
  feedback: string; // Feedback of the user's understanding of the conversation
861
901
  }`,
862
- messages: [],
863
902
  model: { id: 'gpt-4o-mini', provider: 'openai' },
864
- sources: [lessonText],
865
903
  task: `User is reading a taking a lesson, now their are having a conversation,
866
904
  you have to evaluate the current conversation, and give a feedback of the user understanding of the lesson,
867
905
  this is the lesson: ${lessonText}`,
@@ -869,8 +907,7 @@ function getDefaultLessonEvaluatorAgentCard(lessonText) {
869
907
  }
870
908
  class LessonAIService {
871
909
  constructor() {
872
- this.lessonService = inject(LESSONS_TOKEN);
873
- // TODO: Inject the application-level UserService
910
+ this.lessonsService = inject(LESSONS_TOKEN, { optional: true }) ?? inject(DefaultLessonsService);
874
911
  this.userService = inject(USER_DATA_EXCHANGE);
875
912
  }
876
913
  /**
@@ -894,7 +931,7 @@ ${userInformationPrompt}`;
894
931
  * @returns An object containing the master agent card and the evaluator agent card.
895
932
  */
896
933
  async generateAgentCards(lesson) {
897
- const lessonText = this.lessonService.extractTextFromHtml(lesson.textCoded);
934
+ const lessonText = this.lessonsService.extractTextFromHtml(lesson.textCoded);
898
935
  const userInformationPrompt = this.userService.getUserDataInformation();
899
936
  const scenario = this._buildScenarioPrompt(lessonText, userInformationPrompt);
900
937
  // Create a deep copy of the default card to avoid modifying the constant
@@ -912,7 +949,7 @@ ${userInformationPrompt}`;
912
949
  async generateConversationSettingsForLesson(lesson, settings) {
913
950
  // TODO: Consolidate user fetching logic if possible, or ensure consistency
914
951
  const baseLang = this.userService.getUserDataExchange()?.baseLang || 'en';
915
- const lessonText = this.lessonService.extractTextFromHtml(lesson.textCoded);
952
+ const lessonText = this.lessonsService.extractTextFromHtml(lesson.textCoded);
916
953
  const userInformationPrompt = this.userService.getUserDataInformation();
917
954
  let scenario = this._buildScenarioPrompt(lessonText, userInformationPrompt);
918
955
  if (settings.additionalPrompt) {
@@ -921,6 +958,7 @@ ${userInformationPrompt}`;
921
958
  const initialMessage = {
922
959
  role: ChatRole.System,
923
960
  content: scenario,
961
+ messageId: SystemPromptType.SystemPrompt,
924
962
  };
925
963
  // Use defaults similar to DEFAULT_LESSON_AGENT_CARD but adjust for prompt-based start
926
964
  const conversationSettings = {
@@ -929,14 +967,14 @@ ${userInformationPrompt}`;
929
967
  autoStart: true,
930
968
  messages: [initialMessage],
931
969
  model: { provider: 'google' },
932
- voice: getRandomQuickVoice(baseLang || 'en', 'female'),
970
+ tts: { voice: getRandomQuickVoice(baseLang || 'en', 'female') },
933
971
  };
934
972
  return conversationSettings;
935
973
  }
936
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonAIService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
937
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonAIService, providedIn: 'root' }); }
974
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonAIService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
975
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonAIService, providedIn: 'root' }); }
938
976
  }
939
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonAIService, decorators: [{
977
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonAIService, decorators: [{
940
978
  type: Injectable,
941
979
  args: [{
942
980
  providedIn: 'root', // Or provide appropriately if it's library-specific
@@ -994,10 +1032,10 @@ class DynamicComponentsService {
994
1032
  getDynamicComponentClass(type) {
995
1033
  return this._dynamicComponents[type];
996
1034
  }
997
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DynamicComponentsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
998
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DynamicComponentsService, providedIn: 'root' }); }
1035
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DynamicComponentsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1036
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DynamicComponentsService, providedIn: 'root' }); }
999
1037
  }
1000
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DynamicComponentsService, decorators: [{
1038
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DynamicComponentsService, decorators: [{
1001
1039
  type: Injectable,
1002
1040
  args: [{
1003
1041
  providedIn: 'root',
@@ -1007,29 +1045,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
1007
1045
  class DCLessonRendererComponent {
1008
1046
  constructor() {
1009
1047
  // --- Signal Inputs ---
1010
- this.lessonInput = input(); // Input signal for lesson object
1011
- this.lessonIdInput = input(); // Input signal for lesson ID
1012
- this.settings = input();
1048
+ this.lessonInput = input(...(ngDevMode ? [undefined, { debugName: "lessonInput" }] : [])); // Input signal for lesson object
1049
+ this.lessonIdInput = input(...(ngDevMode ? [undefined, { debugName: "lessonIdInput" }] : [])); // Input signal for lesson ID
1050
+ this.settings = input(...(ngDevMode ? [undefined, { debugName: "settings" }] : []));
1013
1051
  // --- Outputs ---
1014
1052
  this.wordClicked = new EventEmitter(); // New output event
1015
1053
  // --- Services ---
1016
1054
  this.renderer = inject(Renderer2);
1017
1055
  this.viewContainerRef = inject(ViewContainerRef);
1018
1056
  this.toastrService = inject(TOAST_ALERTS_TOKEN);
1019
- this.lessonService = inject(LESSONS_TOKEN);
1057
+ this.lessonsService = inject(LESSONS_TOKEN, { optional: true }) ?? inject(DefaultLessonsService);
1020
1058
  this.lessonAIService = inject(LessonAIService); // Inject the new service
1021
1059
  this.userDataExchange = inject(USER_DATA_EXCHANGE);
1022
1060
  this.dynamicComponentsService = inject(DynamicComponentsService);
1061
+ this.uiStateService = inject(UiStateService);
1023
1062
  // --- State Signals ---
1024
- this.lesson = signal(undefined); // Internal lesson state signal
1025
- this.chatVisible = signal(false); // Signal for chat visibility
1026
- this.agentMasterLesson = signal(undefined); // Signal for agent card
1027
- this.evaluatorAgentCard = signal(undefined); // Signal for evaluator card
1028
- this.conversationSettings = signal(undefined);
1029
- this.evalAgentTask = signal(undefined); // Signal for evaluator card
1030
- this.backgroundTasks = {};
1063
+ this.lesson = signal(undefined, ...(ngDevMode ? [{ debugName: "lesson" }] : [])); // Internal lesson state signal
1064
+ // chatVisible = this.uiStateService.chatDrawerVisible; // Signal for chat visibility
1065
+ this.agentMasterLesson = signal(undefined, ...(ngDevMode ? [{ debugName: "agentMasterLesson" }] : [])); // Signal for agent card
1066
+ this.evaluatorAgentCard = signal(undefined, ...(ngDevMode ? [{ debugName: "evaluatorAgentCard" }] : [])); // Signal for evaluator card
1067
+ this.conversationSettings = signal(undefined, ...(ngDevMode ? [{ debugName: "conversationSettings" }] : []));
1068
+ this.evalAgentTask = signal(undefined, ...(ngDevMode ? [{ debugName: "evalAgentTask" }] : [])); // Signal for evaluator card
1069
+ // backgroundTasks: Record<ConversationEvents | string, SimpleAgentTask> = {};
1070
+ this.conversationFlow = signal(undefined, ...(ngDevMode ? [{ debugName: "conversationFlow" }] : []));
1031
1071
  // --- Computed Signals ---
1032
- this.imageCover = computed(() => this.lesson()?.media?.images?.find((img) => img.type === 'cover')?.url); // Computed signal for imageCover
1072
+ this.imageCover = computed(() => this.lesson()?.media?.images?.find((img) => img.type === 'cover')?.url, ...(ngDevMode ? [{ debugName: "imageCover" }] : [])); // Computed signal for imageCover
1033
1073
  // --- Properties ---
1034
1074
  this.components = {};
1035
1075
  this.mainForm = new FormGroup({});
@@ -1046,7 +1086,7 @@ class DCLessonRendererComponent {
1046
1086
  console.log(`[Renderer] Effect 1: Fetching lesson ${lessonId}`);
1047
1087
  try {
1048
1088
  // Consider adding a loading state signal here
1049
- const fetchedLesson = await this.lessonService.getLesson(lessonId);
1089
+ const fetchedLesson = await this.lessonsService.getLesson(lessonId);
1050
1090
  this.lesson.set(fetchedLesson);
1051
1091
  console.log('Fetched lesson:', fetchedLesson);
1052
1092
  }
@@ -1091,9 +1131,55 @@ class DCLessonRendererComponent {
1091
1131
  });
1092
1132
  }
1093
1133
  ngOnInit() {
1094
- this.backgroundTasks = {
1095
- [ConversationEvents.OnUserMessage]: this.evalAgentTask(),
1096
- };
1134
+ // TODO: esto es mal, el goal no puede venir aqui sino pasado desde el componente que inicie la lección
1135
+ this.conversationFlow.set({
1136
+ goal: {
1137
+ enabled: true,
1138
+ task: `User is learning is taking a lesson about languages, evaluate how good are the responses.`,
1139
+ model: { quality: EModelQuality.FAST },
1140
+ },
1141
+ triggerTasks: {
1142
+ [ConversationEvents.OnUserMessage]: {
1143
+ enabled: true,
1144
+ ...this.evalAgentTask(),
1145
+ },
1146
+ },
1147
+ challenges: null,
1148
+ dynamicConditions: [
1149
+ {
1150
+ what: ConditionType.Goal,
1151
+ when: ConditionOperator.GreaterThanOrEqual,
1152
+ value: 100,
1153
+ do: [
1154
+ {
1155
+ actionType: EDoActionType.ChangePrompt,
1156
+ systemPromptType: SystemPromptType.SystemPrompt,
1157
+ prompt: 'You were talking with the user, user finish the conversation, in the next message you must try to finish the conversation and say good bye.',
1158
+ },
1159
+ {
1160
+ actionType: EDoActionType.ChangePrompt,
1161
+ systemPromptType: SystemPromptType.CharacterDescription,
1162
+ prompt: '',
1163
+ },
1164
+ {
1165
+ actionType: EDoActionType.ChangePrompt,
1166
+ systemPromptType: SystemPromptType.UserInformation,
1167
+ prompt: '',
1168
+ },
1169
+ {
1170
+ actionType: EDoActionType.ChangePrompt,
1171
+ systemPromptType: SystemPromptType.MessageExamples,
1172
+ prompt: '',
1173
+ },
1174
+ {
1175
+ actionType: EDoActionType.ChangePrompt,
1176
+ systemPromptType: SystemPromptType.ScenarioDescription,
1177
+ prompt: '',
1178
+ },
1179
+ ],
1180
+ },
1181
+ ],
1182
+ });
1097
1183
  }
1098
1184
  // --- Rendering Logic ---
1099
1185
  _clearLessonRendering() {
@@ -1279,7 +1365,7 @@ class DCLessonRendererComponent {
1279
1365
  const conversationSettings = await this.lessonAIService.generateConversationSettingsForLesson(currentLesson, this.settings());
1280
1366
  if (conversationSettings) {
1281
1367
  this.conversationSettings.set(conversationSettings);
1282
- this.chatVisible.set(true);
1368
+ this.uiStateService.chatDrawerVisible.set(true);
1283
1369
  console.log('Agent cards received and set.');
1284
1370
  }
1285
1371
  else {
@@ -1294,14 +1380,17 @@ class DCLessonRendererComponent {
1294
1380
  }
1295
1381
  onVisibleChange(isVisible) {
1296
1382
  if (isVisible === false) {
1297
- this.chatVisible.set(false);
1383
+ this.uiStateService.chatDrawerVisible.set(false);
1298
1384
  }
1299
1385
  }
1300
- handleGoalCompleted(event) {
1386
+ async handleGoalCompleted(event = {}) {
1301
1387
  console.log('Goal completed:', event);
1302
1388
  const lesson = this.lesson();
1303
- const dummy = { id: lesson.id, goalCompleted: true, score: 100, status: 'finished', lastAccess: new Date() };
1304
- this.lessonService.saveTakenLesson(dummy);
1389
+ const takenLesson = { id: lesson.id, goalCompleted: true, score: 100, status: 'finished', lastAccess: new Date() };
1390
+ const res = await this.lessonsService.saveTakenLesson(takenLesson);
1391
+ if (res) {
1392
+ // this.lessonsMemStateService.updateUserState(res);
1393
+ }
1305
1394
  this.toastrService.success({ subtitle: '¡Has completado la lección! , pero puedes seguir conversando', title: '¡Muy bien, guardaremos tu progreso!' });
1306
1395
  }
1307
1396
  onChatMessage(event) {
@@ -1318,12 +1407,12 @@ class DCLessonRendererComponent {
1318
1407
  console.log('Unhandled chat event type:', event.type);
1319
1408
  }
1320
1409
  }
1321
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1322
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: DCLessonRendererComponent, isStandalone: true, selector: "dc-lesson-renderer", inputs: { lessonInput: { classPropertyName: "lessonInput", publicName: "lessonInput", isSignal: true, isRequired: false, transformFunction: null }, lessonIdInput: { classPropertyName: "lessonIdInput", publicName: "lessonIdInput", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { wordClicked: "wordClicked" }, viewQueries: [{ propertyName: "dynamicLesson", first: true, predicate: ["dynamicLesson"], descendants: true, static: true }], ngImport: i0, template: "<div>\n <div #dynamicLesson class=\"targetclass\">\n <ng-template #target></ng-template>\n </div>\n</div>\n\n<br />\n<div style=\"display: flex; gap: 10px\">\n @if ((mainForm.controls | keyvalue)?.length) {\n <div>\n <p-button label=\"Calificar Lecci\u00F3n\" icon=\"pi pi-check-circle\" (click)=\"evaluateForms()\" [rounded]=\"true\"></p-button>\n </div>\n }\n\n <p-button icon=\"pi pi-verified\" [rounded]=\"true\" (click)=\"startAI()\" label=\"Repasar con IA\" />\n</div>\n<br /><br />\n\n@if(chatVisible()) {\n<p-drawer header=\"Conversation\" [visible]=\"chatVisible()\" (visibleChange)=\"onVisibleChange($event)\" position=\"bottom\" styleClass=\"app-bottom-overlay\">\n <dc-chat\n [backgroundTasks]=\"backgroundTasks\"\n [conversationSettings]=\"conversationSettings()\"\n (goalCompleted)=\"handleGoalCompleted($event)\"\n (sendMessage)=\"onChatMessage($event)\"></dc-chat>\n</p-drawer>\n}\n", styles: [".evaluate{float:right}\n"], dependencies: [{ kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: DCChatComponent, selector: "dc-chat", inputs: ["chatUserSettings", "conversationSettings", "agentCard", "backgroundTasks", "taskOnUserMessage", "taskOnAssistantMessage", "parseDict"], outputs: ["sendMessage", "goalCompleted"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i2$2.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }] }); }
1410
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1411
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DCLessonRendererComponent, isStandalone: true, selector: "dc-lesson-renderer", inputs: { lessonInput: { classPropertyName: "lessonInput", publicName: "lessonInput", isSignal: true, isRequired: false, transformFunction: null }, lessonIdInput: { classPropertyName: "lessonIdInput", publicName: "lessonIdInput", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { wordClicked: "wordClicked" }, viewQueries: [{ propertyName: "dynamicLesson", first: true, predicate: ["dynamicLesson"], descendants: true, static: true }], ngImport: i0, template: "<div>\n <div #dynamicLesson class=\"targetclass\">\n <ng-template #target></ng-template>\n </div>\n</div>\n\n<br />\n<div style=\"display: flex; gap: 10px\">\n @if ((mainForm.controls | keyvalue)?.length) {\n <div>\n <p-button label=\"Calificar Lecci\u00F3n\" icon=\"pi pi-check-circle\" (click)=\"evaluateForms()\" [rounded]=\"true\"></p-button>\n </div>\n }\n\n <p-button icon=\"pi pi-verified\" [rounded]=\"true\" (click)=\"startAI()\" label=\"Repasar con IA\" />\n</div>\n<br /><br />\n\n@if(uiStateService.chatDrawerVisible()) {\n<p-drawer\n header=\"Conversation\"\n [visible]=\"uiStateService.chatDrawerVisible()\"\n (visibleChange)=\"onVisibleChange($event)\"\n position=\"bottom\"\n styleClass=\"app-bottom-overlay\">\n <dc-chat\n [conversationFlow]=\"conversationFlow()\"\n [conversationSettings]=\"conversationSettings()\"\n (goalCompleted)=\"handleGoalCompleted($event)\"\n (chatEvent)=\"onChatMessage($event)\"></dc-chat>\n</p-drawer>\n}\n", styles: ["::ng-deep .targetclass *:not(h1,h2,h3,h4,h5,h6){font-family:\"math\",sans-serif,system-ui,monospace!important}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: DCChatComponent, selector: "dc-chat", inputs: ["chatUserSettings", "conversationSettings", "conversationFlow", "agentCard", "parseDict"], outputs: ["chatEvent", "goalCompleted"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i2$2.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }] }); }
1323
1412
  }
1324
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonRendererComponent, decorators: [{
1413
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonRendererComponent, decorators: [{
1325
1414
  type: Component,
1326
- args: [{ selector: 'dc-lesson-renderer', standalone: true, imports: [KeyValuePipe, ButtonModule, DCChatComponent, DrawerModule], template: "<div>\n <div #dynamicLesson class=\"targetclass\">\n <ng-template #target></ng-template>\n </div>\n</div>\n\n<br />\n<div style=\"display: flex; gap: 10px\">\n @if ((mainForm.controls | keyvalue)?.length) {\n <div>\n <p-button label=\"Calificar Lecci\u00F3n\" icon=\"pi pi-check-circle\" (click)=\"evaluateForms()\" [rounded]=\"true\"></p-button>\n </div>\n }\n\n <p-button icon=\"pi pi-verified\" [rounded]=\"true\" (click)=\"startAI()\" label=\"Repasar con IA\" />\n</div>\n<br /><br />\n\n@if(chatVisible()) {\n<p-drawer header=\"Conversation\" [visible]=\"chatVisible()\" (visibleChange)=\"onVisibleChange($event)\" position=\"bottom\" styleClass=\"app-bottom-overlay\">\n <dc-chat\n [backgroundTasks]=\"backgroundTasks\"\n [conversationSettings]=\"conversationSettings()\"\n (goalCompleted)=\"handleGoalCompleted($event)\"\n (sendMessage)=\"onChatMessage($event)\"></dc-chat>\n</p-drawer>\n}\n", styles: [".evaluate{float:right}\n"] }]
1415
+ args: [{ selector: 'dc-lesson-renderer', standalone: true, imports: [KeyValuePipe, ButtonModule, DCChatComponent, DrawerModule], template: "<div>\n <div #dynamicLesson class=\"targetclass\">\n <ng-template #target></ng-template>\n </div>\n</div>\n\n<br />\n<div style=\"display: flex; gap: 10px\">\n @if ((mainForm.controls | keyvalue)?.length) {\n <div>\n <p-button label=\"Calificar Lecci\u00F3n\" icon=\"pi pi-check-circle\" (click)=\"evaluateForms()\" [rounded]=\"true\"></p-button>\n </div>\n }\n\n <p-button icon=\"pi pi-verified\" [rounded]=\"true\" (click)=\"startAI()\" label=\"Repasar con IA\" />\n</div>\n<br /><br />\n\n@if(uiStateService.chatDrawerVisible()) {\n<p-drawer\n header=\"Conversation\"\n [visible]=\"uiStateService.chatDrawerVisible()\"\n (visibleChange)=\"onVisibleChange($event)\"\n position=\"bottom\"\n styleClass=\"app-bottom-overlay\">\n <dc-chat\n [conversationFlow]=\"conversationFlow()\"\n [conversationSettings]=\"conversationSettings()\"\n (goalCompleted)=\"handleGoalCompleted($event)\"\n (chatEvent)=\"onChatMessage($event)\"></dc-chat>\n</p-drawer>\n}\n", styles: ["::ng-deep .targetclass *:not(h1,h2,h3,h4,h5,h6){font-family:\"math\",sans-serif,system-ui,monospace!important}\n"] }]
1327
1416
  }], ctorParameters: () => [], propDecorators: { wordClicked: [{
1328
1417
  type: Output
1329
1418
  }], dynamicLesson: [{
@@ -1334,13 +1423,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
1334
1423
  class LessonNotionService {
1335
1424
  constructor() {
1336
1425
  this.#notionService = inject(NOTION_SERVICE_TOKEN);
1337
- this.#lessonService = inject(LESSONS_TOKEN);
1426
+ this.lessonsService = inject(LESSONS_TOKEN, { optional: true }) ?? inject(DefaultLessonsService);
1338
1427
  this.#toastService = inject(TOAST_ALERTS_TOKEN);
1339
1428
  // Keep track of loading state specific to Notion operations
1340
- this.isLoading = signal(false);
1429
+ this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
1341
1430
  }
1342
1431
  #notionService;
1343
- #lessonService;
1344
1432
  #toastService;
1345
1433
  /**
1346
1434
  * Extracts the Notion Page ID from a URL.
@@ -1374,14 +1462,17 @@ class LessonNotionService {
1374
1462
  }
1375
1463
  const updatedLesson = {
1376
1464
  ...lesson,
1377
- extras: {
1378
- ...(lesson.extras || {}),
1379
- notionPageId: notionPageId,
1465
+ extensions: {
1466
+ ...(lesson.extensions || {}),
1467
+ extras: {
1468
+ ...(lesson.extensions?.['extras'] || {}),
1469
+ notionPageId: notionPageId,
1470
+ },
1380
1471
  },
1381
1472
  };
1382
1473
  this.isLoading.set(true);
1383
1474
  try {
1384
- const savedLesson = await this.#lessonService.postLesson(updatedLesson);
1475
+ const savedLesson = await this.lessonsService.postLesson(updatedLesson);
1385
1476
  this.#toastService.success({ title: 'Listo', subtitle: 'Se enlazó la lección con Notion.' });
1386
1477
  return savedLesson;
1387
1478
  }
@@ -1407,10 +1498,10 @@ class LessonNotionService {
1407
1498
  if (!currentLesson)
1408
1499
  return null;
1409
1500
  let notionPageId = null;
1410
- if (currentLesson.extras?.notionPageId) {
1411
- const useExisting = confirm(`Ya tenemos el id ${currentLesson.extras.notionPageId} ¿Quieres usar este id para importar?`);
1501
+ if (currentLesson.extensions?.['extras']?.['notionPageId']) {
1502
+ const useExisting = confirm(`Ya tenemos el id ${currentLesson.extensions?.['extras']?.['notionPageId']} ¿Quieres usar este id para importar?`);
1412
1503
  if (useExisting) {
1413
- notionPageId = currentLesson.extras.notionPageId;
1504
+ notionPageId = currentLesson.extensions?.['extras']?.['notionPageId'];
1414
1505
  }
1415
1506
  else {
1416
1507
  const inputUrl = prompt('Ingresa la NUEVA URL de Notion para importar (este ID NO se guardará automáticamente si la lección ya existe)');
@@ -1465,7 +1556,7 @@ class LessonNotionService {
1465
1556
  async improveLessonWithNotionAI(lesson) {
1466
1557
  if (!lesson)
1467
1558
  return;
1468
- const notionId = lesson.extras?.notionPageId;
1559
+ const notionId = lesson.extensions?.['extras']?.['notionPageId'];
1469
1560
  if (!notionId) {
1470
1561
  this.#toastService.warn({ title: 'Sin ID de Notion', subtitle: 'Enlaza la lección con Notion primero.' });
1471
1562
  return;
@@ -1489,22 +1580,21 @@ class LessonNotionService {
1489
1580
  this.isLoading.set(false);
1490
1581
  }
1491
1582
  }
1492
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonNotionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1493
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonNotionService }); }
1583
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonNotionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1584
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonNotionService }); }
1494
1585
  }
1495
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonNotionService, decorators: [{
1586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonNotionService, decorators: [{
1496
1587
  type: Injectable
1497
1588
  }] });
1498
1589
 
1499
1590
  // import { UserDataExchangeService } from '@dataclouder/ngx-agent-cards';
1500
1591
  class LessonUtilsService {
1501
1592
  constructor() {
1502
- this.#lessonService = inject(LESSONS_TOKEN);
1593
+ this.lessonsService = inject(LESSONS_TOKEN, { optional: true }) ?? inject(DefaultLessonsService);
1503
1594
  this.#toastService = inject(TOAST_ALERTS_TOKEN);
1504
1595
  this.#agentService = inject(CONVERSATION_AI_TOKEN);
1505
1596
  this.loadingBarService = inject(LoadingBarService);
1506
1597
  }
1507
- #lessonService;
1508
1598
  #toastService;
1509
1599
  #agentService;
1510
1600
  /**
@@ -1529,10 +1619,11 @@ class LessonUtilsService {
1529
1619
  lessonSignal.update((currentLesson) => {
1530
1620
  if (!currentLesson)
1531
1621
  return undefined;
1532
- const updatedMetadata = { ...(currentLesson.metadata ?? {}), banner: imageUploaded };
1622
+ const assets = { ...(currentLesson.assets ?? {}) };
1623
+ assets.banner = imageUploaded;
1533
1624
  return {
1534
1625
  ...currentLesson,
1535
- metadata: updatedMetadata,
1626
+ assets,
1536
1627
  };
1537
1628
  });
1538
1629
  }
@@ -1550,9 +1641,9 @@ class LessonUtilsService {
1550
1641
  }
1551
1642
  // No need to save here, component should ensure it's saved before calling.
1552
1643
  try {
1553
- await this.#lessonService.postGenerateByAI(lessonId);
1644
+ await this.lessonsService.postGenerateByAI(lessonId);
1554
1645
  // Re-fetch the lesson data to get AI updates
1555
- const updatedLesson = await this.#lessonService.getLesson(lessonId);
1646
+ const updatedLesson = await this.lessonsService.getLesson(lessonId);
1556
1647
  if (updatedLesson) {
1557
1648
  this.#toastService.success({ title: 'IA completada', subtitle: 'Lección actualizada con IA.' });
1558
1649
  return updatedLesson;
@@ -1583,7 +1674,7 @@ class LessonUtilsService {
1583
1674
  }
1584
1675
  try {
1585
1676
  this.loadingBarService.showIndeterminate();
1586
- const textPrompt = this.#lessonService.getPrompts().content(lesson);
1677
+ const textPrompt = this.lessonsService.getPrompts().content(lesson);
1587
1678
  const messages = [{ content: textPrompt, role: ChatRole.User }];
1588
1679
  const response = await this.#agentService.callChatCompletion({ messages, model: { provider: 'google' } });
1589
1680
  let improvedMarkdown = response.content?.trim() ?? null;
@@ -1635,7 +1726,7 @@ class LessonUtilsService {
1635
1726
  this.#toastService.warn({ title: 'Texto Vacío', subtitle: 'No se pudo extraer texto útil del contenido de la lección.' });
1636
1727
  return null;
1637
1728
  }
1638
- const descriptionPrompt = this.#lessonService.getPrompts().description(lesson);
1729
+ const descriptionPrompt = this.lessonsService.getPrompts().description(lesson);
1639
1730
  const messages = [{ content: descriptionPrompt, role: ChatRole.User }];
1640
1731
  const response = await this.#agentService.callChatCompletion({ messages, model: { provider: 'google' } });
1641
1732
  let generatedDescription = response.content?.trim() ?? null;
@@ -1742,10 +1833,10 @@ class LessonUtilsService {
1742
1833
  dynamicComponents: cleanedDynamicComponents,
1743
1834
  };
1744
1835
  }
1745
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonUtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1746
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonUtilsService, providedIn: 'root' }); }
1836
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonUtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1837
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonUtilsService, providedIn: 'root' }); }
1747
1838
  }
1748
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonUtilsService, decorators: [{
1839
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonUtilsService, decorators: [{
1749
1840
  type: Injectable,
1750
1841
  args: [{
1751
1842
  providedIn: 'root', // Provide globally or in a specific module if preferred
@@ -1775,10 +1866,10 @@ class DynamicComponentsBuilderService {
1775
1866
  });
1776
1867
  return dialogRef;
1777
1868
  }
1778
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DynamicComponentsBuilderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1779
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DynamicComponentsBuilderService, providedIn: 'root' }); }
1869
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DynamicComponentsBuilderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1870
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DynamicComponentsBuilderService, providedIn: 'root' }); }
1780
1871
  }
1781
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DynamicComponentsBuilderService, decorators: [{
1872
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DynamicComponentsBuilderService, decorators: [{
1782
1873
  type: Injectable,
1783
1874
  args: [{
1784
1875
  providedIn: 'root',
@@ -1812,10 +1903,10 @@ class DCLessonComponentAdderComponent {
1812
1903
  console.warn(`Dialog could not be opened for type via component: ${type}`);
1813
1904
  }
1814
1905
  }
1815
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonComponentAdderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1816
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: DCLessonComponentAdderComponent, isStandalone: true, selector: "dc-lesson-component-adder", outputs: { componentAdded: "componentAdded" }, providers: [DialogService], ngImport: i0, template: "<span>Componentes: </span>\n<div style=\"display: flex; gap: 10px; flex-wrap: wrap\">\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.Selector)\"\n pTooltip=\"Agrega un selector con multiples opciones\"\n tooltipPosition=\"bottom\">\n Selector\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.Speaker)\"\n pTooltip=\"Para que una palabra o frase sea reproducible\"\n tooltipPosition=\"bottom\">\n Speaker\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.TextWriter)\"\n pTooltip=\"Escribe una respuesta en un cuadro de texto\"\n tooltipPosition=\"bottom\">\n Text\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.VerbSummary)\"\n pTooltip=\"Muestra la informaci\u00F3n de un verbo\"\n tooltipPosition=\"bottom\">\n Verb\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.WordSummary)\"\n pTooltip=\"Muestra la informaci\u00F3n de una palabra\"\n tooltipPosition=\"bottom\">\n Palabra\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.TranslationSwitcher)\"\n pTooltip=\"Muestra el texto pero al pica cambia de idioma\"\n tooltipPosition=\"bottom\">\n Traducci\u00F3n\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.PlayWord)\"\n pTooltip=\"Muestra el texto pero al pica cambia de idioma\"\n tooltipPosition=\"bottom\">\n Play Word\n </p-button>\n <!-- Add other buttons here if needed, following the same pattern -->\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }] }); }
1906
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonComponentAdderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1907
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: DCLessonComponentAdderComponent, isStandalone: true, selector: "dc-lesson-component-adder", outputs: { componentAdded: "componentAdded" }, providers: [DialogService], ngImport: i0, template: "<span>Componentes: </span>\n<div style=\"display: flex; gap: 10px; flex-wrap: wrap\">\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.Selector)\"\n pTooltip=\"Agrega un selector con multiples opciones\"\n tooltipPosition=\"bottom\">\n Selector\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.Speaker)\"\n pTooltip=\"Para que una palabra o frase sea reproducible\"\n tooltipPosition=\"bottom\">\n Speaker\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.TextWriter)\"\n pTooltip=\"Escribe una respuesta en un cuadro de texto\"\n tooltipPosition=\"bottom\">\n Text\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.VerbSummary)\"\n pTooltip=\"Muestra la informaci\u00F3n de un verbo\"\n tooltipPosition=\"bottom\">\n Verb\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.WordSummary)\"\n pTooltip=\"Muestra la informaci\u00F3n de una palabra\"\n tooltipPosition=\"bottom\">\n Palabra\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.TranslationSwitcher)\"\n pTooltip=\"Muestra el texto pero al pica cambia de idioma\"\n tooltipPosition=\"bottom\">\n Traducci\u00F3n\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.PlayWord)\"\n pTooltip=\"Muestra el texto pero al pica cambia de idioma\"\n tooltipPosition=\"bottom\">\n Play Word\n </p-button>\n <!-- Add other buttons here if needed, following the same pattern -->\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }] }); }
1817
1908
  }
1818
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonComponentAdderComponent, decorators: [{
1909
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonComponentAdderComponent, decorators: [{
1819
1910
  type: Component,
1820
1911
  args: [{ selector: 'dc-lesson-component-adder', standalone: true, imports: [CommonModule, ButtonModule, TooltipModule], providers: [DialogService], template: "<span>Componentes: </span>\n<div style=\"display: flex; gap: 10px; flex-wrap: wrap\">\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.Selector)\"\n pTooltip=\"Agrega un selector con multiples opciones\"\n tooltipPosition=\"bottom\">\n Selector\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.Speaker)\"\n pTooltip=\"Para que una palabra o frase sea reproducible\"\n tooltipPosition=\"bottom\">\n Speaker\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.TextWriter)\"\n pTooltip=\"Escribe una respuesta en un cuadro de texto\"\n tooltipPosition=\"bottom\">\n Text\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.VerbSummary)\"\n pTooltip=\"Muestra la informaci\u00F3n de un verbo\"\n tooltipPosition=\"bottom\">\n Verb\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.WordSummary)\"\n pTooltip=\"Muestra la informaci\u00F3n de una palabra\"\n tooltipPosition=\"bottom\">\n Palabra\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.TranslationSwitcher)\"\n pTooltip=\"Muestra el texto pero al pica cambia de idioma\"\n tooltipPosition=\"bottom\">\n Traducci\u00F3n\n </p-button>\n <p-button\n severity=\"info\"\n (click)=\"openComponentBuilder(lessonComponentEnum.PlayWord)\"\n pTooltip=\"Muestra el texto pero al pica cambia de idioma\"\n tooltipPosition=\"bottom\">\n Play Word\n </p-button>\n <!-- Add other buttons here if needed, following the same pattern -->\n</div>\n" }]
1821
1912
  }], propDecorators: { componentAdded: [{
@@ -1825,8 +1916,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
1825
1916
  class DCLessonMetadataEditorComponent {
1826
1917
  constructor() {
1827
1918
  // Use signal for input lesson data
1828
- this.lesson = signal(undefined); // The lesson data itself
1829
- this.isLoadingLesson = signal(false); // Shared loading state
1919
+ this.lesson = signal(undefined, ...(ngDevMode ? [{ debugName: "lesson" }] : [])); // The lesson data itself
1920
+ this.isLoadingLesson = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingLesson" }] : [])); // Shared loading state
1830
1921
  // Outputs for actions
1831
1922
  this.saveRequest = new EventEmitter();
1832
1923
  this.importNotionRequest = new EventEmitter();
@@ -1837,7 +1928,7 @@ class DCLessonMetadataEditorComponent {
1837
1928
  // Injected Services
1838
1929
  this.#lessonUtilsService = inject(LessonUtilsService);
1839
1930
  this.#toastService = inject(TOAST_ALERTS_TOKEN);
1840
- this.#lessonService = inject(LESSONS_TOKEN);
1931
+ this.lessonsService = inject(LESSONS_TOKEN, { optional: true }) ?? inject(DefaultLessonsService);
1841
1932
  this.#turndownService = new TurndownService(); // Instantiate TurndownService
1842
1933
  }
1843
1934
  // Removed generateAIRequest Output as it's handled internally now
@@ -1846,7 +1937,6 @@ class DCLessonMetadataEditorComponent {
1846
1937
  // Injected Services
1847
1938
  #lessonUtilsService;
1848
1939
  #toastService;
1849
- #lessonService;
1850
1940
  #turndownService; // Instantiate TurndownService
1851
1941
  // Method to handle property changes for ROOT properties (e.g., level)
1852
1942
  onRootPropertyChange(property, value) {
@@ -1854,24 +1944,15 @@ class DCLessonMetadataEditorComponent {
1854
1944
  if (!current)
1855
1945
  return undefined;
1856
1946
  // Avoid updating metadata directly here
1857
- if (property === 'metadata') {
1858
- console.warn('Direct metadata updates should use onMetadataPropertyChange');
1859
- return current;
1860
- }
1947
+ // if (property === 'metadata') {
1948
+ // console.warn('Direct metadata updates should use onMetadataPropertyChange');
1949
+ // return current;
1950
+ // }
1861
1951
  return { ...current, [property]: value };
1862
1952
  });
1863
1953
  // Emit removed - signal is updated directly above.
1864
1954
  // this.propertyChange.emit({ propertyPath: property, value });
1865
1955
  }
1866
- // Method to handle property changes for METADATA properties
1867
- onMetadataPropertyChange(property, value) {
1868
- this.lesson.update((current) => {
1869
- if (!current)
1870
- return undefined;
1871
- const updatedMetadata = { ...(current.metadata ?? {}), [property]: value };
1872
- return { ...current, metadata: updatedMetadata };
1873
- });
1874
- }
1875
1956
  // Method to handle property changes for APP EXTENSION properties
1876
1957
  onAppExtensionPropChange(property, value) {
1877
1958
  this.lesson.update((current) => {
@@ -1880,8 +1961,24 @@ class DCLessonMetadataEditorComponent {
1880
1961
  // Ensure appExtension exists, initialize if not
1881
1962
  // Convert value to number specifically for 'level'
1882
1963
  const finalValue = property === 'level' ? Number(value) : value;
1883
- const updatedAppExtension = { ...(current.appExtension ?? {}), [property]: finalValue };
1884
- return { ...current, appExtension: updatedAppExtension };
1964
+ const updatedAppExtension = { ...(current.extensions ?? {}), [property]: finalValue };
1965
+ return { ...current, extensions: updatedAppExtension };
1966
+ });
1967
+ }
1968
+ onManageablePropertyChange(property, value) {
1969
+ this.lesson.update((current) => {
1970
+ if (!current)
1971
+ return undefined;
1972
+ const updatedManageable = { ...(current.manageable ?? {}), [property]: value };
1973
+ return { ...current, manageable: updatedManageable };
1974
+ });
1975
+ }
1976
+ onAuditablePropertyChange(property, value) {
1977
+ this.lesson.update((current) => {
1978
+ if (!current)
1979
+ return undefined;
1980
+ const updatedAuditable = { ...(current.auditable ?? {}), [property]: value };
1981
+ return { ...current, auditable: updatedAuditable };
1885
1982
  });
1886
1983
  }
1887
1984
  // Methods to emit action requests
@@ -1917,7 +2014,7 @@ class DCLessonMetadataEditorComponent {
1917
2014
  else {
1918
2015
  // Clean orphaned and Save before Improve
1919
2016
  const lessonToSave = this.#lessonUtilsService.cleanOrphanedComponents(currentLesson);
1920
- const savedLesson = await this.#lessonService.postLesson(lessonToSave);
2017
+ const savedLesson = await this.lessonsService.postLesson(lessonToSave);
1921
2018
  if (!savedLesson) {
1922
2019
  this.#toastService.error({ title: 'Error al guardar', subtitle: 'No se pudo guardar antes de generar con IA.' });
1923
2020
  throw new Error('Failed to save before AI generation');
@@ -1980,7 +2077,7 @@ class DCLessonMetadataEditorComponent {
1980
2077
  // Ensure lesson() is not undefined before saving
1981
2078
  const lessonToSave = this.lesson();
1982
2079
  if (lessonToSave) {
1983
- await this.#lessonService.postLesson(lessonToSave);
2080
+ await this.lessonsService.postLesson(lessonToSave);
1984
2081
  this.#toastService.success({ title: 'Contenido generado', subtitle: 'Se generó y guardó el contenido con IA.' });
1985
2082
  }
1986
2083
  else {
@@ -2010,32 +2107,35 @@ class DCLessonMetadataEditorComponent {
2010
2107
  }
2011
2108
  const generatedDescription = await this.#lessonUtilsService.generateDescriptionWithAI(currentLesson);
2012
2109
  if (generatedDescription) {
2013
- // Use the new method for metadata properties
2014
- this.onMetadataPropertyChange('description', generatedDescription);
2110
+ this.lessonForm.controls['description'].setValue(generatedDescription);
2015
2111
  }
2016
2112
  }
2017
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonMetadataEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2018
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: DCLessonMetadataEditorComponent, isStandalone: true, selector: "dc-lesson-metadata-editor", inputs: { lesson: "lesson", isLoadingLesson: "isLoadingLesson" }, outputs: { saveRequest: "saveRequest", importNotionRequest: "importNotionRequest", improveNotionRequest: "improveNotionRequest" }, ngImport: i0, template: "@if (lesson(); as currentLesson) {\n<div>\n <div>\n <div style=\"display: flex; gap: 10px; padding: 10px\">\n <p-button label=\"Guardar\" severity=\"primary\" (click)=\"emitSaveRequest()\" />\n <p-button label=\"Importar de Notion\" severity=\"help\" (click)=\"emitImportNotionRequest()\" />\n <p-button label=\"Mejorar Notion con AI\" severity=\"help\" (click)=\"emitImproveNotionRequest()\" />\n </div>\n\n <!-- Use one-way binding and ngModelChange for signals -->\n <div>\n <input\n pInputText\n style=\"width: 100%\"\n [ngModel]=\"currentLesson.metadata?.title\"\n (ngModelChange)=\"onMetadataPropertyChange('title', $event)\"\n type=\"text\"\n placeholder=\"Agrega un t\u00EDtulo\" />\n </div>\n <div style=\"margin-top: 4px\">\n <p-inputgroup>\n <input\n pInputText\n style=\"width: 100%\"\n [ngModel]=\"currentLesson.metadata?.description\"\n (ngModelChange)=\"onMetadataPropertyChange('description', $event)\"\n type=\"text\"\n placeholder=\"Agrega una descripci\u00F3n\" />\n <p-button\n icon=\"pi pi-sparkles\"\n styleClass=\"p-button-secondary p-button-outlined\"\n pTooltip=\"Generar descripci\u00F3n con IA\"\n tooltipPosition=\"top\"\n [disabled]=\"isLoadingLesson()\"\n (click)=\"triggerGenerateDescriptionAI()\" />\n </p-inputgroup>\n </div>\n\n <div style=\"display: flex; align-items: center; margin-top: 10px\">\n <input\n pInputText\n style=\"flex: auto; margin-right: 5px\"\n [ngModel]=\"currentLesson.metadata?.prompt\"\n (ngModelChange)=\"onMetadataPropertyChange('prompt', $event)\"\n type=\"text\"\n placeholder=\"Prompt para IA (opcional)\" />\n <p-button severity=\"primary\" label=\"Generar con IA\" icon=\"pi pi-sparkles\" [disabled]=\"isLoadingLesson()\" (click)=\"generateByAI()\" />\n </div>\n\n <div style=\"margin-top: 10px\">\n <label class=\"checkbox-container\" style=\"margin-right: 15px\">\n <input\n type=\"checkbox\"\n [ngModel]=\"currentLesson.metadata?.isPublished\"\n (ngModelChange)=\"onMetadataPropertyChange('isPublished', $event)\"\n title=\"Cuando termines la edici\u00F3n marca esta casilla\" />\n <span class=\"checkmark\"></span>\n Publicada\n </label>\n </div>\n\n <p-divider />\n\n <div style=\"display: flex; align-items: center; margin-top: 10px; gap: 10px\">\n <input\n pInputText\n [ngModel]=\"currentLesson.appExtension?.['level']\"\n (ngModelChange)=\"onAppExtensionPropChange('level', $event)\"\n type=\"number\"\n placeholder=\"Nivel\"\n style=\"width: 80px\" />\n\n <!-- Access signal values -->\n @if (currentLesson.appExtension) {\n <div>\n {{ currentLesson.appExtension?.['baseLang'] | flagEmoji }} -> {{ currentLesson.appExtension?.['targetLang'] | flagEmoji }} Lecci\u00F3n para hablantes de\n {{ currentLesson.appExtension?.['baseLang'] | langDesc : 'es' }} que aprenden\n {{ currentLesson.appExtension?.['targetLang'] | langDesc : 'es' }}\n </div>\n }\n </div>\n </div>\n</div>\n} @else {\n<!-- Optional: Show a loading state or placeholder if lesson is undefined -->\n<p>Cargando datos de la lecci\u00F3n...</p>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "pipe", type: // Added TooltipModule
2113
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonMetadataEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2114
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DCLessonMetadataEditorComponent, isStandalone: true, selector: "dc-lesson-metadata-editor", inputs: { lesson: "lesson", lessonForm: "lessonForm", isLoadingLesson: "isLoadingLesson" }, outputs: { saveRequest: "saveRequest", importNotionRequest: "importNotionRequest", improveNotionRequest: "improveNotionRequest" }, ngImport: i0, template: "@if (lesson(); as currentLesson) {\n<div [formGroup]=\"lessonForm\">\n <div>\n <div style=\"display: flex; gap: 10px; padding: 10px\">\n <p-button label=\"Guardar\" severity=\"primary\" (click)=\"emitSaveRequest()\" />\n <p-button label=\"Importar de Notion\" severity=\"help\" (click)=\"emitImportNotionRequest()\" />\n <p-button label=\"Mejorar Notion con AI\" severity=\"help\" (click)=\"emitImproveNotionRequest()\" />\n </div>\n\n <!-- Use one-way binding and ngModelChange for signals -->\n <div>\n <input pInputText style=\"width: 100%\" formControlName=\"title\" type=\"text\" placeholder=\"Agrega un t\u00EDtulo\" />\n </div>\n <div style=\"margin-top: 4px\">\n <p-inputgroup>\n <input pInputText style=\"width: 100%\" formControlName=\"description\" type=\"text\" placeholder=\"Agrega una descripci\u00F3n\" />\n <p-button\n icon=\"pi pi-sparkles\"\n styleClass=\"p-button-secondary p-button-outlined\"\n pTooltip=\"Generar descripci\u00F3n con IA\"\n tooltipPosition=\"top\"\n [disabled]=\"isLoadingLesson()\"\n (click)=\"triggerGenerateDescriptionAI()\" />\n </p-inputgroup>\n </div>\n\n <div style=\"display: flex; align-items: center; margin-top: 10px\">\n <input\n pInputText\n style=\"flex: auto; margin-right: 5px\"\n [ngModel]=\"currentLesson.auditable?.prompt\"\n (ngModelChange)=\"onAuditablePropertyChange('prompt', $event)\"\n type=\"text\"\n placeholder=\"Prompt para IA (opcional)\" />\n <p-button severity=\"primary\" label=\"Generar con IA\" icon=\"pi pi-sparkles\" [disabled]=\"isLoadingLesson()\" (click)=\"generateByAI()\" />\n </div>\n\n <div style=\"margin-top: 10px\">\n <label class=\"checkbox-container\" style=\"margin-right: 15px\">\n <input\n type=\"checkbox\"\n [ngModel]=\"currentLesson.manageable?.status === 'published'\"\n (ngModelChange)=\"onManageablePropertyChange('status', $event)\"\n title=\"Cuando termines la edici\u00F3n marca esta casilla\" />\n <span class=\"checkmark\"></span>\n Publicada\n </label>\n </div>\n\n <p-divider />\n\n <div style=\"display: flex; align-items: center; margin-top: 10px; gap: 10px\">\n <input\n pInputText\n [ngModel]=\"currentLesson.extensions?.['level']\"\n (ngModelChange)=\"onAppExtensionPropChange('level', $event)\"\n type=\"number\"\n placeholder=\"Nivel\"\n style=\"width: 80px\" />\n\n <!-- Access signal values -->\n @if (currentLesson.extensions) {\n <div>\n {{ currentLesson.extensions?.['baseLang'] | flagEmoji }} -> {{ currentLesson.extensions?.['targetLang'] | flagEmoji }} Lecci\u00F3n para hablantes de\n {{ currentLesson.extensions?.['baseLang'] | langDesc : 'es' }} que aprenden\n {{ currentLesson.extensions?.['targetLang'] | langDesc : 'es' }}\n </div>\n }\n </div>\n </div>\n</div>\n} @else {\n<!-- Optional: Show a loading state or placeholder if lesson is undefined -->\n<p>Cargando datos de la lecci\u00F3n...</p>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: // Added Pipe
2115
+ InputGroupModule }, { kind: "component", type: i5.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i6.Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "pipe", type: // Added TooltipModule
2019
2116
  FlagLanguagePipe, name: "flagEmoji" }, { kind: "pipe", type: // Added Pipe
2020
- LangDescTranslationPipe, name: "langDesc" }, { kind: "ngmodule", type: // Added Pipe
2021
- InputGroupModule }, { kind: "component", type: i5.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["style", "styleClass"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i6$1.Divider, selector: "p-divider", inputs: ["style", "styleClass", "layout", "type", "align"] }] }); }
2117
+ LangDescTranslationPipe, name: "langDesc" }] }); }
2022
2118
  }
2023
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonMetadataEditorComponent, decorators: [{
2119
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonMetadataEditorComponent, decorators: [{
2024
2120
  type: Component,
2025
2121
  args: [{ selector: 'dc-lesson-metadata-editor', standalone: true, imports: [
2026
2122
  CommonModule,
2027
2123
  FormsModule,
2028
2124
  ButtonModule,
2029
2125
  InputTextModule,
2126
+ ReactiveFormsModule,
2030
2127
  TooltipModule, // Added TooltipModule
2031
2128
  FlagLanguagePipe, // Added Pipe
2032
2129
  LangDescTranslationPipe, // Added Pipe
2033
2130
  InputGroupModule,
2034
2131
  DividerModule,
2035
- ], template: "@if (lesson(); as currentLesson) {\n<div>\n <div>\n <div style=\"display: flex; gap: 10px; padding: 10px\">\n <p-button label=\"Guardar\" severity=\"primary\" (click)=\"emitSaveRequest()\" />\n <p-button label=\"Importar de Notion\" severity=\"help\" (click)=\"emitImportNotionRequest()\" />\n <p-button label=\"Mejorar Notion con AI\" severity=\"help\" (click)=\"emitImproveNotionRequest()\" />\n </div>\n\n <!-- Use one-way binding and ngModelChange for signals -->\n <div>\n <input\n pInputText\n style=\"width: 100%\"\n [ngModel]=\"currentLesson.metadata?.title\"\n (ngModelChange)=\"onMetadataPropertyChange('title', $event)\"\n type=\"text\"\n placeholder=\"Agrega un t\u00EDtulo\" />\n </div>\n <div style=\"margin-top: 4px\">\n <p-inputgroup>\n <input\n pInputText\n style=\"width: 100%\"\n [ngModel]=\"currentLesson.metadata?.description\"\n (ngModelChange)=\"onMetadataPropertyChange('description', $event)\"\n type=\"text\"\n placeholder=\"Agrega una descripci\u00F3n\" />\n <p-button\n icon=\"pi pi-sparkles\"\n styleClass=\"p-button-secondary p-button-outlined\"\n pTooltip=\"Generar descripci\u00F3n con IA\"\n tooltipPosition=\"top\"\n [disabled]=\"isLoadingLesson()\"\n (click)=\"triggerGenerateDescriptionAI()\" />\n </p-inputgroup>\n </div>\n\n <div style=\"display: flex; align-items: center; margin-top: 10px\">\n <input\n pInputText\n style=\"flex: auto; margin-right: 5px\"\n [ngModel]=\"currentLesson.metadata?.prompt\"\n (ngModelChange)=\"onMetadataPropertyChange('prompt', $event)\"\n type=\"text\"\n placeholder=\"Prompt para IA (opcional)\" />\n <p-button severity=\"primary\" label=\"Generar con IA\" icon=\"pi pi-sparkles\" [disabled]=\"isLoadingLesson()\" (click)=\"generateByAI()\" />\n </div>\n\n <div style=\"margin-top: 10px\">\n <label class=\"checkbox-container\" style=\"margin-right: 15px\">\n <input\n type=\"checkbox\"\n [ngModel]=\"currentLesson.metadata?.isPublished\"\n (ngModelChange)=\"onMetadataPropertyChange('isPublished', $event)\"\n title=\"Cuando termines la edici\u00F3n marca esta casilla\" />\n <span class=\"checkmark\"></span>\n Publicada\n </label>\n </div>\n\n <p-divider />\n\n <div style=\"display: flex; align-items: center; margin-top: 10px; gap: 10px\">\n <input\n pInputText\n [ngModel]=\"currentLesson.appExtension?.['level']\"\n (ngModelChange)=\"onAppExtensionPropChange('level', $event)\"\n type=\"number\"\n placeholder=\"Nivel\"\n style=\"width: 80px\" />\n\n <!-- Access signal values -->\n @if (currentLesson.appExtension) {\n <div>\n {{ currentLesson.appExtension?.['baseLang'] | flagEmoji }} -> {{ currentLesson.appExtension?.['targetLang'] | flagEmoji }} Lecci\u00F3n para hablantes de\n {{ currentLesson.appExtension?.['baseLang'] | langDesc : 'es' }} que aprenden\n {{ currentLesson.appExtension?.['targetLang'] | langDesc : 'es' }}\n </div>\n }\n </div>\n </div>\n</div>\n} @else {\n<!-- Optional: Show a loading state or placeholder if lesson is undefined -->\n<p>Cargando datos de la lecci\u00F3n...</p>\n}\n" }]
2132
+ ], template: "@if (lesson(); as currentLesson) {\n<div [formGroup]=\"lessonForm\">\n <div>\n <div style=\"display: flex; gap: 10px; padding: 10px\">\n <p-button label=\"Guardar\" severity=\"primary\" (click)=\"emitSaveRequest()\" />\n <p-button label=\"Importar de Notion\" severity=\"help\" (click)=\"emitImportNotionRequest()\" />\n <p-button label=\"Mejorar Notion con AI\" severity=\"help\" (click)=\"emitImproveNotionRequest()\" />\n </div>\n\n <!-- Use one-way binding and ngModelChange for signals -->\n <div>\n <input pInputText style=\"width: 100%\" formControlName=\"title\" type=\"text\" placeholder=\"Agrega un t\u00EDtulo\" />\n </div>\n <div style=\"margin-top: 4px\">\n <p-inputgroup>\n <input pInputText style=\"width: 100%\" formControlName=\"description\" type=\"text\" placeholder=\"Agrega una descripci\u00F3n\" />\n <p-button\n icon=\"pi pi-sparkles\"\n styleClass=\"p-button-secondary p-button-outlined\"\n pTooltip=\"Generar descripci\u00F3n con IA\"\n tooltipPosition=\"top\"\n [disabled]=\"isLoadingLesson()\"\n (click)=\"triggerGenerateDescriptionAI()\" />\n </p-inputgroup>\n </div>\n\n <div style=\"display: flex; align-items: center; margin-top: 10px\">\n <input\n pInputText\n style=\"flex: auto; margin-right: 5px\"\n [ngModel]=\"currentLesson.auditable?.prompt\"\n (ngModelChange)=\"onAuditablePropertyChange('prompt', $event)\"\n type=\"text\"\n placeholder=\"Prompt para IA (opcional)\" />\n <p-button severity=\"primary\" label=\"Generar con IA\" icon=\"pi pi-sparkles\" [disabled]=\"isLoadingLesson()\" (click)=\"generateByAI()\" />\n </div>\n\n <div style=\"margin-top: 10px\">\n <label class=\"checkbox-container\" style=\"margin-right: 15px\">\n <input\n type=\"checkbox\"\n [ngModel]=\"currentLesson.manageable?.status === 'published'\"\n (ngModelChange)=\"onManageablePropertyChange('status', $event)\"\n title=\"Cuando termines la edici\u00F3n marca esta casilla\" />\n <span class=\"checkmark\"></span>\n Publicada\n </label>\n </div>\n\n <p-divider />\n\n <div style=\"display: flex; align-items: center; margin-top: 10px; gap: 10px\">\n <input\n pInputText\n [ngModel]=\"currentLesson.extensions?.['level']\"\n (ngModelChange)=\"onAppExtensionPropChange('level', $event)\"\n type=\"number\"\n placeholder=\"Nivel\"\n style=\"width: 80px\" />\n\n <!-- Access signal values -->\n @if (currentLesson.extensions) {\n <div>\n {{ currentLesson.extensions?.['baseLang'] | flagEmoji }} -> {{ currentLesson.extensions?.['targetLang'] | flagEmoji }} Lecci\u00F3n para hablantes de\n {{ currentLesson.extensions?.['baseLang'] | langDesc : 'es' }} que aprenden\n {{ currentLesson.extensions?.['targetLang'] | langDesc : 'es' }}\n </div>\n }\n </div>\n </div>\n</div>\n} @else {\n<!-- Optional: Show a loading state or placeholder if lesson is undefined -->\n<p>Cargando datos de la lecci\u00F3n...</p>\n}\n" }]
2036
2133
  }], propDecorators: { lesson: [{
2037
2134
  type: Input,
2038
2135
  args: [{ required: true }]
2136
+ }], lessonForm: [{
2137
+ type: Input,
2138
+ args: [{ required: true }]
2039
2139
  }], isLoadingLesson: [{
2040
2140
  type: Input,
2041
2141
  args: [{ required: true }]
@@ -2047,126 +2147,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2047
2147
  type: Output
2048
2148
  }] } });
2049
2149
 
2050
- // Define placeholder endpoints - these should be configured appropriately
2051
- const LESSONS_BASE_PATH = 'api/lesson'; // Example base path
2052
- class DefaultLessonsService {
2053
- constructor() {
2054
- this.httpCoreService = inject(HttpCoreService);
2055
- // --- Endpoint Definitions (Hardcoded as requested) ---
2056
- this.endpoints = {
2057
- queryLessons: `${LESSONS_BASE_PATH}/query`,
2058
- getLesson: (id) => `${LESSONS_BASE_PATH}/${id}`,
2059
- saveLesson: `api/user/saveLesson`,
2060
- updateLesson: (id) => `${LESSONS_BASE_PATH}/${id}`, // Assuming PUT to /lessons/:id
2061
- deleteLesson: (id) => `${LESSONS_BASE_PATH}/${id}`, // Assuming DELETE to /lessons/:id
2062
- generateLesson: `${LESSONS_BASE_PATH}/generate`, // Placeholder
2063
- generateByAI: `${LESSONS_BASE_PATH}/generate-ai`, // Placeholder
2064
- improveMDWithAI: `${LESSONS_BASE_PATH}/improve-markdown-ai`, // Placeholder
2065
- QueryLessons: 'api/lesson/query',
2066
- Lesson: 'api/lesson',
2067
- SaveLesson: 'api/lesson-polilan',
2068
- GetPublicLessons: 'api/lesson/publicLessons',
2069
- GetUnpublishedLessons: 'api/lesson/unpublished',
2070
- TakenLesson: 'api/lesson/taken',
2071
- DeleteLesson: 'api/lesson',
2072
- Base: 'api/lesson',
2073
- GenerateBanner: 'api/lesson/generate-banner',
2074
- };
2075
- }
2076
- saveTakenLesson(lesson) {
2077
- // Not sure how to implement this yet.
2078
- return this.httpCoreService.post(this.endpoints.saveLesson, lesson);
2079
- }
2080
- // --- Method Implementations ---
2081
- async getLessons(paginator) {
2082
- // Assuming paginator is the body for a POST request based on the example
2083
- return this.httpCoreService.post(this.endpoints.queryLessons, paginator || {});
2084
- }
2085
- async getLesson(id) {
2086
- return this.httpCoreService.get(this.endpoints.getLesson(id));
2087
- }
2088
- async postLesson(lesson) {
2089
- return this.httpCoreService.post(this.endpoints.saveLesson, lesson);
2090
- }
2091
- async updateLesson(lesson) {
2092
- if (!lesson._id) {
2093
- throw new Error('Lesson ID is required for update.');
2094
- }
2095
- // Assuming _id is the identifier
2096
- return this.httpCoreService.put(this.endpoints.updateLesson(lesson._id), lesson);
2097
- }
2098
- async deleteLesson(id) {
2099
- return this.httpCoreService.delete(this.endpoints.deleteLesson(id));
2100
- }
2101
- async generateLesson(lesson) {
2102
- // This endpoint might need specific data or structure
2103
- return this.httpCoreService.post(this.endpoints.generateLesson, lesson);
2104
- }
2105
- async postGenerateByAI(id) {
2106
- return this.httpCoreService.post(this.endpoints.generateByAI, { id });
2107
- }
2108
- async postImproveMDWithAI(lessonId, markdownText) {
2109
- return this.httpCoreService.post(this.endpoints.improveMDWithAI, { id: lessonId, markdown: markdownText });
2110
- }
2111
- extractTextFromHtml(html) {
2112
- // Copied from src/app/core/data-services/lessons.service.ts
2113
- const r1 = new RegExp('~(.+?)~', 'g');
2114
- const lessonHtml = html.replace(r1, (_matching, jsonCoded) => {
2115
- try {
2116
- const data = JSON.parse(jsonCoded);
2117
- return `<span>${data?.settings?.text || ''}</span>`; // Added default empty string
2118
- }
2119
- catch (e) {
2120
- console.error('Error parsing JSON in extractTextFromHtml:', jsonCoded, e);
2121
- return ''; // Return empty string on error
2122
- }
2123
- });
2124
- // Remove HTML tags
2125
- let text = lessonHtml.replace(/<[^>]*>/g, ' ');
2126
- // Remove style and script content
2127
- text = text.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, ' ');
2128
- text = text.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, ' ');
2129
- // Decode HTML entities
2130
- text = text.replace(/&nbsp;/g, ' ');
2131
- text = text.replace(/&/g, '&');
2132
- text = text.replace(/</g, '<');
2133
- text = text.replace(/>/g, '>');
2134
- // Remove extra whitespace
2135
- text = text.replace(/\s+/g, ' ').trim();
2136
- return text;
2137
- }
2138
- generateBanner(prompt, lessonId) {
2139
- return this.httpCoreService.post(this.endpoints.GenerateBanner, { prompt, lessonId });
2140
- }
2141
- getPrompts() {
2142
- return null;
2143
- }
2144
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DefaultLessonsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2145
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DefaultLessonsService, providedIn: 'root' }); }
2146
- }
2147
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DefaultLessonsService, decorators: [{
2148
- type: Injectable,
2149
- args: [{
2150
- providedIn: 'root',
2151
- }]
2152
- }] });
2153
-
2154
2150
  class DCLessonEditorComponent {
2155
2151
  // Services
2156
2152
  #activatedRoute; // Re-inject as it's needed for navigation
2157
2153
  #lessonNotionService;
2158
2154
  #lessonUtilsService;
2159
2155
  #router;
2160
- #lessonService;
2161
2156
  #toastService;
2162
2157
  #loadingBarService;
2158
+ #formBuilder;
2163
2159
  constructor() {
2164
2160
  // Services
2165
2161
  this.#activatedRoute = inject(ActivatedRoute); // Re-inject as it's needed for navigation
2166
2162
  this.#lessonNotionService = inject(LessonNotionService);
2167
2163
  this.#lessonUtilsService = inject(LessonUtilsService);
2168
2164
  this.#router = inject(Router);
2169
- this.#lessonService = inject(LESSONS_TOKEN);
2165
+ this.lessonsService = inject(LESSONS_TOKEN, { optional: true }) ?? inject(DefaultLessonsService);
2170
2166
  this.#toastService = inject(TOAST_ALERTS_TOKEN);
2171
2167
  this.#loadingBarService = inject(LoadingBarService);
2172
2168
  this.defaultLessonsService = inject(DefaultLessonsService);
@@ -2174,26 +2170,24 @@ class DCLessonEditorComponent {
2174
2170
  this.ngxVertexService = inject(NgxVertexService);
2175
2171
  this.cdr = inject(ChangeDetectorRef);
2176
2172
  this.dynamicComponentsBuilderService = inject(DynamicComponentsBuilderService);
2173
+ this.#formBuilder = inject(FormBuilder);
2177
2174
  // Signals States
2178
2175
  this.lessonId = toSignal(inject(ActivatedRoute).paramMap.pipe(map((params) => params.get('id'))));
2179
- this.lesson = signal(undefined); // Initialize as undefined
2180
- this.isLoadingLesson = signal(false);
2176
+ this.lesson = signal(undefined, ...(ngDevMode ? [{ debugName: "lesson" }] : []));
2177
+ this.isLoadingLesson = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingLesson" }] : []));
2181
2178
  // Computed Signals
2182
2179
  this.coverImageUrl = computed(() => {
2183
2180
  // Priority Order 1 Metadata Banner, 2 Banner, 3 Media First Images, 4 Default Banner TODO: reveme banner after migration to Content
2184
2181
  const currentLesson = this.lesson();
2185
- if (currentLesson?.metadata?.banner?.url) {
2186
- return currentLesson.metadata.banner.url;
2187
- }
2188
- else if (currentLesson?.banner?.url) {
2189
- return currentLesson.banner.url;
2182
+ if (currentLesson?.assets?.banner?.url) {
2183
+ return currentLesson.assets.banner.url;
2190
2184
  }
2191
2185
  else if (currentLesson?.media?.images?.find((img) => img.type === 'cover')) {
2192
2186
  // 3 Media First Images
2193
2187
  return currentLesson.media.images.find((img) => img.type === 'cover')?.url;
2194
2188
  }
2195
- return '/assets/images/default_banner.webp';
2196
- });
2189
+ return '/assets/defaults/images/default_banner.webp';
2190
+ }, ...(ngDevMode ? [{ debugName: "coverImageUrl" }] : []));
2197
2191
  // Computed signal to get dynamic components as an array for easier iteration in the template
2198
2192
  this.dynamicComponentsArray = computed(() => {
2199
2193
  const currentLesson = this.lesson();
@@ -2201,7 +2195,7 @@ class DCLessonEditorComponent {
2201
2195
  return Object.values(currentLesson.dynamicComponents);
2202
2196
  }
2203
2197
  return []; // Return empty array if no lesson or no dynamic components
2204
- });
2198
+ }, ...(ngDevMode ? [{ debugName: "dynamicComponentsArray" }] : []));
2205
2199
  // States
2206
2200
  this.components = {}; // Current Dynamic components
2207
2201
  this.editor = BalloonEditor;
@@ -2212,6 +2206,10 @@ class DCLessonEditorComponent {
2212
2206
  cropSettings: { resizeToWidth: 850, aspectRatio: AspectType.RectangleLarge, resolutions: [ResolutionType.Medium] },
2213
2207
  };
2214
2208
  this.promptsVisible = false;
2209
+ this.lessonForm = this.#formBuilder.group({
2210
+ title: [''],
2211
+ description: [''],
2212
+ });
2215
2213
  // Effect to fetch lesson data when ID changes
2216
2214
  effect(async () => {
2217
2215
  const id = this.lessonId();
@@ -2219,9 +2217,10 @@ class DCLessonEditorComponent {
2219
2217
  if (id) {
2220
2218
  this.isLoadingLesson.set(true); // Start loading
2221
2219
  try {
2222
- const fetchedLesson = await this.#lessonService.getLesson(id);
2220
+ const fetchedLesson = await this.lessonsService.getLesson(id);
2223
2221
  if (fetchedLesson) {
2224
2222
  this.lesson.set(fetchedLesson);
2223
+ this.lessonForm.patchValue(fetchedLesson, { emitEvent: false });
2225
2224
  }
2226
2225
  else {
2227
2226
  this.lesson.set(undefined); // Reset if not found
@@ -2246,6 +2245,13 @@ class DCLessonEditorComponent {
2246
2245
  this.isLoadingLesson.set(false); // Ensure loading is off
2247
2246
  }
2248
2247
  });
2248
+ this.lessonForm.valueChanges.subscribe((value) => {
2249
+ this.lesson.update((current) => {
2250
+ if (!current)
2251
+ return undefined;
2252
+ return { ...current, ...value };
2253
+ });
2254
+ });
2249
2255
  }
2250
2256
  /**
2251
2257
  * Updates a specific property on the lesson signal.
@@ -2261,6 +2267,13 @@ class DCLessonEditorComponent {
2261
2267
  return { ...currentLesson, [property]: value };
2262
2268
  });
2263
2269
  }
2270
+ onAssetsChange(updatedAssets) {
2271
+ this.lesson.update((currentLesson) => {
2272
+ if (!currentLesson)
2273
+ return undefined;
2274
+ return { ...currentLesson, assets: updatedAssets };
2275
+ });
2276
+ }
2264
2277
  onTagRemove(tag) {
2265
2278
  this.lesson.update((currentLesson) => {
2266
2279
  if (!currentLesson)
@@ -2298,7 +2311,7 @@ class DCLessonEditorComponent {
2298
2311
  this.isLoadingLesson.set(true); // Indicate saving
2299
2312
  try {
2300
2313
  // Use the cleaned lesson object for saving
2301
- const savedLesson = await this.#lessonService.postLesson(lessonToSave);
2314
+ const savedLesson = await this.lessonsService.postLesson(lessonToSave);
2302
2315
  const currentId = this.lessonId();
2303
2316
  if (!currentId) {
2304
2317
  // No se como guardar los extras aunt
@@ -2397,7 +2410,7 @@ class DCLessonEditorComponent {
2397
2410
  }
2398
2411
  async generateBanner() {
2399
2412
  this.#toastService.info({ title: 'Generando prompt de sugerencia', subtitle: 'Por favor, espera' });
2400
- const prompt = this.#lessonService.getPrompts().banner(this.lesson());
2413
+ const prompt = this.lessonsService.getPrompts().banner(this.lesson());
2401
2414
  const geminiRes = await this.ngxVertexService.generateText([{ role: ChatRoleVertex.User, content: prompt }]);
2402
2415
  this.promptService
2403
2416
  .openPrompt({
@@ -2412,7 +2425,8 @@ class DCLessonEditorComponent {
2412
2425
  this.#loadingBarService.showIndeterminate();
2413
2426
  this.defaultLessonsService.generateBanner(promptResult, this.lessonId()).then((result) => {
2414
2427
  if (result) {
2415
- this.updateLessonProperty('banner', result.banner);
2428
+ alert('Revisar como actualizar el banner');
2429
+ // this.updateLessonProperty('banner', (result as any).banner);
2416
2430
  }
2417
2431
  this.#loadingBarService.successAndHide();
2418
2432
  });
@@ -2430,7 +2444,7 @@ class DCLessonEditorComponent {
2430
2444
  }
2431
2445
  showPrompts() {
2432
2446
  this.promptsVisible = true;
2433
- const promptsFn = this.#lessonService.getPrompts();
2447
+ const promptsFn = this.lessonsService.getPrompts();
2434
2448
  this.prompts = { banner: promptsFn.banner(this.lesson()), content: promptsFn.content(this.lesson()), description: promptsFn.description(this.lesson()) };
2435
2449
  console.log(this.prompts);
2436
2450
  this.cdr.markForCheck();
@@ -2441,12 +2455,11 @@ class DCLessonEditorComponent {
2441
2455
  this.onComponentAdded(result);
2442
2456
  });
2443
2457
  }
2444
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2445
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: DCLessonEditorComponent, isStandalone: true, selector: "dc-lesson-editor", providers: [LessonNotionService], viewQueries: [{ propertyName: "target", first: true, predicate: ["target"], descendants: true, read: ViewContainerRef }, { propertyName: "dhtml", first: true, predicate: ["dhtml"], descendants: true, static: true }], ngImport: i0, template: "<div style=\"position: relative; margin-bottom: 20px\">\n <img class=\"header-cover\" [src]=\"coverImageUrl()\" alt=\"Lesson Cover Image\" />\n\n <dc-cropper-modal\n style=\"position: absolute; top: 10px; left: 20px\"\n [buttonLabel]=\"'Carga una portada'\"\n [imgStorageSettings]=\"coverStorageSettings\"\n (imageUploaded)=\"onImageUploaded($event)\"></dc-cropper-modal>\n\n <p-button\n (click)=\"generateBanner()\"\n class=\"generate-banner-btn\"\n icon=\"pi pi-sparkles\"\n severity=\"primary\"\n [rounded]=\"true\"\n [raised]=\"true\"\n pTooltip=\"Generar Banner AI\"\n tooltipPosition=\"left\"></p-button>\n\n <p-button class=\"prompt-visual\" icon=\"pi pi-info\" label=\"Ver Prompts\" [link]=\"true\" (click)=\"showPrompts()\" />\n</div>\n\n<br />\n\n<!-- Lesson Metadata Editor -->\n<dc-lesson-metadata-editor\n [lesson]=\"lesson\"\n [isLoadingLesson]=\"isLoadingLesson\"\n (saveRequest)=\"saveLesson()\"\n (importNotionRequest)=\"importFromNotion()\"\n (improveNotionRequest)=\"improveNotionWithAI()\">\n</dc-lesson-metadata-editor>\n\n<div style=\"margin-top: 30px\"></div>\n\n<!-- Component Adder -->\n<dc-lesson-component-adder (componentAdded)=\"onComponentAdded($event)\"></dc-lesson-component-adder>\n\n<!-- Display Added Components -->\n<div class=\"added-components-list\" style=\"margin-top: 15px; margin-bottom: 15px\">\n <h4>Componentes Agregados:</h4>\n @if (dynamicComponentsArray().length > 0) {\n <ul>\n @for (comp of dynamicComponentsArray(); track comp.id) {\n <li\n >ID: {{ comp.id }} - Tipo: {{ comp.component }}\n\n <button pButton icon=\"pi pi-info\" (click)=\"showComponentDetails(comp)\"></button>\n <p-button icon=\"pi pi-pencil\" [rounded]=\"true\" severity=\"warn\" (click)=\"editComponent(comp)\"></p-button>\n </li>\n }\n </ul>\n } @else {\n <p>A\u00FAn no se han agregado componentes.</p>\n }\n</div>\n\n<hr />\n\n<!-- Text Editor and Renderer -->\n<p-splitter [style]=\"{ height: '80vh' }\">\n <ng-template pTemplate>\n <ckeditor\n (keydown.control.s)=\"saveLesson($event)\"\n class=\"text-editor\"\n [editor]=\"editor\"\n [ngModel]=\"lesson()?.textCoded\"\n (ngModelChange)=\"updateLessonProperty('textCoded', $event)\">\n </ckeditor>\n </ng-template>\n\n <ng-template pTemplate>\n <dc-lesson-renderer class=\"text-editor\" [lessonInput]=\"lesson()\"></dc-lesson-renderer>\n </ng-template>\n</p-splitter>\n\n<div class=\"float-button\">\n <!-- Removed p-speeddial -->\n <p-button icon=\"pi pi-save\" (click)=\"saveLesson()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n</div>\n\n<hr />\n\n<p-dialog header=\"Prompts\" [modal]=\"true\" [(visible)]=\"promptsVisible\" [style]=\"{ width: '70%' }\">\n <div>\n <h1>Banner</h1>\n <p>{{ prompts?.banner }}</p>\n <h1>Contenido</h1>\n <p>{{ prompts?.content }}</p>\n <h1>Descripci\u00F3n</h1>\n <p>{{ prompts?.description }}</p>\n </div>\n</p-dialog>\n", styles: [".btn{padding:.5rem 1rem;border-radius:4px;border:1px solid transparent;cursor:pointer}.generate-banner-btn{position:absolute;right:10px;top:10px}.prompt-visual{position:absolute;left:10px;bottom:10px}.btn-primary{background-color:#007bff;color:#fff}.btn-outline-primary{border-color:#007bff;color:#007bff}.btn-secondary{background-color:#6c757d;color:#fff}.btn-outline-secondary{border-color:#6c757d;color:#6c757d}.btn-rounded{border-radius:50%}.form-control{padding:.375rem .75rem;border:1px solid #ced4da;border-radius:.25rem}.splitter{display:flex;gap:1rem}.splitter-panel{flex:1}.checkbox-container{display:inline-flex;align-items:center;gap:.5rem;cursor:pointer}.mr-2{margin-right:.5rem}.header-cover{width:100%;height:250px;object-fit:cover;position:relative;border-radius:8px}.float-button{position:fixed;bottom:3.5rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}.text-editor{width:-webkit-fill-available;overflow-y:auto}:host ::ng-deep .p-inputtext{background:#fff3}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: CKEditorModule }, { kind: "component", type: i3$2.CKEditorComponent, selector: "ckeditor", inputs: ["editor", "config", "data", "tagName", "watchdog", "editorWatchdogConfig", "disableTwoWayDataBinding", "disabled"], outputs: ["ready", "change", "blur", "focus", "error"] }, { kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "component", type: DCLessonRendererComponent, selector: "dc-lesson-renderer", inputs: ["lessonInput", "lessonIdInput", "settings"], outputs: ["wordClicked"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: SplitterModule }, { kind: "component", type: i5$1.Splitter, selector: "p-splitter", inputs: ["styleClass", "panelStyleClass", "style", "panelStyle", "stateStorage", "stateKey", "layout", "gutterSize", "step", "minSizes", "panelSizes"], outputs: ["onResizeEnd", "onResizeStart"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: DCLessonComponentAdderComponent, selector: "dc-lesson-component-adder", outputs: ["componentAdded"] }, { kind: "component", type: // Add the component adder here
2446
- DCLessonMetadataEditorComponent, selector: "dc-lesson-metadata-editor", inputs: ["lesson", "isLoadingLesson"], outputs: ["saveRequest", "importNotionRequest", "improveNotionRequest"] }, { kind: "ngmodule", type: // Add the metadata editor here
2447
- DialogModule }, { kind: "component", type: i7.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }] }); }
2458
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2459
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DCLessonEditorComponent, isStandalone: true, selector: "dc-lesson-editor", providers: [LessonNotionService], viewQueries: [{ propertyName: "target", first: true, predicate: ["target"], descendants: true, read: ViewContainerRef }, { propertyName: "dhtml", first: true, predicate: ["dhtml"], descendants: true, static: true }], ngImport: i0, template: "<!-- <div style=\"position: relative; margin-bottom: 20px\">\n <img class=\"header-cover\" [src]=\"coverImageUrl()\" alt=\"Lesson Cover Image\" />\n\n <dc-cropper-modal\n style=\"position: absolute; top: 10px; left: 20px\"\n [buttonLabel]=\"'Carga una portada'\"\n [imgStorageSettings]=\"coverStorageSettings\"\n (imageUploaded)=\"onImageUploaded($event)\"></dc-cropper-modal>\n\n <p-button\n (click)=\"generateBanner()\"\n class=\"generate-banner-btn\"\n icon=\"pi pi-sparkles\"\n severity=\"primary\"\n [rounded]=\"true\"\n [raised]=\"true\"\n pTooltip=\"Generar Banner AI\"\n tooltipPosition=\"left\"></p-button>\n\n <p-button class=\"prompt-visual\" icon=\"pi pi-info\" label=\"Ver Prompts\" [link]=\"true\" (click)=\"showPrompts()\" />\n</div> -->\n\n<div class=\"p-grid\">\n <div class=\"p-col-4\">\n <assets-loader [assets]=\"lesson()?.assets\" storagePath=\"lessons/{{ lesson()?.id }}\" (assetsChange)=\"onAssetsChange($event)\"></assets-loader>\n </div>\n <div class=\"p-col-4\">\n <h3>Learnable</h3>\n <dc-learnable-viewer [data]=\"lesson()?.learnable\"></dc-learnable-viewer>\n </div>\n <div class=\"p-col-4\">\n <h3>Auditable</h3>\n <dc-auditable-viewer [data]=\"lesson()?.auditable\"></dc-auditable-viewer>\n </div>\n <div class=\"p-col-4\">\n <h3>Manageable</h3>\n <dc-manageable-viewer [data]=\"lesson()?.manageable\"></dc-manageable-viewer>\n </div>\n <div class=\"p-col-4\">\n <h3>Reactions</h3>\n <dc-reactions-viewer [data]=\"lesson()?.reactions\"></dc-reactions-viewer>\n </div>\n\n <div class=\"p-col-4\">\n <h3>Extensions</h3>\n <dc-extensions-viewer [data]=\"lesson()?.extensions\"></dc-extensions-viewer>\n </div>\n</div>\n\n<!-- Lesson Metadata Editor -->\n<!-- <dc-lesson-metadata-editor\n [lesson]=\"lesson\"\n [lessonForm]=\"lessonForm\"\n [isLoadingLesson]=\"isLoadingLesson\"\n (saveRequest)=\"saveLesson()\"\n (importNotionRequest)=\"importFromNotion()\"\n (improveNotionRequest)=\"improveNotionWithAI()\">\n</dc-lesson-metadata-editor> -->\n\n<div style=\"margin-top: 30px\"></div>\n\n<!-- Component Adder -->\n<dc-lesson-component-adder (componentAdded)=\"onComponentAdded($event)\"></dc-lesson-component-adder>\n\n<!-- Display Added Components -->\n<div class=\"added-components-list\" style=\"margin-top: 15px; margin-bottom: 15px\">\n <h4>Componentes Agregados:</h4>\n @if (dynamicComponentsArray().length > 0) {\n <ul>\n @for (comp of dynamicComponentsArray(); track comp.id) {\n <li\n >ID: {{ comp.id }} - Tipo: {{ comp.component }}\n\n <button pButton icon=\"pi pi-info\" (click)=\"showComponentDetails(comp)\"></button>\n <p-button icon=\"pi pi-pencil\" [rounded]=\"true\" severity=\"warn\" (click)=\"editComponent(comp)\"></p-button>\n </li>\n }\n </ul>\n } @else {\n <p>A\u00FAn no se han agregado componentes.</p>\n }\n</div>\n\n<hr />\n\n<!-- Text Editor and Renderer -->\n<p-splitter [style]=\"{ height: '80vh' }\">\n <ng-template pTemplate>\n <ckeditor\n (keydown.control.s)=\"saveLesson($event)\"\n class=\"text-editor\"\n [editor]=\"editor\"\n [ngModel]=\"lesson()?.textCoded\"\n (ngModelChange)=\"updateLessonProperty('textCoded', $event)\">\n </ckeditor>\n </ng-template>\n\n <ng-template pTemplate>\n <dc-lesson-renderer class=\"text-editor\" [lessonInput]=\"lesson()\"></dc-lesson-renderer>\n </ng-template>\n</p-splitter>\n\n<div class=\"float-button\">\n <!-- Removed p-speeddial -->\n <p-button icon=\"pi pi-save\" (click)=\"saveLesson()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n</div>\n\n<hr />\n\n<p-dialog header=\"Prompts\" [modal]=\"true\" [(visible)]=\"promptsVisible\" [style]=\"{ width: '70%' }\">\n <div>\n <h1>Banner</h1>\n <p>{{ prompts?.banner }}</p>\n <h1>Contenido</h1>\n <p>{{ prompts?.content }}</p>\n <h1>Descripci\u00F3n</h1>\n <p>{{ prompts?.description }}</p>\n </div>\n</p-dialog>\n", styles: [".btn{padding:.5rem 1rem;border-radius:4px;border:1px solid transparent;cursor:pointer}.generate-banner-btn{position:absolute;right:10px;top:10px}.prompt-visual{position:absolute;left:10px;bottom:10px}.btn-primary{background-color:#007bff;color:#fff}.btn-outline-primary{border-color:#007bff;color:#007bff}.btn-secondary{background-color:#6c757d;color:#fff}.btn-outline-secondary{border-color:#6c757d;color:#6c757d}.btn-rounded{border-radius:50%}.form-control{padding:.375rem .75rem;border:1px solid #ced4da;border-radius:.25rem}.splitter{display:flex;gap:1rem}.splitter-panel{flex:1}.checkbox-container{display:inline-flex;align-items:center;gap:.5rem;cursor:pointer}.mr-2{margin-right:.5rem}.header-cover{width:100%;height:250px;object-fit:cover;position:relative;border-radius:8px}.float-button{position:fixed;bottom:3.5rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}.text-editor{width:-webkit-fill-available;overflow-y:auto}:host ::ng-deep .p-inputtext{background:#fff3}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i1$1.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: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: CKEditorModule }, { kind: "component", type: i3$2.CKEditorComponent, selector: "ckeditor", inputs: ["editor", "config", "data", "tagName", "watchdog", "editorWatchdogConfig", "disableTwoWayDataBinding", "disabled"], outputs: ["ready", "change", "blur", "focus", "error"] }, { kind: "component", type: DCLessonRendererComponent, selector: "dc-lesson-renderer", inputs: ["lessonInput", "lessonIdInput", "settings"], outputs: ["wordClicked"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: SplitterModule }, { kind: "component", type: i5$1.Splitter, selector: "p-splitter", inputs: ["styleClass", "panelStyleClass", "panelStyle", "stateStorage", "stateKey", "layout", "gutterSize", "step", "minSizes", "panelSizes"], outputs: ["onResizeEnd", "onResizeStart"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "component", type: DCLessonComponentAdderComponent, selector: "dc-lesson-component-adder", outputs: ["componentAdded"] }, { kind: "ngmodule", type: // Add the metadata editor here
2460
+ DialogModule }, { kind: "component", type: i7.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: DcExtensionsViewerComponent, selector: "dc-extensions-viewer", inputs: ["data"] }, { kind: "component", type: DcLearnableViewerComponent, selector: "dc-learnable-viewer", inputs: ["data"] }, { kind: "component", type: DcAuditableViewerComponent, selector: "dc-auditable-viewer", inputs: ["data"] }, { kind: "component", type: DcManageableViewerComponent, selector: "dc-manageable-viewer", inputs: ["data"] }, { kind: "component", type: DcReactionsViewerComponent, selector: "dc-reactions-viewer", inputs: ["data"] }, { kind: "component", type: AssetsLoaderComponent, selector: "assets-loader", inputs: ["assets", "storagePath"], outputs: ["assetsChange", "assetUpdate", "onFileSelected"] }] }); }
2448
2461
  }
2449
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonEditorComponent, decorators: [{
2462
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCLessonEditorComponent, decorators: [{
2450
2463
  type: Component,
2451
2464
  args: [{ selector: 'dc-lesson-editor', standalone: true, imports: [
2452
2465
  ButtonModule,
@@ -2455,12 +2468,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2455
2468
  DCLessonRendererComponent,
2456
2469
  FormsModule,
2457
2470
  InputTextModule,
2471
+ ReactiveFormsModule,
2458
2472
  SplitterModule,
2459
2473
  TooltipModule,
2460
2474
  DCLessonComponentAdderComponent, // Add the component adder here
2461
2475
  DCLessonMetadataEditorComponent, // Add the metadata editor here
2462
2476
  DialogModule,
2463
- ], providers: [LessonNotionService], template: "<div style=\"position: relative; margin-bottom: 20px\">\n <img class=\"header-cover\" [src]=\"coverImageUrl()\" alt=\"Lesson Cover Image\" />\n\n <dc-cropper-modal\n style=\"position: absolute; top: 10px; left: 20px\"\n [buttonLabel]=\"'Carga una portada'\"\n [imgStorageSettings]=\"coverStorageSettings\"\n (imageUploaded)=\"onImageUploaded($event)\"></dc-cropper-modal>\n\n <p-button\n (click)=\"generateBanner()\"\n class=\"generate-banner-btn\"\n icon=\"pi pi-sparkles\"\n severity=\"primary\"\n [rounded]=\"true\"\n [raised]=\"true\"\n pTooltip=\"Generar Banner AI\"\n tooltipPosition=\"left\"></p-button>\n\n <p-button class=\"prompt-visual\" icon=\"pi pi-info\" label=\"Ver Prompts\" [link]=\"true\" (click)=\"showPrompts()\" />\n</div>\n\n<br />\n\n<!-- Lesson Metadata Editor -->\n<dc-lesson-metadata-editor\n [lesson]=\"lesson\"\n [isLoadingLesson]=\"isLoadingLesson\"\n (saveRequest)=\"saveLesson()\"\n (importNotionRequest)=\"importFromNotion()\"\n (improveNotionRequest)=\"improveNotionWithAI()\">\n</dc-lesson-metadata-editor>\n\n<div style=\"margin-top: 30px\"></div>\n\n<!-- Component Adder -->\n<dc-lesson-component-adder (componentAdded)=\"onComponentAdded($event)\"></dc-lesson-component-adder>\n\n<!-- Display Added Components -->\n<div class=\"added-components-list\" style=\"margin-top: 15px; margin-bottom: 15px\">\n <h4>Componentes Agregados:</h4>\n @if (dynamicComponentsArray().length > 0) {\n <ul>\n @for (comp of dynamicComponentsArray(); track comp.id) {\n <li\n >ID: {{ comp.id }} - Tipo: {{ comp.component }}\n\n <button pButton icon=\"pi pi-info\" (click)=\"showComponentDetails(comp)\"></button>\n <p-button icon=\"pi pi-pencil\" [rounded]=\"true\" severity=\"warn\" (click)=\"editComponent(comp)\"></p-button>\n </li>\n }\n </ul>\n } @else {\n <p>A\u00FAn no se han agregado componentes.</p>\n }\n</div>\n\n<hr />\n\n<!-- Text Editor and Renderer -->\n<p-splitter [style]=\"{ height: '80vh' }\">\n <ng-template pTemplate>\n <ckeditor\n (keydown.control.s)=\"saveLesson($event)\"\n class=\"text-editor\"\n [editor]=\"editor\"\n [ngModel]=\"lesson()?.textCoded\"\n (ngModelChange)=\"updateLessonProperty('textCoded', $event)\">\n </ckeditor>\n </ng-template>\n\n <ng-template pTemplate>\n <dc-lesson-renderer class=\"text-editor\" [lessonInput]=\"lesson()\"></dc-lesson-renderer>\n </ng-template>\n</p-splitter>\n\n<div class=\"float-button\">\n <!-- Removed p-speeddial -->\n <p-button icon=\"pi pi-save\" (click)=\"saveLesson()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n</div>\n\n<hr />\n\n<p-dialog header=\"Prompts\" [modal]=\"true\" [(visible)]=\"promptsVisible\" [style]=\"{ width: '70%' }\">\n <div>\n <h1>Banner</h1>\n <p>{{ prompts?.banner }}</p>\n <h1>Contenido</h1>\n <p>{{ prompts?.content }}</p>\n <h1>Descripci\u00F3n</h1>\n <p>{{ prompts?.description }}</p>\n </div>\n</p-dialog>\n", styles: [".btn{padding:.5rem 1rem;border-radius:4px;border:1px solid transparent;cursor:pointer}.generate-banner-btn{position:absolute;right:10px;top:10px}.prompt-visual{position:absolute;left:10px;bottom:10px}.btn-primary{background-color:#007bff;color:#fff}.btn-outline-primary{border-color:#007bff;color:#007bff}.btn-secondary{background-color:#6c757d;color:#fff}.btn-outline-secondary{border-color:#6c757d;color:#6c757d}.btn-rounded{border-radius:50%}.form-control{padding:.375rem .75rem;border:1px solid #ced4da;border-radius:.25rem}.splitter{display:flex;gap:1rem}.splitter-panel{flex:1}.checkbox-container{display:inline-flex;align-items:center;gap:.5rem;cursor:pointer}.mr-2{margin-right:.5rem}.header-cover{width:100%;height:250px;object-fit:cover;position:relative;border-radius:8px}.float-button{position:fixed;bottom:3.5rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}.text-editor{width:-webkit-fill-available;overflow-y:auto}:host ::ng-deep .p-inputtext{background:#fff3}\n"] }]
2477
+ DcExtensionsViewerComponent,
2478
+ DcLearnableViewerComponent,
2479
+ DcAuditableViewerComponent,
2480
+ DcManageableViewerComponent,
2481
+ DcReactionsViewerComponent,
2482
+ AssetsLoaderComponent,
2483
+ ], providers: [LessonNotionService], template: "<!-- <div style=\"position: relative; margin-bottom: 20px\">\n <img class=\"header-cover\" [src]=\"coverImageUrl()\" alt=\"Lesson Cover Image\" />\n\n <dc-cropper-modal\n style=\"position: absolute; top: 10px; left: 20px\"\n [buttonLabel]=\"'Carga una portada'\"\n [imgStorageSettings]=\"coverStorageSettings\"\n (imageUploaded)=\"onImageUploaded($event)\"></dc-cropper-modal>\n\n <p-button\n (click)=\"generateBanner()\"\n class=\"generate-banner-btn\"\n icon=\"pi pi-sparkles\"\n severity=\"primary\"\n [rounded]=\"true\"\n [raised]=\"true\"\n pTooltip=\"Generar Banner AI\"\n tooltipPosition=\"left\"></p-button>\n\n <p-button class=\"prompt-visual\" icon=\"pi pi-info\" label=\"Ver Prompts\" [link]=\"true\" (click)=\"showPrompts()\" />\n</div> -->\n\n<div class=\"p-grid\">\n <div class=\"p-col-4\">\n <assets-loader [assets]=\"lesson()?.assets\" storagePath=\"lessons/{{ lesson()?.id }}\" (assetsChange)=\"onAssetsChange($event)\"></assets-loader>\n </div>\n <div class=\"p-col-4\">\n <h3>Learnable</h3>\n <dc-learnable-viewer [data]=\"lesson()?.learnable\"></dc-learnable-viewer>\n </div>\n <div class=\"p-col-4\">\n <h3>Auditable</h3>\n <dc-auditable-viewer [data]=\"lesson()?.auditable\"></dc-auditable-viewer>\n </div>\n <div class=\"p-col-4\">\n <h3>Manageable</h3>\n <dc-manageable-viewer [data]=\"lesson()?.manageable\"></dc-manageable-viewer>\n </div>\n <div class=\"p-col-4\">\n <h3>Reactions</h3>\n <dc-reactions-viewer [data]=\"lesson()?.reactions\"></dc-reactions-viewer>\n </div>\n\n <div class=\"p-col-4\">\n <h3>Extensions</h3>\n <dc-extensions-viewer [data]=\"lesson()?.extensions\"></dc-extensions-viewer>\n </div>\n</div>\n\n<!-- Lesson Metadata Editor -->\n<!-- <dc-lesson-metadata-editor\n [lesson]=\"lesson\"\n [lessonForm]=\"lessonForm\"\n [isLoadingLesson]=\"isLoadingLesson\"\n (saveRequest)=\"saveLesson()\"\n (importNotionRequest)=\"importFromNotion()\"\n (improveNotionRequest)=\"improveNotionWithAI()\">\n</dc-lesson-metadata-editor> -->\n\n<div style=\"margin-top: 30px\"></div>\n\n<!-- Component Adder -->\n<dc-lesson-component-adder (componentAdded)=\"onComponentAdded($event)\"></dc-lesson-component-adder>\n\n<!-- Display Added Components -->\n<div class=\"added-components-list\" style=\"margin-top: 15px; margin-bottom: 15px\">\n <h4>Componentes Agregados:</h4>\n @if (dynamicComponentsArray().length > 0) {\n <ul>\n @for (comp of dynamicComponentsArray(); track comp.id) {\n <li\n >ID: {{ comp.id }} - Tipo: {{ comp.component }}\n\n <button pButton icon=\"pi pi-info\" (click)=\"showComponentDetails(comp)\"></button>\n <p-button icon=\"pi pi-pencil\" [rounded]=\"true\" severity=\"warn\" (click)=\"editComponent(comp)\"></p-button>\n </li>\n }\n </ul>\n } @else {\n <p>A\u00FAn no se han agregado componentes.</p>\n }\n</div>\n\n<hr />\n\n<!-- Text Editor and Renderer -->\n<p-splitter [style]=\"{ height: '80vh' }\">\n <ng-template pTemplate>\n <ckeditor\n (keydown.control.s)=\"saveLesson($event)\"\n class=\"text-editor\"\n [editor]=\"editor\"\n [ngModel]=\"lesson()?.textCoded\"\n (ngModelChange)=\"updateLessonProperty('textCoded', $event)\">\n </ckeditor>\n </ng-template>\n\n <ng-template pTemplate>\n <dc-lesson-renderer class=\"text-editor\" [lessonInput]=\"lesson()\"></dc-lesson-renderer>\n </ng-template>\n</p-splitter>\n\n<div class=\"float-button\">\n <!-- Removed p-speeddial -->\n <p-button icon=\"pi pi-save\" (click)=\"saveLesson()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n</div>\n\n<hr />\n\n<p-dialog header=\"Prompts\" [modal]=\"true\" [(visible)]=\"promptsVisible\" [style]=\"{ width: '70%' }\">\n <div>\n <h1>Banner</h1>\n <p>{{ prompts?.banner }}</p>\n <h1>Contenido</h1>\n <p>{{ prompts?.content }}</p>\n <h1>Descripci\u00F3n</h1>\n <p>{{ prompts?.description }}</p>\n </div>\n</p-dialog>\n", styles: [".btn{padding:.5rem 1rem;border-radius:4px;border:1px solid transparent;cursor:pointer}.generate-banner-btn{position:absolute;right:10px;top:10px}.prompt-visual{position:absolute;left:10px;bottom:10px}.btn-primary{background-color:#007bff;color:#fff}.btn-outline-primary{border-color:#007bff;color:#007bff}.btn-secondary{background-color:#6c757d;color:#fff}.btn-outline-secondary{border-color:#6c757d;color:#6c757d}.btn-rounded{border-radius:50%}.form-control{padding:.375rem .75rem;border:1px solid #ced4da;border-radius:.25rem}.splitter{display:flex;gap:1rem}.splitter-panel{flex:1}.checkbox-container{display:inline-flex;align-items:center;gap:.5rem;cursor:pointer}.mr-2{margin-right:.5rem}.header-cover{width:100%;height:250px;object-fit:cover;position:relative;border-radius:8px}.float-button{position:fixed;bottom:3.5rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}.text-editor{width:-webkit-fill-available;overflow-y:auto}:host ::ng-deep .p-inputtext{background:#fff3}\n"] }]
2464
2484
  }], ctorParameters: () => [], propDecorators: { target: [{
2465
2485
  type: ViewChild,
2466
2486
  args: ['target', { read: ViewContainerRef }]
@@ -2474,10 +2494,10 @@ class LessonDynamicComponent {
2474
2494
  constructor() {
2475
2495
  this.settings = {};
2476
2496
  }
2477
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonDynamicComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2478
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: LessonDynamicComponent, isStandalone: true, selector: "app-lesson-component", inputs: { settings: "settings" }, ngImport: i0, template: '<div>no template</div>', isInline: true }); }
2497
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonDynamicComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2498
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: LessonDynamicComponent, isStandalone: true, selector: "app-lesson-component", inputs: { settings: "settings" }, ngImport: i0, template: '<div>no template</div>', isInline: true }); }
2479
2499
  }
2480
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LessonDynamicComponent, decorators: [{
2500
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LessonDynamicComponent, decorators: [{
2481
2501
  type: Component,
2482
2502
  args: [{
2483
2503
  selector: 'app-lesson-component',
@@ -2488,7 +2508,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2488
2508
  type: Input
2489
2509
  }] } });
2490
2510
 
2491
- const Endpoints$1 = {
2511
+ const Endpoints = {
2492
2512
  courses: 'api/courses',
2493
2513
  };
2494
2514
  class CoursesService {
@@ -2497,12 +2517,12 @@ class CoursesService {
2497
2517
  }
2498
2518
  // Not sure how to implement this yet.
2499
2519
  getCourses() {
2500
- return this.httpCoreService.get(Endpoints$1.courses);
2520
+ return this.httpCoreService.get(Endpoints.courses);
2501
2521
  }
2502
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2503
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesService, providedIn: 'root' }); }
2522
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CoursesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2523
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CoursesService, providedIn: 'root' }); }
2504
2524
  }
2505
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesService, decorators: [{
2525
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CoursesService, decorators: [{
2506
2526
  type: Injectable,
2507
2527
  args: [{
2508
2528
  providedIn: 'root',
@@ -2517,92 +2537,41 @@ class CoursesAdminComponent {
2517
2537
  const courses = await this.httpCoreService.get('courses');
2518
2538
  console.log(courses);
2519
2539
  }
2520
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesAdminComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2521
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: CoursesAdminComponent, isStandalone: true, selector: "ngx-courses-admin", ngImport: i0, template: "<p>welcome to courses creation</p>\n", styles: [""] }); }
2540
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CoursesAdminComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2541
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: CoursesAdminComponent, isStandalone: true, selector: "ngx-courses-admin", ngImport: i0, template: "<p>welcome to courses creation</p>\n", styles: [""] }); }
2522
2542
  }
2523
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesAdminComponent, decorators: [{
2543
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CoursesAdminComponent, decorators: [{
2524
2544
  type: Component,
2525
2545
  args: [{ selector: 'ngx-courses-admin', standalone: true, template: "<p>welcome to courses creation</p>\n" }]
2526
2546
  }] });
2527
2547
 
2528
- class CoursesComponent {
2529
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2530
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: CoursesComponent, isStandalone: true, selector: "app-courses", ngImport: i0, template: "<router-outlet />\n", styles: [":host{display:block;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2531
- }
2532
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesComponent, decorators: [{
2533
- type: Component,
2534
- args: [{ selector: 'app-courses', imports: [RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<router-outlet />\n", styles: [":host{display:block;height:100%}\n"] }]
2535
- }] });
2536
-
2537
- class CourseDetailComponent {
2538
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2539
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: CourseDetailComponent, isStandalone: true, selector: "app-course-detail", ngImport: i0, template: `<p>course-detail works!</p>`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2540
- }
2541
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseDetailComponent, decorators: [{
2542
- type: Component,
2543
- args: [{ selector: 'app-course-detail', imports: [], template: `<p>course-detail works!</p>`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
2544
- }] });
2545
-
2546
- const server = 'primary';
2547
- // TODO add your own end points
2548
- const Endpoints = {
2549
- Courses: {
2550
- Courses: 'api/courses',
2551
- CoursesFiltered: 'api/courses/query',
2552
- },
2553
- };
2554
- class CourseService {
2548
+ class CourseService extends EntityCommunicationService {
2555
2549
  constructor() {
2556
- this.httpService = inject(HttpCoreService);
2557
- this.toastService = inject(TOAST_ALERTS_TOKEN);
2550
+ super('courses');
2558
2551
  }
2559
- async getCourses() {
2560
- try {
2561
- const response = await this.httpService.get(Endpoints.Courses.Courses, server);
2562
- this.toastService.success({ title: 'Se han encontrado generics', subtitle: 'Mostrando información' });
2563
- return response;
2564
- }
2565
- catch (error) {
2566
- this.toastService.warn({ title: 'Error fetching generics', subtitle: 'Showing Default Data' });
2567
- // return RemoveSimpleDataExample;
2568
- return [];
2569
- }
2570
- }
2571
- async getFilteredCourses(filter) {
2572
- return this.httpService.post(Endpoints.Courses.CoursesFiltered, filter, server);
2573
- }
2574
- async getCourse(id) {
2575
- return this.httpService.get(`${Endpoints.Courses.Courses}/${id}`);
2576
- }
2577
- async saveCourse(course) {
2578
- return this.httpService.post(Endpoints.Courses.Courses, course);
2579
- }
2580
- async deleteCourse(id) {
2581
- return this.httpService.delete(`${Endpoints.Courses.Courses}/${id}`);
2582
- }
2583
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2584
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseService, providedIn: 'root' }); }
2552
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2553
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseService, providedIn: 'root' }); }
2585
2554
  }
2586
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseService, decorators: [{
2555
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseService, decorators: [{
2587
2556
  type: Injectable,
2588
2557
  args: [{
2589
2558
  providedIn: 'root',
2590
2559
  }]
2591
- }] });
2560
+ }], ctorParameters: () => [] });
2592
2561
 
2593
2562
  class CourseListComponent extends PaginationBase {
2594
2563
  constructor() {
2595
2564
  super(...arguments);
2596
2565
  // Services
2597
2566
  this.toastService = inject(TOAST_ALERTS_TOKEN);
2598
- this.sourceService = inject(CourseService);
2567
+ this.courseService = inject(CourseService);
2599
2568
  this.cdr = inject(ChangeDetectorRef);
2600
2569
  // Inputs
2601
2570
  this.viewType = 'card';
2602
- this.onlyView = input(true);
2571
+ this.onlyView = input(true, ...(ngDevMode ? [{ debugName: "onlyView" }] : []));
2603
2572
  this.onSelect = output();
2604
2573
  // States
2605
- this.courses = signal([]);
2574
+ this.courses = signal([], ...(ngDevMode ? [{ debugName: "courses" }] : []));
2606
2575
  this.columns = ['name', 'description', 'updatedAt', 'image'];
2607
2576
  this.filterBarOptions = { showActions: true, showCreateButton: true, showViewButton: true };
2608
2577
  }
@@ -2627,7 +2596,8 @@ class CourseListComponent extends PaginationBase {
2627
2596
  }
2628
2597
  async ngOnInit() {
2629
2598
  this.filterConfig.returnProps = { _id: 1, id: 1, name: 1, description: 1, updatedAt: 1, image: 1 };
2630
- const response = await this.sourceService.getFilteredCourses(this.filterConfig);
2599
+ this.filterConfig.filters = { targetLang: 'de', baseLang: 'es' };
2600
+ const response = await this.courseService.query(this.filterConfig);
2631
2601
  this.courses.set(response.rows);
2632
2602
  this.cdr.detectChanges();
2633
2603
  console.log(this.courses(), this.viewType);
@@ -2654,15 +2624,15 @@ class CourseListComponent extends PaginationBase {
2654
2624
  if (action == 'changeView') {
2655
2625
  this.toggleView();
2656
2626
  }
2627
+ const id = item.id || item._id;
2657
2628
  switch (action) {
2658
2629
  case 'view':
2659
- this.router.navigate(['./details', item.id], { relativeTo: this.route });
2630
+ this.router.navigate(['./details', id], { relativeTo: this.route });
2660
2631
  break;
2661
2632
  case 'delete':
2662
2633
  const areYouSure = confirm('¿Estás seguro de querer eliminar este origen?');
2663
2634
  if (areYouSure) {
2664
- const id = item.id || item._id;
2665
- await this.sourceService.deleteCourse(id);
2635
+ await this.courseService.remove(id);
2666
2636
  this.courses.set(this.courses().filter((course) => course._id !== id));
2667
2637
  this.toastService.success({
2668
2638
  title: 'Origen eliminado',
@@ -2672,14 +2642,14 @@ class CourseListComponent extends PaginationBase {
2672
2642
  }
2673
2643
  break;
2674
2644
  case 'edit':
2675
- this.router.navigate(['./edit', item.id], { relativeTo: this.route });
2645
+ this.router.navigate(['./edit', id], { relativeTo: this.route });
2676
2646
  break;
2677
2647
  }
2678
2648
  }
2679
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2680
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: CourseListComponent, isStandalone: true, selector: "app-course-list", inputs: { viewType: { classPropertyName: "viewType", publicName: "viewType", isSignal: false, isRequired: false, transformFunction: null }, onlyView: { classPropertyName: "onlyView", publicName: "onlyView", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, usesInheritance: true, ngImport: i0, template: "@if (!onlyView()) {\n<p-button [icon]=\"viewType === 'card' ? 'pi pi-table' : 'pi pi-list'\" label=\"Change View\" [link]=\"true\" (click)=\"toggleView()\" />\n}\n<div class=\"course-list-container\">\n <dc-filter-bar [options]=\"filterBarOptions\" (onNew)=\"onNew()\" (onFilterAction)=\"doAction($event)\"></dc-filter-bar>\n\n @if (viewType === 'card') {\n <div class=\"course-list-content\">\n @for (course of courses(); track course.id) {\n <div class=\"card-source\">\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(course)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true }\" />\n </div>\n <p-card [header]=\"course.name\">\n <p class=\"m-0\">{{ course.description | slice : 0 : 250 }}...</p>\n <span>{{ course.updatedAt | date : 'dd/MM/yyyy HH:mm' }}</span>\n </p-card>\n </div>\n } @if (courses().length === 0) {\n <p-card>\n <p>No courses found</p>\n </p-card>\n }\n </div>\n } @else if ( viewType == 'table'){\n\n <app-quick-table [tableData]=\"courses()\"></app-quick-table>\n\n }\n\n <div class=\"paginator-container\">\n <p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n </p-paginator>\n </div>\n</div>\n", styles: [":host{display:block;height:100%}.course-list-container{display:flex;flex-direction:column;height:100%}.course-list-content{margin-top:10px;flex:1;overflow-y:auto;padding-bottom:10px}.card-source{margin-bottom:10px;position:relative}.paginator-container{margin-top:auto;padding-top:10px}\n"], dependencies: [{ kind: "ngmodule", type: CardModule }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters"], outputs: ["onFilterAction", "onChangeSort", "onNew"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i2$1.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: SlicePipe, name: "slice" }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i1$2.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "style", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "appendTo", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2649
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2650
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: CourseListComponent, isStandalone: true, selector: "app-course-list", inputs: { viewType: { classPropertyName: "viewType", publicName: "viewType", isSignal: false, isRequired: false, transformFunction: null }, onlyView: { classPropertyName: "onlyView", publicName: "onlyView", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, usesInheritance: true, ngImport: i0, template: "@if (!onlyView()) {\n<p-button [icon]=\"viewType === 'card' ? 'pi pi-table' : 'pi pi-list'\" label=\"Change View\" [link]=\"true\" (click)=\"toggleView()\" />\n}\n<div class=\"course-list-container\">\n <dc-filter-bar [options]=\"filterBarOptions\" (onNew)=\"onNew()\" (onFilterAction)=\"doAction($event)\"></dc-filter-bar>\n\n @if (viewType === 'card') {\n <div class=\"course-list-content\">\n @for (course of courses(); track course.id) {\n <div class=\"card-source\">\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(course)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true }\"\n [tooltipOptions]=\"{ tooltipPosition: 'top' }\" />\n\n />\n </div>\n <p-card [header]=\"course.name\">\n <p class=\"m-0\">{{ course.description | slice : 0 : 250 }}...</p>\n <span>{{ course.updatedAt | date : 'dd/MM/yyyy HH:mm' }}</span>\n </p-card>\n </div>\n } @if (courses().length === 0) {\n <p-card>\n <p>No courses found</p>\n </p-card>\n }\n </div>\n } @else if ( viewType == 'table'){\n\n <app-quick-table [tableData]=\"courses()\"></app-quick-table>\n\n }\n\n <div class=\"paginator-container\">\n <p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n </p-paginator>\n </div>\n</div>\n", styles: [":host{display:block;height:100%}.course-list-container{display:flex;flex-direction:column;height:100%}.course-list-content{margin-top:10px;flex:1;overflow-y:auto;padding-bottom:10px}.card-source{margin-bottom:10px;position:relative}.paginator-container{margin-top:auto;padding-top:10px}\n"], dependencies: [{ kind: "ngmodule", type: CardModule }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["items", "options", "customFilters"], outputs: ["onFilterAction", "onChangeSort", "onNew"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i2$1.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i1$2.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["columns", "tableData", "actions"], outputs: ["onAction"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: SlicePipe, name: "slice" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2681
2651
  }
2682
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseListComponent, decorators: [{
2652
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseListComponent, decorators: [{
2683
2653
  type: Component,
2684
2654
  args: [{ selector: 'app-course-list', imports: [
2685
2655
  CardModule,
@@ -2692,19 +2662,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2692
2662
  RouterModule,
2693
2663
  TableModule,
2694
2664
  QuickTableComponent,
2695
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!onlyView()) {\n<p-button [icon]=\"viewType === 'card' ? 'pi pi-table' : 'pi pi-list'\" label=\"Change View\" [link]=\"true\" (click)=\"toggleView()\" />\n}\n<div class=\"course-list-container\">\n <dc-filter-bar [options]=\"filterBarOptions\" (onNew)=\"onNew()\" (onFilterAction)=\"doAction($event)\"></dc-filter-bar>\n\n @if (viewType === 'card') {\n <div class=\"course-list-content\">\n @for (course of courses(); track course.id) {\n <div class=\"card-source\">\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(course)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true }\" />\n </div>\n <p-card [header]=\"course.name\">\n <p class=\"m-0\">{{ course.description | slice : 0 : 250 }}...</p>\n <span>{{ course.updatedAt | date : 'dd/MM/yyyy HH:mm' }}</span>\n </p-card>\n </div>\n } @if (courses().length === 0) {\n <p-card>\n <p>No courses found</p>\n </p-card>\n }\n </div>\n } @else if ( viewType == 'table'){\n\n <app-quick-table [tableData]=\"courses()\"></app-quick-table>\n\n }\n\n <div class=\"paginator-container\">\n <p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n </p-paginator>\n </div>\n</div>\n", styles: [":host{display:block;height:100%}.course-list-container{display:flex;flex-direction:column;height:100%}.course-list-content{margin-top:10px;flex:1;overflow-y:auto;padding-bottom:10px}.card-source{margin-bottom:10px;position:relative}.paginator-container{margin-top:auto;padding-top:10px}\n"] }]
2665
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!onlyView()) {\n<p-button [icon]=\"viewType === 'card' ? 'pi pi-table' : 'pi pi-list'\" label=\"Change View\" [link]=\"true\" (click)=\"toggleView()\" />\n}\n<div class=\"course-list-container\">\n <dc-filter-bar [options]=\"filterBarOptions\" (onNew)=\"onNew()\" (onFilterAction)=\"doAction($event)\"></dc-filter-bar>\n\n @if (viewType === 'card') {\n <div class=\"course-list-content\">\n @for (course of courses(); track course.id) {\n <div class=\"card-source\">\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(course)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true }\"\n [tooltipOptions]=\"{ tooltipPosition: 'top' }\" />\n\n />\n </div>\n <p-card [header]=\"course.name\">\n <p class=\"m-0\">{{ course.description | slice : 0 : 250 }}...</p>\n <span>{{ course.updatedAt | date : 'dd/MM/yyyy HH:mm' }}</span>\n </p-card>\n </div>\n } @if (courses().length === 0) {\n <p-card>\n <p>No courses found</p>\n </p-card>\n }\n </div>\n } @else if ( viewType == 'table'){\n\n <app-quick-table [tableData]=\"courses()\"></app-quick-table>\n\n }\n\n <div class=\"paginator-container\">\n <p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n </p-paginator>\n </div>\n</div>\n", styles: [":host{display:block;height:100%}.course-list-container{display:flex;flex-direction:column;height:100%}.course-list-content{margin-top:10px;flex:1;overflow-y:auto;padding-bottom:10px}.card-source{margin-bottom:10px;position:relative}.paginator-container{margin-top:auto;padding-top:10px}\n"] }]
2696
2666
  }], propDecorators: { viewType: [{
2697
2667
  type: Input
2698
2668
  }] } });
2699
2669
 
2700
- class CourseFormComponent {
2670
+ class CourseDetailComponent {
2671
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2672
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: CourseDetailComponent, isStandalone: true, selector: "app-course-detail", ngImport: i0, template: `<p>course-detail works!</p>`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2673
+ }
2674
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseDetailComponent, decorators: [{
2675
+ type: Component,
2676
+ args: [{ selector: 'app-course-detail', imports: [], template: `<p>course-detail works!</p>`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
2677
+ }] });
2678
+
2679
+ class CourseFormComponent extends EntityBaseFormComponent {
2701
2680
  constructor() {
2702
- this.route = inject(ActivatedRoute);
2703
- this.courseService = inject(CourseService);
2681
+ super(...arguments);
2682
+ this.entityCommunicationService = inject(CourseService);
2704
2683
  this.fb = inject(FormBuilder);
2705
- this.router = inject(Router);
2706
- this.toastService = inject(TOAST_ALERTS_TOKEN);
2707
- this.cdr = inject(ChangeDetectorRef);
2684
+ this.languageOptions = getSupportedLanguageOptions('en');
2685
+ this.form = this.fb.group({
2686
+ name: ['', Validators.required],
2687
+ description: [''],
2688
+ image: [{}],
2689
+ targetLang: ['', Validators.required],
2690
+ baseLang: ['', Validators.required],
2691
+ });
2692
+ this.onSave = output();
2708
2693
  this.storageImgSettings = {
2709
2694
  path: `courses`,
2710
2695
  cropSettings: { aspectRatio: AspectType.Square, resolutions: [ResolutionType.MediumLarge], resizeToWidth: 700 },
@@ -2713,46 +2698,32 @@ class CourseFormComponent {
2713
2698
  { key: 'title', type: 'input', props: { label: 'Title', placeholder: 'Title', required: false } },
2714
2699
  { key: 'content', type: 'textarea', props: { label: 'Content', placeholder: 'Content', required: false } },
2715
2700
  ];
2716
- this.courseForm = this.fb.group({
2717
- name: ['', Validators.required],
2718
- description: [''],
2719
- image: [{}],
2720
- });
2721
- this.course = null;
2722
- this.courseId = this.route.snapshot.params['id'];
2723
2701
  }
2724
- async ngOnInit() {
2725
- if (this.courseId) {
2726
- this.course = await this.courseService.getCourse(this.courseId);
2727
- if (this.course) {
2728
- this.courseForm.patchValue(this.course);
2729
- }
2730
- }
2702
+ patchForm(entity) {
2703
+ this.form.patchValue(entity);
2731
2704
  }
2732
2705
  async save() {
2733
- if (this.courseForm.valid) {
2734
- const course = { ...this.course, ...this.courseForm.value };
2735
- const result = await this.courseService.saveCourse(course);
2736
- if (!this.courseId) {
2737
- this.router.navigate([result.id], { relativeTo: this.route });
2706
+ const result = await super.save();
2707
+ if (result) {
2708
+ this.onSave.emit(result);
2709
+ if (this.toastService) {
2710
+ this.toastService.success({ title: 'Course', subtitle: 'Data was saved' });
2738
2711
  }
2739
- this.toastService.success({ title: 'Origen guardado', subtitle: 'El origen ha sido guardado correctamente' });
2740
2712
  }
2713
+ return result;
2741
2714
  }
2742
2715
  handleImageUpload(event) {
2743
- // this.genericForm.patchValue({ image: event });
2744
- alert('Image uploaded');
2716
+ this.form.patchValue({ image: event });
2745
2717
  }
2746
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2747
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: CourseFormComponent, isStandalone: true, selector: "app-source-form", ngImport: i0, template: "<h3>Courses Form</h3>\n\n<div class=\"source-form-card\">\n <p-card [header]=\"courseId ? 'Edit Course' : 'New Course'\">\n <form [formGroup]=\"courseForm\">\n <div style=\"display: flex; gap: 10px\">\n <div class=\"form-field\">\n <label class=\"block\" pTooltip=\"Image should be handle after upload\">Subir imagen</label>\n <img width=\"218px\" src=\"assets/images/face-3.jpg\" />\n <dc-cropper-modal [imgStorageSettings]=\"storageImgSettings\" (imageUploaded)=\"handleImageUpload($event)\"></dc-cropper-modal>\n </div>\n\n <div style=\"width: 100%\">\n <div class=\"form-field\">\n <label for=\"name\" class=\"block\">Name</label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" placeholder=\"Enter source name\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\" class=\"block\">Description</label>\n <textarea id=\"description\" pTextarea formControlName=\"description\" rows=\"5\" class=\"w-full\" placeholder=\"Enter source content\"> </textarea>\n </div>\n </div>\n </div>\n </form>\n\n <div style=\"display: flex; justify-content: flex-end\">\n <p-button (click)=\"save()\" label=\"Save Course\" [disabled]=\"!courseForm.valid\" icon=\"pi pi-check\" iconPos=\"right\"> </p-button>\n </div>\n </p-card>\n</div>\n", styles: [":host{display:block;padding:1rem}.source-form-card{max-width:800px;margin:0 auto}.form-field{margin-bottom:1.5rem;display:flex;flex-direction:column}.form-field label{margin-bottom:.5rem;font-weight:500;color:#495057}.form-field input,.form-field textarea,.form-field ::ng-deep .p-element{margin-top:.25rem}:host ::ng-deep .p-card .p-card-content>div:last-child{margin-top:1.5rem;display:flex;justify-content:flex-end}:host ::ng-deep .p-card .p-card-header{background-color:#f8f9fa;padding:1rem;border-bottom:1px solid #dee2e6}h3{color:#495057;margin-bottom:1.5rem;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.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"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$3.Textarea, selector: "[pTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: ChipModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "ngmodule", type: DialogModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2718
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseFormComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2719
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: CourseFormComponent, isStandalone: true, selector: "app-source-form", outputs: { onSave: "onSave" }, usesInheritance: true, ngImport: i0, template: "<h3>Courses Form</h3>\n\n<div class=\"source-form-card\">\n <p-card [header]=\"entityId() ? 'Edit Course' : 'New Course'\">\n <form [formGroup]=\"form\">\n <div class=\"form-field\">\n <label for=\"baseLang\">Base Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"baseLang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"baseLang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n <div class=\"form-field\">\n <label for=\"targetLang\">Target Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"targetLang\"\n [filter]=\"true\"\n [options]=\"languageOptions\"\n formControlName=\"targetLang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div style=\"display: flex; gap: 10px\">\n <div class=\"form-field\">\n <label class=\"block\" pTooltip=\"Image should be handle after upload\">Subir imagen</label>\n <img width=\"218px\" src=\"assets/images/face-3.jpg\" />\n <dc-cropper-modal [imgStorageSettings]=\"storageImgSettings\" (imageUploaded)=\"handleImageUpload($event)\"></dc-cropper-modal>\n </div>\n\n <div style=\"width: 100%\">\n <div class=\"form-field\">\n <label for=\"name\" class=\"block\">Name</label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" placeholder=\"Enter source name\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\" class=\"block\">Description</label>\n <textarea id=\"description\" pTextarea formControlName=\"description\" rows=\"5\" class=\"w-full\" placeholder=\"Enter source content\"> </textarea>\n </div>\n </div>\n </div>\n </form>\n\n <div style=\"display: flex; justify-content: flex-end\">\n <p-button (click)=\"save()\" label=\"Save Course\" [disabled]=\"!form.valid\" icon=\"pi pi-check\" iconPos=\"right\"> </p-button>\n </div>\n </p-card>\n</div>\n", styles: [":host{display:block;padding:1rem}.source-form-card{max-width:800px;margin:0 auto}.form-field{margin-bottom:1.5rem;display:flex;flex-direction:column}.form-field label{margin-bottom:.5rem;font-weight:500;color:#495057}.form-field input,.form-field textarea,.form-field ::ng-deep .p-element{margin-top:.25rem}:host ::ng-deep .p-card .p-card-content>div:last-child{margin-top:1.5rem;display:flex;justify-content:flex-end}:host ::ng-deep .p-card .p-card-header{background-color:#f8f9fa;padding:1rem;border-bottom:1px solid #dee2e6}h3{color:#495057;margin-bottom:1.5rem;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.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"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$3.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: "ngmodule", type: SelectModule }, { kind: "component", type: i2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ChipModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "ngmodule", type: DialogModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2748
2720
  }
2749
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseFormComponent, decorators: [{
2721
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CourseFormComponent, decorators: [{
2750
2722
  type: Component,
2751
2723
  args: [{ selector: 'app-source-form', imports: [
2752
2724
  ReactiveFormsModule,
2753
2725
  CardModule,
2754
2726
  TextareaModule,
2755
- DropdownModule,
2756
2727
  ButtonModule,
2757
2728
  SelectModule,
2758
2729
  InputTextModule,
@@ -2762,7 +2733,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2762
2733
  FormlyModule,
2763
2734
  DialogModule,
2764
2735
  CourseListComponent,
2765
- ], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<h3>Courses Form</h3>\n\n<div class=\"source-form-card\">\n <p-card [header]=\"courseId ? 'Edit Course' : 'New Course'\">\n <form [formGroup]=\"courseForm\">\n <div style=\"display: flex; gap: 10px\">\n <div class=\"form-field\">\n <label class=\"block\" pTooltip=\"Image should be handle after upload\">Subir imagen</label>\n <img width=\"218px\" src=\"assets/images/face-3.jpg\" />\n <dc-cropper-modal [imgStorageSettings]=\"storageImgSettings\" (imageUploaded)=\"handleImageUpload($event)\"></dc-cropper-modal>\n </div>\n\n <div style=\"width: 100%\">\n <div class=\"form-field\">\n <label for=\"name\" class=\"block\">Name</label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" placeholder=\"Enter source name\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\" class=\"block\">Description</label>\n <textarea id=\"description\" pTextarea formControlName=\"description\" rows=\"5\" class=\"w-full\" placeholder=\"Enter source content\"> </textarea>\n </div>\n </div>\n </div>\n </form>\n\n <div style=\"display: flex; justify-content: flex-end\">\n <p-button (click)=\"save()\" label=\"Save Course\" [disabled]=\"!courseForm.valid\" icon=\"pi pi-check\" iconPos=\"right\"> </p-button>\n </div>\n </p-card>\n</div>\n", styles: [":host{display:block;padding:1rem}.source-form-card{max-width:800px;margin:0 auto}.form-field{margin-bottom:1.5rem;display:flex;flex-direction:column}.form-field label{margin-bottom:.5rem;font-weight:500;color:#495057}.form-field input,.form-field textarea,.form-field ::ng-deep .p-element{margin-top:.25rem}:host ::ng-deep .p-card .p-card-content>div:last-child{margin-top:1.5rem;display:flex;justify-content:flex-end}:host ::ng-deep .p-card .p-card-header{background-color:#f8f9fa;padding:1rem;border-bottom:1px solid #dee2e6}h3{color:#495057;margin-bottom:1.5rem;text-align:center}\n"] }]
2736
+ ], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<h3>Courses Form</h3>\n\n<div class=\"source-form-card\">\n <p-card [header]=\"entityId() ? 'Edit Course' : 'New Course'\">\n <form [formGroup]=\"form\">\n <div class=\"form-field\">\n <label for=\"baseLang\">Base Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"baseLang\"\n [options]=\"languageOptions\"\n [filter]=\"true\"\n formControlName=\"baseLang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n <div class=\"form-field\">\n <label for=\"targetLang\">Target Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"targetLang\"\n [filter]=\"true\"\n [options]=\"languageOptions\"\n formControlName=\"targetLang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div style=\"display: flex; gap: 10px\">\n <div class=\"form-field\">\n <label class=\"block\" pTooltip=\"Image should be handle after upload\">Subir imagen</label>\n <img width=\"218px\" src=\"assets/images/face-3.jpg\" />\n <dc-cropper-modal [imgStorageSettings]=\"storageImgSettings\" (imageUploaded)=\"handleImageUpload($event)\"></dc-cropper-modal>\n </div>\n\n <div style=\"width: 100%\">\n <div class=\"form-field\">\n <label for=\"name\" class=\"block\">Name</label>\n <input pInputText id=\"name\" type=\"text\" formControlName=\"name\" placeholder=\"Enter source name\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"description\" class=\"block\">Description</label>\n <textarea id=\"description\" pTextarea formControlName=\"description\" rows=\"5\" class=\"w-full\" placeholder=\"Enter source content\"> </textarea>\n </div>\n </div>\n </div>\n </form>\n\n <div style=\"display: flex; justify-content: flex-end\">\n <p-button (click)=\"save()\" label=\"Save Course\" [disabled]=\"!form.valid\" icon=\"pi pi-check\" iconPos=\"right\"> </p-button>\n </div>\n </p-card>\n</div>\n", styles: [":host{display:block;padding:1rem}.source-form-card{max-width:800px;margin:0 auto}.form-field{margin-bottom:1.5rem;display:flex;flex-direction:column}.form-field label{margin-bottom:.5rem;font-weight:500;color:#495057}.form-field input,.form-field textarea,.form-field ::ng-deep .p-element{margin-top:.25rem}:host ::ng-deep .p-card .p-card-content>div:last-child{margin-top:1.5rem;display:flex;justify-content:flex-end}:host ::ng-deep .p-card .p-card-header{background-color:#f8f9fa;padding:1rem;border-bottom:1px solid #dee2e6}h3{color:#495057;margin-bottom:1.5rem;text-align:center}\n"] }]
2737
+ }] });
2738
+
2739
+ const COURSES_ROUTES = [
2740
+ {
2741
+ path: '',
2742
+ component: CoursesComponent,
2743
+ children: [
2744
+ {
2745
+ path: '',
2746
+ component: CourseListComponent,
2747
+ },
2748
+ {
2749
+ path: 'details/:id',
2750
+ component: CourseDetailComponent,
2751
+ },
2752
+ {
2753
+ path: 'edit',
2754
+ component: CourseFormComponent,
2755
+ },
2756
+ {
2757
+ path: 'edit/:id',
2758
+ component: CourseFormComponent,
2759
+ },
2760
+ ],
2761
+ },
2762
+ ];
2763
+
2764
+ class CoursesComponent {
2765
+ static { this.routes = COURSES_ROUTES; }
2766
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CoursesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2767
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.6", type: CoursesComponent, isStandalone: true, selector: "app-courses", ngImport: i0, template: "<router-outlet />\n", styles: [":host{display:block;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2768
+ }
2769
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: CoursesComponent, decorators: [{
2770
+ type: Component,
2771
+ args: [{ selector: 'app-courses', imports: [RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<router-outlet />\n", styles: [":host{display:block;height:100%}\n"] }]
2766
2772
  }] });
2767
2773
 
2768
2774
  /*
@@ -2773,5 +2779,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2773
2779
  * Generated bundle index. Do not edit.
2774
2780
  */
2775
2781
 
2776
- export { ComponentBuilder, ComponentWithForm, CourseDetailComponent, CourseFormComponent, CourseListComponent, CourseService, CoursesAdminComponent, CoursesComponent, CoursesService, DCLessonEditorComponent, DCLessonFormComponent, DCLessonListComponent, DCLessonRendererComponent, DcLessonCardComponent, DefaultLessonsService, DynamicComponentBuilders, DynamicComponents, DynamicComponentsService, FlagLanguagePipe, LESSONS_TOKEN, LangCodeDescription, LangCodeDescriptionEs, LangDescTranslationPipe, LessonComponentBuilders, LessonComponentEnum, LessonComponents, LessonDynamicComponent, LessonsAbstractService, NOTION_SERVICE_TOKEN, NotionAbstractService, NotionExportType, SelectorBuilderComponent, SelectorComponent, TextWriterBuiderComponent, TextWriterComponent, TranslationSwitcherBuilderComponent, TranslationSwitcherComponent, getLanguageSimpleAgent, getLessonComponentClass, provideLessonsService, provideNotionService };
2782
+ export { ComponentBuilder, ComponentWithForm, CourseDetailComponent, CourseFormComponent, CourseListComponent, CourseService, CoursesAdminComponent, CoursesComponent, CoursesService, DCLessonEditorComponent, DCLessonFormComponent, DCLessonListComponent, DCLessonRendererComponent, DcLessonCardComponent, DefaultLessonsService, DynamicComponentBuilders, DynamicComponents, DynamicComponentsService, FlagLanguagePipe, LESSONS_TOKEN, LangCodeDescription, LangCodeDescriptionEs, LangDescTranslationPipe, LessonComponentBuilders, LessonComponentEnum, LessonComponents, LessonDynamicComponent, NOTION_SERVICE_TOKEN, NotionAbstractService, NotionExportType, SelectorBuilderComponent, SelectorComponent, TextWriterBuiderComponent, TextWriterComponent, TranslationSwitcherBuilderComponent, TranslationSwitcherComponent, getLanguageSimpleAgent, getLessonComponentClass, provideLessonsService, provideNotionService };
2777
2783
  //# sourceMappingURL=dataclouder-ngx-lessons.mjs.map