import { CommonModule } from '@angular/common'; import { Component, ElementRef, EventEmitter, forwardRef, Input, Output, ViewChild, ViewEncapsulation, } from '@angular/core'; // modules import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule, } from '@angular/forms'; import { AngularSvgIconModule } from 'angular-svg-icon'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; // pipes import { SafeHtmlPipe } from '../../pipes/safe-html.pipe'; //helper import { CopyPasteHelper } from '../ca-note/utils/helper/copy-paste.helper'; //components import { CaNoteContainerComponent } from '../ca-note-container/ca-note-container.component'; import { CaSpinnerComponent } from '../ca-spinner/ca-spinner.component'; //animation import { accordionAnimation } from '../../animations/accordion-animation'; //svg-routes import { SvgRoutes } from '../../utils/svg-routes/payroll-list-summary-svg-routes'; @Component({ selector: 'app-ca-input-note', templateUrl: './ca-input-note.component.html', styleUrls: ['./ca-input-note.component.scss'], animations: [accordionAnimation('showHideCardBody')], imports: [ // Module CommonModule, FormsModule, ReactiveFormsModule, NgbModule, AngularSvgIconModule, // Component CaNoteContainerComponent, CaSpinnerComponent, // Pipe SafeHtmlPipe, ], encapsulation: ViewEncapsulation.None, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CaInputNoteComponent), multi: true, }, ], }) export class CaInputNoteComponent implements ControlValueAccessor { @ViewChild('main_editor', { static: true }) public noteRef: | ElementRef | undefined; @ViewChild('noteContainer', { static: true }) public noteContainer!: CaNoteContainerComponent; @Input() set note(value: string) { if ( (value && value != '' && value != 'null' && !this.isValue) || this.isBlankNote ) { this.showNote = value; this.value = value; } } @Input() set isVisibleNote(value: boolean) { this.noActive = value ? 'active' : 'innactive'; this._isVisibleNote = !!value; } @Input() isBlankNote: boolean = false; @Input() noteType: string = ''; @Input() entityId: number = 0; @Input() entityType: string = ''; @Input() hasDefArrow: boolean = true; @Input() isVisibleArrow: boolean = true; @Input() noteLabel: string = 'Note'; @Input() placeholder: string = 'Type Something...'; @Input() isReadOnly: boolean = false; @Input() customClass: string = ''; @Output() styledValueEmitter = new EventEmitter(); @Output() saveNoteEmitter = new EventEmitter(); //note properties public _isVisibleNote: boolean | string = 'null'; public selectionTaken!: Selection; public range!: Range; private isValue: boolean = false; public showNote!: string; public value: string = ''; public isFocused: boolean = false; private blurNoteTimeout!: ReturnType; public noActive!: string; //saving public isSavingNote: boolean = false; private saveInterval: number | undefined; private isSaveIntervalStarted!: boolean; public savedValue: string = ''; // ControlValueAccessor callbacks private onChange: (value: any) => void = () => {}; private onTouched: () => void = () => {}; constructor() {} writeValue(value: any): void { this.value = value ?? ''; this.showNote = this.value; } registerOnChange(fn: any): void { this.onChange = fn; } registerOnTouched(fn: any): void { this.onTouched = fn; } setDisabledState?(isDisabled: boolean): void { this.isReadOnly = isDisabled; } public openNote(): void { this.noActive = ''; this._isVisibleNote = !this._isVisibleNote; if (this._isVisibleNote) { this.checkActiveItems(); } } public checkFocus(): void { this.isFocused = true; if (!this._isVisibleNote) { setTimeout(() => { this.checkActiveItems(); }, 150); } } public changeValue(event: Event): void { this.isValue = true; const target = event.target as HTMLElement; this.value = target.innerHTML; this.checkActiveItems(); this.onChange(this.value); this.onTouched(); } public saveNote(allowSave?: boolean): void { if (this.value == '
') { this.value = this.value.replace('
', ''); } if (allowSave) { this.savedValue = this.value; } if ( this.noteType == 'details-card' && this.entityId && this.entityType != '' ) { this.isSavingNote = true; setTimeout(() => { this.isSavingNote = false; }, 700); this.updateNote(); } this.styledValueEmitter.emit(this.noteRef!.nativeElement.innerHTML); this.onChange(this.value); } public stopBlurRemoveTimeout(): void { clearTimeout(this.blurNoteTimeout); } public checkActiveItems(): void { if (this.noteContainer?.checkActiveItems) { this.noteContainer.checkActiveItems(); } } public prepareForTextRange(): void { this.isFocused = false; this.selectionTaken = window.getSelection()!; if (this.selectionTaken.rangeCount && this.selectionTaken.getRangeAt) { this.range = this.selectionTaken.getRangeAt(0); this.selectionTaken.removeAllRanges(); this.selectionTaken.addRange(this.range); this.blurNoteTimeout = setTimeout(() => { this.selectionTaken.removeAllRanges(); }, 100); } this.isSaveIntervalStarted = false; clearInterval(this.saveInterval); if (this.savedValue != this.value) { this.saveNote(true); } this.styledValueEmitter.emit(this.noteRef!.nativeElement.innerHTML); this.onTouched(); } public updateNote(): void { this.showNote = this.value; this.saveNoteEmitter.emit(this.value); } public onPaste(event: ClipboardEvent): void { CopyPasteHelper.onPaste(event); } public getSvgPath(propertyName: keyof typeof SvgRoutes): string { return SvgRoutes[propertyName] as string; } }