forked from tykayn/funky-framadate-front
⚡ Creation : add hours selection in step 4
This commit is contained in:
parent
edcb1bdcf8
commit
135cc5e512
@ -18,7 +18,7 @@ export class PollConfiguration {
|
||||
public hasMaxCountOfAnswers: boolean = false,
|
||||
public whoCanChangeAnswers: string = environment.poll.defaultConfig.whoCanChangeAnswers, // everybody, self, nobody (= just admin)
|
||||
public visibility: string = environment.poll.defaultConfig.visibility, // visible to anyone with the link:
|
||||
public voteChoices: string = environment.poll.defaultConfig.voteChoices, // possible answers to a vote choice: only "yes", "yes, maybe, no": number = environment.poll.defaultConfig.maxCountOfAnswers,
|
||||
public voteChoices: string = environment.poll.defaultConfig.voteChoices, // possible answers to a vote timeSlice: only "yes", "yes, maybe, no": number = environment.poll.defaultConfig.maxCountOfAnswers,
|
||||
public maxCountOfAnswers: number = environment.poll.defaultConfig.maxCountOfAnswers,
|
||||
public expiresDaysDelay: number = environment.poll.defaultConfig.expiresDaysDelay,
|
||||
public expiracyAfterLastModificationInDays: number = environment.poll.defaultConfig
|
||||
|
@ -8,3 +8,13 @@ export interface DateChoice {
|
||||
export interface TimeSlices {
|
||||
literal: string;
|
||||
}
|
||||
|
||||
export const timeSlicesProposals: TimeSlices[] = [
|
||||
{ literal: 'matin' },
|
||||
{ literal: 'midi' },
|
||||
{ literal: 'après-midi' },
|
||||
{ literal: 'soir' },
|
||||
{ literal: 'aux aurores' },
|
||||
{ literal: 'au petit dej' },
|
||||
{ literal: 'au deuxième petit dej des hobbits' },
|
||||
];
|
||||
|
@ -17,7 +17,7 @@ export class PollDTO {
|
||||
myPolls; // list of retrieved polls from the backend api
|
||||
allowSeveralHours;
|
||||
visibility; // visible to one with the link:
|
||||
voteChoices = 'yes; maybe; no'; // possible answers to a vote choice: only "yes"; "yes; maybe; no"
|
||||
voteChoices = 'yes; maybe; no'; // possible answers to a vote timeSlice: only "yes"; "yes; maybe; no"
|
||||
created_at;
|
||||
expirationDate; // expiracy date
|
||||
voteStackId; // id of the vote stack to update
|
||||
|
@ -77,7 +77,6 @@ export class PollService implements Resolve<Poll> {
|
||||
}
|
||||
if (environment.autofill_creation) {
|
||||
this.setDemoValues();
|
||||
this.toastService.display('auto fill de création fait');
|
||||
}
|
||||
if (environment.autoSendNewPoll) {
|
||||
this.createPoll();
|
||||
@ -303,7 +302,11 @@ export class PollService implements Resolve<Poll> {
|
||||
converted.push({
|
||||
literal: element.literal,
|
||||
date_object: element.date_object,
|
||||
timeList: [],
|
||||
timeList: [
|
||||
{
|
||||
literal: 'matin',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
this.dateChoiceList = [...new Set(converted)];
|
||||
@ -327,14 +330,14 @@ export class PollService implements Resolve<Poll> {
|
||||
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
|
||||
// go to previous timeSlice with arrow up
|
||||
// go to next timeSlice with arrow down
|
||||
|
||||
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
|
||||
// add a field if we are on the last timeSlice
|
||||
if (lastChoice) {
|
||||
this.addChoice();
|
||||
this.toastService.display('choix ajouté par raccourci "flèche bas"');
|
||||
@ -374,7 +377,7 @@ export class PollService implements Resolve<Poll> {
|
||||
}
|
||||
|
||||
/**
|
||||
* add a time period to a specific date choice,
|
||||
* add a time period to a specific date timeSlice,
|
||||
* focus on the new input
|
||||
* @param config
|
||||
* @param id
|
||||
|
@ -71,7 +71,7 @@ export class StorageService {
|
||||
// console.log('autofill au hasard des votes à ce sondage');
|
||||
// this.toastService.display('autofill au hasard des votes à ce sondage');
|
||||
// const defaultvalue = Math.random() > 0.75 ? 'yes' : '';
|
||||
// this.vote_stack.votes.push(new Vote(choice.id, defaultvalue));
|
||||
// this.vote_stack.votes.push(new Vote(timeSlice.id, defaultvalue));
|
||||
// } else {
|
||||
this.vote_stack.votes.push(new Vote(choice.id));
|
||||
// }
|
||||
@ -80,7 +80,7 @@ export class StorageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* look for a choice in the stored vote stack and change it answer
|
||||
* look for a timeSlice in the stored vote stack and change it answer
|
||||
* @param choice_id
|
||||
* @param value
|
||||
*/
|
||||
@ -97,7 +97,7 @@ export class StorageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* check for the value of a choice in the stored vote stack
|
||||
* check for the value of a timeSlice in the stored vote stack
|
||||
* @param choice_id
|
||||
* @param value
|
||||
*/
|
||||
@ -113,7 +113,7 @@ export class StorageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* set all time slices of a choice to the same answer at once
|
||||
* set all time slices of a timeSlice to the same answer at once
|
||||
* @param groupe
|
||||
* @param newAnswer
|
||||
*/
|
||||
|
@ -24,8 +24,8 @@
|
||||
>
|
||||
<!-- <span class="button is-default">-->
|
||||
<!-- <i class="icon fa fa-arrows-v"></i>-->
|
||||
<!-- <span *ngIf="choice.date_object">-->
|
||||
<!-- {{ choice.date_object | date: 'E':'Europe/Paris':'fr_FR' }}-->
|
||||
<!-- <span *ngIf="timeSlice.date_object">-->
|
||||
<!-- {{ timeSlice.date_object | date: 'E':'Europe/Paris':'fr_FR' }}-->
|
||||
<!-- </span>-->
|
||||
<!-- </span>-->
|
||||
<div class="columns">
|
||||
|
@ -60,7 +60,7 @@ export class DayListComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* add a time period to a specific date choice,
|
||||
* add a time period to a specific date timeSlice,
|
||||
* focus on the new input
|
||||
* @param choice DateChoice
|
||||
* @param id number
|
||||
@ -79,7 +79,7 @@ export class DayListComponent {
|
||||
if (firstField) {
|
||||
firstField.focus();
|
||||
} else {
|
||||
console.log('no last time choice found');
|
||||
console.log('no last time timeSlice found');
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,15 +97,15 @@ export class DayListComponent {
|
||||
// TODO handle shortcuts
|
||||
// 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
|
||||
// go to previous timeSlice with arrow up
|
||||
// go to next timeSlice with arrow down
|
||||
console.log('$event', $event);
|
||||
|
||||
if ($event.ctrlKey && $event.key == 'ArrowUp' && choice_number > 0) {
|
||||
this.focusOnChoice(choice_number - 1);
|
||||
}
|
||||
if ($event.ctrlKey && ($event.key == 'ArrowDown' || $event.key == 'ArrowRight')) {
|
||||
// add a field if we are on the last choice
|
||||
// add a field if we are on the last timeSlice
|
||||
if (lastChoice) {
|
||||
this.addChoice();
|
||||
this.toastService.display('choix ajouté par raccourci "flèche bas"');
|
||||
|
@ -60,7 +60,7 @@ export class TimeListComponent implements OnInit {
|
||||
focusOnLastField() {
|
||||
this.cd.detectChanges();
|
||||
if (!this.focusOnFieldNumber(this.timeSlices.length - 1)) {
|
||||
console.log('no last time choice found');
|
||||
console.log('no last time timeSlice found');
|
||||
this.createNewField();
|
||||
this.focusOnLastField();
|
||||
}
|
||||
|
@ -1,12 +1,81 @@
|
||||
<div class="step">
|
||||
<div class="min-height">
|
||||
<form action="#" [formGroup]="pollService.form">
|
||||
<app-stepper [step_current]="4" [step_max]="pollService.step_max"></app-stepper>
|
||||
<app-errors-list [form]="pollService.form"></app-errors-list>
|
||||
<h2 class="title is-2">
|
||||
Choisissez les horaires
|
||||
</h2>
|
||||
</form>
|
||||
<app-stepper [step_current]="4" [step_max]="pollService.step_max"></app-stepper>
|
||||
<app-errors-list [form]="pollService.form"></app-errors-list>
|
||||
<h2 class="title is-2">
|
||||
Choisissez les horaires
|
||||
</h2>
|
||||
<app-wip-todo></app-wip-todo>
|
||||
<div
|
||||
class="days-list-having-separated-time-slices rounded-block"
|
||||
*ngFor="let dayChoice of pollService.dateChoiceList; index as day_id"
|
||||
>
|
||||
<div class="heading day-choice">
|
||||
{{ dayChoice.date_object | date }}
|
||||
</div>
|
||||
|
||||
<section class="time-slice-list-of-a-day">
|
||||
<div *ngFor="let timeSlice of dayChoice.timeSlices; index as id" class="time-choice padded">
|
||||
<label for="dateChoices_{{ id }}"> Horaire / option {{ id + 1 }} </label>
|
||||
<input
|
||||
class="input is-fullwidth"
|
||||
type="text"
|
||||
id="dateChoices_{{ id }}"
|
||||
[(ngModel)]="timeSlice.literal"
|
||||
/>
|
||||
<button class="button input is-full" (click)="pollService.timeList.splice(id, 1)">
|
||||
<i class="fa fa-trash"></i> supprimer
|
||||
</button>
|
||||
</div>
|
||||
<div class="add-time-choice">
|
||||
<button (click)="addChoiceForDay(dayChoice)">
|
||||
<i class="fa fa-plus"></i>
|
||||
Ajouter horaire / option
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="proposals">
|
||||
<h3 class="title is-3">
|
||||
Propositions de créneaux horaires
|
||||
</h3>
|
||||
<div class="time-slices-proposals rounded-block">
|
||||
<div
|
||||
class="button is-rounded"
|
||||
*ngFor="let text of timeSlicesProposals"
|
||||
(click)="addPreselect(text.literal)"
|
||||
>
|
||||
{{ text.literal }}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="same-time-slices">
|
||||
<button class="is-outlined is-primary" (click)="toggleHasSeveralHours()">
|
||||
Appliquer le même horaire / option à toutes les dates
|
||||
</button>
|
||||
<section class="same-time-slices rounded-block" *ngIf="pollService.form.value.hasSeveralHours">
|
||||
<h3 class="title is-3">
|
||||
Choisissez les horaires ou options à appliquer à toutes les dates
|
||||
</h3>
|
||||
<div *ngFor="let timeSlice of pollService.timeList; index as id" class="time-choice padded">
|
||||
<label for="timeList_{{ id }}"> Horaire / option {{ id + 1 }} </label>
|
||||
<input
|
||||
class="input is-fullwidth"
|
||||
type="text"
|
||||
id="timeList_{{ id }}"
|
||||
[(ngModel)]="timeSlice.literal"
|
||||
/>
|
||||
<button class="button is-block" (click)="pollService.timeList.splice(id, 1)">
|
||||
<i class="fa fa-trash"></i> supprimer
|
||||
</button>
|
||||
</div>
|
||||
<button class="is-primary button" (click)="applyTimeSlicesToDateChoices()">
|
||||
Appliquer ces créneaux
|
||||
</button>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
|
@ -1,7 +1,12 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Component, Inject, Input, OnInit } from '@angular/core';
|
||||
import { PollService } from '../../../../../core/services/poll.service';
|
||||
import { environment } from '../../../../../../environments/environment';
|
||||
import { Router } from '@angular/router';
|
||||
import { DateUtilitiesService } from '../../../../../core/services/date.utilities.service';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { StorageService } from '../../../../../core/services/storage.service';
|
||||
import { DateChoice, TimeSlices, timeSlicesProposals } from '../../../../../core/models/dateChoice.model';
|
||||
import { ToastService } from '../../../../../core/services/toast.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-step-four',
|
||||
@ -15,10 +20,78 @@ export class StepFourComponent implements OnInit {
|
||||
step_max: any;
|
||||
@Input()
|
||||
form: any;
|
||||
showSameTimeSlices: boolean = false;
|
||||
timeSlicesProposals: TimeSlices[] = timeSlicesProposals;
|
||||
|
||||
constructor(private router: Router, public pollService: PollService) {
|
||||
constructor(
|
||||
private dateUtilitiesService: DateUtilitiesService,
|
||||
private router: Router,
|
||||
private toastService: ToastService,
|
||||
@Inject(DOCUMENT) private document: any,
|
||||
private storageService: StorageService,
|
||||
public pollService: PollService
|
||||
) {
|
||||
this.pollService.step_current = 4;
|
||||
}
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
/**
|
||||
* toggle hasSeveralHours to show an other form section
|
||||
* so that the user can choose between time slices applying equally to all days in her form,
|
||||
* or have the ability to define different times lices for each day
|
||||
*/
|
||||
toggleHasSeveralHours() {
|
||||
this.pollService.form.patchValue({
|
||||
hasSeveralHours: !this.pollService.form.value.hasSeveralHours,
|
||||
});
|
||||
}
|
||||
|
||||
addChoiceForDay(dayChoice: DateChoice): void {
|
||||
let lastDateChoice = this.pollService.dateChoiceList[this.pollService.dateChoiceList.length];
|
||||
console.log('lastDateChoice', lastDateChoice);
|
||||
let lastDateChoiceObject = this.dateUtilitiesService.addDaysToDate(
|
||||
this.pollService.dateChoiceList.length,
|
||||
new Date()
|
||||
);
|
||||
|
||||
if (lastDateChoice && lastDateChoice.date_object) {
|
||||
lastDateChoiceObject = lastDateChoice.date_object;
|
||||
} else {
|
||||
lastDateChoiceObject = new Date();
|
||||
}
|
||||
dayChoice.timeSlices.push({
|
||||
literal: '',
|
||||
});
|
||||
dayChoice.timeSlices.sort((a: any, b: any) => {
|
||||
return a.date_object - b.date_object;
|
||||
});
|
||||
this.focusOnChoice(this.storageService.dateChoices.length - 1);
|
||||
}
|
||||
|
||||
focusOnChoice(index): void {
|
||||
const selector = '#choice_label_' + index;
|
||||
const elem = this.document.querySelector(selector);
|
||||
if (elem) {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
|
||||
addPreselect(literal: string) {
|
||||
if (
|
||||
!this.pollService.timeList.find((elem) => {
|
||||
return elem.literal === literal;
|
||||
})
|
||||
) {
|
||||
this.pollService.timeList.push({ literal });
|
||||
}
|
||||
}
|
||||
|
||||
applyTimeSlicesToDateChoices() {
|
||||
let timeSlicesToApply = this.pollService.timeList;
|
||||
this.pollService.dateChoiceList.forEach((elem) => {
|
||||
return (elem.timeSlices = timeSlicesToApply);
|
||||
});
|
||||
this.toastService.display(`time slices appliquées avec succès`);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<!-- <button class="button is-white" (click)="openModal(poll, choice)">-->
|
||||
<!-- <button class="button is-white" (click)="openModal(poll, timeSlice)">-->
|
||||
<!-- <i class="fa fa-info-circle"></i>-->
|
||||
<!-- </button>-->
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Choix
|
||||
</th>
|
||||
<th *ngFor="let choice of poll.choices">
|
||||
<!-- {{choice.id}}-->
|
||||
<!-- {{timeSlice.id}}-->
|
||||
<span class="label" *ngIf="poll.kind == 'text'">
|
||||
{{ choice.name }}
|
||||
</span>
|
||||
|
@ -15,7 +15,7 @@ export const environment = {
|
||||
advanced_options_display: false,
|
||||
autofill_participation: false,
|
||||
showDemoWarning: false,
|
||||
autoSendNewPoll: true,
|
||||
autoSendNewPoll: false,
|
||||
showStepperShortcuts: true,
|
||||
interval_days_default: 7,
|
||||
expiresDaysDelay: 60,
|
||||
|
@ -298,7 +298,7 @@ mat-checkbox {
|
||||
}
|
||||
}
|
||||
|
||||
.block-resume {
|
||||
.rounded-block {
|
||||
border-radius: 0.25em;
|
||||
background: $bg-grey;
|
||||
padding: 1em;
|
||||
@ -308,8 +308,8 @@ mat-checkbox {
|
||||
margin: 0.5em -1em;
|
||||
background: $rules;
|
||||
}
|
||||
|
||||
.go-to-step {
|
||||
.go-to-step,
|
||||
.custom-action {
|
||||
@extend .clickable;
|
||||
color: $secondary_color;
|
||||
padding: 1.5em;
|
||||
@ -321,3 +321,7 @@ mat-checkbox {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.block-resume {
|
||||
@extend .rounded-block;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user