@dataclouder/ngx-lessons 0.0.31 → 0.0.33

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 (86) hide show
  1. package/README.md +56 -10
  2. package/fesm2022/dataclouder-ngx-lessons.mjs +292 -81
  3. package/fesm2022/dataclouder-ngx-lessons.mjs.map +1 -1
  4. package/lib/components/dc-lessons/dc-lesson-editor/dc-lesson-editor.component.d.ts +9 -5
  5. package/lib/components/dc-lessons/dc-lesson-renderer/dc-lesson-renderer.component.d.ts +3 -1
  6. package/lib/components/lesson-mini-components/components/lessons.clases.d.ts +1 -0
  7. package/lib/models/simple-agents.d.ts +2 -0
  8. package/lib/services/lesson-ai.service.d.ts +15 -2
  9. package/lib/services/lesson-utils.service.d.ts +10 -1
  10. package/package.json +1 -1
  11. package/public-api.d.ts +1 -0
  12. package/src/lib/components/dc-lessons/dc-lesson-card/dc-lesson-card.component.html +0 -40
  13. package/src/lib/components/dc-lessons/dc-lesson-card/dc-lesson-card.component.scss +0 -120
  14. package/src/lib/components/dc-lessons/dc-lesson-card/dc-lesson-card.component.ts +0 -82
  15. package/src/lib/components/dc-lessons/dc-lesson-component-adder/dc-lesson-component-adder.component.css +0 -1
  16. package/src/lib/components/dc-lessons/dc-lesson-component-adder/dc-lesson-component-adder.component.html +0 -46
  17. package/src/lib/components/dc-lessons/dc-lesson-component-adder/dc-lesson-component-adder.component.ts +0 -52
  18. package/src/lib/components/dc-lessons/dc-lesson-editor/dc-lesson-editor.component.css +0 -90
  19. package/src/lib/components/dc-lessons/dc-lesson-editor/dc-lesson-editor.component.html +0 -67
  20. package/src/lib/components/dc-lessons/dc-lesson-editor/dc-lesson-editor.component.scss +0 -0
  21. package/src/lib/components/dc-lessons/dc-lesson-editor/dc-lesson-editor.component.ts +0 -356
  22. package/src/lib/components/dc-lessons/dc-lesson-metadata-editor/dc-lesson-metadata-editor.component.css +0 -1
  23. package/src/lib/components/dc-lessons/dc-lesson-metadata-editor/dc-lesson-metadata-editor.component.html +0 -72
  24. package/src/lib/components/dc-lessons/dc-lesson-metadata-editor/dc-lesson-metadata-editor.component.ts +0 -60
  25. package/src/lib/components/dc-lessons/dc-lesson-renderer/dc-lesson-renderer.component.html +0 -23
  26. package/src/lib/components/dc-lessons/dc-lesson-renderer/dc-lesson-renderer.component.scss +0 -3
  27. package/src/lib/components/dc-lessons/dc-lesson-renderer/dc-lesson-renderer.component.ts +0 -332
  28. package/src/lib/components/dc-lessons/lesson-form/lesson-form.component.html +0 -5
  29. package/src/lib/components/dc-lessons/lesson-form/lesson-form.component.scss +0 -3
  30. package/src/lib/components/dc-lessons/lesson-form/lesson-form.component.ts +0 -14
  31. package/src/lib/components/dc-lessons/lesson-list/dc-lesson-list.component.html +0 -30
  32. package/src/lib/components/dc-lessons/lesson-list/dc-lesson-list.component.scss +0 -17
  33. package/src/lib/components/dc-lessons/lesson-list/dc-lesson-list.component.ts +0 -170
  34. package/src/lib/components/dc-lessons/lessons.component.ts +0 -10
  35. package/src/lib/components/lesson-mini-components/components/ComponentBuilder.ts +0 -82
  36. package/src/lib/components/lesson-mini-components/components/ComponentWithForm.ts +0 -25
  37. package/src/lib/components/lesson-mini-components/components/lesson-dynamic.component.ts +0 -13
  38. package/src/lib/components/lesson-mini-components/components/lessons.clases.ts +0 -220
  39. package/src/lib/components/lesson-mini-components/components/selector/selector-builder/selector-builder.component.html +0 -62
  40. package/src/lib/components/lesson-mini-components/components/selector/selector-builder/selector-builder.component.scss +0 -15
  41. package/src/lib/components/lesson-mini-components/components/selector/selector-builder/selector-builder.component.ts +0 -70
  42. package/src/lib/components/lesson-mini-components/components/selector/selector.component.html +0 -1
  43. package/src/lib/components/lesson-mini-components/components/selector/selector.component.scss +0 -12
  44. package/src/lib/components/lesson-mini-components/components/selector/selector.component.spec.ts +0 -25
  45. package/src/lib/components/lesson-mini-components/components/selector/selector.component.ts +0 -47
  46. package/src/lib/components/lesson-mini-components/components/speaker/speaker-builder/speaker-builder.component.html +0 -13
  47. package/src/lib/components/lesson-mini-components/components/speaker/speaker-builder/speaker-builder.component.scss +0 -0
  48. package/src/lib/components/lesson-mini-components/components/speaker/speaker-builder/speaker-builder.component.ts +0 -40
  49. package/src/lib/components/lesson-mini-components/components/speaker/speaker.component.html +0 -9
  50. package/src/lib/components/lesson-mini-components/components/speaker/speaker.component.scss +0 -3
  51. package/src/lib/components/lesson-mini-components/components/speaker/speaker.component.ts +0 -33
  52. package/src/lib/components/lesson-mini-components/components/text-writer/text-writer-buider/text-writer-buider.component.html +0 -24
  53. package/src/lib/components/lesson-mini-components/components/text-writer/text-writer-buider/text-writer-buider.component.scss +0 -15
  54. package/src/lib/components/lesson-mini-components/components/text-writer/text-writer-buider/text-writer-buider.component.spec.ts +0 -25
  55. package/src/lib/components/lesson-mini-components/components/text-writer/text-writer-buider/text-writer-buider.component.ts +0 -29
  56. package/src/lib/components/lesson-mini-components/components/text-writer/text-writer.component.html +0 -4
  57. package/src/lib/components/lesson-mini-components/components/text-writer/text-writer.component.scss +0 -8
  58. package/src/lib/components/lesson-mini-components/components/text-writer/text-writer.component.spec.ts +0 -25
  59. package/src/lib/components/lesson-mini-components/components/text-writer/text-writer.component.ts +0 -61
  60. package/src/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcher.component.css +0 -3
  61. package/src/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcher.component.html +0 -9
  62. package/src/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcher.component.ts +0 -32
  63. package/src/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcherBuilder/translationSwitcherBuilder.component.css +0 -3
  64. package/src/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcherBuilder/translationSwitcherBuilder.component.html +0 -28
  65. package/src/lib/components/lesson-mini-components/components/translationSwitcher/translationSwitcherBuilder/translationSwitcherBuilder.component.ts +0 -30
  66. package/src/lib/components/lesson-mini-components/components/verb-summary/verb-summary-builder/verb-summary-builder.component.html +0 -18
  67. package/src/lib/components/lesson-mini-components/components/verb-summary/verb-summary-builder/verb-summary-builder.component.scss +0 -3
  68. package/src/lib/components/lesson-mini-components/components/verb-summary/verb-summary-builder/verb-summary-builder.component.spec.ts +0 -25
  69. package/src/lib/components/lesson-mini-components/components/verb-summary/verb-summary-builder/verb-summary-builder.component.ts +0 -25
  70. package/src/lib/components/lesson-mini-components/components/verb-summary/verb-summary.component.html +0 -15
  71. package/src/lib/components/lesson-mini-components/components/verb-summary/verb-summary.component.scss +0 -27
  72. package/src/lib/components/lesson-mini-components/components/verb-summary/verb-summary.component.spec.ts +0 -25
  73. package/src/lib/components/lesson-mini-components/components/verb-summary/verb-summary.component.ts +0 -46
  74. package/src/lib/components/lesson-mini-components/components/word-summary/word-summary-builder/word-summary-builder.component.html +0 -19
  75. package/src/lib/components/lesson-mini-components/components/word-summary/word-summary-builder/word-summary-builder.component.scss +0 -0
  76. package/src/lib/components/lesson-mini-components/components/word-summary/word-summary-builder/word-summary-builder.component.ts +0 -27
  77. package/src/lib/components/lesson-mini-components/components/word-summary/word-summary.component.html +0 -14
  78. package/src/lib/components/lesson-mini-components/components/word-summary/word-summary.component.scss +0 -22
  79. package/src/lib/components/lesson-mini-components/components/word-summary/word-summary.component.ts +0 -51
  80. package/src/lib/models/lessons.pipes.ts +0 -38
  81. package/src/lib/models/models.ts +0 -92
  82. package/src/lib/models/notion.models.ts +0 -43
  83. package/src/lib/services/lesson-ai.service.ts +0 -103
  84. package/src/lib/services/lesson-notion.service.ts +0 -161
  85. package/src/lib/services/lesson-utils.service.ts +0 -181
  86. package/src/public-api.ts +0 -25
@@ -1,332 +0,0 @@
1
- import { Component, ComponentRef, ElementRef, Renderer2, ViewChild, ViewContainerRef, computed, effect, inject, input, signal } from '@angular/core'; // Added signal imports
2
- import { FormGroup, FormControl, Validators } from '@angular/forms'; // Use typed forms
3
- import { KeyValuePipe } from '@angular/common';
4
- import { ButtonModule } from 'primeng/button';
5
- import { LessonAIService } from '../../../services/lesson-ai.service'; // Import the new service
6
-
7
- import {
8
- getLessonComponentClass,
9
- ILesson,
10
- LessonComponentConfiguration,
11
- LessonComponentsType,
12
- LESSONS_TOKEN,
13
- LessonsAbstractService,
14
- } from '../../lesson-mini-components/components/lessons.clases';
15
-
16
- import { TOAST_ALERTS_TOKEN, ToastAlertsAbstractService } from '@dataclouder/ngx-core';
17
- import { LessonComponentInterface } from '../../lesson-mini-components/components/lessons.clases';
18
- import { DCChatComponent, IAgentCard, IMiniAgentCard } from '@dataclouder/ngx-agent-cards';
19
-
20
- import { DrawerModule } from 'primeng/drawer';
21
-
22
- @Component({
23
- selector: 'dc-lesson-renderer',
24
- templateUrl: './dc-lesson-renderer.component.html',
25
- styleUrls: ['./dc-lesson-renderer.component.scss'],
26
- standalone: true,
27
- imports: [KeyValuePipe, ButtonModule, DCChatComponent, DrawerModule],
28
- })
29
- export class DCLessonRendererComponent {
30
- // --- Signal Inputs ---
31
- lessonInput = input<ILesson>(); // Input signal for lesson object
32
- lessonIdInput = input<string>(); // Input signal for lesson ID
33
- test = input<boolean>(false);
34
-
35
- // --- View Childs ---
36
- @ViewChild('dynamicLesson', { static: true }) dynamicLesson: ElementRef<HTMLElement>;
37
-
38
- // --- Injected Services (using inject function) ---
39
- private readonly renderer = inject(Renderer2);
40
- private readonly viewContainerRef = inject(ViewContainerRef);
41
- private readonly toastrService = inject<ToastAlertsAbstractService>(TOAST_ALERTS_TOKEN);
42
- private readonly lessonService = inject<LessonsAbstractService>(LESSONS_TOKEN);
43
- private readonly lessonAIService = inject(LessonAIService); // Inject the new service
44
-
45
- // --- State Signals ---
46
- lesson = signal<ILesson | undefined>(undefined); // Internal lesson state signal
47
- chatVisible = signal(false); // Signal for chat visibility
48
- agentMasterLesson = signal<IAgentCard | undefined>(undefined); // Signal for agent card
49
- evaluatorAgentCard = signal<IMiniAgentCard | undefined>(undefined); // Signal for evaluator card
50
-
51
- // --- Computed Signals ---
52
- imageCover = computed(() => this.lesson()?.media?.images?.find((img) => img.type === 'cover')?.url); // Computed signal for imageCover
53
-
54
- // --- Properties ---
55
- private components: { [key: string]: ComponentRef<LessonComponentInterface> } = {};
56
- public mainForm: FormGroup<{ [key: string]: FormControl<any> }> = new FormGroup({});
57
-
58
- constructor() {
59
- // Effect to fetch lesson data if ID is provided and lesson object isn't
60
- effect(
61
- async () => {
62
- const lessonInput = this.lessonInput();
63
- const lessonId = this.lessonIdInput();
64
-
65
- if (lessonInput) {
66
- this.lesson.set(lessonInput); // Use input lesson directly
67
- } else if (lessonId && !this.lesson()) {
68
- // Fetch only if ID exists and internal lesson is not set
69
- console.log(`Fetching lesson with ID: ${lessonId}`);
70
- try {
71
- // Consider adding a loading state signal here
72
- const fetchedLesson = await this.lessonService.getLesson(lessonId);
73
- this.lesson.set(fetchedLesson);
74
- console.log('Fetched lesson:', fetchedLesson);
75
- } catch (error) {
76
- console.error(`Failed to fetch lesson with ID: ${lessonId}`, error);
77
- this.toastrService.error({ subtitle: 'Failed to load lesson data.', title: 'Error' });
78
- this.lesson.set(undefined); // Reset lesson on error
79
- } finally {
80
- // Reset loading state signal here
81
- }
82
- } else if (!lessonInput && !lessonId) {
83
- // Handle case where neither input is provided, maybe clear the lesson?
84
- this.lesson.set(undefined);
85
- }
86
- },
87
- { allowSignalWrites: true },
88
- ); // Allow signal writes inside effect
89
-
90
- // Effect to render the lesson whenever the lesson signal changes
91
- effect(() => {
92
- const currentLesson = this.lesson();
93
- if (currentLesson) {
94
- this._renderLesson(currentLesson);
95
- } else {
96
- // Clear previous rendering if lesson becomes undefined
97
- this._clearLessonRendering();
98
- }
99
- });
100
- }
101
-
102
- // --- Rendering Logic ---
103
-
104
- private _clearLessonRendering(): void {
105
- // Destroy previously created dynamic components
106
- Object.values(this.components).forEach((compRef) => compRef.destroy());
107
- this.components = {};
108
- // Clear the form
109
- this.mainForm = new FormGroup({});
110
- // Clear the HTML content
111
- if (this.dynamicLesson?.nativeElement) {
112
- this.dynamicLesson.nativeElement.innerHTML = '';
113
- }
114
- }
115
-
116
- private _renderLesson(lessonData: ILesson): void {
117
- this._clearLessonRendering(); // Clear previous state first
118
-
119
- console.log('Rendering lesson:', lessonData.id);
120
- // console.log('Image cover URL:', this.imageCover()); // Access computed signal
121
-
122
- // 1) Parse textCoded, create components, and build HTML structure
123
- const { htmlContent, components } = this._parseAndCreateComponents(lessonData);
124
- this.components = components;
125
-
126
- // 2) Aggregate form controls from created components
127
- this._aggregateFormControls(this.components);
128
-
129
- // 3) Set the innerHTML of the target element
130
- this.dynamicLesson.nativeElement.innerHTML = htmlContent;
131
-
132
- // 4) Inject the component views into the DOM
133
- this._injectComponentsIntoDom(this.components);
134
- }
135
-
136
- private _parseAndCreateComponents(lessonData: ILesson): { htmlContent: string; components: { [key: string]: ComponentRef<LessonComponentInterface> } } {
137
- const r1 = new RegExp('~(.+?)~', 'g');
138
- let count = 0;
139
- const createdComponents: { [key: string]: ComponentRef<LessonComponentInterface> } = {};
140
-
141
- const htmlContent = lessonData.textCoded.replace(r1, (_matching, jsonCoded) => {
142
- const componentName = `dynamicComp${count}`;
143
- count++;
144
- const componentRef = this._createComponentReferenceWithJson(jsonCoded, lessonData);
145
- if (!componentRef) {
146
- console.error(`Failed to create component for: ${jsonCoded}`);
147
- return '<!-- component creation failed -->'; // Placeholder in HTML
148
- }
149
- createdComponents[componentName] = componentRef;
150
- return `<span id="${componentName}"></span>`; // Return span placeholder
151
- });
152
-
153
- return { htmlContent, components: createdComponents };
154
- }
155
-
156
- private _aggregateFormControls(components: { [key: string]: ComponentRef<LessonComponentInterface> }): void {
157
- const newFormControls: { [key: string]: FormControl<any> } = {};
158
- Object.entries(components).forEach(([name, componentRef]) => {
159
- // Check if the instance has a control property that is a FormControl
160
- if (componentRef.instance?.control instanceof FormControl) {
161
- newFormControls[name] = componentRef.instance.control;
162
- // Add required validator (consider making this configurable via component config?)
163
- newFormControls[name].addValidators(Validators.required);
164
- }
165
- });
166
- this.mainForm = new FormGroup(newFormControls); // Create the typed FormGroup
167
- }
168
-
169
- private _injectComponentsIntoDom(components: { [key: string]: ComponentRef<LessonComponentInterface> }): void {
170
- Object.entries(components).forEach(([name, componentRef]) => {
171
- const elementRef = document.getElementById(name); // Find the placeholder span
172
- if (elementRef) {
173
- this._addComponentToNode(componentRef, elementRef);
174
- } else {
175
- console.warn(`Placeholder element with ID '${name}' not found in the DOM.`);
176
- }
177
- });
178
- }
179
-
180
- private _addComponentToNode(componentRef: ComponentRef<LessonComponentInterface>, nodeDOM: HTMLElement): void {
181
- this.renderer.appendChild(nodeDOM, componentRef.location.nativeElement);
182
- }
183
-
184
- private _createComponentReferenceWithJson(json: string, currentLesson: ILesson): ComponentRef<LessonComponentInterface> | null {
185
- try {
186
- let lessonCodedConfig: LessonComponentConfiguration = JSON.parse(json);
187
- debugger;
188
- // Attempt to find pre-configured component data in the lesson object by ID
189
- if (lessonCodedConfig.id && currentLesson?.dynamicComponents[lessonCodedConfig.id]) {
190
- const foundConfig = currentLesson.dynamicComponents[lessonCodedConfig.id];
191
- if (foundConfig) {
192
- // Merge configurations: Start with coded, override/add with found lesson config
193
- lessonCodedConfig = { ...lessonCodedConfig, ...foundConfig };
194
- }
195
- }
196
-
197
- const LessonClass = getLessonComponentClass(<LessonComponentsType>lessonCodedConfig.component);
198
-
199
- if (!LessonClass) {
200
- console.error(`Component class not found for type: ${lessonCodedConfig.component}. JSON: ${json}`);
201
- return null; // Return null if class doesn't exist
202
- }
203
-
204
- // Create component instance
205
- const componentRef = this.viewContainerRef.createComponent<LessonComponentInterface>(LessonClass);
206
-
207
- if (lessonCodedConfig.inputs) {
208
- for (const key in lessonCodedConfig.inputs) {
209
- if (lessonCodedConfig.inputs.hasOwnProperty(key)) {
210
- componentRef.instance[key] = lessonCodedConfig.inputs[key];
211
- }
212
- }
213
- }
214
- // i think i can improve this to pass only settings not all config, Assign the configuration to the component instance
215
- // settings data i defined in form interface, config will be all the component data including id and component type
216
- if (lessonCodedConfig.settings) {
217
- componentRef.instance.config = lessonCodedConfig;
218
- }
219
- return componentRef;
220
- } catch (error) {
221
- console.error(`Error processing component JSON: ${json}`, error);
222
- return null; // Return null on JSON parsing or other errors
223
- }
224
- }
225
-
226
- // --- Evaluation Logic ---
227
-
228
- public async evaluateForms() {
229
- this.mainForm.markAllAsTouched(); // Mark all controls for validation feedback
230
-
231
- if (!this.mainForm.valid) {
232
- // Trigger validation feedback on individual components visually if needed
233
- Object.keys(this.mainForm.controls).forEach((controlName) => {
234
- if (this.components[controlName]?.instance?.validate) {
235
- this.components[controlName].instance.validate(); // Assuming validate method handles visual feedback
236
- }
237
- });
238
- this.toastrService.warn({ subtitle: 'Por favor completa todos los ejercicios', title: 'Incompleto' });
239
- return;
240
- }
241
-
242
- const rates = { correct: 0, incorrect: 0, score: 0 };
243
-
244
- // Evaluate each component associated with a form control
245
- Object.keys(this.mainForm.controls).forEach((controlName) => {
246
- const instance = this.components[controlName]?.instance;
247
- // Check if the instance has an evaluate method (duck typing is okay here)
248
- if (instance && typeof instance.evaluate === 'function') {
249
- try {
250
- const result = instance.evaluate();
251
- if (result) {
252
- rates.correct++;
253
- } else {
254
- rates.incorrect++;
255
- }
256
- } catch (err) {
257
- console.error('Error during evaluation for component:', controlName, instance, err);
258
- rates.incorrect++; // Count errors as incorrect
259
- }
260
- }
261
- });
262
-
263
- if (this.test()) {
264
- // Access signal value
265
- console.log('Test mode: Evaluation skipped saving.');
266
- this.toastrService.info({ subtitle: `Test Results: ${rates.correct} correct, ${rates.incorrect} incorrect`, title: 'Test Mode' });
267
- return;
268
- }
269
-
270
- const totalQuestions = rates.correct + rates.incorrect;
271
- rates.score = totalQuestions > 0 ? rates.correct / totalQuestions : 0; // Avoid division by zero
272
-
273
- const status = rates.score >= 0.7 ? 'passed' : 'failed'; // Use >= for threshold
274
-
275
- const currentLesson = this.lesson();
276
- if (!currentLesson) {
277
- console.error('Cannot save result, lesson data is missing.');
278
- this.toastrService.error({ subtitle: 'Cannot save result, lesson data missing.', title: 'Error' });
279
- return;
280
- }
281
- const takenLesson = { lessonId: currentLesson.id, status: status, score: rates.score };
282
-
283
- console.log('Lesson evaluation result:', takenLesson);
284
- // TODO: Re-implement saving the taken lesson status via lessonService
285
- // try {
286
- // await this.lessonService.saveTakenLesson(takenLesson);
287
- // if (status === 'passed') {
288
- // this.toastrService.success({ subtitle: `Calificación: ${Math.round(rates.score * 100)}%. Se guardó tu progreso.`, title: '¡Muy bien!' });
289
- // } else {
290
- // this.toastrService.warn({ subtitle: `Calificación: ${Math.round(rates.score * 100)}%. Revisa tus respuestas.`, title: 'Casi lo logras' });
291
- // }
292
- // } catch (error) {
293
- // console.error('Failed to save taken lesson', error);
294
- // this.toastrService.error({ subtitle: 'No se pudo guardar tu progreso.', title: 'Error' });
295
- // }
296
- if (status === 'passed') {
297
- this.toastrService.success({ subtitle: `Calificación: ${Math.round(rates.score * 100)}%.`, title: '¡Muy bien!' });
298
- } else {
299
- this.toastrService.warn({ subtitle: `Calificación: ${Math.round(rates.score * 100)}%. Revisa tus respuestas.`, title: 'Casi lo logras' });
300
- }
301
- }
302
-
303
- // --- AI Chat Logic ---
304
-
305
- public async startAI() {
306
- const currentLesson = this.lesson();
307
- if (!currentLesson) {
308
- console.error('Cannot start AI without a lesson.');
309
- this.toastrService.error({ subtitle: 'Lesson data not available.', title: 'Cannot Start Chat' });
310
- return;
311
- }
312
-
313
- console.log('Requesting agent cards from LessonAIService...');
314
- try {
315
- // Call the service to get the agent cards
316
- const agentCards = await this.lessonAIService.generateAgentCards(currentLesson);
317
-
318
- if (agentCards) {
319
- this.agentMasterLesson.set(agentCards.masterAgent);
320
- this.evaluatorAgentCard.set(agentCards.evaluatorAgent);
321
- this.chatVisible.set(true);
322
- console.log('Agent cards received and set.');
323
- } else {
324
- console.error('Failed to generate agent cards (service returned null).');
325
- this.toastrService.error({ subtitle: 'Could not prepare the AI chat session.', title: 'Error' });
326
- }
327
- } catch (error) {
328
- console.error('Error generating agent cards:', error);
329
- this.toastrService.error({ subtitle: 'An error occurred while preparing the AI chat.', title: 'Error' });
330
- }
331
- }
332
- }
@@ -1,5 +0,0 @@
1
- <div class="lesson-form-container">
2
- <h2>Lesson Form</h2>
3
- <p>Esto es dentro del componente de la leccion</p>
4
- <!-- Form implementation will go here -->
5
- </div>
@@ -1,3 +0,0 @@
1
- .lesson-form-container {
2
- padding: 1rem;
3
- }
@@ -1,14 +0,0 @@
1
- import { Component } from '@angular/core';
2
-
3
- import { ReactiveFormsModule } from '@angular/forms';
4
-
5
- @Component({
6
- selector: 'dc-lesson-form',
7
- templateUrl: './lesson-form.component.html',
8
- styleUrls: ['./lesson-form.component.scss'],
9
- standalone: true,
10
- imports: [ReactiveFormsModule],
11
- })
12
- export class DCLessonFormComponent {
13
- // Form implementation will go here
14
- }
@@ -1,30 +0,0 @@
1
- <dc-filter-bar [customFilters]="customFilters" (onFilterAction)="applyFilterBarEvent($event)" (onNew)="newLesson()"></dc-filter-bar>
2
-
3
- @if(viewType === 'table') {
4
- <app-quick-table [columns]="columns" [tableData]="lessons" (onAction)="doOrEmitAction($event)"></app-quick-table>
5
- } @else {
6
- <div class="lesson-list-container">
7
- @if (!isLoadingLessons && lessons?.length > 0) { @for (lesson of lessons; track lesson._id) {
8
- <ng-container
9
- #outlet="ngComponentOutlet"
10
- [ngComponentOutlet]="cardComponent"
11
- [ngComponentOutletInputs]="{
12
- lesson: lesson,
13
- showOptions: showOptions
14
- }">
15
- </ng-container>
16
- } } @else {
17
- <p>No se encontraron lecciones disponibles</p>
18
- }
19
- </div>
20
- }
21
-
22
- <p-paginator
23
- currentPageReportTemplate="{{ totalRecords }} lecciones"
24
- [showCurrentPageReport]="true"
25
- (onPageChange)="onPageChange($event)"
26
- [first]="paginatorFirst"
27
- [rows]="paginatorRows"
28
- [totalRecords]="totalRecords"
29
- [rowsPerPageOptions]="[10, 20, 30]">
30
- </p-paginator>
@@ -1,17 +0,0 @@
1
- :host {
2
- display: flex;
3
- flex-direction: column;
4
- height: 100%;
5
- }
6
-
7
- .lesson-list-container {
8
- padding: 1rem;
9
- flex: 1;
10
- overflow-y: auto;
11
- min-height: 0; /* This is important for flex containers to respect overflow */
12
- }
13
-
14
- p-paginator {
15
- margin-top: auto;
16
- padding: 0.5rem 1rem;
17
- }
@@ -1,170 +0,0 @@
1
- import { ChangeDetectorRef, Component, EventEmitter, Inject, Input, OnInit, Output, Type, ViewChildren, QueryList, OnDestroy, input } from '@angular/core';
2
-
3
- import { PaginatorModule } from 'primeng/paginator';
4
- import { NgComponentOutlet } from '@angular/common';
5
- import { ActivatedRoute, Router, RouterModule } from '@angular/router';
6
-
7
- import { Subscription } from 'rxjs';
8
- import {
9
- DCFilterBarComponent,
10
- ICustomFilter,
11
- OnActionEvent,
12
- PaginationBase,
13
- PColumn,
14
- QuickTableComponent,
15
- TOAST_ALERTS_TOKEN,
16
- ToastAlertsAbstractService,
17
- } from '@dataclouder/ngx-core';
18
-
19
- import { LESSONS_TOKEN, LessonsAbstractService } from '../../lesson-mini-components/components/lessons.clases';
20
- import { DcLessonCardComponent } from '../dc-lesson-card/dc-lesson-card.component';
21
- import { MenuItem } from 'node_modules/primeng/api/menuitem';
22
-
23
- const tableViewColumns: PColumn[] = [
24
- { field: 'media.images[0].url', header: 'Image', type: 'image' },
25
- { field: 'title', header: 'Título' },
26
- { field: 'description', header: 'Descripción' },
27
- ];
28
-
29
- const TableViewActions: MenuItem[] = [
30
- { title: 'select', label: 'Select', icon: 'pi pi-check', severity: 'primary' },
31
- { title: 'qr', label: 'QR', icon: 'pi pi-qrcode', severity: 'info' },
32
- { title: 'edit', label: 'Edit', icon: 'pi pi-pencil', severity: 'info' },
33
- { title: 'delete', label: 'Delete', icon: 'pi pi-trash', severity: 'danger' },
34
- ];
35
-
36
- const returnProperties: Record<string, 0 | 1> = { id: 1, title: 1, assets: 1 };
37
-
38
- @Component({
39
- selector: 'dc-lesson-list',
40
- templateUrl: './dc-lesson-list.component.html',
41
- styleUrls: ['./dc-lesson-list.component.scss'],
42
- standalone: true,
43
- imports: [RouterModule, DCFilterBarComponent, PaginatorModule, NgComponentOutlet, QuickTableComponent],
44
- })
45
- export class DCLessonListComponent extends PaginationBase implements OnInit, OnDestroy {
46
- @Input() public showOptions: boolean = true;
47
- @Input() public customCardComponent?: Type<DcLessonCardComponent>;
48
- @Input() public customFilters: ICustomFilter[] = [];
49
- @Input() public viewType: 'table' | 'cards' = 'cards';
50
-
51
- // readonly actions = input<MenuItem[]>(TableViewActions);
52
-
53
- public override columns: PColumn[] = tableViewColumns;
54
-
55
- @ViewChildren('outlet') outlets!: QueryList<NgComponentOutlet>;
56
-
57
- public cardComponent: Type<DcLessonCardComponent> = null;
58
- public cardEventSubs: Subscription[] = [];
59
-
60
- public lessons: any[] = [];
61
- public isLoadingLessons = false;
62
-
63
- constructor(
64
- private cdr: ChangeDetectorRef,
65
- public override router: Router,
66
- public override route: ActivatedRoute,
67
- @Inject(LESSONS_TOKEN) private lessonsService: LessonsAbstractService,
68
- @Inject(TOAST_ALERTS_TOKEN) private toastrService: ToastAlertsAbstractService,
69
- ) {
70
- super(route, router);
71
- }
72
-
73
- ngOnInit(): void {
74
- this.filterConfig.returnProps = returnProperties;
75
- this.cardComponent = this.customCardComponent || DcLessonCardComponent;
76
-
77
- this.getPaginatedLessons(this.filterConfig);
78
- }
79
-
80
- public subscribeDinamicInstantToEvents() {
81
- this.clearcardEventSubs();
82
- this.subscribeToCardEvents();
83
- }
84
-
85
- private subscribeToCardEvents() {
86
- this.outlets.forEach((outlet) => {
87
- const instance: DcLessonCardComponent = outlet.componentInstance;
88
-
89
- this.cardEventSubs.push(
90
- instance.onAction.subscribe((lesson: any) => {
91
- this.doOrEmitAction(lesson);
92
- }),
93
- );
94
- });
95
- }
96
-
97
- private clearcardEventSubs() {
98
- this.cardEventSubs.forEach((sub) => sub.unsubscribe());
99
- this.cardEventSubs = [];
100
- }
101
-
102
- ngOnDestroy() {
103
- this.clearcardEventSubs();
104
- }
105
-
106
- public async getPaginatedLessons(paginator: any) {
107
- try {
108
- this.lessons = null;
109
- this.isLoadingLessons = true;
110
- this.cdr.detectChanges();
111
- const lessons = await this.lessonsService.getLessons(paginator);
112
-
113
- this.lessons = lessons['rows'] || lessons;
114
- this.totalRecords = lessons['count'] || this.lessons.length;
115
-
116
- console.log('lessons', lessons);
117
-
118
- setTimeout(() => {
119
- this.subscribeDinamicInstantToEvents();
120
- });
121
- } finally {
122
- this.isLoadingLessons = false;
123
- this.cdr.detectChanges();
124
- }
125
- }
126
-
127
- public search(searchText: string) {
128
- this.filterConfig['text'] = searchText;
129
- this.getPaginatedLessons(this.filterConfig);
130
- }
131
-
132
- private removeLesson(lesson: any) {
133
- const response = confirm('¿Estás seguro de querer eliminar esta lección?');
134
- if (response) {
135
- this.lessonsService.deleteLesson(lesson._id);
136
- this.lessons = this.lessons.filter((l) => l._id !== lesson._id);
137
- this.cdr.detectChanges();
138
- this.toastrService.success({ title: 'Adios a la lección', subtitle: 'La lección ha sido eliminada correctamente' });
139
- }
140
- }
141
-
142
- public newLesson() {
143
- this.onAction.emit({ action: 'new' });
144
- }
145
-
146
- public applyFilterBarEvent(filterEvent: OnActionEvent) {
147
- if (filterEvent.action == 'changeView') {
148
- this.viewType = this.viewType === 'table' ? 'cards' : 'table';
149
- return;
150
- } else {
151
- console.log('filterChanged in dc-lesson-list', filterEvent);
152
- this.filterConfig = filterEvent.item;
153
- this.filterConfig.returnProps = returnProperties;
154
-
155
- this.getPaginatedLessons(this.filterConfig);
156
- }
157
- }
158
-
159
- protected override loadData(): Promise<void> {
160
- return this.getPaginatedLessons(this.filterConfig);
161
- }
162
-
163
- public doOrEmitAction(actionEvent: OnActionEvent) {
164
- if (actionEvent.action === 'delete') {
165
- this.removeLesson(actionEvent.item);
166
- } else {
167
- this.onAction.emit(actionEvent);
168
- }
169
- }
170
- }
@@ -1,10 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { RouterOutlet } from '@angular/router';
3
-
4
- @Component({
5
- selector: 'app-lessonsv2',
6
- template: '<router-outlet></router-outlet>',
7
- standalone: true,
8
- imports: [RouterOutlet],
9
- })
10
- export class LessonsV2Component {}
@@ -1,82 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { FormBuilder, FormControl } from '@angular/forms';
3
- import { DynamicDialogRef } from 'primeng/dynamicdialog';
4
-
5
- import { LessonComponentBuilders, LessonComponentConfiguration, LessonComponentEnum, LessonCompSettings } from './lessons.clases';
6
- import { nanoid } from 'nanoid';
7
-
8
- // Create a type that maps the interface to FormControls
9
- export type LessonCompSettingsForm = {
10
- [K in keyof Required<LessonCompSettings>]: FormControl<LessonCompSettings[K]>;
11
- };
12
-
13
- export interface ComponentBuildData {
14
- str: string;
15
- obj: LessonComponentConfiguration;
16
- }
17
-
18
- @Component({
19
- selector: 'app-component-builder',
20
- template: '<div>no template</div>',
21
- })
22
- export class ComponentBuilder {
23
- constructor(protected formBuilder: FormBuilder, protected ref: DynamicDialogRef) {}
24
-
25
- // Sobreescribir si es necesario
26
- // public formGroup = this.formBuilder.group<LessonCompSettings>({});
27
-
28
- public formGroup = this.formBuilder.group({
29
- response: new FormControl<string | null>(null),
30
- responses: new FormControl<string | null>(null),
31
- options: this.formBuilder.array([]),
32
- text: new FormControl<string | null>(null),
33
- hint: new FormControl<string | null>(null),
34
- explanation: new FormControl<string | null>(null),
35
- });
36
-
37
- // Every component knows its type by comparing agains LessonComponentBuilders
38
- get questionType(): LessonComponentEnum {
39
- const self = this;
40
-
41
- const name = Object.keys(LessonComponentBuilders).find((componentName: any) => {
42
- const componentClass = LessonComponentBuilders[componentName];
43
- if (self instanceof componentClass) {
44
- return componentName;
45
- }
46
- });
47
-
48
- return <LessonComponentEnum>name;
49
- }
50
-
51
- protected getCode(): LessonComponentConfiguration {
52
- const data = this.formGroup.value;
53
- // Deleting null values
54
- Object.keys(data).forEach((key) => {
55
- if (data[key] === null) {
56
- delete data[key];
57
- }
58
- });
59
- const code: LessonComponentConfiguration = { component: this.questionType, settings: { ...data } as unknown as LessonCompSettings };
60
- return code;
61
- }
62
-
63
- public showCode() {
64
- const code = this.getCode();
65
- const stringCode = `~${JSON.stringify(code)}~`;
66
- alert(stringCode);
67
- }
68
-
69
- public getComponentData(): ComponentBuildData {
70
- const code = this.getCode();
71
- const id = nanoid().replace(/-/g, '_');
72
- code.id = id;
73
- return { str: `~${JSON.stringify(code)}~`, obj: code };
74
- }
75
-
76
- // TODO: for now copyToClipboard is the that that closes modal and return data.
77
- public async copyToClipboard() {
78
- const data = this.getComponentData();
79
- await navigator.clipboard.writeText(data.str);
80
- this.ref.close(data);
81
- }
82
- }