|
@@ -1,10 +1,22 @@
|
|
|
-import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
|
+import {
|
|
|
+ Component,
|
|
|
+ OnInit,
|
|
|
+ OnDestroy,
|
|
|
+ inject,
|
|
|
+ TemplateRef,
|
|
|
+ ViewChild,
|
|
|
+ ViewContainerRef,
|
|
|
+ Renderer2,
|
|
|
+ ElementRef,
|
|
|
+} from '@angular/core';
|
|
|
import { Editor } from 'ngx-editor';
|
|
|
import { DateAdapter } from '@angular/material/core';
|
|
|
import { JournalEntry } from 'src/interfaces/interfaces';
|
|
|
import localeDe from '@angular/common/locales/de';
|
|
|
import { registerLocaleData } from '@angular/common';
|
|
|
import { DataService } from 'src/services/data/data.service';
|
|
|
+import { TooltipService } from 'src/services/tooltip/tooltip.service';
|
|
|
+import { HighlightComponent } from 'src/app/shared-components/highlight/highlight.component';
|
|
|
|
|
|
@Component({
|
|
|
selector: 'app-journal-notes',
|
|
@@ -12,6 +24,13 @@ import { DataService } from 'src/services/data/data.service';
|
|
|
styleUrl: './journal-notes.component.scss',
|
|
|
})
|
|
|
export class JournalNotesComponent implements OnInit, OnDestroy {
|
|
|
+ /** Reference to the tooltip */
|
|
|
+ @ViewChild('tooltip', { read: TemplateRef }) tooltip!: TemplateRef<any>;
|
|
|
+
|
|
|
+ /** Reference to the creation anchor */
|
|
|
+ @ViewChild('creationAnchor', { read: ViewContainerRef })
|
|
|
+ creationAnchor!: ViewContainerRef;
|
|
|
+
|
|
|
editor: Editor = new Editor();
|
|
|
toolbar: any = [
|
|
|
// default value
|
|
@@ -20,60 +39,71 @@ export class JournalNotesComponent implements OnInit, OnDestroy {
|
|
|
[{ heading: ['h3', 'h4', 'h5', 'h6'] }],
|
|
|
];
|
|
|
|
|
|
- /** Used to show the interactale form or the display version of an entry. */
|
|
|
- public isInEditMode = false;
|
|
|
+ public entries: JournalEntry[] = [];
|
|
|
+ public currentEntry: JournalEntry = {
|
|
|
+ title: '',
|
|
|
+ content: '',
|
|
|
+ created: new Date(),
|
|
|
+ };
|
|
|
|
|
|
- /** The index of the currently active entry */
|
|
|
+ public isInEditMode = false;
|
|
|
public currentEntryIndex: number = 0;
|
|
|
-
|
|
|
private backupIndex: number = -1;
|
|
|
- /** Indicates, if the currentEntry is a newly generated one that is still not saved. */
|
|
|
public isNewEntry = false;
|
|
|
|
|
|
- /**The array of JournalEntries, synched to the */
|
|
|
- public entries: JournalEntry[] = [];
|
|
|
+ public tooltipText: string = '';
|
|
|
|
|
|
- /** Holds the data for the current entry */
|
|
|
- public currentEntry: JournalEntry = {
|
|
|
- title: '',
|
|
|
- content: '',
|
|
|
+ public npcDescriptions: any = {};
|
|
|
+
|
|
|
+ tooltipifiedEntry: JournalEntry = {
|
|
|
+ title: 'Title',
|
|
|
+ content: 'Content',
|
|
|
created: new Date(),
|
|
|
};
|
|
|
|
|
|
- constructor(
|
|
|
- private _adapter: DateAdapter<any>,
|
|
|
- private dataService: DataService,
|
|
|
- ) {
|
|
|
- registerLocaleData(localeDe);
|
|
|
- this.entries = this.dataService.notesData;
|
|
|
- }
|
|
|
+ private _adapter: DateAdapter<any> = inject(DateAdapter);
|
|
|
+ private dataService: DataService = inject(DataService);
|
|
|
+ private tooltipService: TooltipService = inject(TooltipService);
|
|
|
+ private renderer: Renderer2 = inject(Renderer2);
|
|
|
+ private el: ElementRef = inject(ElementRef);
|
|
|
|
|
|
ngOnInit(): void {
|
|
|
+ registerLocaleData(localeDe);
|
|
|
this._adapter.setLocale('de');
|
|
|
this.entries = this.dataService.notesData;
|
|
|
- console.log('JournalNotesComponent: ', this.entries);
|
|
|
|
|
|
// if the list is empty, set the currentEntryIndex to -1 to hide the entry-container
|
|
|
if (this.entries.length === 0) {
|
|
|
this.currentEntryIndex = -1;
|
|
|
} else {
|
|
|
this.currentEntry = this.entries[0];
|
|
|
+ this.tooltipifiedEntry = JSON.parse(JSON.stringify(this.currentEntry));
|
|
|
}
|
|
|
+ this.tooltipify();
|
|
|
}
|
|
|
|
|
|
+ // ACTIONS FROM THE TEMPLATE
|
|
|
+
|
|
|
/**
|
|
|
* Sets the currentEntry variable when being clicked on in the entries list on the left.
|
|
|
+ * It also modifies the content of the entry by highlighting names and adding tooltips.
|
|
|
+ * Is only called when the entry is not in edit mode or a different entry is selected.
|
|
|
* @param index The index of the selected entry.
|
|
|
*/
|
|
|
public selectEntry(index: number): void {
|
|
|
- this.currentEntryIndex = index;
|
|
|
- this.currentEntry = this.getEntryAt(index);
|
|
|
- this.isNewEntry = false;
|
|
|
- this.isInEditMode = false;
|
|
|
+ if (this.isInEditMode || index !== this.currentEntryIndex) {
|
|
|
+ this.currentEntryIndex = index;
|
|
|
+ this.currentEntry = this.getEntryAt(index);
|
|
|
+ this.isNewEntry = false;
|
|
|
+ this.isInEditMode = false;
|
|
|
+ this.tooltipify();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // DONE
|
|
|
- addEntry(): void {
|
|
|
+ /**
|
|
|
+ * Adds an new empty entry, switches to edit mode and removes the highlighting of the selected entry.
|
|
|
+ */
|
|
|
+ public addEntry(): void {
|
|
|
this.currentEntry = {
|
|
|
title: '',
|
|
|
content: '',
|
|
@@ -86,11 +116,18 @@ export class JournalNotesComponent implements OnInit, OnDestroy {
|
|
|
this.currentEntryIndex = -1;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Switches to edit mode.
|
|
|
+ */
|
|
|
public editEntry(): void {
|
|
|
this.isInEditMode = true;
|
|
|
}
|
|
|
|
|
|
- // DONE
|
|
|
+ /**
|
|
|
+ * If the current entry is a new entry, it will be prepended to the entries list.
|
|
|
+ * Else it is saved at the current index.
|
|
|
+ * The content is the tooltipified and saved in the database.
|
|
|
+ */
|
|
|
public saveEntry(): void {
|
|
|
if (this.isNewEntry) {
|
|
|
// Prepend the new JournalEntry
|
|
@@ -100,9 +137,15 @@ export class JournalNotesComponent implements OnInit, OnDestroy {
|
|
|
}
|
|
|
this.isInEditMode = false;
|
|
|
this.entries[this.currentEntryIndex] = this.currentEntry;
|
|
|
+ this.tooltipify();
|
|
|
this.uploadNotes();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Discards the current entry and resets the currentEntry to the last saved version.
|
|
|
+ * If the entry was a new entry, the currentEntryIndex is reset to the last selected entry.
|
|
|
+ * The content is also tooltipified again.
|
|
|
+ */
|
|
|
public discardEntry(): void {
|
|
|
if (this.isNewEntry) {
|
|
|
this.currentEntryIndex = this.backupIndex;
|
|
@@ -113,28 +156,87 @@ export class JournalNotesComponent implements OnInit, OnDestroy {
|
|
|
this.currentEntry = this.getEntryAt(this.currentEntryIndex);
|
|
|
}
|
|
|
this.isInEditMode = false;
|
|
|
+ this.tooltipify();
|
|
|
}
|
|
|
|
|
|
- deleteEntry(): void {
|
|
|
+ /**
|
|
|
+ * Deletes the current entry and removes it from the entries list.
|
|
|
+ * If the last entry was deleted, the currentEntryIndex is reset to -1.
|
|
|
+ * The content is saved in the database.
|
|
|
+ */
|
|
|
+ public deleteEntry(): void {
|
|
|
this.entries.splice(this.currentEntryIndex, 1);
|
|
|
if (this.entries.length === 0) {
|
|
|
this.currentEntryIndex = -1;
|
|
|
} else {
|
|
|
this.currentEntryIndex = Math.max(this.currentEntryIndex - 1, 0);
|
|
|
this.currentEntry = this.getEntryAt(this.currentEntryIndex);
|
|
|
+ // Update the tooltipified entry
|
|
|
+ this.tooltipify();
|
|
|
}
|
|
|
this.uploadNotes();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns a deep copy of the entry at the given index.
|
|
|
+ * @param index Defines the index of the entry that should be returned.
|
|
|
+ * @returns A deep copy of the entry at the given index.
|
|
|
+ */
|
|
|
private getEntryAt(index: number): JournalEntry {
|
|
|
return JSON.parse(JSON.stringify(this.entries[index]));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Saves the current entries in the data service.
|
|
|
+ */
|
|
|
private uploadNotes(): void {
|
|
|
- console.log('Uploading notes to the server: ', this.entries);
|
|
|
this.dataService.notesData = this.entries;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Converts the content of the current entry to a tooltipified version.
|
|
|
+ * It then adds the highlights to the names and sets the tooltip text.
|
|
|
+ * Is called on every refresh of an entry (selecting, saving, discarding, deleting, adding, etc.)
|
|
|
+ */
|
|
|
+ public tooltipify(): void {
|
|
|
+ let result: any = this.tooltipService.tooltipifyEntry(
|
|
|
+ this.getEntryAt(this.currentEntryIndex).content,
|
|
|
+ );
|
|
|
+
|
|
|
+ this.tooltipifiedEntry.content = result.content;
|
|
|
+ this.npcDescriptions = result.npcDescriptions;
|
|
|
+ setTimeout(() => {
|
|
|
+ result.npcs.forEach((name: string) => {
|
|
|
+ this.addHighlightsToText(name);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Adds a highlight component to the names that are mentioned in the current entry.
|
|
|
+ * Highlights and adds tooltips to the names that are mentioned in the current entry.
|
|
|
+ * @param name The name of the person which is currently highlighted.
|
|
|
+ */
|
|
|
+ private addHighlightsToText(name: string) {
|
|
|
+ // get all elements where a highlight component should be added to
|
|
|
+ const parent = this.el.nativeElement.querySelectorAll('.' + name);
|
|
|
+ parent.forEach((element: any) => {
|
|
|
+ const componentRef =
|
|
|
+ this.creationAnchor.createComponent(HighlightComponent);
|
|
|
+ componentRef.instance.text = name;
|
|
|
+ componentRef.instance.tooltip = this.tooltip;
|
|
|
+ this.renderer.appendChild(element, componentRef.location.nativeElement);
|
|
|
+ // add a mouseover event listener to the highlight component, when it is hovered over, the tooltip-text is set
|
|
|
+ this.renderer.listen(
|
|
|
+ componentRef.location.nativeElement,
|
|
|
+ 'mouseover',
|
|
|
+ () => {
|
|
|
+ this.tooltipText = this.npcDescriptions[name];
|
|
|
+ },
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
ngOnDestroy(): void {
|
|
|
this.editor.destroy();
|
|
|
}
|