diff --git a/frontend/src/app/pages/publication-edition/publication-edition.component.html b/frontend/src/app/pages/publication-edition/publication-edition.component.html
index bede172..f0ed70e 100644
--- a/frontend/src/app/pages/publication-edition/publication-edition.component.html
+++ b/frontend/src/app/pages/publication-edition/publication-edition.component.html
@@ -29,19 +29,19 @@
-
Content
-
+
diff --git a/frontend/src/app/pages/publication-edition/publication-edition.component.ts b/frontend/src/app/pages/publication-edition/publication-edition.component.ts
index 21e986a..9e89618 100644
--- a/frontend/src/app/pages/publication-edition/publication-edition.component.ts
+++ b/frontend/src/app/pages/publication-edition/publication-edition.component.ts
@@ -59,7 +59,6 @@ export class PublicationEditionComponent implements OnInit, OnDestroy {
['title', 'description', 'text'].forEach(fieldName => {
const fieldSubscription = this.publicationEditionForm.controls[fieldName].valueChanges
.pipe(
- debounceTime(300),
map(value => value?.length ? value as string : '')
)
.subscribe(fieldValue => {
@@ -76,18 +75,17 @@ export class PublicationEditionComponent implements OnInit, OnDestroy {
default:
break;
}
- this.publicationEditionService
});
this.subscriptions.push(fieldSubscription);
});
- const publicationSubscription = this.publicationEditionService.publication$.subscribe(publication => {
- this.publication = publication;
- this.publicationEditionForm.controls['title'].setValue(publication.title, { emitEvent: false });
- this.publicationEditionForm.controls['description'].setValue(publication.description, { emitEvent: false });
- this.publicationEditionForm.controls['text'].setValue(publication.text, { emitEvent: false });
- this.publicationEditionForm.controls['illustrationId'].setValue(publication.illustrationId, { emitEvent: false });
- this.publicationEditionForm.controls['categoryId'].setValue(publication.categoryId, { emitEvent: false });
+ const publicationSubscription = this.publicationEditionService.state$.subscribe(state => {
+ this.publication = state.publication;
+ this.publicationEditionForm.controls['title'].setValue(this.publication.title, { emitEvent: false });
+ this.publicationEditionForm.controls['description'].setValue(this.publication.description, { emitEvent: false });
+ this.publicationEditionForm.controls['text'].setValue(this.publication.text, { emitEvent: false });
+ this.publicationEditionForm.controls['illustrationId'].setValue(this.publication.illustrationId, { emitEvent: false });
+ this.publicationEditionForm.controls['categoryId'].setValue(this.publication.categoryId, { emitEvent: false });
});
this.subscriptions.push(publicationSubscription);
@@ -102,6 +100,14 @@ export class PublicationEditionComponent implements OnInit, OnDestroy {
this.location.back();
}
+ insertTitle(titleNumber: number): void {
+ this.publicationEditionService.insertTitle(titleNumber);
+ }
+
+ insertLink(): void {
+ this.publicationEditionService.insertLink();
+ }
+
save(): void {
this.publicationEditionService.save();
}
@@ -109,4 +115,18 @@ export class PublicationEditionComponent implements OnInit, OnDestroy {
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;
+
+ const selectedCharacterCount = positionEnd - positionStart;
+ console.log(`cursor position updated: [${positionStart}, ${positionEnd}] (${selectedCharacterCount})`);
+ this.publicationEditionService.editCursorPosition(positionStart, positionEnd);
+ }
+
+ }
}
diff --git a/frontend/src/app/pages/publication-edition/publication-edition.service.ts b/frontend/src/app/pages/publication-edition/publication-edition.service.ts
index 8a4648f..f1e24a5 100644
--- a/frontend/src/app/pages/publication-edition/publication-edition.service.ts
+++ b/frontend/src/app/pages/publication-edition/publication-edition.service.ts
@@ -9,6 +9,22 @@ import { copy } from '../../core/utils/ObjectUtils';
import { MatDialog } from "@angular/material/dialog";
import { PictureSelectionDialog } from "./picture-selection-dialog/picture-selection-dialog.component";
+export class CursorPosition {
+ start: number;
+ end: number;
+ selectedCharacters: number;
+
+ constructor(start: number, end: number) {
+ this.start = start;
+ this.end = end;
+ this.selectedCharacters = end - start;
+ }
+}
+
+export interface PublicationEditionState {
+ publication: Publication;
+ cursorPosition: CursorPosition;
+}
const DEFAULT_PUBLICATION: Publication = {
id: '',
@@ -27,6 +43,13 @@ const DEFAULT_PUBLICATION: Publication = {
}
};
+const DEFAULT_CURSOR_POSITION = new CursorPosition(0, 0);
+
+const DEFAULT_STATE: PublicationEditionState = {
+ publication: DEFAULT_PUBLICATION,
+ cursorPosition: DEFAULT_CURSOR_POSITION
+};
+
@Injectable()
export class PublicationEditionService implements OnDestroy {
private readonly activatedRoute = inject(ActivatedRoute);
@@ -37,7 +60,7 @@ export class PublicationEditionService implements OnDestroy {
private readonly dialog = inject(MatDialog);
private isLoadingSubject = new BehaviorSubject(false);
- private publicationSubject = new BehaviorSubject(copy(DEFAULT_PUBLICATION));
+ private stateSubject = new BehaviorSubject(copy(DEFAULT_STATE));
private subscriptions: Subscription[] = [];
private isSavingSubject = new BehaviorSubject(false);
@@ -45,12 +68,12 @@ export class PublicationEditionService implements OnDestroy {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
}
- private get _publication(): Publication {
- return this.publicationSubject.value;
+ private get _state(): PublicationEditionState {
+ return this.stateSubject.value;
}
- private _save(publication: Publication): void {
- this.publicationSubject.next(publication);
+ private _save(state: PublicationEditionState): void {
+ this.stateSubject.next(state);
}
get isLoading$(): Observable {
@@ -61,8 +84,8 @@ export class PublicationEditionService implements OnDestroy {
return this.isSavingSubject.asObservable();
}
- get publication$(): Observable {
- return this.publicationSubject.asObservable();
+ get state$(): Observable {
+ return this.stateSubject.asObservable();
}
loadPublication(): void {
@@ -76,7 +99,9 @@ export class PublicationEditionService implements OnDestroy {
} else {
this.publicationRestService.getById(publicationId)
.then(publication => {
- this.publicationSubject.next(publication);
+ const state = this._state;
+ state.publication = publication;
+ this.stateSubject.next(state);
})
.catch(error => {
const errorMessage = 'A technical error occurred while loading publication data.';
@@ -89,27 +114,27 @@ export class PublicationEditionService implements OnDestroy {
}
editTitle(title: string): void {
- const publication = this._publication;
- publication.title = title;
- this._save(publication);
+ const state = this._state;
+ state.publication.title = title;
+ this._save(state);
}
editDescription(description: string): void {
- const publication = this._publication;
- publication.description = description;
- this._save(publication);
+ const state = this._state;
+ state.publication.description = description;
+ this._save(state);
}
editText(text: string): void {
- const publication = this._publication;
- publication.text = text;
- this._save(publication);
+ const state = this._state;
+ state.publication.text = text;
+ this._save(state);
}
editIllustrationId(pictureId: string): void {
- const publication = this._publication;
- publication.illustrationId = pictureId
- this._save(publication);
+ const state = this._state;
+ state.publication.illustrationId = pictureId
+ this._save(state);
}
displayPictureSectionDialog(): void {
@@ -124,11 +149,55 @@ export class PublicationEditionService implements OnDestroy {
this.subscriptions.push(afterDialogCloseSubscription);
}
+ editCursorPosition(positionStart: number, positionEnd: number): void {
+ const state = this._state;
+
+ state.cursorPosition.start = positionStart;
+ state.cursorPosition.end = positionEnd;
+
+ this._save(state);
+ }
+
+ insertTitle(titleNumber: number): void {
+ if (titleNumber >= 1 && titleNumber <= 3) {
+ const state = this._state;
+
+ const publication = state.publication;
+
+ const publicationTextLeftPart = publication.text.substring(0, state.cursorPosition.start);
+ const publicationTextMiddlePart = publication.text.substring(state.cursorPosition.start, state.cursorPosition.end);
+ const publicationTextRightPart = publication.text.substring(state.cursorPosition.end);
+ const textWithTags = `${publicationTextLeftPart}[h${titleNumber}]${publicationTextMiddlePart}[/h${titleNumber}]${publicationTextRightPart}`;
+
+ publication.text = textWithTags;
+
+ this._save(state);
+ } else {
+ console.error(`Bad value for parameter of function 'insertTitle': '${titleNumber}'.`);
+ }
+ }
+
+ insertLink(): void {
+ const state = this._state;
+
+ const publication = state.publication;
+
+ const publicationTextLeftPart = publication.text.substring(0, state.cursorPosition.start);
+ const publicationTextMiddlePart = publication.text.substring(state.cursorPosition.start, state.cursorPosition.end);
+ const publicationTextRightPart = publication.text.substring(state.cursorPosition.end);
+ const textWithTags = `${publicationTextLeftPart}[link href="" txt="${publicationTextMiddlePart}" /]${publicationTextRightPart}`;
+
+ publication.text = textWithTags;
+
+ this._save(state);
+ }
+
+
save(): void {
- const publication = this._publication;
+ const state = this._state;
this.isSavingSubject.next(true);
- this.publicationRestService.update(publication)
+ this.publicationRestService.update(state.publication)
.then(() => {
this.snackBar.open('Publication updated succesfully!', 'Close', { duration: 5000 });
this.router.navigate(['/home']);