Files
codiki-hexagonal/frontend/src/app/components/publication-edition/publication-edition.component.ts
2025-12-30 17:18:50 +01:00

149 lines
5.0 KiB
TypeScript

import { CommonModule, Location } from "@angular/common";
import { Component, EventEmitter, inject, Input, OnChanges, OnDestroy, Output } from "@angular/core";
import { FormGroup, ReactiveFormsModule } from "@angular/forms";
import { MatDialogModule } from "@angular/material/dialog";
import { MatIconModule } from "@angular/material/icon";
import { MatInputModule } from "@angular/material/input";
import { MatProgressSpinnerModule } from "@angular/material/progress-spinner";
import { MatSelectModule } from "@angular/material/select";
import { MatTabsModule } from "@angular/material/tabs";
import { MatTooltipModule } from "@angular/material/tooltip";
import { map, Observable, of, Subscription } from "rxjs";
import { Category } from "../../core/rest-services/category/model/category";
import { Publication } from "../../core/rest-services/publications/model/publication";
import { CategoryService } from "../../core/service/category.service";
import { SubmitButtonComponent } from "../submit-button/submit-button.component";
import { PictureSelectionDialog } from "./picture-selection-dialog/picture-selection-dialog.component";
import { PublicationEditionService } from "./publication-edition.service";
import { MatRippleModule } from "@angular/material/core";
@Component({
selector: 'app-publication-edition',
templateUrl: './publication-edition.component.html',
styleUrl: './publication-edition.component.scss',
imports: [
CommonModule,
MatDialogModule,
MatIconModule,
MatInputModule,
MatRippleModule,
MatProgressSpinnerModule,
MatSelectModule,
MatTabsModule,
MatTooltipModule,
PictureSelectionDialog,
ReactiveFormsModule,
SubmitButtonComponent
],
providers: [PublicationEditionService]
})
export class PublicationEditionComponent implements OnChanges, OnDestroy {
@Input()
publication!: Publication;
@Input()
title!: string;
@Input()
isSaving$: Observable<boolean> = of(false);
@Output()
publicationSave = new EventEmitter<Publication>();
publicationInEdition!: Publication;
private readonly categoryService = inject(CategoryService);
private readonly location = inject(Location);
private readonly publicationEditionService = inject(PublicationEditionService);
private subscriptions: Subscription[] = [];
get publicationEditionForm(): FormGroup {
return this.publicationEditionService.publicationEditionForm;
}
get isLoading$(): Observable<boolean> {
return this.publicationEditionService.isLoading$;
}
get isPreviewing$(): Observable<boolean> {
return this.publicationEditionService.isPreviewing$;
}
get categories$(): Observable<Category[]> {
return this.categoryService.categories$
.pipe(
map(categories =>
categories.filter(category => category.subCategories.length == 0)
.sort(this.byNameAscComparator())
)
);
}
private byNameAscComparator(): (categoryA: Category, categoryB: Category) => number {
return (categoryA, categoryB) => this.compareStrings(categoryA.name, categoryB.name);
}
private compareStrings(stringA: string, stringB: string): number {
if (stringA < stringB) {
return -1;
}
if (stringA > stringB) {
return 1;
}
return 0;
}
ngOnChanges(): void {
this.ngOnDestroy();
if (!this.publicationInEdition || this.publicationInEdition !== this.publication) {
this.publicationInEdition = this.publication;
this.publicationEditionService.init(this.publicationInEdition);
}
}
ngOnDestroy(): void {
this.subscriptions.forEach(subscription => subscription?.unsubscribe());
}
goPreviousLocation(): void {
this.location.back();
}
insertTitle(titleNumber: number): void {
this.publicationEditionService.insertTitle(titleNumber);
}
selectAPicture(): void {
this.publicationEditionService.selectAPicture();
}
insertLink(): void {
this.publicationEditionService.insertLink();
}
displayCodeBlockDialog(): void {
this.publicationEditionService.displayCodeBlockDialog();
}
displayPictureSectionDialog(): void {
this.publicationEditionService.displayPictureSectionDialog();
}
updateCursorPosition(event: KeyboardEvent | MouseEvent): void {
if (event.target) {
const textarea = event.target as HTMLTextAreaElement;
const positionStart = textarea.selectionStart;
const positionEnd = textarea.selectionEnd;
this.publicationEditionService.editCursorPosition(positionStart, positionEnd);
}
}
save(): void {
this.publicationSave.emit(this.publicationEditionService.editedPublication);
}
onTabChange(tabSelectedIndex: number): void {
if (tabSelectedIndex === 1) {
this.publicationEditionService.loadPreview();
}
}
}