Files
2026-05-05 10:53:52 +02:00

1436 lines
74 KiB
JavaScript

import {
DefaultValueAccessor,
FormsModule,
NgControlStatus,
NgModel
} from "./chunk-VD6QIYHN.js";
import {
getErrorMessage
} from "./chunk-QDZ3GX5R.js";
import {
CourseService
} from "./chunk-6K3TDILH.js";
import {
NzMessageService
} from "./chunk-GJYGTZ7J.js";
import {
ActivatedRoute,
ApiService,
AuthService,
NzIconDirective,
NzIconModule,
Router
} from "./chunk-2TRRHRR7.js";
import "./chunk-EDRPZB37.js";
import {
Component,
Injectable,
forkJoin,
inject,
map,
setClassMetadata,
signal,
ɵsetClassDebugInfo,
ɵɵProvidersFeature,
ɵɵadvance,
ɵɵclassProp,
ɵɵconditional,
ɵɵconditionalCreate,
ɵɵdefineComponent,
ɵɵdefineInjectable,
ɵɵelement,
ɵɵelementEnd,
ɵɵelementStart,
ɵɵgetCurrentView,
ɵɵlistener,
ɵɵnextContext,
ɵɵproperty,
ɵɵrepeater,
ɵɵrepeaterCreate,
ɵɵrepeaterTrackByIdentity,
ɵɵresetView,
ɵɵrestoreView,
ɵɵtext,
ɵɵtextInterpolate,
ɵɵtextInterpolate1
} from "./chunk-WI7WFVZR.js";
import {
__spreadProps,
__spreadValues
} from "./chunk-WDMUDEB6.js";
// src/app/services/topic.service.ts
var TopicService = class _TopicService {
api = inject(ApiService);
createTopic(courseId, title, description, position) {
return this.api.post("/api/topics", { courseId, title, description, position });
}
updateTopic(id, title, description, position) {
return this.api.put(`/api/topics/${id}`, { id, title, description, position });
}
deleteTopic(id) {
return this.api.delete(`/api/topics/${id}`);
}
linkResource(topicId, resourceId, position) {
return this.api.post(`/api/topics/${topicId}/resources/${resourceId}`, { position });
}
unlinkResource(topicId, resourceId) {
return this.api.delete(`/api/topics/${topicId}/resources/${resourceId}`);
}
static \u0275fac = function TopicService_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _TopicService)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _TopicService, factory: _TopicService.\u0275fac, providedIn: "root" });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TopicService, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
// src/app/services/resource.service.ts
var TYPE_TO_INT = {
"Url": 0,
"Video": 1,
"Text": 2,
"File": 3
};
var INT_TO_TYPE = {
0: "Url",
1: "Video",
2: "Text",
3: "File"
};
function normalizeResource(r) {
return __spreadProps(__spreadValues({}, r), {
type: typeof r.type === "number" ? INT_TO_TYPE[r.type] ?? "Url" : r.type
});
}
var ResourceService = class _ResourceService {
api = inject(ApiService);
getResources() {
return this.api.get("/api/resources").pipe(map((list) => list.map(normalizeResource)));
}
createResource(type, title, content) {
return this.api.post("/api/resources", { type: TYPE_TO_INT[type], title, content }).pipe(map(normalizeResource));
}
updateResource(id, type, title, content) {
return this.api.put(`/api/resources/${id}`, { id, type: TYPE_TO_INT[type], title, content }).pipe(map(normalizeResource));
}
deleteResource(id) {
return this.api.delete(`/api/resources/${id}`);
}
static \u0275fac = function ResourceService_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ResourceService)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _ResourceService, factory: _ResourceService.\u0275fac, providedIn: "root" });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ResourceService, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
// src/app/pages/course-editor/course-editor.ts
var _forTrack0 = ($index, $item) => $item.id;
function CourseEditorPage_Conditional_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 1);
\u0275\u0275element(1, "span", 2);
\u0275\u0275elementEnd();
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_20_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Enregistrement... ");
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_21_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0);
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(3);
\u0275\u0275textInterpolate1(" ", ctx_r1.isEditMode() ? "Enregistrer les modifications" : "Cr\xE9er le cours", " ");
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_7_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "p", 19);
\u0275\u0275text(1, "Aucun sujet. Commencez par en ajouter un.");
\u0275\u0275elementEnd();
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Conditional_16_For_2_Template(rf, ctx) {
if (rf & 1) {
const _r6 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 38);
\u0275\u0275element(1, "span", 39);
\u0275\u0275elementStart(2, "span", 40);
\u0275\u0275text(3);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "button", 41);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Conditional_16_For_2_Template_button_click_4_listener($event) {
const resource_r7 = \u0275\u0275restoreView(_r6).$implicit;
const topic_r5 = \u0275\u0275nextContext(2).$implicit;
const ctx_r1 = \u0275\u0275nextContext(5);
return \u0275\u0275resetView(ctx_r1.unlinkResource(topic_r5, resource_r7, $event));
});
\u0275\u0275element(5, "span", 42);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
const resource_r7 = ctx.$implicit;
const ctx_r1 = \u0275\u0275nextContext(7);
\u0275\u0275advance();
\u0275\u0275property("nzType", ctx_r1.getResourceIcon(resource_r7.type));
\u0275\u0275advance(2);
\u0275\u0275textInterpolate(resource_r7.title);
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Conditional_16_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 37);
\u0275\u0275repeaterCreate(1, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Conditional_16_For_2_Template, 6, 2, "div", 38, _forTrack0);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const topic_r5 = \u0275\u0275nextContext().$implicit;
\u0275\u0275advance();
\u0275\u0275repeater(topic_r5.resources);
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Template(rf, ctx) {
if (rf & 1) {
const _r4 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 25)(1, "div", 26)(2, "div", 27);
\u0275\u0275text(3);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "div", 28)(5, "p", 29);
\u0275\u0275text(6);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(7, "span", 30);
\u0275\u0275text(8);
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(9, "div", 31)(10, "button", 32);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Template_button_click_10_listener($event) {
const topic_r5 = \u0275\u0275restoreView(_r4).$implicit;
const ctx_r1 = \u0275\u0275nextContext(5);
return \u0275\u0275resetView(ctx_r1.openLinkResource(topic_r5, $event));
});
\u0275\u0275element(11, "span", 33);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(12, "button", 34);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Template_button_click_12_listener($event) {
const topic_r5 = \u0275\u0275restoreView(_r4).$implicit;
const ctx_r1 = \u0275\u0275nextContext(5);
return \u0275\u0275resetView(ctx_r1.openEditTopic(topic_r5, $event));
});
\u0275\u0275element(13, "span", 35);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(14, "button", 36);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Template_button_click_14_listener($event) {
const topic_r5 = \u0275\u0275restoreView(_r4).$implicit;
const ctx_r1 = \u0275\u0275nextContext(5);
return \u0275\u0275resetView(ctx_r1.deleteTopic(topic_r5, $event));
});
\u0275\u0275element(15, "span", 24);
\u0275\u0275elementEnd()()();
\u0275\u0275conditionalCreate(16, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Conditional_16_Template, 3, 0, "div", 37);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const topic_r5 = ctx.$implicit;
\u0275\u0275advance(3);
\u0275\u0275textInterpolate(topic_r5.position);
\u0275\u0275advance(3);
\u0275\u0275textInterpolate(topic_r5.title);
\u0275\u0275advance(2);
\u0275\u0275textInterpolate1("", topic_r5.resources.length, " ressource(s)");
\u0275\u0275advance(8);
\u0275\u0275conditional(topic_r5.resources.length > 0 ? 16 : -1);
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275repeaterCreate(0, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_For_1_Template, 17, 4, "div", 25, _forTrack0);
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(4);
\u0275\u0275repeater(ctx_r1.course().topics);
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_16_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "p", 19);
\u0275\u0275text(1, "Cr\xE9ez des ressources pour les lier aux sujets.");
\u0275\u0275elementEnd();
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_17_For_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 25)(1, "div", 26)(2, "div", 43);
\u0275\u0275element(3, "span", 39);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "div", 28)(5, "p", 29);
\u0275\u0275text(6);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(7, "span", 30);
\u0275\u0275text(8);
\u0275\u0275elementEnd()()()();
}
if (rf & 2) {
const resource_r8 = ctx.$implicit;
const ctx_r1 = \u0275\u0275nextContext(5);
\u0275\u0275advance(3);
\u0275\u0275property("nzType", ctx_r1.getResourceIcon(resource_r8.type));
\u0275\u0275advance(3);
\u0275\u0275textInterpolate(resource_r8.title);
\u0275\u0275advance(2);
\u0275\u0275textInterpolate(resource_r8.type);
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_17_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275repeaterCreate(0, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_17_For_1_Template, 9, 3, "div", 25, _forTrack0);
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(4);
\u0275\u0275repeater(ctx_r1.allResources());
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_19_Conditional_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Publication... ");
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_19_Conditional_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Publier le cours ");
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_19_Template(rf, ctx) {
if (rf & 1) {
const _r9 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "button", 44);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_19_Template_button_click_0_listener() {
\u0275\u0275restoreView(_r9);
const ctx_r1 = \u0275\u0275nextContext(4);
return \u0275\u0275resetView(ctx_r1.publishCourse());
});
\u0275\u0275conditionalCreate(1, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_19_Conditional_1_Template, 1, 0)(2, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_19_Conditional_2_Template, 1, 0);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(4);
\u0275\u0275property("disabled", ctx_r1.publishing());
\u0275\u0275advance();
\u0275\u0275conditional(ctx_r1.publishing() ? 1 : 2);
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_20_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 22);
\u0275\u0275text(1, "Cours publi\xE9");
\u0275\u0275elementEnd();
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Template(rf, ctx) {
if (rf & 1) {
const _r3 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 9)(1, "div", 16)(2, "h2", 10);
\u0275\u0275text(3);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "button", 17);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Template_button_click_4_listener() {
\u0275\u0275restoreView(_r3);
const ctx_r1 = \u0275\u0275nextContext(3);
return \u0275\u0275resetView(ctx_r1.openAddTopic());
});
\u0275\u0275element(5, "span", 18);
\u0275\u0275text(6, " Ajouter ");
\u0275\u0275elementEnd()();
\u0275\u0275conditionalCreate(7, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_7_Template, 2, 0, "p", 19)(8, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_8_Template, 2, 0);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(9, "div", 9)(10, "div", 16)(11, "h2", 10);
\u0275\u0275text(12);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(13, "button", 17);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Template_button_click_13_listener() {
\u0275\u0275restoreView(_r3);
const ctx_r1 = \u0275\u0275nextContext(3);
return \u0275\u0275resetView(ctx_r1.openAddResource());
});
\u0275\u0275element(14, "span", 18);
\u0275\u0275text(15, " Nouvelle ");
\u0275\u0275elementEnd()();
\u0275\u0275conditionalCreate(16, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_16_Template, 2, 0, "p", 19)(17, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_17_Template, 2, 0);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(18, "div", 20);
\u0275\u0275conditionalCreate(19, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_19_Template, 3, 2, "button", 21)(20, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Conditional_20_Template, 2, 0, "div", 22);
\u0275\u0275elementStart(21, "button", 23);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Template_button_click_21_listener() {
\u0275\u0275restoreView(_r3);
const ctx_r1 = \u0275\u0275nextContext(3);
return \u0275\u0275resetView(ctx_r1.deleteCourse());
});
\u0275\u0275element(22, "span", 24);
\u0275\u0275text(23, " Supprimer le cours ");
\u0275\u0275elementEnd()();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(3);
\u0275\u0275advance(3);
\u0275\u0275textInterpolate1("Sujets (", ctx_r1.course().topics.length, ")");
\u0275\u0275advance(4);
\u0275\u0275conditional(ctx_r1.course().topics.length === 0 ? 7 : 8);
\u0275\u0275advance(5);
\u0275\u0275textInterpolate1("Ressources (", ctx_r1.allResources().length, ")");
\u0275\u0275advance(4);
\u0275\u0275conditional(ctx_r1.allResources().length === 0 ? 16 : 17);
\u0275\u0275advance(3);
\u0275\u0275conditional(ctx_r1.course().status === "Draft" ? 19 : 20);
}
}
function CourseEditorPage_Conditional_2_Conditional_0_Template(rf, ctx) {
if (rf & 1) {
const _r1 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 3)(1, "div", 4)(2, "button", 5);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Template_button_click_2_listener() {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.goBack());
});
\u0275\u0275element(3, "span", 6);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "h1", 7);
\u0275\u0275text(5);
\u0275\u0275elementEnd();
\u0275\u0275element(6, "div");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(7, "div", 8)(8, "div", 9)(9, "h2", 10);
\u0275\u0275text(10, "Informations");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(11, "div", 11)(12, "label", 12);
\u0275\u0275text(13, "Titre du cours");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(14, "input", 13);
\u0275\u0275listener("ngModelChange", function CourseEditorPage_Conditional_2_Conditional_0_Template_input_ngModelChange_14_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.courseTitle.set($event));
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(15, "div", 11)(16, "label", 12);
\u0275\u0275text(17, "Description");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(18, "textarea", 14);
\u0275\u0275listener("ngModelChange", function CourseEditorPage_Conditional_2_Conditional_0_Template_textarea_ngModelChange_18_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.courseDescription.set($event));
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(19, "button", 15);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_0_Template_button_click_19_listener() {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.saveCourse());
});
\u0275\u0275conditionalCreate(20, CourseEditorPage_Conditional_2_Conditional_0_Conditional_20_Template, 1, 0)(21, CourseEditorPage_Conditional_2_Conditional_0_Conditional_21_Template, 1, 1);
\u0275\u0275elementEnd()();
\u0275\u0275conditionalCreate(22, CourseEditorPage_Conditional_2_Conditional_0_Conditional_22_Template, 24, 5);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(2);
\u0275\u0275advance(5);
\u0275\u0275textInterpolate1(" ", ctx_r1.isEditMode() ? "Modifier le cours" : "Nouveau cours", " ");
\u0275\u0275advance(9);
\u0275\u0275property("ngModel", ctx_r1.courseTitle());
\u0275\u0275advance(4);
\u0275\u0275property("ngModel", ctx_r1.courseDescription());
\u0275\u0275advance();
\u0275\u0275property("disabled", ctx_r1.saving());
\u0275\u0275advance();
\u0275\u0275conditional(ctx_r1.saving() ? 20 : 21);
\u0275\u0275advance(2);
\u0275\u0275conditional(ctx_r1.isEditMode() && ctx_r1.course() ? 22 : -1);
}
}
function CourseEditorPage_Conditional_2_Conditional_1_Conditional_18_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Enregistrement... ");
}
}
function CourseEditorPage_Conditional_2_Conditional_1_Conditional_19_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0);
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(3);
\u0275\u0275textInterpolate1(" ", ctx_r1.editingTopicId() ? "Mettre \xE0 jour" : "Ajouter le sujet", " ");
}
}
function CourseEditorPage_Conditional_2_Conditional_1_Template(rf, ctx) {
if (rf & 1) {
const _r10 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 3)(1, "div", 4)(2, "button", 5);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_1_Template_button_click_2_listener() {
\u0275\u0275restoreView(_r10);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.cancelMode());
});
\u0275\u0275element(3, "span", 6);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "h1", 7);
\u0275\u0275text(5);
\u0275\u0275elementEnd();
\u0275\u0275element(6, "div");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(7, "div", 8)(8, "div", 9)(9, "div", 11)(10, "label", 12);
\u0275\u0275text(11, "Titre du sujet");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(12, "input", 45);
\u0275\u0275listener("ngModelChange", function CourseEditorPage_Conditional_2_Conditional_1_Template_input_ngModelChange_12_listener($event) {
\u0275\u0275restoreView(_r10);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.topicTitle.set($event));
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(13, "div", 11)(14, "label", 12);
\u0275\u0275text(15, "Description (optionnel)");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(16, "textarea", 46);
\u0275\u0275listener("ngModelChange", function CourseEditorPage_Conditional_2_Conditional_1_Template_textarea_ngModelChange_16_listener($event) {
\u0275\u0275restoreView(_r10);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.topicDescription.set($event));
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(17, "button", 15);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_1_Template_button_click_17_listener() {
\u0275\u0275restoreView(_r10);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.saveTopic());
});
\u0275\u0275conditionalCreate(18, CourseEditorPage_Conditional_2_Conditional_1_Conditional_18_Template, 1, 0)(19, CourseEditorPage_Conditional_2_Conditional_1_Conditional_19_Template, 1, 1);
\u0275\u0275elementEnd()()();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(2);
\u0275\u0275advance(5);
\u0275\u0275textInterpolate1(" ", ctx_r1.editingTopicId() ? "Modifier le sujet" : "Nouveau sujet", " ");
\u0275\u0275advance(7);
\u0275\u0275property("ngModel", ctx_r1.topicTitle());
\u0275\u0275advance(4);
\u0275\u0275property("ngModel", ctx_r1.topicDescription());
\u0275\u0275advance();
\u0275\u0275property("disabled", ctx_r1.saving());
\u0275\u0275advance();
\u0275\u0275conditional(ctx_r1.saving() ? 18 : 19);
}
}
function CourseEditorPage_Conditional_2_Conditional_2_For_14_Template(rf, ctx) {
if (rf & 1) {
const _r12 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "button", 52);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_2_For_14_Template_button_click_0_listener() {
const type_r13 = \u0275\u0275restoreView(_r12).$implicit;
const ctx_r1 = \u0275\u0275nextContext(3);
return \u0275\u0275resetView(ctx_r1.resourceType.set(type_r13));
});
\u0275\u0275element(1, "span", 39);
\u0275\u0275text(2);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const type_r13 = ctx.$implicit;
const ctx_r1 = \u0275\u0275nextContext(3);
\u0275\u0275classProp("active", ctx_r1.resourceType() === type_r13);
\u0275\u0275advance();
\u0275\u0275property("nzType", ctx_r1.getResourceIcon(type_r13));
\u0275\u0275advance();
\u0275\u0275textInterpolate1(" ", type_r13, " ");
}
}
function CourseEditorPage_Conditional_2_Conditional_2_Conditional_21_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Contenu (texte/markdown) ");
}
}
function CourseEditorPage_Conditional_2_Conditional_2_Conditional_22_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Chemin ou URL du fichier ");
}
}
function CourseEditorPage_Conditional_2_Conditional_2_Conditional_23_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " URL ");
}
}
function CourseEditorPage_Conditional_2_Conditional_2_Conditional_24_Template(rf, ctx) {
if (rf & 1) {
const _r14 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "textarea", 53);
\u0275\u0275listener("ngModelChange", function CourseEditorPage_Conditional_2_Conditional_2_Conditional_24_Template_textarea_ngModelChange_0_listener($event) {
\u0275\u0275restoreView(_r14);
const ctx_r1 = \u0275\u0275nextContext(3);
return \u0275\u0275resetView(ctx_r1.resourceContent.set($event));
});
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(3);
\u0275\u0275property("ngModel", ctx_r1.resourceContent());
}
}
function CourseEditorPage_Conditional_2_Conditional_2_Conditional_25_Template(rf, ctx) {
if (rf & 1) {
const _r15 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "input", 54);
\u0275\u0275listener("ngModelChange", function CourseEditorPage_Conditional_2_Conditional_2_Conditional_25_Template_input_ngModelChange_0_listener($event) {
\u0275\u0275restoreView(_r15);
const ctx_r1 = \u0275\u0275nextContext(3);
return \u0275\u0275resetView(ctx_r1.resourceContent.set($event));
});
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(3);
\u0275\u0275property("ngModel", ctx_r1.resourceContent());
}
}
function CourseEditorPage_Conditional_2_Conditional_2_Conditional_27_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Enregistrement... ");
}
}
function CourseEditorPage_Conditional_2_Conditional_2_Conditional_28_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Cr\xE9er la ressource ");
}
}
function CourseEditorPage_Conditional_2_Conditional_2_Template(rf, ctx) {
if (rf & 1) {
const _r11 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 3)(1, "div", 4)(2, "button", 5);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_2_Template_button_click_2_listener() {
\u0275\u0275restoreView(_r11);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.cancelMode());
});
\u0275\u0275element(3, "span", 6);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "h1", 7);
\u0275\u0275text(5, "Nouvelle ressource");
\u0275\u0275elementEnd();
\u0275\u0275element(6, "div");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(7, "div", 8)(8, "div", 9)(9, "div", 11)(10, "label", 12);
\u0275\u0275text(11, "Type");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(12, "div", 47);
\u0275\u0275repeaterCreate(13, CourseEditorPage_Conditional_2_Conditional_2_For_14_Template, 3, 4, "button", 48, \u0275\u0275repeaterTrackByIdentity);
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(15, "div", 11)(16, "label", 12);
\u0275\u0275text(17, "Titre");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(18, "input", 49);
\u0275\u0275listener("ngModelChange", function CourseEditorPage_Conditional_2_Conditional_2_Template_input_ngModelChange_18_listener($event) {
\u0275\u0275restoreView(_r11);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.resourceTitle.set($event));
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(19, "div", 11)(20, "label", 12);
\u0275\u0275conditionalCreate(21, CourseEditorPage_Conditional_2_Conditional_2_Conditional_21_Template, 1, 0)(22, CourseEditorPage_Conditional_2_Conditional_2_Conditional_22_Template, 1, 0)(23, CourseEditorPage_Conditional_2_Conditional_2_Conditional_23_Template, 1, 0);
\u0275\u0275elementEnd();
\u0275\u0275conditionalCreate(24, CourseEditorPage_Conditional_2_Conditional_2_Conditional_24_Template, 1, 1, "textarea", 50)(25, CourseEditorPage_Conditional_2_Conditional_2_Conditional_25_Template, 1, 1, "input", 51);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(26, "button", 15);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_2_Template_button_click_26_listener() {
\u0275\u0275restoreView(_r11);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.saveResource());
});
\u0275\u0275conditionalCreate(27, CourseEditorPage_Conditional_2_Conditional_2_Conditional_27_Template, 1, 0)(28, CourseEditorPage_Conditional_2_Conditional_2_Conditional_28_Template, 1, 0);
\u0275\u0275elementEnd()()();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(2);
\u0275\u0275advance(13);
\u0275\u0275repeater(ctx_r1.resourceTypes);
\u0275\u0275advance(5);
\u0275\u0275property("ngModel", ctx_r1.resourceTitle());
\u0275\u0275advance(3);
\u0275\u0275conditional(ctx_r1.resourceType() === "Text" ? 21 : ctx_r1.resourceType() === "File" ? 22 : 23);
\u0275\u0275advance(3);
\u0275\u0275conditional(ctx_r1.resourceType() === "Text" ? 24 : 25);
\u0275\u0275advance(2);
\u0275\u0275property("disabled", ctx_r1.saving());
\u0275\u0275advance();
\u0275\u0275conditional(ctx_r1.saving() ? 27 : 28);
}
}
function CourseEditorPage_Conditional_2_Conditional_3_Conditional_12_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 9)(1, "p", 19);
\u0275\u0275text(2, "Aucune ressource disponible. Cr\xE9ez-en une d'abord.");
\u0275\u0275elementEnd()();
}
}
function CourseEditorPage_Conditional_2_Conditional_3_Conditional_13_For_2_Conditional_8_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275element(0, "span", 62);
}
}
function CourseEditorPage_Conditional_2_Conditional_3_Conditional_13_For_2_Template(rf, ctx) {
if (rf & 1) {
const _r17 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 58);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_3_Conditional_13_For_2_Template_div_click_0_listener() {
const resource_r18 = \u0275\u0275restoreView(_r17).$implicit;
const ctx_r1 = \u0275\u0275nextContext(4);
return \u0275\u0275resetView(!ctx_r1.isResourceLinked(resource_r18) && ctx_r1.linkResource(resource_r18));
});
\u0275\u0275elementStart(1, "div", 43);
\u0275\u0275element(2, "span", 39);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(3, "div", 59)(4, "p", 60);
\u0275\u0275text(5);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(6, "span", 61);
\u0275\u0275text(7);
\u0275\u0275elementEnd()();
\u0275\u0275conditionalCreate(8, CourseEditorPage_Conditional_2_Conditional_3_Conditional_13_For_2_Conditional_8_Template, 1, 0, "span", 62);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const resource_r18 = ctx.$implicit;
const ctx_r1 = \u0275\u0275nextContext(4);
\u0275\u0275classProp("linked", ctx_r1.isResourceLinked(resource_r18));
\u0275\u0275advance(2);
\u0275\u0275property("nzType", ctx_r1.getResourceIcon(resource_r18.type));
\u0275\u0275advance(3);
\u0275\u0275textInterpolate(resource_r18.title);
\u0275\u0275advance(2);
\u0275\u0275textInterpolate(resource_r18.type);
\u0275\u0275advance();
\u0275\u0275conditional(ctx_r1.isResourceLinked(resource_r18) ? 8 : -1);
}
}
function CourseEditorPage_Conditional_2_Conditional_3_Conditional_13_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 56);
\u0275\u0275repeaterCreate(1, CourseEditorPage_Conditional_2_Conditional_3_Conditional_13_For_2_Template, 9, 6, "div", 57, _forTrack0);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(3);
\u0275\u0275advance();
\u0275\u0275repeater(ctx_r1.allResources());
}
}
function CourseEditorPage_Conditional_2_Conditional_3_Template(rf, ctx) {
if (rf & 1) {
const _r16 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 3)(1, "div", 4)(2, "button", 5);
\u0275\u0275listener("click", function CourseEditorPage_Conditional_2_Conditional_3_Template_button_click_2_listener() {
\u0275\u0275restoreView(_r16);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.cancelMode());
});
\u0275\u0275element(3, "span", 6);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "h1", 7);
\u0275\u0275text(5, "Lier une ressource");
\u0275\u0275elementEnd();
\u0275\u0275element(6, "div");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(7, "p", 55);
\u0275\u0275text(8, "Sujet : ");
\u0275\u0275elementStart(9, "strong");
\u0275\u0275text(10);
\u0275\u0275elementEnd()()();
\u0275\u0275elementStart(11, "div", 8);
\u0275\u0275conditionalCreate(12, CourseEditorPage_Conditional_2_Conditional_3_Conditional_12_Template, 3, 0, "div", 9)(13, CourseEditorPage_Conditional_2_Conditional_3_Conditional_13_Template, 3, 0, "div", 56);
\u0275\u0275elementEnd();
}
if (rf & 2) {
let tmp_2_0;
const ctx_r1 = \u0275\u0275nextContext(2);
\u0275\u0275advance(10);
\u0275\u0275textInterpolate((tmp_2_0 = ctx_r1.selectedTopic()) == null ? null : tmp_2_0.title);
\u0275\u0275advance(2);
\u0275\u0275conditional(ctx_r1.allResources().length === 0 ? 12 : 13);
}
}
function CourseEditorPage_Conditional_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275conditionalCreate(0, CourseEditorPage_Conditional_2_Conditional_0_Template, 23, 6);
\u0275\u0275conditionalCreate(1, CourseEditorPage_Conditional_2_Conditional_1_Template, 20, 5);
\u0275\u0275conditionalCreate(2, CourseEditorPage_Conditional_2_Conditional_2_Template, 29, 5);
\u0275\u0275conditionalCreate(3, CourseEditorPage_Conditional_2_Conditional_3_Template, 14, 2);
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275conditional(ctx_r1.mode() === "course" ? 0 : -1);
\u0275\u0275advance();
\u0275\u0275conditional(ctx_r1.mode() === "topic" ? 1 : -1);
\u0275\u0275advance();
\u0275\u0275conditional(ctx_r1.mode() === "resource" ? 2 : -1);
\u0275\u0275advance();
\u0275\u0275conditional(ctx_r1.mode() === "link-resource" ? 3 : -1);
}
}
var CourseEditorPage = class _CourseEditorPage {
route = inject(ActivatedRoute);
router = inject(Router);
courseService = inject(CourseService);
topicService = inject(TopicService);
resourceService = inject(ResourceService);
authService = inject(AuthService);
message = inject(NzMessageService);
// State
isEditMode = signal(false, ...ngDevMode ? [{ debugName: "isEditMode" }] : []);
loading = signal(true, ...ngDevMode ? [{ debugName: "loading" }] : []);
saving = signal(false, ...ngDevMode ? [{ debugName: "saving" }] : []);
publishing = signal(false, ...ngDevMode ? [{ debugName: "publishing" }] : []);
mode = signal("course", ...ngDevMode ? [{ debugName: "mode" }] : []);
course = signal(null, ...ngDevMode ? [{ debugName: "course" }] : []);
allResources = signal([], ...ngDevMode ? [{ debugName: "allResources" }] : []);
selectedTopic = signal(null, ...ngDevMode ? [{ debugName: "selectedTopic" }] : []);
// Course form
courseTitle = signal("", ...ngDevMode ? [{ debugName: "courseTitle" }] : []);
courseDescription = signal("", ...ngDevMode ? [{ debugName: "courseDescription" }] : []);
// Topic form
topicTitle = signal("", ...ngDevMode ? [{ debugName: "topicTitle" }] : []);
topicDescription = signal("", ...ngDevMode ? [{ debugName: "topicDescription" }] : []);
editingTopicId = signal(null, ...ngDevMode ? [{ debugName: "editingTopicId" }] : []);
// Resource form
resourceType = signal("Url", ...ngDevMode ? [{ debugName: "resourceType" }] : []);
resourceTitle = signal("", ...ngDevMode ? [{ debugName: "resourceTitle" }] : []);
resourceContent = signal("", ...ngDevMode ? [{ debugName: "resourceContent" }] : []);
editingResourceId = signal(null, ...ngDevMode ? [{ debugName: "editingResourceId" }] : []);
resourceTypes = ["Url", "Video", "Text", "File"];
get currentUser() {
return this.authService.currentUser();
}
ngOnInit() {
const id = this.route.snapshot.paramMap.get("id");
if (id) {
this.isEditMode.set(true);
this.loadCourse(id);
} else {
this.loading.set(false);
}
}
loadCourse(id) {
this.loading.set(true);
forkJoin([
this.courseService.getCourseById(id),
this.resourceService.getResources()
]).subscribe({
next: ([course, resources]) => {
this.course.set(course);
this.courseTitle.set(course.title);
this.courseDescription.set(course.description);
this.allResources.set(resources);
this.loading.set(false);
},
error: () => {
this.loading.set(false);
this.message.error("Cours introuvable");
this.router.navigate(["/catalog"]);
}
});
}
// -- Course actions --
saveCourse() {
if (!this.courseTitle().trim()) {
this.message.warning("Le titre est requis");
return;
}
this.saving.set(true);
const user = this.currentUser;
if (this.isEditMode()) {
const id = this.course().id;
this.courseService.updateCourse(id, this.courseTitle(), this.courseDescription()).subscribe({
next: (updated) => {
this.course.update((c) => c ? __spreadProps(__spreadValues({}, c), { title: updated.title, description: updated.description }) : c);
this.saving.set(false);
this.message.success("Cours mis \xE0 jour");
},
error: () => {
this.saving.set(false);
this.message.error("Erreur lors de la mise \xE0 jour");
}
});
} else {
if (!user)
return;
this.courseService.createCourse(this.courseTitle(), this.courseDescription(), user.userId).subscribe({
next: (created) => {
this.saving.set(false);
this.message.success("Cours cr\xE9\xE9 !");
this.router.navigate(["/courses", created.id, "edit"]);
},
error: (err) => {
this.saving.set(false);
this.message.error(getErrorMessage(err, "Erreur lors de la cr\xE9ation"));
}
});
}
}
publishCourse() {
const course = this.course();
if (!course)
return;
this.publishing.set(true);
this.courseService.publishCourse(course.id).subscribe({
next: (updated) => {
this.course.update((c) => c ? __spreadProps(__spreadValues({}, c), { status: updated.status }) : c);
this.publishing.set(false);
this.message.success("Cours publi\xE9 !");
},
error: (err) => {
this.publishing.set(false);
this.message.error(getErrorMessage(err, "Impossible de publier le cours"));
}
});
}
deleteCourse() {
const course = this.course();
if (!course)
return;
this.courseService.deleteCourse(course.id).subscribe({
next: () => {
this.message.success("Cours supprim\xE9");
this.router.navigate(["/catalog"]);
},
error: (err) => {
this.message.error(getErrorMessage(err, "Impossible de supprimer le cours"));
}
});
}
// -- Topic actions --
openAddTopic() {
this.topicTitle.set("");
this.topicDescription.set("");
this.editingTopicId.set(null);
this.mode.set("topic");
}
openEditTopic(topic, event) {
event.stopPropagation();
this.topicTitle.set(topic.title);
this.topicDescription.set(topic.description ?? "");
this.editingTopicId.set(topic.id);
this.mode.set("topic");
}
saveTopic() {
if (!this.topicTitle().trim()) {
this.message.warning("Le titre du sujet est requis");
return;
}
const course = this.course();
if (!course)
return;
this.saving.set(true);
const editId = this.editingTopicId();
if (editId) {
const existing = course.topics.find((t) => t.id === editId);
this.topicService.updateTopic(editId, this.topicTitle(), this.topicDescription(), existing.position).subscribe({
next: (updated) => {
this.course.update((c) => c ? __spreadProps(__spreadValues({}, c), {
topics: c.topics.map((t) => t.id === editId ? __spreadValues(__spreadValues({}, t), updated) : t)
}) : c);
this.saving.set(false);
this.mode.set("course");
this.message.success("Sujet mis \xE0 jour");
},
error: () => {
this.saving.set(false);
this.message.error("Erreur lors de la mise \xE0 jour");
}
});
} else {
const position = course.topics.length + 1;
const desc = this.topicDescription().trim() || null;
this.topicService.createTopic(course.id, this.topicTitle(), desc, position).subscribe({
next: (created) => {
this.course.update((c) => c ? __spreadProps(__spreadValues({}, c), {
topics: [...c.topics, __spreadProps(__spreadValues({}, created), { resources: [] })],
topicCount: c.topicCount + 1
}) : c);
this.saving.set(false);
this.mode.set("course");
this.message.success("Sujet ajout\xE9");
},
error: (err) => {
this.saving.set(false);
this.message.error(getErrorMessage(err, "Erreur lors de la cr\xE9ation du sujet"));
}
});
}
}
deleteTopic(topic, event) {
event.stopPropagation();
this.topicService.deleteTopic(topic.id).subscribe({
next: () => {
this.course.update((c) => c ? __spreadProps(__spreadValues({}, c), {
topics: c.topics.filter((t) => t.id !== topic.id),
topicCount: c.topicCount - 1
}) : c);
this.message.success("Sujet supprim\xE9");
},
error: () => this.message.error("Impossible de supprimer ce sujet")
});
}
// -- Resource actions --
openAddResource() {
this.resourceType.set("Url");
this.resourceTitle.set("");
this.resourceContent.set("");
this.editingResourceId.set(null);
this.mode.set("resource");
}
openLinkResource(topic, event) {
event.stopPropagation();
this.selectedTopic.set(topic);
this.resourceService.getResources().subscribe({
next: (resources) => {
this.allResources.set(resources);
this.mode.set("link-resource");
},
error: () => this.message.error("Impossible de charger les ressources")
});
}
saveResource() {
if (!this.resourceTitle().trim() || !this.resourceContent().trim()) {
this.message.warning("Titre et contenu sont requis");
return;
}
this.saving.set(true);
this.resourceService.createResource(this.resourceType(), this.resourceTitle(), this.resourceContent()).subscribe({
next: (created) => {
this.allResources.update((list) => [...list, created]);
this.saving.set(false);
this.mode.set("course");
this.message.success("Ressource cr\xE9\xE9e");
},
error: (err) => {
this.saving.set(false);
this.message.error(getErrorMessage(err, "Erreur lors de la cr\xE9ation de la ressource"));
}
});
}
linkResource(resource) {
const topic = this.selectedTopic();
if (!topic)
return;
const position = topic.resources.length + 1;
this.topicService.linkResource(topic.id, resource.id, position).subscribe({
next: () => {
this.course.update((c) => c ? __spreadProps(__spreadValues({}, c), {
topics: c.topics.map((t) => t.id === topic.id ? __spreadProps(__spreadValues({}, t), { resources: [...t.resources, resource] }) : t)
}) : c);
this.selectedTopic.update((t) => t ? __spreadProps(__spreadValues({}, t), { resources: [...t.resources, resource] }) : t);
this.message.success("Ressource li\xE9e");
},
error: () => this.message.error("Erreur lors de la liaison")
});
}
unlinkResource(topic, resource, event) {
event.stopPropagation();
this.topicService.unlinkResource(topic.id, resource.id).subscribe({
next: () => {
this.course.update((c) => c ? __spreadProps(__spreadValues({}, c), {
topics: c.topics.map((t) => t.id === topic.id ? __spreadProps(__spreadValues({}, t), { resources: t.resources.filter((r) => r.id !== resource.id) }) : t)
}) : c);
this.message.success("Ressource retir\xE9e");
},
error: () => this.message.error("Erreur lors du retrait")
});
}
isResourceLinked(resource) {
return this.selectedTopic()?.resources.some((r) => r.id === resource.id) ?? false;
}
getResourceIcon(type) {
switch (type) {
case "Video":
return "video-camera";
case "Text":
return "file-text";
case "File":
return "file";
default:
return "link";
}
}
cancelMode() {
this.mode.set("course");
}
goBack() {
this.router.navigate(["/catalog"]);
}
static \u0275fac = function CourseEditorPage_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CourseEditorPage)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _CourseEditorPage, selectors: [["app-course-editor"]], features: [\u0275\u0275ProvidersFeature([NzMessageService])], decls: 3, vars: 1, consts: [[1, "page-container", "editor-page"], [1, "loading-screen"], ["nz-icon", "", "nzType", "loading", "nzTheme", "outline", 1, "loading-spin"], [1, "editor-header"], [1, "header-row"], [1, "back-btn", 3, "click"], ["nz-icon", "", "nzType", "arrow-left", "nzTheme", "outline"], [1, "page-title"], [1, "editor-content"], [1, "section-card"], [1, "section-label"], [1, "field-group"], [1, "field-label"], ["type", "text", "placeholder", "Ex: Introduction \xE0 Angular", 1, "mc-input", 3, "ngModelChange", "ngModel"], ["placeholder", "D\xE9crivez votre cours...", "rows", "4", 1, "mc-input", "mc-textarea", 3, "ngModelChange", "ngModel"], [1, "mc-btn-primary", 3, "click", "disabled"], [1, "section-header"], [1, "add-btn", 3, "click"], ["nz-icon", "", "nzType", "plus", "nzTheme", "outline"], [1, "empty-hint"], [1, "section-card", "danger-zone"], [1, "publish-btn", 3, "disabled"], [1, "status-badge", "published"], [1, "delete-btn", 3, "click"], ["nz-icon", "", "nzType", "delete", "nzTheme", "outline"], [1, "topic-item"], [1, "topic-item-header"], [1, "topic-position"], [1, "topic-item-info"], [1, "topic-item-title"], [1, "topic-item-resources"], [1, "topic-item-actions"], ["title", "Lier une ressource", 1, "icon-action", 3, "click"], ["nz-icon", "", "nzType", "link", "nzTheme", "outline"], ["title", "Modifier", 1, "icon-action", 3, "click"], ["nz-icon", "", "nzType", "edit", "nzTheme", "outline"], ["title", "Supprimer", 1, "icon-action", "danger", 3, "click"], [1, "topic-resources"], [1, "resource-chip"], ["nz-icon", "", "nzTheme", "outline", 3, "nzType"], [1, "chip-title"], [1, "chip-remove", 3, "click"], ["nz-icon", "", "nzType", "close", "nzTheme", "outline"], [1, "resource-icon-sm"], [1, "publish-btn", 3, "click", "disabled"], ["type", "text", "placeholder", "Ex: Introduction aux composants", 1, "mc-input", 3, "ngModelChange", "ngModel"], ["placeholder", "Description du sujet...", "rows", "3", 1, "mc-input", "mc-textarea", 3, "ngModelChange", "ngModel"], [1, "type-pills"], [1, "type-pill", 3, "active"], ["type", "text", "placeholder", "Ex: Documentation Angular", 1, "mc-input", 3, "ngModelChange", "ngModel"], ["placeholder", "R\xE9digez le contenu...", "rows", "6", 1, "mc-input", "mc-textarea", 3, "ngModel"], ["type", "url", "placeholder", "https://...", 1, "mc-input", 3, "ngModel"], [1, "type-pill", 3, "click"], ["placeholder", "R\xE9digez le contenu...", "rows", "6", 1, "mc-input", "mc-textarea", 3, "ngModelChange", "ngModel"], ["type", "url", "placeholder", "https://...", 1, "mc-input", 3, "ngModelChange", "ngModel"], [1, "mode-subtitle"], [1, "resources-picker"], [1, "picker-item", 3, "linked"], [1, "picker-item", 3, "click"], [1, "picker-info"], [1, "picker-title"], [1, "picker-type"], ["nz-icon", "", "nzType", "check-circle", "nzTheme", "outline", 1, "linked-icon"]], template: function CourseEditorPage_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 0);
\u0275\u0275conditionalCreate(1, CourseEditorPage_Conditional_1_Template, 2, 0, "div", 1)(2, CourseEditorPage_Conditional_2_Template, 4, 4);
\u0275\u0275elementEnd();
}
if (rf & 2) {
\u0275\u0275advance();
\u0275\u0275conditional(ctx.loading() ? 1 : 2);
}
}, dependencies: [FormsModule, DefaultValueAccessor, NgControlStatus, NgModel, NzIconModule, NzIconDirective], styles: ["\n\n.editor-page[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n padding-bottom: 100px;\n}\n.loading-screen[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n color: #1abc9c;\n}\n.loading-spin[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_spin 1s linear infinite;\n}\n@keyframes _ngcontent-%COMP%_spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n.editor-header[_ngcontent-%COMP%] {\n padding: 16px 20px 0;\n border-bottom: 1px solid var(--border);\n padding-bottom: 16px;\n margin-bottom: 0;\n}\n.header-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0;\n}\n.back-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 18px;\n color: var(--text);\n}\n.page-title[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: var(--text);\n margin: 0;\n}\n.mode-subtitle[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-muted);\n margin: 8px 0 0;\n}\n.editor-content[_ngcontent-%COMP%] {\n padding: 16px 20px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n.section-card[_ngcontent-%COMP%] {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 16px;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n.section-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 700;\n color: var(--text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin: 0;\n}\n.add-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 10px;\n padding: 6px 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n cursor: pointer;\n}\n.field-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.field-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n}\n.mc-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 80px;\n line-height: 1.5;\n}\n.topic-item[_ngcontent-%COMP%] {\n border: 1px solid var(--border);\n border-radius: 12px;\n overflow: hidden;\n}\n.topic-item-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background: var(--bg);\n}\n.topic-position[_ngcontent-%COMP%] {\n width: 26px;\n height: 26px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 700;\n color: var(--text-muted);\n flex-shrink: 0;\n}\n.topic-item-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n.topic-item-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--text);\n margin: 0 0 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.topic-item-resources[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--text-muted);\n}\n.topic-item-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n.icon-action[_ngcontent-%COMP%] {\n width: 30px;\n height: 30px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 14px;\n color: var(--text-muted);\n}\n.icon-action.danger[_ngcontent-%COMP%] {\n color: #ff4d4f;\n}\n.topic-resources[_ngcontent-%COMP%] {\n padding: 8px 12px;\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n border-top: 1px solid var(--border);\n}\n.resource-chip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 20px;\n padding: 4px 10px;\n font-size: 12px;\n color: var(--text);\n}\n.chip-title[_ngcontent-%COMP%] {\n max-width: 120px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.chip-remove[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--text-muted);\n font-size: 11px;\n padding: 0;\n display: flex;\n align-items: center;\n margin-left: 2px;\n}\n.danger-zone[_ngcontent-%COMP%] {\n gap: 10px;\n}\n.publish-btn[_ngcontent-%COMP%] {\n width: 100%;\n background-color: #1abc9c;\n color: #fff;\n border: none;\n border-radius: 12px;\n padding: 14px;\n font-size: 15px;\n font-weight: 700;\n cursor: pointer;\n transition: opacity 0.2s;\n}\n.publish-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n opacity: 0.85;\n}\n.publish-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.status-badge.published[_ngcontent-%COMP%] {\n text-align: center;\n font-size: 13px;\n font-weight: 700;\n color: #1abc9c;\n background: rgba(26, 188, 156, 0.1);\n border: 1px solid rgba(26, 188, 156, 0.3);\n border-radius: 10px;\n padding: 10px;\n}\n.delete-btn[_ngcontent-%COMP%] {\n width: 100%;\n background: none;\n border: 1px solid #ff4d4f;\n color: #ff4d4f;\n border-radius: 12px;\n padding: 12px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: background 0.2s;\n}\n.delete-btn[_ngcontent-%COMP%]:hover {\n background: rgba(255, 77, 79, 0.08);\n}\n.type-pills[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n.type-pill[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n background: var(--bg);\n border: 1.5px solid var(--border);\n border-radius: 20px;\n padding: 6px 14px;\n font-size: 13px;\n font-weight: 500;\n color: var(--text-muted);\n cursor: pointer;\n transition: all 0.15s;\n}\n.type-pill.active[_ngcontent-%COMP%] {\n background: var(--primary);\n color: var(--primary-fg);\n border-color: var(--primary);\n}\n.resources-picker[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 20px;\n}\n.picker-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 12px;\n cursor: pointer;\n transition: border-color 0.15s;\n}\n.picker-item.linked[_ngcontent-%COMP%] {\n border-color: #1abc9c;\n background: rgba(26, 188, 156, 0.05);\n cursor: default;\n}\n.resource-icon-sm[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: var(--text-muted);\n flex-shrink: 0;\n}\n.picker-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n.picker-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--text);\n margin: 0 0 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.picker-type[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--text-muted);\n}\n.linked-icon[_ngcontent-%COMP%] {\n font-size: 18px;\n color: #1abc9c;\n}\n.empty-hint[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--text-muted);\n margin: 0;\n text-align: center;\n}\n/*# sourceMappingURL=course-editor.css.map */"] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CourseEditorPage, [{
type: Component,
args: [{ selector: "app-course-editor", imports: [FormsModule, NzIconModule], providers: [NzMessageService], template: `<div class="page-container editor-page">
@if (loading()) {
<div class="loading-screen">
<span nz-icon nzType="loading" nzTheme="outline" class="loading-spin"></span>
</div>
} @else {
<!-- COURSE FORM MODE -->
@if (mode() === 'course') {
<div class="editor-header">
<div class="header-row">
<button class="back-btn" (click)="goBack()">
<span nz-icon nzType="arrow-left" nzTheme="outline"></span>
</button>
<h1 class="page-title">
{{ isEditMode() ? 'Modifier le cours' : 'Nouveau cours' }}
</h1>
<div></div>
</div>
</div>
<div class="editor-content">
<!-- Course info form -->
<div class="section-card">
<h2 class="section-label">Informations</h2>
<div class="field-group">
<label class="field-label">Titre du cours</label>
<input
type="text"
class="mc-input"
placeholder="Ex: Introduction \xE0 Angular"
[ngModel]="courseTitle()"
(ngModelChange)="courseTitle.set($event)"
/>
</div>
<div class="field-group">
<label class="field-label">Description</label>
<textarea
class="mc-input mc-textarea"
placeholder="D\xE9crivez votre cours..."
rows="4"
[ngModel]="courseDescription()"
(ngModelChange)="courseDescription.set($event)"
></textarea>
</div>
<button class="mc-btn-primary" (click)="saveCourse()" [disabled]="saving()">
@if (saving()) { Enregistrement... } @else {
{{ isEditMode() ? 'Enregistrer les modifications' : 'Cr\xE9er le cours' }}
}
</button>
</div>
<!-- Topics (edit mode only) -->
@if (isEditMode() && course()) {
<div class="section-card">
<div class="section-header">
<h2 class="section-label">Sujets ({{ course()!.topics.length }})</h2>
<button class="add-btn" (click)="openAddTopic()">
<span nz-icon nzType="plus" nzTheme="outline"></span>
Ajouter
</button>
</div>
@if (course()!.topics.length === 0) {
<p class="empty-hint">Aucun sujet. Commencez par en ajouter un.</p>
} @else {
@for (topic of course()!.topics; track topic.id) {
<div class="topic-item">
<div class="topic-item-header">
<div class="topic-position">{{ topic.position }}</div>
<div class="topic-item-info">
<p class="topic-item-title">{{ topic.title }}</p>
<span class="topic-item-resources">{{ topic.resources.length }} ressource(s)</span>
</div>
<div class="topic-item-actions">
<button class="icon-action" (click)="openLinkResource(topic, $event)" title="Lier une ressource">
<span nz-icon nzType="link" nzTheme="outline"></span>
</button>
<button class="icon-action" (click)="openEditTopic(topic, $event)" title="Modifier">
<span nz-icon nzType="edit" nzTheme="outline"></span>
</button>
<button class="icon-action danger" (click)="deleteTopic(topic, $event)" title="Supprimer">
<span nz-icon nzType="delete" nzTheme="outline"></span>
</button>
</div>
</div>
<!-- Resources of topic -->
@if (topic.resources.length > 0) {
<div class="topic-resources">
@for (resource of topic.resources; track resource.id) {
<div class="resource-chip">
<span nz-icon [nzType]="getResourceIcon(resource.type)" nzTheme="outline"></span>
<span class="chip-title">{{ resource.title }}</span>
<button class="chip-remove" (click)="unlinkResource(topic, resource, $event)">
<span nz-icon nzType="close" nzTheme="outline"></span>
</button>
</div>
}
</div>
}
</div>
}
}
</div>
<!-- Add resource to catalog -->
<div class="section-card">
<div class="section-header">
<h2 class="section-label">Ressources ({{ allResources().length }})</h2>
<button class="add-btn" (click)="openAddResource()">
<span nz-icon nzType="plus" nzTheme="outline"></span>
Nouvelle
</button>
</div>
@if (allResources().length === 0) {
<p class="empty-hint">Cr\xE9ez des ressources pour les lier aux sujets.</p>
} @else {
@for (resource of allResources(); track resource.id) {
<div class="topic-item">
<div class="topic-item-header">
<div class="resource-icon-sm">
<span nz-icon [nzType]="getResourceIcon(resource.type)" nzTheme="outline"></span>
</div>
<div class="topic-item-info">
<p class="topic-item-title">{{ resource.title }}</p>
<span class="topic-item-resources">{{ resource.type }}</span>
</div>
</div>
</div>
}
}
</div>
<!-- Publish / Delete -->
<div class="section-card danger-zone">
@if (course()!.status === 'Draft') {
<button class="publish-btn" (click)="publishCourse()" [disabled]="publishing()">
@if (publishing()) { Publication... } @else { Publier le cours }
</button>
} @else {
<div class="status-badge published">Cours publi\xE9</div>
}
<button class="delete-btn" (click)="deleteCourse()">
<span nz-icon nzType="delete" nzTheme="outline"></span>
Supprimer le cours
</button>
</div>
}
</div>
}
<!-- TOPIC FORM MODE -->
@if (mode() === 'topic') {
<div class="editor-header">
<div class="header-row">
<button class="back-btn" (click)="cancelMode()">
<span nz-icon nzType="arrow-left" nzTheme="outline"></span>
</button>
<h1 class="page-title">
{{ editingTopicId() ? 'Modifier le sujet' : 'Nouveau sujet' }}
</h1>
<div></div>
</div>
</div>
<div class="editor-content">
<div class="section-card">
<div class="field-group">
<label class="field-label">Titre du sujet</label>
<input
type="text"
class="mc-input"
placeholder="Ex: Introduction aux composants"
[ngModel]="topicTitle()"
(ngModelChange)="topicTitle.set($event)"
/>
</div>
<div class="field-group">
<label class="field-label">Description (optionnel)</label>
<textarea
class="mc-input mc-textarea"
placeholder="Description du sujet..."
rows="3"
[ngModel]="topicDescription()"
(ngModelChange)="topicDescription.set($event)"
></textarea>
</div>
<button class="mc-btn-primary" (click)="saveTopic()" [disabled]="saving()">
@if (saving()) { Enregistrement... } @else {
{{ editingTopicId() ? 'Mettre \xE0 jour' : 'Ajouter le sujet' }}
}
</button>
</div>
</div>
}
<!-- RESOURCE FORM MODE -->
@if (mode() === 'resource') {
<div class="editor-header">
<div class="header-row">
<button class="back-btn" (click)="cancelMode()">
<span nz-icon nzType="arrow-left" nzTheme="outline"></span>
</button>
<h1 class="page-title">Nouvelle ressource</h1>
<div></div>
</div>
</div>
<div class="editor-content">
<div class="section-card">
<div class="field-group">
<label class="field-label">Type</label>
<div class="type-pills">
@for (type of resourceTypes; track type) {
<button
class="type-pill"
[class.active]="resourceType() === type"
(click)="resourceType.set(type)"
>
<span nz-icon [nzType]="getResourceIcon(type)" nzTheme="outline"></span>
{{ type }}
</button>
}
</div>
</div>
<div class="field-group">
<label class="field-label">Titre</label>
<input
type="text"
class="mc-input"
placeholder="Ex: Documentation Angular"
[ngModel]="resourceTitle()"
(ngModelChange)="resourceTitle.set($event)"
/>
</div>
<div class="field-group">
<label class="field-label">
@if (resourceType() === 'Text') { Contenu (texte/markdown) }
@else if (resourceType() === 'File') { Chemin ou URL du fichier }
@else { URL }
</label>
@if (resourceType() === 'Text') {
<textarea
class="mc-input mc-textarea"
placeholder="R\xE9digez le contenu..."
rows="6"
[ngModel]="resourceContent()"
(ngModelChange)="resourceContent.set($event)"
></textarea>
} @else {
<input
type="url"
class="mc-input"
placeholder="https://..."
[ngModel]="resourceContent()"
(ngModelChange)="resourceContent.set($event)"
/>
}
</div>
<button class="mc-btn-primary" (click)="saveResource()" [disabled]="saving()">
@if (saving()) { Enregistrement... } @else { Cr\xE9er la ressource }
</button>
</div>
</div>
}
<!-- LINK RESOURCE MODE -->
@if (mode() === 'link-resource') {
<div class="editor-header">
<div class="header-row">
<button class="back-btn" (click)="cancelMode()">
<span nz-icon nzType="arrow-left" nzTheme="outline"></span>
</button>
<h1 class="page-title">Lier une ressource</h1>
<div></div>
</div>
<p class="mode-subtitle">Sujet : <strong>{{ selectedTopic()?.title }}</strong></p>
</div>
<div class="editor-content">
@if (allResources().length === 0) {
<div class="section-card">
<p class="empty-hint">Aucune ressource disponible. Cr\xE9ez-en une d'abord.</p>
</div>
} @else {
<div class="resources-picker">
@for (resource of allResources(); track resource.id) {
<div
class="picker-item"
[class.linked]="isResourceLinked(resource)"
(click)="!isResourceLinked(resource) && linkResource(resource)"
>
<div class="resource-icon-sm">
<span nz-icon [nzType]="getResourceIcon(resource.type)" nzTheme="outline"></span>
</div>
<div class="picker-info">
<p class="picker-title">{{ resource.title }}</p>
<span class="picker-type">{{ resource.type }}</span>
</div>
@if (isResourceLinked(resource)) {
<span nz-icon nzType="check-circle" nzTheme="outline" class="linked-icon"></span>
}
</div>
}
</div>
}
</div>
}
}
</div>
`, styles: ["/* src/app/pages/course-editor/course-editor.css */\n.editor-page {\n display: flex;\n flex-direction: column;\n padding-bottom: 100px;\n}\n.loading-screen {\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n color: #1abc9c;\n}\n.loading-spin {\n animation: spin 1s linear infinite;\n}\n@keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n.editor-header {\n padding: 16px 20px 0;\n border-bottom: 1px solid var(--border);\n padding-bottom: 16px;\n margin-bottom: 0;\n}\n.header-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0;\n}\n.back-btn {\n width: 40px;\n height: 40px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 18px;\n color: var(--text);\n}\n.page-title {\n font-size: 18px;\n font-weight: 700;\n color: var(--text);\n margin: 0;\n}\n.mode-subtitle {\n font-size: 13px;\n color: var(--text-muted);\n margin: 8px 0 0;\n}\n.editor-content {\n padding: 16px 20px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n.section-card {\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 16px;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.section-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n.section-label {\n font-size: 13px;\n font-weight: 700;\n color: var(--text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin: 0;\n}\n.add-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 10px;\n padding: 6px 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n cursor: pointer;\n}\n.field-group {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.field-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n}\n.mc-textarea {\n resize: vertical;\n min-height: 80px;\n line-height: 1.5;\n}\n.topic-item {\n border: 1px solid var(--border);\n border-radius: 12px;\n overflow: hidden;\n}\n.topic-item-header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background: var(--bg);\n}\n.topic-position {\n width: 26px;\n height: 26px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 700;\n color: var(--text-muted);\n flex-shrink: 0;\n}\n.topic-item-info {\n flex: 1;\n min-width: 0;\n}\n.topic-item-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--text);\n margin: 0 0 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.topic-item-resources {\n font-size: 11px;\n color: var(--text-muted);\n}\n.topic-item-actions {\n display: flex;\n gap: 4px;\n}\n.icon-action {\n width: 30px;\n height: 30px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 14px;\n color: var(--text-muted);\n}\n.icon-action.danger {\n color: #ff4d4f;\n}\n.topic-resources {\n padding: 8px 12px;\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n border-top: 1px solid var(--border);\n}\n.resource-chip {\n display: flex;\n align-items: center;\n gap: 5px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 20px;\n padding: 4px 10px;\n font-size: 12px;\n color: var(--text);\n}\n.chip-title {\n max-width: 120px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.chip-remove {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--text-muted);\n font-size: 11px;\n padding: 0;\n display: flex;\n align-items: center;\n margin-left: 2px;\n}\n.danger-zone {\n gap: 10px;\n}\n.publish-btn {\n width: 100%;\n background-color: #1abc9c;\n color: #fff;\n border: none;\n border-radius: 12px;\n padding: 14px;\n font-size: 15px;\n font-weight: 700;\n cursor: pointer;\n transition: opacity 0.2s;\n}\n.publish-btn:hover:not(:disabled) {\n opacity: 0.85;\n}\n.publish-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.status-badge.published {\n text-align: center;\n font-size: 13px;\n font-weight: 700;\n color: #1abc9c;\n background: rgba(26, 188, 156, 0.1);\n border: 1px solid rgba(26, 188, 156, 0.3);\n border-radius: 10px;\n padding: 10px;\n}\n.delete-btn {\n width: 100%;\n background: none;\n border: 1px solid #ff4d4f;\n color: #ff4d4f;\n border-radius: 12px;\n padding: 12px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: background 0.2s;\n}\n.delete-btn:hover {\n background: rgba(255, 77, 79, 0.08);\n}\n.type-pills {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n.type-pill {\n display: flex;\n align-items: center;\n gap: 5px;\n background: var(--bg);\n border: 1.5px solid var(--border);\n border-radius: 20px;\n padding: 6px 14px;\n font-size: 13px;\n font-weight: 500;\n color: var(--text-muted);\n cursor: pointer;\n transition: all 0.15s;\n}\n.type-pill.active {\n background: var(--primary);\n color: var(--primary-fg);\n border-color: var(--primary);\n}\n.resources-picker {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 20px;\n}\n.picker-item {\n display: flex;\n align-items: center;\n gap: 10px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: 12px;\n padding: 12px;\n cursor: pointer;\n transition: border-color 0.15s;\n}\n.picker-item.linked {\n border-color: #1abc9c;\n background: rgba(26, 188, 156, 0.05);\n cursor: default;\n}\n.resource-icon-sm {\n width: 36px;\n height: 36px;\n background: var(--bg);\n border: 1px solid var(--border);\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: var(--text-muted);\n flex-shrink: 0;\n}\n.picker-info {\n flex: 1;\n min-width: 0;\n}\n.picker-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--text);\n margin: 0 0 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.picker-type {\n font-size: 11px;\n color: var(--text-muted);\n}\n.linked-icon {\n font-size: 18px;\n color: #1abc9c;\n}\n.empty-hint {\n font-size: 13px;\n color: var(--text-muted);\n margin: 0;\n text-align: center;\n}\n/*# sourceMappingURL=course-editor.css.map */\n"] }]
}], null, null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(CourseEditorPage, { className: "CourseEditorPage", filePath: "src/app/pages/course-editor/course-editor.ts", lineNumber: 23 });
})();
// src/app/pages/course-editor/course-editor.routes.ts
var COURSE_EDITOR_ROUTES = [
{ path: "", component: CourseEditorPage }
];
export {
COURSE_EDITOR_ROUTES
};
//# sourceMappingURL=chunk-OVXDZVBT.js.map