mirror of
https://framagit.org/framasoft/framadate/funky-framadate-front.git
synced 2023-08-25 13:53:14 +02:00
259 lines
8.4 KiB
TypeScript
259 lines
8.4 KiB
TypeScript
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 { DateUtilitiesService } from './date.utilities.service';
|
|
|
|
@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 dateUtils: DateUtilitiesService,
|
|
private titleService: Title,
|
|
private toastService: ToastService
|
|
) {
|
|
this._poll.next(new Poll(null, 'titre', 'custom-title'));
|
|
}
|
|
|
|
/**
|
|
* 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 {
|
|
console.log('update poll with: ', poll);
|
|
|
|
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 poll
|
|
*/
|
|
makecustom_url(poll: Poll): string {
|
|
console.log('config', poll);
|
|
let str = '';
|
|
const creation_date = new Date(poll.creation_date);
|
|
str =
|
|
creation_date.getFullYear() +
|
|
'_' +
|
|
(creation_date.getMonth() + 1) +
|
|
'_' +
|
|
creation_date.getDate() +
|
|
'_' +
|
|
poll.owner.pseudo +
|
|
'_' +
|
|
poll.title;
|
|
|
|
return this.convertTextToSlug(str) + '-' + this.uuidService.getUUID();
|
|
}
|
|
|
|
public convertTextToSlug(str: string) {
|
|
str = str.trim();
|
|
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;
|
|
}
|
|
|
|
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);
|
|
|
|
console.log('pollKeys, formFields', pollKeys, formFields);
|
|
newpoll.allowed_answers = ['yes'];
|
|
|
|
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.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
|
|
newpoll.choices = Object.assign([], this.storageService.choices);
|
|
newpoll.dateChoices = Object.assign([], this.storageService.dateChoices);
|
|
newpoll.timeSlices = Object.assign([], this.storageService.timeSlices);
|
|
|
|
console.log('this.storageService.timeSlices', this.storageService.timeSlices, newpoll.timeSlices);
|
|
|
|
return newpoll;
|
|
}
|
|
|
|
public getAdministrationUrl(): string {
|
|
let url = '';
|
|
if (this._poll && this._poll.getValue) {
|
|
const polltemp = this._poll.getValue();
|
|
if (polltemp) {
|
|
url = `${environment.frontDomain}#/poll/admin/${polltemp.admin_key}`;
|
|
}
|
|
}
|
|
return url;
|
|
}
|
|
|
|
public getParticipationUrl(): string {
|
|
let url = '';
|
|
if (this._poll && this._poll.getValue) {
|
|
const polltemp = this._poll.getValue();
|
|
if (polltemp) {
|
|
url = `${environment.frontDomain}#/poll/${polltemp.custom_url}/consultation`;
|
|
}
|
|
}
|
|
// TODO handle pass access
|
|
return url;
|
|
}
|
|
}
|