funky-framadate-front/src/app/core/services/poll.service.ts

666 lines
21 KiB
TypeScript
Raw Normal View History

2021-11-07 15:21:27 +01:00
import { Inject, Injectable } from '@angular/core';
import { ActivatedRoute, ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
2020-06-12 19:17:39 +02:00
import { Answer } from '../enums/answer.enum';
2020-05-12 19:16:23 +02:00
import { Choice } from '../models/choice.model';
import { Poll } from '../models/poll.model';
import { ApiService } from './api.service';
import { ToastService } from './toast.service';
2020-06-25 22:42:26 +02:00
import { UserService } from './user.service';
import { UuidService } from './uuid.service';
2020-11-13 09:38:42 +01:00
import { HttpClient } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { StorageService } from './storage.service';
import { Title } from '@angular/platform-browser';
2021-11-07 15:21:27 +01:00
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DOCUMENT } from '@angular/common';
import { DateChoice, TimeSlices } from '../models/dateChoice.model';
2021-05-18 22:51:06 +02:00
import { DateUtilitiesService } from './date.utilities.service';
2021-11-07 15:21:27 +01:00
import { Owner } from '../models/owner.model';
import { Stack } from '../models/stack.model';
import { Vote } from '../models/vote.model';
@Injectable({
providedIn: 'root',
})
2020-06-18 16:15:26 +02:00
export class PollService implements Resolve<Poll> {
2021-11-07 21:08:38 +01:00
public _poll: BehaviorSubject<Poll | undefined> = new BehaviorSubject<Poll | undefined>(undefined);
2020-04-22 12:56:18 +02:00
public readonly poll: Observable<Poll | undefined> = this._poll.asObservable();
2021-11-07 14:52:49 +01:00
public form: FormGroup;
public startDateInterval: string;
public endDateInterval: string;
2021-11-07 15:21:27 +01:00
public intervalDays: number = 1;
2021-11-07 14:52:49 +01:00
public intervalDaysDefault = 7;
2021-11-07 15:21:27 +01:00
public dateList: DateChoice[] = []; // sets of days as strings, config to set identical time for days in a special days poll
public timeList: TimeSlices[] = []; // ranges of time expressed as strings
2021-11-07 14:52:49 +01:00
public previousRouteName: string = '/administration';
public nextRouteName: string = '/administration/step/2';
public step_current: number = 1;
public step_max: number = 5;
2021-11-07 15:21:27 +01:00
public round: Function;
public pass_hash: string;
2021-11-07 21:08:38 +01:00
public admin_key: string;
public urlPrefix: string = window.location.origin;
2021-11-07 15:21:27 +01:00
public advancedDisplayEnabled = false;
public showDateInterval = false;
public allowSeveralHours = false;
public richTextMode = false;
public calendar: any;
2020-06-25 22:42:26 +02:00
constructor(
2020-11-13 09:38:42 +01:00
private http: HttpClient,
2020-06-25 22:42:26 +02:00
private router: Router,
private apiService: ApiService,
private storageService: StorageService,
2020-06-25 22:42:26 +02:00
private userService: UserService,
private uuidService: UuidService,
2021-11-07 15:21:27 +01:00
private toastService: ToastService,
private titleService: Title,
2021-11-07 15:21:27 +01:00
public DateUtilitiesService: DateUtilitiesService,
public route: ActivatedRoute,
@Inject(DOCUMENT) private document: any,
private fb: FormBuilder
) {
2021-11-07 15:21:27 +01:00
this.createFormGroup();
2021-11-12 12:09:48 +01:00
if (environment.autofill_creation) {
2021-11-07 15:21:27 +01:00
this.setDemoValues();
2021-11-12 12:09:48 +01:00
this.toastService.display('auto fill de création fait');
2021-11-07 15:21:27 +01:00
} else {
this.calendar = [new Date()];
}
}
/**
* add example values to the form
*/
setDemoValues(): void {
this.addChoice('orange');
this.addChoice('raisin');
this.addChoice('abricot');
this.calendar = [
this.DateUtilitiesService.addDaysToDate(1, new Date()),
this.DateUtilitiesService.addDaysToDate(2, new Date()),
this.DateUtilitiesService.addDaysToDate(3, new Date()),
];
this.form.patchValue({
title: 'mon titre',
description: 'répondez SVP <3 ! *-* ',
custom_url: this.uuidService.getUUID(),
creatorPseudo: 'Chuck Norris',
creatorEmail: 'chucknorris@example.com',
isAboutDate: true,
whoModifiesAnswers: 'everybody',
whoCanChangeAnswers: 'everybody',
isProtectedByPassword: false,
richTextMode: false,
areResultsPublic: true,
expiracyNumberOfDays: 60,
});
this.automaticSlug();
}
/**
* set the poll slug from other data of the poll
*/
automaticSlug() {
this.form.patchValue({ custom_url: this.makeSlug(this.form) });
}
public createFormGroup() {
let form = this.fb.group({
title: ['', [Validators.required, Validators.minLength(12)]],
creatorPseudo: ['', [Validators.required]],
created_at: [new Date(), [Validators.required]],
creatorEmail: ['', [Validators.required]],
custom_url: [this.uuidService.getUUID(), [Validators.required]],
description: ['', [Validators.required]],
password: ['', [Validators.required]],
2021-11-07 15:21:27 +01:00
choices: new FormArray([]),
whoModifiesAnswers: ['', [Validators.required]],
whoCanChangeAnswers: ['', [Validators.required]],
isAboutDate: [true, [Validators.required]],
startDateInterval: ['', [Validators.required]],
endDateInterval: ['', [Validators.required]],
expiresDaysDelay: ['', [Validators.required]],
maxCountOfAnswers: ['', [Validators.required]],
isZeroKnoledge: [false, [Validators.required]],
2021-11-07 15:21:27 +01:00
isProtectedByPassword: [false, [Validators.required]],
isOwnerNotifiedByEmailOnNewVote: [true, [Validators.required]],
isOwnerNotifiedByEmailOnNewComment: [true, [Validators.required]],
2021-11-07 15:21:27 +01:00
areResultsPublic: [true, [Validators.required]],
richTextMode: [false, [Validators.required]],
isYesAnswerAvailable: [true, [Validators.required]],
isMaybeAnswerAvailable: [true, [Validators.required]],
isNoAnswerAvailable: [true, [Validators.required]],
allowComments: [true, [Validators.required]],
hasMaxCountOfAnswers: [300, [Validators.required]],
useVoterUniqueLink: [false, [Validators.required]],
voterEmailList: ['', [Validators.required]],
allowNewDateTime: [60, [Validators.required, Validators.min(0)]],
2021-11-07 15:21:27 +01:00
});
this.form = form;
return form;
}
public updateSlug(): void {
console.log('this.form.value', this.form.value);
this.form.patchValue({ custom_url: this.makeSlug(this.form) });
}
2020-11-13 09:38:42 +01:00
/**
* auto fetch a poll when route is looking for one in the administration pattern
* @param route
* @param state
*/
2020-06-18 16:15:26 +02:00
public async resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Poll> {
console.log('resolve route,state', route, state);
2020-06-25 22:42:26 +02:00
const segments: string[] = state.url.split('/');
const wantedcustom_url: string = segments.includes('poll') ? segments[segments.indexOf('poll') + 1] : '';
if (
!this._poll.getValue() ||
!this._poll.getValue().custom_url ||
this._poll.getValue().custom_url !== wantedcustom_url
) {
if (this.pass_hash) {
this.storageService.vote_stack.pass_hash = this.pass_hash;
await this.loadPollByCustomUrlWithPasswordHash(wantedcustom_url, this.pass_hash);
} else {
await this.loadPollByCustomUrl(wantedcustom_url);
}
2020-06-18 16:15:26 +02:00
}
const loadedPoll = this._poll.getValue();
if (loadedPoll) {
this.storageService.vote_stack.poll_custom_url = loadedPoll.custom_url;
return loadedPoll;
2020-06-18 16:15:26 +02:00
} else {
this.router.navigate(['page-not-found']);
return;
}
}
/**
* get all polls
*/
getAllAvailablePolls(): void {
2020-11-13 09:38:42 +01:00
const baseHref = environment.api.version.apiV1.baseHref;
2021-11-07 15:21:27 +01:00
console.log('getAllAvailablePolls baseHref', baseHref);
2020-11-13 09:38:42 +01:00
const headers = ApiService.makeHeaders();
2021-11-07 15:21:27 +01:00
console.log('getAllAvailablePolls headers', headers);
2020-11-13 09:38:42 +01:00
try {
this.http.get(`${baseHref}/poll`, headers).subscribe((res: Observable<any>) => {
console.log('getAllAvailablePolls res', res);
});
} catch (e) {
2021-11-07 15:21:27 +01:00
console.log('getAllAvailablePolls e', e);
}
}
public async loadPollByCustomUrl(custom_url: string): Promise<void> {
if (custom_url) {
const poll: Poll | undefined = await this.apiService.getPollByCustomUrl(custom_url);
if (poll) {
this.updateCurrentPoll(poll);
this.titleService.setTitle(`☑️ ${poll.title} - ${environment.appTitle}`);
} else {
this.toastService.display(`sondage ${custom_url} non trouvé`);
this.router.navigate(['page-not-found']);
}
} else {
this.toastService.display(`sondage sans custom url : ${custom_url}`);
2021-11-07 15:21:27 +01:00
}
}
public async loadPollByCustomUrlWithPasswordHash(custom_url: string, hash: string): Promise<void> {
if (custom_url) {
const poll: Poll | undefined = await this.apiService.getPollByCustomUrlWithHash(custom_url, hash);
if (poll) {
this.updateCurrentPoll(poll);
this.titleService.setTitle(`☑️ ${poll.title} - ${environment.appTitle}`);
} else {
this.toastService.display(`sondage ${custom_url} non trouvé`);
this.router.navigate(['page-not-found']);
}
} else {
this.toastService.display(`sondage sans custom url : ${custom_url}`);
2020-11-13 09:38:42 +01:00
}
}
/**
* update poll and parse its fields
* @param poll
*/
2021-11-07 15:21:27 +01:00
public updateCurrentPoll(poll: Poll): void {
console.log('this.storageService.vote_stack.id', this.storageService.vote_stack.id);
if (!this.storageService.vote_stack.id || this.storageService.vote_stack.poll_custom_url !== poll.custom_url) {
console.log('set base choices', poll.choices);
// set the choices only the first time the poll loads, or if we changed the poll
console.log(
'this.storageService.vote_stack.poll_custom_url',
this.storageService.vote_stack.poll_custom_url
);
// this.storageService.setChoicesForVoteStack(poll.choices);
}
this.toastService.display('sondage bien mis à jour', 'success');
2021-11-07 15:21:27 +01:00
this._poll.next(poll);
}
/**
* add all the dates between the start and end dates in the interval section
*/
addIntervalOfDates(): void {
const newIntervalArray = this.DateUtilitiesService.getDatesInRange(
this.DateUtilitiesService.parseInputDateToDateObject(new Date(this.startDateInterval)),
this.DateUtilitiesService.parseInputDateToDateObject(new Date(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;
2021-11-07 15:21:27 +01:00
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();
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
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"');
2021-04-29 10:17:13 +02:00
} else {
2021-11-07 15:21:27 +01:00
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.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();
2021-04-29 10:17:13 +02:00
}
2021-04-21 12:17:05 +02:00
}
}
2021-04-30 23:24:48 +02:00
2021-11-07 15:21:27 +01:00
/**
* change time spans
*/
addTime() {
this.timeList.push({
literal: '',
});
}
2021-06-08 14:30:05 +02:00
2021-11-07 15:21:27 +01:00
removeAllTimes() {
this.timeList = [];
}
resetTimes() {
this.timeList = [];
}
/**
* 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: '',
});
const selector = '[ng-reflect-choice_label="dateTime_' + id + '_Choices_' + (this.timeList.length - 1) + '"]';
const elem = this.document.querySelector(selector);
if (elem) {
elem.focus();
2020-10-17 11:12:53 +02:00
}
}
2021-11-07 15:21:27 +01:00
public createPoll(): void {
console.log('this.form', this.form);
const newpoll = this.newPollFromForm(this.form);
this.apiService.createPoll(newpoll).then((resp) => {
console.log('poll created resp', resp);
console.log('TODO fill admin_key');
// this.admin_key = resp.data.admin_key;
});
2021-11-07 15:21:27 +01:00
}
/**
2021-11-07 15:21:27 +01:00
* default interval of dates proposed is from today to 7 days more
*/
2021-11-07 15:21:27 +01:00
setDefaultDatesForInterval(): void {
const dateCurrent = new Date();
const dateJson = dateCurrent.toISOString();
this.startDateInterval = dateJson.substring(0, 10);
this.endDateInterval = this.DateUtilitiesService.addDaysToDate(this.intervalDaysDefault, dateCurrent)
.toISOString()
.substring(0, 10);
this.form.patchValue({
startDateInterval: this.startDateInterval,
endDateInterval: this.endDateInterval,
});
this.countDays();
}
askInitFormDefault(): void {
2021-11-12 12:09:48 +01:00
this.initFormDefault(environment.autofill_creation);
2021-11-07 15:21:27 +01:00
this.toastService.display('formulaire réinitialisé');
}
countDays(): void {
this.intervalDays = this.DateUtilitiesService.countDays(
this.DateUtilitiesService.parseInputDateToDateObject(new Date(this.startDateInterval)),
this.DateUtilitiesService.parseInputDateToDateObject(new Date(this.endDateInterval))
);
}
focusOnChoice(index): void {
const selector = '#choice_label_' + index;
const elem = this.document.querySelector(selector);
if (elem) {
elem.focus();
2021-06-08 10:41:46 +02:00
}
2021-11-07 15:21:27 +01:00
}
2021-11-07 15:21:27 +01:00
deleteChoiceField(index: number): void {
if (this.choices.length !== 1) {
this.choices.removeAt(index);
}
}
initFormDefault(showDemoValues = true): void {
this.form = this.createFormGroup();
this.setDefaultDatesForInterval();
if (showDemoValues) {
this.setDemoValues();
}
}
get choices(): FormArray {
return this.form.get('choices') as FormArray;
}
reinitChoices(): void {
this.choices.setValue([]);
}
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.focusOnChoice(this.choices.length - 1);
2020-06-18 16:15:26 +02:00
}
/**
2021-11-07 15:21:27 +01:00
* make a uniq slug for the current poll creation
* @param form
*/
2021-11-07 15:21:27 +01:00
makeSlug(form: FormGroup): string {
let str = '';
str =
2021-11-07 15:21:27 +01:00
form.value.created_at.getFullYear() +
'_' +
2021-11-07 15:21:27 +01:00
(form.value.created_at.getMonth() + 1) +
'_' +
2021-11-07 15:21:27 +01:00
form.value.created_at.getDate() +
'_' +
2021-11-07 15:21:27 +01:00
form.value.creatorPseudo +
'_' +
2021-11-07 15:21:27 +01:00
form.value.title;
str = str.replace(/^\s+|\s+$/g, ''); // trim
str = str.toLowerCase();
// remove accents, swap ñ for n, etc
const from = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;';
const to = 'aaaaeeeeiiiioooouuuunc------';
for (let i = 0, l = from.length; i < l; i++) {
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
}
str = str
.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
.replace(/\s+/g, '-') // collapse whitespace and replace by -
.replace(/-+/g, '-'); // collapse dashes
2021-11-07 15:21:27 +01:00
return str + '-' + this.uuidService.getUUID();
}
public async saveCurrentPoll(): Promise<void> {
const pollUrl: Subscription = await this.apiService.createPoll(this._poll.getValue());
// TODO: Maybe handle the url to update currentPoll according to backend response
if (pollUrl) {
this.toastService.display('Le sondage a été enregistré.');
} else {
this.toastService.display('Le sondage na été correctement enregistré, veuillez ré-essayer.');
}
}
public saveParticipation(choice: Choice, user: Owner, response: Answer): void {
2021-11-07 15:21:27 +01:00
const currentPoll = this._poll.getValue();
currentPoll.choices.find((c) => c.name === choice.name)?.updateParticipation(user, response);
this.updateCurrentPoll(currentPoll);
this.apiService.createParticipation(currentPoll.custom_url, choice.name, user.pseudo, response);
2020-06-25 22:42:26 +02:00
this.toastService.display('Votre participation au sondage a été enregistrée.');
}
2020-05-12 19:16:23 +02:00
public async deleteAllAnswers(): Promise<void> {
await this.apiService.deletePollAnswers(this._poll.getValue().custom_url);
2020-06-25 22:42:26 +02:00
this.toastService.display('Les participations des votants à ce sondage ont été supprimées.');
2020-05-01 19:10:17 +02:00
}
2020-05-12 19:16:23 +02:00
public async addComment(comment: string): Promise<void> {
await this.apiService.createComment(this._poll.getValue().custom_url, comment);
this.toastService.display('Votre commentaire a été enregistré.');
2020-05-12 19:16:23 +02:00
}
public async deleteComments(): Promise<void> {
await this.apiService.deletePollComments(this._poll.getValue().custom_url);
this.toastService.display('Les commentaires de ce sondage ont été supprimés.');
}
2020-06-12 19:17:39 +02:00
2021-11-07 15:21:27 +01:00
public buildAnswersByChoiceLabelByPseudo(poll: Poll): Map<string, Map<string, Answer>> {
const pseudos: Set<string> = new Set();
poll.choices.forEach((choice: Choice) => {
choice.participants.forEach((users: Set<Owner>) => {
users.forEach((user: Owner) => {
pseudos.add(user.pseudo);
});
});
});
2021-04-30 23:24:48 +02:00
2021-11-07 15:21:27 +01:00
const list = new Map<string, Map<string, Answer>>();
pseudos.forEach((pseudo: string) => {
list.set(
pseudo,
new Map<string, Answer>(
poll.choices.map((choice: Choice) => {
return [choice.name, undefined];
})
)
);
});
2021-11-07 15:21:27 +01:00
poll.choices.forEach((choice: Choice) => {
choice.participants.forEach((users: Set<Owner>, answer: Answer) => {
users.forEach((user: Owner) => {
list.get(user.pseudo).set(choice.name, answer);
});
});
});
2021-04-30 23:24:48 +02:00
2021-11-07 15:21:27 +01:00
return list;
2021-04-30 22:49:55 +02:00
}
public getParticipationUrlFromForm(): string {
return `${environment.frontDomain}#/poll/${this.form.value.custom_url}/consultation`;
}
public getAdministrationUrlFromForm(): string {
// admin_key is filled after creation
return `${environment.frontDomain}#/admin/${this.admin_key}/consultation`;
}
public getParticipationUrl(): string {
2021-11-08 10:56:03 +01:00
// http://localhost:4200/#/poll/dessin-anime/consultation
// TODO handle secure access
// http://localhost:4200/#/poll/citron/consultation/secure/1c01ed9c94fc640a1be864f197ff808c
let url = '';
if (this._poll && this._poll.getValue) {
const polltemp = this._poll.getValue();
if (polltemp) {
url = `${environment.frontDomain}#/poll/${polltemp.custom_url}/consultation`;
}
} else {
url = `${environment.frontDomain}#/poll/${this.form.value.custom_url}/consultation`;
}
// TODO handle pass access
return url;
}
public getAdministrationUrl(): string {
// http://localhost:4200/#/admin/9S75b70ECXI5J5xDc058d3H40H9r2CHfO0Kj8T02EK2U8rY8fYTn-eS659j2Dhp794Oa6R1b9V70e3WGaE30iD9h45zwdm76C85SWB4LcUCrc7e0Ncc0
let url = '';
if (this._poll && this._poll.getValue) {
const polltemp = this._poll.getValue();
if (polltemp) {
url = `${environment.frontDomain}#/admin/${polltemp.admin_key}`;
}
} else {
url = `${environment.frontDomain}#/admin/${this.form.value.admin_key}`;
}
return url;
2021-11-08 10:56:03 +01:00
}
/**
* enrich vote stack with missing default votes
* @param vote_stack
*/
enrichVoteStackWithCurrentPollChoicesDefaultVotes(vote_stack: Stack) {
if (this._poll && this._poll.getValue) {
const polltemp = this._poll.getValue();
polltemp.choices.map((choice) => {
// for each vote, if it has the choice_id, do nothing, else, add a default vote
if (!this.findExistingVoteFromChoiceId(choice.id, vote_stack.votes)) {
vote_stack.votes.push(new Vote(choice.id));
}
});
}
}
/**
* find an existing vote in vote_stack from its choice_id
* @param choice_id
* @param votes
*/
findExistingVoteFromChoiceId(choice_id: number, votes: Vote[]) {
return votes.find((vote: Vote) => {
if (vote.choice_id === choice_id) {
return vote;
}
});
}
2021-11-08 09:32:50 +01:00
convertCalendarDatesToChoices(array_dates) {
return array_dates;
}
/**
* @description convert to API version 1 data transition object
* @param form
*/
newPollFromForm(form: any): Poll {
const newOwner = this.storageService.vote_stack.owner;
const newpoll = new Poll(newOwner, form.value.custom_url, form.value.title);
const pollKeys = Object.keys(newpoll);
const formFields = Object.keys(form.value);
newpoll.allowed_answers = [];
for (const pk of pollKeys) {
if (formFields.indexOf(pk) !== -1) {
const field = form.value[pk];
newpoll[pk] = field;
} else {
console.log('manque pollKey', pk);
}
}
if (form.value.isYesAnswerAvailable) {
newpoll.allowed_answers.push('yes');
}
if (form.value.isMaybeAnswerAvailable) {
newpoll.allowed_answers.push('maybe');
}
if (form.value.isNoAnswerAvailable) {
newpoll.allowed_answers.push('no');
}
newpoll.description = form.value.description;
newpoll.has_several_hours = form.value.hasSeveralHours;
newpoll.hasSeveralHours = form.value.hasSeveralHours;
newpoll.max_count_of_answers = form.value.allowComments;
newpoll.maxCountOfAnswers = form.value.maxCountOfAnswers;
newpoll.password = form.value.password;
newpoll.kind = form.value.kind;
newpoll.allow_comments = form.value.allowComments;
// merge choices from storage
if (form.value.kind === 'date') {
// convert calendar picker dates
}
newpoll.choices = Object.assign([], this.storageService.choices);
newpoll.dateChoices = Object.assign([], this.storageService.dateChoices);
newpoll.timeSlices = Object.assign([], this.storageService.timeSlices);
console.log('newpoll', newpoll);
return newpoll;
}
}