import { ChangeDetectorRef, Component, Inject, Input, OnInit } from '@angular/core'; import { Poll } from '../../../core/models/poll.model'; import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { UuidService } from '../../../core/services/uuid.service'; import { ApiService } from '../../../core/services/api.service'; import { ToastService } from '../../../core/services/toast.service'; import { PollService } from '../../../core/services/poll.service'; import { DateUtilities } from '../../old-stuff/config/DateUtilities'; import { DOCUMENT } from '@angular/common'; import { DateChoice, otherDefaultDates } from '../../old-stuff/config/defaultConfigs'; import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; @Component({ selector: 'app-admin-form', templateUrl: './form.component.html', styleUrls: ['./form.component.scss'], }) export class FormComponent implements OnInit { @Input() public poll?: Poll; public form: FormGroup; public urlPrefix: string = window.location.origin + '/participation/'; public advancedDisplayEnabled = false; public showDateInterval = false; public allowSeveralHours = false; public richTextMode = false; startDateInterval: string; endDateInterval: string; intervalDays: any; intervalDaysDefault = 7; dateList: any = otherDefaultDates; // sets of days as strings, config to set identical time for days in a special days poll timeList: DateChoice[] = otherDefaultDates; // ranges of time expressed as strings step_current: number = 1; step_max: number = 5; public round: Function; constructor( private fb: FormBuilder, private cd: ChangeDetectorRef, private uuidService: UuidService, private toastService: ToastService, private pollService: PollService, public dateUtilities: DateUtilities, private apiService: ApiService, @Inject(DOCUMENT) private document: any ) {} drop(event: CdkDragDrop) { // moveItemInArray(this.choices, event.previousIndex, event.currentIndex); } get choices(): FormArray { return this.form.get('choices') as FormArray; } ngOnInit(): void { this.initFormDefault(); const pollsAvailable = this.pollService.getAllAvailablePolls(); console.log('pollsAvailable', pollsAvailable); } public createPoll(): void { console.log('this.form', this.form); const newpoll = this.pollService.newPollFromForm(this.form); console.log('newpoll', newpoll); this.apiService.createPoll(newpoll); } public updateSlug(): void { const newValueFormatted = 'TODO'; this.form.patchValue({ slug: newValueFormatted }); } addChoice(optionalLabel = ''): void { const newControlGroup = this.fb.group({ label: this.fb.control('', [Validators.required]), imageUrl: ['', [Validators.required]], }); if (optionalLabel) { newControlGroup.patchValue({ label: optionalLabel, imageUrl: 'mon url', }); } this.choices.push(newControlGroup); this.cd.detectChanges(); console.log('this.choices.length', this.choices.length); this.focusOnChoice(this.choices.length - 1); } focusOnChoice(index): void { const selector = '#choice_label_' + index; const elem = this.document.querySelector(selector); if (elem) { elem.focus(); } } deleteChoiceField(index: number): void { if (this.choices.length !== 1) { this.choices.removeAt(index); } } reinitChoices(): void { this.choices.setValue([]); } initFormDefault(showDemoValues = true): void { this.form = this.fb.group({ title: ['', [Validators.required, Validators.minLength(12)]], creatorPseudo: ['', [Validators.required]], creatorEmail: ['', [Validators.required]], slug: [this.uuidService.getUUID(), [Validators.required]], description: ['', [Validators.required]], choices: new FormArray([]), whoModifiesAnswers: ['', [Validators.required]], whoCanChangeAnswers: ['', [Validators.required]], isAboutDate: [true, [Validators.required]], startDateInterval: ['', [Validators.required]], endDateInterval: ['', [Validators.required]], isProtectedByPassword: [false, [Validators.required]], isOwnerNotifiedByEmailOnNewVote: [false, [Validators.required]], isOwnerNotifiedByEmailOnNewComment: [false, [Validators.required]], isMaybeAnswerAvailable: [false, [Validators.required]], areResultsPublic: [true, [Validators.required]], expiracyNumberOfDays: [60, [Validators.required, Validators.min(0)]], }); console.log('this.form ', this.form); this.setDefaultDatesForInterval(); if (showDemoValues) { this.setDemoValues(); } } /** * default interval of dates proposed is from today to 7 days more */ setDefaultDatesForInterval(): void { const dateCurrent = new Date(); const dateJson = dateCurrent.toISOString(); this.startDateInterval = dateJson.substring(0, 10); this.endDateInterval = this.dateUtilities .addDaysToDate(this.intervalDaysDefault, dateCurrent) .toISOString() .substring(0, 10); this.form.patchValue({ startDateInterval: this.startDateInterval, endDateInterval: this.endDateInterval, }); this.countDays(); } /** * add example values to the form */ setDemoValues(): void { this.addChoice('orange'); this.addChoice('raisin'); this.addChoice('abricot'); this.form.patchValue({ title: 'mon titre', description: 'répondez SVP <3 ! *-* ', slug: this.uuidService.getUUID(), creatorPseudo: 'Chuck Norris', creatorEmail: 'chucknorris@example.com', isAboutDate: true, whoModifiesAnswers: 'everybody', whoCanChangeAnswers: 'everybody', isProtectedByPassword: false, isOwnerNotifiedByEmailOnNewVote: false, isOwnerNotifiedByEmailOnNewComment: false, isMaybeAnswerAvailable: false, areResultsPublic: true, expiracyNumberOfDays: 60, }); this.automaticSlug(); } askInitFormDefault(): void { this.initFormDefault(false); this.toastService.display('formulaire réinitialisé'); } countDays(): void { this.intervalDays = this.dateUtilities.countDays( this.dateUtilities.parseInputDateToDateObject(this.startDateInterval), this.dateUtilities.parseInputDateToDateObject(this.endDateInterval) ); this.cd.detectChanges(); } /** * add all the dates between the start and end dates in the interval section */ addIntervalOfDates(): void { const newIntervalArray = this.dateUtilities.getDatesInRange( this.dateUtilities.parseInputDateToDateObject(this.startDateInterval), this.dateUtilities.parseInputDateToDateObject(this.endDateInterval), 1 ); const converted = []; newIntervalArray.forEach((element) => { converted.push({ literal: element.literal, date_object: element.date_object, timeList: [], }); }); this.dateList = [...new Set(converted)]; // add only dates that are not already present with a Set of unique items console.log('this.dateList', this.dateList); this.showDateInterval = false; this.form.patchValue({ choices: this.dateList }); this.toastService.display(`les dates ont été ajoutées aux réponses possibles.`); } /** * handle keyboard shortcuts * @param $event * @param choice_number */ keyOnChoice($event: KeyboardEvent, choice_number: number): void { $event.preventDefault(); console.log('this.choices.length', this.choices.length); console.log('choice_number', choice_number); const lastChoice = this.choices.length - 1 === choice_number; // reset field with Ctrl + D // add a field with Ctrl + N // go to previous choice with arrow up // go to next choice with arrow down console.log('$event', $event); if ($event.key == 'ArrowUp' && choice_number > 0) { this.focusOnChoice(choice_number - 1); } if ($event.key == 'ArrowDown') { // add a field if we are on the last choice if (lastChoice) { this.addChoice(); this.toastService.display('choix ajouté par raccourci "flèche bas"'); } else { this.focusOnChoice(choice_number + 1); } } if ($event.ctrlKey && $event.key == 'Backspace') { this.deleteChoiceField(choice_number); this.toastService.display('choix supprimé par raccourci "Ctrl + retour"'); this.cd.detectChanges(); this.focusOnChoice(Math.min(choice_number - 1, 0)); } if ($event.ctrlKey && $event.key == 'Enter') { // go to other fields const elem = this.document.querySelector('#creatorEmail'); if (elem) { elem.focus(); } } } /** * change time spans */ addTime() { this.timeList.push({ literal: '', timeList: [], date_object: new Date(), }); } removeAllTimes() { this.timeList = []; } resetTimes() { this.timeList = otherDefaultDates; } /** * add a time period to a specific date choice, * focus on the new input * @param config * @param id */ addTimeToDate(config: any, id: number) { this.timeList.push({ literal: '', timeList: [], date_object: new Date(), }); const selector = '[ng-reflect-choice_label="dateTime_' + id + '_Choices_' + (this.timeList.length - 1) + '"]'; this.cd.detectChanges(); const elem = this.document.querySelector(selector); if (elem) { elem.focus(); } } /** * set the poll slug from other data of the poll */ automaticSlug() { this.poll.slug = this.pollService.makeSlug(this.poll); } }