forked from tykayn/funky-framadate-front
Merge branch 'several-steps-creation' into 'master'
5 steps to create a poll See merge request framasoft/framadate/funky-framadate-front!49
This commit is contained in:
commit
c1ec249e02
@ -40,7 +40,7 @@ build:
|
|||||||
stage: build
|
stage: build
|
||||||
script:
|
script:
|
||||||
- yarn install --pure-lockfile
|
- yarn install --pure-lockfile
|
||||||
- npx ng build --prod
|
- yarn run build:prod
|
||||||
cache:
|
cache:
|
||||||
policy: pull
|
policy: pull
|
||||||
|
|
||||||
|
@ -45,10 +45,12 @@
|
|||||||
"@fullcalendar/core": "^4.4.0",
|
"@fullcalendar/core": "^4.4.0",
|
||||||
"@ngx-translate/core": "^12.1.2",
|
"@ngx-translate/core": "^12.1.2",
|
||||||
"@ngx-translate/http-loader": "^5.0.0",
|
"@ngx-translate/http-loader": "^5.0.0",
|
||||||
|
"angular-date-value-accessor": "^1.0.2",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"bulma": "^0.9.0",
|
"bulma": "^0.9.0",
|
||||||
"bulma-switch": "^2.0.0",
|
"bulma-switch": "^2.0.0",
|
||||||
"chart.js": "^2.9.3",
|
"chart.js": "^2.9.3",
|
||||||
|
"crypto": "^1.0.1",
|
||||||
"crypto-js": "^4.0.0",
|
"crypto-js": "^4.0.0",
|
||||||
"fork-awesome": "^1.1.7",
|
"fork-awesome": "^1.1.7",
|
||||||
"ng-keyboard-shortcuts": "^10.1.17",
|
"ng-keyboard-shortcuts": "^10.1.17",
|
||||||
@ -57,6 +59,7 @@
|
|||||||
"ngx-markdown": "^9.0.0",
|
"ngx-markdown": "^9.0.0",
|
||||||
"ngx-webstorage": "^5.0.0",
|
"ngx-webstorage": "^5.0.0",
|
||||||
"node-forge": "^0.10.0",
|
"node-forge": "^0.10.0",
|
||||||
|
"primeng": "^11.0.0",
|
||||||
"quill": "^1.3.7",
|
"quill": "^1.3.7",
|
||||||
"rxjs": "^6.5.5",
|
"rxjs": "^6.5.5",
|
||||||
"rxjs-compat": "^6.5.5",
|
"rxjs-compat": "^6.5.5",
|
||||||
@ -75,9 +78,9 @@
|
|||||||
"@babel/preset-env": "^7.9.5",
|
"@babel/preset-env": "^7.9.5",
|
||||||
"@babel/preset-typescript": "^7.9.0",
|
"@babel/preset-typescript": "^7.9.0",
|
||||||
"@compodoc/compodoc": "^1.1.11",
|
"@compodoc/compodoc": "^1.1.11",
|
||||||
|
"@types/crypto-js": "^4.0.0",
|
||||||
"@types/jest": "^26.0.0",
|
"@types/jest": "^26.0.0",
|
||||||
"@types/node": "^14.0.1",
|
"@types/node": "^14.0.1",
|
||||||
"@types/crypto-js": "^4.0.0",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^3.0.0",
|
"@typescript-eslint/eslint-plugin": "^3.0.0",
|
||||||
"@typescript-eslint/parser": "^3.0.0",
|
"@typescript-eslint/parser": "^3.0.0",
|
||||||
"babel-jest": "^26.0.0",
|
"babel-jest": "^26.0.0",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core';
|
import { AfterViewInit, Component, Inject, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
@ -11,6 +11,12 @@ import { slideInAnimation } from './shared/animations/main';
|
|||||||
import { FramaKeyboardShortcuts } from './shared/shortcuts/main';
|
import { FramaKeyboardShortcuts } from './shared/shortcuts/main';
|
||||||
import { ShortcutEventOutput, ShortcutInput } from 'ng-keyboard-shortcuts';
|
import { ShortcutEventOutput, ShortcutInput } from 'ng-keyboard-shortcuts';
|
||||||
import { PollService } from './core/services/poll.service';
|
import { PollService } from './core/services/poll.service';
|
||||||
|
import { Poll } from './core/models/poll.model';
|
||||||
|
import { PollDTO } from './core/models/poll.DTO.model';
|
||||||
|
import { PrimeNGConfig } from 'primeng/api';
|
||||||
|
import { Language } from './core/enums/language.enum';
|
||||||
|
import { ApiService } from './core/services/api.service';
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
@ -35,13 +41,15 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
private titleService: Title,
|
private titleService: Title,
|
||||||
private themeService: ThemeService,
|
private themeService: ThemeService,
|
||||||
private pollService: PollService,
|
private pollService: PollService,
|
||||||
|
private apiService: ApiService,
|
||||||
|
private config: PrimeNGConfig,
|
||||||
|
@Inject(DOCUMENT) private document: any,
|
||||||
private languageService: LanguageService // private mockingService: MockingService
|
private languageService: LanguageService // private mockingService: MockingService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
printpath(parent: string, config: Route[]) {
|
printpath(parent: string, config: Route[]) {
|
||||||
for (let i = 0; i < config.length; i++) {
|
for (let i = 0; i < config.length; i++) {
|
||||||
const route = config[i];
|
const route = config[i];
|
||||||
console.info(parent + '/' + route.path);
|
|
||||||
if (route.children) {
|
if (route.children) {
|
||||||
const currentPath = route.path ? parent + '/' + route.path : parent;
|
const currentPath = route.path ? parent + '/' + route.path : parent;
|
||||||
this.printpath(currentPath, route.children);
|
this.printpath(currentPath, route.children);
|
||||||
@ -50,21 +58,29 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.languageService.getPrimeNgStrings().subscribe((resp) => {
|
||||||
|
this.config.setTranslation(resp);
|
||||||
|
});
|
||||||
|
|
||||||
this.printpath('', this.router.config);
|
this.printpath('', this.router.config);
|
||||||
this.router.events.subscribe((evt) => {
|
this.router.events.subscribe((evt) => {
|
||||||
console.log('route changed', evt);
|
|
||||||
|
|
||||||
if (!(evt instanceof NavigationEnd)) {
|
if (!(evt instanceof NavigationEnd)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window.scrollTo(0, 0);
|
|
||||||
|
let mainelem = this.document.querySelector('#big_container main');
|
||||||
|
console.log('mainelem', mainelem);
|
||||||
|
window.scrollTo(0, mainelem.offsetTop);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!environment.production) {
|
if (!environment.production) {
|
||||||
this.appTitle += ' [DEV]';
|
this.appTitle += ' [DEV]';
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadedPoll = this.pollService._poll.getValue();
|
let loadedPoll;
|
||||||
|
if (this.pollService.poll) {
|
||||||
|
loadedPoll = this.pollService.poll;
|
||||||
|
}
|
||||||
|
|
||||||
this.titleService.setTitle(this.appTitle + ' - ' + loadedPoll.title);
|
this.titleService.setTitle(this.appTitle + ' - ' + loadedPoll.title);
|
||||||
this.languageService.configureAndInitTranslations();
|
this.languageService.configureAndInitTranslations();
|
||||||
@ -83,9 +99,12 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
this.themeClass = 'theme-light-watermelon';
|
this.themeClass = 'theme-light-watermelon';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// debug cors
|
||||||
|
this.apiService.getAllAvailablePolls();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
console.log('this.shortcuts', this.shortcuts);
|
|
||||||
this.shortcuts.push(
|
this.shortcuts.push(
|
||||||
{
|
{
|
||||||
key: '?',
|
key: '?',
|
||||||
@ -108,7 +127,6 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log('this.shortcuts', this.shortcuts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
@ -117,10 +135,6 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleSidebar(status: boolean): void {
|
|
||||||
this.isSidebarOpened = status === true;
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareRoute(outlet: RouterOutlet) {
|
prepareRoute(outlet: RouterOutlet) {
|
||||||
return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;
|
return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;
|
||||||
}
|
}
|
||||||
|
@ -26,5 +26,33 @@
|
|||||||
canal Matrix
|
canal Matrix
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
<div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<h3 class="title is-3">Framasoft</h3>
|
||||||
|
L’association,Notre charte,Contacter Framasoft,Statistiques,État des services
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<h3 class="title is-3">Communauté</h3>
|
||||||
|
Framacolibri,Participer,Bénévolat valorisé,Partenaires,Charte de modération
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<h3 class="title is-3">Framadate</h3>
|
||||||
|
Entraide,Guides et astuces,Mentions légales,CGU,Crédits
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<form action="#">
|
||||||
|
<label for="subscribe_newsletter">
|
||||||
|
<i class="fa fa-enveloppe"></i>
|
||||||
|
Inscrivez-vous à la newsletter
|
||||||
|
</label>
|
||||||
|
<input type="text" class="input" id="subscribe_newsletter" />
|
||||||
|
<button class="button is-outlined is-primary" (click)="subscribeToNewsletter()">
|
||||||
|
S'inscrire
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -11,4 +11,8 @@ export class FooterComponent implements OnInit {
|
|||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
ngOnInit(): void {}
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
subscribeToNewsletter() {
|
||||||
|
alert('TODO');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,4 +123,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<a
|
||||||
|
class="has-text-black"
|
||||||
|
href="/#/administration/key/8Ubcg2YI99f69xz946cn4O64bQAebi11012P70trL5372qJ9JOem1Ks2fz7XD0b09p-8Ubcg2YI99f69xz946cn4O64bQAeb"
|
||||||
|
>
|
||||||
|
<i class="fa fa-hand-paper-o"></i> test admin link to edit poll
|
||||||
|
</a>
|
||||||
</header>
|
</header>
|
||||||
|
@ -1,5 +1,20 @@
|
|||||||
<section class="hero">
|
<section class="hero">
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
|
<div class="columns presentation">
|
||||||
|
<div class="column">
|
||||||
|
<h2 class="title is-2">
|
||||||
|
Organisez des évènements ou récoltez l’opinion de vos proches, simplement, librement.
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Grâce à Framadate planifiez, organisez et prenez des décisions rapidement, simplement et sans
|
||||||
|
inscription.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<img src="assets/img/icone_home.png" alt="calendrier icone framadate" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<section class="creation">
|
<section class="creation">
|
||||||
@ -22,7 +37,9 @@
|
|||||||
*ngIf="environment.showDemoWarning"
|
*ngIf="environment.showDemoWarning"
|
||||||
class="demo demo-warning well has-background-warning-light padded marged"
|
class="demo demo-warning well has-background-warning-light padded marged"
|
||||||
>
|
>
|
||||||
|
<h3 class="title is-3">
|
||||||
Ce que l'on peut faire sur cette démo:
|
Ce que l'on peut faire sur cette démo:
|
||||||
|
</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
☑️ Créer un nouveau sondage
|
☑️ Créer un nouveau sondage
|
||||||
@ -39,7 +56,9 @@
|
|||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h3 class="title is-3">
|
||||||
Ce qu'on ne peut pas encore faire:
|
Ce qu'on ne peut pas encore faire:
|
||||||
|
</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
🚴️ mettre à jour son vote à un sondage
|
🚴️ mettre à jour son vote à un sondage
|
||||||
@ -58,6 +77,8 @@
|
|||||||
<h1 class="title is-1 is-centered">
|
<h1 class="title is-1 is-centered">
|
||||||
{{ 'home.search_title' | translate }}
|
{{ 'home.search_title' | translate }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
<img src="assets/img/where-is-it.jpg" alt="batman veut savoir où sont ses sondages" />
|
||||||
<div class="poll-list">
|
<div class="poll-list">
|
||||||
<ul>
|
<ul>
|
||||||
<li *ngFor="let p of storageService.userPolls">
|
<li *ngFor="let p of storageService.userPolls">
|
||||||
@ -75,7 +96,7 @@
|
|||||||
<form (ngSubmit)="searchMyPolls()">
|
<form (ngSubmit)="searchMyPolls()">
|
||||||
<div class="search-others">
|
<div class="search-others">
|
||||||
<label for="search_email">
|
<label for="search_email">
|
||||||
Je cherche d'autres sondages, qui correspondent à mon mail :
|
{{ 'home.search_subtitle' | translate }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
@ -139,9 +160,11 @@
|
|||||||
<div class="column"></div>
|
<div class="column"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column"></div>
|
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<img src="assets/img/kind/classic.jpeg" alt="sondage date" />
|
<img src="assets/img/kind/date.jpeg" alt="sondage date" />
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<img src="assets/img/kind/classic.jpeg" alt="sondage classique" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
@import '../../../../styles/variables';
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
margin-left: -2em;
|
||||||
|
margin-right: -2em;
|
||||||
a .fa {
|
a .fa {
|
||||||
margin-right: 1ch;
|
margin-right: 1ch;
|
||||||
}
|
}
|
||||||
@ -9,4 +13,7 @@
|
|||||||
.poll-list {
|
.poll-list {
|
||||||
margin: 2em 0;
|
margin: 2em 0;
|
||||||
}
|
}
|
||||||
|
.presentation {
|
||||||
|
background: $secondary_color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { StorageService } from '../../services/storage.service';
|
|||||||
import { ApiService } from '../../services/api.service';
|
import { ApiService } from '../../services/api.service';
|
||||||
import { ToastService } from '../../services/toast.service';
|
import { ToastService } from '../../services/toast.service';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { Title } from '@angular/platform-browser';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
@ -18,8 +19,11 @@ export class HomeComponent {
|
|||||||
@Inject(DOCUMENT) private document: any,
|
@Inject(DOCUMENT) private document: any,
|
||||||
public storageService: StorageService,
|
public storageService: StorageService,
|
||||||
public toastService: ToastService,
|
public toastService: ToastService,
|
||||||
|
public titleService: Title,
|
||||||
private api: ApiService
|
private api: ApiService
|
||||||
) {}
|
) {
|
||||||
|
this.titleService.setTitle(environment.appTitle + ' - Accueil ');
|
||||||
|
}
|
||||||
|
|
||||||
searchMyPolls() {
|
searchMyPolls() {
|
||||||
const email = this.storageService.vote_stack.owner.email;
|
const email = this.storageService.vote_stack.owner.email;
|
||||||
|
@ -6,8 +6,8 @@ export class Owner {
|
|||||||
public pseudo: string = 'pseudo',
|
public pseudo: string = 'pseudo',
|
||||||
public email: string = '_nonexistent_contact@cipherbliss.com',
|
public email: string = '_nonexistent_contact@cipherbliss.com',
|
||||||
public polls: Poll[] = [],
|
public polls: Poll[] = [],
|
||||||
public role?: UserRole,
|
public role: UserRole = UserRole.ADMIN,
|
||||||
public modifier_token?: string,
|
public modifier_token: string = '',
|
||||||
public created_at?: string
|
public created_at: string = new Date().toISOString()
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
46
src/app/core/models/poll.DTO.model.ts
Normal file
46
src/app/core/models/poll.DTO.model.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Choice, ChoiceGroup } from './choice.model';
|
||||||
|
import { DateChoice, TimeSlices } from './dateChoice.model';
|
||||||
|
|
||||||
|
export class PollDTO {
|
||||||
|
menuVisible = true;
|
||||||
|
expiracyDateDefaultInDays;
|
||||||
|
deletionDateAfterLastModification;
|
||||||
|
pollType: string = 'date'; // classic or dates
|
||||||
|
title;
|
||||||
|
description;
|
||||||
|
myName;
|
||||||
|
myComment = '';
|
||||||
|
isAdmin; // when we create a poll; we are admin on it
|
||||||
|
myVoteStack;
|
||||||
|
myTempVoteStack;
|
||||||
|
myEmail;
|
||||||
|
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"
|
||||||
|
created_at;
|
||||||
|
expirationDate; // expiracy date
|
||||||
|
voteStackId; // id of the vote stack to update
|
||||||
|
pollId; // id of the current poll when created. data given by the backend api
|
||||||
|
pollSlug; // id of the current poll when created. data given by the backend api
|
||||||
|
currentPoll; // current poll selected with createPoll or getPoll of ConfigService
|
||||||
|
passwordAccess;
|
||||||
|
password;
|
||||||
|
customUrl; // custom slug in the url; must be unique
|
||||||
|
customUrlIsUnique; // given by the backend
|
||||||
|
urlSlugPublic;
|
||||||
|
urlPublic;
|
||||||
|
urlAdmin;
|
||||||
|
adminKey; // key to change config of the poll
|
||||||
|
owner_modifier_token; // key to change a vote stack
|
||||||
|
canModifyAnswers; // bool for the frontend selector
|
||||||
|
whoModifiesAnswers; // everybody; self; nobody (: just admin)
|
||||||
|
whoCanChangeAnswers; // everybody; self; nobody (: just admin)
|
||||||
|
dateList; // sets of days as strings; config to set identical time for days in a special days poll
|
||||||
|
timeList; // ranges of time expressed as strings
|
||||||
|
|
||||||
|
answers;
|
||||||
|
displayConfirmVoteModalAdmin;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
}
|
@ -16,6 +16,8 @@ const apiBaseHref = environment.api.version[apiVersion].baseHref;
|
|||||||
|
|
||||||
const apiEndpoints = environment.api.endpoints;
|
const apiEndpoints = environment.api.endpoints;
|
||||||
|
|
||||||
|
class PollDTO {}
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
@ -36,16 +38,17 @@ export class ApiService {
|
|||||||
|
|
||||||
this.axiosInstance = axios.create({ baseURL: apiBaseHref });
|
this.axiosInstance = axios.create({ baseURL: apiBaseHref });
|
||||||
this.axiosInstance.defaults.timeout = 2500;
|
this.axiosInstance.defaults.timeout = 2500;
|
||||||
this.axiosInstance.defaults.headers.post['Content-Type'] = 'application/json';
|
// this.axiosInstance.defaults.headers.post['Content-Type'] = 'application/json';
|
||||||
this.axiosInstance.defaults.headers.post['Accept'] = 'application/json';
|
// this.axiosInstance.defaults.headers.post['Accept'] = 'application/json';
|
||||||
this.axiosInstance.defaults.headers.post['Charset'] = 'UTF-8';
|
// this.axiosInstance.defaults.headers.post['Charset'] = 'UTF-8';
|
||||||
// this.axiosInstance.defaults.headers.post['Accept-Charset'] = 'UTF-8';
|
// this.axiosInstance.defaults.headers.post['Accept-Charset'] = 'UTF-8';
|
||||||
this.axiosInstance.defaults.headers.post['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS';
|
// this.axiosInstance.defaults.headers.post['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS';
|
||||||
this.axiosInstance.defaults.headers.post['Referrer-Policy'] = 'origin-when-cross-origin';
|
// this.axiosInstance.defaults.headers.post['Referrer-Policy'] = 'origin-when-cross-origin';
|
||||||
this.axiosInstance.defaults.headers.post['Access-Control-Allow-Origin'] = '*';
|
// this.axiosInstance.defaults.headers.post['Access-Control-Allow-Origin'] = '*';
|
||||||
this.axiosInstance.defaults.headers.post['Allow-Origin'] = '*';
|
// this.axiosInstance.defaults.headers.post['Control-Allow-Origin'] = '*';
|
||||||
this.axiosInstance.defaults.headers.post['Access-Control-Allow-Headers'] =
|
// this.axiosInstance.defaults.headers.post['Allow-Origin'] = '*';
|
||||||
'Origin, X-Requested-With, Content-Type, Accept';
|
// this.axiosInstance.defaults.headers.post['Access-Control-Allow-Headers'] =
|
||||||
|
// 'Origin, X-Requested-With, Content-Type, Accept';
|
||||||
|
|
||||||
console.log('this.axiosInstance.defaults.headers', this.axiosInstance.defaults.headers);
|
console.log('this.axiosInstance.defaults.headers', this.axiosInstance.defaults.headers);
|
||||||
}
|
}
|
||||||
@ -66,25 +69,29 @@ export class ApiService {
|
|||||||
// Accept: 'application/json',
|
// Accept: 'application/json',
|
||||||
'Access-Control-Allow-Origin': '*',
|
'Access-Control-Allow-Origin': '*',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
mode: 'no-cors',
|
// mode: 'no-cors',
|
||||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||||
'Access-Control-Allow-Headers': 'Accept,Accept-Language,Content-Language,Content-Type',
|
'Access-Control-Allow-Headers': 'Accept,Accept-Language,Content-Language,Content-Type',
|
||||||
// 'Access-Control-Allow-Origin': '*',
|
|
||||||
};
|
};
|
||||||
|
const headersAxios = {
|
||||||
return {
|
|
||||||
headers: headerDict,
|
headers: headerDict,
|
||||||
body: bodyContent,
|
body: bodyContent,
|
||||||
};
|
};
|
||||||
|
console.log('headersAxios', headersAxios);
|
||||||
|
return headersAxios;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createPoll(poll: Poll): Promise<Subscription> {
|
/**
|
||||||
|
*
|
||||||
|
* @param poll
|
||||||
|
*/
|
||||||
|
public async createPoll(poll: PollDTO): Promise<Subscription> {
|
||||||
// this.loaderService.setStatus(true);
|
// this.loaderService.setStatus(true);
|
||||||
console.log('createPoll config', poll);
|
console.log('apiservice createPoll config', poll);
|
||||||
return this.axiosInstance.post(
|
return this.axiosInstance.post(
|
||||||
`${this.baseHref}${currentApiRoutes['api_new_poll']}`,
|
`${this.baseHref}${currentApiRoutes['api_new_poll']}`,
|
||||||
poll,
|
poll
|
||||||
ApiService.makeHeaders()
|
// ApiService.makeHeaders()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,10 +141,14 @@ export class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////
|
/**
|
||||||
|
* get all polls published by the API
|
||||||
|
*/
|
||||||
public async getAllAvailablePolls(): Promise<Poll[]> {
|
public async getAllAvailablePolls(): Promise<Poll[]> {
|
||||||
// TODO: used for facilities in DEV, should be removed in production
|
// TODO: used for facilities in DEV, should be removed in production
|
||||||
try {
|
try {
|
||||||
|
this.axiosInstance.options(this.pollsEndpoint);
|
||||||
|
|
||||||
const response: AxiosResponse<Poll[]> = await this.axiosInstance.get<Poll[]>(`${this.pollsEndpoint}`);
|
const response: AxiosResponse<Poll[]> = await this.axiosInstance.get<Poll[]>(`${this.pollsEndpoint}`);
|
||||||
return response?.data;
|
return response?.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -145,10 +156,32 @@ export class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getPollByCustomUrl(slug: string): Promise<Poll | undefined> {
|
/**
|
||||||
|
* get one poll by its admin key
|
||||||
|
* @param admin_key
|
||||||
|
*/
|
||||||
|
public async getPollByAdminKey(admin_key: string): Promise<any | undefined> {
|
||||||
try {
|
try {
|
||||||
console.log('fetch API : asking for poll with custom_url=' + slug);
|
console.log('fetch API : asking for poll with admin_key=' + admin_key);
|
||||||
const response: AxiosResponse<Poll> = await this.axiosInstance.get<Poll>(`${this.pollsEndpoint}/${slug}`);
|
const response: AxiosResponse<Poll> = await this.axiosInstance.get<any>(
|
||||||
|
`${this.pollsEndpoint}/admin/${admin_key}`
|
||||||
|
);
|
||||||
|
return response && response.data && !Array.isArray(response.data) ? response.data : undefined;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response?.status === 404) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
ApiService.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getPollByCustomUrl(custom_url: string): Promise<Poll | undefined> {
|
||||||
|
try {
|
||||||
|
console.log('fetch API : asking for poll with custom_url=' + custom_url);
|
||||||
|
const response: AxiosResponse<Poll> = await this.axiosInstance.get<Poll>(
|
||||||
|
`${this.pollsEndpoint}/${custom_url}`
|
||||||
|
);
|
||||||
|
|
||||||
return response && response.data && !Array.isArray(response.data) ? response.data : undefined;
|
return response && response.data && !Array.isArray(response.data) ? response.data : undefined;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -160,12 +193,12 @@ export class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getPollByCustomUrlWithHash(slug: string, hash: string): Promise<Poll | undefined> {
|
public async getPollByCustomUrlWithHash(custom_url: string, hash: string): Promise<Poll | undefined> {
|
||||||
try {
|
try {
|
||||||
const response: AxiosResponse<Poll> = await this.axiosInstance.get<Poll>(
|
const response: AxiosResponse<Poll> = await this.axiosInstance.get<Poll>(
|
||||||
`${this.pollsEndpoint}/${slug}/pass/${hash}`
|
`${this.pollsEndpoint}/${custom_url}/pass/${hash}`
|
||||||
);
|
);
|
||||||
console.log('fetch API : asking for poll with custom_url=' + slug, { response });
|
console.log('fetch API : asking for poll with custom_url=' + custom_url, { response });
|
||||||
|
|
||||||
return response && response.data && !Array.isArray(response.data) ? response.data : undefined;
|
return response && response.data && !Array.isArray(response.data) ? response.data : undefined;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -179,11 +212,11 @@ export class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getSlug(slug: string): Promise<boolean> {
|
public async getSlug(custom_url: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
// TODO: scenario should be : if we can get this custom_url, it exists. if not, it doesn't. It's just a GET.
|
// TODO: scenario should be : if we can get this custom_url, it exists. if not, it doesn't. It's just a GET.
|
||||||
const response: AxiosResponse = await this.axiosInstance.get(
|
const response: AxiosResponse = await this.axiosInstance.get(
|
||||||
`${this.pollsEndpoint}${this.slugsEndpoint}/${slug}`
|
`${this.pollsEndpoint}${this.slugsEndpoint}/${custom_url}`
|
||||||
);
|
);
|
||||||
if (response?.status !== 404) {
|
if (response?.status !== 404) {
|
||||||
return false;
|
return false;
|
||||||
@ -199,7 +232,7 @@ export class ApiService {
|
|||||||
|
|
||||||
////////////
|
////////////
|
||||||
// UPDATE //
|
// UPDATE //
|
||||||
|
////////////
|
||||||
public async sendUpdateVoteStack(vote_stack: Stack) {
|
public async sendUpdateVoteStack(vote_stack: Stack) {
|
||||||
try {
|
try {
|
||||||
return await this.axiosInstance.patch(
|
return await this.axiosInstance.patch(
|
||||||
|
@ -100,8 +100,6 @@ export class DateUtilitiesService {
|
|||||||
const ladate2 = this.addDaysToDate(1, today);
|
const ladate2 = this.addDaysToDate(1, today);
|
||||||
const ladate3 = this.addDaysToDate(2, today);
|
const ladate3 = this.addDaysToDate(2, today);
|
||||||
const ladate4 = this.addDaysToDate(3, today);
|
const ladate4 = this.addDaysToDate(3, today);
|
||||||
const ladate5 = this.addDaysToDate(4, today);
|
|
||||||
const ladate6 = this.addDaysToDate(5, today);
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -124,16 +122,6 @@ export class DateUtilitiesService {
|
|||||||
timeSlices: Object.create(defaultTimeOfDay),
|
timeSlices: Object.create(defaultTimeOfDay),
|
||||||
date_object: ladate4,
|
date_object: ladate4,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
literal: this.formateDateToInputStringNg(ladate5),
|
|
||||||
timeSlices: Object.create(defaultTimeOfDay),
|
|
||||||
date_object: ladate5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
literal: this.formateDateToInputStringNg(ladate6),
|
|
||||||
timeSlices: Object.create(defaultTimeOfDay),
|
|
||||||
date_object: ladate6,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,10 @@ export class LanguageService {
|
|||||||
this.setLanguageOnInit();
|
this.setLanguageOnInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getPrimeNgStrings() {
|
||||||
|
return this.translate.get('calendar_widget');
|
||||||
|
}
|
||||||
|
|
||||||
private setLanguageOnInit(): void {
|
private setLanguageOnInit(): void {
|
||||||
// set language from storage
|
// set language from storage
|
||||||
if (!this.translate.currentLang) {
|
if (!this.translate.currentLang) {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Inject, Injectable } from '@angular/core';
|
||||||
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
|
import { ActivatedRoute, ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { Answer } from '../enums/answer.enum';
|
import { Answer } from '../enums/answer.enum';
|
||||||
import { Choice } from '../models/choice.model';
|
import { Choice } from '../models/choice.model';
|
||||||
import { Poll } from '../models/poll.model';
|
import { Poll } from '../models/poll.model';
|
||||||
import { Owner } from '../models/owner.model';
|
|
||||||
import { ApiService } from './api.service';
|
import { ApiService } from './api.service';
|
||||||
import { ToastService } from './toast.service';
|
import { ToastService } from './toast.service';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
@ -14,7 +13,12 @@ import { HttpClient } from '@angular/common/http';
|
|||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
|
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { DateChoice, TimeSlices } from '../models/dateChoice.model';
|
||||||
import { DateUtilitiesService } from './date.utilities.service';
|
import { DateUtilitiesService } from './date.utilities.service';
|
||||||
|
import { Owner } from '../models/owner.model';
|
||||||
import { Stack } from '../models/stack.model';
|
import { Stack } from '../models/stack.model';
|
||||||
import { Vote } from '../models/vote.model';
|
import { Vote } from '../models/vote.model';
|
||||||
|
|
||||||
@ -22,9 +26,29 @@ import { Vote } from '../models/vote.model';
|
|||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class PollService implements Resolve<Poll> {
|
export class PollService implements Resolve<Poll> {
|
||||||
_poll: BehaviorSubject<Poll | undefined> = new BehaviorSubject<Poll | undefined>(undefined);
|
public _poll: BehaviorSubject<Poll | undefined> = new BehaviorSubject<Poll | undefined>(undefined);
|
||||||
public readonly poll: Observable<Poll | undefined> = this._poll.asObservable();
|
public readonly poll: Observable<Poll | undefined> = this._poll.asObservable();
|
||||||
|
public form: FormGroup;
|
||||||
|
public startDateInterval: string;
|
||||||
|
public endDateInterval: string;
|
||||||
|
public intervalDays: number = 1;
|
||||||
|
public intervalDaysDefault = 7;
|
||||||
|
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
|
||||||
|
public previousRouteName: string = '/administration';
|
||||||
|
public nextRouteName: string = '/administration/step/2';
|
||||||
|
public step_current: number = 1;
|
||||||
|
public step_max: number = 5;
|
||||||
|
public round: Function;
|
||||||
public pass_hash: string;
|
public pass_hash: string;
|
||||||
|
public admin_key: string;
|
||||||
|
public urlPrefix: string = window.location.origin;
|
||||||
|
public advancedDisplayEnabled = false;
|
||||||
|
public showDateInterval = false;
|
||||||
|
public allowSeveralHours = false;
|
||||||
|
public richTextMode = false;
|
||||||
|
public calendar: Date[] = [new Date()];
|
||||||
|
public disabled_dates: Date[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
@ -33,15 +57,132 @@ export class PollService implements Resolve<Poll> {
|
|||||||
private storageService: StorageService,
|
private storageService: StorageService,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
private uuidService: UuidService,
|
private uuidService: UuidService,
|
||||||
private dateUtils: DateUtilitiesService,
|
private toastService: ToastService,
|
||||||
private titleService: Title,
|
private titleService: Title,
|
||||||
private toastService: ToastService
|
public DateUtilitiesService: DateUtilitiesService,
|
||||||
|
public route: ActivatedRoute,
|
||||||
|
@Inject(DOCUMENT) private document: any,
|
||||||
|
private fb: FormBuilder
|
||||||
) {
|
) {
|
||||||
this._poll.next(new Poll(null, 'titre', 'custom-title'));
|
this.createFormGroup();
|
||||||
|
|
||||||
|
// fill in the next 3 days of the calendar date picker
|
||||||
|
this.calendar = [
|
||||||
|
this.DateUtilitiesService.addDaysToDate(1, new Date()),
|
||||||
|
this.DateUtilitiesService.addDaysToDate(2, new Date()),
|
||||||
|
this.DateUtilitiesService.addDaysToDate(3, new Date()),
|
||||||
|
];
|
||||||
|
// disable days before today
|
||||||
|
for (let i = 1; i < 31; i++) {
|
||||||
|
this.disabled_dates.push(this.DateUtilitiesService.addDaysToDate(-i, new Date()));
|
||||||
|
}
|
||||||
|
if (environment.autofill_creation) {
|
||||||
|
this.setDemoValues();
|
||||||
|
this.toastService.display('auto fill de création fait');
|
||||||
|
}
|
||||||
|
if (environment.autoSendNewPoll) {
|
||||||
|
this.createPoll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add example values to the form for demo env
|
||||||
|
*/
|
||||||
|
setDemoValues(): void {
|
||||||
|
this.form.patchValue({
|
||||||
|
title: 'Mon titre de sondage du ' + this.DateUtilitiesService.formateDateToInputStringNg(new Date()),
|
||||||
|
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,
|
||||||
|
expiresDaysDelay: environment.expiresDaysDelay,
|
||||||
|
});
|
||||||
|
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 minlengthValidation = environment.production ? 12 : 0;
|
||||||
|
let form = this.fb.group({
|
||||||
|
title: ['mon titre de sondage', [Validators.required, Validators.minLength(minlengthValidation)]],
|
||||||
|
creatorPseudo: ['', [Validators.required]],
|
||||||
|
created_at: [new Date(), [Validators.required]],
|
||||||
|
creatorEmail: ['', [Validators.required]],
|
||||||
|
custom_url: [this.uuidService.getUUID(), [Validators.required]],
|
||||||
|
description: ['', [Validators.required]],
|
||||||
|
password: ['', []],
|
||||||
|
choices: new FormArray([]),
|
||||||
|
whoModifiesAnswers: ['', [Validators.required]],
|
||||||
|
whoCanChangeAnswers: ['', [Validators.required]],
|
||||||
|
isAboutDate: [true, [Validators.required]],
|
||||||
|
expiresDaysDelay: [environment.expiresDaysDelay, []],
|
||||||
|
maxCountOfAnswers: [300, []],
|
||||||
|
isZeroKnoledge: [false, [Validators.required]],
|
||||||
|
isProtectedByPassword: [false, [Validators.required]],
|
||||||
|
isOwnerNotifiedByEmailOnNewVote: [true, [Validators.required]],
|
||||||
|
isOwnerNotifiedByEmailOnNewComment: [true, [Validators.required]],
|
||||||
|
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: ['', []],
|
||||||
|
allowNewDateTime: [true, [Validators.required]],
|
||||||
|
});
|
||||||
|
this.form = form;
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set default configs to the form
|
||||||
|
*/
|
||||||
|
public patchFormDefaultValues() {
|
||||||
|
this.form.patchValue({
|
||||||
|
title: 'mon titre de sondage',
|
||||||
|
description: '',
|
||||||
|
custom_url: this.uuidService.getUUID(),
|
||||||
|
creatorPseudo: '',
|
||||||
|
creatorEmail: '',
|
||||||
|
isAboutDate: true,
|
||||||
|
whoModifiesAnswers: 'everybody',
|
||||||
|
whoCanChangeAnswers: 'everybody',
|
||||||
|
isProtectedByPassword: false,
|
||||||
|
richTextMode: false,
|
||||||
|
areResultsPublic: true,
|
||||||
|
expiresDaysDelay: environment.expiresDaysDelay,
|
||||||
|
maxCountOfAnswers: 300,
|
||||||
|
voterEmailList: '',
|
||||||
|
password: '',
|
||||||
|
});
|
||||||
|
this.setDefaultDatesForInterval();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get a new slug from form title and creation date
|
||||||
|
*/
|
||||||
|
public updateSlug(): void {
|
||||||
|
console.log('this.form.value', this.form.value);
|
||||||
|
this.form.patchValue({ custom_url: this.makeSlug(this.form) });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* auto fetch a poll when route is looking for one in the administration pattern
|
* auto fetch a poll when route is looking for one in the administration pattern
|
||||||
|
* DO NOT USE - needs refacto
|
||||||
* @param route
|
* @param route
|
||||||
* @param state
|
* @param state
|
||||||
*/
|
*/
|
||||||
@ -57,9 +198,9 @@ export class PollService implements Resolve<Poll> {
|
|||||||
) {
|
) {
|
||||||
if (this.pass_hash) {
|
if (this.pass_hash) {
|
||||||
this.storageService.vote_stack.pass_hash = this.pass_hash;
|
this.storageService.vote_stack.pass_hash = this.pass_hash;
|
||||||
await this.loadPollBycustom_urlWithPasswordHash(wantedcustom_url, this.pass_hash);
|
await this.loadPollByCustomUrlWithPasswordHash(wantedcustom_url, this.pass_hash);
|
||||||
} else {
|
} else {
|
||||||
await this.loadPollBycustom_url(wantedcustom_url);
|
await this.loadPollByCustomUrl(wantedcustom_url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const loadedPoll = this._poll.getValue();
|
const loadedPoll = this._poll.getValue();
|
||||||
@ -77,17 +218,19 @@ export class PollService implements Resolve<Poll> {
|
|||||||
*/
|
*/
|
||||||
getAllAvailablePolls(): void {
|
getAllAvailablePolls(): void {
|
||||||
const baseHref = environment.api.version.apiV1.baseHref;
|
const baseHref = environment.api.version.apiV1.baseHref;
|
||||||
|
console.log('getAllAvailablePolls baseHref', baseHref);
|
||||||
const headers = ApiService.makeHeaders();
|
const headers = ApiService.makeHeaders();
|
||||||
|
console.log('getAllAvailablePolls headers', headers);
|
||||||
try {
|
try {
|
||||||
this.http.get(`${baseHref}/poll`, headers).subscribe((res: Observable<any>) => {
|
this.http.get(`${baseHref}/poll`, headers).subscribe((res: Observable<any>) => {
|
||||||
console.log('getAllAvailablePolls res', res);
|
console.log('getAllAvailablePolls res', res);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('getAllAvailablePolls e', e);
|
console.log('getAllAvailablePolls e', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadPollBycustom_url(custom_url: string): Promise<void> {
|
public async loadPollByCustomUrl(custom_url: string): Promise<void> {
|
||||||
if (custom_url) {
|
if (custom_url) {
|
||||||
const poll: Poll | undefined = await this.apiService.getPollByCustomUrl(custom_url);
|
const poll: Poll | undefined = await this.apiService.getPollByCustomUrl(custom_url);
|
||||||
|
|
||||||
@ -103,7 +246,7 @@ export class PollService implements Resolve<Poll> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadPollBycustom_urlWithPasswordHash(custom_url: string, hash: string): Promise<void> {
|
public async loadPollByCustomUrlWithPasswordHash(custom_url: string, hash: string): Promise<void> {
|
||||||
if (custom_url) {
|
if (custom_url) {
|
||||||
const poll: Poll | undefined = await this.apiService.getPollByCustomUrlWithHash(custom_url, hash);
|
const poll: Poll | undefined = await this.apiService.getPollByCustomUrlWithHash(custom_url, hash);
|
||||||
|
|
||||||
@ -123,50 +266,243 @@ export class PollService implements Resolve<Poll> {
|
|||||||
* update poll and parse its fields
|
* update poll and parse its fields
|
||||||
* @param poll
|
* @param poll
|
||||||
*/
|
*/
|
||||||
public updateCurrentPoll(poll: Poll): void {
|
public updateCurrentPoll(poll: Poll): Poll {
|
||||||
console.log('this.storageService.vote_stack.id', this.storageService.vote_stack.id);
|
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) {
|
// if (!this.storageService.vote_stack.id || this.storageService.vote_stack.poll_custom_url !== poll.custom_url) {
|
||||||
console.log('set base choices', poll.choices);
|
// console.log('set base choices', poll.choices);
|
||||||
// set the choices only the first time the poll loads, or if we changed the poll
|
// // set the choices only the first time the poll loads, or if we changed the poll
|
||||||
console.log(
|
// console.log(
|
||||||
'this.storageService.vote_stack.poll_custom_url',
|
// 'this.storageService.vote_stack.poll_custom_url',
|
||||||
this.storageService.vote_stack.poll_custom_url
|
// this.storageService.vote_stack.poll_custom_url
|
||||||
);
|
// );
|
||||||
// this.storageService.setChoicesForVoteStack(poll.choices);
|
// this.storageService.setChoicesForVoteStack(poll.choices);
|
||||||
}
|
// }
|
||||||
|
|
||||||
this.toastService.display('sondage bien mis à jour', 'success');
|
|
||||||
this._poll.next(poll);
|
this._poll.next(poll);
|
||||||
|
console.log('next poll', poll);
|
||||||
|
|
||||||
|
this.storageService.setChoicesForVoteStack(poll.choices);
|
||||||
|
|
||||||
|
this.toastService.display(`sondage ${poll.title} bien mis à jour`, 'success');
|
||||||
|
return poll;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* make a uniq custom_url for the current poll creation
|
* add all the dates between the start and end dates in the interval section
|
||||||
* @param poll
|
|
||||||
*/
|
*/
|
||||||
makecustom_url(poll: Poll): string {
|
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;
|
||||||
|
|
||||||
|
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"');
|
||||||
|
} else {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* change time spans
|
||||||
|
*/
|
||||||
|
addTime() {
|
||||||
|
this.timeList.push({
|
||||||
|
literal: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert form data to DTO to create a new poll, and store the admin key
|
||||||
|
*/
|
||||||
|
public createPoll(): Promise<any> {
|
||||||
|
this.toastService.display('sending...');
|
||||||
|
const newpoll = this.newPollFromForm();
|
||||||
|
return this.apiService.createPoll(newpoll).then(
|
||||||
|
(resp: any) => {
|
||||||
|
console.log('poll created resp', resp);
|
||||||
|
this.admin_key = resp.data.poll.admin_key;
|
||||||
|
this.storageService.userPolls.push(resp.data.poll);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toastService.display('BOOM, the createPoll went wrong');
|
||||||
|
this.apiService.ousideHandleError(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default interval of dates proposed is from today to 7 days more
|
||||||
|
*/
|
||||||
|
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 {
|
||||||
|
this.initFormDefault(environment.autofill_creation);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteChoiceField(index: number): void {
|
||||||
|
if (this.choices.length !== 1) {
|
||||||
|
this.choices.removeAt(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initFormDefault(showDemoValues = true): void {
|
||||||
|
this.form = this.createFormGroup();
|
||||||
|
this.patchFormDefaultValues();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* make a uniq slug for the current poll creation
|
||||||
|
* @param form
|
||||||
|
*/
|
||||||
|
makeSlug(form: FormGroup): string {
|
||||||
let str = '';
|
let str = '';
|
||||||
const creation_date = new Date(poll.creation_date);
|
|
||||||
str =
|
str =
|
||||||
creation_date.getFullYear() +
|
form.value.created_at.getFullYear() +
|
||||||
'_' +
|
'_' +
|
||||||
(creation_date.getMonth() + 1) +
|
(form.value.created_at.getMonth() + 1) +
|
||||||
'_' +
|
'_' +
|
||||||
creation_date.getDate() +
|
form.value.created_at.getDate() +
|
||||||
'_' +
|
'_' +
|
||||||
poll.owner.pseudo +
|
form.value.creatorPseudo +
|
||||||
'_' +
|
'_' +
|
||||||
poll.title;
|
form.value.title;
|
||||||
|
|
||||||
return this.convertTextToSlug(str) + '-' + this.uuidService.getUUID();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* convert a text to a slug
|
|
||||||
* @param str
|
|
||||||
*/
|
|
||||||
public convertTextToSlug(str: string): string {
|
|
||||||
str = str.trim();
|
|
||||||
str = str.replace(/^\s+|\s+$/g, ''); // trim
|
str = str.replace(/^\s+|\s+$/g, ''); // trim
|
||||||
str = str.toLowerCase();
|
str = str.toLowerCase();
|
||||||
|
|
||||||
@ -181,10 +517,25 @@ export class PollService implements Resolve<Poll> {
|
|||||||
.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
|
.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
|
||||||
.replace(/\s+/g, '-') // collapse whitespace and replace by -
|
.replace(/\s+/g, '-') // collapse whitespace and replace by -
|
||||||
.replace(/-+/g, '-'); // collapse dashes
|
.replace(/-+/g, '-'); // collapse dashes
|
||||||
return str;
|
|
||||||
|
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 n’a été correctement enregistré, veuillez ré-essayer.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public saveParticipation(choice: Choice, user: Owner, response: Answer): void {
|
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.');
|
this.toastService.display('Votre participation au sondage a été enregistrée.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,72 +554,85 @@ export class PollService implements Resolve<Poll> {
|
|||||||
this.toastService.display('Les commentaires de ce sondage ont été supprimés.');
|
this.toastService.display('Les commentaires de ce sondage ont été supprimés.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public buildAnswersByChoiceLabelByPseudo(poll: Poll): Map<string, Map<string, Answer>> {
|
||||||
* @description convert to API version 1 data transition object
|
const pseudos: Set<string> = new Set();
|
||||||
* @param form
|
poll.choices.forEach((choice: Choice) => {
|
||||||
*/
|
choice.participants.forEach((users: Set<Owner>) => {
|
||||||
newPollFromForm(form: any): Poll {
|
users.forEach((user: Owner) => {
|
||||||
const newOwner = this.storageService.vote_stack.owner;
|
pseudos.add(user.pseudo);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const newpoll = new Poll(newOwner, form.value.custom_url, form.value.title);
|
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];
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const pollKeys = Object.keys(newpoll);
|
poll.choices.forEach((choice: Choice) => {
|
||||||
const formFields = Object.keys(form.value);
|
choice.participants.forEach((users: Set<Owner>, answer: Answer) => {
|
||||||
newpoll.allowed_answers = ['yes'];
|
users.forEach((user: Owner) => {
|
||||||
|
list.get(user.pseudo).set(choice.name, answer);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
for (const pk of pollKeys) {
|
return list;
|
||||||
if (formFields.indexOf(pk) !== -1) {
|
|
||||||
const field = form.value[pk];
|
|
||||||
newpoll[pk] = field;
|
|
||||||
} else {
|
|
||||||
console.log('manque pollKey', pk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (form.value.isMaybeAnswerAvailable) {
|
public getParticipationUrlFromForm(): string {
|
||||||
newpoll.allowed_answers.push('maybe');
|
return `${environment.frontDomain}#/poll/${this.form.value.custom_url}/consultation`;
|
||||||
}
|
|
||||||
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);
|
|
||||||
return newpoll;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAdministrationUrl(): string {
|
public getAdministrationUrlFromForm(): string {
|
||||||
let url = '';
|
// admin_key is filled after creation
|
||||||
if (this._poll && this._poll.getValue) {
|
// example http://localhost:4200/#/administration/key/8Ubcg2YI99f69xz946cn4O64bQAeb
|
||||||
const polltemp = this._poll.getValue();
|
|
||||||
if (polltemp) {
|
return `${environment.frontDomain}#/administration/key/${this.admin_key}`;
|
||||||
url = `${environment.frontDomain}#/poll/admin/${polltemp.admin_key}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getParticipationUrl(): string {
|
public getParticipationUrl(): string {
|
||||||
|
// http://localhost:4200/#/poll/dessin-anime/consultation
|
||||||
|
|
||||||
|
// TODO handle secure access
|
||||||
|
// http://localhost:4200/#/poll/citron/consultation/secure/1c01ed9c94fc640a1be864f197ff808c
|
||||||
|
|
||||||
let url = '';
|
let url = '';
|
||||||
if (this._poll && this._poll.getValue) {
|
if (this._poll && this._poll.getValue) {
|
||||||
const polltemp = this._poll.getValue();
|
const polltemp = this._poll.getValue();
|
||||||
if (polltemp) {
|
if (polltemp) {
|
||||||
url = `${environment.frontDomain}#/poll/${polltemp.custom_url}/consultation`;
|
url = `${environment.frontDomain}#/poll/${polltemp.custom_url}/consultation`;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
url = `${environment.frontDomain}#/poll/${this.form.value.custom_url}/consultation`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO handle pass access
|
// TODO handle pass access
|
||||||
return url;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enrich vote stack with missing default votes
|
* enrich vote stack with missing default votes
|
||||||
* @param vote_stack
|
* @param vote_stack
|
||||||
@ -297,4 +661,78 @@ export class PollService implements Resolve<Poll> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convertCalendarDatesToChoices(array_dates) {
|
||||||
|
return array_dates;
|
||||||
|
}
|
||||||
|
|
||||||
|
patchFormWithPoll(poll: Poll) {
|
||||||
|
this.form.patchValue({
|
||||||
|
...poll,
|
||||||
|
isAboutDate: poll.kind == 'date',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description convert to API version 1 data transition object
|
||||||
|
*/
|
||||||
|
newPollFromForm(): Poll {
|
||||||
|
let form = this.form;
|
||||||
|
console.log('this.form.value', this.form.value);
|
||||||
|
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 = [];
|
||||||
|
|
||||||
|
// comparer les champs de formulaire avec le DTO de création de sondage
|
||||||
|
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.max_count_of_answers = form.value.maxCountOfAnswers;
|
||||||
|
newpoll.maxCountOfAnswers = form.value.maxCountOfAnswers;
|
||||||
|
newpoll.password = form.value.password;
|
||||||
|
newpoll.kind = form.value.isAboutDate ? 'date' : 'classic';
|
||||||
|
newpoll.allow_comments = form.value.allowComments;
|
||||||
|
// merge choices from storage
|
||||||
|
if (form.value.isAboutDate) {
|
||||||
|
// convert calendar picker dates
|
||||||
|
console.log('this.calendar', this.calendar);
|
||||||
|
|
||||||
|
for (let elem of this.calendar) {
|
||||||
|
console.log('elem', elem);
|
||||||
|
let converted_day = {
|
||||||
|
literal: this.DateUtilitiesService.formateDateToInputStringNg(elem),
|
||||||
|
timeSlices: [],
|
||||||
|
date_object: elem,
|
||||||
|
};
|
||||||
|
newpoll.dateChoices.push(converted_day);
|
||||||
|
}
|
||||||
|
console.log('newpoll.dateChoices', newpoll.dateChoices);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,16 +65,16 @@ export class PollUtilitiesService {
|
|||||||
* @param bodyContent
|
* @param bodyContent
|
||||||
*/
|
*/
|
||||||
makeHeaders(bodyContent?: any) {
|
makeHeaders(bodyContent?: any) {
|
||||||
const headerDict = {
|
// const headerDict = {
|
||||||
Charset: 'UTF-8',
|
// Charset: 'UTF-8',
|
||||||
'Content-Type': 'application/json',
|
// 'Content-Type': 'application/json',
|
||||||
Accept: 'application/json',
|
// Accept: 'application/json',
|
||||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
// 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||||
'Access-Control-Allow-Origin': '*',
|
// 'Access-Control-Allow-Origin': '*',
|
||||||
};
|
// };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
headers: headerDict,
|
headers: [],
|
||||||
body: bodyContent,
|
body: bodyContent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -46,18 +46,13 @@ export class StorageService {
|
|||||||
public choices: Choice[] = [];
|
public choices: Choice[] = [];
|
||||||
|
|
||||||
constructor(public dateUtilities: DateUtilitiesService, private toastService: ToastService) {
|
constructor(public dateUtilities: DateUtilitiesService, private toastService: ToastService) {
|
||||||
if (environment.autofill) {
|
if (environment.autofill_participation) {
|
||||||
this.toastService.display('autofill des sondages utilisateur');
|
|
||||||
this.userPolls.push(new Poll(new Owner(), 'Démo: Anniversaire de tonton Patrick', 'aujourdhui-ou-demain'));
|
this.userPolls.push(new Poll(new Owner(), 'Démo: Anniversaire de tonton Patrick', 'aujourdhui-ou-demain'));
|
||||||
this.userPolls.push(new Poll(new Owner(), 'Démo: Atelier cuisine du quartier', 'aujourdhui-ou-demain'));
|
this.userPolls.push(new Poll(new Owner(), 'Démo: Atelier cuisine du quartier', 'aujourdhui-ou-demain'));
|
||||||
this.userPolls.push(
|
this.userPolls.push(
|
||||||
new Poll(new Owner(), 'Démo: Réunion du département des chatons', 'aujourdhui-ou-demain')
|
new Poll(new Owner(), 'Démo: Réunion du département des chatons', 'aujourdhui-ou-demain')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.dateChoices.length) {
|
|
||||||
this.dateChoices = this.dateUtilities.makeDefaultDateChoices();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,15 +65,16 @@ export class StorageService {
|
|||||||
if (!this.vote_stack.id) {
|
if (!this.vote_stack.id) {
|
||||||
this.vote_stack = new Stack();
|
this.vote_stack = new Stack();
|
||||||
|
|
||||||
|
console.log('choices_list', choices_list);
|
||||||
for (const choice of choices_list) {
|
for (const choice of choices_list) {
|
||||||
if (environment.autofill) {
|
// if (environment.autofill_participation) {
|
||||||
console.log('autofill au hasard des votes à ce sondage');
|
// console.log('autofill au hasard des votes à ce sondage');
|
||||||
this.toastService.display('autofill au hasard des votes à ce sondage');
|
// this.toastService.display('autofill au hasard des votes à ce sondage');
|
||||||
const defaultvalue = Math.random() > 0.75 ? 'yes' : '';
|
// const defaultvalue = Math.random() > 0.75 ? 'yes' : '';
|
||||||
this.vote_stack.votes.push(new Vote(choice.id, defaultvalue));
|
// this.vote_stack.votes.push(new Vote(choice.id, defaultvalue));
|
||||||
} else {
|
// } else {
|
||||||
this.vote_stack.votes.push(new Vote(choice.id));
|
this.vote_stack.votes.push(new Vote(choice.id));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,34 @@ import { NgModule } from '@angular/core';
|
|||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
import { AdministrationComponent } from './administration.component';
|
import { AdministrationComponent } from './administration.component';
|
||||||
import { NamingComponent } from './naming/naming.component';
|
import { StepTwoComponent } from './form/steps/step-two/step-two.component';
|
||||||
|
import { StepThreeComponent } from './form/steps/step-three/step-three.component';
|
||||||
|
import { StepFourComponent } from './form/steps/step-four/step-four.component';
|
||||||
|
import { StepFiveComponent } from './form/steps/step-five/step-five.component';
|
||||||
|
import { StepOneComponent } from './form/steps/step-one/step-one.component';
|
||||||
|
import { SuccessComponent } from './success/success.component';
|
||||||
|
import { AdminConsultationComponent } from './consultation/consultation.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', component: AdministrationComponent, data: { animation: 'AdminPage' } },
|
{
|
||||||
{ path: 'naming', component: NamingComponent },
|
path: '',
|
||||||
|
component: AdministrationComponent,
|
||||||
|
},
|
||||||
|
{ path: 'key/:admin_key', component: AdminConsultationComponent },
|
||||||
|
{
|
||||||
|
path: 'step',
|
||||||
|
children: [
|
||||||
|
{ path: '1', component: StepOneComponent },
|
||||||
|
{ path: '2', component: StepTwoComponent },
|
||||||
|
{ path: '3', component: StepThreeComponent },
|
||||||
|
{ path: '4', component: StepFourComponent },
|
||||||
|
{ path: '5', component: StepFiveComponent },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'success',
|
||||||
|
component: SuccessComponent,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -20,7 +20,7 @@ export class AdministrationComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.routeSubscription = this.route.data.subscribe((data: { poll: Poll }) => {
|
this.routeSubscription = this.route.data.subscribe((data: { poll: Poll }) => {
|
||||||
console.log('data', data);
|
console.log('routeSubscription data', data);
|
||||||
if (data.poll) {
|
if (data.poll) {
|
||||||
this.poll = data.poll;
|
this.poll = data.poll;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,12 @@ import { AdministrationComponent } from './administration.component';
|
|||||||
import { StepperComponent } from './stepper/stepper.component';
|
import { StepperComponent } from './stepper/stepper.component';
|
||||||
import { NamingComponent } from './naming/naming.component';
|
import { NamingComponent } from './naming/naming.component';
|
||||||
import { FormComponent } from './form/form.component';
|
import { FormComponent } from './form/form.component';
|
||||||
|
import { StepOneComponent } from './form/steps/step-one/step-one.component';
|
||||||
|
import { StepTwoComponent } from './form/steps/step-two/step-two.component';
|
||||||
|
import { StepThreeComponent } from './form/steps/step-three/step-three.component';
|
||||||
|
import { StepFourComponent } from './form/steps/step-four/step-four.component';
|
||||||
|
import { StepFiveComponent } from './form/steps/step-five/step-five.component';
|
||||||
|
import { CalendarModule } from 'primeng/calendar';
|
||||||
import { SuccessComponent } from './success/success.component';
|
import { SuccessComponent } from './success/success.component';
|
||||||
import { DateSelectComponent } from './form/date-select/date-select.component';
|
import { DateSelectComponent } from './form/date-select/date-select.component';
|
||||||
import { TextSelectComponent } from './form/text-select/text-select.component';
|
import { TextSelectComponent } from './form/text-select/text-select.component';
|
||||||
@ -21,6 +27,7 @@ import { IntervalComponent } from './form/date/interval/interval.component';
|
|||||||
import { DayListComponent } from './form/date/list/day/day-list.component';
|
import { DayListComponent } from './form/date/list/day/day-list.component';
|
||||||
import { PickerComponent } from './form/date/picker/picker.component';
|
import { PickerComponent } from './form/date/picker/picker.component';
|
||||||
import { TimeListComponent } from './form/date/list/time/time-list.component';
|
import { TimeListComponent } from './form/date/list/time/time-list.component';
|
||||||
|
import { AdminConsultationComponent } from './consultation/consultation.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -34,14 +41,22 @@ import { TimeListComponent } from './form/date/list/time/time-list.component';
|
|||||||
KindSelectComponent,
|
KindSelectComponent,
|
||||||
BaseConfigComponent,
|
BaseConfigComponent,
|
||||||
AdvancedConfigComponent,
|
AdvancedConfigComponent,
|
||||||
|
StepOneComponent,
|
||||||
|
StepTwoComponent,
|
||||||
|
StepThreeComponent,
|
||||||
|
StepFourComponent,
|
||||||
|
StepFiveComponent,
|
||||||
|
SuccessComponent,
|
||||||
IntervalComponent,
|
IntervalComponent,
|
||||||
DayListComponent,
|
DayListComponent,
|
||||||
PickerComponent,
|
PickerComponent,
|
||||||
TimeListComponent,
|
TimeListComponent,
|
||||||
|
AdminConsultationComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
AdministrationRoutingModule,
|
AdministrationRoutingModule,
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
CalendarModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
<div class="admin-consultation min-height padded">
|
||||||
|
<h2 class="title is-2">Consulter le sondage</h2>
|
||||||
|
<button class="btn is-primary" [routerLink]="'/administration'">
|
||||||
|
<i class="fa fa-pencil"></i>
|
||||||
|
modifier
|
||||||
|
</button>
|
||||||
|
<div>
|
||||||
|
<h2>{{ form.value.title }}</h2>
|
||||||
|
|
||||||
|
<div *ngIf="poll">
|
||||||
|
<h2>{{ poll.title }}</h2>
|
||||||
|
|
||||||
|
Créé le {{ poll.created_at | date }} par {{ poll.owner.pseudo }}, {{ poll.owner.email }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ConsultationComponent } from './consultation.component';
|
||||||
|
|
||||||
|
describe('ConsultationComponent', () => {
|
||||||
|
let component: ConsultationComponent;
|
||||||
|
let fixture: ComponentFixture<ConsultationComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ConsultationComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ConsultationComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,49 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { PollService } from '../../../core/services/poll.service';
|
||||||
|
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
||||||
|
import { ApiService } from '../../../core/services/api.service';
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
import { Poll } from '../../../core/models/poll.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-admin-consultation',
|
||||||
|
templateUrl: './consultation.component.html',
|
||||||
|
styleUrls: ['./consultation.component.scss'],
|
||||||
|
})
|
||||||
|
export class AdminConsultationComponent implements OnInit {
|
||||||
|
private admin_key: string;
|
||||||
|
public form: FormGroup;
|
||||||
|
public poll: any;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private pollService: PollService,
|
||||||
|
private apiService: ApiService,
|
||||||
|
private _Activatedroute: ActivatedRoute,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
this.poll = this.pollService._poll.getValue();
|
||||||
|
this.form = this.pollService.form;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this._Activatedroute.paramMap.subscribe((params: ParamMap) => {
|
||||||
|
this.admin_key = params.get('admin_key');
|
||||||
|
if (!this.admin_key) {
|
||||||
|
this.router.navigate(['page-not-found']);
|
||||||
|
}
|
||||||
|
this.apiService.getPollByAdminKey(this.admin_key).then(
|
||||||
|
(res) => {
|
||||||
|
this.pollService.updateCurrentPoll(res.poll);
|
||||||
|
this.form = this.pollService.form;
|
||||||
|
this.poll = this.pollService._poll.getValue();
|
||||||
|
console.log('formulaire patché', this.pollService.form, this.pollService.poll);
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
if (!this.admin_key) {
|
||||||
|
this.router.navigate(['page-not-found']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
<form [formGroup]="form" class="box">
|
<form [formGroup]="form" class="box">
|
||||||
<fieldset class="complete well">
|
<fieldset class="complete well">
|
||||||
<h2>{{ 'creation.advanced' | translate }}</h2>
|
|
||||||
<label for="descr">Description (optionnel)</label>
|
<label for="descr">Description (optionnel)</label>
|
||||||
<br />
|
<br />
|
||||||
<textarea
|
<textarea
|
||||||
@ -11,32 +10,20 @@
|
|||||||
formControlName="description"
|
formControlName="description"
|
||||||
required
|
required
|
||||||
></textarea>
|
></textarea>
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
*ngIf="description.value"
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="Clear"
|
|
||||||
(click)="description.value = ''"
|
|
||||||
>
|
|
||||||
<i class="fa fa-close"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<label for="custom_url">
|
<label for="custom_url">
|
||||||
Url personnalisée pour les participants
|
Url personnalisée pour les participants
|
||||||
<i class="fa fa-close"></i>
|
|
||||||
</label>
|
</label>
|
||||||
<br />
|
<br />
|
||||||
<button
|
<button
|
||||||
mat-button
|
|
||||||
*ngIf="form.controls.custom_url.value"
|
*ngIf="form.controls.custom_url.value"
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="Clear"
|
aria-label="Clear"
|
||||||
(click)="form.patchValue({ custom_url: '' })"
|
(click)="form.patchValue({ custom_url: pollService.makeSlug(form) })"
|
||||||
></button>
|
>
|
||||||
|
<i class="fa fa-recycle"></i> régénérer
|
||||||
|
</button>
|
||||||
<input #custom_url matInput id="custom_url" placeholder="Url" formControlName="custom_url" required />
|
<input #custom_url matInput id="custom_url" placeholder="Url" formControlName="custom_url" required />
|
||||||
<br />
|
<br />
|
||||||
<div appearance="outline" class="is-not-flex">
|
<div appearance="outline" class="is-not-flex">
|
||||||
@ -52,16 +39,6 @@
|
|||||||
formControlName="expiresDaysDelay"
|
formControlName="expiresDaysDelay"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
*ngIf="expiresDaysDelay.value"
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="Clear"
|
|
||||||
(click)="expiresDaysDelay.value = ''"
|
|
||||||
>
|
|
||||||
<i class="fa fa-close"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<mat-checkbox class="is-not-flex" formControlName="areResultsPublic">
|
<mat-checkbox class="is-not-flex" formControlName="areResultsPublic">
|
||||||
Les participants pourront consulter les résultats
|
Les participants pourront consulter les résultats
|
||||||
@ -75,16 +52,26 @@
|
|||||||
Le sondage sera protégé par un mot de passe
|
Le sondage sera protégé par un mot de passe
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<br />
|
<br />
|
||||||
|
<div class="password-box" *ngIf="form.value.isProtectedByPassword">
|
||||||
<input
|
<input
|
||||||
*ngIf="form.value.isProtectedByPassword"
|
|
||||||
#password
|
#password
|
||||||
id="password"
|
id="password"
|
||||||
matInput
|
matInput
|
||||||
type="password"
|
[type]="displayClearPassword ? 'text' : 'password'"
|
||||||
placeholder="password"
|
placeholder="password"
|
||||||
formControlName="password"
|
formControlName="password"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<button
|
||||||
|
class="button"
|
||||||
|
[ngClass]="{ 'is-primary': displayClearPassword, 'is-info': !displayClearPassword }"
|
||||||
|
(click)="displayClearPassword = !displayClearPassword"
|
||||||
|
>
|
||||||
|
voir
|
||||||
|
<i class="fa fa-eye" *ngIf="!displayClearPassword"></i>
|
||||||
|
<i class="fa fa-eye-slash" *ngIf="displayClearPassword"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h3 class="title is-3">
|
<h3 class="title is-3">
|
||||||
<i class="fa fa-envelope-open"></i>
|
<i class="fa fa-envelope-open"></i>
|
||||||
@ -103,20 +90,19 @@
|
|||||||
Réponses proposées
|
Réponses proposées
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_YES.svg" />
|
|
||||||
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_MAYBE.svg" />
|
|
||||||
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_NO.svg" />
|
|
||||||
|
|
||||||
<mat-checkbox class="is-not-flex" formControlName="isYesAnswerAvailable">
|
<mat-checkbox class="is-not-flex" formControlName="isYesAnswerAvailable">
|
||||||
La réponse « oui » sera disponible
|
La réponse « oui » sera disponible
|
||||||
|
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_YES.svg" />
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<br />
|
<br />
|
||||||
<mat-checkbox class="is-not-flex" formControlName="isMaybeAnswerAvailable">
|
<mat-checkbox class="is-not-flex" formControlName="isMaybeAnswerAvailable">
|
||||||
La réponse « peut-être » sera disponible
|
La réponse « peut-être » sera disponible
|
||||||
|
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_MAYBE.svg" />
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<br />
|
<br />
|
||||||
<mat-checkbox class="is-not-flex" formControlName="isNoAnswerAvailable">
|
<mat-checkbox class="is-not-flex" formControlName="isNoAnswerAvailable">
|
||||||
La réponse « non » sera disponible
|
La réponse « non » sera disponible
|
||||||
|
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_NO.svg" />
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="title is-3">
|
<h3 class="title is-3">
|
||||||
@ -128,7 +114,7 @@
|
|||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<br />
|
<br />
|
||||||
<mat-checkbox class="is-not-flex" formControlName="hasMaxCountOfAnswers">
|
<mat-checkbox class="is-not-flex" formControlName="hasMaxCountOfAnswers">
|
||||||
Nombre de réponses limitées à ce nombre
|
Nombre de réponses limitées à ce nombre. Utile pour réserver des places à un évènement.
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<input
|
<input
|
||||||
*ngIf="form.value.hasMaxCountOfAnswers"
|
*ngIf="form.value.hasMaxCountOfAnswers"
|
||||||
@ -142,16 +128,14 @@
|
|||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset class="work-in-progress">
|
||||||
<h2 class="title is-2">
|
<h2 class="title is-2">
|
||||||
<i class="fa fa-wikidata"></i>
|
<i class="fa fa-wikidata"></i>
|
||||||
Fonctionnalités pas encore disponibles:
|
Fonctionnalités pas encore disponibles:
|
||||||
</h2>
|
</h2>
|
||||||
<app-wip-todo></app-wip-todo>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<mat-checkbox class="is-not-flex" formControlName="useVoterUniqueLink">
|
<mat-checkbox class="is-not-flex" formControlName="useVoterUniqueLink">
|
||||||
Spécifier un lien unique de vote à des participants définis
|
Spécifier un <strong> lien unique de vote</strong> à des participants définis par leur email
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<p>
|
<p>
|
||||||
lister les email des participants et leur fournir un lien unique pour voter à chacun, au lieu d'un lien
|
lister les email des participants et leur fournir un lien unique pour voter à chacun, au lieu d'un lien
|
||||||
@ -174,4 +158,5 @@
|
|||||||
Les informations du sondage seront chiffrés en base de données
|
Les informations du sondage seront chiffrés en base de données
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<app-errors-list [form]="form"></app-errors-list>
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
@import '../../../../../styles/variables';
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
|
.mat-checkbox {
|
||||||
|
img {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.button .fa {
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
input,
|
||||||
|
textarea {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { Component, Input, OnInit } from '@angular/core';
|
|||||||
import { Poll } from '../../../../core/models/poll.model';
|
import { Poll } from '../../../../core/models/poll.model';
|
||||||
import { FormGroup } from '@angular/forms';
|
import { FormGroup } from '@angular/forms';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
|
import { PollService } from '../../../../core/services/poll.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-advanced-config',
|
selector: 'app-advanced-config',
|
||||||
@ -11,11 +12,12 @@ import { environment } from 'src/environments/environment';
|
|||||||
export class AdvancedConfigComponent implements OnInit {
|
export class AdvancedConfigComponent implements OnInit {
|
||||||
public urlPrefix = '/participation/';
|
public urlPrefix = '/participation/';
|
||||||
public environment = environment;
|
public environment = environment;
|
||||||
|
public displayClearPassword = false;
|
||||||
@Input()
|
@Input()
|
||||||
public poll?: Poll;
|
public poll?: Poll;
|
||||||
@Input()
|
@Input()
|
||||||
public form: FormGroup;
|
public form: FormGroup;
|
||||||
constructor() {}
|
constructor(public pollService: PollService) {}
|
||||||
|
|
||||||
ngOnInit(): void {}
|
ngOnInit(): void {}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#title {
|
#title {
|
||||||
display: block;
|
display: block;
|
||||||
width: 80%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ export class BaseConfigComponent {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
public updateSlug(): void {
|
public updateSlug(): void {
|
||||||
const newValueFormatted = this.pollService.convertTextToSlug(this.form.value.title);
|
const newValueFormatted = this.pollService.makeSlug(this.pollService.form);
|
||||||
console.log('newValueFormatted', newValueFormatted);
|
console.log('newValueFormatted', newValueFormatted);
|
||||||
this.form.patchValue({ custom_url: newValueFormatted });
|
this.form.patchValue({ custom_url: newValueFormatted });
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,8 @@ export class IntervalComponent implements OnInit {
|
|||||||
this.intervalDays = this.dateUtilities.countDays(
|
this.intervalDays = this.dateUtilities.countDays(
|
||||||
this.startDateInterval,
|
this.startDateInterval,
|
||||||
this.endDateInterval
|
this.endDateInterval
|
||||||
// this.dateUtilities.parseInputDateToDateObject(this.startDateIntervalString),
|
// this.DateUtilitiesService.parseInputDateToDateObject(this.startDateIntervalString),
|
||||||
// this.dateUtilities.parseInputDateToDateObject(this.endDateIntervalString)
|
// this.DateUtilitiesService.parseInputDateToDateObject(this.endDateIntervalString)
|
||||||
);
|
);
|
||||||
console.log('this.intervalDays ', this.intervalDays);
|
console.log('this.intervalDays ', this.intervalDays);
|
||||||
}
|
}
|
||||||
|
@ -1,101 +1,9 @@
|
|||||||
<div class="admin-form padded">
|
<div class="admin-form">
|
||||||
<div class="container is-max-widescreen">
|
<section class="min-height padded">
|
||||||
<form [formGroup]="form">
|
<router-outlet>
|
||||||
<header class="columns">
|
<app-step-one [form]="form"></app-step-one>
|
||||||
<div class="column">
|
</router-outlet>
|
||||||
<h1 class="title is-2">
|
|
||||||
{{ 'creation.title' | translate }}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<button class="btn is-success is-fixed-bottom" (click)="createPoll()" *ngIf="!environment.production">
|
|
||||||
<i class="fa fa-save"></i>
|
|
||||||
Enregistrer le sondage (sans vérifier)
|
|
||||||
</button>
|
|
||||||
<button class="btn btn--warning" (click)="askInitFormDefault()">
|
|
||||||
<i class="fa fa-refresh"></i>
|
|
||||||
Tout réinitialiser
|
|
||||||
</button>
|
|
||||||
<button class="btn is-default" (click)="automaticSlug()">
|
|
||||||
<i class="fa fa-refresh"></i>
|
|
||||||
Slug automatique
|
|
||||||
</button>
|
|
||||||
<main class="columns">
|
|
||||||
<div class="column">
|
|
||||||
<label class="label is-medium" for="kind">
|
|
||||||
{{ 'creation.want' | translate }}
|
|
||||||
</label>
|
|
||||||
<!-- <div class="step-choices" *ngIf="currentStep === 'base'">-->
|
|
||||||
<app-kind-select [form]="form"></app-kind-select>
|
|
||||||
<app-base-config [form]="form"></app-base-config>
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="step-choices" *ngIf="currentStep === 'choices'"> </div>-->
|
|
||||||
<app-date-select *ngIf="form.value && form.value.kind == 'date'" [form]="form"></app-date-select>
|
|
||||||
<app-text-select *ngIf="form.value && form.value.kind == 'text'" [form]="form"></app-text-select>
|
|
||||||
|
|
||||||
<button
|
<app-errors-list [form]="pollService.form"></app-errors-list>
|
||||||
class="btn"
|
</section>
|
||||||
[class]="{ 'is-primary': advancedDisplayEnabled, 'is-info': !advancedDisplayEnabled }"
|
|
||||||
(click)="advancedDisplayEnabled = !advancedDisplayEnabled"
|
|
||||||
>
|
|
||||||
<i class="fa fa-save"></i>
|
|
||||||
{{ 'creation.advanced' | translate }}
|
|
||||||
</button>
|
|
||||||
<app-advanced-config
|
|
||||||
[poll]="poll"
|
|
||||||
[form]="form"
|
|
||||||
*ngIf="advancedDisplayEnabled"
|
|
||||||
></app-advanced-config>
|
|
||||||
|
|
||||||
<!-- <div class="bar-nav-admin">-->
|
|
||||||
<!-- <div class="columns">-->
|
|
||||||
<!-- <div class="column">-->
|
|
||||||
<!-- <p class="control">-->
|
|
||||||
<!-- <a class="button is-light" (click)="goPreviousStep()">-->
|
|
||||||
<!-- Précédent-->
|
|
||||||
<!-- </a>-->
|
|
||||||
<!-- </p>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="column">-->
|
|
||||||
<!-- <p class="control text-right">-->
|
|
||||||
<!-- <a class="button is-primary" (click)="goNextStep()">-->
|
|
||||||
<!-- Suivant-->
|
|
||||||
<!-- </a>-->
|
|
||||||
<!-- </p>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<app-picker [form]="form" *ngIf="displayDatePicker"></app-picker>
|
|
||||||
<app-errors-list [form]="form"></app-errors-list>
|
|
||||||
<button
|
|
||||||
[disabled]="!form.valid && form.touched"
|
|
||||||
class="btn is-success is-fixed-bottom"
|
|
||||||
(click)="createPoll()"
|
|
||||||
>
|
|
||||||
<i class="fa fa-save"></i>
|
|
||||||
Enregistrer le sondage
|
|
||||||
</button>
|
|
||||||
<button class="btn is-success is-fixed-bottom" (click)="createPoll()" *ngIf="!environment.production">
|
|
||||||
<i class="fa fa-save"></i>
|
|
||||||
Enregistrer le sondage (sans vérifier)
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<footer class="column" *ngIf="show_debug_data">
|
|
||||||
<h2>Debug data</h2>
|
|
||||||
<pre class="debug padded warning">
|
|
||||||
form values :
|
|
||||||
{{ form.value | json }}
|
|
||||||
</pre
|
|
||||||
>
|
|
||||||
<pre class="debug padded warning">
|
|
||||||
poll initial values :
|
|
||||||
{{ poll | json }}
|
|
||||||
</pre
|
|
||||||
>
|
|
||||||
</footer>
|
|
||||||
<hr />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
@import '../../../../styles/variables';
|
||||||
|
.admin-form {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
border: solid 1px $border-color;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
@ -1,231 +1,40 @@
|
|||||||
import { ChangeDetectorRef, Component, Inject, Input, OnInit, AfterViewInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
import { Poll } from '../../../core/models/poll.model';
|
import { Poll } from '../../../core/models/poll.model';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { UuidService } from '../../../core/services/uuid.service';
|
||||||
import { ApiService } from '../../../core/services/api.service';
|
import { ApiService } from '../../../core/services/api.service';
|
||||||
import { ToastService } from '../../../core/services/toast.service';
|
import { ToastService } from '../../../core/services/toast.service';
|
||||||
import { PollService } from '../../../core/services/poll.service';
|
import { PollService } from '../../../core/services/poll.service';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { environment } from '../../../../environments/environment';
|
|
||||||
import { PollUtilitiesService } from '../../../core/services/poll.utilities.service';
|
|
||||||
import { StorageService } from '../../../core/services/storage.service';
|
|
||||||
import { DateUtilitiesService } from '../../../core/services/date.utilities.service';
|
|
||||||
import { formatDate } from '@angular/common';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-admin-form',
|
selector: 'app-admin-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
styleUrls: ['./form.component.scss'],
|
styleUrls: ['./form.component.scss'],
|
||||||
})
|
})
|
||||||
export class FormComponent implements OnInit, AfterViewInit {
|
export class FormComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
public poll?: Poll;
|
public poll?: Poll;
|
||||||
public form: FormGroup;
|
public form: FormGroup;
|
||||||
|
|
||||||
public displayDatePicker = false;
|
|
||||||
public advancedDisplayEnabled = false;
|
|
||||||
public show_debug_data = false;
|
|
||||||
public currentStep = 'base';
|
|
||||||
public steps = ['base', 'choices', 'advanced'];
|
|
||||||
|
|
||||||
public environment = environment;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
private cd: ChangeDetectorRef,
|
private cd: ChangeDetectorRef,
|
||||||
private pollUtilitiesService: PollUtilitiesService,
|
private uuidService: UuidService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private pollService: PollService,
|
public pollService: PollService,
|
||||||
private storageService: StorageService,
|
|
||||||
public apiService: ApiService,
|
|
||||||
public dateUtils: DateUtilitiesService,
|
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private utilitiesService: PollUtilitiesService,
|
public route: ActivatedRoute,
|
||||||
|
private apiService: ApiService,
|
||||||
@Inject(DOCUMENT) private document: any
|
@Inject(DOCUMENT) private document: any
|
||||||
) {}
|
) {
|
||||||
|
this.form = this.pollService.form;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.initFormDefault();
|
this.pollService.askInitFormDefault();
|
||||||
// this.goNextStep();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
goNextStep() {}
|
||||||
// focus on first field of the creation form
|
|
||||||
const firstField = this.document.querySelector('#kind');
|
|
||||||
if (firstField) {
|
|
||||||
console.log('focus on ', firstField);
|
|
||||||
firstField.focus();
|
|
||||||
} else {
|
|
||||||
console.log('no first field of form');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initFormDefault(showDemoValues = environment.autofill): void {
|
|
||||||
const creationDate = new Date();
|
|
||||||
|
|
||||||
// choices of date are managed outside of this form
|
|
||||||
this.form = this.fb.group({
|
|
||||||
title: ['', [Validators.required, Validators.minLength(5)]],
|
|
||||||
creatorPseudo: ['', [Validators.required]],
|
|
||||||
creatorEmail: ['', [Validators.required, Validators.email]],
|
|
||||||
custom_url: [this.pollUtilitiesService.makeUuid(), [Validators.required]],
|
|
||||||
description: ['', [Validators.required]],
|
|
||||||
kind: ['date', [Validators.required]],
|
|
||||||
areResultsPublic: [true, [Validators.required]],
|
|
||||||
whoCanChangeAnswers: ['everybody', [Validators.required]],
|
|
||||||
isProtectedByPassword: [false, [Validators.required]],
|
|
||||||
allowNewDateTime: [false, [Validators.required]],
|
|
||||||
isOwnerNotifiedByEmailOnNewVote: [false, [Validators.required]],
|
|
||||||
isOwnerNotifiedByEmailOnNewComment: [false, [Validators.required]],
|
|
||||||
isYesAnswerAvailable: [false, [Validators.required]],
|
|
||||||
isMaybeAnswerAvailable: [false, [Validators.required]],
|
|
||||||
isNoAnswerAvailable: [false, [Validators.required]],
|
|
||||||
isAboutDate: [true, [Validators.required]],
|
|
||||||
isZeroKnoledge: [false, [Validators.required]],
|
|
||||||
useVoterUniqueLink: [false, [Validators.required]],
|
|
||||||
expiresDaysDelay: [60, [Validators.required, Validators.min(1), Validators.max(365)]],
|
|
||||||
maxCountOfAnswers: [150, [Validators.required, Validators.min(1), Validators.max(5000)]],
|
|
||||||
allowComments: [true, [Validators.required]],
|
|
||||||
password: ['', []],
|
|
||||||
voterEmailList: ['', []],
|
|
||||||
natural_lang_interval: ['', []],
|
|
||||||
dateCreated: [creationDate, [Validators.required]],
|
|
||||||
hasSeveralHours: [false, [Validators.required]],
|
|
||||||
hasMaxCountOfAnswers: [true, [Validators.required, Validators.min(1)]],
|
|
||||||
startDateInterval: ['', [Validators.required]],
|
|
||||||
endDateInterval: ['', [Validators.required]],
|
|
||||||
});
|
|
||||||
|
|
||||||
// take back values from pollservice
|
|
||||||
// this.form.patchValue(this.pollService.poll);
|
|
||||||
this.setDefaultFormValues();
|
|
||||||
|
|
||||||
if (showDemoValues) {
|
|
||||||
this.setDemoValues();
|
|
||||||
this.toastService.display('default values filled for demo');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (environment.autoSendNewPoll) {
|
|
||||||
this.createPoll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setDefaultFormValues(): void {
|
|
||||||
this.form.patchValue({
|
|
||||||
creatorPseudo: 'Anne Onyme',
|
|
||||||
creatorEmail: 'anne_onyme@anonymous_email.com',
|
|
||||||
description: 'RSVP',
|
|
||||||
isAboutDate: true,
|
|
||||||
hasSeveralHours: false,
|
|
||||||
kind: 'date',
|
|
||||||
password: '',
|
|
||||||
whoCanChangeAnswers: 'everybody',
|
|
||||||
isProtectedByPassword: false,
|
|
||||||
isOwnerNotifiedByEmailOnNewVote: false,
|
|
||||||
isOwnerNotifiedByEmailOnNewComment: false,
|
|
||||||
isYesAnswerAvailable: true,
|
|
||||||
isMaybeAnswerAvailable: false,
|
|
||||||
isNoAnswerAvailable: false,
|
|
||||||
isZeroKnoledge: true,
|
|
||||||
areResultsPublic: true,
|
|
||||||
allowComments: true,
|
|
||||||
expiresDaysDelay: environment.expiresDaysDelay,
|
|
||||||
maxCountOfAnswers: environment.maxCountOfAnswers,
|
|
||||||
allowNewDateTime: false,
|
|
||||||
// startDateInterval: formatDate(new Date(), 'yyyy-MM-dd', 'fr_FR'),
|
|
||||||
endDateInterval: formatDate(
|
|
||||||
this.dateUtils.addDaysToDate(environment.interval_days_default, new Date()),
|
|
||||||
'yyyy-MM-dd',
|
|
||||||
'fr_FR'
|
|
||||||
),
|
|
||||||
});
|
|
||||||
console.log("this.form.controls['startDateInterval']", this.form.controls['startDateInterval']);
|
|
||||||
this.form.controls['startDateInterval'].setValue(formatDate(new Date(), 'yyyy-MM-dd', 'fr_FR'));
|
|
||||||
console.log("this.form.controls['startDateInterval']", this.form.controls['startDateInterval']);
|
|
||||||
this.automaticSlug();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add example values to the form, overrides defaults of PollConfiguration
|
|
||||||
*/
|
|
||||||
setDemoValues(): void {
|
|
||||||
const title = 'le titre de démo __ ' + new Date().getTime();
|
|
||||||
|
|
||||||
this.form.patchValue({ creatorPseudo: 'Chuck Norris', creatorEmail: 'chucknorris@example.com' });
|
|
||||||
|
|
||||||
this.form.patchValue({
|
|
||||||
title: title,
|
|
||||||
custom_url: this.pollUtilitiesService.makeSlugFromString(title),
|
|
||||||
description: 'répondez SVP <3 ! *-*',
|
|
||||||
creatorPseudo: 'Chuck Norris',
|
|
||||||
creatorEmail: 'chucknorris@example.com',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
askInitFormDefault(): void {
|
|
||||||
this.toastService.display('formulaire réinitialisé', 'info');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the poll custom_url from other data of the poll
|
|
||||||
*/
|
|
||||||
automaticSlug(): void {
|
|
||||||
this.form.patchValue({
|
|
||||||
custom_url:
|
|
||||||
this.pollService.convertTextToSlug(this.form.value.title) +
|
|
||||||
'_' +
|
|
||||||
this.utilitiesService.makeUuid().substr(0, 12),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
goPreviousStep() {
|
|
||||||
alert('todo');
|
|
||||||
}
|
|
||||||
|
|
||||||
goNextStep() {
|
|
||||||
let indexCurrentStep = this.steps.indexOf(this.currentStep);
|
|
||||||
indexCurrentStep += 1;
|
|
||||||
this.currentStep = this.steps[indexCurrentStep];
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public createPoll(): void {
|
|
||||||
const newpoll = this.pollService.newPollFromForm(this.form);
|
|
||||||
console.log('newpoll', newpoll);
|
|
||||||
const router = this.router;
|
|
||||||
|
|
||||||
if (!environment.production) {
|
|
||||||
this.toastService.display('mode dev : envoi du form sans validation');
|
|
||||||
this.apiService.createPoll(newpoll).then(
|
|
||||||
(resp: any) => {
|
|
||||||
this.pollService.updateCurrentPoll(resp.data.poll);
|
|
||||||
this.storageService.userPolls.push(resp.data.poll);
|
|
||||||
this.storageService.vote_stack.owner.polls.push(resp.data.poll);
|
|
||||||
this.toastService.display('sauvegarde du nouveau sondage réussie');
|
|
||||||
router.navigate(['success']);
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
this.toastService.display('erreur lors de la sauvegarde ' + err.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if (this.form.valid) {
|
|
||||||
this.toastService.display("C'est parti!");
|
|
||||||
this.apiService.createPoll(newpoll).then(
|
|
||||||
(resp: any) => {
|
|
||||||
this.pollService.updateCurrentPoll(resp.data.poll);
|
|
||||||
this.storageService.userPolls.push(resp.data.poll);
|
|
||||||
this.storageService.vote_stack.owner.polls.push(resp.data.poll);
|
|
||||||
this.toastService.display('sauvegarde du nouveau sondage réussie');
|
|
||||||
router.navigate(['success']);
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
this.toastService.display('erreur lors de la sauvegarde');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.toastService.display('invalid form');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
<app-stepper [step_current]="5" [step_max]="5"></app-stepper>
|
||||||
|
<app-errors-list [form]="pollService.form"></app-errors-list>
|
||||||
|
<app-success [poll]="pollService.form.value"></app-success>
|
||||||
|
|
||||||
|
<section class="supplement container">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<button class="button is-primary is-fullwidth" [routerLink]="['/administration/step/1']">
|
||||||
|
<i class="fa fa-pencil"></i>
|
||||||
|
modifier le sondage
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn--warning" (click)="askInitFormDefault()">
|
||||||
|
<i class="fa fa-refresh"></i>
|
||||||
|
Tout réinitialiser
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="well">
|
||||||
|
{{ pollService.form.value.custom_url }}
|
||||||
|
</div>
|
||||||
|
<div class="has-background-danger" *ngIf="!pollService.form.valid">
|
||||||
|
le formulaire est invalide
|
||||||
|
<pre> {{ pollService.form.errors | json }}</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StepFiveComponent } from './step-five.component';
|
||||||
|
|
||||||
|
describe('StepFiveComponent', () => {
|
||||||
|
let component: StepFiveComponent;
|
||||||
|
let fixture: ComponentFixture<StepFiveComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [StepFiveComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(StepFiveComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,27 @@
|
|||||||
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
import { PollService } from '../../../../../core/services/poll.service';
|
||||||
|
import { ApiService } from '../../../../../core/services/api.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-step-five',
|
||||||
|
templateUrl: './step-five.component.html',
|
||||||
|
styleUrls: ['./step-five.component.scss'],
|
||||||
|
})
|
||||||
|
export class StepFiveComponent implements OnInit {
|
||||||
|
@Input() step_max: any;
|
||||||
|
@Input() public form: FormGroup;
|
||||||
|
poll: any;
|
||||||
|
constructor(public pollService: PollService) {
|
||||||
|
this.pollService.step_current = 5;
|
||||||
|
}
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
askInitFormDefault() {
|
||||||
|
if (window.confirm('réinitialiser le formulaire ?')) {
|
||||||
|
this.pollService.askInitFormDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
automaticSlug() {}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<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>
|
||||||
|
<div class="creator-infos">
|
||||||
|
<label class="" for="creatorEmail">
|
||||||
|
<span>
|
||||||
|
{{ 'creation.name' | translate }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
#title
|
||||||
|
matInput
|
||||||
|
placeholder="pseudo"
|
||||||
|
formControlName="creatorPseudo"
|
||||||
|
id="creatorPseudo"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<label class="hidden" for="creatorPseudo">
|
||||||
|
<span>
|
||||||
|
{{ 'creation.email' | translate }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
#title
|
||||||
|
matInput
|
||||||
|
placeholder="mon-email@example.com"
|
||||||
|
formControlName="creatorEmail"
|
||||||
|
id="creatorEmail"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<fieldset class="advanced-config">
|
||||||
|
<button
|
||||||
|
class="button is-unchecked-info"
|
||||||
|
[ngClass]="{ 'is-info': !advancedDisplayEnabled, 'is-primary': advancedDisplayEnabled }"
|
||||||
|
(click)="advancedDisplayEnabled = !advancedDisplayEnabled"
|
||||||
|
>
|
||||||
|
<i class="fa fa-chevron-circle-down" *ngIf="!advancedDisplayEnabled"></i>
|
||||||
|
<i class="fa fa-chevron-circle-up" *ngIf="advancedDisplayEnabled"></i>
|
||||||
|
{{ 'creation.advanced' | translate }}
|
||||||
|
</button>
|
||||||
|
<fieldset class="complete well" *ngIf="advancedDisplayEnabled">
|
||||||
|
<app-advanced-config [form]="pollService.form"></app-advanced-config>
|
||||||
|
</fieldset>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<button class="button is-secondary is-fullwidth" [routerLink]="['/administration/step/3']">
|
||||||
|
précédent
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<button class="btn is-primary is-fullwidth" (click)="createPoll()" [disabled]="!pollService.form.valid">
|
||||||
|
<i class="fa fa-save"></i>
|
||||||
|
Enregistrer le sondage
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1 @@
|
|||||||
|
@import '../../../../../../styles/variables';
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StepFourComponent } from './step-four.component';
|
||||||
|
|
||||||
|
describe('StepFourComponent', () => {
|
||||||
|
let component: StepFourComponent;
|
||||||
|
let fixture: ComponentFixture<StepFourComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [StepFourComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(StepFourComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,35 @@
|
|||||||
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
import { PollService } from '../../../../../core/services/poll.service';
|
||||||
|
import { environment } from '../../../../../../environments/environment';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-step-four',
|
||||||
|
templateUrl: './step-four.component.html',
|
||||||
|
styleUrls: ['./step-four.component.scss'],
|
||||||
|
})
|
||||||
|
export class StepFourComponent implements OnInit {
|
||||||
|
urlPrefix: any;
|
||||||
|
advancedDisplayEnabled: boolean = environment.advanced_options_display;
|
||||||
|
@Input()
|
||||||
|
step_max: any;
|
||||||
|
@Input()
|
||||||
|
form: any;
|
||||||
|
|
||||||
|
constructor(private router: Router, public pollService: PollService) {
|
||||||
|
this.pollService.step_current = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
createPoll() {
|
||||||
|
this.pollService.createPoll().then(
|
||||||
|
(resp) => {
|
||||||
|
this.router.navigate(['administration/success']);
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.error('oops err', err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
<div class="step step-container">
|
||||||
|
<form class="min-height" [formGroup]="pollService.form">
|
||||||
|
<app-stepper [step_current]="1" [step_max]="5"></app-stepper>
|
||||||
|
<section class="poll-title">
|
||||||
|
<h2 class="title is-2">
|
||||||
|
{{ 'creation.choose_title' | translate }}
|
||||||
|
</h2>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div>
|
||||||
|
<label for="title">{{ 'creation.choose_title_label' | translate }}</label>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
class="input is-fullwidth"
|
||||||
|
#title
|
||||||
|
[placeholder]="'creation.choose_title_placeholder' | translate"
|
||||||
|
formControlName="title"
|
||||||
|
(keyup)="pollService.updateSlug()"
|
||||||
|
(blur)="pollService.updateSlug()"
|
||||||
|
id="title"
|
||||||
|
maxlength="140"
|
||||||
|
autofocus="autofocus"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<div class="poll-description">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<label for="descr">Description (optionnel)</label>
|
||||||
|
<!-- <div class="rich-text-toggle">-->
|
||||||
|
<!-- <label for="richTextMode">mode de saisie avancée</label>-->
|
||||||
|
|
||||||
|
<!-- <mat-checkbox formControlName="richTextMode" id="richTextMode"></mat-checkbox>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<div class="rich-toolbar" *ngIf="pollService.form.value.richTextMode">
|
||||||
|
richTextMode activé
|
||||||
|
</div>
|
||||||
|
<textarea
|
||||||
|
class="ui-inputtextarea is-fullwidth is-block"
|
||||||
|
#description
|
||||||
|
matInput
|
||||||
|
id="descr"
|
||||||
|
class="is-large is-full input"
|
||||||
|
placeholder="Description"
|
||||||
|
formControlName="description"
|
||||||
|
required
|
||||||
|
maxlength="300"
|
||||||
|
></textarea>
|
||||||
|
<div
|
||||||
|
class="text-info padded"
|
||||||
|
[ngClass]="{ 'has-background-warning': pollService.form.value.description.length === 300 }"
|
||||||
|
>
|
||||||
|
{{ pollService.form.value.description.length }} / 300 caractères maximum
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<button class="button is-warning is-fullwidth" [routerLink]="['/']">
|
||||||
|
Annuler
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<!-- [disabled]="form.invalid"-->
|
||||||
|
<button class="button is-primary is-fullwidth" [routerLink]="['/administration/step/2']">
|
||||||
|
Suivant
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StepOneComponent } from './step-one.component';
|
||||||
|
|
||||||
|
describe('StepOneComponent', () => {
|
||||||
|
let component: StepOneComponent;
|
||||||
|
let fixture: ComponentFixture<StepOneComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [StepOneComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(StepOneComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,27 @@
|
|||||||
|
import { Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
import { PollService } from '../../../../../core/services/poll.service';
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-step-one',
|
||||||
|
templateUrl: './step-one.component.html',
|
||||||
|
styleUrls: ['./step-one.component.scss'],
|
||||||
|
})
|
||||||
|
export class StepOneComponent implements OnInit {
|
||||||
|
constructor(public pollService: PollService, @Inject(DOCUMENT) private document: any) {}
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
step_max: any;
|
||||||
|
@Input()
|
||||||
|
form: FormGroup;
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.pollService.step_current = 1;
|
||||||
|
const selector = '#title';
|
||||||
|
const firstField = this.document.querySelector(selector);
|
||||||
|
if (firstField) {
|
||||||
|
firstField.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
<div class="step min-height">
|
||||||
|
<app-stepper [step_current]="3" [step_max]="5"></app-stepper>
|
||||||
|
<app-errors-list [form]="pollService.form"></app-errors-list>
|
||||||
|
<!-- choix spécialement pour les dates-->
|
||||||
|
<span class="count-dates title">
|
||||||
|
{{ pollService.calendar.length }}
|
||||||
|
</span>
|
||||||
|
<span> - {{ 'dates.count_dates' | translate }} </span>
|
||||||
|
|
||||||
|
<div class="calendar" *ngIf="mode_calendar">
|
||||||
|
<p-calendar
|
||||||
|
[(ngModel)]="pollService.calendar"
|
||||||
|
firstDayOfWeek="1"
|
||||||
|
selectionMode="multiple"
|
||||||
|
inputId="multiple"
|
||||||
|
showButtonBar="true"
|
||||||
|
[locale]="'calendar_widget' | translate"
|
||||||
|
[disabledDates]="pollService.disabled_dates"
|
||||||
|
[inline]="true"
|
||||||
|
[showWeek]="false"
|
||||||
|
></p-calendar>
|
||||||
|
</div>
|
||||||
|
<button class="button" (click)="mode_calendar = !mode_calendar" [ngClass]="{ 'is-primary': !mode_calendar }">
|
||||||
|
Saisir les dates manuellement
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="dates-list">
|
||||||
|
<div class="actions">
|
||||||
|
<button
|
||||||
|
(click)="pollService.addTime()"
|
||||||
|
*ngIf="false == pollService.allowSeveralHours"
|
||||||
|
class="button is-primary is-block is-fullwidth"
|
||||||
|
id="add_time_button"
|
||||||
|
>
|
||||||
|
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||||
|
{{ 'dates.add_time' | translate }}
|
||||||
|
</button>
|
||||||
|
<button class="button" (click)="pollService.allowSeveralHours = !pollService.allowSeveralHours">
|
||||||
|
Horaires différentes pour chaque jour
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
(click)="pollService.removeAllTimes()"
|
||||||
|
*ngIf="pollService.timeList.length && false == pollService.allowSeveralHours"
|
||||||
|
class="btn is-warning marged"
|
||||||
|
id="remove_time_button"
|
||||||
|
>
|
||||||
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||||
|
Aucune plage horaire
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
(click)="pollService.resetTimes()"
|
||||||
|
*ngIf="pollService.timeList.length && false == pollService.allowSeveralHours"
|
||||||
|
class="btn is-warning marged"
|
||||||
|
id="reset_time_button"
|
||||||
|
>
|
||||||
|
<i class="fa fa-refresh" aria-hidden="true"></i>
|
||||||
|
réinitialiser
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="title" *ngIf="pollService.timeList.length">
|
||||||
|
<span class="count-dates">
|
||||||
|
{{ pollService.timeList.length }}
|
||||||
|
</span>
|
||||||
|
<span class="count-dates-txt">
|
||||||
|
{{ 'dates.count_time' | translate }}
|
||||||
|
(pour chaque jour)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
*ngIf="pollService.timeList.length && false == pollService.allowSeveralHours"
|
||||||
|
class="marged padded identical-dates"
|
||||||
|
>
|
||||||
|
<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
|
||||||
|
<div *ngFor="let time of pollService.timeList; index as id" class="time-choice" cdkDrag>
|
||||||
|
<label for="timeChoices_{{ id }}">
|
||||||
|
<i class="fa fa-clock-o" aria-hidden="true"></i>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
[(ngModel)]="time.literal"
|
||||||
|
name="timeChoices_{{ id }}"
|
||||||
|
type="text"
|
||||||
|
id="timeChoices_{{ id }}"
|
||||||
|
/>
|
||||||
|
<button (click)="time.timeList.splice(id, 1)" class="btn btn-warning">
|
||||||
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<button class="button is-secondary is-fullwidth" [routerLink]="['/administration/step/2']">
|
||||||
|
précédent
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<!-- [disabled]="form.invalid"-->
|
||||||
|
<button class="button is-primary is-fullwidth" [routerLink]="['/administration/step/4']">
|
||||||
|
suivant
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,9 @@
|
|||||||
|
@import '../../../../../../styles/variables';
|
||||||
|
|
||||||
|
.ui-datepicker table td.ui-datepicker-today > a.ui-state-active,
|
||||||
|
.ui-datepicker table td.ui-datepicker-today > span.ui-state-active {
|
||||||
|
background-color: $primary-color !important;
|
||||||
|
}
|
||||||
|
.calendar {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StepThreeComponent } from './step-three.component';
|
||||||
|
|
||||||
|
describe('StepThreeComponent', () => {
|
||||||
|
let component: StepThreeComponent;
|
||||||
|
let fixture: ComponentFixture<StepThreeComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [StepThreeComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(StepThreeComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
import { PollService } from '../../../../../core/services/poll.service';
|
||||||
|
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-step-three',
|
||||||
|
templateUrl: './step-three.component.html',
|
||||||
|
styleUrls: ['./step-three.component.scss'],
|
||||||
|
})
|
||||||
|
export class StepThreeComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
step_max: any;
|
||||||
|
@Input()
|
||||||
|
form: any;
|
||||||
|
public mode_calendar = true;
|
||||||
|
|
||||||
|
constructor(public pollService: PollService) {
|
||||||
|
this.pollService.step_current = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
drop(event: CdkDragDrop<string[]>) {
|
||||||
|
// moveItemInArray(this.pollService.choices, event.previousIndex, event.currentIndex);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
<div class="step step-container form-field poll-kind">
|
||||||
|
<div class="min-height">
|
||||||
|
<app-stepper [step_current]="2" [step_max]="5"></app-stepper>
|
||||||
|
<app-errors-list [form]="pollService.form"></app-errors-list>
|
||||||
|
<h2 class="title is-2">
|
||||||
|
{{ 'creation.want' | translate }}
|
||||||
|
</h2>
|
||||||
|
<div class="container">
|
||||||
|
<div class="kind-of-poll columns">
|
||||||
|
<div class="column">
|
||||||
|
<button
|
||||||
|
class="button is-fullwidth"
|
||||||
|
[ngClass]="{ 'is-selected is-primary': pollService.form.controls.isAboutDate.value }"
|
||||||
|
(click)="pollService.form.controls.isAboutDate.setValue(true)"
|
||||||
|
>
|
||||||
|
<i class="fa fa-calendar"></i>
|
||||||
|
{{ 'creation.kind.date' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<button
|
||||||
|
class="button is-fullwidth"
|
||||||
|
[ngClass]="{ 'is-selected is-primary': !pollService.form.controls.isAboutDate.value }"
|
||||||
|
(click)="pollService.form.controls.isAboutDate.setValue(false)"
|
||||||
|
>
|
||||||
|
<i class="fa fa-list-ul"></i>
|
||||||
|
{{ 'creation.kind.classic' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<button class="button is-secondary is-fullwidth" [routerLink]="['/administration/step/1']">
|
||||||
|
précédent
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<!-- [disabled]="form.invalid"-->
|
||||||
|
<button class="button is-primary is-fullwidth" [routerLink]="['/administration/step/3']">
|
||||||
|
suivant
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,16 @@
|
|||||||
|
@import '../../../../../../styles/variables';
|
||||||
|
|
||||||
|
.kind-of-poll {
|
||||||
|
margin-top: 5em;
|
||||||
|
.fa {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
background: $d-grey;
|
||||||
|
border: solid white 1px;
|
||||||
|
&.is-selected {
|
||||||
|
border: solid $primary-color 1px;
|
||||||
|
color: $font_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StepTwoComponent } from './step-two.component';
|
||||||
|
|
||||||
|
describe('StepTwoComponent', () => {
|
||||||
|
let component: StepTwoComponent;
|
||||||
|
let fixture: ComponentFixture<StepTwoComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [StepTwoComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(StepTwoComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,62 @@
|
|||||||
|
import { ChangeDetectorRef, Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
|
import { FormArray, FormBuilder } from '@angular/forms';
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { CdkDragDrop } from '@angular/cdk/drag-drop';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { UuidService } from '../../../../../core/services/uuid.service';
|
||||||
|
import { ToastService } from '../../../../../core/services/toast.service';
|
||||||
|
import { PollService } from '../../../../../core/services/poll.service';
|
||||||
|
import { DateUtilitiesService } from '../../../../../core/services/date.utilities.service';
|
||||||
|
import { ApiService } from '../../../../../core/services/api.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-step-two',
|
||||||
|
templateUrl: './step-two.component.html',
|
||||||
|
styleUrls: ['./step-two.component.scss'],
|
||||||
|
})
|
||||||
|
export class StepTwoComponent implements OnInit {
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
form: any;
|
||||||
|
@Input()
|
||||||
|
step_max: any;
|
||||||
|
timeList: any;
|
||||||
|
allowSeveralHours: string;
|
||||||
|
dateList: any;
|
||||||
|
showDateInterval: boolean;
|
||||||
|
intervalDays: any;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private cd: ChangeDetectorRef,
|
||||||
|
private uuidService: UuidService,
|
||||||
|
private toastService: ToastService,
|
||||||
|
public pollService: PollService,
|
||||||
|
private router: Router,
|
||||||
|
public dateUtilities: DateUtilitiesService,
|
||||||
|
private apiService: ApiService,
|
||||||
|
@Inject(DOCUMENT) private document: any
|
||||||
|
) {
|
||||||
|
this.form = this.pollService.form;
|
||||||
|
this.pollService.step_current = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
addIntervalOfDates() {}
|
||||||
|
|
||||||
|
get choices(): FormArray {
|
||||||
|
return this.form.get('choices') as FormArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
addTime() {}
|
||||||
|
|
||||||
|
removeAllTimes() {}
|
||||||
|
|
||||||
|
resetTimes() {}
|
||||||
|
|
||||||
|
addChoice() {}
|
||||||
|
|
||||||
|
addTimeToDate(choice: any, id: number) {}
|
||||||
|
|
||||||
|
countDays() {}
|
||||||
|
}
|
@ -1,114 +1,55 @@
|
|||||||
<mat-vertical-stepper #stepper linear>
|
<section class="creation-stepper">
|
||||||
<mat-step [stepControl]="pollFormGroup" class="is-expanded">
|
<div class="shortcuts">
|
||||||
<form [formGroup]="pollFormGroup">
|
<a
|
||||||
<ng-template matStepLabel>Informations du sondage</ng-template>
|
class="shortcut"
|
||||||
<mat-form-field appearance="outline">
|
href="#"
|
||||||
<mat-label>Titre</mat-label>
|
[routerLink]="['/administration/step/1']"
|
||||||
<input #title matInput placeholder="Question posée, sujet" formControlName="title" required />
|
[ngClass]="{ 'is-active': pollService.step_current == 1 }"
|
||||||
</mat-form-field>
|
>1</a
|
||||||
|
|
||||||
<mat-form-field appearance="outline" class="is-flex">
|
|
||||||
<mat-label>Description</mat-label>
|
|
||||||
<textarea
|
|
||||||
#description
|
|
||||||
matInput
|
|
||||||
placeholder="Description"
|
|
||||||
formControlName="description"
|
|
||||||
required
|
|
||||||
></textarea>
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
*ngIf="description.value"
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="Clear"
|
|
||||||
(click)="description.value = ''"
|
|
||||||
>
|
>
|
||||||
<i class="fa fa-close"></i>
|
<a
|
||||||
</button>
|
class="shortcut"
|
||||||
</mat-form-field>
|
href="#"
|
||||||
<mat-form-field appearance="outline" class="is-flex">
|
[routerLink]="['/administration/step/2']"
|
||||||
<mat-label>Url pour les participants</mat-label>
|
[ngClass]="{ 'is-active': pollService.step_current == 2 }"
|
||||||
<span matPrefix>{{ urlPrefix }}</span>
|
>2</a
|
||||||
<input #slug matInput placeholder="Url" formControlName="slug" required />
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
*ngIf="slug.value"
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="Clear"
|
|
||||||
(click)="slug.value = ''"
|
|
||||||
>
|
>
|
||||||
<i class="fa fa-close"></i>
|
<a
|
||||||
</button>
|
class="shortcut"
|
||||||
</mat-form-field>
|
href="#"
|
||||||
<div>
|
[routerLink]="['/administration/step/3']"
|
||||||
<button mat-button matStepperNext>Next</button>
|
[ngClass]="{ 'is-active': pollService.step_current == 3 }"
|
||||||
</div>
|
>3</a
|
||||||
</form>
|
|
||||||
</mat-step>
|
|
||||||
|
|
||||||
<mat-step [stepControl]="configurationFormGroup">
|
|
||||||
<form [formGroup]="configurationFormGroup">
|
|
||||||
<ng-template matStepLabel>PollConfiguration du sondage</ng-template>
|
|
||||||
<mat-form-field appearance="outline" class="is-flex">
|
|
||||||
<mat-label>Nombre de jours avant expiration</mat-label>
|
|
||||||
<input
|
|
||||||
#expiracy
|
|
||||||
matInput
|
|
||||||
type="number"
|
|
||||||
placeholder="Nombre de jours avant expiration"
|
|
||||||
formControlName="expiracyNumberOfDays"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
*ngIf="expiracy.value"
|
|
||||||
matSuffix
|
|
||||||
mat-icon-button
|
|
||||||
aria-label="Clear"
|
|
||||||
(click)="expiracy.value = ''"
|
|
||||||
>
|
>
|
||||||
<i class="fa fa-close"></i>
|
<a
|
||||||
</button>
|
class="shortcut"
|
||||||
</mat-form-field>
|
href="#"
|
||||||
<mat-checkbox class="is-flex" formControlName="areResultsPublic">
|
[routerLink]="['/administration/step/4']"
|
||||||
Les participants pourront consulter les résultats
|
[ngClass]="{ 'is-active': pollService.step_current == 4 }"
|
||||||
</mat-checkbox>
|
>4</a
|
||||||
<mat-checkbox class="is-flex" formControlName="isAboutDate">
|
>
|
||||||
Les choix possibles concerneront des dates
|
<a
|
||||||
</mat-checkbox>
|
class="shortcut"
|
||||||
<mat-checkbox class="is-flex" formControlName="isProtectedByPassword">
|
href="#"
|
||||||
Le sondage sera protégé par un mot de passe
|
[routerLink]="['/administration/step/5']"
|
||||||
</mat-checkbox>
|
[ngClass]="{ 'is-active': pollService.step_current == 5 }"
|
||||||
<mat-checkbox class="is-flex" formControlName="isOwnerNotifiedByEmailOnNewVote">
|
>5</a
|
||||||
Vous recevrez un mail à chaque nouvelle participation
|
>
|
||||||
</mat-checkbox>
|
<!-- <a class="shortcut" href="#" [routerLink]="['/administration/step/6']" [ngClass]="{'is-active':pollService.step_current == 6}">6</a>-->
|
||||||
<mat-checkbox class="is-flex" formControlName="isOwnerNotifiedByEmailOnNewComment">
|
<!-- <a class="shortcut" href="#" [routerLink]="['/administration/step/7']" [ngClass]="{'is-active':pollService.step_current == 7}">7</a>-->
|
||||||
Vous recevrez un mail à chaque nouveau commentaire
|
|
||||||
</mat-checkbox>
|
|
||||||
<mat-checkbox class="is-flex" formControlName="isMaybeAnswerAvailable">
|
|
||||||
La réponse « peut-être » sera disponible
|
|
||||||
</mat-checkbox>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button mat-button matStepperPrevious>Back</button>
|
|
||||||
<button mat-button matStepperNext>Next</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="step-info">
|
||||||
</mat-step>
|
<h2 classs="title is-2" *ngIf="pollService.step_current == 1">
|
||||||
|
{{ 'creation.title' | translate }}
|
||||||
<mat-step>
|
</h2>
|
||||||
<ng-template matStepLabel>Done</ng-template>
|
<h2 class="title is-3" *ngIf="pollService.step_current > 1">
|
||||||
<p>You are now done.</p>
|
<span class="poll-title">
|
||||||
<div>
|
{{ pollService.form.value.title }}
|
||||||
<button mat-button matStepperPrevious>Back</button>
|
</span>
|
||||||
<button mat-button (click)="stepper.reset()">Reset</button>
|
</h2>
|
||||||
|
<h3 class="title is-2">Étape {{ step_current }} sur {{ step_max }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="step-bar-container" style="width: 100%;">
|
||||||
<button mat-button (click)="savePoll()" [disabled]="!pollFormGroup.valid || !configurationFormGroup.valid">
|
<div class="step-bar-progress" [ngStyle]="{ width: (step_current / step_max) * 100 + '%' }"></div>
|
||||||
Enregistrer le sondage
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</mat-step>
|
</section>
|
||||||
</mat-vertical-stepper>
|
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
@import '../../../../styles/variables';
|
||||||
|
|
||||||
|
.step-bar-container {
|
||||||
|
margin: 1em 0;
|
||||||
|
height: 0.5em;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 1px;
|
||||||
|
background: $border-color !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.step-bar-progress {
|
||||||
|
position: relative;
|
||||||
|
top: -0.6em;
|
||||||
|
left: 0;
|
||||||
|
height: 0.5em;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 1px;
|
||||||
|
background: $primary_color;
|
||||||
|
}
|
||||||
|
.shortcut {
|
||||||
|
background: $dark-lavender;
|
||||||
|
color: white;
|
||||||
|
padding: 1em;
|
||||||
|
margin: 1em;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 100%;
|
||||||
|
text-align: center;
|
||||||
|
width: 4em;
|
||||||
|
&.is-active {
|
||||||
|
background: $font_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.poll-title {
|
||||||
|
color: $d-neutral;
|
||||||
|
}
|
@ -1,55 +1,17 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { PollService } from '../../../core/services/poll.service';
|
||||||
|
import { environment } from '../../../../environments/environment';
|
||||||
import { Poll } from '../../../core/models/poll.model';
|
|
||||||
import { UuidService } from '../../../core/services/uuid.service';
|
|
||||||
import { DateService } from '../../../core/services/date.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-stepper',
|
selector: 'app-stepper',
|
||||||
templateUrl: './stepper.component.html',
|
templateUrl: './stepper.component.html',
|
||||||
styleUrls: ['./stepper.component.scss'],
|
styleUrls: ['./stepper.component.scss'],
|
||||||
})
|
})
|
||||||
export class StepperComponent implements OnInit {
|
export class StepperComponent {
|
||||||
@Input()
|
@Input()
|
||||||
public poll?: Poll;
|
public step_current: number = 1;
|
||||||
|
@Input()
|
||||||
public pollFormGroup: FormGroup;
|
public step_max: number = 5;
|
||||||
public configurationFormGroup: FormGroup;
|
public show_shortcuts = environment.showStepperShortcuts;
|
||||||
public choicesFormGroup: FormGroup;
|
constructor(public pollService: PollService) {}
|
||||||
|
|
||||||
public urlPrefix = '/participation/';
|
|
||||||
|
|
||||||
constructor(private fb: FormBuilder, private uuidService: UuidService) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.pollFormGroup = this.fb.group({
|
|
||||||
question: [this.poll ? this.poll.title : '', [Validators.required]],
|
|
||||||
slug: [this.poll ? this.poll.custom_url : this.uuidService.getUUID(), [Validators.required]],
|
|
||||||
description: [this.poll ? this.poll.description : ''],
|
|
||||||
});
|
|
||||||
|
|
||||||
this.configurationFormGroup = this.fb.group({
|
|
||||||
title: [this.poll ? this.poll : false, [Validators.required]],
|
|
||||||
isAboutDate: [this.poll ? this.poll.kind === 'date' : false, [Validators.required]],
|
|
||||||
isProtectedByPassword: [this.poll ? this.poll.password.length : false, [Validators.required]],
|
|
||||||
isOwnerNotifiedByEmailOnNewVote: [
|
|
||||||
this.poll ? this.poll.isOwnerNotifiedByEmailOnNewVote : false,
|
|
||||||
[Validators.required],
|
|
||||||
],
|
|
||||||
isOwnerNotifiedByEmailOnNewComment: [
|
|
||||||
this.poll ? this.poll.isOwnerNotifiedByEmailOnNewComment : false,
|
|
||||||
[Validators.required],
|
|
||||||
],
|
|
||||||
areResultsPublic: [this.poll ? this.poll.areResultsPublic : true, [Validators.required]],
|
|
||||||
expiracyNumberOfDays: [this.poll ? this.poll.default_expiracy_days_from_now : '60', [Validators.required]],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public savePoll(): void {
|
|
||||||
if (this.pollFormGroup.valid && this.configurationFormGroup.valid) {
|
|
||||||
console.log('Le sondage est correctement rempli, prêt à enregistrer.');
|
|
||||||
// TODO : save the poll
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,89 +1,108 @@
|
|||||||
<section class="hero is-medium is-success">
|
<section
|
||||||
|
class="hero is-medium"
|
||||||
|
[ngClass]="{ 'has-background-success': pollService.admin_key, 'has-background-danger': pollService.admin_key }"
|
||||||
|
>
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
<div class="container has-text-centered">
|
<div class="container has-text-centered">
|
||||||
<div class="main-block">
|
<div class="main-block">
|
||||||
<h1 class="title is-1">🎉 {{ 'resume.title' | translate }}</h1>
|
<h1 class="title is-1" *ngIf="pollService.admin_key">🎉 {{ 'resume.title' | translate }}</h1>
|
||||||
<h2 class="subtitle">
|
<h2 class="subtitle">
|
||||||
Votre sondage «
|
Votre sondage
|
||||||
|
<br />
|
||||||
|
«
|
||||||
<strong class="poll-title">
|
<strong class="poll-title">
|
||||||
{{ poll.title }}
|
{{ pollService.form.value.title }}
|
||||||
</strong>
|
</strong>
|
||||||
» a bien été créé !
|
»
|
||||||
|
<span *ngIf="!pollService.admin_key">
|
||||||
|
n'a pas été créé :(
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<button class="button is-primary" [routerLink]="['/administration/step/4']">
|
||||||
|
Revenir en arrière
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<span *ngIf="pollService.admin_key">
|
||||||
|
a bien été créé !
|
||||||
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div class="container padded">
|
<div class="container padded">
|
||||||
<div class="has-text-centered">
|
<div class=" ">
|
||||||
<div class="main-block">
|
<div class="main-block">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
<div class="admin">
|
<div class="admin">
|
||||||
|
<div class="no-admin-key padded has-background-danger" *ngIf="!pollService.admin_key">
|
||||||
|
Pas de clé d'administration, l'enregistrement du sondage a échoué. vérifiez vos paramètres
|
||||||
|
réseau.
|
||||||
|
</div>
|
||||||
|
<div class="admin-ok" *ngIf="pollService.admin_key">
|
||||||
<h2 class="title is-2">
|
<h2 class="title is-2">
|
||||||
|
<i class="fa fa-gears"></i>
|
||||||
{{ 'resume.admins' | translate }}
|
{{ 'resume.admins' | translate }}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Voici les liens d’accès au sondage, conservez-les soigneusement ! (Si vous les perdez vous pourrez
|
Voici les liens d’accès au sondage, conservez-les soigneusement ! (Si vous les perdez
|
||||||
toujours les recevoir par email)
|
vous pourrez toujours les recevoir par email)
|
||||||
</p>
|
</p>
|
||||||
<h2 class="title is-2">
|
<div>
|
||||||
Côté admin
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
Pour accéder au sondage et à tous ses paramètres :
|
Pour accéder au sondage et à tous ses paramètres :
|
||||||
<br />
|
<br />
|
||||||
<a class="button is-info" routerLink="/admin/{{ poll.admin_key }}"
|
<pre class="is-default" routerLink="{{ pollService.getAdministrationUrlFromForm() }}"
|
||||||
>{{ pollService.getAdministrationUrl() }}
|
>{{ pollService.getAdministrationUrlFromForm() }}
|
||||||
</a>
|
</pre
|
||||||
<app-copy-text [textToCopy]="pollService.getAdministrationUrl()"></app-copy-text>
|
>
|
||||||
</p>
|
<app-copy-text
|
||||||
|
[textToCopy]="pollService.getAdministrationUrlFromForm()"
|
||||||
|
></app-copy-text>
|
||||||
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<a class="button is-info" [href]="pollService.getAdministrationUrl()">
|
<a class="button is-info" [href]="pollService.getAdministrationUrlFromForm()">
|
||||||
Voir le sondage coté administrateur·ice
|
Voir le sondage coté administrateur·ice
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<p class="note">
|
<p class="note has-background-info padded">
|
||||||
Note : Le sondage sera supprimé {{ poll.default_expiracy_days_from_now }} jours après la date de sa
|
<i class="fa fa-info-circle"></i> Note : Le sondage sera supprimé
|
||||||
dernière modification.
|
<strong> {{ pollService.form.value.expiresDaysDelay }} </strong> jours après la date de
|
||||||
<span class="expiracy-detail" *ngIf="poll.expiracy_date">
|
sa dernière modification.
|
||||||
Le {{ poll.expiracy_date | date: 'short' }}
|
<span class="expiracy-detail" *ngIf="pollService.form.value.expiresDaysDelay">
|
||||||
|
Le
|
||||||
|
{{
|
||||||
|
pollService.DateUtilitiesService.addDaysToDate(
|
||||||
|
pollService.form.value.expiresDaysDelay,
|
||||||
|
today
|
||||||
|
) | date: 'short'
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="public">
|
</div>
|
||||||
<h2 class="title is-2" i18n>{{ 'resume.users' | translate }}</h2>
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="public" *ngIf="pollService.admin_key">
|
||||||
|
<h2 class="title is-2">
|
||||||
|
<i class="fa fa-ellipsis-v"></i>
|
||||||
|
{{ 'resume.users' | translate }}
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
Pour voir le sondage :
|
Pour voir le sondage :
|
||||||
<br />
|
<br />
|
||||||
<a class="button is-info" routerLink="/poll/{{ poll.custom_url }}/consultation"
|
<a class="button is-info" [href]="pollService.getParticipationUrlFromForm()"
|
||||||
>{{ pollService.getParticipationUrl() }}
|
>{{ pollService.getParticipationUrlFromForm() }}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<app-copy-text [textToCopy]="pollService.getParticipationUrl()"></app-copy-text>
|
<app-copy-text [textToCopy]="pollService.getParticipationUrlFromForm()"></app-copy-text>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<!-- <img src="assets/img/undraw_group_selfie_ijc6.svg" alt="image succès" />-->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<section class="mail">
|
|
||||||
<h2 i18n>{{ 'resume.links_mail' | translate }}</h2>
|
|
||||||
<p>
|
|
||||||
<label for="email">
|
|
||||||
Pour être sûr de retrouver ces liens, nous pouvons vous les envoyer sur votre mail :
|
|
||||||
</label>
|
|
||||||
<br />
|
|
||||||
<input type="email" id="email" name="email" [(ngModel)]="poll.creatorEmail" placeholder="email" />
|
|
||||||
<br />
|
|
||||||
<button class="btn btn--primary" (click)="sendToEmail()">
|
|
||||||
Envoyer les liens du sondage
|
|
||||||
<i class="fa fa-paper-plane" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<a class="button is-info" href="{{ poll.custom_url }}">
|
|
||||||
Voir le sondage côté public
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
@import './src/styles/variables';
|
||||||
|
|
||||||
.button,
|
.button,
|
||||||
a,
|
a,
|
||||||
button {
|
button {
|
||||||
@ -5,6 +7,7 @@ button {
|
|||||||
margin-right: 1ch;
|
margin-right: 1ch;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
|
padding: 1em;
|
||||||
max-width: 20em;
|
max-width: 20em;
|
||||||
@extend .truncate;
|
@extend .truncate;
|
||||||
}
|
}
|
||||||
@ -13,3 +16,9 @@ a {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
:host {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
.has-background-success {
|
||||||
|
background: $logo_color_2 !important;
|
||||||
|
}
|
||||||
|
@ -15,12 +15,14 @@ export class SuccessComponent {
|
|||||||
mailToRecieve: string;
|
mailToRecieve: string;
|
||||||
window: any = window;
|
window: any = window;
|
||||||
environment = environment;
|
environment = environment;
|
||||||
|
today: Date = new Date();
|
||||||
constructor(public pollService: PollService, private dateUtils: DateUtilitiesService, private titleService: Title) {
|
constructor(public pollService: PollService, private dateUtils: DateUtilitiesService, private titleService: Title) {
|
||||||
this.titleService.setTitle(environment.appTitle + ' - 🎉 succès de création de sondage -');
|
this.titleService.setTitle(
|
||||||
|
environment.appTitle + ' - 🎉 succès de création de sondage - ' + this.pollService.form.value.title
|
||||||
|
);
|
||||||
|
|
||||||
this.pollService.poll.subscribe((newpoll: Poll) => {
|
this.pollService.poll.subscribe((newpoll: Poll) => {
|
||||||
this.poll = newpoll;
|
this.poll = newpoll;
|
||||||
// this.poll.expiracy_date = this.getExpiracyDateFromPoll(this.poll);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import { PasswordPromptComponent } from './password/password-prompt/password-pro
|
|||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: 'secure/:pass_hash', component: ConsultationComponent },
|
{ path: 'secure/:pass_hash', component: ConsultationComponent },
|
||||||
|
|
||||||
{ path: 'prompt', component: PasswordPromptComponent },
|
{ path: 'prompt', component: PasswordPromptComponent },
|
||||||
{ path: 'simple', component: WipTodoComponent },
|
{ path: 'simple', component: WipTodoComponent },
|
||||||
{ path: 'table', component: WipTodoComponent },
|
{ path: 'table', component: WipTodoComponent },
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="message is-warning" *ngIf="poll && poll.admin_key">
|
<div class="message is-warning" *ngIf="poll && poll.admin_key">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
vous êtes admin de ce sondage
|
vous êtes admin de ce sondage et pouvez le modifier
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -60,15 +60,15 @@ export class ConsultationComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
console.log('this.pass_hash ', this.pass_hash);
|
console.log('this.pass_hash ', this.pass_hash);
|
||||||
if (this.pass_hash) {
|
if (this.pass_hash) {
|
||||||
this.pollService.loadPollBycustom_urlWithPasswordHash(this.pollSlug, this.pass_hash).then((resp) => {
|
this.pollService.loadPollByCustomUrlWithPasswordHash(this.pollSlug, this.pass_hash).then((resp) => {
|
||||||
console.log('resp', resp);
|
console.log('loadPollByCustomUrlWithPasswordHash resp', resp);
|
||||||
this.fetching = false;
|
this.fetching = false;
|
||||||
this.storageService.vote_stack.id = null;
|
this.storageService.vote_stack.id = null;
|
||||||
this.storageService.setChoicesForVoteStack(this.pollService._poll.getValue().choices);
|
this.storageService.setChoicesForVoteStack(this.pollService._poll.getValue().choices);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.pollService.loadPollBycustom_url(this.pollSlug).then((resp) => {
|
this.pollService.loadPollByCustomUrl(this.pollSlug).then((resp) => {
|
||||||
console.log('resp', resp);
|
console.log('loadPollByCustomUrl resp', resp);
|
||||||
this.fetching = false;
|
this.fetching = false;
|
||||||
this.storageService.vote_stack.id = null;
|
this.storageService.vote_stack.id = null;
|
||||||
this.storageService.setChoicesForVoteStack(this.pollService._poll.getValue().choices);
|
this.storageService.setChoicesForVoteStack(this.pollService._poll.getValue().choices);
|
||||||
@ -131,9 +131,9 @@ export class ConsultationComponent implements OnInit, OnDestroy {
|
|||||||
this.storageService.mapVotes(voteStack.data);
|
this.storageService.mapVotes(voteStack.data);
|
||||||
this.pollService.enrichVoteStackWithCurrentPollChoicesDefaultVotes(this.storageService.vote_stack);
|
this.pollService.enrichVoteStackWithCurrentPollChoicesDefaultVotes(this.storageService.vote_stack);
|
||||||
if (this.pass_hash) {
|
if (this.pass_hash) {
|
||||||
this.pollService.loadPollBycustom_urlWithPasswordHash(this.poll.custom_url, this.pass_hash);
|
this.pollService.loadPollByCustomUrlWithPasswordHash(this.poll.custom_url, this.pass_hash);
|
||||||
} else {
|
} else {
|
||||||
this.pollService.loadPollBycustom_url(this.poll.custom_url);
|
this.pollService.loadPollByCustomUrl(this.poll.custom_url);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.toastService.display('erreur à l enregistrement');
|
this.toastService.display('erreur à l enregistrement');
|
||||||
|
@ -9,6 +9,8 @@ import { PollResultsCompactComponent } from './poll-results-compact/poll-results
|
|||||||
import { PollResultsDetailedComponent } from './poll-results-detailed/poll-results-detailed.component';
|
import { PollResultsDetailedComponent } from './poll-results-detailed/poll-results-detailed.component';
|
||||||
import { ChoiceButtonComponent } from '../../shared/components/choice-item/choice-button.component';
|
import { ChoiceButtonComponent } from '../../shared/components/choice-item/choice-button.component';
|
||||||
import { PasswordPromptComponent } from './password/password-prompt/password-prompt.component';
|
import { PasswordPromptComponent } from './password/password-prompt/password-prompt.component';
|
||||||
|
import { ChoiceDetailsComponent } from '../../shared/components/choice-details/choice-details.component';
|
||||||
|
import { CoreModule } from '../../core/core.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
@import '../../../../styles/variables';
|
@import '../../../../styles/variables';
|
||||||
|
|
||||||
.box {
|
.box {
|
||||||
border-left: 3px solid white;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
* {
|
* {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -77,11 +77,11 @@ export class PollResultsDetailedComponent {
|
|||||||
if (voteStack.status == 200) {
|
if (voteStack.status == 200) {
|
||||||
this.storageService.mapVotes(voteStack.data);
|
this.storageService.mapVotes(voteStack.data);
|
||||||
this.pollService.enrichVoteStackWithCurrentPollChoicesDefaultVotes(this.storageService.vote_stack);
|
this.pollService.enrichVoteStackWithCurrentPollChoicesDefaultVotes(this.storageService.vote_stack);
|
||||||
// if (this.pass_hash) {
|
if (this.pollService.pass_hash) {
|
||||||
// this.pollService.loadPollBycustom_urlWithPasswordHash(this.poll.custom_url, this.pass_hash);
|
this.pollService.loadPollByCustomUrlWithPasswordHash(this.poll.custom_url, this.pollService.pass_hash);
|
||||||
// } else {
|
} else {
|
||||||
this.pollService.loadPollBycustom_url(this.poll.custom_url);
|
this.pollService.loadPollByCustomUrl(this.poll.custom_url);
|
||||||
// }
|
}
|
||||||
} else {
|
} else {
|
||||||
this.toastService.display('erreur à l enregistrement');
|
this.toastService.display('erreur à l enregistrement');
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<div
|
<div
|
||||||
class="validation-error-list padded"
|
class="validation-error-list padded"
|
||||||
|
*ngIf="(form.valid && !hide_on_valid) || !form.valid"
|
||||||
[ngClass]="{ 'has-background-warning': totalErrors > 0, 'has-background-success': totalErrors === 0 }"
|
[ngClass]="{ 'has-background-warning': totalErrors > 0, 'has-background-success': totalErrors === 0 }"
|
||||||
>
|
>
|
||||||
<h1 class="title is-1">
|
<h1 class="title is-1">
|
||||||
@ -24,4 +25,10 @@
|
|||||||
{{ m }}
|
{{ m }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="debug" *ngIf="!environment.production">
|
||||||
|
<pre>
|
||||||
|
{{ messages | json }}
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,3 +7,6 @@
|
|||||||
color: white;
|
color: white;
|
||||||
border: solid 2px white;
|
border: solid 2px white;
|
||||||
}
|
}
|
||||||
|
.validation-error-list {
|
||||||
|
margin: 2em;
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Component, Inject, Input, OnInit } from '@angular/core';
|
import { Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
import { FormGroup, ValidationErrors } from '@angular/forms';
|
import { FormGroup, ValidationErrors } from '@angular/forms';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { environment } from '../../../../../../../environments/environment';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-errors-list',
|
selector: 'app-errors-list',
|
||||||
@ -12,6 +13,8 @@ export class ErrorsListComponent implements OnInit {
|
|||||||
public totalErrors = 0;
|
public totalErrors = 0;
|
||||||
public firstErrorId = '';
|
public firstErrorId = '';
|
||||||
public messages = [];
|
public messages = [];
|
||||||
|
public hide_on_valid = true;
|
||||||
|
public environment = environment;
|
||||||
|
|
||||||
constructor(@Inject(DOCUMENT) private document: any) {}
|
constructor(@Inject(DOCUMENT) private document: any) {}
|
||||||
|
|
||||||
|
@ -20,13 +20,6 @@ export const routes: Routes = [
|
|||||||
data: { animation: 'AdminPage' },
|
data: { animation: 'AdminPage' },
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./features/administration/administration.module').then((m) => m.AdministrationModule),
|
import('./features/administration/administration.module').then((m) => m.AdministrationModule),
|
||||||
// resolve: { poll: PollService },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'admin/:admin_key',
|
|
||||||
loadChildren: () =>
|
|
||||||
import('./features/administration/administration.module').then((m) => m.AdministrationModule),
|
|
||||||
// resolve: { poll: PollService },
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'poll/:custom_url/consultation',
|
path: 'poll/:custom_url/consultation',
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
<section class="hero is-warning is-medium">
|
<section class="hero is-warning is-medium">
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="title has-text-centered">
|
<h1 class="title has-text-centered">o_O {{ message | translate }}</h1>
|
||||||
{{ message | translate }}
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
"home": {
|
"home": {
|
||||||
"title": "Bienvenue sur",
|
"title": "Bienvenue sur",
|
||||||
"subtitle": "Se consulter simplement pour s’organiser collectivement.",
|
"subtitle": "Se consulter simplement pour s’organiser collectivement.",
|
||||||
"search_title": "Où sont mes sondages? ",
|
"search_title": "Vous avez déjà créé un sondage et vous souhaitez y accéder ?",
|
||||||
|
"search_subtitle": "Saisissez votre adresse e-mail et nous vous enverrons le lien vers votre sondage. ",
|
||||||
"create_button": "Créer un nouveau sondage ",
|
"create_button": "Créer un nouveau sondage ",
|
||||||
"search_button": "Rechercher"
|
"search_button": "Rechercher"
|
||||||
},
|
},
|
||||||
@ -27,13 +28,14 @@
|
|||||||
},
|
},
|
||||||
"creation": {
|
"creation": {
|
||||||
"title": "Créer un sondage",
|
"title": "Créer un sondage",
|
||||||
"want": "Je veux créer un sondage",
|
"want": "Choisissez le type de sondage",
|
||||||
"advanced": "Options avancées",
|
"advanced": "Options avancées",
|
||||||
"kind": {
|
"kind": {
|
||||||
"classic": "classique",
|
"classic": "Propositions",
|
||||||
"date": "spécial dates"
|
"date": "Date"
|
||||||
},
|
},
|
||||||
"choose_title": "Dont le titre sera",
|
"choose_title": "Renseignez un nom pour votre sondage",
|
||||||
|
"choose_title_label": "Nom de votre sondage (obligatoire)",
|
||||||
"choose_title_placeholder": "titre",
|
"choose_title_placeholder": "titre",
|
||||||
"choices_hint": "Utilisez les flèches haut ⬆️ et bas ⬇️ pour passer d'un choix à un autre",
|
"choices_hint": "Utilisez les flèches haut ⬆️ et bas ⬇️ pour passer d'un choix à un autre",
|
||||||
"name": "Je peux aussi préciser mon nom si je le souhaite",
|
"name": "Je peux aussi préciser mon nom si je le souhaite",
|
||||||
@ -72,7 +74,7 @@
|
|||||||
"continue": "Voyons ce que ça donne"
|
"continue": "Voyons ce que ça donne"
|
||||||
},
|
},
|
||||||
"resume": {
|
"resume": {
|
||||||
"title": "Et c'est tout pour nous !",
|
"title": "Félicitations !",
|
||||||
"admins": "Côté administrateur-ice-eux",
|
"admins": "Côté administrateur-ice-eux",
|
||||||
"users": "Côté sondés",
|
"users": "Côté sondés",
|
||||||
"links_mail": "Recevoir les liens par e-mail"
|
"links_mail": "Recevoir les liens par e-mail"
|
||||||
@ -145,6 +147,7 @@
|
|||||||
"lang": "Sélectionner la langue"
|
"lang": "Sélectionner la langue"
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"required": "champ requis",
|
||||||
"You must enter a value": "You must enter a EEEE"
|
"You must enter a value": "You must enter a EEEE"
|
||||||
},
|
},
|
||||||
"You must enter a value": "You must enter a valueeeeeeee",
|
"You must enter a value": "You must enter a valueeeeeeee",
|
||||||
@ -576,8 +579,7 @@
|
|||||||
"the-administrator-locked-this-poll-votes-and-comments-are-frozen-it-is-no-longer-possible-to-partici": "L'administrateur·rice a verrouillé ce sondage. Les votes et commentaires sont gelés, il n'est plus possible de participer",
|
"the-administrator-locked-this-poll-votes-and-comments-are-frozen-it-is-no-longer-possible-to-partici": "L'administrateur·rice a verrouillé ce sondage. Les votes et commentaires sont gelés, il n'est plus possible de participer",
|
||||||
"the-poll-has-expired-it-will-soon-be-deleted": "Le sondage a expiré, il sera bientôt supprimé.",
|
"the-poll-has-expired-it-will-soon-be-deleted": "Le sondage a expiré, il sera bientôt supprimé.",
|
||||||
"your-vote-has-been-saved-but-please-note-you-need-to-keep-this-personalised-link-to-be-able-to-edit-": "Votre vote a bien été pris en compte, mais faites attention : ce sondage n'autorise l'édition de votre vote qu'avec le lien personnalisé suivant ; conservez-le précieusement !"
|
"your-vote-has-been-saved-but-please-note-you-need-to-keep-this-personalised-link-to-be-able-to-edit-": "Votre vote a bien été pris en compte, mais faites attention : ce sondage n'autorise l'édition de votre vote qu'avec le lien personnalisé suivant ; conservez-le précieusement !"
|
||||||
}
|
},
|
||||||
,
|
|
||||||
"LANGUAGES": {
|
"LANGUAGES": {
|
||||||
"DE": "Allemand",
|
"DE": "Allemand",
|
||||||
"FR": "Français",
|
"FR": "Français",
|
||||||
@ -594,7 +596,7 @@
|
|||||||
"SV": "sv"
|
"SV": "sv"
|
||||||
},
|
},
|
||||||
"calendar_widget": {
|
"calendar_widget": {
|
||||||
"startsWith": "Starts with",
|
"startsWith": "Commence par",
|
||||||
"contains": "Contains",
|
"contains": "Contains",
|
||||||
"notContains": "Not contains",
|
"notContains": "Not contains",
|
||||||
"endsWith": "Ends with",
|
"endsWith": "Ends with",
|
||||||
@ -605,26 +607,76 @@
|
|||||||
"lte": "Less than or equal to",
|
"lte": "Less than or equal to",
|
||||||
"gt": "Greater than",
|
"gt": "Greater than",
|
||||||
"gte": "Great then or equals",
|
"gte": "Great then or equals",
|
||||||
"is": "Is",
|
"is": "Est",
|
||||||
"isNot": "Is not",
|
"isNot": "N'est pas",
|
||||||
"before": "Before",
|
"before": "Avant",
|
||||||
"after": "After",
|
"after": "Après",
|
||||||
"clear": "Clear",
|
"clear": "Vider",
|
||||||
"apply": "Apply",
|
"apply": "Appliquer",
|
||||||
"matchAll": "Match All",
|
"matchAll": "Match All",
|
||||||
"matchAny": "Match Any",
|
"matchAny": "Match Any",
|
||||||
"addRule": "Add Rule",
|
"addRule": "Add Rule",
|
||||||
"removeRule": "Remove Rule",
|
"removeRule": "Remove Rule",
|
||||||
"accept": "Yes",
|
"accept": "Oui",
|
||||||
"reject": "No",
|
"reject": "Non",
|
||||||
"choose": "Choose",
|
"choose": "Choisir",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"cancel": "Cancel",
|
"cancel": "Annuler",
|
||||||
"dayNames": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
"dayNames": [
|
||||||
"dayNamesShort": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
|
"Sunday",
|
||||||
"dayNamesMin": ["Su","Mo","Tu","We","Th","Fr","Sa"],
|
"Monday",
|
||||||
"monthNames": ["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],
|
"Tuesday",
|
||||||
"monthNamesShort": ["Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
"Wednesday",
|
||||||
|
"Thursday",
|
||||||
|
"Friday",
|
||||||
|
"Saturday"
|
||||||
|
],
|
||||||
|
"dayNamesShort": [
|
||||||
|
"Dim",
|
||||||
|
"Lun",
|
||||||
|
"Mar",
|
||||||
|
"Mer",
|
||||||
|
"Jeu",
|
||||||
|
"Ven",
|
||||||
|
"Sam"
|
||||||
|
],
|
||||||
|
"dayNamesMin": [
|
||||||
|
"Di",
|
||||||
|
"Lu",
|
||||||
|
"Ma",
|
||||||
|
"Me",
|
||||||
|
"Je",
|
||||||
|
"Ve",
|
||||||
|
"Sa"
|
||||||
|
],
|
||||||
|
"monthNames": [
|
||||||
|
"Janvier",
|
||||||
|
"Février",
|
||||||
|
"Mars",
|
||||||
|
"Avril",
|
||||||
|
"Mai",
|
||||||
|
"Juin",
|
||||||
|
"Juillet",
|
||||||
|
"Août",
|
||||||
|
"Septembre",
|
||||||
|
"Octobre",
|
||||||
|
"Novembre",
|
||||||
|
"Décembre"
|
||||||
|
],
|
||||||
|
"monthNamesShort": [
|
||||||
|
"Jan",
|
||||||
|
"Feb",
|
||||||
|
"Mar",
|
||||||
|
"Apr",
|
||||||
|
"May",
|
||||||
|
"Jun",
|
||||||
|
"Jul",
|
||||||
|
"Aug",
|
||||||
|
"Sep",
|
||||||
|
"Oct",
|
||||||
|
"Nov",
|
||||||
|
"Dec"
|
||||||
|
],
|
||||||
"today": "Aujourd'hui",
|
"today": "Aujourd'hui",
|
||||||
"weekHeader": "Wk"
|
"weekHeader": "Wk"
|
||||||
}
|
}
|
||||||
|
BIN
src/assets/img/icone_home.png
Normal file
BIN
src/assets/img/icone_home.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
BIN
src/assets/img/where-is-it.jpg
Normal file
BIN
src/assets/img/where-is-it.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 89 KiB |
@ -1,15 +1,15 @@
|
|||||||
export const backendApiUrlsInDev = {
|
export const backendApiUrlsInDev = {
|
||||||
// local: 'http://tktest.lan/api/v1',
|
// local: 'http://tktest.lan/api/v1',
|
||||||
// remote: 'http://tktest.lan/api/v1',
|
// remote: 'http://tktest.lan/api/v1',
|
||||||
// local: 'https://localhost:8000/api/v1',
|
local: 'http://localhost:8000/api/v1',
|
||||||
local: 'https://framadate-api.cipherbliss.com/api/v1',
|
// local: 'https://framadate-api.cipherbliss.com/api/v1',
|
||||||
// remote: 'https://localhost:8000/api/v1',
|
remote: 'http://localhost:8000/api/v1',
|
||||||
remote: 'https://framadate-api.cipherbliss.com/api/v1',
|
// remote: 'https://framadate-api.cipherbliss.com/api/v1',
|
||||||
};
|
};
|
||||||
export const apiV1 = {
|
export const apiV1 = {
|
||||||
// baseHref: 'https://localhost:8000/api/v1',
|
baseHref: 'http://localhost:8000/api/v1',
|
||||||
// baseHref: 'http://tktest.lan/api/v1',
|
// baseHref: 'http://tktest.lan/api/v1',
|
||||||
baseHref: 'https://framadate-api.cipherbliss.com/api/v1',
|
// baseHref: 'https://framadate-api.cipherbliss.com/api/v1',
|
||||||
api_new_poll: '/poll/',
|
api_new_poll: '/poll/',
|
||||||
api_get_poll: '/poll/{id}',
|
api_get_poll: '/poll/{id}',
|
||||||
api_new_vote_stack: '/vote-stack',
|
api_new_vote_stack: '/vote-stack',
|
||||||
|
@ -16,9 +16,12 @@ export const environment = {
|
|||||||
production: true,
|
production: true,
|
||||||
display_routes: true,
|
display_routes: true,
|
||||||
showDemoWarning: true,
|
showDemoWarning: true,
|
||||||
autofill: false,
|
autofill_creation: true,
|
||||||
|
autofill_participation: true,
|
||||||
|
advanced_options_display: false,
|
||||||
autoSendNewPoll: false,
|
autoSendNewPoll: false,
|
||||||
interval_days_default: 7,
|
interval_days_default: 7,
|
||||||
|
showStepperShortcuts: true,
|
||||||
expiresDaysDelay: 60,
|
expiresDaysDelay: 60,
|
||||||
maxCountOfAnswers: 150,
|
maxCountOfAnswers: 150,
|
||||||
appTitle: 'FramaDate Funky',
|
appTitle: 'FramaDate Funky',
|
||||||
|
@ -10,15 +10,19 @@ endpoints.baseHref = apiV1.baseHref;
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
frontDomain: 'http://127.0.0.1:4200',
|
frontDomain: 'http://127.0.0.1:4200',
|
||||||
production: false,
|
production: false,
|
||||||
display_routes: true,
|
display_routes: true, // demo paths to test polls
|
||||||
autofill: true,
|
autofill_creation: true,
|
||||||
|
advanced_options_display: true,
|
||||||
|
autofill_participation: true,
|
||||||
// autofill: false,
|
// autofill: false,
|
||||||
showDemoWarning: true,
|
showDemoWarning: false,
|
||||||
|
// autoSendNewPoll: true,
|
||||||
autoSendNewPoll: false,
|
autoSendNewPoll: false,
|
||||||
|
showStepperShortcuts: true,
|
||||||
interval_days_default: 7,
|
interval_days_default: 7,
|
||||||
expiresDaysDelay: 60,
|
expiresDaysDelay: 60,
|
||||||
maxCountOfAnswers: 150,
|
maxCountOfAnswers: 150,
|
||||||
appTitle: 'Framadate Funky',
|
appTitle: 'Framadate',
|
||||||
appVersion: '0.6.0',
|
appVersion: '0.6.0',
|
||||||
appLogo: 'assets/img/logo.png',
|
appLogo: 'assets/img/logo.png',
|
||||||
api: endpoints,
|
api: endpoints,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Update Bulma's global variables
|
// Update Bulma's global variables
|
||||||
$family-sans-serif: 'Nunito', sans-serif;
|
$family-sans-serif: 'Nunito', sans-serif;
|
||||||
|
|
||||||
$primary: $dark-lavender;
|
$primary: $primary_color;
|
||||||
$link: $wisteria;
|
$link: $wisteria;
|
||||||
$widescreen-enabled: false;
|
$widescreen-enabled: false;
|
||||||
$fullhd-enabled: false;
|
$fullhd-enabled: false;
|
||||||
|
@ -1,4 +1,32 @@
|
|||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
|
.input:hover,
|
||||||
|
input:hover,
|
||||||
|
select:hover,
|
||||||
|
.textarea:hover,
|
||||||
|
.select select:hover,
|
||||||
|
.is-hovered.input,
|
||||||
|
input.is-hovered,
|
||||||
|
select.is-hovered,
|
||||||
|
.is-hovered.textarea,
|
||||||
|
.select select.is-hovered {
|
||||||
|
border-color: $border-color !important;
|
||||||
|
}
|
||||||
|
app-step-one,
|
||||||
|
app-step-two,
|
||||||
|
app-step-three,
|
||||||
|
app-step-four {
|
||||||
|
padding: 2em 2.5em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
app-step-five {
|
||||||
|
app-stepper {
|
||||||
|
padding: 2em 2.5em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
select,
|
select,
|
||||||
@ -212,18 +240,18 @@ mat-checkbox {
|
|||||||
.ng-pristine,
|
.ng-pristine,
|
||||||
.ng-dirty {
|
.ng-dirty {
|
||||||
//border-left: #ccc 3px solid;
|
//border-left: #ccc 3px solid;
|
||||||
padding-left: 1em;
|
//padding-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ng-touched.ng-invalid {
|
.ng-touched.ng-invalid {
|
||||||
border-left: $danger 3px solid;
|
//border-left: $danger 3px solid;
|
||||||
padding-left: 1em;
|
//padding-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-dark-crystal {
|
.theme-dark-crystal {
|
||||||
.ng-touched.ng-valid {
|
.ng-touched.ng-valid {
|
||||||
border-left: $success 3px solid;
|
//border-left: $success 3px solid;
|
||||||
padding-left: 1em;
|
//padding-left: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,3 +263,86 @@ mat-checkbox {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calendar primeng
|
||||||
|
.p-datepicker {
|
||||||
|
border: solid 1px $logo_color;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 1em auto;
|
||||||
|
|
||||||
|
button {
|
||||||
|
border: solid 1px $primary_color;
|
||||||
|
}
|
||||||
|
.p-datepicker-buttonbar {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
.pi-chevron-left:after {
|
||||||
|
content: '<';
|
||||||
|
}
|
||||||
|
|
||||||
|
.pi-chevron-right:after {
|
||||||
|
content: '>';
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-datepicker-month {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-datepicker-weeknumber span {
|
||||||
|
border-right: 1px solid $legend_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-datepicker-today span {
|
||||||
|
font-weight: bold;
|
||||||
|
border: solid 1px $legend_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-datepicker-calendar td span {
|
||||||
|
padding: 1em;
|
||||||
|
width: 3.5em;
|
||||||
|
transition: all ease 0.5s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: mix($white, $legend_color);
|
||||||
|
color: $white;
|
||||||
|
transition: all ease 0.2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-highlight {
|
||||||
|
background: $legend_color;
|
||||||
|
color: $white;
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
.p-disabled {
|
||||||
|
background: $d-grey;
|
||||||
|
color: $grey;
|
||||||
|
}
|
||||||
|
.p-datepicker-other-month {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
// weekend days
|
||||||
|
tr > td {
|
||||||
|
&:nth-of-type(6),
|
||||||
|
&:nth-of-type(7) {
|
||||||
|
//border-left: 1px solid $border-color;
|
||||||
|
background: $grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.advanced-config {
|
||||||
|
.box {
|
||||||
|
background: $light;
|
||||||
|
border: 3px solid $primary-color;
|
||||||
|
}
|
||||||
|
.work-in-progress {
|
||||||
|
padding: 1em 2em;
|
||||||
|
background: $border-color;
|
||||||
|
color: $light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-container {
|
||||||
|
@extend .container, .is-widescreen;
|
||||||
|
}
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
.legend {
|
.legend {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-left: 14px;
|
margin-left: 14px;
|
||||||
color: $dark-lavender;
|
color: $primary-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
.legend_first {
|
.legend_first {
|
||||||
|
@ -4,24 +4,9 @@ main {
|
|||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 2rem;
|
|
||||||
}
|
|
||||||
.main-block {
|
|
||||||
min-height: 20em;
|
|
||||||
max-width: 40em;
|
|
||||||
margin-bottom: 10em;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
.title {
|
|
||||||
margin-top: 2em;
|
|
||||||
margin-bottom: 2em;
|
|
||||||
}
|
|
||||||
.button {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.creation,
|
.creation,
|
||||||
.search {
|
.search {
|
||||||
@extend .main-block;
|
@extend main;
|
||||||
}
|
}
|
||||||
|
@ -7,3 +7,11 @@ html {
|
|||||||
main {
|
main {
|
||||||
min-height: 90vh;
|
min-height: 90vh;
|
||||||
}
|
}
|
||||||
|
.min-height {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
min-height: 50vh;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
@ -2,10 +2,8 @@
|
|||||||
background: $primary;
|
background: $primary;
|
||||||
|
|
||||||
main {
|
main {
|
||||||
padding: 0;
|
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
padding-bottom: 5em;
|
padding-bottom: 5em;
|
||||||
padding-top: 1em;
|
|
||||||
background: $white;
|
background: $white;
|
||||||
}
|
}
|
||||||
.big-header {
|
.big-header {
|
||||||
|
@ -1,106 +1,62 @@
|
|||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
// ****************************** config ******************************
|
|
||||||
$theme-vars: 'violet'; // violet , blue
|
|
||||||
|
|
||||||
// ****************************** colors from styleguide https://app.zeplin.io/project/5d4d83d68866d6522ff2ff10/styleguide/colors?cid=5d502bb032e23e3516af8154
|
// colors from styleguide https://app.zeplin.io/project/5d4d83d68866d6522ff2ff10/styleguide/colors?cid=5d502bb032e23e3516af8154
|
||||||
|
$green: #64d16e;
|
||||||
$black: #000000;
|
$black: #000000;
|
||||||
|
$ugly-purple: #b24eb7;
|
||||||
|
$lavender-pink: #e9bdeb;
|
||||||
$white: #ffffff;
|
$white: #ffffff;
|
||||||
|
$dark-lavender: #7d6c99;
|
||||||
|
$dusty-orange: #f18647;
|
||||||
|
$violet: #bd10e0;
|
||||||
|
$red: #cd0000;
|
||||||
$cool-grey: #aeafb1;
|
$cool-grey: #aeafb1;
|
||||||
$warm-grey: #807e7e;
|
$warm-grey: #807e7e;
|
||||||
|
|
||||||
$green: #64d16e;
|
|
||||||
$dusty-orange: #f18647;
|
|
||||||
$red: #cd0000;
|
|
||||||
$pink: #fa7c91;
|
|
||||||
|
|
||||||
$purple: #8a4d76;
|
|
||||||
$ugly-purple: #b24eb7;
|
|
||||||
$violet: #bd10e0;
|
|
||||||
$wisteria: #bf83c2;
|
$wisteria: #bf83c2;
|
||||||
$pale-purple: #d198d4;
|
$pale-purple: #d198d4;
|
||||||
$lavender-pink: #e9bdeb;
|
|
||||||
$dark-lavender: #7d6c99;
|
|
||||||
|
|
||||||
// themes ****************************** blue variation around styleguide
|
|
||||||
$blueish-green: #64d1a9;
|
|
||||||
$blueish-dusty-orange: #74a389;
|
|
||||||
$blueish-red: #9d00cd;
|
|
||||||
$blueish-pink: #d47cfa;
|
|
||||||
$blueish-purple: #4d4d8a;
|
|
||||||
$blueish-ugly-purple: #4d5b8a;
|
|
||||||
$blueish-violet: #5810bd;
|
|
||||||
$blueish-wisteria: #8b83bf;
|
|
||||||
$blueish-pale-purple: #8a9bd1;
|
|
||||||
$blueish-lavender-pink: #8a97e9;
|
|
||||||
$blueish-dark-lavender: #7d6c8a;
|
|
||||||
$blueish-brown: #636c77;
|
|
||||||
|
|
||||||
|
$purple: #8a4d76;
|
||||||
|
$pink: #fa7c91;
|
||||||
$brown: #757763;
|
$brown: #757763;
|
||||||
$beige-light: #d0d1cd;
|
$beige-light: #d0d1cd;
|
||||||
$beige-lighter: #eff0eb;
|
$beige-lighter: #eff0eb;
|
||||||
|
|
||||||
// ****************************** interpretations in app
|
// DINUM colors
|
||||||
|
|
||||||
$primary_color: $ugly-purple;
|
$d-primary: #3e3882; // bleu 800
|
||||||
$primary: $ugly-purple;
|
$d-primary-intense: #6359cf; // bleu 600
|
||||||
$secondary_color: $lavender-pink;
|
$d-grey: #f6f5fd;
|
||||||
$font_color: $black;
|
$d-neutral: #767486;
|
||||||
$logo_color: $dark-lavender;
|
$d-alt: #a9607f;
|
||||||
$logo_color_2: $green;
|
|
||||||
$legend_color: $dark-lavender;
|
$d-info: #ecf4ff;
|
||||||
$legend_color_2: $dusty-orange;
|
$d-info-text: #316ec7;
|
||||||
$choice_select_border_color: $cool-grey;
|
$d-success: #ecfff5;
|
||||||
$hover-color: $warm-grey;
|
$d-success-text: #128149;
|
||||||
$grey-dark: $warm-grey;
|
$d-warning: #dcd3bb;
|
||||||
$grey-light: $beige-light;
|
$d-warning-text: #86671b;
|
||||||
$clicked-color: $wisteria;
|
$d-error: #ffecee;
|
||||||
$mini-button-color: $pale-purple;
|
$d-error-text: #d51b38;
|
||||||
$warning: $dusty-orange;
|
|
||||||
$danger: $red;
|
// interpretations in app
|
||||||
$success: $green;
|
$primary_color: $d-primary;
|
||||||
// ****************************** render ******************************
|
$primary: $d-primary;
|
||||||
@if $theme-vars == 'violet' {
|
$secondary_color: $d-primary-intense;
|
||||||
$primary_color: $ugly-purple;
|
$font_color: $black;
|
||||||
$primary: $ugly-purple;
|
$logo_color: $d-primary;
|
||||||
$secondary_color: $lavender-pink;
|
$logo_color_2: $d-primary-intense;
|
||||||
$font_color: $black;
|
$legend_color: $d-info-text;
|
||||||
$logo_color: $dark-lavender;
|
$legend_color_2: $d-info;
|
||||||
$logo_color_2: $green;
|
$choice_select_border_color: $d-info;
|
||||||
$legend_color: $dark-lavender;
|
$hover-color: $d-neutral;
|
||||||
$legend_color_2: $dusty-orange;
|
$border-color: $d-neutral;
|
||||||
$choice_select_border_color: $cool-grey;
|
$grey-dark: $d-primary;
|
||||||
$hover-color: $warm-grey;
|
$grey-lighter: $beige-light;
|
||||||
$grey-dark: $warm-grey;
|
$clicked-color: $d-primary;
|
||||||
$grey-light: $beige-light;
|
$mini-button-color: $d-primary-intense;
|
||||||
$clicked-color: $wisteria;
|
$warning: $d-warning;
|
||||||
$mini-button-color: $pale-purple;
|
$danger: $d-error;
|
||||||
$warning: $dusty-orange;
|
$success: $d-success;
|
||||||
$danger: $red;
|
|
||||||
$success: $green;
|
|
||||||
|
|
||||||
// FONT
|
|
||||||
$default_font: 'pt_sans';
|
$default_font: 'pt_sans';
|
||||||
$title_font: 'proza_libre', 'Brie Light', 'Arial', 'DejaVu Sans Mono';
|
$title_font: 'proza_libre', 'Brie Light', 'Arial', 'DejaVu Sans Mono';
|
||||||
} @else if $theme-vars == 'blue' {
|
|
||||||
$primary_color: $blueish-ugly-purple;
|
|
||||||
$primary: $blueish-ugly-purple;
|
|
||||||
$secondary_color: $blueish-lavender-pink;
|
|
||||||
$font_color: $black;
|
|
||||||
$logo_color: $blueish-dark-lavender;
|
|
||||||
$logo_color_2: $blueish-green;
|
|
||||||
$legend_color: $blueish-dark-lavender;
|
|
||||||
$legend_color_2: $blueish-dusty-orange;
|
|
||||||
$choice_select_border_color: $cool-grey;
|
|
||||||
$hover-color: $warm-grey;
|
|
||||||
$grey-dark: $warm-grey;
|
|
||||||
$grey-light: $beige-light;
|
|
||||||
$clicked-color: $blueish-wisteria;
|
|
||||||
$mini-button-color: $blueish-pale-purple;
|
|
||||||
$warning: $blueish-dusty-orange;
|
|
||||||
$danger: $blueish-red;
|
|
||||||
$success: $blueish-green;
|
|
||||||
|
|
||||||
// FONT
|
|
||||||
$default_font: 'pt_sans';
|
|
||||||
$title_font: 'proza_libre', 'Brie Light', 'Arial', 'DejaVu Sans Mono';
|
|
||||||
}
|
|
||||||
|
19
yarn.lock
19
yarn.lock
@ -2150,6 +2150,13 @@ amdefine@>=0.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
||||||
integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
|
integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
|
||||||
|
|
||||||
|
angular-date-value-accessor@^1.0.2:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/angular-date-value-accessor/-/angular-date-value-accessor-1.2.1.tgz#a5f07b11fef1c0d1fde5aa851057de177c510137"
|
||||||
|
integrity sha512-4lhVi5PRpaIKtsCDEHioue324u1j18t46ZrD/jI7+M6DrZeRyxfMeSGsZXWNOC6eaq9x/pzXyaE8slXSj3Qd5A==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
ansi-align@^3.0.0:
|
ansi-align@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
|
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
|
||||||
@ -3755,6 +3762,11 @@ crypto-random-string@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
|
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
|
||||||
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
|
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
|
||||||
|
|
||||||
|
crypto@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037"
|
||||||
|
integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==
|
||||||
|
|
||||||
css-color-names@0.0.4, css-color-names@^0.0.4:
|
css-color-names@0.0.4, css-color-names@^0.0.4:
|
||||||
version "0.0.4"
|
version "0.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
||||||
@ -9451,6 +9463,13 @@ pretty-format@^26.0.0, pretty-format@^26.1.0:
|
|||||||
ansi-styles "^4.0.0"
|
ansi-styles "^4.0.0"
|
||||||
react-is "^16.12.0"
|
react-is "^16.12.0"
|
||||||
|
|
||||||
|
primeng@^11.0.0:
|
||||||
|
version "11.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/primeng/-/primeng-11.4.5.tgz#128137d727d555f68c212a1dcb1f2af3b0f4afd4"
|
||||||
|
integrity sha512-7f5LDHrvFsJA4670Ftmib5ndDxTqcaQiM88XXJrjWYNGjXsXT3Yc5g9fgPvDrg2D38/jjpcSYeW9kalNcvlbrQ==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
prismjs@^1.20.0:
|
prismjs@^1.20.0:
|
||||||
version "1.20.0"
|
version "1.20.0"
|
||||||
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.20.0.tgz#9b685fc480a3514ee7198eac6a3bf5024319ff03"
|
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.20.0.tgz#9b685fc480a3514ee7198eac6a3bf5024319ff03"
|
||||||
|
Loading…
Reference in New Issue
Block a user