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

230 lines
8.3 KiB
TypeScript
Raw Normal View History

import { Injectable } from '@angular/core';
2020-06-18 16:15:26 +02:00
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { BehaviorSubject, Observable } 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';
2020-05-12 19:16:23 +02:00
import { User } from '../models/user.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-05 19:13:43 +01:00
import { Form } from '@angular/forms';
import { PollConfig } from '../../features/old-stuff/config/PollConfig';
2020-11-11 12:14:01 +01:00
import { environment } from '../../../environments/environment';
import {
DateChoice,
defaultAnswers,
otherDefaultDates,
PollAnswer,
} from '../../features/old-stuff/config/defaultConfigs';
@Injectable({
providedIn: 'root',
})
2020-06-18 16:15:26 +02:00
export class PollService implements Resolve<Poll> {
private _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();
2020-06-25 22:42:26 +02:00
constructor(
private router: Router,
private apiService: ApiService,
private userService: UserService,
private uuidService: UuidService,
private toastService: ToastService
) {}
2020-06-18 16:15:26 +02:00
public async resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Poll> {
2020-06-25 22:42:26 +02:00
const segments: string[] = state.url.split('/');
const wantedSlug: string = segments.includes('poll') ? segments[segments.indexOf('poll') + 1] : '';
2020-06-18 16:15:26 +02:00
if (!wantedSlug && state.url.includes('administration')) {
// creation of new poll
2020-06-25 22:42:26 +02:00
const poll = new Poll(this.userService.getCurrentUser(), this.uuidService.getUUID(), '');
this._poll.next(poll);
this.router.navigate(['poll/' + poll.slug + '/administration']);
2020-06-18 16:15:26 +02:00
}
if (!this._poll.getValue() || !this._poll.getValue().slug || this._poll.getValue().slug !== wantedSlug) {
await this.loadPollBySlug(wantedSlug);
}
if (this._poll.getValue()) {
return this._poll.getValue();
} else {
this.router.navigate(['page-not-found']);
return;
}
}
2020-06-18 16:15:26 +02:00
public async loadPollBySlug(slug: string): Promise<void> {
2020-10-17 11:12:53 +02:00
console.log('slug', slug);
if (slug) {
const poll: Poll | undefined = await this.apiService.getPollBySlug(slug);
console.log({ loadPollBySlugResponse: poll });
this.updateCurrentPoll(poll);
}
}
2020-06-18 16:15:26 +02:00
public updateCurrentPoll(poll: Poll): void {
this._poll.next(poll);
}
/**
* make a uniq slug for the current poll creation
* @param config
*/
makeSlug(config: Poll): string {
let str = '';
str =
config.configuration.dateCreated.getFullYear() +
'_' +
(config.configuration.dateCreated.getMonth() + 1) +
'_' +
config.configuration.dateCreated.getDate() +
'_' +
config.owner.pseudo +
'_' +
config.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
return str + '-' + this.uuidService.getUUID();
}
2020-05-12 19:16:23 +02:00
public async saveCurrentPoll(): Promise<void> {
const pollUrl: string = await this.apiService.createPoll(this._poll.getValue());
// TODO: Maybe handle the url to update currentPoll according to backend response
if (pollUrl) {
2020-11-09 12:44:24 +01:00
console.log('pollUrl', pollUrl);
this.toastService.display('Le sondage a été enregistré.');
2020-05-12 19:16:23 +02:00
} else {
this.toastService.display('Le sondage na été correctement enregistré, veuillez ré-essayer.');
2020-05-12 19:16:23 +02:00
}
}
2020-06-12 19:17:39 +02:00
public saveParticipation(choice: Choice, user: User, response: Answer): void {
2020-05-12 19:16:23 +02:00
const currentPoll = this._poll.getValue();
2020-06-12 19:17:39 +02:00
currentPoll.choices.find((c) => c.label === choice.label)?.updateParticipation(user, response);
2020-05-12 19:16:23 +02:00
this.updateCurrentPoll(currentPoll);
this.apiService.createParticipation(currentPoll.slug, choice.label, 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().slug);
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().slug, 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().slug);
this.toastService.display('Les commentaires de ce sondage ont été supprimés.');
}
2020-06-12 19:17:39 +02: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<User>) => {
users.forEach((user: User) => {
pseudos.add(user.pseudo);
});
});
});
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.label, undefined];
})
)
);
});
poll.choices.forEach((choice: Choice) => {
choice.participants.forEach((users: Set<User>, answer: Answer) => {
users.forEach((user: User) => {
list.get(user.pseudo).set(choice.label, answer);
});
});
});
return list;
}
2020-11-05 19:13:43 +01:00
newPollFromForm(form: any) {
const newpoll = new Poll(
this.userService.getCurrentUser(),
this.uuidService.getUUID(),
form.controls.title.value
);
2020-11-11 12:14:01 +01:00
/**
* convert to API version 1 config poll
*/
const apiV1Poll = {
menuVisible: true,
expiracyDateDefaultInDays: newpoll.configuration.expiresDaysDelay,
deletionDateAfterLastModification: newpoll.configuration.expiracyAfterLastModificationInDays,
pollType: newpoll.configuration.isAboutDate ? 'dates' : 'classic', // classic or dates
title: newpoll.title,
description: newpoll.description,
myName: newpoll.owner.pseudo,
myComment: '',
isAdmin: true, // when we create a poll, we are admin on it
myVoteStack: {},
myTempVoteStack: 0,
myEmail: newpoll.owner.email,
myPolls: [], // list of retrieved polls from the backend api
/*
date specific poll, we have the choice to setup different hours (timeList) for all possible dates (dateList), or use the same hours for all dates
*/
allowSeveralHours: 'true',
// access
visibility: newpoll.configuration.areResultsPublic, // visible to one with the link:
voteChoices: newpoll.configuration.isMaybeAnswerAvailable ? 'yes, maybe, no' : 'yes', // possible answers to a vote choice: only "yes", "yes, maybe, no"
creationDate: new Date(),
expirationDate: '', // expiracy date
voteStackId: null, // id of the vote stack to update
pollId: null, // id of the current poll when created. data given by the backend api
pollSlug: null, // id of the current poll when created. data given by the backend api
currentPoll: null, // current poll selected with createPoll or getPoll of ConfigService
passwordAccess: newpoll.configuration.isProtectedByPassword,
password: newpoll.configuration.password,
customUrl: newpoll.slug, // custom slug in the url, must be unique
customUrlIsUnique: null, // given by the backend
urlSlugPublic: null,
urlPublic: null,
urlAdmin: null,
adminKey: '', // key to change config of the poll
owner_modifier_token: '', // key to change a vote stack
canModifyAnswers: newpoll.configuration.isAllowingtoChangeOwnAnswers, // bool for the frontend selector
whoModifiesAnswers: newpoll.configuration.whoCanChangeAnswers, // everybody, self, nobody (: just admin)
whoCanChangeAnswers: newpoll.configuration.whoCanChangeAnswers, // everybody, self, nobody (: just admin)
dateList: newpoll.dateChoices, // sets of days as strings, config to set identical time for days in a special days poll
timeList: newpoll.timeChoices, // ranges of time expressed as strings
answers: newpoll.choices,
// modals
displayConfirmVoteModalAdmin: false,
};
return apiV1Poll;
2020-11-05 19:13:43 +01:00
}
}