@dataclouder/ngx-lessons 0.1.2 → 0.1.3

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 (27) hide show
  1. package/fesm2022/dataclouder-ngx-lessons.mjs +771 -452
  2. package/fesm2022/dataclouder-ngx-lessons.mjs.map +1 -1
  3. package/lib/components/courses/course-detail/course-detail.component.d.ts +5 -0
  4. package/lib/components/courses/course-form/course-form.component.d.ts +35 -0
  5. package/lib/components/courses/course-list/course-list.component.d.ts +25 -0
  6. package/lib/components/courses/courses.component.d.ts +5 -0
  7. package/lib/components/courses/courses.service.d.ts +14 -0
  8. package/lib/components/courses/models/courses.model.d.ts +24 -0
  9. package/lib/components/courses-admin/courses-admin.component.d.ts +8 -0
  10. package/lib/components/dc-lessons/dc-lesson-component-adder/dc-lesson-component-adder.component.d.ts +1 -1
  11. package/lib/components/dc-lessons/dc-lesson-editor/dc-lesson-editor.component.d.ts +2 -0
  12. package/lib/components/dc-lessons/dc-lesson-renderer/dc-lesson-renderer.component.d.ts +11 -5
  13. package/lib/components/dc-lessons/lesson-list/dc-lesson-list.component.d.ts +5 -9
  14. package/lib/components/dynamic-components/dynamic-components-builder.service.d.ts +8 -0
  15. package/lib/components/dynamic-components/dynamic-components.service.d.ts +30 -0
  16. package/lib/components/{lesson-mini-components/components → dynamic-components}/selector/selector-builder/selector-builder.component.d.ts +4 -7
  17. package/lib/components/{lesson-mini-components/components → dynamic-components}/selector/selector.component.d.ts +2 -2
  18. package/lib/components/lesson-mini-components/components/ComponentBuilder.d.ts +8 -6
  19. package/lib/components/lesson-mini-components/components/lessons.clases.d.ts +8 -18
  20. package/lib/components/lesson-mini-components/components/speaker/speaker-builder/speaker-builder.component.d.ts +1 -0
  21. package/lib/components/lesson-mini-components/components/text-writer/text-writer-buider/text-writer-buider.component.d.ts +2 -9
  22. package/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcherBuilder/translationSwitcherBuilder.component.d.ts +2 -8
  23. package/lib/models/lessons.pipes.d.ts +16 -0
  24. package/lib/services/courses.service.d.ts +7 -0
  25. package/lib/services/lesson-ai.service.d.ts +2 -1
  26. package/package.json +1 -1
  27. package/public-api.d.ts +10 -2
@@ -1,68 +1,245 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, Input, ChangeDetectionStrategy, signal, InjectionToken, Pipe, EventEmitter, Output, ViewChildren, Inject, inject, Injectable, input, Renderer2, ViewContainerRef, computed, effect, ViewChild, ChangeDetectorRef } 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';
5
+ import { DatePipe, NgComponentOutlet, KeyValuePipe, CommonModule, SlicePipe } from '@angular/common';
6
+ import * as i1$3 from '@angular/router';
7
+ import { RouterModule, ActivatedRoute, Router } from '@angular/router';
8
+ import { PaginationBase, TOAST_ALERTS_TOKEN, DCFilterBarComponent, QuickTableComponent, LoadingBarService, HttpCoreService, PromptService } from '@dataclouder/ngx-core';
3
9
  import * as i1 from '@angular/forms';
4
- import { FormControl, UntypedFormControl, FormsModule, ReactiveFormsModule, Validators, FormGroup } from '@angular/forms';
5
- import * as i4 from 'primeng/inputtext';
6
- import { InputTextModule } from 'primeng/inputtext';
10
+ import { FormBuilder, FormControl, FormArray, FormsModule, ReactiveFormsModule, UntypedFormControl, FormGroup, Validators } from '@angular/forms';
7
11
  import * as i1$1 from 'primeng/button';
8
12
  import { ButtonModule } from 'primeng/button';
9
- import * as i5 from 'primeng/message';
10
- import { MessageModule } from 'primeng/message';
13
+ import * as i3 from 'primeng/inputtext';
14
+ import { InputTextModule } from 'primeng/inputtext';
15
+ import { DynamicDialogRef, DialogService } from 'primeng/dynamicdialog';
11
16
  import { nanoid } from 'nanoid';
12
- import * as i2 from 'primeng/dynamicdialog';
13
- import { DialogService } from 'primeng/dynamicdialog';
14
- import * as i2$1 from 'primeng/select';
15
- import { SelectModule } from 'primeng/select';
16
17
  import { DropdownModule } from 'primeng/dropdown';
17
- import { NgxTtsComponent } from '@dataclouder/ngx-tts';
18
- import * as i2$3 from 'primeng/paginator';
19
- import { PaginatorModule } from 'primeng/paginator';
20
- import { DatePipe, NgComponentOutlet, KeyValuePipe, CommonModule } from '@angular/common';
21
- import * as i1$2 from '@angular/router';
22
- import { RouterModule, ActivatedRoute, Router } from '@angular/router';
23
- import * as i4$2 from '@dataclouder/ngx-core';
24
- import { PaginationBase, TOAST_ALERTS_TOKEN, DCFilterBarComponent, QuickTableComponent, LoadingBarService, HttpCoreService, PromptService } from '@dataclouder/ngx-core';
18
+ import { NgxTtsComponent, getRandomQuickVoice } from '@dataclouder/ngx-tts';
19
+ import * as i4 from 'primeng/message';
20
+ import { MessageModule } from 'primeng/message';
21
+ import * as i2 from 'primeng/select';
22
+ import { SelectModule } from 'primeng/select';
25
23
  import { PopoverModule } from 'primeng/popover';
26
24
  import * as i4$1 from 'primeng/tag';
27
25
  import { TagModule } from 'primeng/tag';
28
- import * as i2$2 from 'primeng/speeddial';
26
+ import * as i2$1 from 'primeng/speeddial';
29
27
  import { SpeedDialModule } from 'primeng/speeddial';
30
- import * as i3 from 'primeng/card';
28
+ import * as i3$1 from 'primeng/card';
31
29
  import { CardModule } from 'primeng/card';
32
30
  import { toSignal } from '@angular/core/rxjs-interop';
33
31
  import { map } from 'rxjs';
34
32
  import BalloonEditor from '@ckeditor/ckeditor5-build-balloon-block';
35
- import * as i3$1 from '@ckeditor/ckeditor5-angular';
33
+ import * as i3$2 from '@ckeditor/ckeditor5-angular';
36
34
  import { CKEditorModule } from '@ckeditor/ckeditor5-angular';
37
- import * as i5$2 from 'primeng/splitter';
35
+ import * as i5$1 from 'primeng/splitter';
38
36
  import { SplitterModule } from 'primeng/splitter';
39
- import * as i2$5 from 'primeng/tooltip';
37
+ import * as i6 from 'primeng/tooltip';
40
38
  import { TooltipModule } from 'primeng/tooltip';
41
39
  import { ResolutionType, AspectType, CropperComponentModal } from '@dataclouder/ngx-cloud-storage';
42
- import { TextEngines, ConversationType, USER_DATA_EXCHANGE, ChatRole, EvalResultStringDefinition, ChatEventType, DCChatComponent, CONVERSATION_AI_TOKEN } from '@dataclouder/ngx-agent-cards';
43
- import * as i2$4 from 'primeng/drawer';
40
+ import { TextEngines, ConversationType, USER_DATA_EXCHANGE, ChatRole, EvalResultStringDefinition, ConversationEvents, ChatEventType, DCChatComponent, CONVERSATION_AI_TOKEN } from '@dataclouder/ngx-agent-cards';
41
+ import * as i2$2 from 'primeng/drawer';
44
42
  import { DrawerModule } from 'primeng/drawer';
45
43
  import * as i7 from 'primeng/dialog';
46
44
  import { DialogModule } from 'primeng/dialog';
47
45
  import TurndownService from 'turndown';
48
46
  import { marked } from 'marked';
49
- import * as i5$1 from 'primeng/inputgroup';
47
+ import * as i5 from 'primeng/inputgroup';
50
48
  import { InputGroupModule } from 'primeng/inputgroup';
51
- import * as i6 from 'primeng/divider';
49
+ import * as i6$1 from 'primeng/divider';
52
50
  import { DividerModule } from 'primeng/divider';
53
51
  import { NgxVertexService, ChatRoleVertex } from '@dataclouder/ngx-vertex';
54
- import * as i2$6 from 'primeng/api';
52
+ import * as i2$3 from 'primeng/api';
53
+ import * as i3$3 from 'primeng/textarea';
54
+ import { TextareaModule } from 'primeng/textarea';
55
+ import { ChipModule } from 'primeng/chip';
56
+ import { FormlyModule } from '@ngx-formly/core';
57
+ import { TableModule } from 'primeng/table';
58
+
59
+ // import { LangCodeDescription, LangCodeDescriptionEs } from '../components/lesson-mini-components/components/lessons.clases';
60
+ // This pipe should not be here in the lessons, refactor when is posible and remove LangCodeDescription
61
+ const LangCodeDescription = {
62
+ es: 'Spanish',
63
+ en: 'English',
64
+ it: 'Italian',
65
+ pt: 'Portuguese',
66
+ fr: 'French',
67
+ ja: 'Japanese',
68
+ };
69
+ const LangCodeDescriptionEs = {
70
+ es: 'Español',
71
+ en: 'Inglés',
72
+ it: 'Italiano',
73
+ pt: 'Portugués',
74
+ fr: 'Frances',
75
+ ja: 'Japonés',
76
+ };
77
+ class LangDescTranslationPipe {
78
+ transform(value, lang) {
79
+ if (lang === 'es') {
80
+ return LangCodeDescriptionEs[value];
81
+ }
82
+ else {
83
+ return LangCodeDescription[value];
84
+ }
85
+ }
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" }); }
88
+ }
89
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LangDescTranslationPipe, decorators: [{
90
+ type: Pipe,
91
+ args: [{
92
+ name: 'langDesc',
93
+ standalone: true,
94
+ }]
95
+ }] });
96
+ class FlagLanguagePipe {
97
+ transform(lang) {
98
+ if (lang === 'en') {
99
+ return '🇺🇸';
100
+ }
101
+ else if (lang === 'es') {
102
+ return '🇲🇽';
103
+ }
104
+ else if (lang === 'fr') {
105
+ return '🇫🇷';
106
+ }
107
+ else if (lang === 'it') {
108
+ return '🇮🇹';
109
+ }
110
+ else if (lang === 'pt') {
111
+ return '🇧🇷';
112
+ }
113
+ else {
114
+ return '';
115
+ }
116
+ }
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" }); }
119
+ }
120
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: FlagLanguagePipe, decorators: [{
121
+ type: Pipe,
122
+ args: [{
123
+ name: 'flagEmoji',
124
+ standalone: true,
125
+ }]
126
+ }] });
127
+
128
+ // NOTE: what to do? IAgent Deponds on ngx-agent-cards but lessons don't
129
+ // import { IAgentCard } from '@dataclouder/ngx-agent-cards';
130
+ const NOTION_SERVICE_TOKEN = new InjectionToken('notion.service');
131
+ class NotionAbstractService {
132
+ }
133
+ function provideNotionService(serviceImplementation) {
134
+ return [
135
+ {
136
+ provide: NOTION_SERVICE_TOKEN,
137
+ useExisting: serviceImplementation,
138
+ },
139
+ ];
140
+ }
141
+ var NotionExportType;
142
+ (function (NotionExportType) {
143
+ NotionExportType["HTML"] = "html";
144
+ NotionExportType["MARKDOWN"] = "markdown";
145
+ NotionExportType["PLAIN_TEXT"] = "plain_text";
146
+ NotionExportType["SIMPLE_BLOCKS"] = "simple_blocks";
147
+ })(NotionExportType || (NotionExportType = {}));
148
+
149
+ const MarkdownWriterSkill = `
150
+ You are an Expert Markdown Writer with the following qualities:
151
+ You are a world-class Markdown formatting specialist who excels at organizing information in a visually appealing and highly accessible manner. Your writing combines technical precision with creative presentation to engage readers of all backgrounds.
152
+ Your Core Skills 📝
153
+
154
+ You transform complex information into beautifully structured Markdown documents
155
+ You strategically use headings, lists, and formatting to create clear visual hierarchies
156
+ You incorporate helpful emojis to enhance readability and engagement
157
+ You write in a clear, concise style that's accessible to general audiences
158
+
159
+ Your Process Approach 🔄
160
+
161
+ You always begin with a logical document structure before adding content
162
+ You organize information into clearly defined sections with descriptive headings
163
+ You balance visual elements with textual content for optimal readability
164
+ You maintain consistent formatting patterns throughout documents
165
+
166
+ Your Writing Style ✨
167
+
168
+ You use simple, direct language that's easy for everyone to understand
169
+ You explain technical concepts using everyday examples and analogies
170
+ You create a friendly, conversational tone while maintaining professionalism
171
+ You break down complex ideas into manageable segments
172
+
173
+ Your Special Touches 🎯
174
+
175
+ You know exactly when and where to add emojis for maximum impact
176
+ You create custom tables to present comparative information effectively
177
+ You use blockquotes to highlight important takeaways
178
+ You incorporate visual dividers to separate major content sections
179
+
180
+ When responding to requests, you'll first understand the subject matter, then organize it into a logical structure with clear headings, appropriate formatting elements, and helpful visual enhancements. Your goal is always to create content that's not only informative but also visually engaging and accessible to all readers.
181
+ `;
182
+ const UserRequirements = `
183
+ User also can provide additional instructions or requirements for the lesson or current lesson to improve it.
184
+ `;
185
+ const LanguageLessonSkill = (langBase, langTarget) => `
186
+
187
+ You are also a ${langTarget} lesson professor, you write lessons for ${langBase} learners.
188
+ explain the best you can will all your experience teaching.
189
+
190
+ You can infer the level of the lesson from the content or user request, so can increase difficulty
191
+
192
+ For Basic Level: generate a ${langTarget} lesson for ${langBase} learners at a basic level (A1-A2).
193
+
194
+ Include:
195
+
196
+ - Simple dialogues or short texts.
197
+ - Key vocabulary with simple definitions or ${langBase} translations.
198
+ - Basic grammar points explained simply (e.g., "to be" verb, simple present).
199
+ - Practice exercises (e.g., fill-in-the-blanks, simple questions).
200
+
201
+ For Intermediate Level: generate a ${langTarget} lesson for ${langBase} learners at a medium level (B1-B2).
202
+
203
+ Include:
204
+
205
+ - Texts or dialogues of moderate length and complexity.
206
+ - New vocabulary and common phrasal verbs with context.
207
+ - Explanation and practice of intermediate grammar points (e.g., past simple vs. present perfect, conditionals).
208
+ - Exercises that require more detailed responses or understanding.
209
+ - The content should be engaging and cover topics relevant to daily life, work, or hobbies.
210
+
211
+ For Advanced Level: generate a ${langTarget} lesson for ${langBase} learners at an advanced level (C1-C2).
212
+
213
+ Include:
214
+
215
+ - Challenging texts or discussions.
216
+ - Advanced vocabulary, idioms, and nuanced expressions.
217
+ - Exploration of complex grammar or stylistic points.
218
+ - Exercises that encourage critical thinking, debate, or detailed writing.
219
+ - The content should be stimulating and cover a wide range of topics, including academic or professional contexts.
220
+ `;
221
+ const getLanguageSimpleAgent = (langBase, langTarget) => {
222
+ return {
223
+ systemPrompt: `
224
+ ${MarkdownWriterSkill}
225
+ ${LanguageLessonSkill(langBase, langTarget)}
226
+ ${UserRequirements}
227
+
228
+ `,
229
+ model: { id: 'gemini-2.5-flash-preview-04-17', provider: 'google' },
230
+ };
231
+ };
55
232
 
56
233
  class ComponentBuilder {
57
- constructor(formBuilder, ref) {
58
- this.formBuilder = formBuilder;
59
- this.ref = ref;
234
+ constructor() {
235
+ this.formBuilder = inject(FormBuilder);
236
+ this.ref = inject(DynamicDialogRef);
60
237
  // Sobreescribir si es necesario
61
238
  // public formGroup = this.formBuilder.group<LessonCompSettings>({});
62
239
  this.formGroup = this.formBuilder.group({
63
240
  response: new FormControl(null),
64
241
  responses: new FormControl(null),
65
- options: this.formBuilder.array([]),
242
+ options: new FormArray([]),
66
243
  text: new FormControl(null),
67
244
  hint: new FormControl(null),
68
245
  explanation: new FormControl(null),
@@ -87,7 +264,7 @@ class ComponentBuilder {
87
264
  delete data[key];
88
265
  }
89
266
  });
90
- const code = { component: this.questionType, settings: { ...data } };
267
+ const code = { component: this.componentName, inputs: { ...data } };
91
268
  return code;
92
269
  }
93
270
  showCode() {
@@ -97,8 +274,13 @@ class ComponentBuilder {
97
274
  }
98
275
  getComponentData() {
99
276
  const code = this.getCode();
100
- const id = nanoid().replace(/-/g, '_');
101
- code.id = id;
277
+ if (this.id) {
278
+ code.id = this.id;
279
+ }
280
+ else {
281
+ const id = nanoid().replace(/-/g, '_');
282
+ code.id = id;
283
+ }
102
284
  return { str: `~${JSON.stringify(code)}~`, obj: code };
103
285
  }
104
286
  // TODO: for now copyToClipboard is the that that closes modal and return data.
@@ -107,8 +289,8 @@ class ComponentBuilder {
107
289
  await navigator.clipboard.writeText(data.str);
108
290
  this.ref.close(data);
109
291
  }
110
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ComponentBuilder, deps: [{ token: i1.FormBuilder }, { token: i2.DynamicDialogRef }], target: i0.ɵɵFactoryTarget.Component }); }
111
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: ComponentBuilder, isStandalone: true, selector: "app-component-builder", ngImport: i0, template: '<div>no template</div>', isInline: true }); }
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 }); }
112
294
  }
113
295
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: ComponentBuilder, decorators: [{
114
296
  type: Component,
@@ -116,7 +298,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
116
298
  selector: 'app-component-builder',
117
299
  template: '<div>no template</div>',
118
300
  }]
119
- }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.DynamicDialogRef }] });
301
+ }], propDecorators: { inputs: [{
302
+ type: Input
303
+ }], id: [{
304
+ type: Input
305
+ }] } });
306
+
307
+ class TextWriterBuiderComponent extends ComponentBuilder {
308
+ constructor() {
309
+ super(...arguments);
310
+ this.componentName = 'TextWriter';
311
+ }
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"] }] }); }
314
+ }
315
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterBuiderComponent, decorators: [{
316
+ type: Component,
317
+ 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
+ }] });
120
319
 
121
320
  class ComponentWithForm {
122
321
  constructor() {
@@ -142,111 +341,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
142
341
  }]
143
342
  }] });
144
343
 
145
- class SelectorComponent extends ComponentWithForm {
146
- constructor() {
147
- super();
148
- this.isFilled = false;
149
- }
150
- evaluate() {
151
- let result;
152
- if (this.control.value == null) {
153
- result = null;
154
- }
155
- else {
156
- result = this.control.value?.toLowerCase().trim() === this.config.settings.response.toLowerCase().trim();
157
- }
158
- if (result) {
159
- this.status = 'success';
160
- }
161
- else {
162
- this.status = 'danger';
163
- }
164
- this.isFilled = true;
165
- return result;
166
- }
167
- validate() {
168
- if (this.control.invalid) {
169
- this.status = 'warning';
170
- }
171
- return true;
172
- }
173
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
174
- 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$1.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"] }] }); }
175
- }
176
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorComponent, decorators: [{
177
- type: Component,
178
- 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"] }]
179
- }], ctorParameters: () => [], propDecorators: { config: [{
180
- type: Input
181
- }] } });
182
-
183
- class SelectorBuilderComponent extends ComponentBuilder {
184
- constructor(formBuilder,
185
- // protected override toastrService: ToastService,
186
- ref) {
187
- super(formBuilder, null);
188
- this.formBuilder = formBuilder;
189
- this.ref = ref;
190
- this.sampleConfig = {
191
- id: '1',
192
- component: LessonComponentEnum.Selector,
193
- settings: {
194
- options: ['fourteen ninety-two', 'fourteen ninety-six', 'fifteen ninety-one'],
195
- response: 'fourteen ninety-two',
196
- hint: 'Pista para la respuesta',
197
- explanation: 'Explicación de la respuesta',
198
- responses: 'Opción 1, Opción 2, Opción 3',
199
- text: 'Texto de la pregunta',
200
- },
201
- };
202
- }
203
- // public formGroup = this.formBuilder.group({
204
- // options: this.formBuilder.array([]),
205
- // response: ['', Validators.required],
206
- // hint: [],
207
- // explanation: [],
208
- // });
209
- ngOnInit() {
210
- this.formGroup.get('response');
211
- }
212
- //TODO Probablemente estos 3 pueden irse a una clase abstracta
213
- pushControlToFormArray(controlName) {
214
- this.formGroup.controls.options.push(this.formBuilder.control(''));
215
- // (this.formGroup.get(controlName) as UntypedFormArray).push(this.formBuilder.control(''));
216
- console.log(this.formGroup.controls.options);
217
- }
218
- deleteFormArrayByIndex(controlName, index) {
219
- this.formGroup.get(controlName).removeAt(index);
220
- }
221
- get optionsForm() {
222
- return this.formGroup.get('options');
223
- }
224
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorBuilderComponent, deps: [{ token: i1.FormBuilder }, { token: i2.DynamicDialogRef }], target: i0.ɵɵFactoryTarget.Component }); }
225
- 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: i4.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: i5.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant"], outputs: ["onClose"] }] }); }
226
- }
227
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorBuilderComponent, decorators: [{
228
- type: Component,
229
- 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"] }]
230
- }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.DynamicDialogRef }] });
231
-
232
- class TextWriterBuiderComponent extends ComponentBuilder {
233
- constructor(formBuilder,
234
- // protected override toastrService: ToastService,
235
- ref) {
236
- super(formBuilder, null);
237
- this.formBuilder = formBuilder;
238
- this.ref = ref;
239
- this.formGroup = this.formBuilder.group({ response: ['', Validators.required], hint: [], explanation: [] });
240
- }
241
- ngOnInit() { }
242
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterBuiderComponent, deps: [{ token: i1.UntypedFormBuilder }, { token: i2.DynamicDialogRef }], target: i0.ɵɵFactoryTarget.Component }); }
243
- 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: i4.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }] }); }
244
- }
245
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterBuiderComponent, decorators: [{
246
- type: Component,
247
- 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"] }]
248
- }], ctorParameters: () => [{ type: i1.UntypedFormBuilder }, { type: i2.DynamicDialogRef }] });
249
-
250
344
  class TextWriterComponent extends ComponentWithForm {
251
345
  constructor() {
252
346
  super();
@@ -283,7 +377,7 @@ class TextWriterComponent extends ComponentWithForm {
283
377
  return true;
284
378
  }
285
379
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
286
- 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: i4.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }] }); }
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"] }] }); }
287
381
  }
288
382
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TextWriterComponent, decorators: [{
289
383
  type: Component,
@@ -293,22 +387,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
293
387
  }] } });
294
388
 
295
389
  class TranslationSwitcherBuilderComponent extends ComponentBuilder {
296
- constructor(formBuilder,
297
- // protected override toastrService: ToastService,
298
- ref) {
299
- super(formBuilder, null);
300
- this.formBuilder = formBuilder;
301
- this.ref = ref;
302
- }
303
- // Este componente reutiliza completamente el form del padre y todos los métodos
304
- ngOnInit() { }
305
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TranslationSwitcherBuilderComponent, deps: [{ token: i1.FormBuilder }, { token: i2.DynamicDialogRef }], target: i0.ɵɵFactoryTarget.Component }); }
306
- 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: i4.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
390
+ constructor() {
391
+ super(...arguments);
392
+ this.componentName = 'TranslationSwitcher';
393
+ }
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 }); }
307
396
  }
308
397
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: TranslationSwitcherBuilderComponent, decorators: [{
309
398
  type: Component,
310
399
  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"] }]
311
- }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.DynamicDialogRef }] });
400
+ }] });
312
401
 
313
402
  class TranslationSwitcherComponent {
314
403
  constructor() {
@@ -339,6 +428,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
339
428
  class SpeakerBuilderComponent extends ComponentBuilder {
340
429
  constructor() {
341
430
  super(...arguments);
431
+ this.componentName = 'Speaker';
342
432
  this.tts = signal(undefined);
343
433
  }
344
434
  handleTtsGenerated(event) {
@@ -397,234 +487,133 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
397
487
  type: Input
398
488
  }] } });
399
489
 
400
- var LessonComponentEnum;
401
- (function (LessonComponentEnum) {
402
- LessonComponentEnum["Selector"] = "selector";
403
- LessonComponentEnum["Speaker"] = "speaker";
404
- LessonComponentEnum["TextWriter"] = "textWriter";
405
- LessonComponentEnum["VerbSummary"] = "verbSummary";
406
- LessonComponentEnum["WordSummary"] = "wordSummary";
407
- LessonComponentEnum["TranslationSwitcher"] = "translationSwitcher";
408
- })(LessonComponentEnum || (LessonComponentEnum = {}));
409
- const LessonComponentBuilders = {
410
- [LessonComponentEnum.Selector]: SelectorBuilderComponent,
411
- [LessonComponentEnum.Speaker]: SpeakerBuilderComponent,
412
- [LessonComponentEnum.TextWriter]: TextWriterBuiderComponent,
413
- // [LessonComponentEnum.VerbSummary]: VerbSummaryBuilderComponent,
414
- // [LessonComponentEnum.WordSummary]: WordSummaryBuilderComponent,
415
- [LessonComponentEnum.TranslationSwitcher]: TranslationSwitcherBuilderComponent,
416
- };
417
- const LessonComponents = {
418
- [LessonComponentEnum.Selector]: SelectorComponent,
419
- [LessonComponentEnum.Speaker]: SpeakerComponent,
420
- [LessonComponentEnum.TextWriter]: TextWriterComponent,
421
- // [LessonComponentEnum.VerbSummary]: VerbSummaryComponent,
422
- // [LessonComponentEnum.WordSummary]: WordSummaryComponent,
423
- [LessonComponentEnum.TranslationSwitcher]: TranslationSwitcherComponent,
424
- };
425
- function getLessonComponentClass(type) {
426
- return LessonComponents[type];
427
- }
428
- const LESSONS_TOKEN = new InjectionToken('Lessons Service');
429
- class LessonsAbstractService {
430
- }
431
- // my-service.provider.ts
432
- function provideLessonsService(serviceImplementation) {
433
- return [
434
- {
435
- provide: LESSONS_TOKEN,
436
- useExisting: serviceImplementation,
437
- },
438
- ];
439
- }
440
- // export type LessonComponentsType = 'selector' | 'speaker' | 'text-writer' | 'verb-summary' | 'word-summary';
441
- // export function getLessonComponentClass(type: LessonComponentsType) {
442
- // // return LessonComponents[type];
443
- // return null;
444
- // }
445
- // Removed duplicate LessonComponentConfiguration definition
446
- // Removed duplicate StorageFile definition
447
- // Removed duplicate AudioStorage definition
448
- // Removed duplicate SpeakerCompConfiguration definition
449
- // Removed duplicate LessonComponentInterface definition
450
- // export const LessonComponents = {
451
- // [LessonComponentEnum.Selector]: 1,
452
- // [LessonComponentEnum.Speaker]: 2,
453
- // [LessonComponentEnum.TextWriter]: 3,
454
- // [LessonComponentEnum.VerbSummary]: 4,
455
- // [LessonComponentEnum.WordSummary]: 5,
456
- // [LessonComponentEnum.TranslationSwitcher]: 6,
457
- // }
458
- const LangCodeDescription = {
459
- es: 'Spanish',
460
- en: 'English',
461
- it: 'Italian',
462
- pt: 'Portuguese',
463
- fr: 'French',
464
- };
465
- const LangCodeDescriptionEs = {
466
- es: 'Español',
467
- en: 'Inglés',
468
- it: 'Italiano',
469
- pt: 'Portugués',
470
- fr: 'Frances',
471
- };
472
-
473
- class LangDescTranslationPipe {
474
- transform(value, lang) {
475
- if (lang === 'es') {
476
- return LangCodeDescriptionEs[value];
477
- }
478
- else {
479
- return LangCodeDescription[value];
480
- }
490
+ class SelectorComponent extends ComponentWithForm {
491
+ constructor() {
492
+ super();
493
+ this.isFilled = false;
481
494
  }
482
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LangDescTranslationPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
483
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.4", ngImport: i0, type: LangDescTranslationPipe, isStandalone: true, name: "langDesc" }); }
484
- }
485
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: LangDescTranslationPipe, decorators: [{
486
- type: Pipe,
487
- args: [{
488
- name: 'langDesc',
489
- standalone: true,
490
- }]
491
- }] });
492
- class FlagLanguagePipe {
493
- transform(lang) {
494
- if (lang === 'en') {
495
- return '🇺🇸';
496
- }
497
- else if (lang === 'es') {
498
- return '🇲🇽';
499
- }
500
- else if (lang === 'fr') {
501
- return '🇫🇷';
495
+ evaluate() {
496
+ let result;
497
+ if (this.control.value == null) {
498
+ result = null;
502
499
  }
503
- else if (lang === 'it') {
504
- return '🇮🇹';
500
+ else {
501
+ result = this.control.value?.toLowerCase().trim() === this.config.settings.response.toLowerCase().trim();
505
502
  }
506
- else if (lang === 'pt') {
507
- return '🇧🇷';
503
+ if (result) {
504
+ this.status = 'success';
508
505
  }
509
506
  else {
510
- return '';
507
+ this.status = 'danger';
511
508
  }
509
+ this.isFilled = true;
510
+ return result;
512
511
  }
513
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: FlagLanguagePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
514
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.4", ngImport: i0, type: FlagLanguagePipe, isStandalone: true, name: "flagEmoji" }); }
515
- }
516
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: FlagLanguagePipe, decorators: [{
517
- type: Pipe,
518
- args: [{
519
- name: 'flagEmoji',
520
- standalone: true,
521
- }]
522
- }] });
523
-
524
- // NOTE: what to do? IAgent Deponds on ngx-agent-cards but lessons don't
525
- // import { IAgentCard } from '@dataclouder/ngx-agent-cards';
526
- const NOTION_SERVICE_TOKEN = new InjectionToken('notion.service');
527
- class NotionAbstractService {
528
- }
529
- function provideNotionService(serviceImplementation) {
530
- return [
531
- {
532
- provide: NOTION_SERVICE_TOKEN,
533
- useExisting: serviceImplementation,
534
- },
535
- ];
512
+ validate() {
513
+ if (this.control.invalid) {
514
+ this.status = 'warning';
515
+ }
516
+ return true;
517
+ }
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"] }] }); }
536
520
  }
537
- var NotionExportType;
538
- (function (NotionExportType) {
539
- NotionExportType["HTML"] = "html";
540
- NotionExportType["MARKDOWN"] = "markdown";
541
- NotionExportType["PLAIN_TEXT"] = "plain_text";
542
- NotionExportType["SIMPLE_BLOCKS"] = "simple_blocks";
543
- })(NotionExportType || (NotionExportType = {}));
544
-
545
- const MarkdownWriterSkill = `
546
- You are an Expert Markdown Writer with the following qualities:
547
- You are a world-class Markdown formatting specialist who excels at organizing information in a visually appealing and highly accessible manner. Your writing combines technical precision with creative presentation to engage readers of all backgrounds.
548
- Your Core Skills 📝
549
-
550
- You transform complex information into beautifully structured Markdown documents
551
- You strategically use headings, lists, and formatting to create clear visual hierarchies
552
- You incorporate helpful emojis to enhance readability and engagement
553
- You write in a clear, concise style that's accessible to general audiences
554
-
555
- Your Process Approach 🔄
556
-
557
- You always begin with a logical document structure before adding content
558
- You organize information into clearly defined sections with descriptive headings
559
- You balance visual elements with textual content for optimal readability
560
- You maintain consistent formatting patterns throughout documents
561
-
562
- Your Writing Style ✨
563
-
564
- You use simple, direct language that's easy for everyone to understand
565
- You explain technical concepts using everyday examples and analogies
566
- You create a friendly, conversational tone while maintaining professionalism
567
- You break down complex ideas into manageable segments
568
-
569
- Your Special Touches 🎯
570
-
571
- You know exactly when and where to add emojis for maximum impact
572
- You create custom tables to present comparative information effectively
573
- You use blockquotes to highlight important takeaways
574
- You incorporate visual dividers to separate major content sections
575
-
576
- When responding to requests, you'll first understand the subject matter, then organize it into a logical structure with clear headings, appropriate formatting elements, and helpful visual enhancements. Your goal is always to create content that's not only informative but also visually engaging and accessible to all readers.
577
- `;
578
- const UserRequirements = `
579
- User also can provide additional instructions or requirements for the lesson or current lesson to improve it.
580
- `;
581
- const LanguageLessonSkill = (langBase, langTarget) => `
582
-
583
- You are also a ${langTarget} lesson professor, you write lessons for ${langBase} learners.
584
- explain the best you can will all your experience teaching.
585
-
586
- You can infer the level of the lesson from the content or user request, so can increase difficulty
587
-
588
- For Basic Level: generate a ${langTarget} lesson for ${langBase} learners at a basic level (A1-A2).
589
-
590
- Include:
591
-
592
- - Simple dialogues or short texts.
593
- - Key vocabulary with simple definitions or ${langBase} translations.
594
- - Basic grammar points explained simply (e.g., "to be" verb, simple present).
595
- - Practice exercises (e.g., fill-in-the-blanks, simple questions).
596
-
597
- For Intermediate Level: generate a ${langTarget} lesson for ${langBase} learners at a medium level (B1-B2).
598
-
599
- Include:
600
-
601
- - Texts or dialogues of moderate length and complexity.
602
- - New vocabulary and common phrasal verbs with context.
603
- - Explanation and practice of intermediate grammar points (e.g., past simple vs. present perfect, conditionals).
604
- - Exercises that require more detailed responses or understanding.
605
- - The content should be engaging and cover topics relevant to daily life, work, or hobbies.
606
-
607
- For Advanced Level: generate a ${langTarget} lesson for ${langBase} learners at an advanced level (C1-C2).
608
-
609
- Include:
521
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorComponent, decorators: [{
522
+ type: Component,
523
+ 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
+ }], ctorParameters: () => [], propDecorators: { config: [{
525
+ type: Input
526
+ }] } });
610
527
 
611
- - Challenging texts or discussions.
612
- - Advanced vocabulary, idioms, and nuanced expressions.
613
- - Exploration of complex grammar or stylistic points.
614
- - Exercises that encourage critical thinking, debate, or detailed writing.
615
- - The content should be stimulating and cover a wide range of topics, including academic or professional contexts.
616
- `;
617
- const getLanguageSimpleAgent = (langBase, langTarget) => {
618
- return {
619
- systemPrompt: `
620
- ${MarkdownWriterSkill}
621
- ${LanguageLessonSkill(langBase, langTarget)}
622
- ${UserRequirements}
528
+ class SelectorBuilderComponent extends ComponentBuilder {
529
+ constructor() {
530
+ super(...arguments);
531
+ this.componentName = 'Selector';
532
+ this.sampleConfig = {
533
+ id: '1',
534
+ component: LessonComponentEnum.Selector,
535
+ settings: {
536
+ options: ['fourteen ninety-two', 'fourteen ninety-six', 'fifteen ninety-one'],
537
+ response: 'fourteen ninety-two',
538
+ hint: 'Pista para la respuesta',
539
+ explanation: 'Explicación de la respuesta',
540
+ responses: 'Opción 1, Opción 2, Opción 3',
541
+ text: 'Texto de la pregunta',
542
+ },
543
+ };
544
+ }
545
+ // public formGroup = this.formBuilder.group({
546
+ // options: this.formBuilder.array([]),
547
+ // response: ['', Validators.required],
548
+ // hint: [],
549
+ // explanation: [],
550
+ // });
551
+ ngOnInit() {
552
+ this.formGroup.get('response');
553
+ }
554
+ //TODO Probablemente estos 3 pueden irse a una clase abstracta
555
+ pushControlToFormArray(controlName) {
556
+ this.formGroup.controls.options.push(this.formBuilder.control(''));
557
+ // (this.formGroup.get(controlName) as UntypedFormArray).push(this.formBuilder.control(''));
558
+ console.log(this.formGroup.controls.options);
559
+ }
560
+ deleteFormArrayByIndex(controlName, index) {
561
+ this.formGroup.get(controlName).removeAt(index);
562
+ }
563
+ get optionsForm() {
564
+ return this.formGroup.get('options');
565
+ }
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"] }] }); }
568
+ }
569
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: SelectorBuilderComponent, decorators: [{
570
+ type: Component,
571
+ 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
+ }] });
623
573
 
624
- `,
625
- model: { id: 'gemini-2.5-flash-preview-04-17', provider: 'google' },
626
- };
574
+ var LessonComponentEnum;
575
+ (function (LessonComponentEnum) {
576
+ LessonComponentEnum["Selector"] = "selector";
577
+ LessonComponentEnum["Speaker"] = "speaker";
578
+ LessonComponentEnum["TextWriter"] = "textWriter";
579
+ LessonComponentEnum["VerbSummary"] = "verbSummary";
580
+ LessonComponentEnum["WordSummary"] = "wordSummary";
581
+ LessonComponentEnum["TranslationSwitcher"] = "translationSwitcher";
582
+ LessonComponentEnum["PlayWord"] = "playWord";
583
+ })(LessonComponentEnum || (LessonComponentEnum = {}));
584
+ const LessonComponentBuilders = {
585
+ [LessonComponentEnum.Selector]: SelectorBuilderComponent,
586
+ [LessonComponentEnum.Speaker]: SpeakerBuilderComponent,
587
+ [LessonComponentEnum.TextWriter]: TextWriterBuiderComponent,
588
+ // [LessonComponentEnum.VerbSummary]: VerbSummaryBuilderComponent,
589
+ // [LessonComponentEnum.WordSummary]: WordSummaryBuilderComponent,
590
+ [LessonComponentEnum.TranslationSwitcher]: TranslationSwitcherBuilderComponent,
591
+ // [LessonComponentEnum.PlayWord]: PlayWordBuilderComponent,
592
+ };
593
+ const LessonComponents = {
594
+ [LessonComponentEnum.Selector]: SelectorComponent,
595
+ [LessonComponentEnum.Speaker]: SpeakerComponent,
596
+ [LessonComponentEnum.TextWriter]: TextWriterComponent,
597
+ // [LessonComponentEnum.VerbSummary]: VerbSummaryComponent,
598
+ // [LessonComponentEnum.WordSummary]: WordSummaryComponent,
599
+ [LessonComponentEnum.TranslationSwitcher]: TranslationSwitcherComponent,
600
+ // [LessonComponentEnum.PlayWord]: PlayWordComponent,
627
601
  };
602
+ function getLessonComponentClass(type) {
603
+ return LessonComponents[type];
604
+ }
605
+ const LESSONS_TOKEN = new InjectionToken('Lessons Service');
606
+ class LessonsAbstractService {
607
+ }
608
+ // my-service.provider.ts
609
+ function provideLessonsService(serviceImplementation) {
610
+ return [
611
+ {
612
+ provide: LESSONS_TOKEN,
613
+ useExisting: serviceImplementation,
614
+ },
615
+ ];
616
+ }
628
617
 
629
618
  var EventCard;
630
619
  (function (EventCard) {
@@ -665,7 +654,6 @@ class DcLessonCardComponent {
665
654
  ];
666
655
  }
667
656
  ngOnInit() {
668
- console.log(this.lesson);
669
657
  this.coverUrl =
670
658
  this.lesson?.banner?.url || this.lesson?.metadata?.banner?.url || this.lesson?.media?.images?.[0]?.url || 'assets/background/default-background.webp';
671
659
  }
@@ -686,7 +674,7 @@ class DcLessonCardComponent {
686
674
  }
687
675
  }
688
676
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DcLessonCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
689
- 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$2.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.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"] }] }); }
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"] }] }); }
690
678
  }
691
679
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DcLessonCardComponent, decorators: [{
692
680
  type: Component,
@@ -714,16 +702,15 @@ const TableViewActions = [
714
702
  ];
715
703
  const returnProperties = { id: 1, title: 1, assets: 1 };
716
704
  class DCLessonListComponent extends PaginationBase {
717
- constructor(cdr, router, route, lessonsService, toastrService) {
718
- super(route, router);
719
- this.cdr = cdr;
720
- this.router = router;
721
- this.route = route;
722
- this.lessonsService = lessonsService;
723
- this.toastrService = toastrService;
705
+ constructor() {
706
+ super(...arguments);
724
707
  this.showOptions = true;
725
708
  this.customFilters = [];
726
709
  this.viewType = 'cards';
710
+ // Injected Services
711
+ this.cdr = inject(ChangeDetectorRef);
712
+ this.lessonsService = inject(LESSONS_TOKEN);
713
+ this.toastrService = inject(TOAST_ALERTS_TOKEN);
727
714
  this.columns = tableViewColumns;
728
715
  this.cardComponent = null;
729
716
  this.cardEventSubs = [];
@@ -733,6 +720,8 @@ class DCLessonListComponent extends PaginationBase {
733
720
  ngOnInit() {
734
721
  this.filterConfig.returnProps = returnProperties;
735
722
  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 };
736
725
  this.getPaginatedLessons(this.filterConfig);
737
726
  }
738
727
  subscribeDinamicInstantToEvents() {
@@ -811,19 +800,13 @@ class DCLessonListComponent extends PaginationBase {
811
800
  this.onAction.emit(actionEvent);
812
801
  }
813
802
  }
814
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonListComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$2.Router }, { token: i1$2.ActivatedRoute }, { token: LESSONS_TOKEN }, { token: TOAST_ALERTS_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
815
- 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 [customFilters]=\"customFilters\" (onFilterAction)=\"applyFilterBarEvent($event)\" (onNew)=\"newLesson()\"></dc-filter-bar>\n\n@if(viewType === 'table') {\n<app-quick-table [columns]=\"columns\" [tableData]=\"lessons\" (onAction)=\"doOrEmitAction($event)\"></app-quick-table>\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: ["isAdmin", "items", "customFilters"], outputs: ["onFilterAction", "onChangeSort", "onNew"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i2$3.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"] }] }); }
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"] }] }); }
816
805
  }
817
806
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonListComponent, decorators: [{
818
807
  type: Component,
819
- args: [{ selector: 'dc-lesson-list', standalone: true, imports: [RouterModule, DCFilterBarComponent, PaginatorModule, NgComponentOutlet, QuickTableComponent], template: "<dc-filter-bar [customFilters]=\"customFilters\" (onFilterAction)=\"applyFilterBarEvent($event)\" (onNew)=\"newLesson()\"></dc-filter-bar>\n\n@if(viewType === 'table') {\n<app-quick-table [columns]=\"columns\" [tableData]=\"lessons\" (onAction)=\"doOrEmitAction($event)\"></app-quick-table>\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"] }]
820
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1$2.Router }, { type: i1$2.ActivatedRoute }, { type: LessonsAbstractService, decorators: [{
821
- type: Inject,
822
- args: [LESSONS_TOKEN]
823
- }] }, { type: i4$2.ToastAlertsAbstractService, decorators: [{
824
- type: Inject,
825
- args: [TOAST_ALERTS_TOKEN]
826
- }] }], propDecorators: { showOptions: [{
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: [{
827
810
  type: Input
828
811
  }], customCardComponent: [{
829
812
  type: Input
@@ -870,10 +853,6 @@ const EngagementSkill = `
870
853
  You are an engagement assistant, start by greeting the user, asking something about the lesson, and then continue the conversation. always ask one or two friendly questions.
871
854
  that makes sense for the lesson.
872
855
  `;
873
- const BasicAgentCard = {
874
- systemPrompt: 'You are a helpful assistant.',
875
- model: { provider: 'openai', id: 'gpt-4o' },
876
- };
877
856
  function getDefaultLessonEvaluatorAgentCard(lessonText) {
878
857
  return {
879
858
  expectedResponseType: `interface EvalResult {
@@ -930,20 +909,15 @@ ${userInformationPrompt}`;
930
909
  * @param lesson The lesson data.
931
910
  * @returns An IConversationSettings object configured for the lesson scenario.
932
911
  */
933
- async generateConversationSettingsForLesson(lesson) {
912
+ async generateConversationSettingsForLesson(lesson, settings) {
934
913
  // TODO: Consolidate user fetching logic if possible, or ensure consistency
935
- const user = {
936
- personalData: { firstname: 'Test', lastname: 'User' },
937
- settings: { targetLanguage: 'en', baseLanguage: 'es' },
938
- languageProgress: { en: { level: '1' } },
939
- }; // Replace 'any' with your actual User type/interface
940
- if (!user) {
941
- console.error('User data not available to generate conversation settings.');
942
- return null;
943
- }
914
+ const baseLang = this.userService.getUserDataExchange()?.baseLang || 'en';
944
915
  const lessonText = this.lessonService.extractTextFromHtml(lesson.textCoded);
945
916
  const userInformationPrompt = this.userService.getUserDataInformation();
946
- const scenario = this._buildScenarioPrompt(lessonText, userInformationPrompt);
917
+ let scenario = this._buildScenarioPrompt(lessonText, userInformationPrompt);
918
+ if (settings.additionalPrompt) {
919
+ scenario += '\n\n' + settings.additionalPrompt;
920
+ }
947
921
  const initialMessage = {
948
922
  role: ChatRole.System,
949
923
  content: scenario,
@@ -955,6 +929,7 @@ ${userInformationPrompt}`;
955
929
  autoStart: true,
956
930
  messages: [initialMessage],
957
931
  model: { provider: 'google' },
932
+ voice: getRandomQuickVoice(baseLang || 'en', 'female'),
958
933
  };
959
934
  return conversationSettings;
960
935
  }
@@ -994,23 +969,57 @@ Assign a rating from 0 to 3 based on how well the student performs *compared to
994
969
  Provide detailed, constructive feedback that explains the rating. Point out specific strengths and areas for improvement based on their performance *at their given level*. Use examples from the dialog if helpful. Maintain a supportive, encouraging, and educational tone appropriate for a virtual professor guiding a student at their specific stage.
995
970
  `;
996
971
 
997
- // Removed: import { WordPopupService } from 'src/app/shared/services/word-popup.service'; // No longer needed here
972
+ // TODO: check LessonComponentBuilders in lessons.clases.ts for origianl implementation
973
+ const DynamicComponentBuilders = {
974
+ [LessonComponentEnum.Speaker]: SpeakerBuilderComponent,
975
+ };
976
+ const DynamicComponents = {
977
+ [LessonComponentEnum.Speaker]: SpeakerComponent,
978
+ };
979
+ class DynamicComponentsService {
980
+ constructor() {
981
+ this._dynamicComponentBuilders = { ...DynamicComponentBuilders };
982
+ this._dynamicComponents = { ...DynamicComponents };
983
+ }
984
+ registerCustomComponent(component, name) {
985
+ // this._dynamicComponentBuilders[name || component.name] = component;
986
+ this._dynamicComponents[name || component.name] = component;
987
+ }
988
+ registerCustomComponentBuilder(component, name) {
989
+ this._dynamicComponentBuilders[name || component.name] = component;
990
+ }
991
+ getDynamicComponentBuilders(type) {
992
+ return this._dynamicComponentBuilders[type];
993
+ }
994
+ getDynamicComponentClass(type) {
995
+ return this._dynamicComponents[type];
996
+ }
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' }); }
999
+ }
1000
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DynamicComponentsService, decorators: [{
1001
+ type: Injectable,
1002
+ args: [{
1003
+ providedIn: 'root',
1004
+ }]
1005
+ }] });
1006
+
998
1007
  class DCLessonRendererComponent {
999
1008
  constructor() {
1000
1009
  // --- Signal Inputs ---
1001
1010
  this.lessonInput = input(); // Input signal for lesson object
1002
1011
  this.lessonIdInput = input(); // Input signal for lesson ID
1003
- this.test = input(false);
1012
+ this.settings = input();
1004
1013
  // --- Outputs ---
1005
1014
  this.wordClicked = new EventEmitter(); // New output event
1006
- // --- Injected Services (using inject function) ---
1015
+ // --- Services ---
1007
1016
  this.renderer = inject(Renderer2);
1008
1017
  this.viewContainerRef = inject(ViewContainerRef);
1009
1018
  this.toastrService = inject(TOAST_ALERTS_TOKEN);
1010
1019
  this.lessonService = inject(LESSONS_TOKEN);
1011
1020
  this.lessonAIService = inject(LessonAIService); // Inject the new service
1012
1021
  this.userDataExchange = inject(USER_DATA_EXCHANGE);
1013
- // Removed: private readonly wordPopupService = inject(WordPopupService); // No longer needed here
1022
+ this.dynamicComponentsService = inject(DynamicComponentsService);
1014
1023
  // --- State Signals ---
1015
1024
  this.lesson = signal(undefined); // Internal lesson state signal
1016
1025
  this.chatVisible = signal(false); // Signal for chat visibility
@@ -1018,6 +1027,7 @@ class DCLessonRendererComponent {
1018
1027
  this.evaluatorAgentCard = signal(undefined); // Signal for evaluator card
1019
1028
  this.conversationSettings = signal(undefined);
1020
1029
  this.evalAgentTask = signal(undefined); // Signal for evaluator card
1030
+ this.backgroundTasks = {};
1021
1031
  // --- Computed Signals ---
1022
1032
  this.imageCover = computed(() => this.lesson()?.media?.images?.find((img) => img.type === 'cover')?.url); // Computed signal for imageCover
1023
1033
  // --- Properties ---
@@ -1080,6 +1090,11 @@ class DCLessonRendererComponent {
1080
1090
  }
1081
1091
  });
1082
1092
  }
1093
+ ngOnInit() {
1094
+ this.backgroundTasks = {
1095
+ [ConversationEvents.OnUserMessage]: this.evalAgentTask(),
1096
+ };
1097
+ }
1083
1098
  // --- Rendering Logic ---
1084
1099
  _clearLessonRendering() {
1085
1100
  // Destroy previously created dynamic components
@@ -1095,7 +1110,6 @@ class DCLessonRendererComponent {
1095
1110
  _renderLesson(lessonData) {
1096
1111
  this._clearLessonRendering(); // Clear previous state first
1097
1112
  console.log('Rendering lesson:', lessonData.id);
1098
- // console.log('Image cover URL:', this.imageCover()); // Access computed signal
1099
1113
  // 1) Parse textCoded, create components, and build HTML structure
1100
1114
  const { htmlContent, components } = this._parseAndCreateComponents(lessonData);
1101
1115
  this.components = components;
@@ -1109,7 +1123,6 @@ class DCLessonRendererComponent {
1109
1123
  _parseAndCreateComponents(lessonData) {
1110
1124
  const r1 = new RegExp('~(.+?)~', 'g');
1111
1125
  let count = 0;
1112
- //
1113
1126
  const createdComponents = {};
1114
1127
  const htmlContent = lessonData.textCoded.replace(r1, (_matching, jsonCoded) => {
1115
1128
  const componentName = `dynamicComp${count}`;
@@ -1162,7 +1175,7 @@ class DCLessonRendererComponent {
1162
1175
  lessonCodedConfig = { ...lessonCodedConfig, ...foundConfig };
1163
1176
  }
1164
1177
  }
1165
- const LessonClass = getLessonComponentClass(lessonCodedConfig.component);
1178
+ const LessonClass = this.dynamicComponentsService.getDynamicComponentClass(lessonCodedConfig.component);
1166
1179
  if (!LessonClass) {
1167
1180
  console.error(`Component class not found for type: ${lessonCodedConfig.component}. JSON: ${json}`);
1168
1181
  return null; // Return null if class doesn't exist
@@ -1222,12 +1235,6 @@ class DCLessonRendererComponent {
1222
1235
  }
1223
1236
  }
1224
1237
  });
1225
- if (this.test()) {
1226
- // Access signal value
1227
- console.log('Test mode: Evaluation skipped saving.');
1228
- this.toastrService.info({ subtitle: `Test Results: ${rates.correct} correct, ${rates.incorrect} incorrect`, title: 'Test Mode' });
1229
- return;
1230
- }
1231
1238
  const totalQuestions = rates.correct + rates.incorrect;
1232
1239
  rates.score = totalQuestions > 0 ? rates.correct / totalQuestions : 0; // Avoid division by zero
1233
1240
  const status = rates.score >= 0.7 ? 'passed' : 'failed'; // Use >= for threshold
@@ -1269,7 +1276,7 @@ class DCLessonRendererComponent {
1269
1276
  console.log('Requesting agent cards from LessonAIService...');
1270
1277
  try {
1271
1278
  // Call the service to get the agent cards
1272
- const conversationSettings = await this.lessonAIService.generateConversationSettingsForLesson(currentLesson);
1279
+ const conversationSettings = await this.lessonAIService.generateConversationSettingsForLesson(currentLesson, this.settings());
1273
1280
  if (conversationSettings) {
1274
1281
  this.conversationSettings.set(conversationSettings);
1275
1282
  this.chatVisible.set(true);
@@ -1312,11 +1319,11 @@ class DCLessonRendererComponent {
1312
1319
  }
1313
1320
  }
1314
1321
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1315
- 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 }, test: { classPropertyName: "test", publicName: "test", 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 [taskOnUserMessage]=\"evalAgentTask()\"\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", "taskOnUserMessage", "taskOnAssistantMessage", "parseDict"], outputs: ["sendMessage", "goalCompleted"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i2$4.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"] }] }); }
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"] }] }); }
1316
1323
  }
1317
1324
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonRendererComponent, decorators: [{
1318
1325
  type: Component,
1319
- 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 [taskOnUserMessage]=\"evalAgentTask()\"\n [conversationSettings]=\"conversationSettings()\"\n (goalCompleted)=\"handleGoalCompleted($event)\"\n (sendMessage)=\"onChatMessage($event)\"></dc-chat>\n</p-drawer>\n}\n", styles: [".evaluate{float:right}\n"] }]
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"] }]
1320
1327
  }], ctorParameters: () => [], propDecorators: { wordClicked: [{
1321
1328
  type: Output
1322
1329
  }], dynamicLesson: [{
@@ -1745,45 +1752,72 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
1745
1752
  }]
1746
1753
  }] });
1747
1754
 
1755
+ class DynamicComponentsBuilderService {
1756
+ #dialogService = inject(DialogService);
1757
+ #toastService = inject(TOAST_ALERTS_TOKEN);
1758
+ #dynamicComponentsService = inject(DynamicComponentsService);
1759
+ openComponentBuilder(componentType, data = null) {
1760
+ const componentToBuild = this.#dynamicComponentsService.getDynamicComponentBuilders(componentType);
1761
+ if (!componentToBuild) {
1762
+ console.error(`No component builder found for type: ${componentType}`);
1763
+ this.#toastService.error({ title: 'Error', subtitle: `Componente desconocido: ${componentType}` });
1764
+ return undefined;
1765
+ }
1766
+ const dialogRef = this.#dialogService.open(componentToBuild, {
1767
+ inputValues: {
1768
+ // inputValues was removed in newer PrimeNG versions, use 'data'
1769
+ inputs: data.inputs,
1770
+ id: data.id,
1771
+ },
1772
+ width: '80vw',
1773
+ header: 'Agregar componente',
1774
+ closable: true,
1775
+ });
1776
+ return dialogRef;
1777
+ }
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' }); }
1780
+ }
1781
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DynamicComponentsBuilderService, decorators: [{
1782
+ type: Injectable,
1783
+ args: [{
1784
+ providedIn: 'root',
1785
+ }]
1786
+ }] });
1787
+
1748
1788
  class DCLessonComponentAdderComponent {
1749
1789
  constructor() {
1750
1790
  // Services
1751
- this.#dialogService = inject(DialogService);
1752
- this.#toastService = inject(TOAST_ALERTS_TOKEN);
1791
+ this.#dynamicComponentsBuilderService = inject(DynamicComponentsBuilderService);
1753
1792
  this.componentAdded = new EventEmitter(); // Changed Output name and type
1754
1793
  // Expose enum to the template
1755
1794
  this.lessonComponentEnum = LessonComponentEnum;
1756
1795
  }
1757
1796
  // Services
1758
- #dialogService;
1759
- #toastService;
1760
- // Moved logic from DCLessonEditorComponent
1797
+ #dynamicComponentsBuilderService;
1798
+ // Logic to open component builder, now utilizing DynamicComponentsBuilderService
1761
1799
  openComponentBuilder(type) {
1762
- const componentToBuild = LessonComponentBuilders[type];
1763
- if (!componentToBuild) {
1764
- console.error(`No component builder found for type: ${type}`);
1765
- this.#toastService.error({ title: 'Error', subtitle: `Componente desconocido: ${type}` });
1766
- return;
1800
+ const dialogRef = this.#dynamicComponentsBuilderService.openComponentBuilder(type);
1801
+ if (dialogRef) {
1802
+ // Handle the result and emit the new event
1803
+ dialogRef.onClose.subscribe((result) => {
1804
+ if (result) {
1805
+ console.log('Component builder closed:', result);
1806
+ this.componentAdded.emit(result); // Emit the result when dialog closes successfully
1807
+ }
1808
+ });
1809
+ }
1810
+ else {
1811
+ // Optional: Log if the dialog couldn't be opened, though the service already logs an error.
1812
+ console.warn(`Dialog could not be opened for type via component: ${type}`);
1767
1813
  }
1768
- const dialogRef = this.#dialogService.open(componentToBuild, {
1769
- width: '80vw',
1770
- header: 'Agregar componente',
1771
- closable: true,
1772
- });
1773
- // Handle the result and emit the new event
1774
- dialogRef.onClose.subscribe((result) => {
1775
- if (result) {
1776
- console.log('Component builder closed:', result);
1777
- this.componentAdded.emit(result); // Emit the result when dialog closes successfully
1778
- }
1779
- });
1780
1814
  }
1781
1815
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonComponentAdderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1782
- 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 <!-- 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: i2$5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }] }); }
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"] }] }); }
1783
1817
  }
1784
1818
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonComponentAdderComponent, decorators: [{
1785
1819
  type: Component,
1786
- 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 <!-- Add other buttons here if needed, following the same pattern -->\n</div>\n" }]
1820
+ 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" }]
1787
1821
  }], propDecorators: { componentAdded: [{
1788
1822
  type: Output
1789
1823
  }] } });
@@ -1981,10 +2015,10 @@ class DCLessonMetadataEditorComponent {
1981
2015
  }
1982
2016
  }
1983
2017
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonMetadataEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1984
- 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: i4.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$5.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
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
1985
2019
  FlagLanguagePipe, name: "flagEmoji" }, { kind: "pipe", type: // Added Pipe
1986
2020
  LangDescTranslationPipe, name: "langDesc" }, { kind: "ngmodule", type: // Added Pipe
1987
- InputGroupModule }, { kind: "component", type: i5$1.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["style", "styleClass"] }, { kind: "ngmodule", type: DividerModule }, { kind: "component", type: i6.Divider, selector: "p-divider", inputs: ["style", "styleClass", "layout", "type", "align"] }] }); }
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"] }] }); }
1988
2022
  }
1989
2023
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonMetadataEditorComponent, decorators: [{
1990
2024
  type: Component,
@@ -2139,6 +2173,7 @@ class DCLessonEditorComponent {
2139
2173
  this.promptService = inject(PromptService);
2140
2174
  this.ngxVertexService = inject(NgxVertexService);
2141
2175
  this.cdr = inject(ChangeDetectorRef);
2176
+ this.dynamicComponentsBuilderService = inject(DynamicComponentsBuilderService);
2142
2177
  // Signals States
2143
2178
  this.lessonId = toSignal(inject(ActivatedRoute).paramMap.pipe(map((params) => params.get('id'))));
2144
2179
  this.lesson = signal(undefined); // Initialize as undefined
@@ -2266,6 +2301,7 @@ class DCLessonEditorComponent {
2266
2301
  const savedLesson = await this.#lessonService.postLesson(lessonToSave);
2267
2302
  const currentId = this.lessonId();
2268
2303
  if (!currentId) {
2304
+ // No se como guardar los extras aunt
2269
2305
  // It was a new lesson, now it has an ID. Navigate.
2270
2306
  this.#toastService.success({ title: 'Se creó la lección', subtitle: 'Éxito' });
2271
2307
  // The effect should automatically fetch the lesson again after navigation due to paramMap change.
@@ -2399,8 +2435,14 @@ class DCLessonEditorComponent {
2399
2435
  console.log(this.prompts);
2400
2436
  this.cdr.markForCheck();
2401
2437
  }
2438
+ editComponent(comp) {
2439
+ console.log('Edit component:', comp);
2440
+ this.dynamicComponentsBuilderService.openComponentBuilder(comp.component, comp).onClose.subscribe((result) => {
2441
+ this.onComponentAdded(result);
2442
+ });
2443
+ }
2402
2444
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: DCLessonEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2403
- 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>ID: {{ comp.id }} - Tipo: {{ comp.component }}<button pButton icon=\"pi pi-info\" (click)=\"showComponentDetails(comp)\"></button></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()\" [test]=\"true\"></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<div>\n <h4>Aqui estan los prompts</h4>\n</div>\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$6.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: CKEditorModule }, { kind: "component", type: i3$1.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", "test"], 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$2.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: i2$5.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
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
2404
2446
  DCLessonMetadataEditorComponent, selector: "dc-lesson-metadata-editor", inputs: ["lesson", "isLoadingLesson"], outputs: ["saveRequest", "importNotionRequest", "improveNotionRequest"] }, { kind: "ngmodule", type: // Add the metadata editor here
2405
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"] }] }); }
2406
2448
  }
@@ -2418,7 +2460,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2418
2460
  DCLessonComponentAdderComponent, // Add the component adder here
2419
2461
  DCLessonMetadataEditorComponent, // Add the metadata editor here
2420
2462
  DialogModule,
2421
- ], 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>ID: {{ comp.id }} - Tipo: {{ comp.component }}<button pButton icon=\"pi pi-info\" (click)=\"showComponentDetails(comp)\"></button></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()\" [test]=\"true\"></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<div>\n <h4>Aqui estan los prompts</h4>\n</div>\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"] }]
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"] }]
2422
2464
  }], ctorParameters: () => [], propDecorators: { target: [{
2423
2465
  type: ViewChild,
2424
2466
  args: ['target', { read: ViewContainerRef }]
@@ -2446,6 +2488,283 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2446
2488
  type: Input
2447
2489
  }] } });
2448
2490
 
2491
+ const Endpoints$1 = {
2492
+ courses: 'api/courses',
2493
+ };
2494
+ class CoursesService {
2495
+ constructor() {
2496
+ this.httpCoreService = inject(HttpCoreService);
2497
+ }
2498
+ // Not sure how to implement this yet.
2499
+ getCourses() {
2500
+ return this.httpCoreService.get(Endpoints$1.courses);
2501
+ }
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' }); }
2504
+ }
2505
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesService, decorators: [{
2506
+ type: Injectable,
2507
+ args: [{
2508
+ providedIn: 'root',
2509
+ }]
2510
+ }] });
2511
+
2512
+ class CoursesAdminComponent {
2513
+ constructor() {
2514
+ this.httpCoreService = inject(HttpCoreService);
2515
+ }
2516
+ async ngOnInit() {
2517
+ const courses = await this.httpCoreService.get('courses');
2518
+ console.log(courses);
2519
+ }
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: [""] }); }
2522
+ }
2523
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CoursesAdminComponent, decorators: [{
2524
+ type: Component,
2525
+ args: [{ selector: 'ngx-courses-admin', standalone: true, template: "<p>welcome to courses creation</p>\n" }]
2526
+ }] });
2527
+
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 {
2555
+ constructor() {
2556
+ this.httpService = inject(HttpCoreService);
2557
+ this.toastService = inject(TOAST_ALERTS_TOKEN);
2558
+ }
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' }); }
2585
+ }
2586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseService, decorators: [{
2587
+ type: Injectable,
2588
+ args: [{
2589
+ providedIn: 'root',
2590
+ }]
2591
+ }] });
2592
+
2593
+ class CourseListComponent extends PaginationBase {
2594
+ constructor() {
2595
+ super(...arguments);
2596
+ // Services
2597
+ this.toastService = inject(TOAST_ALERTS_TOKEN);
2598
+ this.sourceService = inject(CourseService);
2599
+ this.cdr = inject(ChangeDetectorRef);
2600
+ // Inputs
2601
+ this.viewType = 'card';
2602
+ this.onlyView = input(true);
2603
+ this.onSelect = output();
2604
+ // States
2605
+ this.courses = signal([]);
2606
+ this.columns = ['name', 'description', 'updatedAt', 'image'];
2607
+ this.filterBarOptions = { showActions: true, showCreateButton: true, showViewButton: true };
2608
+ }
2609
+ getCustomButtons(item) {
2610
+ return [
2611
+ {
2612
+ tooltipOptions: { tooltipLabel: 'Ver detalles', tooltipPosition: 'bottom' },
2613
+ icon: 'pi pi-eye',
2614
+ command: () => this.doAction({ item, action: 'view' }),
2615
+ },
2616
+ {
2617
+ label: 'Editar',
2618
+ icon: 'pi pi-pencil',
2619
+ command: () => this.doAction({ item, action: 'edit' }),
2620
+ },
2621
+ {
2622
+ label: 'Eliminar',
2623
+ icon: 'pi pi-trash',
2624
+ command: () => this.doAction({ item, action: 'delete' }),
2625
+ },
2626
+ ];
2627
+ }
2628
+ async ngOnInit() {
2629
+ this.filterConfig.returnProps = { _id: 1, id: 1, name: 1, description: 1, updatedAt: 1, image: 1 };
2630
+ const response = await this.sourceService.getFilteredCourses(this.filterConfig);
2631
+ this.courses.set(response.rows);
2632
+ this.cdr.detectChanges();
2633
+ console.log(this.courses(), this.viewType);
2634
+ this.cdr.detectChanges();
2635
+ }
2636
+ loadData() {
2637
+ throw new Error('Method not implemented.');
2638
+ }
2639
+ onNew() {
2640
+ console.log('onNew');
2641
+ this.router.navigate(['./edit'], { relativeTo: this.route });
2642
+ }
2643
+ toggleView() {
2644
+ this.viewType = this.viewType === 'card' ? 'table' : 'card';
2645
+ console.log(this.viewType, this.courses());
2646
+ this.cdr.detectChanges();
2647
+ }
2648
+ selectItem(course) {
2649
+ console.log('onSelect');
2650
+ this.onSelect.emit(course);
2651
+ }
2652
+ async doAction(actionEvent) {
2653
+ const { item, action } = actionEvent;
2654
+ if (action == 'changeView') {
2655
+ this.toggleView();
2656
+ }
2657
+ switch (action) {
2658
+ case 'view':
2659
+ this.router.navigate(['./details', item.id], { relativeTo: this.route });
2660
+ break;
2661
+ case 'delete':
2662
+ const areYouSure = confirm('¿Estás seguro de querer eliminar este origen?');
2663
+ if (areYouSure) {
2664
+ const id = item.id || item._id;
2665
+ await this.sourceService.deleteCourse(id);
2666
+ this.courses.set(this.courses().filter((course) => course._id !== id));
2667
+ this.toastService.success({
2668
+ title: 'Origen eliminado',
2669
+ subtitle: 'El origen ha sido eliminado correctamente',
2670
+ });
2671
+ this.cdr.detectChanges();
2672
+ }
2673
+ break;
2674
+ case 'edit':
2675
+ this.router.navigate(['./edit', item.id], { relativeTo: this.route });
2676
+ break;
2677
+ }
2678
+ }
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 }); }
2681
+ }
2682
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseListComponent, decorators: [{
2683
+ type: Component,
2684
+ args: [{ selector: 'app-course-list', imports: [
2685
+ CardModule,
2686
+ ButtonModule,
2687
+ DCFilterBarComponent,
2688
+ SpeedDialModule,
2689
+ DatePipe,
2690
+ SlicePipe,
2691
+ PaginatorModule,
2692
+ RouterModule,
2693
+ TableModule,
2694
+ 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"] }]
2696
+ }], propDecorators: { viewType: [{
2697
+ type: Input
2698
+ }] } });
2699
+
2700
+ class CourseFormComponent {
2701
+ constructor() {
2702
+ this.route = inject(ActivatedRoute);
2703
+ this.courseService = inject(CourseService);
2704
+ this.fb = inject(FormBuilder);
2705
+ this.router = inject(Router);
2706
+ this.toastService = inject(TOAST_ALERTS_TOKEN);
2707
+ this.cdr = inject(ChangeDetectorRef);
2708
+ this.storageImgSettings = {
2709
+ path: `courses`,
2710
+ cropSettings: { aspectRatio: AspectType.Square, resolutions: [ResolutionType.MediumLarge], resizeToWidth: 700 },
2711
+ };
2712
+ this.extraFields = [
2713
+ { key: 'title', type: 'input', props: { label: 'Title', placeholder: 'Title', required: false } },
2714
+ { key: 'content', type: 'textarea', props: { label: 'Content', placeholder: 'Content', required: false } },
2715
+ ];
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
+ }
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
+ }
2731
+ }
2732
+ 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 });
2738
+ }
2739
+ this.toastService.success({ title: 'Origen guardado', subtitle: 'El origen ha sido guardado correctamente' });
2740
+ }
2741
+ }
2742
+ handleImageUpload(event) {
2743
+ // this.genericForm.patchValue({ image: event });
2744
+ alert('Image uploaded');
2745
+ }
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 }); }
2748
+ }
2749
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: CourseFormComponent, decorators: [{
2750
+ type: Component,
2751
+ args: [{ selector: 'app-source-form', imports: [
2752
+ ReactiveFormsModule,
2753
+ CardModule,
2754
+ TextareaModule,
2755
+ DropdownModule,
2756
+ ButtonModule,
2757
+ SelectModule,
2758
+ InputTextModule,
2759
+ ChipModule,
2760
+ TooltipModule,
2761
+ CropperComponentModal,
2762
+ FormlyModule,
2763
+ DialogModule,
2764
+ 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"] }]
2766
+ }] });
2767
+
2449
2768
  /*
2450
2769
  * Public API Surface of lessons
2451
2770
  */
@@ -2454,5 +2773,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
2454
2773
  * Generated bundle index. Do not edit.
2455
2774
  */
2456
2775
 
2457
- export { ComponentBuilder, ComponentWithForm, DCLessonEditorComponent, DCLessonFormComponent, DCLessonListComponent, DCLessonRendererComponent, DcLessonCardComponent, DefaultLessonsService, 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 };
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 };
2458
2777
  //# sourceMappingURL=dataclouder-ngx-lessons.mjs.map