forked from tykayn/funky-framadate-front
add keybaord shortcuts on array for choices
This commit is contained in:
parent
d3042b3723
commit
4769ecefc3
@ -65,6 +65,34 @@
|
||||
<fieldset class="date-kind">
|
||||
<!-- choix spécialement pour les dates-->
|
||||
</fieldset>
|
||||
|
||||
<button
|
||||
(click)="showDateInterval = !showDateInterval"
|
||||
[ngClass]="{ active: showDateInterval }"
|
||||
class="btn btn--primary"
|
||||
id="toggle_interval_button"
|
||||
>
|
||||
<i class="fa fa-clock-o" aria-hidden="true"></i>
|
||||
{{ 'dates.add_interval' | translate }}
|
||||
</button>
|
||||
<section *ngIf="showDateInterval" class="date-interval form-row">
|
||||
<h2>{{ 'dates.add_interval' | translate }}</h2>
|
||||
<p>
|
||||
{{ 'dates.interval_propose' | translate }}
|
||||
<input (change)="countDays()" formControlName="startDateInterval" type="date" />
|
||||
{{ 'dates.interval_span' | translate }}
|
||||
<input (change)="countDays()" formControlName="endDateInterval" type="date" />
|
||||
<br />
|
||||
</p>
|
||||
<button (click)="addIntervalOfDates()" class="btn btn-block btn--primary">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||
{{ 'dates.interval_button' | translate }}
|
||||
{{ intervalDays }}
|
||||
{{ 'dates.interval_button_dates' | translate }}
|
||||
</button>
|
||||
<hr />
|
||||
</section>
|
||||
|
||||
<div class="form-field">
|
||||
<h2>
|
||||
{{ 'choices.title' | translate }}
|
||||
@ -94,6 +122,9 @@
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<p class="hint">
|
||||
{{ 'creation.choices_hint' | translate }}
|
||||
</p>
|
||||
<span *ngFor="let choice of choices.controls; let i = index">
|
||||
<div class="form-row" [formGroup]="choice">
|
||||
<div class="columns">
|
||||
@ -104,11 +135,23 @@
|
||||
{{ i * 1 + 1 }})
|
||||
</div>
|
||||
<div class="column">
|
||||
<label for="label" class="hidden">label</label>
|
||||
<input formControlName="label" id="label" placeholder="Enter a choice description" />
|
||||
<label [for]="'choice_label_' + i" class="hidden">label</label>
|
||||
<input
|
||||
formControlName="label"
|
||||
[id]="'choice_label_' + i"
|
||||
placeholder="Enter a choice description"
|
||||
(keyup)="keyOnChoice($event, i)"
|
||||
(keyup.backspace)="deleteChoiceField(i)"
|
||||
/>
|
||||
<br />
|
||||
<label for="imageUrl" class="hidden">image Url</label>
|
||||
<input formControlName="imageUrl" id="imageUrl" placeholder="URL de l' image" />
|
||||
<label [for]="'image_url_' + i" class="hidden">image Url</label>
|
||||
<input
|
||||
formControlName="imageUrl"
|
||||
[id]="'image_url_' + i"
|
||||
placeholder="URL de l' image"
|
||||
(keyup)="keyOnChoice($event, i)"
|
||||
(keyup.backspace)="deleteChoiceField(i)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-admin-form',
|
||||
@ -18,13 +20,22 @@ export class FormComponent implements OnInit {
|
||||
|
||||
public urlPrefix: string = window.location.origin + '/participation/';
|
||||
public advancedDisplayEnabled = false;
|
||||
public showDateInterval = true;
|
||||
startDateInterval: any;
|
||||
intervalDays: any;
|
||||
intervalDaysDefault = 7;
|
||||
endDateInterval: any;
|
||||
dateList: any[];
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private cd: ChangeDetectorRef,
|
||||
private uuidService: UuidService,
|
||||
private toastService: ToastService,
|
||||
private pollService: PollService,
|
||||
private apiService: ApiService
|
||||
public dateUtilities: DateUtilities,
|
||||
private apiService: ApiService,
|
||||
@Inject(DOCUMENT) private document: any
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -61,6 +72,13 @@ export class FormComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
this.choices.push(newControlGroup);
|
||||
this.cd.detectChanges();
|
||||
console.log('this.choices.length', this.choices.length);
|
||||
const selector = '#choice_label_' + (this.choices.length - 1);
|
||||
const elem = this.document.querySelector(selector);
|
||||
if (elem) {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
|
||||
deleteChoiceField(index: number): void {
|
||||
@ -73,7 +91,7 @@ export class FormComponent implements OnInit {
|
||||
this.choices.setValue([]);
|
||||
}
|
||||
|
||||
initFormDefault(): void {
|
||||
initFormDefault(showDemoValues = true): void {
|
||||
this.form = this.fb.group({
|
||||
title: ['', [Validators.required, Validators.minLength(12)]],
|
||||
creatorPseudo: ['', [Validators.required]],
|
||||
@ -82,6 +100,8 @@ export class FormComponent implements OnInit {
|
||||
description: ['', [Validators.required]],
|
||||
choices: new FormArray([]),
|
||||
isAboutDate: [true, [Validators.required]],
|
||||
startDateInterval: ['', [Validators.required]],
|
||||
endDateInterval: ['', [Validators.required]],
|
||||
isProtectedByPassword: [false, [Validators.required]],
|
||||
isOwnerNotifiedByEmailOnNewVote: [false, [Validators.required]],
|
||||
isOwnerNotifiedByEmailOnNewComment: [false, [Validators.required]],
|
||||
@ -90,9 +110,33 @@ export class FormComponent implements OnInit {
|
||||
expiracyNumberOfDays: [60, [Validators.required, Validators.min(0)]],
|
||||
});
|
||||
console.log('this.form ', this.form);
|
||||
this.setDemoValues();
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* add example values to the form
|
||||
*/
|
||||
setDemoValues(): void {
|
||||
this.addChoice('orange');
|
||||
this.addChoice('raisin');
|
||||
@ -116,7 +160,88 @@ export class FormComponent implements OnInit {
|
||||
}
|
||||
|
||||
askInitFormDefault(): void {
|
||||
this.initFormDefault();
|
||||
this.initFormDefault(false);
|
||||
this.toastService.display('formulaire réinitialisé');
|
||||
}
|
||||
|
||||
countDays(): void {
|
||||
this.intervalDays = this.dateUtilities.countDays(this.startDateInterval, this.endDateInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* add all the dates between the start and end dates in the interval section
|
||||
*/
|
||||
addIntervalOfDates(): void {
|
||||
const newIntervalArray = this.dateUtilities.getDatesInRange(this.startDateInterval, 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.toastService.display(`les dates ont été ajoutées aux réponses possibles.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* handle keyboard shortcuts
|
||||
* @param $event
|
||||
*/
|
||||
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) {
|
||||
const selector = '#choice_label_' + (choice_number - 1);
|
||||
const elem = this.document.querySelector(selector);
|
||||
if (elem) {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
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 {
|
||||
const selector = '#choice_label_' + (choice_number + 1);
|
||||
const elem = this.document.querySelector(selector);
|
||||
if (elem) {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($event.ctrlKey && $event.key == 'Backspace') {
|
||||
this.deleteChoiceField(choice_number);
|
||||
this.toastService.display('choix supprimé par raccourci "Ctrl + retour"');
|
||||
this.cd.detectChanges();
|
||||
const selector = '#choice_label_' + Math.min(choice_number - 1, 0);
|
||||
const elem = this.document.querySelector(selector);
|
||||
if (elem) {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
if ($event.ctrlKey && $event.key == 'Enter') {
|
||||
// go to other fields
|
||||
const elem = this.document.querySelector('#creatorEmail');
|
||||
if (elem) {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,4 +60,12 @@ export class DateUtilities {
|
||||
getDoubleDigits(str) {
|
||||
return ('00' + str).slice(-2);
|
||||
}
|
||||
|
||||
countDays(startDateInterval: Date, endDateInterval: Date): number {
|
||||
// compute the number of days in the date interval
|
||||
if (endDateInterval && startDateInterval) {
|
||||
return this.dayDiff(endDateInterval, startDateInterval);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ export class DatesComponent extends BaseComponent implements OnInit {
|
||||
date_object: new Date(),
|
||||
timeList: [],
|
||||
});
|
||||
const selector = '[ng-reflect-choice_label="dateChoices_' + (this.config.dateList.length - 1) + '"]';
|
||||
const selector = '["choice_label_' + (this.config.dateList.length - 1) + '"]';
|
||||
this.cd.detectChanges();
|
||||
const elem = this.document.querySelector(selector);
|
||||
if (elem) {
|
||||
|
@ -35,6 +35,7 @@
|
||||
},
|
||||
"choose_title": "Dont le titre sera",
|
||||
"choose_title_placeholder": "titre",
|
||||
"choices_hint": "Utilisez les flèches haut ⬆️ et bas ⬇️ pour passer d'un choix à un autre",
|
||||
"name": "Je peux aussi préciser mon nom si je le souhaite",
|
||||
"name_placeholder": "mon nom",
|
||||
"description": "et la description serait",
|
||||
|
Loading…
Reference in New Issue
Block a user