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

241 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { Answer } from '../enums/answer.enum';
import { Choice } from '../models/choice.model';
import { Poll } from '../models/poll.model';
import { Owner } from '../models/owner.model';
import { ApiService } from './api.service';
import { ToastService } from './toast.service';
import { UserService } from './user.service';
import { UuidService } from './uuid.service';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { StorageService } from './storage.service';
import { Title } from '@angular/platform-browser';
import { TimeSlices } from '../../../../mocks/old-stuff/config/defaultConfigs';
@Injectable({
providedIn: 'root',
})
export class PollService implements Resolve<Poll> {
_poll: BehaviorSubject<Poll | undefined> = new BehaviorSubject<Poll | undefined>(undefined);
public readonly poll: Observable<Poll | undefined> = this._poll.asObservable();
constructor(
private http: HttpClient,
private router: Router,
private apiService: ApiService,
private storageService: StorageService,
private userService: UserService,
private uuidService: UuidService,
private titleService: Title,
private toastService: ToastService
) {}
/**
* auto fetch a poll when route is looking for one in the administration pattern
* @param route
* @param state
*/
public async resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Poll> {
const segments: string[] = state.url.split('/');
const wantedcustom_url: string = segments.includes('poll') ? segments[segments.indexOf('poll') + 1] : '';
// FIXME should be handled by routing
if (!wantedcustom_url && state.url.includes('administration')) {
// creation of new poll
const poll = new Poll(this.userService.getCurrentUser(), this.uuidService.getUUID(), '');
this._poll.next(poll);
this.router.navigate(['poll/' + poll.custom_url + '/administration']);
}
if (
!this._poll.getValue() ||
!this._poll.getValue().custom_url ||
this._poll.getValue().custom_url !== wantedcustom_url
) {
await this.loadPollBycustom_url(wantedcustom_url);
}
if (this._poll.getValue()) {
return this._poll.getValue();
} else {
this.router.navigate(['page-not-found']);
return;
}
}
getAllAvailablePolls() {
const baseHref = environment.api.version.apiV1.baseHref;
console.log('getAllAvailablePolls baseHref', baseHref);
const headers = ApiService.makeHeaders();
console.log('getAllAvailablePolls headers', headers);
try {
this.http.get(`${baseHref}/poll`, headers).subscribe((res: Observable<any>) => {
console.log('getAllAvailablePolls res', res);
});
} catch (e) {
console.error('getAllAvailablePolls e', e);
}
}
public async loadPollBycustom_url(custom_url: string): Promise<void> {
console.log('custom_url', custom_url);
if (custom_url) {
const poll: Poll | undefined = await this.apiService.getPollByCustomUrl(custom_url);
console.log({ loadPollBycustom_urlResponse: poll });
if (poll) {
this.updateCurrentPoll(poll);
this.titleService.setTitle(`☑️ ${poll.title} - ${environment.appTitle}`);
} else {
this.toastService.display(`sondage ${custom_url} non trouvé`);
}
}
}
public async loadPollBycustom_urlWithPasswordHash(custom_url: string, hash: string): Promise<void> {
console.log('custom_url', custom_url);
if (custom_url) {
const poll: Poll | undefined = await this.apiService.getPollByCustomUrlWithHash(custom_url, hash);
console.log({ loadPollBycustom_urlResponse: poll });
this.updateCurrentPoll(poll);
}
}
/**
* update poll and parse its fields
* @param poll
*/
public updateCurrentPoll(poll: Poll): void {
if (poll.kind == 'date') {
poll.choices = this.parseDateChoices(poll.choices);
}
this.storageService.setChoicesForVoteStack(poll.choices);
this.toastService.display('sondage bien mis à jour', 'success');
console.log('poll', poll);
this._poll.next(poll);
}
/**
* make a uniq custom_url for the current poll creation
* @param config
*/
makecustom_url(config: Poll): string {
console.log('config', config);
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();
}
public async saveCurrentPoll(): Promise<Subscription> {
// .then((resp) => {
// console.log('resp', resp);
// if (pollUrl) {
// console.log('pollUrl', pollUrl);
// this.toastService.display('Le sondage a été enregistré.');
// // TODO: redirect to view
// } else {
// this.toastService.display('Le sondage na été correctement enregistré, veuillez ré-essayer.');
// }
// })
// .catch((err) => {
// console.error('err', err);
// });
return await this.apiService.createPoll(this._poll.getValue());
}
public saveParticipation(choice: Choice, user: Owner, response: Answer): void {
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);
this.toastService.display('Votre participation au sondage a été enregistrée.');
}
public async deleteAllAnswers(): Promise<void> {
await this.apiService.deletePollAnswers(this._poll.getValue().custom_url);
this.toastService.display('Les participations des votants à ce sondage ont été supprimées.');
}
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é.');
}
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.');
}
/**
* @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);
for (const fieldOfForm of formFields) {
if (pollKeys.indexOf(fieldOfForm) !== -1) {
newpoll[fieldOfForm] = form.value[fieldOfForm];
}
}
newpoll.dateChoices = this.storageService.dateList;
newpoll.timeSlices = this.storageService.timeSlices;
console.log('newpoll', newpoll);
return newpoll;
}
public parseDateChoices(choices: Choice[]) {
const SEPARATOR_DATE_TIME_SLICE = ' >>> ';
const parsedChoices = [];
for (const c of choices) {
const time_list = [];
const choice = { name: c.name };
if (c.name.includes(SEPARATOR_DATE_TIME_SLICE)) {
const date_string = '';
const time_slice = '';
choice.name = time_slice;
}
parsedChoices.push({
date_string: choice,
choices: c,
});
}
console.log('parsedChoices', parsedChoices);
return [];
}
}