Merge branch 'feature/reformat_all_files' into 'develop'

reformat all files + move routes.ts to AppRoutingModule

See merge request framasoft/framadate/funky-framadate-front!28
This commit is contained in:
ty kayn 2020-04-14 12:05:48 +02:00
commit d9c325a0e9
151 changed files with 4347 additions and 5151 deletions

View File

@ -6,7 +6,6 @@
"ng": "ng", "ng": "ng",
"start": "ng serve", "start": "ng serve",
"compodoc": "compodoc -p tsconfig.json", "compodoc": "compodoc -p tsconfig.json",
"serve": "ng serve",
"build": "ng build --crossOrigin=anonymous --prod", "build": "ng build --crossOrigin=anonymous --prod",
"package": "cat dist/framadate/*.js > dist/framadate/framadate-scripts-bundled.js && ls -l dist/framadate", "package": "cat dist/framadate/*.js > dist/framadate/framadate-scripts-bundled.js && ls -l dist/framadate",
"bld:pkg": "npm run build && npm run package", "bld:pkg": "npm run build && npm run package",

View File

@ -1,12 +1,48 @@
import {NgModule} from '@angular/core'; import { NgModule } from '@angular/core';
import {RouterModule, Routes} from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { AdminComponent } from './pages/admin/admin.component';
import { AnswersComponent } from './pages/answers/answers.component';
import { BaseComponent } from './pages/base-page/base.component';
import { CreateOrRetrieveComponent } from './pages/create-or-retrieve/create-or-retrieve.component';
import { DatesComponent } from './pages/dates/dates.component';
import { EndConfirmationComponent } from './pages/end-confirmation/end-confirmation.component';
import { HomeComponent } from './pages/home/home.component';
import { KindComponent } from './pages/kind/kind.component';
import { PasswordComponent } from './pages/password/password.component';
import { PicturesComponent } from './pages/pictures/pictures.component';
import { PollDisplayComponent } from './pages/poll-display/poll-display.component';
import { ResumeComponent } from './pages/resume/resume.component';
import { VisibilityComponent } from './pages/visibility/visibility.component';
import { VotingChoiceComponent } from './pages/voting/voting-choice/voting-choice.component';
import { VotingComponent } from './pages/voting/voting.component';
import { PollGraphicComponent } from './poll-graphic/poll-graphic.component';
const routes: Routes = []; const routes: Routes = [
{ path: '', redirectTo: 'step/creation', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'base', component: BaseComponent },
{ path: 'step/base', component: BaseComponent },
{ path: 'step/creation', component: CreateOrRetrieveComponent },
{ path: 'step/date', component: DatesComponent },
{ path: 'step/kind', component: KindComponent },
{ path: 'step/answers', component: AnswersComponent },
{ path: 'step/admin', component: AdminComponent },
{ path: 'step/pictures', component: PicturesComponent },
{ path: 'step/visibility', component: VisibilityComponent },
{ path: 'step/resume', component: ResumeComponent },
{ path: 'step/end', component: EndConfirmationComponent },
{ path: 'graphic/:poll', component: PollGraphicComponent },
{ path: 'vote/poll/id/:poll', component: PollDisplayComponent },
{ path: 'vote/poll/slug/:pollSlug', component: PollDisplayComponent },
{ path: 'votingchoice', component: VotingChoiceComponent },
{ path: 'voting', component: VotingComponent },
{ path: 'step/password', component: PasswordComponent },
{ path: '**', redirectTo: '/home', pathMatch: 'full' },
];
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes, {useHash: true, anchorScrolling: 'enabled',})], imports: [RouterModule.forRoot(routes, { useHash: true, anchorScrolling: 'enabled' })],
exports: [RouterModule] exports: [RouterModule],
}) })
export class AppRoutingModule { export class AppRoutingModule {}
}

View File

@ -1,47 +1,31 @@
<div <div id="big_container" class="{{ this.config.preferences.themeClass }}">
id='big_container' <header class="big-header">
class={{this.config.preferences.themeClass}} <div class="container">
> <div class="columns">
<div class="column">
<header class='big-header'>
<div class='container'>
<div class='columns'>
<div class='column'>
<framadate-master-head></framadate-master-head> <framadate-master-head></framadate-master-head>
</div> </div>
<div class='column'> <div class="column">
<framadate-language></framadate-language> <framadate-language></framadate-language>
</div> </div>
</div> </div>
</div> </div>
</header> </header>
<main> <main>
<div class="container"> <div class="container">
<div class="columns"> <div class="columns">
<div class="column is-one-quarter"> <div class="column is-one-quarter">
<framadate-theme-selector></framadate-theme-selector> <framadate-theme-selector></framadate-theme-selector>
<framadate-navigation <framadate-navigation *ngIf="config.menuVisible" [step]="step"></framadate-navigation>
*ngIf="config.menuVisible" <framadate-debugger *ngIf="isDevelopmentEnv"></framadate-debugger>
[step]="step"
></framadate-navigation>
<framadate-debugger
*ngIf="isDevelopmentEnv"
></framadate-debugger>
<p-toast position="top-right"></p-toast> <p-toast position="top-right"></p-toast>
</div> </div>
<div class="column"> <div class="column">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>
</div> </div>
</div> </div>
</main> </main>
</div> </div>

View File

@ -5,12 +5,8 @@ import { AppComponent } from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [RouterTestingModule],
RouterTestingModule declarations: [AppComponent],
],
declarations: [
AppComponent
],
}).compileComponents(); }).compileComponents();
})); }));

View File

@ -1,46 +1,43 @@
import {Component, Inject} from '@angular/core'; import { Component, Inject } from '@angular/core';
import {TranslateService} from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import {NavigationStart, Router} from '@angular/router'; import { NavigationStart, Router } from '@angular/router';
import {DOCUMENT} from '@angular/common'; import { DOCUMENT } from '@angular/common';
import {filter} from 'rxjs/operators'; import { filter } from 'rxjs/operators';
import {ConfigService} from './services/config.service'; import { ConfigService } from './services/config.service';
import {environment} from '../environments/environment'; import { environment } from '../environments/environment';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'] styleUrls: ['./app.component.scss'],
}) })
export class AppComponent { export class AppComponent {
step: string; step: string;
isDevelopmentEnv=false; isDevelopmentEnv = false;
constructor(private translate: TranslateService, constructor(
private translate: TranslateService,
public config: ConfigService, public config: ConfigService,
@Inject(DOCUMENT) private document, @Inject(DOCUMENT) private document,
private route: Router) { private route: Router
) {
this.detectCurrentTabOnRouteChange(); this.detectCurrentTabOnRouteChange();
this.isDevelopmentEnv = !environment.production this.isDevelopmentEnv = !environment.production;
} }
detectCurrentTabOnRouteChange() { detectCurrentTabOnRouteChange() {
this.route.events.subscribe((event: any) => { this.route.events.subscribe((event: any) => {});
this.route.events
.pipe(filter((event) => event instanceof NavigationStart))
}); .subscribe((event: NavigationStart) => {
this.route.events.pipe(filter(event => event instanceof NavigationStart)).subscribe((event: NavigationStart) => {
this.scrollGoToTop(); this.scrollGoToTop();
this.updateCurrentTab(event); this.updateCurrentTab(event);
// only if there is a poll ID // only if there is a poll ID
this.config.fetchPollFromRoute(event); this.config.fetchPollFromRoute(event);
}) });
} }
scrollGoToTop() { scrollGoToTop() {
this.document.documentElement.scrollTop = 0; this.document.documentElement.scrollTop = 0;
} }
@ -55,6 +52,4 @@ export class AppComponent {
} }
} }
} }
} }

View File

@ -1,65 +1,63 @@
import {BrowserModule} from '@angular/platform-browser'; import { CommonModule, registerLocaleData } from '@angular/common';
import {NgModule} from '@angular/core'; import { HttpClient, HttpClientModule } from '@angular/common/http';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {BaseComponent} from './pages/base-page/base.component';
import {KindComponent} from './pages/kind/kind.component';
import {HeaderComponent} from './header/header.component';
import {FormsModule} from '@angular/forms';
import {NavigationComponent} from './ui/navigation/navigation.component';
import {RouterModule} from '@angular/router';
import {Routes} from './config/Routes';
import {CommonModule, registerLocaleData} from '@angular/common';
import {DatesComponent} from './pages/dates/dates.component';
import {DebuggerComponent} from './debugger/debugger.component';
import {VisibilityComponent} from './pages/visibility/visibility.component';
import {ResumeComponent} from './pages/resume/resume.component';
import {PicturesComponent} from './pages/pictures/pictures.component';
import {AnswersComponent} from './pages/answers/answers.component';
import {EndConfirmationComponent} from './pages/end-confirmation/end-confirmation.component';
import {CreateOrRetrieveComponent} from './pages/create-or-retrieve/create-or-retrieve.component';
import localeFr from '@angular/common/locales/fr';
import localeEn from '@angular/common/locales/en'; import localeEn from '@angular/common/locales/en';
import {VotingSummaryComponent} from './pages/voting/voting-summary/voting-summary.component'; import localeFr from '@angular/common/locales/fr';
import {VotingGraphComponent} from './pages/voting/voting-graph/voting-graph.component'; import { NgModule } from '@angular/core';
import {VotingChoiceComponent} from './pages/voting/voting-choice/voting-choice.component'; import { FormsModule } from '@angular/forms';
import {PasswordComponent} from './pages/password/password.component'; import { BrowserModule } from '@angular/platform-browser';
import {HomeComponent} from './pages/home/home.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {MarkdownModule} from 'ngx-markdown';
import { import {
MissingTranslationHandler, MissingTranslationHandler,
MissingTranslationHandlerParams, MissingTranslationHandlerParams,
TranslateLoader, TranslateLoader,
TranslateModule, TranslateModule,
TranslateService TranslateService,
} from '@ngx-translate/core'; } from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader'; import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import {PollGraphicComponent} from './poll-graphic/poll-graphic.component'; import { ClipboardModule } from 'ngx-clipboard';
import { MarkdownModule } from 'ngx-markdown';
import { ConfirmationService, MessageModule, MessageService } from 'primeng';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { DialogModule } from 'primeng/dialog';
import { ToastModule } from 'primeng/toast';
import {AdminComponent} from './pages/admin/admin.component'; import { AppRoutingModule } from './app-routing.module';
import {SelectorComponent} from './ui/selector/selector.component'; import { AppComponent } from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import { DateValueAccessorModule } from './custom-lib/date-value-accessor';
import {ConfigService} from './services/config.service'; import { DebuggerComponent } from './debugger/debugger.component';
import {PollService} from './services/poll.service'; import { HeaderComponent } from './header/header.component';
import {ToastModule} from 'primeng/toast'; import { AdminComponent } from './pages/admin/admin.component';
import {ConfirmationService, MessageModule, MessageService} from 'primeng'; import { AnswersComponent } from './pages/answers/answers.component';
import {PollDisplayComponent} from './pages/poll-display/poll-display.component'; import { BaseComponent } from './pages/base-page/base.component';
import {VotingComponent} from './pages/voting/voting.component'; import { CreateOrRetrieveComponent } from './pages/create-or-retrieve/create-or-retrieve.component';
import {VotingCommentComponent} from './pages/voting/voting-comment/voting-comment.component'; import { DatesComponent } from './pages/dates/dates.component';
import {ResettableInputDirective} from './ui/directives/resettable-input.directive'; import { EndConfirmationComponent } from './pages/end-confirmation/end-confirmation.component';
import {ClipboardModule} from 'ngx-clipboard'; import { HomeComponent } from './pages/home/home.component';
import {ErasableInputComponent} from './ui/erasable-input/erasable-input.component'; import { KindComponent } from './pages/kind/kind.component';
import {ConfirmDialogModule} from 'primeng/confirmdialog'; import { PasswordComponent } from './pages/password/password.component';
import {DialogModule} from 'primeng/dialog'; import { PicturesComponent } from './pages/pictures/pictures.component';
import {DateValueAccessorModule} from './custom-lib/date-value-accessor'; import { PollDisplayComponent } from './pages/poll-display/poll-display.component';
import {CopyTextComponent} from './ui/copy-text/copy-text.component'; import { ResumeComponent } from './pages/resume/resume.component';
import {CommentsListComponent} from './pages/voting/comments-list/comments-list.component'; import { VisibilityComponent } from './pages/visibility/visibility.component';
import {ChoicesListComponent} from './pages/voting/choices-list/choices-list.component'; import { ChoicesListComponent } from './pages/voting/choices-list/choices-list.component';
import {VotingNavigationComponent} from './pages/voting/voting-navigation/voting-navigation.component'; import { CommentsListComponent } from './pages/voting/comments-list/comments-list.component';
import { ThemeSelectorComponent } from './ui/theme-selector/theme-selector.component'; import { VotingChoiceComponent } from './pages/voting/voting-choice/voting-choice.component';
import { VotingCommentComponent } from './pages/voting/voting-comment/voting-comment.component';
import { VotingGraphComponent } from './pages/voting/voting-graph/voting-graph.component';
import { VotingNavigationComponent } from './pages/voting/voting-navigation/voting-navigation.component';
import { VotingSummaryComponent } from './pages/voting/voting-summary/voting-summary.component';
import { VotingComponent } from './pages/voting/voting.component';
import { PollGraphicComponent } from './poll-graphic/poll-graphic.component';
import { ConfigService } from './services/config.service';
import { PollService } from './services/poll.service';
import { CopyTextComponent } from './ui/copy-text/copy-text.component';
import { ResettableInputDirective } from './ui/directives/resettable-input.directive';
import { ErasableInputComponent } from './ui/erasable-input/erasable-input.component';
import { MasterHeadComponent } from './ui/navigation/master-head/master-head.component'; import { MasterHeadComponent } from './ui/navigation/master-head/master-head.component';
import { NavigationComponent } from './ui/navigation/navigation.component';
import { LanguageComponent } from './ui/selector/language/language.component'; import { LanguageComponent } from './ui/selector/language/language.component';
import { SelectorComponent } from './ui/selector/selector.component';
import { ThemeSelectorComponent } from './ui/theme-selector/theme-selector.component';
export class MyMissingTranslationHandler implements MissingTranslationHandler { export class MyMissingTranslationHandler implements MissingTranslationHandler {
handle(params: MissingTranslationHandlerParams) { handle(params: MissingTranslationHandlerParams) {
@ -70,7 +68,7 @@ export class MyMissingTranslationHandler implements MissingTranslationHandler {
registerLocaleData(localeFr, 'fr'); registerLocaleData(localeFr, 'fr');
registerLocaleData(localeEn, 'en'); registerLocaleData(localeEn, 'en');
export function HttpLoaderFactory(http: HttpClient) { export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
return new TranslateHttpLoader(http); return new TranslateHttpLoader(http);
} }
@ -109,7 +107,6 @@ export function HttpLoaderFactory(http: HttpClient) {
ThemeSelectorComponent, ThemeSelectorComponent,
MasterHeadComponent, MasterHeadComponent,
LanguageComponent, LanguageComponent,
], ],
imports: [ imports: [
ConfirmDialogModule, ConfirmDialogModule,
@ -132,15 +129,13 @@ export function HttpLoaderFactory(http: HttpClient) {
loader: { loader: {
provide: TranslateLoader, provide: TranslateLoader,
useFactory: HttpLoaderFactory, useFactory: HttpLoaderFactory,
deps: [HttpClient] deps: [HttpClient],
} },
}), }),
HttpClientModule, HttpClientModule,
FormsModule, FormsModule,
RouterModule.forRoot(Routes, {useHash: true})
], ],
providers: [TranslateService, ConfigService, PollService, MessageService, ConfirmationService], providers: [TranslateService, ConfigService, PollService, MessageService, ConfirmationService],
bootstrap: [AppComponent] bootstrap: [AppComponent],
}) })
export class AppModule { export class AppModule {}
}

View File

@ -1,10 +1,9 @@
import {Injectable} from "@angular/core"; import { Injectable } from '@angular/core';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root',
}) })
export class DateUtilities { export class DateUtilities {
/** /**
* add some days to a date, to compute intervals * add some days to a date, to compute intervals
* @param days * @param days
@ -14,7 +13,7 @@ export class DateUtilities {
date = new Date(date.valueOf()); date = new Date(date.valueOf());
date.setDate(date.getDate() + days); date.setDate(date.getDate() + days);
return date; return date;
}; }
/** /**
* *
@ -29,9 +28,9 @@ export class DateUtilities {
while (+d1 < +d2) { while (+d1 < +d2) {
dates.push({ dates.push({
literal: this.formateDate(d1), literal: this.formateDate(d1),
date_object: d1 date_object: d1,
}); });
d1.setDate(d1.getDate() + interval) d1.setDate(d1.getDate() + interval);
} }
return dates.slice(0); return dates.slice(0);
} }
@ -42,7 +41,7 @@ export class DateUtilities {
* @param d2 * @param d2
*/ */
dayDiff(d1: Date, d2: Date): Number { dayDiff(d1: Date, d2: Date): Number {
return Number(((d2.getTime()) - (d1.getTime()) / 31536000000)); return Number(d2.getTime() - d1.getTime() / 31536000000);
} }
/** /**
@ -55,10 +54,10 @@ export class DateUtilities {
date.getFullYear(), date.getFullYear(),
this.getDoubleDigits(date.getMonth() + 1), this.getDoubleDigits(date.getMonth() + 1),
this.getDoubleDigits(date.getDate()), this.getDoubleDigits(date.getDate()),
].join('-') ].join('-');
} }
getDoubleDigits(str) { getDoubleDigits(str) {
return ("00" + str).slice(-2); return ('00' + str).slice(-2);
} }
} }

View File

@ -1,8 +1,8 @@
/** /**
* une option de date dans les sondages spéciaux * une option de date dans les sondages spéciaux
*/ */
import {environment} from '../../environments/environment'; import { environment } from '../../environments/environment';
import {DateChoice, defaultAnswers, otherDefaultDates, PollAnswer} from './defaultConfigs'; import { DateChoice, defaultAnswers, otherDefaultDates, PollAnswer } from './defaultConfigs';
export interface DateOption { export interface DateOption {
timeList: any; timeList: any;
@ -18,22 +18,17 @@ const baseConfigValues = {
myEmail: '', myEmail: '',
}; };
/** /**
* configuration of the poll, add new fields at will * configuration of the poll, add new fields at will
*/ */
export class PollConfig { export class PollConfig {
menuVisible = true; menuVisible = true;
expiracyDateDefaultInDays = 60; expiracyDateDefaultInDays = 60;
deletionDateAfterLastModification = 180; deletionDateAfterLastModification = 180;
step = 0; // step in the progress of creating a poll step = 0; // step in the progress of creating a poll
stepMax = 3; // step max in the progress of creating a poll stepMax = 3; // step max in the progress of creating a poll
pollType = 'dates';// classic or dates pollType = 'dates'; // classic or dates
title: string = environment.production ? '' : 'titre'; title: string = environment.production ? '' : 'titre';
description: string = environment.production ? '' : 'ma description'; description: string = environment.production ? '' : 'ma description';
@ -43,7 +38,7 @@ export class PollConfig {
myVoteStack: any; myVoteStack: any;
myTempVoteStack = 0; myTempVoteStack = 0;
myEmail: string = environment.production ? '' : 'tktest@tktest.com'; myEmail: string = environment.production ? '' : 'tktest@tktest.com';
myPolls: any = [];// list of retrieved polls from the backend api myPolls: any = []; // list of retrieved polls from the backend api
/* /*
date specific poll, we have the choice to setup different hours (timeList) for all possible dates (dateList), or use the same hours for all dates date specific poll, we have the choice to setup different hours (timeList) for all possible dates (dateList), or use the same hours for all dates
*/ */
@ -66,9 +61,9 @@ export class PollConfig {
urlAdmin = environment.baseHref + '/#/admin/d65es45fd45sdf45sd345f312sdf31sgfd345'; urlAdmin = environment.baseHref + '/#/admin/d65es45fd45sdf45sd345f312sdf31sgfd345';
adminKey = ''; // key to change config of the poll adminKey = ''; // key to change config of the poll
owner_modifier_token = ''; // key to change a vote stack owner_modifier_token = ''; // key to change a vote stack
canModifyAnswers = true;// bool for the frontend selector canModifyAnswers = true; // bool for the frontend selector
whoModifiesAnswers = 'everybody';// everybody, self, nobody (= just admin) whoModifiesAnswers = 'everybody'; // everybody, self, nobody (= just admin)
whoCanChangeAnswers = 'everybody';// everybody, self, nobody (= just admin) whoCanChangeAnswers = 'everybody'; // everybody, self, nobody (= just admin)
dateList: any = otherDefaultDates; // sets of days as strings, config to set identical time for days in a special days poll dateList: any = otherDefaultDates; // sets of days as strings, config to set identical time for days in a special days poll
timeList: DateChoice[] = otherDefaultDates; // ranges of time expressed as strings timeList: DateChoice[] = otherDefaultDates; // ranges of time expressed as strings

View File

@ -1,9 +1,9 @@
import {HttpHeaders} from "@angular/common/http"; import { HttpHeaders } from '@angular/common/http';
import {PollConfig} from "./PollConfig"; import { PollConfig } from './PollConfig';
import {Injectable} from "@angular/core"; import { Injectable } from '@angular/core';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root',
}) })
export class PollUtilities { export class PollUtilities {
// utils functions // utils functions
@ -12,7 +12,8 @@ export class PollUtilities {
*/ */
makeUuid() { makeUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); var r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16); return v.toString(16);
}); });
} }
@ -23,18 +24,28 @@ export class PollUtilities {
*/ */
makeSlug(config: PollConfig) { makeSlug(config: PollConfig) {
let str = ''; let str = '';
str = config.creationDate.getFullYear() + '_' + (config.creationDate.getMonth() + 1) + '_' + config.creationDate.getDate() + '_' + config.myName + '_' + config.title; str =
config.creationDate.getFullYear() +
'_' +
(config.creationDate.getMonth() + 1) +
'_' +
config.creationDate.getDate() +
'_' +
config.myName +
'_' +
config.title;
str = str.replace(/^\s+|\s+$/g, ''); // trim str = str.replace(/^\s+|\s+$/g, ''); // trim
str = str.toLowerCase(); str = str.toLowerCase();
// remove accents, swap ñ for n, etc // remove accents, swap ñ for n, etc
var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;"; var from = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;';
var to = "aaaaeeeeiiiioooouuuunc------"; var to = 'aaaaeeeeiiiioooouuuunc------';
for (var i = 0, l = from.length; i < l; i++) { for (var i = 0, l = from.length; i < l; i++) {
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i)); str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
} }
str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars str = str
.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
@ -46,18 +57,17 @@ export class PollUtilities {
* @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': '*',
}; };
const requestOptions = { const requestOptions = {
headers: new HttpHeaders(headerDict), headers: new HttpHeaders(headerDict),
body: bodyContent body: bodyContent,
}; };
return requestOptions; return requestOptions;

View File

@ -1,45 +1,42 @@
import {KindComponent} from '../pages/kind/kind.component'; import { AdminComponent } from '../pages/admin/admin.component';
import {DatesComponent} from '../pages/dates/dates.component'; import { AnswersComponent } from '../pages/answers/answers.component';
import {VisibilityComponent} from '../pages/visibility/visibility.component'; import { BaseComponent } from '../pages/base-page/base.component';
import {ResumeComponent} from '../pages/resume/resume.component'; import { CreateOrRetrieveComponent } from '../pages/create-or-retrieve/create-or-retrieve.component';
import {PicturesComponent} from '../pages/pictures/pictures.component'; import { DatesComponent } from '../pages/dates/dates.component';
import {EndConfirmationComponent} from '../pages/end-confirmation/end-confirmation.component'; import { EndConfirmationComponent } from '../pages/end-confirmation/end-confirmation.component';
import {AnswersComponent} from '../pages/answers/answers.component'; import { HomeComponent } from '../pages/home/home.component';
import {AdminComponent} from '../pages/admin/admin.component'; import { KindComponent } from '../pages/kind/kind.component';
import {CreateOrRetrieveComponent} from '../pages/create-or-retrieve/create-or-retrieve.component'; import { PasswordComponent } from '../pages/password/password.component';
import {BaseComponent} from '../pages/base-page/base.component'; import { PicturesComponent } from '../pages/pictures/pictures.component';
import {HomeComponent} from "../pages/home/home.component"; import { PollDisplayComponent } from '../pages/poll-display/poll-display.component';
import {PollGraphicComponent} from '../poll-graphic/poll-graphic.component'; import { ResumeComponent } from '../pages/resume/resume.component';
import {PollDisplayComponent} from "../pages/poll-display/poll-display.component"; import { VisibilityComponent } from '../pages/visibility/visibility.component';
import { VotingChoiceComponent } from '../pages/voting/voting-choice/voting-choice.component';
import {VotingComponent} from "../pages/voting/voting.component"; import { VotingComponent } from '../pages/voting/voting.component';
import {PasswordComponent} from "../pages/password/password.component"; import { PollGraphicComponent } from '../poll-graphic/poll-graphic.component';
import {VotingChoiceComponent} from "../pages/voting/voting-choice/voting-choice.component";
/** /**
* each step in the form is a component * each step in the form is a component
*/ */
export const Routes = export const Routes = [
[ { path: '', redirectTo: 'step/creation', pathMatch: 'full' },
{path: '', redirectTo: 'step/creation', pathMatch: 'full'}, { path: 'home', component: HomeComponent },
{path: 'home', component: HomeComponent}, { path: 'base', component: BaseComponent },
{path: 'base', component: BaseComponent}, { path: 'step/base', component: BaseComponent },
{path: 'step/base', component: BaseComponent}, { path: 'step/creation', component: CreateOrRetrieveComponent },
{path: 'step/creation', component: CreateOrRetrieveComponent}, { path: 'step/date', component: DatesComponent },
{path: 'step/date', component: DatesComponent}, { path: 'step/kind', component: KindComponent },
{path: 'step/kind', component: KindComponent}, { path: 'step/answers', component: AnswersComponent },
{path: 'step/answers', component: AnswersComponent}, { path: 'step/admin', component: AdminComponent },
{path: 'step/admin', component: AdminComponent}, { path: 'step/pictures', component: PicturesComponent },
{path: 'step/pictures', component: PicturesComponent}, { path: 'step/visibility', component: VisibilityComponent },
{path: 'step/visibility', component: VisibilityComponent}, { path: 'step/resume', component: ResumeComponent },
{path: 'step/resume', component: ResumeComponent}, { path: 'step/end', component: EndConfirmationComponent },
{path: 'step/end', component: EndConfirmationComponent}, { path: 'graphic/:poll', component: PollGraphicComponent },
{path: 'graphic/:poll', component: PollGraphicComponent}, { path: 'vote/poll/id/:poll', component: PollDisplayComponent },
{path: 'vote/poll/id/:poll', component: PollDisplayComponent}, { path: 'vote/poll/slug/:pollSlug', component: PollDisplayComponent },
{path: 'vote/poll/slug/:pollSlug', component: PollDisplayComponent}, { path: 'votingchoice', component: VotingChoiceComponent },
{path: 'votingchoice', component: VotingChoiceComponent}, { path: 'voting', component: VotingComponent },
{path: 'voting', component: VotingComponent}, { path: 'step/password', component: PasswordComponent },
{path: 'step/password', component: PasswordComponent}, { path: '**', redirectTo: '/home', pathMatch: 'full' },
{path: '**', redirectTo: '/home', pathMatch: 'full'}, ];
]
;

View File

@ -1,106 +1,107 @@
export interface DateChoice { export interface DateChoice {
literal: string, literal: string;
timeList: TimeSlices[], timeList: TimeSlices[];
date_object: Date date_object: Date;
} }
export interface TimeSlices { export interface TimeSlices {
literal: string literal: string;
} }
export interface PollAnswer { export interface PollAnswer {
id: number, id: number;
text: string, text: string;
url: string, url: string;
file: string, file: string;
literal: string, literal: string;
date_object: Date, date_object: Date;
timeList: TimeSlices[] timeList: TimeSlices[];
} }
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
const currentMonth = new Date().getMonth(); const currentMonth = new Date().getMonth();
const currentDay = new Date().getDate(); const currentDay = new Date().getDate();
export const basicSlicesOfDay: TimeSlices[] = [ export const basicSlicesOfDay: TimeSlices[] = [{ literal: 'matin' }, { literal: 'midi' }, { literal: 'soir' }];
{literal: 'matin'},
{literal: 'midi'},
{literal: 'soir'}
];
export const otherSlicesOfDay: TimeSlices[] = [ export const otherSlicesOfDay: TimeSlices[] = [
{literal: 'aux aurores'}, { literal: 'aux aurores' },
{literal: 'au petit dej'}, { literal: 'au petit dej' },
{literal: 'au deuxième petit dej des hobbits'} { literal: 'au deuxième petit dej des hobbits' },
]; ];
export const defaultTimeOfDay: TimeSlices[] = (() => { export const defaultTimeOfDay: TimeSlices[] = (() => {
return [...basicSlicesOfDay] return [...basicSlicesOfDay];
})(); })();
export const otherTimeOfDay: TimeSlices[] = (() => { export const otherTimeOfDay: TimeSlices[] = (() => {
return [...otherSlicesOfDay] return [...otherSlicesOfDay];
})(); })();
export const moreTimeOfDay: TimeSlices[] = (() => { export const moreTimeOfDay: TimeSlices[] = (() => {
return [...otherSlicesOfDay] return [...otherSlicesOfDay];
})(); })();
export const defaultDates: DateChoice[] = [ export const defaultDates: DateChoice[] = [
{ {
literal: `${currentYear}-${currentMonth}-${currentDay}`, literal: `${currentYear}-${currentMonth}-${currentDay}`,
date_object: new Date(), date_object: new Date(),
timeList: defaultTimeOfDay timeList: defaultTimeOfDay,
}, },
{ {
literal: `${currentYear}-${currentMonth}-${currentDay + 1}`, literal: `${currentYear}-${currentMonth}-${currentDay + 1}`,
date_object: new Date(), date_object: new Date(),
timeList: defaultTimeOfDay timeList: defaultTimeOfDay,
}, },
{ {
literal: `${currentYear}-${currentMonth}-${currentDay + 2}`, literal: `${currentYear}-${currentMonth}-${currentDay + 2}`,
date_object: new Date(), date_object: new Date(),
timeList: defaultTimeOfDay timeList: defaultTimeOfDay,
} },
]; ];
export const otherDefaultDates: DateChoice[] = [ export const otherDefaultDates: DateChoice[] = [
{ {
literal: `${currentYear}-${currentMonth}-${currentDay}`, literal: `${currentYear}-${currentMonth}-${currentDay}`,
date_object: new Date(), date_object: new Date(),
timeList: defaultTimeOfDay timeList: defaultTimeOfDay,
}, },
{ {
literal: `${currentYear}-${currentMonth}-${currentDay + 1}`, literal: `${currentYear}-${currentMonth}-${currentDay + 1}`,
date_object: new Date(currentYear, currentMonth, currentDay + 1), date_object: new Date(currentYear, currentMonth, currentDay + 1),
timeList: otherTimeOfDay timeList: otherTimeOfDay,
}, },
{ {
literal: `${currentYear}-${currentMonth}-${currentDay + 2}`, literal: `${currentYear}-${currentMonth}-${currentDay + 2}`,
date_object: new Date(), date_object: new Date(),
timeList: moreTimeOfDay timeList: moreTimeOfDay,
} },
]; ];
export const defaultAnswers: PollAnswer[] = [{ export const defaultAnswers: PollAnswer[] = [
{
id: 0, id: 0,
text: 'réponse de démo 1', text: 'réponse de démo 1',
file: '', file: '',
url: 'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574', url:
'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574',
literal: `${currentYear}-${currentMonth}-${currentDay}`, literal: `${currentYear}-${currentMonth}-${currentDay}`,
date_object: new Date(), date_object: new Date(),
timeList: otherSlicesOfDay timeList: otherSlicesOfDay,
}, },
{ {
id: 1, id: 1,
text: 'réponse 2', text: 'réponse 2',
file: '', file: '',
url: 'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574', url:
'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574',
literal: `${currentYear}-${currentMonth}-${currentDay + 1}`, literal: `${currentYear}-${currentMonth}-${currentDay + 1}`,
date_object: new Date(), date_object: new Date(),
timeList: basicSlicesOfDay timeList: basicSlicesOfDay,
}, },
{ {
id: 2, id: 2,
text: 'la réponse D', text: 'la réponse D',
file: '', file: '',
url: 'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574', url:
'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574',
literal: `${currentYear}-${currentMonth}-${currentDay + 2}`, literal: `${currentYear}-${currentMonth}-${currentDay + 2}`,
date_object: new Date(), date_object: new Date(),
timeList: otherSlicesOfDay timeList: otherSlicesOfDay,
}]; },
];

View File

@ -1,24 +1,24 @@
export var graphOptions = { export var graphOptions = {
legend: {display: false}, legend: { display: false },
scales: { scales: {
xAxes: [ xAxes: [
{ {
gridLines: {drawBorder: false, display: false}, gridLines: { drawBorder: false, display: false },
display: false, display: false,
stacked: true, stacked: true,
ticks: { ticks: {
beginAtZero: true, beginAtZero: true,
maxRotation: 0, maxRotation: 0,
minRotation: 0 minRotation: 0,
} },
} },
], ],
yAxes: [ yAxes: [
{ {
gridLines: {drawBorder: true, display: false}, gridLines: { drawBorder: true, display: false },
display: true, display: true,
stacked: true stacked: true,
} },
] ],
} },
}; };

View File

@ -1,11 +1,11 @@
export const mockChoice = { export const mockChoice = {
"id": 11, id: 11,
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"text": "Les mondes engloutis", text: 'Les mondes engloutis',
"url": null, url: null,
"answer": null, answer: null,
}; };

View File

@ -1,20 +1,21 @@
export const mockComments = [ export const mockComments = [
{ {
pseudo: "Bulbizarre", pseudo: 'Bulbizarre',
"date": { date: {
"date": "2020-01-22 16:00:22.000000", date: '2020-01-22 16:00:22.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Paris" timezone: 'Europe/Paris',
}, },
text: "Pokem ipsum dolor sit amet Electric Cottonee Scratch Leech Life Ice Berry Ducklett. Leaf Green Durant Zoroark\n" + text:
" Skitty Rock Luxio Surskit. Glacier Badge", 'Pokem ipsum dolor sit amet Electric Cottonee Scratch Leech Life Ice Berry Ducklett. Leaf Green Durant Zoroark\n' +
' Skitty Rock Luxio Surskit. Glacier Badge',
}, },
{ {
pseudo: "Marylin", pseudo: 'Marylin',
"date": { date: {
"date": "2020-01-22 16:00:22.000000", date: '2020-01-22 16:00:22.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Paris" timezone: 'Europe/Paris',
}, },
text: "j'ai vu de la lumière o_o", text: "j'ai vu de la lumière o_o",
}, },

View File

@ -1,52 +1,52 @@
export const mockGraphConfig = { export const mockGraphConfig = {
step: 0, step: 0,
stepMax: 3, stepMax: 3,
pollType: "special dates", pollType: 'special dates',
title: "", title: '',
description: "", description: '',
myName: "", myName: '',
visibility: "link_only", visibility: 'link_only',
// date specific poll // date specific poll
allowSeveralHours: "true", allowSeveralHours: 'true',
dateLgfgfgfgist: ["jeudi", "vendredi", "samedi"], // sets of days as strings dateLgfgfgfgist: ['jeudi', 'vendredi', 'samedi'], // sets of days as strings
timeList: ["08:00", "08:30", "09:00"], // ranges of time expressed as strings timeList: ['08:00', '08:30', '09:00'], // ranges of time expressed as strings
answers: [ answers: [
{ {
id: 0, id: 0,
text: "no" text: 'no',
}, },
{ {
id: 1, id: 1,
text: "yes" text: 'yes',
}, },
{ {
id: 2, id: 2,
text: "maybe" text: 'maybe',
}, },
{ {
id: 3, id: 3,
text: "maybe" text: 'maybe',
}, },
{ {
id: 4, id: 4,
text: "maybe" text: 'maybe',
}, },
{ {
id: 5, id: 5,
text: "maybe" text: 'maybe',
}, },
{ {
id: 6, id: 6,
text: "maybe" text: 'maybe',
}, },
{ {
id: 7, id: 7,
text: "maybe" text: 'maybe',
}, },
{ {
id: 8, id: 8,
text: "maybe" text: 'maybe',
} },
] ],
}; };

View File

@ -1,569 +1,529 @@
export const mockPoll3 = { export const mockPoll3 = {
"message": "your poll config", message: 'your poll config',
"poll": { poll: {
"id": 4, id: 4,
"title": "dessin animé préféré", title: 'dessin animé préféré',
"customUrl": null, customUrl: null,
"description": "choisissez votre animé préféré", description: 'choisissez votre animé préféré',
"creationDate": { creationDate: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"expiracyDate": { expiracyDate: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"owner": { owner: {
"__initializer__": null, __initializer__: null,
"__cloner__": null, __cloner__: null,
"__isInitialized__": true, __isInitialized__: true,
"pseudo": "tk_TEST", pseudo: 'tk_TEST',
"email": "tktest@tktest.com" email: 'tktest@tktest.com',
}, },
"kind": "text", kind: 'text',
"allowedAnswers": [ allowedAnswers: [
// "yes", "maybe", "no" // "yes", "maybe", "no"
"yes", 'yes',
], ],
"modificationPolicy": "everybody", modificationPolicy: 'everybody',
"mailOnComment": null, mailOnComment: null,
"mailOnVote": null, mailOnVote: null,
"hideResults": null, hideResults: null,
"showResultEvenIfPasswords": null, showResultEvenIfPasswords: null,
"votes": {}, votes: {},
"stacksOfVotes": {}, stacksOfVotes: {},
"choices": {}, choices: {},
"choices_count": { choices_count: {
"counts": { counts: {
"10": { '10': {
"choice_id": 10, choice_id: 10,
"choice_text": "Les mystérieuses cités d'or", choice_text: "Les mystérieuses cités d'or",
"id": 4, id: 4,
"score": 2.5, score: 2.5,
"yes": { yes: {
"count": 2, count: 2,
"people": [ people: ['voting_people_TEST', 'voting_people_TEST'],
"voting_people_TEST",
"voting_people_TEST"
]
}, },
"maybe": { maybe: {
"count": 1, count: 1,
"people": [ people: ['Nikolas Edison'],
"Nikolas Edison"
]
}, },
"no": { no: {
"count": 1, count: 1,
"people": [ people: ['voting_people_TEST'],
"voting_people_TEST"
]
}
}, },
"9": {
"choice_id": 9,
"choice_text": "Boumbo petite automobile",
"id": 5,
"score": 2.5,
"yes": {
"count": 2,
"people": [
"voting_people_TEST",
"Billie Jean"
]
}, },
"maybe": { '9': {
"count": 1, choice_id: 9,
"people": [ choice_text: 'Boumbo petite automobile',
"voting_people_TEST" id: 5,
] score: 2.5,
yes: {
count: 2,
people: ['voting_people_TEST', 'Billie Jean'],
}, },
"no": { maybe: {
"count": 0, count: 1,
"people": [] people: ['voting_people_TEST'],
}
}, },
"12": { no: {
"choice_id": 12, count: 0,
"choice_text": "Foot 2 rue", people: [],
"id": 14,
"score": 0.5,
"yes": {
"count": 0,
"people": []
}, },
"maybe": {
"count": 1,
"people": [
"Nikolas Edison"
]
}, },
"no": { '12': {
"count": 0, choice_id: 12,
"people": [] choice_text: 'Foot 2 rue',
} id: 14,
score: 0.5,
yes: {
count: 0,
people: [],
}, },
"11": { maybe: {
"choice_id": 11, count: 1,
"choice_text": "Les mondes engloutis", people: ['Nikolas Edison'],
"id": 15,
"score": 1.5,
"yes": {
"count": 1,
"people": [
"Billie Jean"
]
}, },
"maybe": { no: {
"count": 1, count: 0,
"people": [ people: [],
"Wulfila"
]
}, },
"no": {
"count": 0,
"people": []
}
}, },
"13": { '11': {
"choice_id": 13, choice_id: 11,
"choice_text": "Le chat, la vache, et l'océan", choice_text: 'Les mondes engloutis',
"id": 16, id: 15,
"score": 1, score: 1.5,
"yes": { yes: {
"count": 1, count: 1,
"people": [ people: ['Billie Jean'],
"Wulfila"
]
}, },
"maybe": { maybe: {
"count": 0, count: 1,
"people": [] people: ['Wulfila'],
}, },
"no": { no: {
"count": 0, count: 0,
"people": [] people: [],
}
}
}, },
"maxScore": 2.5
}, },
"comments": {}, '13': {
"defaultExpiracyDaysFromNow": 60 choice_id: 13,
choice_text: "Le chat, la vache, et l'océan",
id: 16,
score: 1,
yes: {
count: 1,
people: ['Wulfila'],
}, },
"stacks_count": 5, maybe: {
"stacks": [ count: 0,
people: [],
},
no: {
count: 0,
people: [],
},
},
},
maxScore: 2.5,
},
comments: {},
defaultExpiracyDaysFromNow: 60,
},
stacks_count: 5,
stacks: [
{ {
"id": 3, id: 3,
"pseudo": "voting_people_TEST", pseudo: 'voting_people_TEST',
"creation_date": { creation_date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"votes": { votes: {
"8": { '8': {
"choice_id": 8 choice_id: 8,
}, },
"9": { '9': {
"id": 3, id: 3,
"vote_id": 5, vote_id: 5,
"value": "maybe", value: 'maybe',
"choice_id": 9, choice_id: 9,
"text": "Boumbo petite automobile" text: 'Boumbo petite automobile',
}, },
"10": { '10': {
"id": 3, id: 3,
"vote_id": 4, vote_id: 4,
"value": "yes", value: 'yes',
"choice_id": 10, choice_id: 10,
"text": "Les mystérieuses cités d'or" text: "Les mystérieuses cités d'or",
}, },
"11": { '11': {
"choice_id": 11 choice_id: 11,
}, },
"12": { '12': {
"choice_id": 12 choice_id: 12,
},
'13': {
choice_id: 13,
},
'14': {
choice_id: 14,
}, },
"13": {
"choice_id": 13
}, },
"14": {
"choice_id": 14
}
}
}, },
{ {
"id": 4, id: 4,
"pseudo": "voting_people_TEST", pseudo: 'voting_people_TEST',
"creation_date": { creation_date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"votes": { votes: {
"8": { '8': {
"choice_id": 8 choice_id: 8,
}, },
"9": { '9': {
"id": 4, id: 4,
"vote_id": 6, vote_id: 6,
"value": "yes", value: 'yes',
"choice_id": 9, choice_id: 9,
"text": "Boumbo petite automobile" text: 'Boumbo petite automobile',
}, },
"10": { '10': {
"id": 4, id: 4,
"vote_id": 8, vote_id: 8,
"value": "no", value: 'no',
"choice_id": 10, choice_id: 10,
"text": "Les mystérieuses cités d'or" text: "Les mystérieuses cités d'or",
}, },
"11": { '11': {
"choice_id": 11 choice_id: 11,
}, },
"12": { '12': {
"choice_id": 12 choice_id: 12,
},
'13': {
choice_id: 13,
},
'14': {
choice_id: 14,
}, },
"13": {
"choice_id": 13
}, },
"14": {
"choice_id": 14
}
}
}, },
{ {
"id": 7, id: 7,
"pseudo": "Nikolas Edison", pseudo: 'Nikolas Edison',
"creation_date": { creation_date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"votes": { votes: {
"8": { '8': {
"choice_id": 8 choice_id: 8,
}, },
"9": { '9': {
"choice_id": 9 choice_id: 9,
}, },
"10": { '10': {
"id": 7, id: 7,
"vote_id": 13, vote_id: 13,
"value": "maybe", value: 'maybe',
"choice_id": 10, choice_id: 10,
"text": "Les mystérieuses cités d'or" text: "Les mystérieuses cités d'or",
}, },
"11": { '11': {
"choice_id": 11 choice_id: 11,
}, },
"12": { '12': {
"id": 7, id: 7,
"vote_id": 14, vote_id: 14,
"value": "maybe", value: 'maybe',
"choice_id": 12, choice_id: 12,
"text": "Foot 2 rue" text: 'Foot 2 rue',
},
'13': {
choice_id: 13,
},
'14': {
choice_id: 14,
}, },
"13": {
"choice_id": 13
}, },
"14": {
"choice_id": 14
}
}
}, },
{ {
"id": 8, id: 8,
"pseudo": "Wulfila", pseudo: 'Wulfila',
"creation_date": { creation_date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"votes": { votes: {
"8": { '8': {
"choice_id": 8 choice_id: 8,
}, },
"9": { '9': {
"choice_id": 9 choice_id: 9,
}, },
"10": { '10': {
"choice_id": 10 choice_id: 10,
}, },
"11": { '11': {
"id": 8, id: 8,
"vote_id": 15, vote_id: 15,
"value": "maybe", value: 'maybe',
"choice_id": 11, choice_id: 11,
"text": "Les mondes engloutis" text: 'Les mondes engloutis',
}, },
"12": { '12': {
"choice_id": 12 choice_id: 12,
},
'13': {
id: 8,
vote_id: 16,
value: 'yes',
choice_id: 13,
text: "Le chat, la vache, et l'océan",
},
'14': {
choice_id: 14,
}, },
"13": {
"id": 8,
"vote_id": 16,
"value": "yes",
"choice_id": 13,
"text": "Le chat, la vache, et l'océan"
}, },
"14": {
"choice_id": 14
}
}
}, },
{ {
"id": 9, id: 9,
"pseudo": "Billie Jean", pseudo: 'Billie Jean',
"creation_date": { creation_date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"votes": { votes: {
"8": { '8': {
"choice_id": 8 choice_id: 8,
}, },
"9": { '9': {
"id": 9, id: 9,
"vote_id": 17, vote_id: 17,
"value": "yes", value: 'yes',
"choice_id": 9, choice_id: 9,
"text": "Boumbo petite automobile" text: 'Boumbo petite automobile',
}, },
"10": { '10': {
"choice_id": 10 choice_id: 10,
}, },
"11": { '11': {
"id": 9, id: 9,
"vote_id": 18, vote_id: 18,
"value": "yes", value: 'yes',
"choice_id": 11, choice_id: 11,
"text": "Les mondes engloutis" text: 'Les mondes engloutis',
},
'12': {
choice_id: 12,
},
'13': {
choice_id: 13,
},
'14': {
choice_id: 14,
}, },
"12": {
"choice_id": 12
}, },
"13": {
"choice_id": 13
}, },
"14": {
"choice_id": 14
}
}
}
], ],
"choices_count": { choices_count: {
"counts": { counts: {
"10": { '10': {
"choice_id": 10, choice_id: 10,
"choice_text": "Les mystérieuses cités d'or", choice_text: "Les mystérieuses cités d'or",
"id": 4, id: 4,
"score": 2.5, score: 2.5,
"yes": { yes: {
"count": 2, count: 2,
"people": [ people: ['voting_people_TEST', 'voting_people_TEST'],
"voting_people_TEST",
"voting_people_TEST"
]
}, },
"maybe": { maybe: {
"count": 1, count: 1,
"people": [ people: ['Nikolas Edison'],
"Nikolas Edison"
]
}, },
"no": { no: {
"count": 1, count: 1,
"people": [ people: ['voting_people_TEST'],
"voting_people_TEST"
]
}
}, },
"9": {
"choice_id": 9,
"choice_text": "Boumbo petite automobile",
"id": 5,
"score": 2.5,
"yes": {
"count": 2,
"people": [
"voting_people_TEST",
"Billie Jean"
]
}, },
"maybe": { '9': {
"count": 1, choice_id: 9,
"people": [ choice_text: 'Boumbo petite automobile',
"voting_people_TEST" id: 5,
] score: 2.5,
yes: {
count: 2,
people: ['voting_people_TEST', 'Billie Jean'],
}, },
"no": { maybe: {
"count": 0, count: 1,
"people": [] people: ['voting_people_TEST'],
}
}, },
"12": { no: {
"choice_id": 12, count: 0,
"choice_text": "Foot 2 rue", people: [],
"id": 14,
"score": 0.5,
"yes": {
"count": 0,
"people": []
}, },
"maybe": {
"count": 1,
"people": [
"Nikolas Edison"
]
}, },
"no": { '12': {
"count": 0, choice_id: 12,
"people": [] choice_text: 'Foot 2 rue',
} id: 14,
score: 0.5,
yes: {
count: 0,
people: [],
}, },
"11": { maybe: {
"choice_id": 11, count: 1,
"choice_text": "Les mondes engloutis", people: ['Nikolas Edison'],
"id": 15,
"score": 1.5,
"yes": {
"count": 1,
"people": [
"Billie Jean"
]
}, },
"maybe": { no: {
"count": 1, count: 0,
"people": [ people: [],
"Wulfila"
]
}, },
"no": {
"count": 0,
"people": []
}
}, },
"13": { '11': {
"choice_id": 13, choice_id: 11,
"choice_text": "Le chat, la vache, et l'océan", choice_text: 'Les mondes engloutis',
"id": 16, id: 15,
"score": 1, score: 1.5,
"yes": { yes: {
"count": 1, count: 1,
"people": [ people: ['Billie Jean'],
"Wulfila"
]
}, },
"maybe": { maybe: {
"count": 0, count: 1,
"people": [] people: ['Wulfila'],
}, },
"no": { no: {
"count": 0, count: 0,
"people": [] people: [],
}
}
}, },
"maxScore": 2.5
}, },
"choices": [ '13': {
choice_id: 13,
choice_text: "Le chat, la vache, et l'océan",
id: 16,
score: 1,
yes: {
count: 1,
people: ['Wulfila'],
},
maybe: {
count: 0,
people: [],
},
no: {
count: 0,
people: [],
},
},
},
maxScore: 2.5,
},
choices: [
{ {
"id": 8, id: 8,
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"text": "Vic le viking", text: 'Vic le viking',
"url": null url: null,
}, },
{ {
"id": 9, id: 9,
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"text": "Boumbo petite automobile", text: 'Boumbo petite automobile',
"url": null url: null,
}, },
{ {
"id": 10, id: 10,
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"text": "Les mystérieuses cités d'or", text: "Les mystérieuses cités d'or",
"url": null url: null,
}, },
{ {
"id": 11, id: 11,
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"text": "Les mondes engloutis", text: 'Les mondes engloutis',
"url": null url: null,
}, },
{ {
"id": 12, id: 12,
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"text": "Foot 2 rue", text: 'Foot 2 rue',
"url": null url: null,
}, },
{ {
"id": 13, id: 13,
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
}, },
"text": "Le chat, la vache, et l'océan", text: "Le chat, la vache, et l'océan",
"url": null url: null,
}, },
{ {
"id": 14, id: 14,
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
},
text: 'Digimon',
url: null,
}, },
"text": "Digimon",
"url": null
}
], ],
"comments": [ comments: [
{ {
"id": 3, id: 3,
"text": "allez boumbo!", text: 'allez boumbo!',
"pseudo": "tk_TEST_commentateur", pseudo: 'tk_TEST_commentateur',
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
} },
}, },
{ {
"id": 4, id: 4,
"text": "je suis pour la team rocket de digimon", text: 'je suis pour la team rocket de digimon',
"pseudo": "tk_TEST", pseudo: 'tk_TEST',
"date": { date: {
"date": "2020-01-30 12:25:13.000000", date: '2020-01-30 12:25:13.000000',
"timezone_type": 3, timezone_type: 3,
"timezone": "Europe/Berlin" timezone: 'Europe/Berlin',
} },
} },
], ],
"comments_count": 2 comments_count: 2,
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,43 +1,44 @@
export const mockMyPolls = export const mockMyPolls = [
[{ {
"id": 1000001, id: 1000001,
"title": "blehehehe heh hehhe e test1", title: 'blehehehe heh hehhe e test1',
"customUrl": null, customUrl: null,
"description": "maaaaaaaaaaah", description: 'maaaaaaaaaaah',
"creationDate": {"date": "2020-01-20 14:21:16.270157", "timezone_type": 3, "timezone": "Europe/Paris"}, creationDate: { date: '2020-01-20 14:21:16.270157', timezone_type: 3, timezone: 'Europe/Paris' },
"expiracyDate": {"date": "2020-01-20 14:21:16.270178", "timezone_type": 3, "timezone": "Europe/Paris"}, expiracyDate: { date: '2020-01-20 14:21:16.270178', timezone_type: 3, timezone: 'Europe/Paris' },
"owner": null, owner: null,
"kind": "text", kind: 'text',
"allowedAnswers": ["yes"], allowedAnswers: ['yes'],
"modificationPolicy": "nobody", modificationPolicy: 'nobody',
"mailOnComment": null, mailOnComment: null,
"mailOnVote": null, mailOnVote: null,
"hideResults": null, hideResults: null,
"showResultEvenIfPasswords": null, showResultEvenIfPasswords: null,
"votes": {}, votes: {},
"stacksOfVotes": {}, stacksOfVotes: {},
"choices": {}, choices: {},
"comments": {}, comments: {},
"defaultExpiracyDaysFromNow": 60 defaultExpiracyDaysFromNow: 60,
}, { },
"id": 1000002, {
"title": "bleh z zr erth tuyjikioy yylil test2", id: 1000002,
"customUrl": null, title: 'bleh z zr erth tuyjikioy yylil test2',
"description": "maaaaaaaaaaah 2", customUrl: null,
"creationDate": {"date": "2020-01-20 14:21:16.270157", "timezone_type": 3, "timezone": "Europe/Paris"}, description: 'maaaaaaaaaaah 2',
"expiracyDate": {"date": "2020-01-20 14:21:16.270178", "timezone_type": 3, "timezone": "Europe/Paris"}, creationDate: { date: '2020-01-20 14:21:16.270157', timezone_type: 3, timezone: 'Europe/Paris' },
"owner": null, expiracyDate: { date: '2020-01-20 14:21:16.270178', timezone_type: 3, timezone: 'Europe/Paris' },
"kind": "text", owner: null,
"allowedAnswers": ["yes"], kind: 'text',
"modificationPolicy": "nobody", allowedAnswers: ['yes'],
"mailOnComment": null, modificationPolicy: 'nobody',
"mailOnVote": null, mailOnComment: null,
"hideResults": null, mailOnVote: null,
"showResultEvenIfPasswords": null, hideResults: null,
"votes": {}, showResultEvenIfPasswords: null,
"stacksOfVotes": {}, votes: {},
"choices": {}, stacksOfVotes: {},
"comments": {}, choices: {},
"defaultExpiracyDaysFromNow": 60 comments: {},
}] defaultExpiracyDaysFromNow: 60,
; },
];

View File

@ -1,10 +1,10 @@
import {Directive, ElementRef, forwardRef, HostListener, Renderer2} from '@angular/core'; import { Directive, ElementRef, forwardRef, HostListener, Renderer2 } from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
export const DATE_VALUE_ACCESSOR: any = { export const DATE_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DateValueAccessor), useExisting: forwardRef(() => DateValueAccessor),
multi: true multi: true,
}; };
/** /**
@ -19,17 +19,13 @@ export const DATE_VALUE_ACCESSOR: any = {
// this selector is an opt-in version // this selector is an opt-in version
selector: '[useValueAsDate]', selector: '[useValueAsDate]',
providers: [DATE_VALUE_ACCESSOR] providers: [DATE_VALUE_ACCESSOR],
}) })
export class DateValueAccessor implements ControlValueAccessor { export class DateValueAccessor implements ControlValueAccessor {
@HostListener('input', ['$event.target.valueAsDate']) onChange = (_: any) => {};
@HostListener('blur', []) onTouched = () => {};
@HostListener('input', ['$event.target.valueAsDate']) onChange = (_: any) => { constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
};
@HostListener('blur', []) onTouched = () => {
};
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {
}
writeValue(value: Date): void { writeValue(value: Date): void {
if (!value) { if (!value) {

View File

@ -1,3 +1,2 @@
export * from './module'; export * from './module';
export * from './date-value-accessor'; export * from './date-value-accessor';

View File

@ -3,6 +3,6 @@ import { DateValueAccessor } from './date-value-accessor';
@NgModule({ @NgModule({
declarations: [DateValueAccessor], declarations: [DateValueAccessor],
exports: [DateValueAccessor] exports: [DateValueAccessor],
}) })
export class DateValueAccessorModule { } export class DateValueAccessorModule {}

View File

@ -1,52 +1,30 @@
<div class="well debug" > <div class="well debug">
<strong > <strong>
<h2 i18n > <h2 i18n>
infos de debug - environement de Dev infos de debug - environement de Dev
</h2 > </h2>
<span class="demo" > <span class="demo">
{{"config.demo"|translate}} {{ 'config.demo' | translate }}
</span > </span>
</strong > </strong>
<ul > <ul>
<li > <li>étape actuelle {{ config.step }} / {{ config.stepMax }}</li>
étape actuelle {{config.step}} / {{config.stepMax}} <li>formulaire valide : {{ formIsValid }}</li>
</li > <li>type de formulaire: {{ config.pollType }}</li>
<li > </ul>
formulaire valide : {{formIsValid}} <button class="btn btn--primary" i18n (click)="config.createPoll()">
</li >
<li >
type de formulaire: {{config.pollType}}
</li >
</ul >
<button
class="btn btn--primary"
i18n
(click)="config.createPoll()"
>
Envoyer le formulaire Envoyer le formulaire
</button > </button>
<button <button class="btn btn--primary" i18n (click)="config.getPollById('1', 'example password')">
class="btn btn--primary"
i18n
(click)="config.getPollById( '1', 'example password')"
>
get poll 1 get poll 1
</button > </button>
<button <button class="btn btn--primary" i18n (click)="config.getMyPolls('tktest@tktest.com')">
class="btn btn--primary"
i18n
(click)="config.getMyPolls( 'tktest@tktest.com')"
>
get my polls get my polls
</button > </button>
<button <button class="btn btn--success" (click)="launchToast()">
class="btn btn--success"
(click)="launchToast()" >
launch success toast launch success toast
</button > </button>
<a <a [routerLink]="'/vote/poll/id/3'" class="btn btn--success">
[routerLink]="'/vote/poll/id/3'"
class="btn btn--success" >
See example of vote page See example of vote page
</a > </a>
</div > </div>

View File

@ -8,9 +8,8 @@ describe('DebuggerComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ DebuggerComponent ] declarations: [DebuggerComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,19 +1,17 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {ConfigService} from '../services/config.service'; import { ConfigService } from '../services/config.service';
@Component({ @Component({
selector: 'framadate-debugger', selector: 'framadate-debugger',
templateUrl: './debugger.component.html', templateUrl: './debugger.component.html',
styleUrls: ['./debugger.component.scss'] styleUrls: ['./debugger.component.scss'],
}) })
export class DebuggerComponent implements OnInit { export class DebuggerComponent implements OnInit {
formIsValid = true; formIsValid = true;
constructor(public config: ConfigService) { constructor(public config: ConfigService) {}
}
ngOnInit() { ngOnInit() {}
}
selectOption(key: string, val: any) { selectOption(key: string, val: any) {
if (!this.config[key]) { if (!this.config[key]) {
@ -25,6 +23,6 @@ export class DebuggerComponent implements OnInit {
} }
launchToast() { launchToast() {
this.config.handleError({message: "hop"}) this.config.handleError({ message: 'hop' });
} }
} }

View File

@ -8,9 +8,8 @@ describe('HeaderComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ HeaderComponent ] declarations: [HeaderComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -3,13 +3,10 @@ import { Component, OnInit } from '@angular/core';
@Component({ @Component({
selector: 'framadate-header', selector: 'framadate-header',
templateUrl: './header.component.html', templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'] styleUrls: ['./header.component.scss'],
}) })
export class HeaderComponent implements OnInit { export class HeaderComponent implements OnInit {
constructor() {}
constructor() { } ngOnInit() {}
ngOnInit() {
}
} }

View File

@ -2,153 +2,147 @@
<h1>Nom du sondage</h1> <h1>Nom du sondage</h1>
<!--Infos--> <!--Infos-->
<h2>{{"admin.info_section_title"|translate}}</h2> <h2>{{ 'admin.info_section_title' | translate }}</h2>
<label for="title"> <label for="title">
{{"admin.choose_title"|translate}} {{ 'admin.choose_title' | translate }}
</label> </label>
<input type="text" name="title"> <input type="text" name="title" />
<label for="desc"> <label for="desc">
{{"admin.description"|translate}} {{ 'admin.description' | translate }}
</label> </label>
<textarea name="desc"> </textarea> <textarea name="desc"> </textarea>
<label for="name"> <label for="name">
{{"creation.name"|translate}} {{ 'creation.name' | translate }}
</label> </label>
<input type="text" name="name"> <input type="text" name="name" />
<!--Params--> <!--Params-->
<h2>{{"admin.settings_section_title"|translate}}</h2> <h2>{{ 'admin.settings_section_title' | translate }}</h2>
<h3>{{"visibility.title"|translate}}</h3> <h3>{{ 'visibility.title' | translate }}</h3>
<section class="row"> <section class="row">
<label for="answer-visible"> <label for="answer-visible">
{{"visibility.visibility_want"|translate}} {{ 'visibility.visibility_want' | translate }}
</label> </label>
<select name="answer-visible"> <select name="answer-visible">
<option value="all" selected> <option value="all" selected>
{{"visibility.visibility_link"|translate}} {{ 'visibility.visibility_link' | translate }}
</option> </option>
<option value="per"> <option value="per">
{{"visibility.visibility_nobody"|translate}} {{ 'visibility.visibility_nobody' | translate }}
</option> </option>
</select> </select>
<label for="answer-visible"> <label for="answer-visible">
{{"visibility.visibility_see"|translate}} {{ 'visibility.visibility_see' | translate }}
</label> </label>
</section> </section>
<h3>{{"visibility.votes"|translate}}</h3> <h3>{{ 'visibility.votes' | translate }}</h3>
<section> <section>
<label for="vote-date"> <label for="vote-date">
{{"visibility.archiving"|translate}} {{ 'visibility.archiving' | translate }}
</label> </label>
<input type="date" name="vote-date"> <input type="date" name="vote-date" />
</section> </section>
<section> <section>
<label for="alter-vote"> <label for="alter-vote">
{{"visibility.archiving_start"|translate}} {{ 'visibility.archiving_start' | translate }}
</label> </label>
<select name="alter-vote"> <select name="alter-vote">
<option value="yes" selected> <option value="yes" selected>
{{"visibility.archiving_can"|translate}} {{ 'visibility.archiving_can' | translate }}
</option> </option>
<option value="no"> <option value="no">
{{"visibility.archiving_can_not"|translate}} {{ 'visibility.archiving_can_not' | translate }}
</option> </option>
</select> </select>
<label for="type-vote"> <label for="type-vote">
{{"visibility.archiving_end"|translate}} {{ 'visibility.archiving_end' | translate }}
</label> </label>
<select name="type-vote"> <select name="type-vote">
<option value="solo" selected> <option value="solo" selected>
{{"visibility.modfiy_their"|translate}} {{ 'visibility.modfiy_their' | translate }}
</option> </option>
<option value="all"> <option value="all">
{{"visibility.modfiy_everyone"|translate}} {{ 'visibility.modfiy_everyone' | translate }}
</option> </option>
</select> </select>
</section> </section>
<label for="del-vote"> <label for="del-vote">
{{"admin.votes_deletion_desc"|translate}} {{ 'admin.votes_deletion_desc' | translate }}
</label> </label>
<button class="btn btn--alert btn--outline" <button class="btn btn--alert btn--outline" (click)="config.deleteVotes()">
(click)="config.deleteVotes()"
>
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
{{'admin.votes_deletion_btn'|translate}} {{ 'admin.votes_deletion_btn' | translate }}
<i class="fa fa-object-group"></i></button> <i class="fa fa-object-group"></i>
</button>
<h3>{{"admin.comments_deletion_title"|translate}}</h3> <h3>{{ 'admin.comments_deletion_title' | translate }}</h3>
<label for="del-com"> <label for="del-com">
{{"admin.comments_deletion_desc"|translate}} {{ 'admin.comments_deletion_desc' | translate }}
</label> </label>
<button class="btn btn--alert btn--outline" <button class="btn btn--alert btn--outline" (click)="config.deleteComments()">
(click)="config.deleteComments()"
>
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
{{'admin.comments_deletion_btn'|translate}} {{ 'admin.comments_deletion_btn' | translate }}
<i class="fa fa-comments-o"></i></button> <i class="fa fa-comments-o"></i>
</button>
<h3>{{"admin.archiving_title"|translate}}</h3> <h3>{{ 'admin.archiving_title' | translate }}</h3>
<section class="row"> <section class="row">
<label for="arch"> <label for="arch">
{{"admin.archiving_desc"|translate}} {{ 'admin.archiving_desc' | translate }}
</label> </label>
<input type="date" name="arch"> <input type="date" name="arch" />
</section> </section>
<h3>{{"visibility.access"|translate}}</h3> <h3>{{ 'visibility.access' | translate }}</h3>
<section class="row"> <section class="row">
<label for="password">Je</label> <label for="password">Je</label>
<select name="password"> <select name="password">
<option value="yes" selected> <option value="yes" selected>
{{"visibility.access_want_yes"|translate}} {{ 'visibility.access_want_yes' | translate }}
</option> </option>
<option value="no"> <option value="no">
{{"visibility.access_want_no"|translate}} {{ 'visibility.access_want_no' | translate }}
</option> </option>
</select> </select>
<label for="alter-vote"> <label for="alter-vote">
{{"visibility.access_protect"|translate}} {{ 'visibility.access_protect' | translate }}
</label> </label>
</section> </section>
<h3>{{"admin.deletion"|translate}}</h3> <h3>{{ 'admin.deletion' | translate }}</h3>
<label for="del"> {{"admin.deletion_desc"|translate}} </label> <label for="del"> {{ 'admin.deletion_desc' | translate }} </label>
<input class="btn btn--alert" type="submit" <input class="btn btn--alert" type="submit" name="del" value="{{ 'admin.deletion_btn' | translate }}" />
name="del" value="{{'admin.deletion_btn'|translate}}">
<!-- Access link --> <!-- Access link -->
<h2>{{"admin.link"|translate}}</h2> <h2>{{ 'admin.link' | translate }}</h2>
<h3>{{"admin.link_admin"|translate}}</h3> <h3>{{ 'admin.link_admin' | translate }}</h3>
<label for="copy-link-admin"> <label for="copy-link-admin">
{{"admin.link_admin_desc"|translate}} {{ 'admin.link_admin_desc' | translate }}
https://framadate.org/urladmindusondage https://framadate.org/urladmindusondage
</label> </label>
<input class="btn btn--mini" type="submit" name="copy-link-admin" <input class="btn btn--mini" type="submit" name="copy-link-admin" value="{{ 'admin.copy_link' | translate }}" />
value="{{'admin.copy_link'|translate}}"> <a href="#" class="next">{{ 'admin.link_admin_btn' | translate }}</a>
<a href="#" class="next">{{"admin.link_admin_btn"|translate}}</a>
<h3>{{"admin.polled_people"|translate}}</h3> <h3>{{ 'admin.polled_people' | translate }}</h3>
<label for="copy-link"> <label for="copy-link">
{{"admin.polled_people_desc"|translate}} {{ 'admin.polled_people_desc' | translate }}
{{config.urlPublic}}</label> {{ config.urlPublic }}</label
<input class="btn btn--mini" type="submit" name="copy-link" >
value="{{'admin.copy_link'|translate}}"> <input class="btn btn--mini" type="submit" name="copy-link" value="{{ 'admin.copy_link' | translate }}" />
<a href="#" class="next">{{"admin.polled_people_btn"|translate}}</a> <a href="#" class="next">{{ 'admin.polled_people_btn' | translate }}</a>
<h3>{{"admin.email_links"|translate}}</h3>
<label for="mail">{{"admin.email_links_desc"|translate}}</label>
<input type="email" name="mail">
<input class="btn btn--mini" type="submit" name="send-mail"
value="{{'admin.email_links_btn'|translate}}">
<h3>{{ 'admin.email_links' | translate }}</h3>
<label for="mail">{{ 'admin.email_links_desc' | translate }}</label>
<input type="email" name="mail" />
<input class="btn btn--mini" type="submit" name="send-mail" value="{{ 'admin.email_links_btn' | translate }}" />
</form> </form>
<p-confirmDialog header="Confirmation" icon="pi pi-exclamation-triangle"></p-confirmDialog> <p-confirmDialog header="Confirmation" icon="pi pi-exclamation-triangle"></p-confirmDialog>

View File

@ -1,39 +1,41 @@
form{ form {
display:flex; display: flex;
flex-direction: column; flex-direction: column;
width:340px; width: 340px;
margin:auto; margin: auto;
} }
.row{ .row {
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
padding-bottom: 65px; padding-bottom: 65px;
} }
textarea{ textarea {
height:115px; height: 115px;
margin-bottom: 50px; margin-bottom: 50px;
} }
label{ label {
padding-bottom: 10px; padding-bottom: 10px;
flex-wrap: wrap; flex-wrap: wrap;
} }
h2,h1{ h2,
h1 {
margin-bottom: 40px; margin-bottom: 40px;
} }
h2{ h2 {
margin-top: 40px; margin-top: 40px;
padding-left:16px; padding-left: 16px;
} }
.btn--alert{ .btn--alert {
font-weight: 600; font-weight: 600;
} }
h3{ h3 {
padding-left: 28px; padding-left: 28px;
padding-bottom:15px; padding-bottom: 15px;
} }
select,input[type=date]{ select,
input[type='date'] {
max-width: 130px; max-width: 130px;
} }
.btn--outline{ .btn--outline {
margin-bottom: 70px; margin-bottom: 70px;
} }

View File

@ -8,9 +8,8 @@ describe('AdminComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ AdminComponent ] declarations: [AdminComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,17 +1,13 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {ConfigService} from '../../services/config.service'; import { ConfigService } from '../../services/config.service';
@Component({ @Component({
selector: 'framadate-admin', selector: 'framadate-admin',
templateUrl: './admin.component.html', templateUrl: './admin.component.html',
styleUrls: ['./admin.component.scss'] styleUrls: ['./admin.component.scss'],
}) })
export class AdminComponent implements OnInit { export class AdminComponent implements OnInit {
constructor(public config: ConfigService) {}
constructor(public config: ConfigService) { ngOnInit() {}
}
ngOnInit() {
}
} }

View File

@ -1,102 +1,76 @@
<div class="answers" > <div class="answers">
<h1 i18n > <h1 i18n>
Choisir les propositions Choisir les propositions
</h1 > </h1>
<p <p class="subtitle" i18n>
class="subtitle"
i18n >
Vous pouvez utiliser la syntaxe markdown, et naviguer entre les inputs avec les flèches du clavier. Vous pouvez utiliser la syntaxe markdown, et naviguer entre les inputs avec les flèches du clavier.
</p > </p>
<ol > <ol>
<li <li #answers *ngFor="let answer of config.answers; index as i; trackBy: trackFunction" class="answer-item">
#answers <button class="btn btn--default" title="ajouter une image" (click)="showModalForPictureOfAnswer(answer)">
*ngFor="let answer of config.answers; index as i;trackBy trackFunction" <i class="fa fa-image"></i>
class="answer-item" > </button>
<button <label for="answer_{{ answer.id }}_url" (click)="showModalForPictureOfAnswer(answer)">
class='btn btn--default' <img class="img-thumbnail" src="{{ answer.url }}" alt="image {{ answer.url }}" />
title='ajouter une image' </label>
(click)='showModalForPictureOfAnswer(answer)' > <p-dialog class="url-dialog" [(visible)]="display" [modal]="true">
<i class='fa fa-image' ></i > <p-header>
</button > {{ answer.text }}
<label </p-header>
for='answer_{{answer.id}}_url'
(click)='showModalForPictureOfAnswer(answer)' >
<img <form action="#" (submit)="display = false">
class='img-thumbnail' <label for="answer_{{ answer.id }}_url">
src='{{answer.url}}'
alt='image {{answer.url}}' >
</label >
<p-dialog
class='url-dialog'
[(visible)]="display"
[modal]='true' >
<p-header >
{{answer.text}}
</p-header >
<form
action='#'
(submit)='display=false' >
<label for='answer_{{answer.id}}_url' >
Choisissez une URL pour illustrer le choix de réponse Choisissez une URL pour illustrer le choix de réponse
</label > </label>
<i class='fa fa-image' ></i > <i class="fa fa-image"></i>
<br > <br />
<input <input
class='input is-block' class="input is-block"
id='answer_{{answer.id}}_url' id="answer_{{ answer.id }}_url"
type='text' type="text"
autofocus='autofocus' autofocus="autofocus"
name='answer-url' name="answer-url"
[(ngModel)]='answer.url' > [(ngModel)]="answer.url"
/>
</form > </form>
</p-dialog>
</p-dialog >
<input <input
type="name" type="name"
class="answer" class="answer"
id='answer_{{answer.id}}' id="answer_{{ answer.id }}"
[(ngModel)]="answer.text" [(ngModel)]="answer.text"
(keyup.enter)="addAnswer()" (keyup.enter)="addAnswer()"
(keyup)="navigateOrDelete($event,i)" (keyup)="navigateOrDelete($event, i)"
required='required' required="required"
placeholder="réponse" placeholder="réponse"
> />
<button <button class="btn btn--alert" (click)="config.answers.splice(i, 1)">X</button>
class="btn btn--alert" </li>
(click)="config.answers.splice(i,1)" >X </ol>
</button >
</li >
</ol >
<button <button
class="btn btn--primary btn--outline" class="btn btn--primary btn--outline"
(click)="addAnswer()" (click)="addAnswer()"
[ngClass]="{'btn--primary': allAnswersAreValid}" [ngClass]="{ 'btn--primary': allAnswersAreValid }"
i18n i18n
> >
<i class='fa fa-plus' ></i > <i class="fa fa-plus"></i>
Ajouter une proposition Ajouter une proposition
</button > </button>
<br > <br />
<button <button
[routerLink]="'/step/resume'" [routerLink]="'/step/resume'"
class="btn btn--full " class="btn btn--full"
i18n i18n
[ngClass]="{'btn--primary': allAnswersAreValid}" [ngClass]="{ 'btn--primary': allAnswersAreValid }"
[disabled]='!allAnswersAreValid' [disabled]="!allAnswersAreValid"
> >
Voyons ce que ça donne Voyons ce que ça donne
</button > </button>
<br > <br />
<a <a [routerLink]="'/home'" class="prev" i18n>
[routerLink]="'/home'"
class="prev"
i18n >
Retour Retour
</a > </a>
</div > </div>

View File

@ -8,9 +8,8 @@ describe('AnswersComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ AnswersComponent ] declarations: [AnswersComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,41 +1,36 @@
import {AfterViewInit, ChangeDetectorRef, Component, Inject, OnChanges, OnInit} from '@angular/core'; import { AfterViewInit, ChangeDetectorRef, Component, Inject, OnChanges, OnInit } from '@angular/core';
import {BaseComponent} from '../base-page/base.component'; import { BaseComponent } from '../base-page/base.component';
import {ConfigService} from '../../services/config.service'; import { ConfigService } from '../../services/config.service';
import {DOCUMENT} from '@angular/common'; import { DOCUMENT } from '@angular/common';
@Component({ @Component({
selector: 'framadate-answers', selector: 'framadate-answers',
templateUrl: './answers.component.html', templateUrl: './answers.component.html',
styleUrls: ['./answers.component.scss'] styleUrls: ['./answers.component.scss'],
}) })
export class AnswersComponent extends BaseComponent implements OnInit, AfterViewInit, OnChanges { export class AnswersComponent extends BaseComponent implements OnInit, AfterViewInit, OnChanges {
allAnswersAreValid = false; allAnswersAreValid = false;
answerList = []; answerList = [];
currentHeader: any = ""; currentHeader: any = '';
display: boolean; display: boolean;
constructor(public config: ConfigService, constructor(public config: ConfigService, @Inject(DOCUMENT) private document: any, private cd: ChangeDetectorRef) {
@Inject(DOCUMENT) private document: any,
private cd: ChangeDetectorRef) {
super(config); super(config);
this.answerList = this.config.answers; this.answerList = this.config.answers;
} }
// todo, manage validation of each page in a common way // todo, manage validation of each page in a common way
ngOnInit() { ngOnInit() {}
}
ngOnChanges() { ngOnChanges() {
this.checkValidAnswers(); this.checkValidAnswers();
} }
checkValidAnswers() { checkValidAnswers() {
this.allAnswersAreValid = true; this.allAnswersAreValid = true;
this.config.answers.forEach(answer => { this.config.answers.forEach((answer) => {
if (!answer.text.length) { if (!answer.text.length) {
this.allAnswersAreValid = false; this.allAnswersAreValid = false;
return; return;
@ -53,18 +48,17 @@ export class AnswersComponent extends BaseComponent implements OnInit, AfterView
} }
addAnswer() { addAnswer() {
this.config.answers.push( this.config.answers.push({
{
id: this.config.answers.length + 1, id: this.config.answers.length + 1,
text: '', text: '',
url: '', url: '',
file: '', file: '',
literal: '', literal: '',
date_object: null, date_object: null,
timeList: [] timeList: [],
}); });
this.cd.detectChanges(); // to refresh the view before focusing on the new input this.cd.detectChanges(); // to refresh the view before focusing on the new input
this.focusOnAnswer(this.config.answers.length - 1) this.focusOnAnswer(this.config.answers.length - 1);
} }
focusOnAnswer(i) { focusOnAnswer(i) {
@ -79,13 +73,13 @@ export class AnswersComponent extends BaseComponent implements OnInit, AfterView
} }
navigateOrDelete(event: KeyboardEvent, i) { navigateOrDelete(event: KeyboardEvent, i) {
if (event.ctrlKey && event.key == "d") { if (event.ctrlKey && event.key == 'd') {
this.config.answers.splice(i, 1) this.config.answers.splice(i, 1);
} }
if (event.key == "ArrowUp" && i > 0) { if (event.key == 'ArrowUp' && i > 0) {
this.focusOnAnswer(i - 1); this.focusOnAnswer(i - 1);
} }
if (event.key == "ArrowDown" && i < this.config.answers.length) { if (event.key == 'ArrowDown' && i < this.config.answers.length) {
this.focusOnAnswer(i + 1); this.focusOnAnswer(i + 1);
} }
} }

View File

@ -1,4 +1,4 @@
<h1>Ce composant est celui de base pour les pages</h1> <h1>Ce composant est celui de base pour les pages</h1>
<a [routerLink]="'/step/end'" class="btn btn-block" i18n="@@confirm"> <a [routerLink]="'/step/end'" class="btn btn-block" i18n="@@confirm">
{{"config.perfect"|translate}} {{ 'config.perfect' | translate }}
</a> </a>

View File

@ -8,9 +8,8 @@ describe('BaseComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ BaseComponent ] declarations: [BaseComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,22 +1,18 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {ConfigService} from '../../services/config.service'; import { ConfigService } from '../../services/config.service';
@Component({ @Component({
selector: 'framadate-base-page', selector: 'framadate-base-page',
templateUrl: './base.component.html', templateUrl: './base.component.html',
styleUrls: ['./base.component.scss'] styleUrls: ['./base.component.scss'],
}) })
/** /**
* base page is aware of the state of the filling * base page is aware of the state of the filling
*/ */
export class BaseComponent implements OnInit { export class BaseComponent implements OnInit {
constructor(public config: ConfigService) {}
constructor(public config: ConfigService) { ngOnInit() {}
}
ngOnInit() {
}
checkValidity() { checkValidity() {
// TODO with form controls // TODO with form controls

View File

@ -1,46 +1,33 @@
<div class="container" > <div class="container">
<div class="columns"> <div class="columns">
<div class="column" id="newPoll"> <div class="column" id="newPoll">
<section class="creation">
<section class="creation" > <h1>
<h1 > {{ 'creation.title' | translate }}
{{"creation.title"|translate}} </h1>
</h1 > <p class="description margin-btm-x5" i18n>
<p {{ 'config.description' | translate }}
class="description margin-btm-x5" </p>
i18n > <div class="btn-next">
{{"config.description"|translate}} <button [routerLink]="'step/date'" class="btn btn--full btn--primary">
</p > {{ 'config.letsgo' | translate }}
<div class="btn-next" > </button>
</div>
<button </section>
[routerLink]="'step/date'"
class="btn btn--full btn--primary" >
{{"config.letsgo"|translate}}
</button >
</div >
</section >
</div> </div>
<div class="column" id="searchMyPolls"> <div class="column" id="searchMyPolls">
<section class="recuperation" > <section class="recuperation">
<h1 > <h1>
{{"config.find_my_polls"|translate}} {{ 'config.find_my_polls' | translate }}
</h1 > </h1>
<form <form (ngSubmit)="findMyPollsByEmail(config.myEmail)">
(ngSubmit)="findMyPollsByEmail(config.myEmail)" <label class="description" for="sendemail" i18n>
> <i class="fa fa-envelope"></i>
<label {{ 'config.find_helper' | translate }} :
class="description" </label>
for="sendemail"
i18n
>
<i class='fa fa-envelope' ></i >
{{"config.find_helper"|translate}} :
</label >
<input <input
[(ngModel)]="config.myEmail" [(ngModel)]="config.myEmail"
class='input' class="input"
autofocus="autofocus" autofocus="autofocus"
id="sendemail" id="sendemail"
name="mail" name="mail"
@ -49,48 +36,36 @@
/> />
<input <input
[disabled]="!config.myEmail || !config.myEmail.length" [disabled]="!config.myEmail || !config.myEmail.length"
[ngClass]="{'btn--primary': config.myEmail}" [ngClass]="{ 'btn--primary': config.myEmail }"
class="btn btn--full" class="btn btn--full"
id='sendemailbutton' id="sendemailbutton"
i18n-value="'config.find_button'|translate" i18n-value="'config.find_button'|translate"
type="submit" type="submit"
/> />
</form > </form>
</section > </section>
<section <section class="list-my-polls" *ngIf="!config.loading">
class="list-my-polls" <h2>
*ngIf="!config.loading" >
<h2 >
Mes Sondages trouvés: Mes Sondages trouvés:
</h2 > </h2>
<ul <ul class="poll-list" *ngFor="let poll of config.myPolls; index as i; trackBy: trackFunction">
class="poll-list" <li>
*ngFor="let poll of config.myPolls ; index as i;trackBy trackFunction" > <a href="{{ poll.url }}">
<li > {{ poll.title }}
<a href='{{poll.url}}' > <sub>
{{poll.title}} {{ poll.description }}
<sub > </sub>
{{poll.description}} </a>
</sub > </li>
</a > </ul>
</li >
</ul >
<div <div class="no-polls" *ngIf="!config.myPolls || !config.myPolls.length">
class="no-polls"
*ngIf="! config.myPolls || !config.myPolls.length" >
Aucun sondage. Aucun sondage.
</div > </div>
</section > </section>
<div <div class="loading" *ngIf="config.loading">
class="loading" <i class="fa fa-refresh fa-spin fa-3x fa-fw"></i>
*ngIf="config.loading" >
<i class="fa fa-refresh fa-spin fa-3x fa-fw" ></i >
</div >
</div> </div>
</div> </div>
</div>
</div>
</div >

View File

@ -1,7 +1,7 @@
.container{ .container {
display:flex; display: flex;
flex-direction: column; flex-direction: column;
margin:auto; margin: auto;
} }
h1 { h1 {
display: inline-block; display: inline-block;
@ -9,7 +9,7 @@ h1 {
font-size: 2.6rem; font-size: 2.6rem;
&::after { &::after {
content: ""; content: '';
display: block; display: block;
width: 27.4%; width: 27.4%;
height: 2px; height: 2px;
@ -18,10 +18,10 @@ h1 {
margin-left: auto; margin-left: auto;
// background-color: $primary_color; // background-color: $primary_color;
} }
}
label{
float:left;
} }
input[type=email]{ label {
display:block; float: left;
}
input[type='email'] {
display: block;
} }

View File

@ -8,9 +8,8 @@ describe('CreateOrRetrieveComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ CreateOrRetrieveComponent ] declarations: [CreateOrRetrieveComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,17 +1,15 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {BaseComponent} from "../base-page/base.component"; import { BaseComponent } from '../base-page/base.component';
import {ConfigService} from "../../services/config.service"; import { ConfigService } from '../../services/config.service';
@Component({ @Component({
selector: 'framadate-create-or-retrieve', selector: 'framadate-create-or-retrieve',
templateUrl: './create-or-retrieve.component.html', templateUrl: './create-or-retrieve.component.html',
styleUrls: ['./create-or-retrieve.component.scss'] styleUrls: ['./create-or-retrieve.component.scss'],
}) })
export class CreateOrRetrieveComponent extends BaseComponent implements OnInit { export class CreateOrRetrieveComponent extends BaseComponent implements OnInit {
loadedMyPolls: boolean = false; loadedMyPolls: boolean = false;
constructor(public config: ConfigService) { constructor(public config: ConfigService) {
super(config); super(config);
} }
@ -20,12 +18,11 @@ export class CreateOrRetrieveComponent extends BaseComponent implements OnInit {
// if (!environment.production) { // if (!environment.production) {
// this.findMyPollsByEmail('tktest@tktest.com') // this.findMyPollsByEmail('tktest@tktest.com')
// } // }
} }
findMyPollsByEmail(email: string) { findMyPollsByEmail(email: string) {
if (!email) { if (!email) {
return return;
} }
this.config.findPollsByEmail(email); this.config.findPollsByEmail(email);
this.loadedMyPolls = true; this.loadedMyPolls = true;
@ -33,5 +30,5 @@ export class CreateOrRetrieveComponent extends BaseComponent implements OnInit {
trackFunction(index: number, item: any): number { trackFunction(index: number, item: any): number {
return item.id; return item.id;
}; }
} }

View File

@ -1,223 +1,168 @@
<h1 class="title is-1" > <h1 class="title is-1"><i class="fa fa-calendar"></i> {{ 'dates.title' | translate }}</h1>
<i class="fa fa-calendar"></i> {{"dates.title"|translate}}
</h1 >
<div > <div>
<label for="multi_hours" > <label for="multi_hours">
<span > <span>
{{"dates.hours_different"|translate}} {{ 'dates.hours_different' | translate }}
</span > </span>
<select <select [(ngModel)]="config.allowSeveralHours" id="multi_hours" name="multi_hours">
[(ngModel)]="config.allowSeveralHours" <option value="true">{{ 'dates.multiple.different' | translate }}</option>
id="multi_hours" <option value="false">{{ 'dates.multiple.identical' | translate }}</option>
name="multi_hours" </select>
> <span i18n>
<option value=true >{{"dates.multiple.different"|translate}}</option > {{ 'dates.hours_each_day' | translate }}
<option value=false >{{"dates.multiple.identical"|translate}}</option > </span>
</select > </label>
<span i18n > </div>
{{"dates.hours_each_day"|translate}}
</span >
</label >
</div >
<button (click)="addDate()" class="btn btn--primary" id="add_date_button">
<i class="fa fa-plus"></i>
{{ 'dates.add' | translate }}
</button>
<button <button
(click)="addDate()" (click)="showDateInterval = !showDateInterval"
class="btn btn--primary" [ngClass]="{ active: showDateInterval }"
id="add_date_button"
>
<i class='fa fa-plus' ></i >
{{"dates.add"|translate}}
</button >
<button
(click)="showDateInterval = !showDateInterval "
[ngClass]="{active: showDateInterval}"
class="btn btn--primary" class="btn btn--primary"
id="toggle_interval_button" id="toggle_interval_button"
> >
<i class='fa fa-clock-o' ></i > <i class="fa fa-clock-o"></i>
{{"dates.add_interval"|translate}} {{ 'dates.add_interval' | translate }}
</button > </button>
<button <button (click)="emptyAll()" class="btn btn--warning" id="empty_button">
(click)="emptyAll()" <i class="fa fa-trash"></i>
class="btn btn--warning" {{ 'dates.empty' | translate }}
id="empty_button" </button>
> <section *ngIf="showDateInterval" class="date-interval">
<i class='fa fa-trash' ></i >
{{"dates.empty"|translate}}
</button >
<section
*ngIf="showDateInterval"
class="date-interval " >
<!-- TODO à mettre en popup--> <!-- TODO à mettre en popup-->
<hr > <hr />
<h2 > {{"dates.add_interval"|translate}}</h2 > <h2>{{ 'dates.add_interval' | translate }}</h2>
<p > <p>
{{"dates.interval_propose"|translate}} {{ 'dates.interval_propose' | translate }}
<input <input (change)="countDays()" [(ngModel)]="startDateInterval" type="date" />
(change)="countDays()" {{ 'dates.interval_span' | translate }}
[(ngModel)]="startDateInterval" <input (change)="countDays()" [(ngModel)]="endDateInterval" type="date" />
type="date" > <br />
{{"dates.interval_span"|translate}} </p>
<input <button (click)="addIntervalOfDates()" class="btn btn-block btn--primary">
(change)="countDays()" <i class="fa fa-plus"></i>
[(ngModel)]="endDateInterval" {{ 'dates.interval_button' | translate }}
type="date" > {{ intervalDays }}
<br > {{ 'dates.interval_button_dates' | translate }}
</button>
</p > <hr />
<button </section>
(click)="addIntervalOfDates()" <div class="columns">
class="btn btn-block btn--primary" > <div class="column">
<i class='fa fa-plus' ></i > <div class="dates-list">
{{"dates.interval_button"|translate}} <div class="title">
{{intervalDays}} <span class="count-dates">
{{"dates.interval_button_dates"|translate}} {{ config.timeList.length }}
</button > </span>
<hr > <span class="count-dates-txt">
</section > {{ 'dates.count_time' | translate }}
<div class='columns' >
<div class='column' >
<div class="dates-list " >
<div class='title' >
<span class="count-dates" >
{{config.timeList.length}}
</span >
<span class="count-dates-txt " >
{{"dates.count_time"|translate}}
(pour chaque jour) (pour chaque jour)
</span > </span>
</div>
</div > <div class="actions">
<div class='actions' >
<button <button
(click)="addTime()" (click)="addTime()"
*ngIf=" 'false' === config.allowSeveralHours " *ngIf="'false' === config.allowSeveralHours"
class="btn btn--primary" class="btn btn--primary"
id="add_time_button" id="add_time_button"
> >
<i class='fa fa-plus' ></i > <i class="fa fa-plus"></i>
{{"dates.add_time"|translate}} {{ 'dates.add_time' | translate }}
</button > </button>
<button <button
(click)="removeAllTimes()" (click)="removeAllTimes()"
*ngIf=" 'false' === config.allowSeveralHours " *ngIf="'false' === config.allowSeveralHours"
class="btn btn--warning" class="btn btn--warning"
id="remove_time_button" id="remove_time_button"
> >
<i class='fa fa-trash' ></i > <i class="fa fa-trash"></i>
Aucune plage horaire Aucune plage horaire
</button > </button>
<button <button
(click)="resetTimes()" (click)="resetTimes()"
*ngIf=" 'false' === config.allowSeveralHours" *ngIf="'false' === config.allowSeveralHours"
class="btn btn--warning" class="btn btn--warning"
id="reset_time_button" id="reset_time_button"
> >
<i class='fa fa-refresh' ></i > <i class="fa fa-refresh"></i>
réinitialiser réinitialiser
</button > </button>
</div > </div>
<div <div *ngIf="'false' === config.allowSeveralHours" class="identical-dates">
*ngIf=" 'false' === config.allowSeveralHours" <div *ngFor="let time of config.timeList; index as id" class="time-choice">
class="identical-dates" <label for="timeChoices_{{ id }}">
> <i class="fa fa-clock-o"></i>
<div </label>
*ngFor="let time of config.timeList; index as id"
class="time-choice"
>
<label for='timeChoices_{{id}}' >
<i class='fa fa-clock-o' ></i >
</label >
<input <input
[(ngModel)]="time.literal" [(ngModel)]="time.literal"
name="timeChoices_{{id}}" name="timeChoices_{{ id }}"
type="text" type="text"
id='timeChoices_{{id}}' id="timeChoices_{{ id }}"
> />
<button <button (click)="time.timeList.splice(id, 1)" class="btn btn-warning">
(click)="time.timeList.splice(id, 1)" <i class="fa fa-times"></i>
class="btn btn-warning" ><i class="fa fa-times" ></i > </button>
</button > </div>
</div > </div>
</div > <hr />
<hr > <span class="count-dates title">
<span class="count-dates title" > {{ config.dateList.length }}
{{config.dateList.length}} </span>
</span > <span>
<span > {{ 'dates.count_dates' | translate }}
{{"dates.count_dates"|translate}} </span>
</span > <button class="btn btn--primary" (click)="addDate()">
<button {{ 'dates.add' | translate }}
class='btn btn--primary' </button>
(click)='addDate()' > <div *ngFor="let choice of config.dateList; index as id" class="date-choice">
{{"dates.add"|translate}} {{ id }})
</button >
<div
*ngFor="let choice of config.dateList; index as id"
class="date-choice"
>
{{id}})
<input <input
[(ngModel)]="choice.date_object" [(ngModel)]="choice.date_object"
name="dateChoices_{{id}}" name="dateChoices_{{ id }}"
id="dateChoices_{{id}}" id="dateChoices_{{ id }}"
useValueAsDate useValueAsDate
type="date" type="date"
> />
<button <button (click)="config.dateList.splice(id, 1)" class="btn btn-warning">
(click)="config.dateList.splice(id, 1)" <i class="fa fa-times"></i>
class="btn btn-warning" </button>
><i class="fa fa-times" ></i >
</button >
<button <button
(click)="addTimeToDate(choice, id)" (click)="addTimeToDate(choice, id)"
*ngIf=" 'true' === config.allowSeveralHours" *ngIf="'true' === config.allowSeveralHours"
class="btn btn--primary" class="btn btn--primary"
> >
{{"dates.add_time"|translate}} {{ 'dates.add_time' | translate }}
</button > </button>
<div <div *ngIf="'true' === config.allowSeveralHours" class="several-times">
*ngIf=" 'true' === config.allowSeveralHours" <div *ngFor="let timeItem of choice.timeList; index as idTime" class="time-choice">
class="several-times"
>
<div
*ngFor="let timeItem of choice.timeList; index as idTime"
class="time-choice"
>
<input <input
[(ngModel)]="timeItem.literal" [(ngModel)]="timeItem.literal"
name="dateTime_{{id}}_Choices_{{idTime}}" name="dateTime_{{ id }}_Choices_{{ idTime }}"
id="dateTime_{{id}}_Choices_{{idTime}}" id="dateTime_{{ id }}_Choices_{{ idTime }}"
type="text" type="text"
> />
<button <button (click)="choice.timeList.splice(idTime, 1)" class="btn btn-warning">
(click)="choice.timeList.splice(idTime, 1)" <i class="fa fa-times"></i>
class="btn btn-warning" </button>
><i class="fa fa-times" ></i > </div>
</button > </div>
</div > </div>
</div > </div>
</div > </div>
</div > <div class="column">
</div > <framadate-resume></framadate-resume>
<div class='column' > </div>
<framadate-resume ></framadate-resume > </div>
</div >
</div >
<a <a [routerLink]="'/step/resume'" class="btn btn--full btn--primary">
[routerLink]="'/step/resume'"
class="btn btn--full btn--primary"
>
C'est parfait! C'est parfait!
</a > </a>
<a <a [routerLink]="'/step/home'" class="prev">
[routerLink]="'/step/home'"
class="prev"
>
Retour Retour
</a > </a>

View File

@ -12,10 +12,10 @@
} }
:host { :host {
input, button { input,
button {
+ button { + button {
margin-left: 1em; margin-left: 1em;
} }
} }
} }

View File

@ -8,9 +8,8 @@ describe('DatesComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ DatesComponent ] declarations: [DatesComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,15 +1,15 @@
import {ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core'; import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
import {ConfigService} from '../../services/config.service'; import { ConfigService } from '../../services/config.service';
import {BaseComponent} from '../base-page/base.component'; import { BaseComponent } from '../base-page/base.component';
import {DOCUMENT} from '@angular/common'; import { DOCUMENT } from '@angular/common';
import {MessageService} from "primeng/api"; import { MessageService } from 'primeng/api';
import {otherDefaultDates} from "../../config/defaultConfigs"; import { otherDefaultDates } from '../../config/defaultConfigs';
import {DateUtilities} from "../../config/DateUtilities"; import { DateUtilities } from '../../config/DateUtilities';
@Component({ @Component({
selector: 'framadate-dates', selector: 'framadate-dates',
templateUrl: './dates.component.html', templateUrl: './dates.component.html',
styleUrls: ['./dates.component.scss'] styleUrls: ['./dates.component.scss'],
}) })
export class DatesComponent extends BaseComponent implements OnInit { export class DatesComponent extends BaseComponent implements OnInit {
showDateInterval: boolean = false; showDateInterval: boolean = false;
@ -18,7 +18,8 @@ export class DatesComponent extends BaseComponent implements OnInit {
intervalDaysDefault: number = 7; intervalDaysDefault: number = 7;
endDateInterval: any; endDateInterval: any;
constructor(public config: ConfigService, constructor(
public config: ConfigService,
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
private messageService: MessageService, private messageService: MessageService,
private dateUtilities: DateUtilities, private dateUtilities: DateUtilities,
@ -30,7 +31,7 @@ export class DatesComponent extends BaseComponent implements OnInit {
countDays() { countDays() {
// compute the number of days in the date interval // compute the number of days in the date interval
if (this.endDateInterval && this.startDateInterval) { if (this.endDateInterval && this.startDateInterval) {
this.intervalDays = (this.dateUtilities.dayDiff(this.endDateInterval, this.startDateInterval)).toFixed(0) this.intervalDays = this.dateUtilities.dayDiff(this.endDateInterval, this.startDateInterval).toFixed(0);
} }
} }
@ -41,14 +42,17 @@ export class DatesComponent extends BaseComponent implements OnInit {
let dateCurrent = new Date(); let dateCurrent = new Date();
const dateJson = dateCurrent.toISOString(); const dateJson = dateCurrent.toISOString();
this.startDateInterval = dateJson.substring(0, 10); this.startDateInterval = dateJson.substring(0, 10);
this.endDateInterval = this.dateUtilities.addDaysToDate(this.intervalDaysDefault, dateCurrent).toISOString().substring(0, 10); this.endDateInterval = this.dateUtilities
.addDaysToDate(this.intervalDaysDefault, dateCurrent)
.toISOString()
.substring(0, 10);
} }
addDate() { addDate() {
this.config.dateList.push({ this.config.dateList.push({
literal: '', literal: '',
date_object: new Date(), date_object: new Date(),
timeList: [] timeList: [],
}); });
let selector = '[ng-reflect-name="dateChoices_' + (this.config.dateList.length - 1) + '"]'; let selector = '[ng-reflect-name="dateChoices_' + (this.config.dateList.length - 1) + '"]';
this.cd.detectChanges(); this.cd.detectChanges();
@ -62,13 +66,11 @@ export class DatesComponent extends BaseComponent implements OnInit {
* change time spans * change time spans
*/ */
addTime() { addTime() {
this.config.timeList.push( this.config.timeList.push({
{
literal: '', literal: '',
timeList: [], timeList: [],
date_object: new Date() date_object: new Date(),
} });
);
} }
removeAllTimes() { removeAllTimes() {
@ -79,7 +81,6 @@ export class DatesComponent extends BaseComponent implements OnInit {
this.config.timeList = otherDefaultDates; this.config.timeList = otherDefaultDates;
} }
/** /**
* add a time period to a specific date choice, * add a time period to a specific date choice,
* focus on the new input * focus on the new input
@ -87,7 +88,7 @@ export class DatesComponent extends BaseComponent implements OnInit {
* @param id * @param id
*/ */
addTimeToDate(config: any, id: number) { addTimeToDate(config: any, id: number) {
config.timeList.push({literal: ''}); config.timeList.push({ literal: '' });
let selector = '[ng-reflect-name="dateTime_' + id + '_Choices_' + (config.timeList.length - 1) + '"]'; let selector = '[ng-reflect-name="dateTime_' + id + '_Choices_' + (config.timeList.length - 1) + '"]';
this.cd.detectChanges(); this.cd.detectChanges();
const elem = this.document.querySelector(selector); const elem = this.document.querySelector(selector);
@ -100,17 +101,16 @@ export class DatesComponent extends BaseComponent implements OnInit {
* remove all input contents, does not reset to default * remove all input contents, does not reset to default
*/ */
emptyAll() { emptyAll() {
this.config.dateList.forEach(element => { this.config.dateList.forEach((element) => {
element.literal = ''; element.literal = '';
element.date_object = new Date(); element.date_object = new Date();
element.timeList = ['', '', '']; element.timeList = ['', '', ''];
}); });
this.config.timeList.forEach(element => { this.config.timeList.forEach((element) => {
element.literal = ''; element.literal = '';
}); });
} }
/** /**
* add all the dates between the start and end dates in the interval section * add all the dates between the start and end dates in the interval section
*/ */
@ -118,11 +118,11 @@ export class DatesComponent extends BaseComponent implements OnInit {
let newIntervalArray = this.dateUtilities.getDatesInRange(this.startDateInterval, this.endDateInterval, 1); let newIntervalArray = this.dateUtilities.getDatesInRange(this.startDateInterval, this.endDateInterval, 1);
const converted = []; const converted = [];
newIntervalArray.forEach(element => { newIntervalArray.forEach((element) => {
converted.push({ converted.push({
literal: element.literal, literal: element.literal,
date_object: element.date_object, date_object: element.date_object,
timeList: [] timeList: [],
}); });
}); });
this.config.dateList = [...new Set(converted)]; // add only dates that are not already present with a Set of unique items this.config.dateList = [...new Set(converted)]; // add only dates that are not already present with a Set of unique items
@ -131,10 +131,7 @@ export class DatesComponent extends BaseComponent implements OnInit {
this.messageService.add({ this.messageService.add({
severity: 'success', severity: 'success',
summary: 'Dates ajoutées', summary: 'Dates ajoutées',
detail: `les dates ont été ajoutées aux réponses possibles` detail: `les dates ont été ajoutées aux réponses possibles`,
}); });
} }
} }

View File

@ -1,74 +1,56 @@
<h1 i18n > <h1 i18n>
{{"resume.title"|translate}} {{ 'resume.title' | translate }}
</h1 > </h1>
<section class="admin" > <section class="admin">
<h2 i18n >{{"resume.admins"|translate}}</h2 > <h2 i18n>{{ 'resume.admins' | translate }}</h2>
<p > <p>
Votre sondage «
<span class="poll-title">
{{ config.title }}
</span>
» a bien été créé !
</p>
<p>
Voici les liens daccès au sondage, conservez-les soigneusement ! (Si vous les perdez vous pourrez toujours les
recevoir par email)
</p>
Votre sondage «  <p>
<span class="poll-title" >
{{config.title}}
</span >
 » a bien été créé !
</p >
<p >
Voici les liens daccès au sondage, conservez-les soigneusement !
(Si vous les perdez vous pourrez toujours les recevoir par email)
</p >
<p >
Pour accéder au sondage et à tous ses paramètres : Pour accéder au sondage et à tous ses paramètres :
<a href="{{config.urlAdmin}}" >{{config.urlAdmin}} <a href="{{ config.urlAdmin }}">{{ config.urlAdmin }} </a>
</a > </p>
</p > <framadate-copy-text [textToCopy]="config.urlAdmin"></framadate-copy-text>
<framadate-copy-text [textToCopy]='config.urlAdmin' ></framadate-copy-text > <a href="{{ config.urlAdmin }}">
<a href="{{config.urlAdmin}}" >
Voir le sondage coté administrateur·ice Voir le sondage coté administrateur·ice
</a > </a>
<p class="note" > <p class="note">
Note : Le sondage sera supprimé {{config.deletionDateAfterLastModification}} jours après la date de sa dernière Note : Le sondage sera supprimé {{ config.deletionDateAfterLastModification }} jours après la date de sa
modification. dernière modification.
</p > </p>
</section>
</section > <section class="public">
<section class="public" > <h2 i18n>{{ 'resume.users' | translate }}</h2>
<p>
<h2 i18n >{{"resume.users"|translate}}</h2 >
<p >
Pour accéder au sondage : Pour accéder au sondage :
<a href="{{config.urlPublic}}" >{{config.urlPublic}} <a href="{{ config.urlPublic }}">{{ config.urlPublic }} </a>
</a > </p>
<framadate-copy-text [textToCopy]="config.urlPublic"></framadate-copy-text>
</p > <a href="{{ config.urlPublic }}">
<framadate-copy-text [textToCopy]='config.urlPublic' ></framadate-copy-text >
<a href="{{config.urlPublic}}" >
Voir le sondage Voir le sondage
</a > </a>
</section > </section>
<section class="mail" > <section class="mail">
<h2 i18n>{{ 'resume.links_mail' | translate }}</h2>
<p>
Pour être sur de retrouver ces liens, nous pouvons vous les envoyer sur votre mail mail :
<input type="email" [(ngModel)]="mailToRecieve" paceholder="email" />
</p>
<h2 i18n >{{"resume.links_mail"|translate}}</h2 > <button class="btn btn--primary" (click)="sendToEmail()">
<p > <i class="fa fa-paper-plane"></i>
Pour être sur de retrouver ces liens, nous pouvons vous les envoyer sur votre mail
mail :
<input
type="email"
[(ngModel)]="mailToRecieve"
paceholder="email"
>
</p >
<button
class="btn btn--primary"
(click)="sendToEmail()"
><i class="fa fa-paper-plane" ></i >
Envoyer les liens du sondage Envoyer les liens du sondage
</button > </button>
<a href="{{config.urlPublic}}" > <a href="{{ config.urlPublic }}">
Voir le sondage Voir le sondage
</a > </a>
</section>
</section >

View File

@ -8,9 +8,8 @@ describe('EndConfirmationComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ EndConfirmationComponent ] declarations: [EndConfirmationComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,37 +1,31 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {BaseComponent} from '../base-page/base.component'; import { BaseComponent } from '../base-page/base.component';
import {HttpClient} from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import {ConfigService} from "../../services/config.service"; import { ConfigService } from '../../services/config.service';
import {MessageService} from 'primeng/api'; import { MessageService } from 'primeng/api';
@Component({ @Component({
selector: 'framadate-end-confirmation', selector: 'framadate-end-confirmation',
templateUrl: './end-confirmation.component.html', templateUrl: './end-confirmation.component.html',
styleUrls: ['./end-confirmation.component.scss'] styleUrls: ['./end-confirmation.component.scss'],
}) })
export class EndConfirmationComponent extends BaseComponent implements OnInit { export class EndConfirmationComponent extends BaseComponent implements OnInit {
mailToRecieve = ''; mailToRecieve = '';
constructor(public config: ConfigService, constructor(public config: ConfigService, public http: HttpClient, private messageService: MessageService) {
public http: HttpClient,
private messageService: MessageService
) {
super(config); super(config);
this.mailToRecieve = this.config.myEmail; this.mailToRecieve = this.config.myEmail;
} }
ngOnInit() { ngOnInit() {}
}
copyLink(str: any) { copyLink(str: any) {
this.messageService.add({ this.messageService.add({
severity: 'success', severity: 'success',
summary: 'Lien copié', summary: 'Lien copié',
detail: str detail: str,
}); });
} }
sendToEmail() { sendToEmail() {}
}
} }

View File

@ -1,84 +1,58 @@
<div class="description" > <div class="description">
<router-outlet ></router-outlet > <router-outlet></router-outlet>
<h1 i18n > <h1 i18n>
{{"creation.title"|translate}} {{ 'creation.title' | translate }}
</h1 > </h1>
<span <span class="pre-selector" i18n>
class="pre-selector" {{ 'creation.want' | translate }}
i18n </span>
> <button (click)="config.resetConfig()" class="btn btn--warning">
{{"creation.want"|translate}}
</span >
<button
(click)='config.resetConfig()'
class='btn btn--warning' >
Reset all Reset all
</button > </button>
<select <select [(ngModel)]="config.pollType" autofocus="autofocus" id="selector" name="polltype">
[(ngModel)]="config.pollType" <option value="dates" name="polltype_date">
autofocus="autofocus" {{ 'creation.kind.date' | translate }}
id="selector" </option>
name='polltype' <option value="classic" name="polltype_classic">
> {{ 'creation.kind.classic' | translate }}
<option </option>
value="dates" </select>
name='polltype_date' >
{{"creation.kind.date"|translate}}
</option >
<option
value="classic"
name='polltype_classic' >
{{"creation.kind.classic"|translate}}
</option >
</select >
<span class="post-selector" > <span class="post-selector"> </span>
</span >
<div > <div>
<label class="title-label" for="poll_title" i18n>
<label {{ 'creation.choose_title' | translate }}
class="title-label" </label>
for="poll_title"
i18n
>
{{"creation.choose_title"|translate}}
</label >
<input <input
[(ngModel)]="config.title" [(ngModel)]="config.title"
id="poll_title" id="poll_title"
name="poll_title" name="poll_title"
placeholder="{{'creation.choose_title_placeholder'|translate}}" placeholder="{{ 'creation.choose_title_placeholder' | translate }}"
type="name" type="name"
> />
<framadate-erasable-input [(inputModel)]="config.title" ></framadate-erasable-input > <framadate-erasable-input [(inputModel)]="config.title"></framadate-erasable-input>
</div > </div>
<div > <div>
<label for="my_name" > <label for="my_name"> {{ 'creation.name' | translate }} : </label>
{{"creation.name"|translate}} :
</label >
<input <input
[(ngModel)]="config.myName" [(ngModel)]="config.myName"
id="my_name" id="my_name"
name="my_name" name="my_name"
placeholder="{{'creation.name_placeholder'|translate}}" placeholder="{{ 'creation.name_placeholder' | translate }}"
type="name" type="name"
> />
<framadate-erasable-input [(inputModel)]="config.myName" ></framadate-erasable-input > <framadate-erasable-input [(inputModel)]="config.myName"></framadate-erasable-input>
</div > </div>
<div > <div>
<label <label class="title-label" for="poll_description" i18n>
class="title-label" {{ 'creation.description' | translate }}:
for="poll_description" <framadate-erasable-input [(inputModel)]="config.description"></framadate-erasable-input>
i18n </label>
> <br />
{{"creation.description"|translate}}:
<framadate-erasable-input [(inputModel)]="config.description" ></framadate-erasable-input >
</label >
<br >
<textarea <textarea
[(ngModel)]="config.description" [(ngModel)]="config.description"
cols="50" cols="50"
@ -86,12 +60,12 @@
lines="5" lines="5"
name="poll_description" name="poll_description"
placeholder="description" placeholder="description"
></textarea > ></textarea>
</div > </div>
<div > <div>
<label for="email" > <label for="email">
Mon email pour administrer le sondage est Mon email pour administrer le sondage est
</label > </label>
<input <input
[(ngModel)]="config.myEmail" [(ngModel)]="config.myEmail"
autofocus="autofocus" autofocus="autofocus"
@ -100,33 +74,19 @@
required="required" required="required"
type="email" type="email"
/> />
<framadate-erasable-input [(inputModel)]="config.myEmail" ></framadate-erasable-input > <framadate-erasable-input [(inputModel)]="config.myEmail"></framadate-erasable-input>
</div > </div>
<button <button [routerLink]="'/step/answers'" class="btn btn--primary btn--full" *ngIf="config.pollType == 'classic'" i18n>
[routerLink]="'/step/answers'"
class="btn btn--primary btn--full"
*ngIf="config.pollType == 'classic'"
i18n
>
Continuer Continuer
<i class='fa fa-file-text' ></i > <i class="fa fa-file-text"></i>
</button > </button>
<button <button [routerLink]="'/step/date'" class="btn btn--primary btn--full" *ngIf="config.pollType == 'dates'" i18n>
[routerLink]="'/step/date'"
class="btn btn--primary btn--full"
*ngIf="config.pollType == 'dates'"
i18n
>
Continuer Continuer
<i class='fa fa-calendar-check-o' ></i > <i class="fa fa-calendar-check-o"></i>
</button > </button>
<a <a [routerLink]="'/step/creation'" class="prev" i18n>
[routerLink]="'/step/creation'"
class="prev"
i18n
>
Retour Retour
</a > </a>
<hr > <hr />
</div > </div>

View File

@ -8,9 +8,8 @@ describe('HomeComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ HomeComponent ] declarations: [HomeComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,20 +1,17 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {ConfigService} from "../../services/config.service"; import { ConfigService } from '../../services/config.service';
import {BaseComponent} from "../base-page/base.component"; import { BaseComponent } from '../base-page/base.component';
@Component({ @Component({
selector: 'framadate-home', selector: 'framadate-home',
templateUrl: './home.component.html', templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'] styleUrls: ['./home.component.scss'],
}) })
export class HomeComponent extends BaseComponent implements OnInit { export class HomeComponent extends BaseComponent implements OnInit {
nextStep = '/step/answers'; nextStep = '/step/answers';
constructor(public config: ConfigService) { constructor(public config: ConfigService) {
super(config); super(config);
} }
ngOnInit() { ngOnInit() {}
}
} }

View File

@ -1,343 +1,265 @@
<h1 >page de démo</h1 > <h1>page de démo</h1>
<p >cette étape est en cours de développement. <br > S'inspirer de la page de Home pour réaliser d'autres pages <p>
</p > cette étape est en cours de développement. <br />
<a S'inspirer de la page de Home pour réaliser d'autres pages
[routerLink]="'/step/end'" </p>
class="btn btn--primary" <a [routerLink]="'/step/end'" class="btn btn--primary" i18n="@@confirm">C'est parfait!</a>
i18n="@@confirm" >C'est parfait!</a > <h1>Atoms</h1>
<h1 >Atoms</h1 > <section>
<section > <article>
<article > <h2>Headings</h2>
<h2 >Headings</h2 >
<h1 >Ceci est un h1</h1 > <h1>Ceci est un h1</h1>
<h2 >Ceci est un h2</h2 > <h2>Ceci est un h2</h2>
<h3 >Ceci est un h3</h3 > <h3>Ceci est un h3</h3>
</article > </article>
<article > <article>
<h2 >Links</h2 > <h2>Links</h2>
<div > <div>
<a <a [routerLink]="'/home'" class="next">
[routerLink]="'/home'" <span class="text" i18n>
class="next" >
<span
class="text"
i18n >
C'est parti ! C'est parti !
</span > </span>
</a > </a>
</div > </div>
<div > <div>
<a <a [routerLink]="'/home'" class="prev">
[routerLink]="'/home'" <span class="text" i18n>
class="prev" >
<span
class="text"
i18n >
C'est parti ! C'est parti !
</span > </span>
</a > </a>
</div > </div>
</article > </article>
<article > <article>
<h2 >Buttons</h2 > <h2>Buttons</h2>
<button <button type="submit" class="btn btn--primary">
type="submit"
class="btn btn--primary" >
primary - default primary - default
</button > </button>
<br > <br />
<button <button type="submit" class="btn btn--primary btn--small">
type="submit"
class="btn btn--primary btn--small" >
primary - small primary - small
</button > </button>
<br > <br />
<a <a href="#" class="btn btn--primary btn--outline">
href="#"
class="btn btn--primary btn--outline" >
primary - outline - default primary - outline - default
</a > </a>
<br > <br />
<button <button type="submit" class="btn btn--primary btn--outline btn--small">
type="submit"
class="btn btn--primary btn--outline btn--small" >
primary - outline - small primary - outline - small
</button > </button>
<br > <br />
<input <input type="submit" class="btn btn--alert" value="alert - default" />
type="submit"
class="btn btn--alert"
value="alert - default" >
<br > <br />
<button <button type="submit" class="btn btn--alert btn--small">
type="submit"
class="btn btn--alert btn--small" >
alert - small alert - small
</button > </button>
<br > <br />
<button <button type="submit" class="btn btn--alert btn--outline">
type="submit"
class="btn btn--alert btn--outline" >
alert - outline - default alert - outline - default
</button > </button>
<br > <br />
<button <button type="submit" class="btn btn--alert btn--outline btn--small">
type="submit"
class="btn btn--alert btn--outline btn--small" >
alert - outline - small alert - outline - small
</button > </button>
<br ><br > <br /><br />
<button <button type="submit" class="btn btn--primary btn--full">
type="submit"
class="btn btn--primary btn--full" >
primary - full primary - full
</button > </button>
<button <button type="submit" class="btn btn--primary btn--outline btn--full">
type="submit"
class="btn btn--primary btn--outline btn--full" >
primary - outline - full primary - outline - full
</button > </button>
<button <button type="submit" class="btn btn--alert btn--full">
type="submit"
class="btn btn--alert btn--full" >
alert - full alert - full
</button > </button>
<button <button type="submit" class="btn btn--alert btn--outline btn--full">
type="submit"
class="btn btn--alert btn--outline btn--full" >
alert - outline - full alert - outline - full
</button > </button>
</article>
</article > <article>
<h2>Forms element</h2>
<article > <h3>Labels</h3>
<h2 >Forms element</h2 >
<h3 >Labels</h3 > <label for="">Un label pour les labelliser tous</label>
<label for="" >Un label pour les labelliser tous</label > <h3>Input name</h3>
<input type="name" name="" id="" /><br />
<input type="name" name="" id="" value="texte" />
<h3 >Input name</h3 > <h3>Input email</h3>
<input <input type="email" name="" id="" /><br />
type="name" <input type="email" name="" id="" value="adresse@email.com" />
name=""
id="" ><br >
<input
type="name"
name=""
id=""
value="texte" >
<h3 >Input email</h3 > <h3>Input password</h3>
<input <input type="password" name="" id="" /><br />
type="email" <input type="password" name="" id="" value="password" />
name=""
id="" ><br >
<input
type="email"
name=""
id=""
value="adresse@email.com" >
<h3 >Input password</h3 > <h3>Input date</h3>
<input <input type="date" name="" id="" /><br />
type="password" <input type="date" name="" id="" value="1985-11-23" />
name=""
id="" ><br >
<input
type="password"
name=""
id=""
value="password" >
<h3 >Input date</h3 > <h3>Select</h3>
<input <select name="" id="">
type="date" <option value="">
name=""
id="" ><br >
<input
type="date"
name=""
id=""
value="1985-11-23" >
<h3 >Select</h3 >
<select
name=""
id="" >
<option value="" >
1 1
</option > </option>
<option value="" > <option value="">
2 2
</option > </option>
<option value="" > <option value="">
3 3
</option > </option>
</select > </select>
<h3 >Textarea</h3 > <h3>Textarea</h3>
<textarea <textarea name="" id="" cols="30" rows="10"></textarea>
name="" </article>
id=""
cols="30"
rows="10" ></textarea >
</article >
<article > <article>
<h2 >Paragraphs</h2 > <h2>Paragraphs</h2>
<p >Lorem, ipsum dolor sit amet consectetur adipisicing elit. Magnam perspiciatis minus libero error dolores. <p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Magnam perspiciatis minus libero error dolores.
Corrupti repellat vero repellendus reiciendis assumenda minus. Nobis, quaerat ut nihil minima sed animi Corrupti repellat vero repellendus reiciendis assumenda minus. Nobis, quaerat ut nihil minima sed animi
delectus beatae!</p > delectus beatae!
</article > </p>
</article>
<article > <article>
<h2 >Lists</h2 > <h2>Lists</h2>
<h3 >Unordered list</h3 > <h3>Unordered list</h3>
<ul > <ul>
<li > <li>
plop plop
</li > </li>
<li > <li>
plop plop
</li > </li>
<li > <li>
plop plop
</li > </li>
</ul > </ul>
<h3 >Ordered list</h3 > <h3>Ordered list</h3>
<ol > <ol>
<li > <li>
plop plop
</li > </li>
<li > <li>
plop plop
</li > </li>
<li > <li>
plop plop
</li > </li>
</ol > </ol>
</article > </article>
<article > <article>
<h2 >Images</h2 > <h2>Images</h2>
<img <img src="http://placekitten.com/200/300" alt="" />
src="http://placekitten.com/200/300" </article>
alt="" > </section>
</article >
</section >
<section > <section>
<h1 >Molecules</h1 > <h1>Molecules</h1>
<framadate-voting-choice ></framadate-voting-choice > <framadate-voting-choice></framadate-voting-choice>
<article > <article>
<h2 >Useful classes</h2 > <h2>Useful classes</h2>
<h3 >Align right</h3 > <h3>Align right</h3>
<div class="align-right" > <div class="align-right">
<a <a [routerLink]="'/home'" class="next">
[routerLink]="'/home'" <span class="text" i18n>
class="next" >
<span
class="text"
i18n >
C'est parti ! C'est parti !
</span > </span>
</a > </a>
</div > </div>
</article > </article>
<article > <article>
<h2 >Label + input name</h2 > <h2>Label + input name</h2>
<label for="test-text" >Ceci est un label un peu long mais pas trop</label > <label for="test-text">Ceci est un label un peu long mais pas trop</label>
<input <input type="name" name="test-text" id="test-text" />
type="name" </article>
name="test-text"
id="test-text" >
</article >
<article > <article>
<h2 >Label + select</h2 > <h2>Label + select</h2>
<label for="test-select" >Ceci est un label un peu long mais pas trop</label > <label for="test-select">Ceci est un label un peu long mais pas trop</label>
<select <select name="test-select" id="test-select">
name="test-select" <option value="">
id="test-select" >
<option value="" >
1 1
</option > </option>
<option value="" > <option value="">
2 2
</option > </option>
<option value="" > <option value="">
3 3
</option > </option>
</select > </select>
</article > </article>
<article > <article>
<h2 >Input name with info</h2 > <h2>Input name with info</h2>
<a href="https://sketch.cloud/s/00A80/a/MAl5q7" >like here</a > <a href="https://sketch.cloud/s/00A80/a/MAl5q7">like here</a>
</article > </article>
<article > <article>
<h2 >Commentaries</h2 > <h2>Commentaries</h2>
</article > </article>
</section > </section>
<section > <section>
<h1 >Components</h1 > <h1>Components</h1>
<article > <article>
<h2 >Images list</h2 > <h2>Images list</h2>
<a href="https://sketch.cloud/s/00A80/a/bQA9wj" >that</a > <a href="https://sketch.cloud/s/00A80/a/bQA9wj">that</a>
</article > </article>
<article > <article>
<h2 >Calendar</h2 > <h2>Calendar</h2>
</article > </article>
<article > <article>
<h2 >Modale</h2 > <h2>Modale</h2>
</article > </article>
<article > <article>
<h2 >Way to vote</h2 > <h2>Way to vote</h2>
<a href="https://sketch.cloud/s/00A80/a/Ol0598" >that</a > <a href="https://sketch.cloud/s/00A80/a/Ol0598">that</a>
</article > </article>
<article > <article>
<h2 >Voted</h2 > <h2>Voted</h2>
<a href="https://sketch.cloud/s/00A80/a/OlJZo2" >that</a > <a href="https://sketch.cloud/s/00A80/a/OlJZo2">that</a>
</article > </article>
<article > <article>
<h2 >Graphics</h2 > <h2>Graphics</h2>
<a href="https://sketch.cloud/s/00A80/a/megprw" >that</a > <a href="https://sketch.cloud/s/00A80/a/megprw">that</a>
</article > </article>
</section > </section>

View File

@ -8,7 +8,6 @@ section {
+ section { + section {
margin: 0 !important; margin: 0 !important;
} }
} }
article { article {

View File

@ -8,9 +8,8 @@ describe('KindComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ KindComponent ] declarations: [KindComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,19 +1,16 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {BaseComponent} from '../base-page/base.component'; import { BaseComponent } from '../base-page/base.component';
import {ConfigService} from '../../services/config.service'; import { ConfigService } from '../../services/config.service';
@Component({ @Component({
selector: 'framadate-page-kind', selector: 'framadate-page-kind',
templateUrl: './kind.component.html', templateUrl: './kind.component.html',
styleUrls: ['./kind.component.scss'] styleUrls: ['./kind.component.scss'],
}) })
export class KindComponent extends BaseComponent implements OnInit { export class KindComponent extends BaseComponent implements OnInit {
constructor(public config: ConfigService) { constructor(public config: ConfigService) {
super(config); super(config);
} }
ngOnInit() { ngOnInit() {}
}
} }

View File

@ -4,9 +4,9 @@
<form> <form>
<label for="password">Mot de passe :</label> <label for="password">Mot de passe :</label>
<section class="row"> <section class="row">
<input class="margin-btm-x5" type="password" name="password"> <input class="margin-btm-x5" type="password" name="password" />
<input type="submit" name="view" value="Voir" class="btn btn--small btn--purple"> <input type="submit" name="view" value="Voir" class="btn btn--small btn--purple" />
</section> </section>
<input type="submit" name="go" value="Accéder au sondage" class="btn btn--primary btn--full btn--semi-bold"> <input type="submit" name="go" value="Accéder au sondage" class="btn btn--primary btn--full btn--semi-bold" />
</form> </form>

View File

@ -1,12 +1,12 @@
form{ form {
display:flex; display: flex;
flex-direction: column; flex-direction: column;
} }
label{ label {
font-weight: 600; font-weight: 600;
font-size: 18px; font-size: 18px;
} }
h1{ h1 {
display:flex; display: flex;
align-self: center; align-self: center;
} }

View File

@ -8,9 +8,8 @@ describe('PasswordComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ PasswordComponent ] declarations: [PasswordComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,19 +1,16 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {BaseComponent} from "../base-page/base.component"; import { BaseComponent } from '../base-page/base.component';
import {ConfigService} from "../../services/config.service"; import { ConfigService } from '../../services/config.service';
@Component({ @Component({
selector: 'framadate-password', selector: 'framadate-password',
templateUrl: './password.component.html', templateUrl: './password.component.html',
styleUrls: ['./password.component.scss'] styleUrls: ['./password.component.scss'],
}) })
export class PasswordComponent extends BaseComponent implements OnInit { export class PasswordComponent extends BaseComponent implements OnInit {
constructor(public config: ConfigService) { constructor(public config: ConfigService) {
super(config); super(config);
} }
ngOnInit() { ngOnInit() {}
}
} }

View File

@ -3,4 +3,3 @@
Images Images
</h1> </h1>
<a [routerLink]="'/step/visibility'" class="btn btn--primary">ok</a> <a [routerLink]="'/step/visibility'" class="btn btn--primary">ok</a>

View File

@ -8,9 +8,8 @@ describe('PicturesComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ PicturesComponent ] declarations: [PicturesComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,19 +1,16 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {ConfigService} from '../../services/config.service'; import { ConfigService } from '../../services/config.service';
import {BaseComponent} from '../base-page/base.component'; import { BaseComponent } from '../base-page/base.component';
@Component({ @Component({
selector: 'framadate-pictures', selector: 'framadate-pictures',
templateUrl: './pictures.component.html', templateUrl: './pictures.component.html',
styleUrls: ['./pictures.component.scss'] styleUrls: ['./pictures.component.scss'],
}) })
export class PicturesComponent extends BaseComponent implements OnInit { export class PicturesComponent extends BaseComponent implements OnInit {
constructor(public config: ConfigService) { constructor(public config: ConfigService) {
super(config); super(config);
} }
ngOnInit() { ngOnInit() {}
}
} }

View File

@ -1,87 +1,67 @@
<div <div class="poll">
class="poll" <button class="btn btn--primary" (click)="config.execStuff()" *ngIf="config.isAdmin">
>
<button
class='btn btn--primary'
(click)='config.execStuff()'
*ngIf='config.isAdmin' >
launch admin action execStuff ! launch admin action execStuff !
</button > </button>
<button <button class="btn btn--primary" (click)="config.exportJson()" *ngIf="config.isAdmin">
class='btn btn--primary'
(click)='config.exportJson()'
*ngIf='config.isAdmin' >
<i class="fa fa-file-archive-o"></i> <i class="fa fa-file-archive-o"></i>
export CSV export CSV
</button > </button>
<div class="loading" *ngIf="config.loading">
<div <i class="fa fa-refresh fa-spin"></i>
class='loading' </div>
*ngIf='config.loading' > <div class="loaded-poll" *ngIf="!config.loading && config.currentPoll">
<i class='fa fa-refresh fa-spin' ></i > <div id="choices">
</div > <framadate-choices-list></framadate-choices-list>
<div </div>
class='loaded-poll' <div id="table">
*ngIf='!config.loading && config.currentPoll' >
<div id='choices' >
<framadate-choices-list ></framadate-choices-list >
</div >
<div id='table' >
<!-- <framadate-voting-navigation ></framadate-voting-navigation >--> <!-- <framadate-voting-navigation ></framadate-voting-navigation >-->
<framadate-voting-summary ></framadate-voting-summary > <framadate-voting-summary></framadate-voting-summary>
</div > </div>
<div id='poll_comments' > <div id="poll_comments">
<framadate-comments-list ></framadate-comments-list > <framadate-comments-list></framadate-comments-list>
</div > </div>
<div id='graph' > <div id="graph">
<!--<framadate-voting-graph ></framadate-voting-graph >--> <!--<framadate-voting-graph ></framadate-voting-graph >-->
</div > </div>
<div id='export_and_share' > <div id="export_and_share">
<div class="sharing" *ngIf="config.currentPoll">
<h3 class="margin-top-x8">
Partager le sondage
<div <i class="fa fa-share"></i>
class="sharing" </h3>
*ngIf='config.currentPoll' > <p class="nobold text-14" for="copyLink">
<h3 class="margin-top-x8" >Partager le sondage Pour partager le sondage, vous pouvez diffuser ce lien :
<a href="{{ config.currentPoll.urlPublic }}">
{{ config.currentPoll.urlPublic }}
</a>
</p>
<i class='fa fa-share' ></i ></h3 > <framadate-copy-text [textToCopy]="config.currentPoll.urlPublic"></framadate-copy-text>
<p <h3 class="margin-top-x6 margin-btm-x3">
class="nobold text-14"
for="copyLink" >Pour partager le sondage, vous pouvez diffuser ce lien :
<a href='{{config.currentPoll.urlPublic}}' >
{{config.currentPoll.urlPublic}}
</a >
</p >
<framadate-copy-text [textToCopy]='config.currentPoll.urlPublic' ></framadate-copy-text >
<h3 class="margin-top-x6 margin-btm-x3" >
Exporter/Imprimer Exporter/Imprimer
</h3 > </h3>
<input <input
type="submit" type="submit"
name="export" name="export"
class="margin-btm-x3 btn btn--primary btn--outline" class="margin-btm-x3 btn btn--primary btn--outline"
value="Exporter en .csv" value="Exporter en .csv"
(click)="config.exportCSV()" > (click)="config.exportCSV()"
/>
<input <input
type="submit" type="submit"
name="copy-link" name="copy-link"
class="btn btn--primary btn--outline" class="btn btn--primary btn--outline"
value="Imprimer le sondage" value="Imprimer le sondage"
(click)="config.print()" > (click)="config.print()"
</div > />
</div>
</div > </div>
</div > </div>
<div <div class="badly-loaded" *ngIf="config.loading && !config.currentPoll">
class='badly-loaded' <div class="well is-warning">
*ngIf='config.loading && !config.currentPoll' >
<div class='well is-warning' >
No current poll available No current poll available
</div > </div>
</div > </div>
</div>
</div >

View File

@ -1,3 +1 @@
@import "../../../assets/scss/variables"; @import '../../../assets/scss/variables';

View File

@ -8,9 +8,8 @@ describe('PollDisplayComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ PollDisplayComponent ] declarations: [PollDisplayComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,25 +1,22 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {BaseComponent} from "../base-page/base.component"; import { BaseComponent } from '../base-page/base.component';
import {ConfigService} from "../../services/config.service"; import { ConfigService } from '../../services/config.service';
import {mockComments} from "../../config/mocks/mock-comments"; import { mockComments } from '../../config/mocks/mock-comments';
import {ActivatedRoute, Router} from "@angular/router"; import { ActivatedRoute, Router } from '@angular/router';
import {environment} from "../../../environments/environment"; import { environment } from '../../../environments/environment';
import {mockPoll3} from "../../config/mocks/mock-poll3"; import { mockPoll3 } from '../../config/mocks/mock-poll3';
@Component({ @Component({
selector: 'framadate-poll-display', selector: 'framadate-poll-display',
templateUrl: './poll-display.component.html', templateUrl: './poll-display.component.html',
styleUrls: ['./poll-display.component.scss'] styleUrls: ['./poll-display.component.scss'],
}) })
export class PollDisplayComponent extends BaseComponent implements OnInit { export class PollDisplayComponent extends BaseComponent implements OnInit {
comments = mockComments; comments = mockComments;
constructor(public config: ConfigService, constructor(public config: ConfigService, private router: Router, public activeRoute: ActivatedRoute) {
private router: Router,
public activeRoute: ActivatedRoute) {
super(config); super(config);
this.activeRoute.paramMap.subscribe(params => { this.activeRoute.paramMap.subscribe((params) => {
console.log('params', params); console.log('params', params);
this.config.pollId = params.get('poll'); this.config.pollId = params.get('poll');
this.config.pollSlug = params.get('pollSlug'); this.config.pollSlug = params.get('pollSlug');
@ -29,10 +26,7 @@ export class PollDisplayComponent extends BaseComponent implements OnInit {
}); });
} }
ngOnInit() { ngOnInit() {}
}
// fetch poll with its ID or slug. // fetch poll with its ID or slug.
fetchPoll() { fetchPoll() {
@ -52,10 +46,11 @@ export class PollDisplayComponent extends BaseComponent implements OnInit {
console.log('res', res); console.log('res', res);
this.config.updateCurrentPollFromResponse(res); this.config.updateCurrentPollFromResponse(res);
this.config.loading = false; this.config.loading = false;
}, (e) => { },
(e) => {
// handle need for a password // handle need for a password
console.log('e', e); console.log('e', e);
this.config.handleError(e) this.config.handleError(e);
} }
); );
} else if (pollSlug) { } else if (pollSlug) {
@ -64,13 +59,12 @@ export class PollDisplayComponent extends BaseComponent implements OnInit {
(res: any) => { (res: any) => {
this.config.loading = false; this.config.loading = false;
this.config.updateCurrentPollFromResponse(res); this.config.updateCurrentPollFromResponse(res);
}, (e) => { },
(e) => {
// handle need for a password // handle need for a password
this.config.handleError(e) this.config.handleError(e);
} }
); );
} }
} }
} }

View File

@ -1,113 +1,71 @@
<h1 > <h1>
Récapitulatif Récapitulatif
</h1 > </h1>
<div class='card content' > <div class="card content">
<h2 class="hero-title title">
<h2 class="hero-title title" > {{ config.title }}
{{config.title}} </h2>
</h2 > <div class="creation">
<div class="creation" >
créé par créé par
<i class='pseudo' > <i class="pseudo">
{{config.myName}} {{ config.myName }}
</i > </i>
</div > </div>
<div class="description" > <div class="description">
<cite > <cite>
{{config.description}} {{ config.description }}
</cite > </cite>
</div > </div>
<section <section class="preview type-classic" *ngIf="config.pollType == 'classic'">
class='preview type-classic' <ul>
*ngIf='config.pollType == "classic"' > <li markdown *ngFor="let questions of config.answers">
<ul > <img class="img-thumbnail" src="{{ questions.url }}" alt="image {{ questions.url }}" />
<li {{ questions.id + 1 }}. {{ questions.text }}
markdown </li>
*ngFor="let questions of config.answers" > </ul>
<img </section>
class='img-thumbnail' <section class="type-date" *ngIf="config.pollType !== 'classic'">
src='{{questions.url}}' <i class="fa fa-clock-o"></i>
alt='image {{questions.url}}' > <span class="well" *ngIf="'true' === config.allowSeveralHours">
{{questions.id + 1}}. {{questions.text}} {{ 'dates.multiple.different' | translate }}
</li > </span>
</ul > <span class="well" *ngIf="'false' === config.allowSeveralHours">
</section > {{ 'dates.multiple.identical' | translate }}
<section </span>
class='type-date' <div *ngFor="let choice of config.dateList; index as id" class="date-choice">
*ngIf='config.pollType !== "classic"' > <div class="only-one-slice" *ngIf="!choice.timeList.length">
<i class='fa fa-clock-o' ></i > <i class="fa fa-square-o"></i>
<span </div>
class='well' {{ choice.literal }}
*ngIf="'true' === config.allowSeveralHours" >
{{"dates.multiple.different"|translate}}
</span >
<span
class='well'
*ngIf="'false' === config.allowSeveralHours" >
{{"dates.multiple.identical"|translate}}
</span >
<div
*ngFor="let choice of config.dateList; index as id"
class="date-choice"
>
<div
class='only-one-slice'
*ngIf='!choice.timeList.length' >
<i class='fa fa-square-o' ></i >
</div >
{{choice.literal}}
<!-- CASE different slices of the day--> <!-- CASE different slices of the day-->
<div <div *ngIf="'true' === config.allowSeveralHours" class="several-times">
*ngIf="'true' === config.allowSeveralHours" <div *ngFor="let time of choice.timeList; index as idTime" class="time-choice">
class="several-times" {{ idTime }})
> <i class="fa fa-square-o"></i>
{{ time.literal }}
<div </div>
*ngFor="let time of choice.timeList ; index as idTime" </div>
class="time-choice"
>
{{idTime}})
<i class='fa fa-square-o' ></i >
{{time.literal}}
</div >
</div >
<!-- CASE all dates having the same slices of the day--> <!-- CASE all dates having the same slices of the day-->
<div <div *ngIf="'false' === config.allowSeveralHours" class="same-times">
*ngIf="'false' === config.allowSeveralHours" <div *ngFor="let time of config.timeList" class="time-choice">
class="same-times" <i class="fa fa-square-o"></i>
> {{ time.literal }}
<div </div>
*ngFor="let time of config.timeList " </div>
class="time-choice" </div>
> </section>
<i class='fa fa-square-o' ></i > </div>
{{time.literal}}
</div >
</div >
</div >
</section >
</div > <button [routerLink]="'/step/visibility'" class="btn btn--primary btn--full">
<button
[routerLink]="'/step/visibility'"
class="btn btn--primary btn--full" >
C'est parfait! C'est parfait!
</button > </button>
<div class="back" > <div class="back">
<a <a *ngIf="config.pollType == 'classic'" [routerLink]="'/step/answers'" class="prev">
*ngIf='config.pollType == "classic"'
[routerLink]="'/step/answers'"
class="prev" >
Retour Retour
</a > </a>
<a <a *ngIf="config.pollType == 'dates'" [routerLink]="'/step/date'" class="prev">
*ngIf='config.pollType == "dates"'
[routerLink]="'/step/date'"
class="prev" >
Retour Retour
</a > </a>
</div > </div>

View File

@ -8,9 +8,8 @@ describe('ResumeComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ ResumeComponent ] declarations: [ResumeComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,18 +1,15 @@
import {Component} from '@angular/core'; import { Component } from '@angular/core';
import {BaseComponent} from '../base-page/base.component'; import { BaseComponent } from '../base-page/base.component';
import {ConfigService} from '../../services/config.service'; import { ConfigService } from '../../services/config.service';
import {Router} from "@angular/router"; import { Router } from '@angular/router';
@Component({ @Component({
selector: 'framadate-resume', selector: 'framadate-resume',
templateUrl: './resume.component.html', templateUrl: './resume.component.html',
styleUrls: ['./resume.component.scss'] styleUrls: ['./resume.component.scss'],
}) })
export class ResumeComponent extends BaseComponent { export class ResumeComponent extends BaseComponent {
constructor(public config: ConfigService, private router: Router) {
constructor(public config: ConfigService,
private router: Router) {
super(config); super(config);
} }
} }

View File

@ -1,195 +1,163 @@
<h1 i18n > <h1 i18n>
{{"visibility.top_txt"|translate}} {{ 'visibility.top_txt' | translate }}
</h1 > </h1>
<section class="answers" > <section class="answers">
<h2 > <h2>
{{"visibility.title"|translate}} {{ 'visibility.title' | translate }}
</h2 > </h2>
<span > <span>
{{"visibility.visibility_want"|translate}} {{ 'visibility.visibility_want' | translate }}
</span >
<select
name="visible_people"
id="visible_people"
[(ngModel)]="config.visibility"
>
<option value="link_only" >
{{"visibility.visibility_link"|translate}}
</option >
<option value="only_me" >
{{"visibility.visibility_nobody"|translate}}
</option >
</select >
<span >
{{"visibility.visibility_see"|translate}}
</span >
</section >
<section class="possible_votes" >
<h2 >
{{"visibility.votes"|translate}}
</h2 >
<label for="votes" >
{{"visibility.votes_possible"|translate}}
</label >
<select
name="votes"
id="votes"
[(ngModel)]="config.voteChoices"
>
<option value="only_yes" >
{{"visibility.votes_possible_single"|translate}}
</option >
<option value="normal" >
{{"visibility.votes_possible_normal"|translate}}
</option >
<option value="full" >
{{"visibility.votes_possible_full"|translate}}
</option >
</select >
</section >
<section class="expiracy" >
<label for="expirationDate" >
{{"visibility.archiving"|translate}}
</label >
<input
type="date"
id="expirationDate"
[(ngModel)]="config.expirationDate" >
<div class="modification" >
<label for="modificationAbility" >
{{"visibility.archiving_start"|translate}}
</label >
<select
name="modificationAbility"
id="modificationAbility"
[(ngModel)]="config.canModifyAnswers" >
<option value=true >
{{"visibility.archiving_can"|translate}}
</option >
<option value=false >
{{"visibility.archiving_can_not"|translate}}
</option >
</select >
<span *ngIf=" config.canModifyAnswers == false">
{{"visibility.archiving_end_not"|translate}}
</span> </span>
<span class="can_modify_votes" *ngIf="config.canModifyAnswers== true "> <select name="visible_people" id="visible_people" [(ngModel)]="config.visibility">
<label for="modificationScope"> <option value="link_only">
{{"visibility.archiving_end"|translate}} {{ 'visibility.visibility_link' | translate }}
</option>
<option value="only_me">
{{ 'visibility.visibility_nobody' | translate }}
</option>
</select>
<span>
{{ 'visibility.visibility_see' | translate }}
</span>
</section>
<section class="possible_votes">
<h2>
{{ 'visibility.votes' | translate }}
</h2>
<label for="votes">
{{ 'visibility.votes_possible' | translate }}
</label> </label>
<span *ngIf="false == !!config.canModifyAnswers" > <select name="votes" id="votes" [(ngModel)]="config.voteChoices">
{{"visibility.modfiy_their"|translate}} <option value="only_yes">
</span > {{ 'visibility.votes_possible_single' | translate }}
</option>
<option value="normal">
{{ 'visibility.votes_possible_normal' | translate }}
</option>
<option value="full">
{{ 'visibility.votes_possible_full' | translate }}
</option>
</select>
</section>
<section class="expiracy">
<label for="expirationDate">
{{ 'visibility.archiving' | translate }}
</label>
<input type="date" id="expirationDate" [(ngModel)]="config.expirationDate" />
<div class="modification">
<label for="modificationAbility">
{{ 'visibility.archiving_start' | translate }}
</label>
<select name="modificationAbility" id="modificationAbility" [(ngModel)]="config.canModifyAnswers">
<option value="true">
{{ 'visibility.archiving_can' | translate }}
</option>
<option value="false">
{{ 'visibility.archiving_can_not' | translate }}
</option>
</select>
<span *ngIf="config.canModifyAnswers == false">
{{ 'visibility.archiving_end_not' | translate }}
</span>
<span class="can_modify_votes" *ngIf="config.canModifyAnswers == true">
<label for="modificationScope">
{{ 'visibility.archiving_end' | translate }}
</label>
<span *ngIf="false == !!config.canModifyAnswers">
{{ 'visibility.modfiy_their' | translate }}
</span>
<select <select
name="modificationScope" name="modificationScope"
id="modificationScope" id="modificationScope"
*ngIf="true == !!config.canModifyAnswers"[(ngModel)]="config.whoModifiesAnswers" *ngIf="true == !!config.canModifyAnswers"
[disabled]="false == !!config.canModifyAnswers"> [(ngModel)]="config.whoModifiesAnswers"
[disabled]="false == !!config.canModifyAnswers"
>
<option value="self"> <option value="self">
{{"visibility.modfiy_their"|translate}} {{ 'visibility.modfiy_their' | translate }}
</option> </option>
<option value="everybody"> <option value="everybody">
{{"visibility.modfiy_everyone"|translate}} {{ 'visibility.modfiy_everyone' | translate }}
</option> </option>
</select> </select>
</span> </span>
</div>
</section>
<section class="access">
<h2 class="title">
{{ 'visibility.access' | translate }}
</h2>
<label for="url">
{{ 'visibility.access_url' | translate }}
<br />
{{ 'visibility.access_url_key' | translate }}
</label>
<br />
<input type="name" class="input-lg" name="url" id="url" [(ngModel)]="config.customUrl" />
</div > <sub class="instructions">
{{ 'visibility.access_instructions' | translate }}
</sub>
<div class="preview-url">
<a [href]="'/#/vote/poll/slug/' + config.customUrl">
{{ environment.baseHref + '#/vote/poll/slug/' + config.customUrl }}
</a>
<framadate-copy-text [textToCopy]="config.urlPublic"></framadate-copy-text>
</div>
<br />
<label for="passwordAccess">
{{ 'visibility.access_want' | translate }}
</label>
<select name="passwordAccess" id="passwordAccess" [(ngModel)]="config.passwordAccess">
<option value="0"> {{ 'visibility.access_want_no' | translate }}</option>
<option value="1"> {{ 'visibility.access_want_yes' | translate }}</option>
</select>
</section > <label for="password">
<section class="access" > {{ 'visibility.access_protect' | translate }}
<h2 class='title' > </label>
{{"visibility.access"|translate}}
</h2 >
<label for="url" >
{{"visibility.access_url"|translate}}
<br >
{{"visibility.access_url_key"|translate}}
</label >
<br >
<input
type="name"
class="input-lg"
name="url"
id="url"
[(ngModel)]="config.customUrl" >
<sub class="instructions" > <div class="enablepassword" *ngIf="config.passwordAccess == 1">
{{"visibility.access_instructions"|translate}}
</sub >
<div class="preview-url" >
<a [href]="'/#/vote/poll/slug/' + config.customUrl" >
{{environment.baseHref + '#/vote/poll/slug/' + config.customUrl}}
</a >
<framadate-copy-text [textToCopy]='config.urlPublic' ></framadate-copy-text >
</div >
<br >
<label for="passwordAccess" >
{{"visibility.access_want"|translate}}
</label >
<select
name="passwordAccess"
id="passwordAccess"
[(ngModel)]="config.passwordAccess" >
<option value="0" > {{"visibility.access_want_no"|translate}}</option >
<option value="1" > {{"visibility.access_want_yes"|translate}}</option >
</select >
<label for="password" >
{{"visibility.access_protect"|translate}}
</label >
<div
class="enablepassword"
*ngIf="config.passwordAccess == 1" >
<input <input
type="password" type="password"
name="password" name="password"
id="password" id="password"
min="8" min="8"
*ngIf="!showCustomPassword" *ngIf="!showCustomPassword"
[(ngModel)]="config.password" > [(ngModel)]="config.password"
/>
<input <input
type="name" type="name"
name="password_visible" name="password_visible"
id="password_visible" id="password_visible"
min="8" min="8"
*ngIf="showCustomPassword" *ngIf="showCustomPassword"
[(ngModel)]="config.password" > [(ngModel)]="config.password"
/>
<button <button
(click)="showCustomPassword = !showCustomPassword" (click)="showCustomPassword = !showCustomPassword"
[disabled]="!config.password" [disabled]="!config.password"
class="btn btn--default" > class="btn btn--default"
<i class="fa fa-eye" ></i > >
{{"visibility.see_pass"|translate}} <i class="fa fa-eye"></i>
</button > {{ 'visibility.see_pass' | translate }}
</div > </button>
</section > </div>
</section>
<button <button (click)="submitCreationAndGoToEnd()" class="btn btn--primary btn--full" i18n="@@confirm">
(click)='submitCreationAndGoToEnd()' {{ 'visibility.validate_btn' | translate }}
class="btn btn--primary btn--full" <i class="fa fa-paper-plane" *ngIf="!config.loading"></i>
i18n="@@confirm" > <span class="loading" *ngIf="config.loading">
{{"visibility.validate_btn"|translate}} <i class="fa fa-refresh fa-spin fa-fw"></i>
<i </span>
class='fa fa-paper-plane' </button>
*ngIf="!config.loading" ></i >
<span
class="loading"
*ngIf="config.loading" >
<i class="fa fa-refresh fa-spin fa-fw" ></i >
</span >
</button >
<div class="back" > <div class="back">
<a [routerLink]="'/step/answers'" class="prev">
<a
[routerLink]="'/step/answers'"
class="prev" >
Retour Retour
</a > </a>
</div > </div>

View File

@ -8,9 +8,8 @@ describe('VisibilityComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ VisibilityComponent ] declarations: [VisibilityComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,31 +1,32 @@
import {Component, OnInit} from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {BaseComponent} from '../base-page/base.component'; import { BaseComponent } from '../base-page/base.component';
import {ConfigService} from '../../services/config.service'; import { ConfigService } from '../../services/config.service';
import {environment} from "../../../environments/environment"; import { environment } from '../../../environments/environment';
import {PollUtilities} from "../../config/PollUtilities"; import { PollUtilities } from '../../config/PollUtilities';
@Component({ @Component({
selector: 'framadate-visibility', selector: 'framadate-visibility',
templateUrl: './visibility.component.html', templateUrl: './visibility.component.html',
styleUrls: ['./visibility.component.scss'] styleUrls: ['./visibility.component.scss'],
}) })
export class VisibilityComponent extends BaseComponent implements OnInit { export class VisibilityComponent extends BaseComponent implements OnInit {
showCustomPassword = false; showCustomPassword = false;
baseUrl = environment.baseApiHref; baseUrl = environment.baseApiHref;
environment = environment; environment = environment;
constructor(public config: ConfigService, constructor(public config: ConfigService, public utils: PollUtilities) {
public utils: PollUtilities) {
super(config); super(config);
} }
ngOnInit() { ngOnInit() {
this.config.customUrl = this.utils.makeSlug(this.config); this.config.customUrl = this.utils.makeSlug(this.config);
this.config.expirationDate = (this.config.addDaysToDate(this.config.expiracyDateDefaultInDays, new Date())).toISOString().substring(0, 10); this.config.expirationDate = this.config
.addDaysToDate(this.config.expiracyDateDefaultInDays, new Date())
.toISOString()
.substring(0, 10);
} }
submitCreationAndGoToEnd() { submitCreationAndGoToEnd() {
this.config.createPoll(); this.config.createPoll();
} }
} }

View File

@ -1,27 +1,26 @@
<div *ngIf="config.currentPoll" class="list-of-choices">
<div <div *ngFor="let choice of config.currentPoll.choices">
*ngIf='config.currentPoll'
class="list-of-choices" >
<div *ngFor="let choice of config.currentPoll.choices" >
<framadate-voting-choice <framadate-voting-choice
[choice]="choice" [choice]="choice"
[choices_count]="config.currentPoll.choices_count" [choices_count]="config.currentPoll.choices_count"
[pollIsSpecialDate]="config.currentPoll.poll.kind == 'date'" [pollIsSpecialDate]="config.currentPoll.poll.kind == 'date'"
[poll]='config.currentPoll' ></framadate-voting-choice > [poll]="config.currentPoll"
</div > ></framadate-voting-choice>
</div > </div>
</div>
<button <button
class='btn btn-block submit-votestack' class="btn btn-block submit-votestack"
(click)='config.addVote()' (click)="config.addVote()"
[disabled]='!config.myTempVoteStack' [disabled]="!config.myTempVoteStack"
[ngClass]='{"btn--primary" : config.myTempVoteStack } ' [ngClass]="{ 'btn--primary': config.myTempVoteStack }"
*ngIf='!config.myVoteStack || !config.myVoteStack.id' > *ngIf="!config.myVoteStack || !config.myVoteStack.id"
<i class='fa fa-paper-plane' ></i > Envoyer >
</button > <i class="fa fa-paper-plane"></i> Envoyer
</button>
<button <button
class='btn btn--primary btn-block submit-votestack update' class="btn btn--primary btn-block submit-votestack update"
(click)='config.updateVote(config.myVoteStack)' (click)="config.updateVote(config.myVoteStack)"
*ngIf='config.myVoteStack && config.myVoteStack.id' > *ngIf="config.myVoteStack && config.myVoteStack.id"
<i class='fa fa-pencil' ></i > Mettre à jour >
</button > <i class="fa fa-pencil"></i> Mettre à jour
</button>

View File

@ -8,9 +8,8 @@ describe('ChoicesListComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ ChoicesListComponent ] declarations: [ChoicesListComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,15 +1,11 @@
import {Component} from '@angular/core'; import { Component } from '@angular/core';
import {ConfigService} from "../../../services/config.service"; import { ConfigService } from '../../../services/config.service';
@Component({ @Component({
selector: 'framadate-choices-list', selector: 'framadate-choices-list',
templateUrl: './choices-list.component.html', templateUrl: './choices-list.component.html',
styleUrls: ['./choices-list.component.scss'] styleUrls: ['./choices-list.component.scss'],
}) })
export class ChoicesListComponent { export class ChoicesListComponent {
constructor(public config: ConfigService) {}
constructor(public config: ConfigService) {
}
} }

View File

@ -1,61 +1,34 @@
<section class="name" > <section class="name">
<label for="name" > <label for="name">
<i class='fa fa-user' ></i > <i class="fa fa-user"></i>
Votre nom :</label > Votre nom :</label
<input
type="text"
name="name"
id="name"
[(ngModel)]="config.myName" >
<input
type="text"
name="name"
id="email"
[(ngModel)]="config.myEmail" >
<i class='fa fa-envelope' ></i >
</section >
<div
class="comments"
id='comments' >
<h2 class="margin-top-x7" >Laisser un commentaire</h2 >
<label for="crname" >Votre nom :</label >
<input
type="text"
class="margin-btm-x3"
name="crname"
[(ngModel)]='config.myName'
id="crname" >
<input
type="text"
name="cremail"
id="email_comment"
[(ngModel)]="config.myEmail" >
<label for='email_comment' >
<i class='fa fa-envelope' ></i >
</label >
<div >
<label for="comment" >Votre commentaire :</label >
<br >
<textarea
name="comment"
id="comment"
[(ngModel)]='config.myComment'
> >
</textarea > <input type="text" name="name" id="name" [(ngModel)]="config.myName" />
</div > <input type="text" name="name" id="email" [(ngModel)]="config.myEmail" />
<i class="fa fa-envelope"></i>
</section>
<div class="comments" id="comments">
<h2 class="margin-top-x7">Laisser un commentaire</h2>
<label for="crname">Votre nom :</label>
<input type="text" class="margin-btm-x3" name="crname" [(ngModel)]="config.myName" id="crname" />
<input type="text" name="cremail" id="email_comment" [(ngModel)]="config.myEmail" />
<label for="email_comment">
<i class="fa fa-envelope"></i>
</label>
<div>
<label for="comment">Votre commentaire :</label>
<br />
<textarea name="comment" id="comment" [(ngModel)]="config.myComment"> </textarea>
</div>
<input <input
type="submit" type="submit"
name="add-comment" name="add-comment"
class="btn btn--primary btn--outline" class="btn btn--primary btn--outline"
value="Ajouter mon commentaire" value="Ajouter mon commentaire"
(click)='config.addComment()' > (click)="config.addComment()"
<div />
class='comments-part' <div class="comments-part" *ngIf="config.currentPoll">
*ngIf='config.currentPoll' > <framadate-voting-comment [comment]="c" *ngFor="let c of config.currentPoll.comments">
</framadate-voting-comment>
<framadate-voting-comment </div>
[comment]="c" </div>
*ngFor="let c of config.currentPoll.comments " >
</framadate-voting-comment >
</div >
</div >

View File

@ -1,13 +1,13 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {CommentsListComponent} from './comments-list.component'; import { CommentsListComponent } from './comments-list.component';
import {FormsModule} from "@angular/forms"; import { FormsModule } from '@angular/forms';
import {HttpClient, HttpClientModule} from "@angular/common/http"; import { HttpClient, HttpClientModule } from '@angular/common/http';
import {BrowserModule} from "@angular/platform-browser"; import { BrowserModule } from '@angular/platform-browser';
import {CommonModule} from "@angular/common"; import { CommonModule } from '@angular/common';
import {ConfirmationService, MessageService} from "primeng"; import { ConfirmationService, MessageService } from 'primeng';
import {Router} from "@angular/router"; import { Router } from '@angular/router';
import {ConfigService} from "../../../services/config.service"; import { ConfigService } from '../../../services/config.service';
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']); const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
@ -17,18 +17,16 @@ describe('CommentsListComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [FormsModule, imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule],
BrowserModule, declarations: [CommentsListComponent],
CommonModule, providers: [
HttpClientModule], HttpClient,
declarations: [CommentsListComponent,]
, providers: [HttpClient,
MessageService, MessageService,
ConfirmationService, ConfirmationService,
ConfigService, ConfigService,
{provide: Router, useValue: routerSpy}] { provide: Router, useValue: routerSpy },
}) ],
.compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,15 +1,11 @@
import {Component} from '@angular/core'; import { Component } from '@angular/core';
import {ConfigService} from "../../../services/config.service"; import { ConfigService } from '../../../services/config.service';
@Component({ @Component({
selector: 'framadate-comments-list', selector: 'framadate-comments-list',
templateUrl: './comments-list.component.html', templateUrl: './comments-list.component.html',
styleUrls: ['./comments-list.component.scss'] styleUrls: ['./comments-list.component.scss'],
}) })
export class CommentsListComponent { export class CommentsListComponent {
constructor(public config: ConfigService) {}
constructor(public config: ConfigService) {
}
} }

View File

@ -1,171 +1,142 @@
<div class="choicebox selection-{{choice.answer}}" > <div class="choicebox selection-{{ choice.answer }}">
<!-- add .choicebox--active to most voted --> <!-- add .choicebox--active to most voted -->
<button <button
*ngIf='showChangeChoicebutton' *ngIf="showChangeChoicebutton"
class='btn btn--primary' class="btn btn--primary"
(click)=' choice.simpleAnswer = !choice.simpleAnswer' > (click)="choice.simpleAnswer = !choice.simpleAnswer"
<i class='fa fa-gears' ></i > >
</button > <i class="fa fa-gears"></i>
</button>
<div class="choicebox__subject" > <div class="choicebox__subject">
<div class='columns' > <div class="columns">
<div class='column' > <div class="column">
<div <div class="text title clickable" (click)="setAnswserTo('yes')">
class="text title clickable" {{ choice.text }}
(click)="setAnswserTo('yes')" > </div>
{{choice.text}} <!-- TEXT CASE --><!--
</div > <!-- TEXT CASE --><!--
<p class="choicebox__txt"> <p class="choicebox__txt">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nulla nobis nam culpa ! Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nulla nobis nam culpa !
</p> </p>
--><!-- TEXT CASE --> --><!-- TEXT CASE -->
<!-- IMG CASE --> <!-- IMG CASE -->
<img <img *ngIf="choice.url" class="choicebox__img" [src]="choice.url" alt="{{ choice.url }}" />
*ngIf='choice.url'
class="choicebox__img"
[src]="choice.url"
alt="{{choice.url}}"
>
<!-- IMG CASE --> <!-- IMG CASE -->
<!-- DATE CASE --> <!-- DATE CASE -->
<div <div class="dates" *ngIf="pollIsSpecialDate">
class="dates" <div class="choicebox__date">
*ngIf="pollIsSpecialDate" > {{ choice.date.date | date: 'EEE' }}
<div class="choicebox__date" > <span class="choicebox__day">{{ choice.date.date | date: 'dd' }}</span>
{{choice.date.date | date:'EEE'}} <span {{ choice.date.date | date: 'LLL' }}
class="choicebox__day" >{{choice.date.date | date:'dd'}}</span > {{choice.date.date | date:'LLL'}} </div>
</div > <div class="choicebox__hour">
<div class="choicebox__hour" > {{ choice.date.date | date: 'H:m' }}
{{choice.date.date | date:'H:m'}} </div>
</div > </div>
</div >
<!-- DATE CASE --> <!-- DATE CASE -->
</div > </div>
<div class='column' > <div class="column">
<div class="choicebox__actions" > <div class="choicebox__actions">
<!-- show only the yes check if the config is set to simpleAnswer --> <!-- show only the yes check if the config is set to simpleAnswer -->
<!-- add .choicebox__btn--active to selected <button> --> <!-- add .choicebox__btn--active to selected <button> -->
<span class="simple-answer" > <span class="simple-answer">
<button <button
class="choicebox__btn choicebox__btn--yes" class="choicebox__btn choicebox__btn--yes"
type="button" type="button"
[ngClass]="{'choicebox__btn--active': choice.answer === 'yes'}" [ngClass]="{ 'choicebox__btn--active': choice.answer === 'yes' }"
(click)="setAnswserTo('yes')" > (click)="setAnswserTo('yes')"
<img >
src="../../../assets/img/check.svg" <img src="../../../assets/img/check.svg" alt="" />
alt="" > </button>
</button > </span>
</span > <span class="complex-answers" *ngIf="!simpleAnswer">
<span
class="complex-answers"
*ngIf="!simpleAnswer" >
<button <button
class="choicebox__btn choicebox__btn--maybe" class="choicebox__btn choicebox__btn--maybe"
type="button" type="button"
[ngClass]="{'choicebox__btn--active': choice.answer === 'maybe'}" [ngClass]="{ 'choicebox__btn--active': choice.answer === 'maybe' }"
(click)="setAnswserTo('maybe')" > (click)="setAnswserTo('maybe')"
<img >
src="../../../assets/img/check-2.svg" <img src="../../../assets/img/check-2.svg" alt="" />
alt="" > </button>
</button >
<button <button
class="choicebox__btn choicebox__btn--no" class="choicebox__btn choicebox__btn--no"
type="button" type="button"
[ngClass]="{'choicebox__btn--active': choice.answer === 'no'}" [ngClass]="{ 'choicebox__btn--active': choice.answer === 'no' }"
(click)="setAnswserTo('no')" (click)="setAnswserTo('no')"
> >
<img <img src="../../../assets/img/croix.svg" alt="" />
src="../../../assets/img/croix.svg" </button>
alt="" > </span>
</button > </div>
</span > </div>
<div class="column">
</div > <div class="choicebox__count">
</div > <div class="no-votes" *ngIf="!poll.choices_count.counts[choice.id]">
<div class='column' >
<div class="choicebox__count" >
<div
class='no-votes'
*ngIf='! poll.choices_count.counts[choice.id] ' >
aucun vote aucun vote
</div > </div>
<button <button
type="button" type="button"
aria-describedby="choicebox-tooltip" aria-describedby="choicebox-tooltip"
class="choicebox__votes" class="choicebox__votes"
*ngIf="poll.choices_count && choice && poll.choices_count.counts[choice.id]" > *ngIf="poll.choices_count && choice && poll.choices_count.counts[choice.id]"
<div class="choicebox__vote" > >
{{poll.choices_count.counts[choice.id].yes.count}} <div class="choicebox__vote">
<img {{ poll.choices_count.counts[choice.id].yes.count }}
width="20px" <img width="20px" height="21px" src="../../../assets/img/votant-sur.svg" alt="" />
height="21px" </div>
src="../../../assets/img/votant-sur.svg" <div class="choicebox__vote">
alt="" > {{ poll.choices_count.counts[choice.id].maybe.count }}
</div > <img width="22px" height="24px" src="../../../assets/img/votant-pas-sur.svg" alt="" />
<div class="choicebox__vote" > </div>
{{poll.choices_count.counts[choice.id].maybe.count}} <div class="choicebox__tooltip" id="choicebox-tooltip">
<img <div class="choicebox__tooltiplist">
width="22px" <div class="choicebox__tooltipttl">
height="24px" <img width="20px" height="21px" src="../../../assets/img/votant-sur.svg" alt="" />
src="../../../assets/img/votant-pas-sur.svg" {{ poll.choices_count.counts[choice.id].yes.count }} "Oui"
alt="" > </div>
</div >
<div
class="choicebox__tooltip"
id="choicebox-tooltip" >
<div class="choicebox__tooltiplist" >
<div class="choicebox__tooltipttl" >
<img
width="20px"
height="21px"
src="../../../assets/img/votant-sur.svg"
alt="" >
{{poll.choices_count.counts[choice.id].yes.count}} "Oui"
</div >
<!-- liste des gens qui ont répondu oui--> <!-- liste des gens qui ont répondu oui-->
<ul > <ul>
<li *ngFor='let pseudo of choices_count.counts[choice.id].yes.people ' >{{pseudo}}</li > <li *ngFor="let pseudo of choices_count.counts[choice.id].yes.people">
</ul > {{ pseudo }}
</div > </li>
<div </ul>
class="choicebox__tooltiplist" </div>
*ngIf='!simpleAnswer' > <div class="choicebox__tooltiplist" *ngIf="!simpleAnswer">
<div class="choicebox__tooltipttl" > <div class="choicebox__tooltipttl">
<img <img
width="22px" width="22px"
height="24px" height="24px"
src="../../../assets/img/votant-pas-sur.svg" src="../../../assets/img/votant-pas-sur.svg"
alt="" > alt=""
{{poll.choices_count.counts[choice.id].maybe.count}} "Peut-être" />
</div > {{ poll.choices_count.counts[choice.id].maybe.count }} "Peut-être"
<ul > </div>
<li *ngFor='let pseudo of choices_count.counts[choice.id].maybe.people ' >{{pseudo}}</li > <ul>
</ul > <li *ngFor="let pseudo of choices_count.counts[choice.id].maybe.people">
</div > {{ pseudo }}
<div </li>
class="choicebox__tooltiplist" </ul>
*ngIf='!simpleAnswer' > </div>
<div class="choicebox__tooltipttl" > <div class="choicebox__tooltiplist" *ngIf="!simpleAnswer">
<i class='fa fa-times' ></i > <div class="choicebox__tooltipttl">
{{poll.choices_count.counts[choice.id].no.count}} "Non" <i class="fa fa-times"></i>
</div > {{ poll.choices_count.counts[choice.id].no.count }} "Non"
<ul > </div>
<li *ngFor='let pseudo of choices_count.counts[choice.id].no.people ' >{{pseudo}}</li > <ul>
</ul > <li *ngFor="let pseudo of choices_count.counts[choice.id].no.people">
</div > {{ pseudo }}
</div > </li>
</button > </ul>
<div class="choicebox__countxt" > </div>
</div>
</button>
<div class="choicebox__countxt">
Choix ayant reçu le plus de votes Choix ayant reçu le plus de votes
</div > </div>
</div > </div>
</div > </div>
</div > </div>
</div>
</div > </div>
</div >

View File

@ -5,14 +5,13 @@
// -- IMPORTS // -- IMPORTS
// ---------------------------- // ----------------------------
@import "../../../../assets/scss/variables"; @import '../../../../assets/scss/variables';
// -- VARIABLES // -- VARIABLES
// ---------------------------- // ----------------------------
$box-padding: 2rem; $box-padding: 2rem;
$box-border-width: .6rem; $box-border-width: 0.6rem;
$btn-size: 5rem; $btn-size: 5rem;
$btn-margin-x: 1rem; $btn-margin-x: 1rem;
$btn-margin-y: 1.5rem; $btn-margin-y: 1.5rem;
@ -20,7 +19,6 @@ $btn-wrap-size: calc(2 * #{$btn-size} + 4 * #{$btn-margin-x});
$img-maxheight: 12rem; $img-maxheight: 12rem;
$breakpoint-responsive: 640px; // à définir $breakpoint-responsive: 640px; // à définir
// -- GLOBAL // -- GLOBAL
// ---------------------------- // ----------------------------
@ -32,7 +30,7 @@ $breakpoint-responsive: 640px; // à définir
padding: $box-padding $box-padding $box-padding calc(#{$box-padding} - #{$box-border-width}); padding: $box-padding $box-padding $box-padding calc(#{$box-padding} - #{$box-border-width});
border-left: $box-border-width solid transparent; border-left: $box-border-width solid transparent;
background-color: $white; background-color: $white;
box-shadow: 0 0 .6rem 0 rgba($black, .2); box-shadow: 0 0 0.6rem 0 rgba($black, 0.2);
&--active { &--active {
padding-left: $box-padding; padding-left: $box-padding;
@ -54,13 +52,12 @@ $breakpoint-responsive: 640px; // à définir
} }
} }
// -- DATE // -- DATE
// ---------------------------- // ----------------------------
.choicebox__date { .choicebox__date {
font-size: 1.8rem; font-size: 1.8rem;
margin-bottom: .5rem; margin-bottom: 0.5rem;
white-space: nowrap; white-space: nowrap;
text-transform: capitalize; text-transform: capitalize;
@ -74,7 +71,6 @@ $breakpoint-responsive: 640px; // à définir
font-weight: bold; font-weight: bold;
} }
// -- IMG // -- IMG
// ---------------------------- // ----------------------------
@ -83,7 +79,6 @@ $breakpoint-responsive: 640px; // à définir
max-height: $img-maxheight; max-height: $img-maxheight;
} }
// -- TXT // -- TXT
// ---------------------------- // ----------------------------
@ -93,7 +88,6 @@ $breakpoint-responsive: 640px; // à définir
min-width: 10em; min-width: 10em;
} }
// -- VOTE BTNS // -- VOTE BTNS
// ---------------------------- // ----------------------------
@ -119,7 +113,7 @@ $breakpoint-responsive: 640px; // à définir
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin: $btn-margin-y $btn-margin-x; margin: $btn-margin-y $btn-margin-x;
border: .3rem solid #ccc9c9; border: 0.3rem solid #ccc9c9;
background-color: transparent; background-color: transparent;
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
@ -133,24 +127,22 @@ $breakpoint-responsive: 640px; // à définir
left: auto; left: auto;
} }
} }
&:focus, &:active { &:focus,
&:active {
border-color: #bf83c2; border-color: #bf83c2;
color: #bf83c2; color: #bf83c2;
background: #000; background: #000;
} }
&--active { &--active {
border-color: #bf83c2; border-color: #bf83c2;
} }
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
margin-top: 0; margin-top: 0;
margin-bottom: 0; margin-bottom: 0;
} }
} }
// -- VOTE COUNT // -- VOTE COUNT
// ---------------------------- // ----------------------------
@ -184,7 +176,7 @@ $breakpoint-responsive: 640px; // à définir
.choicebox__countxt { .choicebox__countxt {
display: none; display: none;
margin-top: .5rem; margin-top: 0.5rem;
.choicebox--active & { .choicebox--active & {
display: block; display: block;
@ -194,7 +186,6 @@ $breakpoint-responsive: 640px; // à définir
} }
} }
// -- TOOLTIP // -- TOOLTIP
// ---------------------------- // ----------------------------
@ -208,7 +199,7 @@ $breakpoint-responsive: 640px; // à définir
left: 50%; left: 50%;
z-index: 1; z-index: 1;
padding: 2rem; padding: 2rem;
border: .1rem solid rgba($black, .1); border: 0.1rem solid rgba($black, 0.1);
background-color: $white; background-color: $white;
text-align: left; text-align: left;
transform: translateX(-50%); transform: translateX(-50%);
@ -219,7 +210,7 @@ $breakpoint-responsive: 640px; // à définir
height: 0; height: 0;
bottom: 100%; bottom: 100%;
left: 50%; left: 50%;
content: " "; content: ' ';
pointer-events: none; pointer-events: none;
border: solid transparent; border: solid transparent;
} }
@ -233,7 +224,7 @@ $breakpoint-responsive: 640px; // à définir
margin-left: -1.6rem; margin-left: -1.6rem;
border-width: 1.6rem; border-width: 1.6rem;
border-color: rgba($black, 0); border-color: rgba($black, 0);
border-bottom-color: rgba($black, .1); border-bottom-color: rgba($black, 0.1);
} }
ul { ul {
margin: 0; margin: 0;
@ -261,7 +252,7 @@ $breakpoint-responsive: 640px; // à définir
font-weight: bold; font-weight: bold;
white-space: nowrap; white-space: nowrap;
img { img {
margin-right: .5rem; margin-right: 0.5rem;
vertical-align: sub; vertical-align: sub;
} }
& ~ .choicebox__tooltipttl { & ~ .choicebox__tooltipttl {

View File

@ -1,14 +1,14 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {FormsModule} from "@angular/forms"; import { FormsModule } from '@angular/forms';
import {HttpClient, HttpClientModule} from "@angular/common/http"; import { HttpClient, HttpClientModule } from '@angular/common/http';
import {BrowserModule} from "@angular/platform-browser"; import { BrowserModule } from '@angular/platform-browser';
import {CommonModule} from "@angular/common"; import { CommonModule } from '@angular/common';
import {ConfirmationService, MessageService} from "primeng"; import { ConfirmationService, MessageService } from 'primeng';
import {Router} from "@angular/router"; import { Router } from '@angular/router';
import {ConfigService} from "../../../services/config.service"; import { ConfigService } from '../../../services/config.service';
import {VotingChoiceComponent} from './voting-choice.component'; import { VotingChoiceComponent } from './voting-choice.component';
import {mockChoice} from "../../../config/mocks/choice"; import { mockChoice } from '../../../config/mocks/choice';
import {mockPoll3} from "../../../config/mocks/mock-poll3"; import { mockPoll3 } from '../../../config/mocks/mock-poll3';
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']); const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
@ -18,24 +18,22 @@ describe('VotingChoiceComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [FormsModule, imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule],
BrowserModule, declarations: [VotingChoiceComponent],
CommonModule, providers: [
HttpClientModule], HttpClient,
declarations: [VotingChoiceComponent]
, providers: [HttpClient,
MessageService, MessageService,
ConfirmationService, ConfirmationService,
ConfigService, ConfigService,
{provide: Router, useValue: routerSpy}] { provide: Router, useValue: routerSpy },
}) ],
.compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(VotingChoiceComponent); fixture = TestBed.createComponent(VotingChoiceComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
component.choice = {...mockChoice}; component.choice = { ...mockChoice };
component.choices_count = mockPoll3.choices_count; component.choices_count = mockPoll3.choices_count;
component.choice_id = mockChoice.id; component.choice_id = mockChoice.id;
component.poll = mockPoll3.poll; component.poll = mockPoll3.poll;
@ -76,7 +74,6 @@ describe('VotingChoiceComponent', () => {
expect(component.choice.answer).toBe('no'); expect(component.choice.answer).toBe('no');
}); });
it('should consider to have simple answer when allowedAnswers is only one answer long, which is yes', () => { it('should consider to have simple answer when allowedAnswers is only one answer long, which is yes', () => {
expect(component.poll.allowedAnswers[0]).toBe('yes'); expect(component.poll.allowedAnswers[0]).toBe('yes');
expect(component.poll.allowedAnswers.length).toBe(1); expect(component.poll.allowedAnswers.length).toBe(1);
expect(component.simpleAnswer).toBeTruthy(); expect(component.simpleAnswer).toBeTruthy();

View File

@ -1,17 +1,17 @@
import {Component, ElementRef, Input} from '@angular/core'; import { Component, ElementRef, Input } from '@angular/core';
import {ConfigService} from "../../../services/config.service"; import { ConfigService } from '../../../services/config.service';
interface VoteChoice { interface VoteChoice {
votes?: { votes?: {
yes: number yes: number;
no: number no: number;
maybe: number maybe: number;
notAnswered: number notAnswered: number;
}; };
name?: string; name?: string;
date?: Date; date?: Date;
answer: 'yes' | 'no' | 'maybe' | null; answer: 'yes' | 'no' | 'maybe' | null;
simpleAnswer?: boolean simpleAnswer?: boolean;
false; // enable if we display only a togglable "yes" false; // enable if we display only a togglable "yes"
} }
@ -22,10 +22,9 @@ interface VoteChoice {
@Component({ @Component({
selector: 'framadate-voting-choice', selector: 'framadate-voting-choice',
templateUrl: './voting-choice.component.html', templateUrl: './voting-choice.component.html',
styleUrls: ['./voting-choice.component.scss'] styleUrls: ['./voting-choice.component.scss'],
}) })
export class VotingChoiceComponent { export class VotingChoiceComponent {
public showChangeChoicebutton = false; public showChangeChoicebutton = false;
@Input() public choice: any; @Input() public choice: any;
@Input() public choices_count: any; @Input() public choices_count: any;
@ -34,11 +33,9 @@ export class VotingChoiceComponent {
@Input() public simpleAnswer: boolean = true; @Input() public simpleAnswer: boolean = true;
@Input() public pollIsSpecialDate: boolean = false; @Input() public pollIsSpecialDate: boolean = false;
constructor(private el: ElementRef, constructor(private el: ElementRef, private config: ConfigService) {
private config: ConfigService) {
if (this.poll && this.poll.allowedAnswers) { if (this.poll && this.poll.allowedAnswers) {
this.simpleAnswer = this.poll.allowedAnswers.length == 1 this.simpleAnswer = this.poll.allowedAnswers.length == 1;
} }
} }
@ -52,7 +49,6 @@ export class VotingChoiceComponent {
this.choice.answer = newAnswer; this.choice.answer = newAnswer;
this.config.myTempVoteStack++; this.config.myTempVoteStack++;
} }
} else { } else {
this.choice.answer = newAnswer; this.choice.answer = newAnswer;
if (this.choice.answer !== newAnswer) { if (this.choice.answer !== newAnswer) {
@ -60,11 +56,9 @@ export class VotingChoiceComponent {
this.config.myTempVoteStack++; this.config.myTempVoteStack++;
} }
} else { } else {
console.info('same answer as before') console.info('same answer as before');
} }
} }
this.el.nativeElement.blur(); this.el.nativeElement.blur();
} }
} }

View File

@ -1,13 +1,11 @@
<div class="comment" > <div class="comment">
<span class="cname" > <span class="cname"> {{ comment.pseudo }} </span>, le
{{comment.pseudo}} <span class="date padding-btm-x1">
</span >, le {{ comment.date.date }}
<span class="date padding-btm-x1" > </span>
{{comment.date.date }} <blockquote>
</span > <p class="text">
<blockquote > {{ comment.text }}
<p class="text" > </p>
{{comment.text}} </blockquote>
</p > </div>
</blockquote >
</div >

View File

@ -1,6 +1,6 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {VotingCommentComponent} from './voting-comment.component'; import { VotingCommentComponent } from './voting-comment.component';
describe('VotingCommentComponent', () => { describe('VotingCommentComponent', () => {
let component: VotingCommentComponent; let component: VotingCommentComponent;
@ -8,9 +8,8 @@ describe('VotingCommentComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [VotingCommentComponent] declarations: [VotingCommentComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,19 +1,15 @@
import {Component, Input, OnInit} from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
import {mockComments} from "../../../config/mocks/mock-comments"; import { mockComments } from '../../../config/mocks/mock-comments';
@Component({ @Component({
selector: 'framadate-voting-comment', selector: 'framadate-voting-comment',
templateUrl: './voting-comment.component.html', templateUrl: './voting-comment.component.html',
styleUrls: ['./voting-comment.component.scss'] styleUrls: ['./voting-comment.component.scss'],
}) })
export class VotingCommentComponent implements OnInit { export class VotingCommentComponent implements OnInit {
@Input() comment = mockComments[0]; @Input() comment = mockComments[0];
constructor() { constructor() {}
}
ngOnInit() {
}
ngOnInit() {}
} }

View File

@ -8,9 +8,8 @@ describe('VotingGraphComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ VotingGraphComponent ] declarations: [VotingGraphComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,19 +1,16 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {BaseComponent} from "../../base-page/base.component"; import { BaseComponent } from '../../base-page/base.component';
import {ConfigService} from "../../../services/config.service"; import { ConfigService } from '../../../services/config.service';
@Component({ @Component({
selector: 'framadate-voting-graph', selector: 'framadate-voting-graph',
templateUrl: './voting-graph.component.html', templateUrl: './voting-graph.component.html',
styleUrls: ['./voting-graph.component.scss'] styleUrls: ['./voting-graph.component.scss'],
}) })
export class VotingGraphComponent extends BaseComponent implements OnInit { export class VotingGraphComponent extends BaseComponent implements OnInit {
constructor(public config: ConfigService) { constructor(public config: ConfigService) {
super(config); super(config);
} }
ngOnInit() { ngOnInit() {}
}
} }

View File

@ -1,34 +1,31 @@
<nav id='navigation'> <nav id="navigation">
<nav class="sections-nav">
<nav class='sections-nav' > <ul>
<ul > <li>
<li > <a href="#title">
<a href='#title' > {{ config.currentPoll.poll.title }}
{{config.currentPoll.poll.title}} </a>
</a > </li>
</li > <li>
<li > <a href="#table">
<a href='#table' > {{ config.currentPoll.stacks.length }}
{{config.currentPoll.stacks.length}}
votes votes
</a > </a>
</li > </li>
<li > <li>
<a href='#graph' > <a href="#graph">
Graphique Graphique
</a > </a>
</li > </li>
<li > <li>
<a href='#comments' > <a href="#comments">
<i class='fa fa-comments' ></i > <i class="fa fa-comments"></i>
<span <span *ngIf="config.currentPoll && config.currentPoll.comments" class="comments-count">
*ngIf='config.currentPoll && config.currentPoll.comments' {{ config.currentPoll.comments.length }}
class='comments-count' > </span>
{{config.currentPoll.comments.length}}
</span >
commentaires commentaires
</a > </a>
</li > </li>
</ul > </ul>
</nav > </nav>
</nav> </nav>

View File

@ -8,9 +8,8 @@ describe('VotingNavigationComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ VotingNavigationComponent ] declarations: [VotingNavigationComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,14 +1,11 @@
import {Component} from '@angular/core'; import { Component } from '@angular/core';
import {ConfigService} from "../../../services/config.service"; import { ConfigService } from '../../../services/config.service';
@Component({ @Component({
selector: 'framadate-voting-navigation', selector: 'framadate-voting-navigation',
templateUrl: './voting-navigation.component.html', templateUrl: './voting-navigation.component.html',
styleUrls: ['./voting-navigation.component.scss'] styleUrls: ['./voting-navigation.component.scss'],
}) })
export class VotingNavigationComponent { export class VotingNavigationComponent {
constructor(public config: ConfigService) {}
constructor(public config: ConfigService) {
}
} }

View File

@ -1,81 +1,68 @@
<h2 >Résumé</h2 > <h2>Résumé</h2>
<div class='heading' > <div class="heading">
<div class='col-xs-6' > <div class="col-xs-6">
<h1 id='title' >{{config.currentPoll.poll.title}}</h1 > <h1 id="title">{{ config.currentPoll.poll.title }}</h1>
<p >{{config.currentPoll.poll.description}}</p > <p>{{ config.currentPoll.poll.description }}</p>
<span class="creationDate" > <span class="creationDate"> Créé le {{ config.currentPoll.poll.creationDate.date }} </span>
Créé le {{config.currentPoll.poll.creationDate.date}} <span class="expiracyDate"> Expire le {{ config.currentPoll.poll.expiracyDate.date }} </span>
</span > <div class="votants">
<span class="expiracyDate" > <i class="fa fa-users"></i>
Expire le {{config.currentPoll.poll.expiracyDate.date}} {{ config.currentPoll.stacks.length }} votants, {{ config.currentPoll.choices.length }} choix,
</span > </div>
<div class="votants" > </div>
<i class='fa fa-users' ></i > </div>
{{config.currentPoll.stacks.length}} votants, <div class="preferred">
{{config.currentPoll.choices.length}} choix, <i class="fa fa-star"></i>
</div >
</div >
</div >
<div class="preferred" >
<i class='fa fa-star' ></i >
Pour l'instant, Pour l'instant,
<span *ngIf='severalPreferred' > <span *ngIf="severalPreferred">
les les
</span > <span *ngIf='!severalPreferred' > </span>
<span *ngIf="!severalPreferred">
le le
</span > </span>
choix ayant reçu le plus grand nombre de votes ( {{config.currentPoll.choices_count.maxScore}} points ) choix ayant reçu le plus grand nombre de votes ( {{ config.currentPoll.choices_count.maxScore }} points )
<span *ngIf='severalPreferred' > <span *ngIf="severalPreferred">
sont à égalité sont à égalité
</span > <span *ngIf='!severalPreferred' > </span>
<span *ngIf="!severalPreferred">
est est
</span > </span>
: :
<span class='preferred-result' > <span class="preferred-result">
{{preferred}} {{ preferred }}
</span > </span>
</div > </div>
<table class='table is-striped is-bordered is-hoverable' > <table class="table is-striped is-bordered is-hoverable">
<thead > <thead>
<tr *ngIf='config.currentPoll.choices && config.currentPoll.choices_count' > <tr *ngIf="config.currentPoll.choices && config.currentPoll.choices_count">
<td > <td>
Pseudo Pseudo
</td > </td>
<td <td *ngFor="let choice of config.currentPoll.choices">
*ngFor='let choice of config.currentPoll.choices' {{ choice.text }}
</td>
> </tr>
{{choice.text}}
</td >
</tr >
<!-- somme des points, dont un demi point pour les "peut être" --> <!-- somme des points, dont un demi point pour les "peut être" -->
</thead>
</thead > <tbody>
<tbody > <tr title='somme des points, dont un demi point pour les "peut être"'>
<tr <td><i class="fa fa-plus-circle"></i> points</td>
title='somme des points, dont un demi point pour les "peut être"' >
<td >
<i class='fa fa-plus-circle' ></i > points
</td >
<!-- <td--> <!-- <td-->
<!-- *ngFor='let choice of config.currentPoll.choices'--> <!-- *ngFor='let choice of config.currentPoll.choices'-->
<!-- [ngClass]='{"has-max-score" : config.currentPoll.choices_count.maxScore === config.currentPoll.choices_count.counts[choice.id].score}' >--> <!-- [ngClass]='{"has-max-score" : config.currentPoll.choices_count.maxScore === config.currentPoll.choices_count.counts[choice.id].score}' >-->
<!-- {{config.currentPoll.choices[choice.id].score}}--> <!-- {{config.currentPoll.choices[choice.id].score}}-->
<!-- </td >--> <!-- </td >-->
<td <td *ngFor="let choice of config.currentPoll.choices">
*ngFor='let choice of config.currentPoll.choices' {{ pollconfig.choices_count.counts[this.pollconfig.choices[2].id].score }}
> </td>
{{pollconfig.choices_count.counts[this.pollconfig.choices[2].id].score}} </tr>
</td > <tr class="details">
</tr > <td>
<tr class='details' > <i class="fa fa-eye"></i>
<td > </td>
<i class='fa fa-eye' ></i > <td *ngFor="let choice of config.currentPoll.choices">
</td > id: {{ choice.id }}
<td *ngFor='let choice of config.currentPoll.choices' > <br />
id: {{choice.id}}
<br >
<!-- yes {{config.currentPoll.choices_count.counts[choice.id].yes.count}}--> <!-- yes {{config.currentPoll.choices_count.counts[choice.id].yes.count}}-->
<!-- <br >--> <!-- <br >-->
<!-- maybe--> <!-- maybe-->
@ -83,56 +70,53 @@
<!-- <br >--> <!-- <br >-->
<!-- no {{(config.currentPoll.choices_count.counts[k].yes.maybe ? config.currentPoll.choices_count.counts[k].maybe.count * 0.5 : 0)}}--> <!-- no {{(config.currentPoll.choices_count.counts[k].yes.maybe ? config.currentPoll.choices_count.counts[k].maybe.count * 0.5 : 0)}}-->
<br > <br />
<!-- score :--> <!-- score :-->
<!-- {{(config.currentPoll.choices_count.counts[choice.id].score)}}--> <!-- {{(config.currentPoll.choices_count.counts[choice.id].score)}}-->
</td>
</td > </tr>
</tr > <tr class="votes-of-the-person" *ngFor="let voteStack of config.currentPoll.stacks">
<tr <td>
class='votes-of-the-person'
*ngFor='let voteStack of config.currentPoll.stacks'
>
<td >
<!-- // TODO show modify if this is our own vote--> <!-- // TODO show modify if this is our own vote-->
<button <button
(click)='config.loadVoteStack(voteStack)' (click)="config.loadVoteStack(voteStack)"
*ngIf="config.currentPoll.poll.modificationPolicy === 'everybody'" *ngIf="config.currentPoll.poll.modificationPolicy === 'everybody'"
class='btn btn--primary pull-left btn--small' class="btn btn--primary pull-left btn--small"
> >
<i class='fa fa-pencil' ></i > <i class="fa fa-pencil"></i>
</button > </button>
{{voteStack.pseudo}}
</td >
<td *ngFor='let v of getKeys(voteStack.votes)' >
<span *ngIf='voteStack.votes[v].value' >
{{ voteStack.pseudo }}
</td>
<td *ngFor="let v of getKeys(voteStack.votes)">
<span *ngIf="voteStack.votes[v].value">
<img <img
*ngIf="voteStack.votes[v].value == 'yes'" *ngIf="voteStack.votes[v].value == 'yes'"
src='../../../../assets/img/votant-sur.svg' src="../../../../assets/img/votant-sur.svg"
alt='yes' > alt="yes"
/>
<img <img
*ngIf="voteStack.votes[v].value == 'maybe'" *ngIf="voteStack.votes[v].value == 'maybe'"
src='../../../../assets/img/votant-pas-sur.svg' src="../../../../assets/img/votant-pas-sur.svg"
alt='yes' > alt="yes"
</span > />
</td > </span>
</tr > </td>
</tr>
<!-- bottom line shows each answer details--> <!-- bottom line shows each answer details-->
</tbody>
</tbody > </table>
</table >
<button <button
*ngIf='config.isAdmin' *ngIf="config.isAdmin"
type="button" type="button"
(click)="showModalDialog()" (click)="showModalDialog()"
pButton pButton
icon="pi pi-external-link" icon="pi pi-external-link"
label="Show" > label="Show"
>
show admin confirmation modal show admin confirmation modal
</button > </button>
<p-dialog <p-dialog
[(visible)]="config.displayConfirmVoteModalAdmin" [(visible)]="config.displayConfirmVoteModalAdmin"
[modal]="true" [modal]="true"
@ -140,32 +124,29 @@
[draggable]="false" [draggable]="false"
[resizable]="false" [resizable]="false"
[showHeader]="false" [showHeader]="false"
[transitionOptions]="'200ms'" > [transitionOptions]="'200ms'"
<div style='max-width: 30em; padding: 2em 1em;' > >
<h4 class='title' > <div style="max-width: 30em; padding: 2em 1em;">
<h4 class="title">
Participation validée ! Participation validée !
</h4 > </h4>
<p class="margin-btm-x1" > <p class="margin-btm-x1">
Votre vote a bien été pris en compte, mais faites attention, ce sondage n'autorise Votre vote a bien été pris en compte, mais faites attention, ce sondage n'autorise l'édition de votre vote
l'édition de votre vote qu'avec le lien personnalisé suivant : qu'avec le lien personnalisé suivant :
</p > </p>
<br > <br />
<a <a href="{{ config.urlAdmin }}" class="text-ellipsis">{{ config.urlAdmin }}</a>
href='{{config.urlAdmin}}' <framadate-copy-text [textToCopy]="config.urlAdmin"></framadate-copy-text>
class='text-ellipsis' >{{config.urlAdmin}}</a > <br />
<framadate-copy-text [textToCopy]='config.urlAdmin' ></framadate-copy-text > <p class="margin-btm-x6 margin-top-x2">Conservez-le précieusement !</p>
<br > <br />
<p class="margin-btm-x6 margin-top-x2" >Conservez-le précieusement !</p >
<br >
<button <button
type="button btn--large btn btn--block" type="button btn--large btn btn--block"
pButton pButton
icon="fa fa-check" icon="fa fa-check"
(click)="config.displayConfirmVoteModalAdmin=false" (click)="config.displayConfirmVoteModalAdmin = false"
label='Revenir au sondage' label="Revenir au sondage"
class="btn btn--primary btn--default btn--purple btn--black-text" > class="btn btn--primary btn--default btn--purple btn--black-text"
></button>
</button > </div>
</div > </p-dialog>
</p-dialog >

View File

@ -1,4 +1,4 @@
@import "../../../../assets/scss/variables"; @import '../../../../assets/scss/variables';
.person { .person {
font-weight: 700; font-weight: 700;

View File

@ -8,9 +8,8 @@ describe('VotingSummaryComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ VotingSummaryComponent ] declarations: [VotingSummaryComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,29 +1,26 @@
import {Component, Input, OnInit} from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
import {ConfigService} from "../../../services/config.service"; import { ConfigService } from '../../../services/config.service';
import {mockPoll3} from "../../../config/mocks/mock-poll3"; import { mockPoll3 } from '../../../config/mocks/mock-poll3';
@Component({ @Component({
selector: 'framadate-voting-summary', selector: 'framadate-voting-summary',
templateUrl: './voting-summary.component.html', templateUrl: './voting-summary.component.html',
styleUrls: ['./voting-summary.component.scss'] styleUrls: ['./voting-summary.component.scss'],
}) })
export class VotingSummaryComponent implements OnInit { export class VotingSummaryComponent implements OnInit {
preferred: string = 'rien'; preferred: string = 'rien';
severalPreferred: boolean = false; severalPreferred: boolean = false;
@Input() pollconfig = mockPoll3; @Input() pollconfig = mockPoll3;
constructor(public config: ConfigService) { constructor(public config: ConfigService) {}
}
ngOnInit() { ngOnInit() {
this.computePreferred(); this.computePreferred();
} }
getKeys(obj) { getKeys(obj) {
return Object.keys(obj) return Object.keys(obj);
} }
/** /**
@ -35,21 +32,18 @@ export class VotingSummaryComponent implements OnInit {
this.severalPreferred = false; this.severalPreferred = false;
let maxScore = this.pollconfig.choices_count.maxScore; let maxScore = this.pollconfig.choices_count.maxScore;
keys.forEach(item => { keys.forEach((item) => {
if (maxScore === this.pollconfig.choices_count.counts[item].score) { if (maxScore === this.pollconfig.choices_count.counts[item].score) {
if (this.preferred.length) { if (this.preferred.length) {
this.preferred += ', ' this.preferred += ', ';
this.severalPreferred = true; this.severalPreferred = true;
} }
// find the favourite // find the favourite
this.preferred += this.pollconfig.choices_count.counts[item].choice_text; this.preferred += this.pollconfig.choices_count.counts[item].choice_text;
} }
}); });
} }
showModalDialog() { showModalDialog() {
this.config.displayConfirmVoteModalAdmin = true; this.config.displayConfirmVoteModalAdmin = true;
} }

View File

@ -1,6 +1,4 @@
<form> <form>
<a class="next">Voir le graphique</a> <a class="next">Voir le graphique</a>
<h2 class="margin-top-x4">Les commentaires</h2> <h2 class="margin-top-x4">Les commentaires</h2>
@ -9,9 +7,4 @@
<span class="date date padding-btm-x1"> le 26 novembre 2019</span> <span class="date date padding-btm-x1"> le 26 novembre 2019</span>
Rock Luxio Surskit. Glacier Badge Rock Luxio Surskit. Glacier Badge
</p> </p>
</form> </form>

View File

@ -8,9 +8,8 @@ describe('VotingComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ VotingComponent ] declarations: [VotingComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -3,14 +3,11 @@ import { Component, OnInit } from '@angular/core';
@Component({ @Component({
selector: 'framadate-voting', selector: 'framadate-voting',
templateUrl: './voting.component.html', templateUrl: './voting.component.html',
styleUrls: ['./voting.component.scss'] styleUrls: ['./voting.component.scss'],
}) })
export class VotingComponent implements OnInit { export class VotingComponent implements OnInit {
show_mask=true; show_mask = true;
constructor() { constructor() {}
}
ngOnInit() {
}
ngOnInit() {}
} }

View File

@ -6,24 +6,19 @@
(change)="toggleColorblind()" (change)="toggleColorblind()"
class="input" class="input"
> >
<option value="true" > <option value="true">
{{ "pollGraphic.choiceColorblind" | translate }} {{ 'pollGraphic.choiceColorblind' | translate }}
</option > </option>
<option value="false" > <option value="false">
{{ "pollGraphic.choiceNotColorblind" | translate }} {{ 'pollGraphic.choiceNotColorblind' | translate }}
</option > </option>
</select > </select>
<span class="colorblind" > <span class="colorblind">
{{ "pollGraphic.colorblindText" | translate }} {{ 'pollGraphic.colorblindText' | translate }}
</span > </span>
<div class='well' > <div class="well">
work in progress to link data with poll config work in progress to link data with poll config
</div > </div>
<div > <div>
<canvas <canvas id="graph" width="100%" height="15em"></canvas>
id="graph" </div>
width="100%"
height="15em" ></canvas >
</div >

View File

@ -8,9 +8,8 @@ describe('PollGraphicComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ PollGraphicComponent ] declarations: [PollGraphicComponent],
}) }).compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -1,60 +1,58 @@
import {Component, Inject, OnInit} from "@angular/core"; import { Component, Inject, OnInit } from '@angular/core';
import {Chart} from "chart.js"; import { Chart } from 'chart.js';
import {DOCUMENT} from '@angular/common'; import { DOCUMENT } from '@angular/common';
import {mockGraphConfig} from "../config/mocks/mock-graph"; import { mockGraphConfig } from '../config/mocks/mock-graph';
import {graphOptions} from "../config/graph-canevas-options"; import { graphOptions } from '../config/graph-canevas-options';
import {ConfigService} from "../services/config.service"; import { ConfigService } from '../services/config.service';
import {mockPoll3} from "../config/mocks/mock-poll3"; import { mockPoll3 } from '../config/mocks/mock-poll3';
@Component({ @Component({
selector: "framadate-poll-graphic", selector: 'framadate-poll-graphic',
templateUrl: "./poll-graphic.component.html", templateUrl: './poll-graphic.component.html',
styleUrls: ["./poll-graphic.component.scss"] styleUrls: ['./poll-graphic.component.scss'],
}) })
export class PollGraphicComponent implements OnInit { export class PollGraphicComponent implements OnInit {
isColorblind: boolean = false; isColorblind: boolean = false;
pollConfigRetrieved: any = mockPoll3; pollConfigRetrieved: any = mockPoll3;
graphicConfig: any = mockGraphConfig; graphicConfig: any = mockGraphConfig;
preferred: any = "rien"; preferred: any = 'rien';
yesList: number[] = []; yesList: number[] = [];
maybeList: number[] = []; maybeList: number[] = [];
noList: number[] = []; noList: number[] = [];
nbPoll: number = 0; nbPoll: number = 0;
dateList: string[] = []; dateList: string[] = [];
constructor(@Inject(DOCUMENT) private document: any, constructor(@Inject(DOCUMENT) private document: any, private config: ConfigService) {}
private config: ConfigService) {
}
ngOnInit() { ngOnInit() {
this.formatDataAnswers(this.graphicConfig); this.formatDataAnswers(this.graphicConfig);
this.isColorblind = false; this.isColorblind = false;
this.pollConfigRetrieved = new Chart(this.document.getElementById("graph"), { this.pollConfigRetrieved = new Chart(this.document.getElementById('graph'), {
type: "horizontalBar", type: 'horizontalBar',
data: { data: {
labels: this.pollConfigRetrieved.choices.map(choice => choice.name), labels: this.pollConfigRetrieved.choices.map((choice) => choice.name),
datasets: [ datasets: [
{ {
type: "horizontalBar", type: 'horizontalBar',
stack: "Yes", stack: 'Yes',
backgroundColor: "#429a00", backgroundColor: '#429a00',
data: this.yesList data: this.yesList,
}, },
{ {
type: "horizontalBar", type: 'horizontalBar',
stack: "Yes", stack: 'Yes',
backgroundColor: "#f5a623", backgroundColor: '#f5a623',
data: this.maybeList data: this.maybeList,
}, },
{ {
type: "horizontalBar", type: 'horizontalBar',
stack: "No", stack: 'No',
backgroundColor: "#cd0000", backgroundColor: '#cd0000',
data: this.noList data: this.noList,
}
]
}, },
options: graphOptions ],
},
options: graphOptions,
}); });
} }
@ -65,15 +63,15 @@ export class PollGraphicComponent implements OnInit {
formatDataAnswers(poll) { formatDataAnswers(poll) {
// if (poll && poll.pollType === "date") { // if (poll && poll.pollType === "date") {
this.initPollCounter(); this.initPollCounter();
poll.answers.forEach(response => { poll.answers.forEach((response) => {
switch (response.text) { switch (response.text) {
case "yes": case 'yes':
this.yesList[this.nbPoll - 1]++; this.yesList[this.nbPoll - 1]++;
break; break;
case "maybe": case 'maybe':
this.maybeList[this.nbPoll - 1]++; this.maybeList[this.nbPoll - 1]++;
break; break;
case "no": case 'no':
this.noList[this.nbPoll - 1]++; this.noList[this.nbPoll - 1]++;
break; break;
} }
@ -83,7 +81,7 @@ export class PollGraphicComponent implements OnInit {
initPollCounter() { initPollCounter() {
this.nbPoll++; this.nbPoll++;
this.dateList[this.nbPoll - 1] = "jeudi"; this.dateList[this.nbPoll - 1] = 'jeudi';
this.maybeList[this.nbPoll - 1] = 0; this.maybeList[this.nbPoll - 1] = 0;
this.yesList[this.nbPoll - 1] = 0; this.yesList[this.nbPoll - 1] = 0;
this.noList[this.nbPoll - 1] = 0; this.noList[this.nbPoll - 1] = 0;

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More