PageSourceSearch

https://stridenavigation.com/chunk-BYDHXBHJ.js

js stridenavigation.com collected 2026-09-24 14:53:37 UTC 34,018 bytes, 783 lines download raw bytes

1import {
2  v4_default
3} from "./chunk-33EQSEY6.js";
4import {
5  AlertController,
6  IonBackButton,
7  IonBadge,
8  IonButton,
9  IonButtons,
10  IonContent,
11  IonHeader,
12  IonInput,
13  IonItem,
14  IonLabel,
15  IonList,
16  IonSpinner,
17  IonTextarea,
18  IonTitle,
19  IonToggle,
20  IonToolbar,
21  ToastController
22} from "./chunk-RLZ522BW.js";
23import {
24  DatabaseService,
25  EntityType
26} from "./chunk-RLJCY5HS.js";
27import {
28  TranslateModule,
29  TranslatePipe,
30  TranslateService
31} from "./chunk-O5XYYQCR.js";
32import {
33  AuthService,
34  News,
35  UserRole
36} from "./chunk-QGEJYSW7.js";
37import {
38  ApiUrlService
39} from "./chunk-MAIAEXGG.js";
40import "./chunk-L4O6SE3A.js";
41import {
42  NgIcon,
43  lucideCalendar,
44  lucideImage,
45  lucidePencil,
46  lucideSave,
47  lucideStar,
48  lucideTrash2,
49  lucideUser,
50  lucideX,
51  provideIcons
52} from "./chunk-GMPIA5L4.js";
53import {
54  ActivatedRoute,
55  CommonModule,
56  Component,
57  DatePipe,
58  FormsModule,
59  Location,
60  NgControlStatus,
61  NgModel,
62  RequiredValidator,
63  Router,
64  Subject,
65  setClassMetadata,
66  takeUntil,
67  ɵsetClassDebugInfo,
68  ɵɵProvidersFeature,
69  ɵɵadvance,
70  ɵɵconditional,
71  ɵɵdefineComponent,
72  ɵɵdirectiveInject,
73  ɵɵelement,
74  ɵɵelementEnd,
75  ɵɵelementStart,
76  ɵɵgetCurrentView,
77  ɵɵlistener,
78  ɵɵnextContext,
79  ɵɵpipe,
80  ɵɵpipeBind1,
81  ɵɵpipeBind2,
82  ɵɵproperty,
83  ɵɵresetView,
84  ɵɵrestoreView,
85  ɵɵsanitizeUrl,
86  ɵɵtemplate,
87  ɵɵtext,
88  ɵɵtextInterpolate,
89  ɵɵtextInterpolate1,
90  ɵɵtextInterpolate2,
91  ɵɵtwoWayBindingSet,
92  ɵɵtwoWayListener,
93  ɵɵtwoWayProperty
94} from "./chunk-UQ6LLOJ6.js";
95import "./chunk-V3YFOG6Q.js";
96import "./chunk-LPMBLWVS.js";
97import "./chunk-S6LHOZ5A.js";
98import "./chunk-Y6HZOH3Q.js";
99import "./chunk-TWQHADEW.js";
100import "./chunk-3J4L7S6G.js";
101import "./chunk-IL42VKT6.js";
102import "./chunk-LONO5O5R.js";
103import "./chunk-KFBF5L4X.js";
104import "./chunk-PWC4K6CW.js";
105import "./chunk-R6JLIESI.js";
106import "./chunk-UG6K57PI.js";
107import "./chunk-UR6VIRNL.js";
108import "./chunk-OJO5RD3M.js";
109import {
110  __async
111} from "./chunk-CO64IJQE.js";
112
113// src/app/pages/news-detail/news-detail.page.ts
114function NewsDetailPage_Conditional_7_Template(rf, ctx) {
115  if (rf & 1) {
116    const _r1 = \u0275\u0275getCurrentView();
117    \u0275\u0275elementStart(0, "ion-button", 7);
118    \u0275\u0275listener("click", function NewsDetailPage_Conditional_7_Template_ion_button_click_0_listener() {
119      \u0275\u0275restoreView(_r1);
120      const ctx_r1 = \u0275\u0275nextContext();
121      return \u0275\u0275resetView(ctx_r1.enterEditMode());
122    });
123    \u0275\u0275element(1, "ng-icon", 8);
124    \u0275\u0275elementEnd();
125  }
126}
127function NewsDetailPage_Conditional_8_Conditional_1_Template(rf, ctx) {
128  if (rf & 1) {
129    \u0275\u0275element(0, "ion-spinner", 10);
130  }
131}
132function NewsDetailPage_Conditional_8_Conditional_2_Template(rf, ctx) {
133  if (rf & 1) {
134    \u0275\u0275element(0, "ng-icon", 11);
135  }
136}
137function NewsDetailPage_Conditional_8_Template(rf, ctx) {
138  if (rf & 1) {
139    const _r3 = \u0275\u0275getCurrentView();
140    \u0275\u0275elementStart(0, "ion-button", 9);
141    \u0275\u0275listener("click", function NewsDetailPage_Conditional_8_Template_ion_button_click_0_listener() {
142      \u0275\u0275restoreView(_r3);
143      const ctx_r1 = \u0275\u0275nextContext();
144      return \u0275\u0275resetView(ctx_r1.saveNews());
145    });
146    \u0275\u0275template(1, NewsDetailPage_Conditional_8_Conditional_1_Template, 1, 0, "ion-spinner", 10)(2, NewsDetailPage_Conditional_8_Conditional_2_Template, 1, 0, "ng-icon", 11);
147    \u0275\u0275elementEnd();
148  }
149  if (rf & 2) {
150    const ctx_r1 = \u0275\u0275nextContext();
151    \u0275\u0275property("disabled", ctx_r1.saving);
152    \u0275\u0275advance();
153    \u0275\u0275conditional(ctx_r1.saving ? 1 : 2);
154  }
155}
156function NewsDetailPage_Conditional_10_Template(rf, ctx) {
157  if (rf & 1) {
158    \u0275\u0275elementStart(0, "div", 4);
159    \u0275\u0275element(1, "ion-spinner", 12);
160    \u0275\u0275elementEnd();
161  }
162}
163function NewsDetailPage_Conditional_11_Conditional_21_Template(rf, ctx) {
164  if (rf & 1) {
165    \u0275\u0275text(0);
166    \u0275\u0275pipe(1, "translate");
167  }
168  if (rf & 2) {
169    \u0275\u0275textInterpolate1(" ", \u0275\u0275pipeBind1(1, 1, "news.form.saving"), " ");
170  }
171}
172function NewsDetailPage_Conditional_11_Conditional_22_Template(rf, ctx) {
173  if (rf & 1) {
174    \u0275\u0275text(0);
175    \u0275\u0275pipe(1, "translate");
176  }
177  if (rf & 2) {
178    \u0275\u0275textInterpolate1(" ", \u0275\u0275pipeBind1(1, 1, "news.form.save"), " ");
179  }
180}
181function NewsDetailPage_Conditional_11_Conditional_26_Template(rf, ctx) {
182  if (rf & 1) {
183    const _r5 = \u0275\u0275getCurrentView();
184    \u0275\u0275elementStart(0, "ion-button", 20);
185    \u0275\u0275listener("click", function NewsDetailPage_Conditional_11_Conditional_26_Template_ion_button_click_0_listener() {
186      \u0275\u0275restoreView(_r5);
187      const ctx_r1 = \u0275\u0275nextContext(2);
188      return \u0275\u0275resetView(ctx_r1.confirmDelete());
189    });
190    \u0275\u0275element(1, "ng-icon", 21);
191    \u0275\u0275text(2);
192    \u0275\u0275pipe(3, "translate");
193    \u0275\u0275elementEnd();
194  }
195  if (rf & 2) {
196    \u0275\u0275advance(2);
197    \u0275\u0275textInterpolate1(" ", \u0275\u0275pipeBind1(3, 1, "news.delete"), " ");
198  }
199}
200function NewsDetailPage_Conditional_11_Template(rf, ctx) {
201  if (rf & 1) {
202    const _r4 = \u0275\u0275getCurrentView();
203    \u0275\u0275elementStart(0, "div", 5)(1, "ion-list")(2, "ion-item")(3, "ion-input", 13);
204    \u0275\u0275pipe(4, "translate");
205    \u0275\u0275pipe(5, "translate");
206    \u0275\u0275twoWayListener("ngModelChange", function NewsDetailPage_Conditional_11_Template_ion_input_ngModelChange_3_listener($event) {
207      \u0275\u0275restoreView(_r4);
208      const ctx_r1 = \u0275\u0275nextContext();
209      \u0275\u0275twoWayBindingSet(ctx_r1.formTitle, $event) || (ctx_r1.formTitle = $event);
210      return \u0275\u0275resetView($event);
211    });
212    \u0275\u0275elementEnd()();
213    \u0275\u0275elementStart(6, "ion-item")(7, "ion-textarea", 14);
214    \u0275\u0275pipe(8, "translate");
215    \u0275\u0275pipe(9, "translate");
216    \u0275\u0275twoWayListener("ngModelChange", function NewsDetailPage_Conditional_11_Template_ion_textarea_ngModelChange_7_listener($event) {
217      \u0275\u0275restoreView(_r4);
218      const ctx_r1 = \u0275\u0275nextContext();
219      \u0275\u0275twoWayBindingSet(ctx_r1.formContent, $event) || (ctx_r1.formContent = $event);
220      return \u0275\u0275resetView($event);
221    });
222    \u0275\u0275elementEnd()();
223    \u0275\u0275elementStart(10, "ion-item")(11, "ion-toggle", 15);
224    \u0275\u0275twoWayListener("ngModelChange", function NewsDetailPage_Conditional_11_Template_ion_toggle_ngModelChange_11_listener($event) {
225      \u0275\u0275restoreView(_r4);
226      const ctx_r1 = \u0275\u0275nextContext();
227      \u0275\u0275twoWayBindingSet(ctx_r1.formIsFeatured, $event) || (ctx_r1.formIsFeatured = $event);
228      return \u0275\u0275resetView($event);
229    });
230    \u0275\u0275elementStart(12, "ion-label")(13, "h2");
231    \u0275\u0275text(14);
232    \u0275\u0275pipe(15, "translate");
233    \u0275\u0275elementEnd();
234    \u0275\u0275elementStart(16, "p");
235    \u0275\u0275text(17);
236    \u0275\u0275pipe(18, "translate");
237    \u0275\u0275elementEnd()()()()();
238    \u0275\u0275elementStart(19, "div", 16)(20, "ion-button", 17);
239    \u0275\u0275listener("click", function NewsDetailPage_Conditional_11_Template_ion_button_click_20_listener() {
240      \u0275\u0275restoreView(_r4);
241      const ctx_r1 = \u0275\u0275nextContext();
242      return \u0275\u0275resetView(ctx_r1.saveNews());
243    });
244    \u0275\u0275template(21, NewsDetailPage_Conditional_11_Conditional_21_Template, 2, 3)(22, NewsDetailPage_Conditional_11_Conditional_22_Template, 2, 3);
245    \u0275\u0275elementEnd();
246    \u0275\u0275elementStart(23, "ion-button", 18);
247    \u0275\u0275listener("click", function NewsDetailPage_Conditional_11_Template_ion_button_click_23_listener() {
248      \u0275\u0275restoreView(_r4);
249      const ctx_r1 = \u0275\u0275nextContext();
250      return \u0275\u0275resetView(ctx_r1.cancelEdit());
251    });
252    \u0275\u0275text(24);
253    \u0275\u0275pipe(25, "translate");
254    \u0275\u0275elementEnd();
255    \u0275\u0275template(26, NewsDetailPage_Conditional_11_Conditional_26_Template, 4, 3, "ion-button", 19);
256    \u0275\u0275elementEnd()();
257  }
258  if (rf & 2) {
259    const ctx_r1 = \u0275\u0275nextContext();
260    \u0275\u0275advance(3);
261    \u0275\u0275twoWayProperty("ngModel", ctx_r1.formTitle);
262    \u0275\u0275property("label", \u0275\u0275pipeBind1(4, 15, "news.form.title"))("placeholder", \u0275\u0275pipeBind1(5, 17, "news.form.titlePlaceholder"));
263    \u0275\u0275advance(4);
264    \u0275\u0275twoWayProperty("ngModel", ctx_r1.formContent);
265    \u0275\u0275property("label", \u0275\u0275pipeBind1(8, 19, "news.form.content"))("placeholder", \u0275\u0275pipeBind1(9, 21, "news.form.contentPlaceholder"))("autoGrow", true)("rows", 8);
266    \u0275\u0275advance(4);
267    \u0275\u0275twoWayProperty("ngModel", ctx_r1.formIsFeatured);
268    \u0275\u0275advance(3);
269    \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(15, 23, "news.form.featured"));
270    \u0275\u0275advance(3);
271    \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(18, 25, "news.form.featuredDescription"));
272    \u0275\u0275advance(3);
273    \u0275\u0275property("disabled", ctx_r1.saving);
274    \u0275\u0275advance();
275    \u0275\u0275conditional(ctx_r1.saving ? 21 : 22);
276    \u0275\u0275advance(3);
277    \u0275\u0275textInterpolate1(" ", \u0275\u0275pipeBind1(25, 27, "news.form.cancel"), " ");
278    \u0275\u0275advance(2);
279    \u0275\u0275conditional(!ctx_r1.isNewArticle && ctx_r1.canEdit ? 26 : -1);
280  }
281}
282function NewsDetailPage_Conditional_12_Conditional_1_Template(rf, ctx) {
283  if (rf & 1) {
284    \u0275\u0275elementStart(0, "div", 22);
285    \u0275\u0275element(1, "img", 32);
286    \u0275\u0275elementEnd();
287  }
288  if (rf & 2) {
289    const ctx_r1 = \u0275\u0275nextContext(2);
290    \u0275\u0275advance();
291    \u0275\u0275property("src", ctx_r1.imageUrl, \u0275\u0275sanitizeUrl)("alt", ctx_r1.news.entity.title);
292  }
293}
294function NewsDetailPage_Conditional_12_Conditional_3_Template(rf, ctx) {
295  if (rf & 1) {
296    \u0275\u0275elementStart(0, "ion-badge", 24);
297    \u0275\u0275element(1, "ng-icon", 33);
298    \u0275\u0275text(2);
299    \u0275\u0275pipe(3, "translate");
300    \u0275\u0275elementEnd();
301  }
302  if (rf & 2) {
303    \u0275\u0275advance(2);
304    \u0275\u0275textInterpolate1(" ", \u0275\u0275pipeBind1(3, 1, "news.featured"), " ");
305  }
306}
307function NewsDetailPage_Conditional_12_Template(rf, ctx) {
308  if (rf & 1) {
309    \u0275\u0275elementStart(0, "div", 6);
310    \u0275\u0275template(1, NewsDetailPage_Conditional_12_Conditional_1_Template, 2, 2, "div", 22);
311    \u0275\u0275elementStart(2, "div", 23);
312    \u0275\u0275template(3, NewsDetailPage_Conditional_12_Conditional_3_Template, 4, 3, "ion-badge", 24);
313    \u0275\u0275elementStart(4, "h1", 25);
314    \u0275\u0275text(5);
315    \u0275\u0275elementEnd();
316    \u0275\u0275elementStart(6, "div", 26)(7, "span", 27);
317    \u0275\u0275element(8, "ng-icon", 28);
318    \u0275\u0275text(9);
319    \u0275\u0275pipe(10, "date");
320    \u0275\u0275elementEnd();
321    \u0275\u0275elementStart(11, "span", 27);
322    \u0275\u0275element(12, "ng-icon", 29);
323    \u0275\u0275text(13);
324    \u0275\u0275pipe(14, "translate");
325    \u0275\u0275elementEnd()();
326    \u0275\u0275element(15, "div", 30);
327    \u0275\u0275elementStart(16, "div", 31);
328    \u0275\u0275text(17);
329    \u0275\u0275elementEnd()()();
330  }
331  if (rf & 2) {
332    const ctx_r1 = \u0275\u0275nextContext();
333    \u0275\u0275advance();
334    \u0275\u0275conditional(ctx_r1.imageUrl ? 1 : -1);
335    \u0275\u0275advance(2);
336    \u0275\u0275conditional(ctx_r1.news.entity.isFeatured ? 3 : -1);
337    \u0275\u0275advance(2);
338    \u0275\u0275textInterpolate(ctx_r1.news.entity.title);
339    \u0275\u0275advance(4);
340    \u0275\u0275textInterpolate1(" ", \u0275\u0275pipeBind2(10, 7, ctx_r1.publishedDate, "longDate"), " ");
341    \u0275\u0275advance(4);
342    \u0275\u0275textInterpolate2(" ", \u0275\u0275pipeBind1(14, 10, "news.by"), " ", ctx_r1.authorName, " ");
343    \u0275\u0275advance(4);
344    \u0275\u0275textInterpolate1(" ", ctx_r1.news.entity.content, " ");
345  }
346}
347var _NewsDetailPage = class _NewsDetailPage {
348  constructor(route, router, location, databaseService, authService, apiUrlService, alertController, toastController, translate) {
349    this.route = route;
350    this.router = router;
351    this.location = location;
352    this.databaseService = databaseService;
353    this.authService = authService;
354    this.apiUrlService = apiUrlService;
355    this.alertController = alertController;
356    this.toastController = toastController;
357    this.translate = translate;
358    this.destroy$ = new Subject();
359    this.newsId = null;
360    this.news = null;
361    this.isEditMode = false;
362    this.isNewArticle = false;
363    this.loading = true;
364    this.saving = false;
365    this.formTitle = "";
366    this.formContent = "";
367    this.formIsFeatured = false;
368    this.formCampusId = "";
369  }
370  ngOnInit() {
371    this.route.paramMap.pipe(takeUntil(this.destroy$)).subscribe((params) => {
372      const id = params.get("id");
373      if (id === "new" || this.router.url === "/news/new") {
374        this.isNewArticle = true;
375        this.isEditMode = true;
376        this.loading = false;
377        this.initNewArticle();
378      } else if (id) {
379        this.newsId = id;
380        this.loadNews();
381      }
382    });
383  }
384  ngOnDestroy() {
385    this.destroy$.next();
386    this.destroy$.complete();
387  }
388  get canEdit() {
389    return this.authService.hasRole(UserRole.Moderator);
390  }
391  get imageUrl() {
392    var _a;
393    if (!((_a = this.news) == null ? void 0 : _a.entity.imageUploadId))
394      return null;
395    return `${this.apiUrlService.getSelectedUrl()}/api/v1/media/${this.news.entity.imageUploadId}`;
396  }
397  get authorName() {
398    var _a, _b;
399    return ((_b = (_a = this.news) == null ? void 0 : _a.author) == null ? void 0 : _b.entity.name) || this.translate.instant("news.unknownAuthor");
400  }
401  get publishedDate() {
402    var _a;
403    if (!((_a = this.news) == null ? void 0 : _a.entity.publishedAt))
404      return null;
405    return new Date(this.news.entity.publishedAt);
406  }
407  get pageTitle() {
408    var _a;
409    if (this.isNewArticle)
410      return this.translate.instant("news.create");
411    if (this.isEditMode)
412      return this.translate.instant("news.edit");
413    return ((_a = this.news) == null ? void 0 : _a.entity.title) || "";
414  }
415  initNewArticle() {
416    var _a;
417    for (const [, model] of this.databaseService.Models) {
418      if (model.type === EntityType.PERSON_CAMPUS) {
419        const pc = model.entity;
420        if (pc.personId === ((_a = this.authService.currentUserValue) == null ? void 0 : _a.id) && pc.campusId) {
421          this.formCampusId = pc.campusId;
422          break;
423        }
424      }
425    }
426    if (!this.formCampusId && this.authService.hasRole(UserRole.Admin)) {
427      for (const [, model] of this.databaseService.Models) {
428        if (model.type === EntityType.CAMPUS && !model.entity.isDeleted) {
429          this.formCampusId = model.entity.id;
430          break;
431        }
432      }
433    }
434  }
435  loadNews() {
436    const model = this.databaseService.Models.get(this.newsId);
437    if (model && model.type === EntityType.NEWS) {
438      this.news = model;
439      this.populateForm();
440    }
441    this.loading = false;
442  }
443  populateForm() {
444    if (!this.news)
445      return;
446    this.formTitle = this.news.entity.title || "";
447    this.formContent = this.news.entity.content || "";
448    this.formIsFeatured = this.news.entity.isFeatured || false;
449    this.formCampusId = this.news.entity.campusId || "";
450  }
451  enterEditMode() {
452    this.isEditMode = true;
453    this.populateForm();
454  }
455  cancelEdit() {
456    if (this.isNewArticle) {
457      this.location.back();
458    } else {
459      this.isEditMode = false;
460      this.populateForm();
461    }
462  }
463  saveNews() {
464    return __async(this, null, function* () {
465      var _a;
466      if (!this.formTitle.trim()) {
467        this.showToast(this.translate.instant("news.validation.titleRequired"), "warning");
468        return;
469      }
470      if (!this.formContent.trim()) {
471        this.showToast(this.translate.instant("news.validation.contentRequired"), "warning");
472        return;
473      }
474      this.saving = true;
475      try {
476        if (this.isNewArticle) {
477          const newNews = new News();
478          newNews.id = v4_default();
479          newNews.isDeleted = false;
480          newNews.version = 0;
481          newNews.campusId = this.formCampusId;
482          newNews.title = this.formTitle.trim();
483          newNews.content = this.formContent.trim();
484          newNews.isFeatured = this.formIsFeatured;
485          newNews.publishedAt = (/* @__PURE__ */ new Date()).toISOString();
486          newNews.authorId = ((_a = this.authService.currentUserValue) == null ? void 0 : _a.id) || void 0;
487          yield this.databaseService.addEntity(newNews);
488          this.showToast(this.translate.instant("news.success.created"), "success");
489          this.router.navigate(["/news"]);
490        } else if (this.news) {
491          this.news.entity.title = this.formTitle.trim();
492          this.news.entity.content = this.formContent.trim();
493          this.news.entity.isFeatured = this.formIsFeatured;
494          yield this.databaseService.updateEntity(this.news.entity);
495          this.showToast(this.translate.instant("news.success.updated"), "success");
496          this.isEditMode = false;
497        }
498      } catch (error) {
499        console.error("Failed to save news:", error);
500        this.showToast(this.translate.instant("news.error.save"), "danger");
501      } finally {
502        this.saving = false;
503      }
504    });
505  }
506  confirmDelete() {
507    return __async(this, null, function* () {
508      const alert = yield this.alertController.create({
509        header: this.translate.instant("news.deleteConfirm.title"),
510        message: this.translate.instant("news.deleteConfirm.message"),
511        buttons: [
512          {
513            text: this.translate.instant("news.form.cancel"),
514            role: "cancel"
515          },
516          {
517            text: this.translate.instant("news.delete"),
518            role: "destructive",
519            handler: () => this.deleteNews()
520          }
521        ]
522      });
523      yield alert.present();
524    });
525  }
526  deleteNews() {
527    return __async(this, null, function* () {
528      if (!this.news)
529        return;
530      try {
531        yield this.databaseService.deleteEntity(this.news.entity);
532        this.showToast(this.translate.instant("news.success.deleted"), "success");
533        this.router.navigate(["/news"]);
534      } catch (error) {
535        console.error("Failed to delete news:", error);
536        this.showToast(this.translate.instant("news.error.delete"), "danger");
537      }
538    });
539  }
540  showToast(message, color) {
541    return __async(this, null, function* () {
542      const toast = yield this.toastController.create({
543        message,
544        duration: 3e3,
545        color,
546        position: "bottom"
547      });
548      yield toast.present();
549    });
550  }
551};
552_NewsDetailPage.\u0275fac = function NewsDetailPage_Factory(__ngFactoryType__) {
553  return new (__ngFactoryType__ || _NewsDetailPage)(\u0275\u0275directiveInject(ActivatedRoute), \u0275\u0275directiveInject(Router), \u0275\u0275directiveInject(Location), \u0275\u0275directiveInject(DatabaseService), \u0275\u0275directiveInject(AuthService), \u0275\u0275directiveInject(ApiUrlService), \u0275\u0275directiveInject(AlertController), \u0275\u0275directiveInject(ToastController), \u0275\u0275directiveInject(TranslateService));
554};
555_NewsDetailPage.\u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _NewsDetailPage, selectors: [["app-news-detail"]], features: [\u0275\u0275ProvidersFeature([], [provideIcons({
556  lucideCalendar,
557  lucideUser,
558  lucidePencil,
559  lucideTrash2,
560  lucideSave,
561  lucideX,
562  lucideImage,
563  lucideStar
564})])], decls: 13, vars: 4, consts: [["slot", "start"], ["defaultHref", "/news"], ["slot", "end"], [3, "disabled"], [1, "loading-container"], [1, "edit-form"], [1, "article-view"], [3, "click"], ["name", "lucidePencil", "size", "1.2em"], [3, "click", "disabled"], ["name", "crescent", "size", "small"], ["name", "lucideSave", "size", "1.2em"], ["name", "crescent"], ["labelPlacement", "stacked", "type", "text", "required", "", 3, "ngModelChange", "ngModel", "label", "placeholder"], ["labelPlacement", "stacked", "required", "", 3, "ngModelChange", "ngModel", "label", "placeholder", "autoGrow", "rows"], ["labelPlacement", "start", 3, "ngModelChange", "ngModel"], [1, "form-actions"], ["expand", "block", 3, "click", "disabled"], ["expand", "block", "fill", "outline", 3, "click"], ["expand", "block", "fill", "clear", "color", "danger"], ["expand", "block", "fill", "clear", "color", "danger", 3, "click"], ["name", "lucideTrash2", "size", "1.1em", "slot", "start"], [1, "article-image"], [1, "article-content"], ["color", "warning", 1, "featured-badge"], [1, "article-title"], [1, "article-meta"], [1, "meta-item"], ["name", "lucideCalendar", "size", "1em"], ["name", "lucideUser", "size", "1em"], [1, "article-divider"], [1, "article-body"], [3, "src", "alt"], ["name", "lucideStar", "size", "0.9em"]], template: function NewsDetailPage_Template(rf, ctx) {
565  if (rf & 1) {
566    \u0275\u0275elementStart(0, "ion-header")(1, "ion-toolbar")(2, "ion-buttons", 0);
567    \u0275\u0275element(3, "ion-back-button", 1);
568    \u0275\u0275elementEnd();
569    \u0275\u0275elementStart(4, "ion-title");
570    \u0275\u0275text(5);
571    \u0275\u0275elementEnd();
572    \u0275\u0275elementStart(6, "ion-buttons", 2);
573    \u0275\u0275template(7, NewsDetailPage_Conditional_7_Template, 2, 0, "ion-button")(8, NewsDetailPage_Conditional_8_Template, 3, 2, "ion-button", 3);
574    \u0275\u0275elementEnd()()();
575    \u0275\u0275elementStart(9, "ion-content");
576    \u0275\u0275template(10, NewsDetailPage_Conditional_10_Template, 2, 0, "div", 4)(11, NewsDetailPage_Conditional_11_Template, 27, 29, "div", 5)(12, NewsDetailPage_Conditional_12_Template, 18, 12, "div", 6);
577    \u0275\u0275elementEnd();
578  }
579  if (rf & 2) {
580    \u0275\u0275advance(5);
581    \u0275\u0275textInterpolate(ctx.pageTitle);
582    \u0275\u0275advance(2);
583    \u0275\u0275conditional(!ctx.isEditMode && ctx.canEdit && ctx.news ? 7 : -1);
584    \u0275\u0275advance();
585    \u0275\u0275conditional(ctx.isEditMode ? 8 : -1);
586    \u0275\u0275advance(2);
587    \u0275\u0275conditional(ctx.loading ? 10 : ctx.isEditMode ? 11 : ctx.news ? 12 : -1);
588  }
589}, dependencies: [
590  CommonModule,
591  DatePipe,
592  FormsModule,
593  NgControlStatus,
594  RequiredValidator,
595  NgModel,
596  TranslateModule,
597  TranslatePipe,
598  NgIcon,
599  IonHeader,
600  IonToolbar,
601  IonButtons,
602  IonBackButton,
603  IonTitle,
604  IonContent,
605  IonButton,
606  IonBadge,
607  IonSpinner,
608  IonInput,
609  IonTextarea,
610  IonToggle,
611  IonItem,
612  IonLabel,
613  IonList
614], styles: ["\n\n.loading-container[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 50vh;\n}\n.article-view[_ngcontent-%COMP%]   .article-image[_ngcontent-%COMP%] {\n  width: 100%;\n  max-height: 300px;\n  overflow: hidden;\n}\n.article-view[_ngcontent-%COMP%]   .article-image[_ngcontent-%COMP%]   img[_ngcontent-%COMP%] {\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n.article-view[_ngcontent-%COMP%]   .article-content[_ngcontent-%COMP%] {\n  padding: 20px;\n}\n@media (min-width: 768px) {\n  .article-view[_ngcontent-%COMP%]   .article-content[_ngcontent-%COMP%] {\n    max-width: 800px;\n    margin: 0 auto;\n    padding: 24px 32px;\n  }\n}\n.article-view[_ngcontent-%COMP%]   .featured-badge[_ngcontent-%COMP%] {\n  display: inline-flex;\n  align-items: center;\n  gap: 4px;\n  font-size: 0.75rem;\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n  margin-bottom: 12px;\n}\n.article-view[_ngcontent-%COMP%]   .article-title[_ngcontent-%COMP%] {\n  font-size: 1.75rem;\n  font-weight: 700;\n  line-height: 1.3;\n  margin: 0 0 16px;\n  color: var(--ion-text-color);\n}\n@media (min-width: 768px) {\n  .article-view[_ngcontent-%COMP%]   .article-title[_ngcontent-%COMP%] {\n    font-size: 2rem;\n  }\n}\n.article-view[_ngcontent-%COMP%]   .article-meta[_ngcontent-%COMP%] {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 16px;\n  font-size: 0.9rem;\n  color: var(--ion-color-medium);\n  margin-bottom: 20px;\n}\n.article-view[_ngcontent-%COMP%]   .article-meta[_ngcontent-%COMP%]   .meta-item[_ngcontent-%COMP%] {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n}\n.article-view[_ngcontent-%COMP%]   .article-divider[_ngcontent-%COMP%] {\n  height: 1px;\n  background: var(--ion-color-light);\n  margin: 20px 0;\n}\n.article-view[_ngcontent-%COMP%]   .article-body[_ngcontent-%COMP%] {\n  font-size: 1.05rem;\n  line-height: 1.7;\n  color: var(--ion-text-color);\n  white-space: pre-wrap;\n  word-wrap: break-word;\n}\n.edit-form[_ngcontent-%COMP%] {\n  padding: 16px;\n}\n@media (min-width: 768px) {\n  .edit-form[_ngcontent-%COMP%] {\n    max-width: 700px;\n    margin: 0 auto;\n    padding: 24px;\n  }\n}\n.edit-form[_ngcontent-%COMP%]   ion-list[_ngcontent-%COMP%] {\n  background: transparent;\n  padding: 0;\n}\n.edit-form[_ngcontent-%COMP%]   ion-item[_ngcontent-%COMP%] {\n  --background: var(--ion-card-background);\n  --border-radius: 8px;\n  margin-bottom: 12px;\n  --padding-start: 16px;\n  --padding-end: 16px;\n  --inner-padding-end: 0;\n}\n.edit-form[_ngcontent-%COMP%]   ion-input[_ngcontent-%COMP%], \n.edit-form[_ngcontent-%COMP%]   ion-textarea[_ngcontent-%COMP%] {\n  --padding-top: 12px;\n  --padding-bottom: 12px;\n}\n.edit-form[_ngcontent-%COMP%]   ion-toggle[_ngcontent-%COMP%]   ion-label[_ngcontent-%COMP%]   h2[_ngcontent-%COMP%] {\n  font-size: 1rem;\n  font-weight: 500;\n  margin: 0 0 4px;\n}\n.edit-form[_ngcontent-%COMP%]   ion-toggle[_ngcontent-%COMP%]   ion-label[_ngcontent-%COMP%]   p[_ngcontent-%COMP%] {\n  font-size: 0.85rem;\n  color: var(--ion-color-medium);\n  margin: 0;\n}\n.edit-form[_ngcontent-%COMP%]   .form-actions[_ngcontent-%COMP%] {\n  margin-top: 24px;\n}\n.edit-form[_ngcontent-%COMP%]   .form-actions[_ngcontent-%COMP%]   ion-button[_ngcontent-%COMP%] {\n  margin-bottom: 8px;\n}\n.edit-form[_ngcontent-%COMP%]   .form-actions[_ngcontent-%COMP%]   ion-button[_ngcontent-%COMP%]:last-child {\n  margin-bottom: 0;\n}\nion-toolbar[_ngcontent-%COMP%]   ion-button[_ngcontent-%COMP%] {\n  --padding-start: 8px;\n  --padding-end: 8px;\n}"] });
615var NewsDetailPage = _NewsDetailPage;
616(() => {
617  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NewsDetailPage, [{
618    type: Component,
619    args: [{ selector: "app-news-detail", standalone: true, imports: [
620      CommonModule,
621      FormsModule,
622      TranslateModule,
623      NgIcon,
624      IonHeader,
625      IonToolbar,
626      IonButtons,
627      IonBackButton,
628      IonTitle,
629      IonContent,
630      IonButton,
631      IonBadge,
632      IonSpinner,
633      IonInput,
634      IonTextarea,
635      IonToggle,
636      IonItem,
637      IonLabel,
638      IonList
639    ], viewProviders: [provideIcons({
640      lucideCalendar,
641      lucideUser,
642      lucidePencil,
643      lucideTrash2,
644      lucideSave,
645      lucideX,
646      lucideImage,
647      lucideStar
648    })], template: `<ion-header>
649  <ion-toolbar>
650    <ion-buttons slot="start">
651      <ion-back-button defaultHref="/news"></ion-back-button>
652    </ion-buttons>
653    <ion-title>{{ pageTitle }}</ion-title>
654    <ion-buttons slot="end">
655      @if (!isEditMode && canEdit && news) {
656        <ion-button (click)="enterEditMode()">
657          <ng-icon name="lucidePencil" size="1.2em"></ng-icon>
658        </ion-button>
659      }
660      @if (isEditMode) {
661        <ion-button (click)="saveNews()" [disabled]="saving">
662          @if (saving) {
663            <ion-spinner name="crescent" size="small"></ion-spinner>
664          } @else {
665            <ng-icon name="lucideSave" size="1.2em"></ng-icon>
666          }
667        </ion-button>
668      }
669    </ion-buttons>
670  </ion-toolbar>
671</ion-header>
672
673<ion-content>
674  @if (loading) {
675    <div class="loading-container">
676      <ion-spinner name="crescent"></ion-spinner>
677    </div>
678  } @else if (isEditMode) {
679    <!-- Edit Mode -->
680    <div class="edit-form">
681      <ion-list>
682        <ion-item>
683          <ion-input
684            [(ngModel)]="formTitle"
685            [label]="'news.form.title' | translate"
686            labelPlacement="stacked"
687            [placeholder]="'news.form.titlePlaceholder' | translate"
688            type="text"
689            required>
690          </ion-input>
691        </ion-item>
692
693        <ion-item>
694          <ion-textarea
695            [(ngModel)]="formContent"
696            [label]="'news.form.content' | translate"
697            labelPlacement="stacked"
698            [placeholder]="'news.form.contentPlaceholder' | translate"
699            [autoGrow]="true"
700            [rows]="8"
701            required>
702          </ion-textarea>
703        </ion-item>
704
705        <ion-item>
706          <ion-toggle [(ngModel)]="formIsFeatured" labelPlacement="start">
707            <ion-label>
708              <h2>{{ 'news.form.featured' | translate }}</h2>
709              <p>{{ 'news.form.featuredDescription' | translate }}</p>
710            </ion-label>
711          </ion-toggle>
712        </ion-item>
713      </ion-list>
714
715      <div class="form-actions">
716        <ion-button expand="block" (click)="saveNews()" [disabled]="saving">
717          @if (saving) {
718            {{ 'news.form.saving' | translate }}
719          } @else {
720            {{ 'news.form.save' | translate }}
721          }
722        </ion-button>
723
724        <ion-button expand="block" fill="outline" (click)="cancelEdit()">
725          {{ 'news.form.cancel' | translate }}
726        </ion-button>
727
728        @if (!isNewArticle && canEdit) {
729          <ion-button expand="block" fill="clear" color="danger" (click)="confirmDelete()">
730            <ng-icon name="lucideTrash2" size="1.1em" slot="start"></ng-icon>
731            {{ 'news.delete' | translate }}
732          </ion-button>
733        }
734      </div>
735    </div>
736  } @else if (news) {
737    <!-- View Mode -->
738    <div class="article-view">
739      @if (imageUrl) {
740        <div class="article-image">
741          <img [src]="imageUrl" [alt]="news.entity.title" />
742        </div>
743      }
744
745      <div class="article-content">
746        @if (news.entity.isFeatured) {
747          <ion-badge color="warning" class="featured-badge">
748            <ng-icon name="lucideStar" size="0.9em"></ng-icon>
749            {{ 'news.featured' | translate }}
750          </ion-badge>
751        }
752
753        <h1 class="article-title">{{ news.entity.title }}</h1>
754
755        <div class="article-meta">
756          <span class="meta-item">
757            <ng-icon name="lucideCalendar" size="1em"></ng-icon>
758            {{ publishedDate | date:'longDate' }}
759          </span>
760          <span class="meta-item">
761            <ng-icon name="lucideUser" size="1em"></ng-icon>
762            {{ 'news.by' | translate }} {{ authorName }}
763          </span>
764        </div>
765
766        <div class="article-divider"></div>
767
768        <div class="article-body">
769          {{ news.entity.content }}
770        </div>
771      </div>
772    </div>
773  }
774</ion-content>
775`, styles: ["/* src/app/pages/news-detail/news-detail.page.scss */\n.loading-container {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 50vh;\n}\n.article-view .article-image {\n  width: 100%;\n  max-height: 300px;\n  overflow: hidden;\n}\n.article-view .article-image img {\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n.article-view .article-content {\n  padding: 20px;\n}\n@media (min-width: 768px) {\n  .article-view .article-content {\n    max-width: 800px;\n    margin: 0 auto;\n    padding: 24px 32px;\n  }\n}\n.article-view .featured-badge {\n  display: inline-flex;\n  align-items: center;\n  gap: 4px;\n  font-size: 0.75rem;\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n  margin-bottom: 12px;\n}\n.article-view .article-title {\n  font-size: 1.75rem;\n  font-weight: 700;\n  line-height: 1.3;\n  margin: 0 0 16px;\n  color: var(--ion-text-color);\n}\n@media (min-width: 768px) {\n  .article-view .article-title {\n    font-size: 2rem;\n  }\n}\n.article-view .article-meta {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 16px;\n  font-size: 0.9rem;\n  color: var(--ion-color-medium);\n  margin-bottom: 20px;\n}\n.article-view .article-meta .meta-item {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n}\n.article-view .article-divider {\n  height: 1px;\n  background: var(--ion-color-light);\n  margin: 20px 0;\n}\n.article-view .article-body {\n  font-size: 1.05rem;\n  line-height: 1.7;\n  color: var(--ion-text-color);\n  white-space: pre-wrap;\n  word-wrap: break-word;\n}\n.edit-form {\n  padding: 16px;\n}\n@media (min-width: 768px) {\n  .edit-form {\n    max-width: 700px;\n    margin: 0 auto;\n    padding: 24px;\n  }\n}\n.edit-form ion-list {\n  background: transparent;\n  padding: 0;\n}\n.edit-form ion-item {\n  --background: var(--ion-card-background);\n  --border-radius: 8px;\n  margin-bottom: 12px;\n  --padding-start: 16px;\n  --padding-end: 16px;\n  --inner-padding-end: 0;\n}\n.edit-form ion-input,\n.edit-form ion-textarea {\n  --padding-top: 12px;\n  --padding-bottom: 12px;\n}\n.edit-form ion-toggle ion-label h2 {\n  font-size: 1rem;\n  font-weight: 500;\n  margin: 0 0 4px;\n}\n.edit-form ion-toggle ion-label p {\n  font-size: 0.85rem;\n  color: var(--ion-color-medium);\n  margin: 0;\n}\n.edit-form .form-actions {\n  margin-top: 24px;\n}\n.edit-form .form-actions ion-button {\n  margin-bottom: 8px;\n}\n.edit-form .form-actions ion-button:last-child {\n  margin-bottom: 0;\n}\nion-toolbar ion-button {\n  --padding-start: 8px;\n  --padding-end: 8px;\n}\n"] }]
776  }], () => [{ type: ActivatedRoute }, { type: Router }, { type: Location }, { type: DatabaseService }, { type: AuthService }, { type: ApiUrlService }, { type: AlertController }, { type: ToastController }, { type: TranslateService }], null);
777})();
778(() => {
779  (typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(NewsDetailPage, { className: "NewsDetailPage", filePath: "src/app/pages/news-detail/news-detail.page.ts", lineNumber: 58 });
780})();
781export {
782  NewsDetailPage
783};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.