Feature/simplify scss

This commit is contained in:
ty kayn 2020-04-21 10:50:26 +02:00
parent 88fec2c0c6
commit ba7a24708d
183 changed files with 7788 additions and 7778 deletions

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@ image: weboaks/node-karma-protractor-chrome
stages: stages:
- test - test
- e2e # - e2e
cache: cache:
paths: paths:
@ -13,17 +13,17 @@ test:
script: script:
- npm i - npm i
- pkill Xvfb - pkill Xvfb
- npm run test - npm run test:ci
artifacts: artifacts:
paths: paths:
- coverage/ - coverage/
e2e: #e2e:
stage: e2e # stage: e2e
script: # script:
- npm i # - npm i
- pkill Xvfb # - pkill Xvfb
- npm run e2e # - npm run e2e
pages: pages:
stage: .post stage: .post

View File

@ -32,7 +32,7 @@
"node_modules/font-awesome/css/font-awesome.css", "node_modules/font-awesome/css/font-awesome.css",
"node_modules/primeng/resources/themes/nova-light/theme.css", "node_modules/primeng/resources/themes/nova-light/theme.css",
"node_modules/primeng/resources/primeng.min.css", "node_modules/primeng/resources/primeng.min.css",
"src/styles.scss" "src/assets/scss/styles.scss"
], ],
"scripts": [ "scripts": [
"node_modules/marked/lib/marked.js", "node_modules/marked/lib/marked.js",

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,11 @@
import 'jest-preset-angular';
// const { defaults } = require('jest-config'); // const { defaults } = require('jest-config');
// //
// module.exports = { // module.exports = {
// verbose: true, // verbose: true,
// collectCoverage: true, // collectCoverage: true,
// collectCoverageFrom: ['src/**/*.ts'], // // collectCoverageFrom: ['src/**/*.ts'],
// collectCoverageFrom: ['src/app/pages/admin/*.ts'],
// }; // };
Error.stackTraceLimit = 2;

View File

@ -1,102 +1,107 @@
{ {
"name": "framadate-funky-frontend", "name": "framadate-funky-frontend",
"version": "1.0.0", "version": "1.0.0",
"licence": "AGPL-3.0-or-later", "licence": "AGPL-3.0-or-later",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "ng serve", "start": "ng serve",
"compodoc": "compodoc -p tsconfig.json", "compodoc": "compodoc -p tsconfig.json",
"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",
"build:demo": "ng build --crossOrigin=anonymous --extractCss=true --progress=true --prod && npm run package", "build:demo": "ng build --crossOrigin=anonymous --extractCss=true --progress=true --prod && npm run package",
"build:demobliss": "ng build --crossOrigin=anonymous --extractCss=true --baseHref=https://framadate-api.cipherbliss.com --progress=true --prod && npm run package", "build:demobliss": "ng build --crossOrigin=anonymous --extractCss=true --baseHref=https://framadate-api.cipherbliss.com --progress=true --prod && npm run package",
"test": "ng test --watch=false", "test": "jest",
"lint": "ng lint", "test:watch": "jest --watch",
"e2e": "ng e2e", "test:ci": "jest --runInBand",
"format:check": "prettier --list-different \"src/{app,environments,assets}/**/*{.ts,.js,.json,.css,.scss}\"", "lint": "ng lint",
"format:all": "prettier --write \"src/**/*.{js,jsx,ts,tsx,md,html,css,scss}\"", "e2e": "ng e2e",
"trans": "ng xi18n --output-path=src/locale --i18n-locale=fr", "format:check": "prettier --list-different \"src/{app,environments,assets}/**/*{.ts,.js,.json,.css,.scss}\"",
"storybook": "start-storybook -p 6006", "format:all": "prettier --write \"src/**/*.{js,jsx,ts,tsx,md,html,css,scss}\"",
"build-storybook": "build-storybook", "trans": "ng xi18n --output-path=src/locale --i18n-locale=fr",
"postinstall": "ngcc" "storybook": "start-storybook -p 6006",
}, "build-storybook": "build-storybook",
"private": false, "postinstall": "ngcc"
"dependencies": { },
"@angular/animations": "^9.1.1", "private": false,
"@angular/cdk": "^9.2.0", "dependencies": {
"@angular/common": "^9.0.7", "@angular/animations": "^9.1.1",
"@angular/compiler": "^9.0.7", "@angular/cdk": "^9.2.0",
"@angular/core": "^9.0.7", "@angular/common": "^9.0.7",
"@angular/forms": "^9.0.7", "@angular/compiler": "^9.0.7",
"@angular/localize": "^9.1.1", "@angular/core": "^9.0.7",
"@angular/platform-browser": "^9.0.7", "@angular/forms": "^9.0.7",
"@angular/platform-browser-dynamic": "^9.0.7", "@angular/localize": "^9.1.1",
"@angular/router": "^9.0.7", "@angular/platform-browser": "^9.0.7",
"@fullcalendar/core": "^4.4.0", "@angular/platform-browser-dynamic": "^9.0.7",
"@ngx-translate/core": "^12.1.2", "@angular/router": "^9.0.7",
"@ngx-translate/http-loader": "^4.0.0", "@fullcalendar/core": "^4.4.0",
"angular-date-value-accessor": "^1.0.2", "@ngx-translate/core": "^12.1.2",
"bulma": "^0.8.2", "@ngx-translate/http-loader": "^4.0.0",
"chart.js": "^2.8.0", "angular-date-value-accessor": "^1.0.2",
"font-awesome": "^4.7.0", "bulma": "^0.8.2",
"karma-coverage": "^2.0.1", "chart.js": "^2.8.0",
"karma-firefox-launcher": "^1.3.0", "font-awesome": "^4.7.0",
"karma-phantomjs-launcher": "^1.0.4", "jest-preset-angular": "^8.1.3",
"ngx-clipboard": "^13.0.0", "karma-coverage": "^2.0.1",
"ngx-markdown": "^9.0.0", "karma-firefox-launcher": "^1.3.0",
"ngx-toaster": "^1.0.1", "karma-phantomjs-launcher": "^1.0.4",
"primeicons": "^2.0.0", "ngx-clipboard": "^13.0.0",
"primeng": "^9.0.5", "ngx-markdown": "^9.0.0",
"quill": "^1.3.7", "ngx-toaster": "^1.0.1",
"rxjs": "^6.5.5", "primeicons": "^2.0.0",
"rxjs-compat": "^6.5.5", "primeng": "^9.0.5",
"tslib": "^1.11.1", "quill": "^1.3.7",
"zone.js": "^0.10.3" "rxjs": "^6.5.5",
}, "rxjs-compat": "^6.5.5",
"devDependencies": { "tslib": "^1.11.1",
"@angular-builders/jest": "^9.0.1", "zone.js": "^0.10.3"
"@angular-devkit/build-angular": "^0.901.1", },
"@angular/cli": "^9.0.7", "devDependencies": {
"@angular/compiler-cli": "^9.1.1", "@angular-builders/jest": "^9.0.1",
"@angular/language-service": "^9.0.7", "@angular-devkit/build-angular": "^0.901.1",
"@babel/core": "^7.9.0", "@angular/cli": "^9.0.7",
"@storybook/addon-actions": "^5.3.18", "@angular/compiler-cli": "^9.1.1",
"@storybook/addon-links": "^5.3.18", "@angular/language-service": "^9.0.7",
"@storybook/addon-notes": "^5.3.18", "@babel/core": "^7.9.0",
"@storybook/addons": "^5.3.18", "@storybook/addon-actions": "^5.3.18",
"@storybook/angular": "^5.3.18", "@storybook/addon-links": "^5.3.18",
"@types/jasmine": "^3.5.10", "@storybook/addon-notes": "^5.3.18",
"@types/jasminewd2": "~2.0.8", "@storybook/addons": "^5.3.18",
"@types/jest": "^25.2.1", "@storybook/angular": "^5.3.18",
"@types/node": "^13.11.1", "@types/jasminewd2": "~2.0.8",
"@typescript-eslint/eslint-plugin": "^2.27.0", "@types/jest": "^25.2.1",
"@typescript-eslint/parser": "^2.27.0", "@types/node": "^13.11.1",
"babel-loader": "^8.1.0", "@typescript-eslint/eslint-plugin": "^2.27.0",
"compodoc": "^0.0.41", "@typescript-eslint/parser": "^2.27.0",
"eslint": "^6.8.0", "babel-loader": "^8.1.0",
"eslint-config-prettier": "^6.10.1", "compodoc": "^0.0.41",
"eslint-plugin-prettier": "^3.1.3", "eslint": "^6.8.0",
"husky": "^4.2.5", "eslint-config-prettier": "^6.10.1",
"jasmine-core": "~3.5.0", "eslint-plugin-prettier": "^3.1.3",
"jasmine-spec-reporter": "~5.0.1", "husky": "^4.2.5",
"jest": "^25.3.0", "jasmine-core": "~3.5.0",
"lint-staged": "^10.1.3", "jasmine-spec-reporter": "~5.0.1",
"prettier": "^2.0.4", "jest": "^25.3.0",
"protractor": "~5.4.3", "lint-staged": "^10.1.3",
"ts-node": "~8.8.2", "prettier": "^2.0.4",
"typescript": "~3.8.3" "protractor": "~5.4.3",
}, "ts-node": "~8.8.2",
"husky": { "typescript": "~3.8.3"
"hooks": { },
"pre-commit": "lint-staged" "husky": {
} "hooks": {
}, "pre-commit": "lint-staged"
"lint-staged": { }
"src/{app,environments,assets}/**/*.{js,jsx,ts,tsx,md,html,css,scss}": [ },
"prettier --write", "lint-staged": {
"git add" "src/{app,environments,assets}/**/*.{js,jsx,ts,tsx,md,html,css,scss}": [
], "prettier --write",
"*.js": "eslint --cache --fix" "git add"
} ]
},
"jest": {
"preset": "jest-preset-angular",
"setupFilesAfterEnv": "./jest.config.js"
}
} }

View File

@ -1,31 +1,31 @@
<div id="big_container" class="{{ this.config.preferences.themeClass }}"> <div id="big_container" class="{{ this.config.preferences.themeClass }}">
<header class="big-header"> <header class="big-header">
<div class="container"> <div class="container">
<div class="columns"> <div class="columns">
<div class="column"> <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 togglable-menu" *ngIf="config.menuVisible">
<framadate-theme-selector></framadate-theme-selector> <framadate-theme-selector></framadate-theme-selector>
<framadate-navigation *ngIf="config.menuVisible" [step]="step"></framadate-navigation> <framadate-navigation [step]="step"></framadate-navigation>
<framadate-debugger *ngIf="isDevelopmentEnv"></framadate-debugger> <framadate-debugger *ngIf="isDevelopmentEnv"></framadate-debugger>
<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> <p-toast position="top-right"></p-toast>
</div> </div>

View File

@ -1,13 +1,13 @@
@charset "UTF-8"; @charset "UTF-8";
.big-header { .big-header {
padding: 0.5rem; padding: 0.5rem;
} }
i { i {
display: block; display: block;
} }
.language-selector { .language-selector {
width: auto; width: auto;
} }

View File

@ -3,29 +3,29 @@ import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [RouterTestingModule], imports: [RouterTestingModule],
declarations: [AppComponent], declarations: [AppComponent],
}).compileComponents(); }).compileComponents();
})); }));
it('should create the app', () => { it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance; const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy(); expect(app).toBeTruthy();
}); });
it(`should have as title 'framadate'`, () => { it(`should have as title 'framadate'`, () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance; const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('framadate'); expect(app.title).toEqual('framadate');
}); });
it('should render title in a h1 tag', () => { it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to framadate!'); expect(compiled.querySelector('h1').textContent).toContain('Welcome to framadate!');
}); });
}); });

View File

@ -7,49 +7,49 @@ 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( constructor(
private translate: TranslateService, 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 this.route.events
.pipe(filter((event) => event instanceof NavigationStart)) .pipe(filter((event) => event instanceof NavigationStart))
.subscribe((event: 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;
} }
updateCurrentTab(event) { updateCurrentTab(event) {
if (event.url) { if (event.url) {
const tab = event.url.split('/'); const tab = event.url.split('/');
if (tab && tab[2]) { if (tab && tab[2]) {
this.step = tab[2]; this.step = tab[2];
} else { } else {
this.step = 'home'; this.step = 'home';
} }
} }
} }
} }

View File

@ -7,11 +7,11 @@ import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
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 { ClipboardModule } from 'ngx-clipboard'; import { ClipboardModule } from 'ngx-clipboard';
@ -60,82 +60,82 @@ import { SelectorComponent } from './ui/selector/selector.component';
import { ThemeSelectorComponent } from './ui/theme-selector/theme-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) {
return 'some value'; return 'some value';
} }
} }
registerLocaleData(localeFr, 'fr'); registerLocaleData(localeFr, 'fr');
registerLocaleData(localeEn, 'en'); registerLocaleData(localeEn, 'en');
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader { export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
return new TranslateHttpLoader(http); return new TranslateHttpLoader(http);
} }
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
BaseComponent, BaseComponent,
KindComponent, KindComponent,
HeaderComponent, HeaderComponent,
NavigationComponent, NavigationComponent,
DatesComponent, DatesComponent,
DebuggerComponent, DebuggerComponent,
VisibilityComponent, VisibilityComponent,
ResumeComponent, ResumeComponent,
PicturesComponent, PicturesComponent,
AnswersComponent, AnswersComponent,
EndConfirmationComponent, EndConfirmationComponent,
CreateOrRetrieveComponent, CreateOrRetrieveComponent,
VotingSummaryComponent, VotingSummaryComponent,
VotingGraphComponent, VotingGraphComponent,
VotingChoiceComponent, VotingChoiceComponent,
PasswordComponent, PasswordComponent,
HomeComponent, HomeComponent,
PollGraphicComponent, PollGraphicComponent,
AdminComponent, AdminComponent,
SelectorComponent, SelectorComponent,
PollDisplayComponent, PollDisplayComponent,
VotingComponent, VotingComponent,
VotingCommentComponent, VotingCommentComponent,
ResettableInputDirective, ResettableInputDirective,
ErasableInputComponent, ErasableInputComponent,
CopyTextComponent, CopyTextComponent,
CommentsListComponent, CommentsListComponent,
ChoicesListComponent, ChoicesListComponent,
VotingNavigationComponent, VotingNavigationComponent,
ThemeSelectorComponent, ThemeSelectorComponent,
MasterHeadComponent, MasterHeadComponent,
LanguageComponent, LanguageComponent,
], ],
imports: [ imports: [
ConfirmDialogModule, ConfirmDialogModule,
ClipboardModule, ClipboardModule,
CommonModule, CommonModule,
BrowserModule, BrowserModule,
DialogModule, DialogModule,
DateValueAccessorModule, DateValueAccessorModule,
BrowserAnimationsModule, BrowserAnimationsModule,
AppRoutingModule, AppRoutingModule,
ToastModule, ToastModule,
MessageModule, MessageModule,
MarkdownModule.forRoot(), MarkdownModule.forRoot(),
TranslateModule.forRoot({ TranslateModule.forRoot({
missingTranslationHandler: { missingTranslationHandler: {
provide: MissingTranslationHandler, provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler, useClass: MyMissingTranslationHandler,
}, },
// useDefaultLang: false, // useDefaultLang: false,
loader: { loader: {
provide: TranslateLoader, provide: TranslateLoader,
useFactory: HttpLoaderFactory, useFactory: HttpLoaderFactory,
deps: [HttpClient], deps: [HttpClient],
}, },
}), }),
HttpClientModule, HttpClientModule,
FormsModule, FormsModule,
], ],
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,63 +1,63 @@
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
* @param date * @param date
*/ */
addDaysToDate(days: number, date: Date) { addDaysToDate(days: number, date: Date) {
date = new Date(date.valueOf()); date = new Date(date.valueOf());
date.setDate(date.getDate() + days); date.setDate(date.getDate() + days);
return date; return date;
} }
/** /**
* *
* @param d1 * @param d1
* @param d2 * @param d2
* @param interval * @param interval
*/ */
getDatesInRange(d1: Date, d2: Date, interval: number) { getDatesInRange(d1: Date, d2: Date, interval: number) {
d1 = new Date(d1); d1 = new Date(d1);
d2 = new Date(d2); d2 = new Date(d2);
const dates = []; const dates = [];
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);
} }
/** /**
* get the number of days between two dates * get the number of days between two dates
* @param d1 * @param d1
* @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);
} }
/** /**
* format a date object to the date format used by the inputs of type date * format a date object to the date format used by the inputs of type date
* YYYY-MM-DD * YYYY-MM-DD
* @param date * @param date
*/ */
formateDate(date) { formateDate(date) {
return [ return [
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

@ -5,80 +5,80 @@ 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;
literal: string; literal: string;
date_object?: object; date_object?: object;
} }
const baseConfigValues = { const baseConfigValues = {
pollType: 'dates', pollType: 'dates',
title: '', title: '',
description: '', description: '',
myName: '', myName: '',
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';
myName: string = environment.production ? '' : 'mon pseudo'; myName: string = environment.production ? '' : 'mon pseudo';
myComment: string = environment.production ? '' : 'wouah trop bien framadate!'; myComment: string = environment.production ? '' : 'wouah trop bien framadate!';
isAdmin: boolean = !environment.production; isAdmin = !environment.production;
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
*/ */
allowSeveralHours = 'true'; allowSeveralHours = 'true';
// access // access
visibility = 'link_only'; // visible to anyone with the link: visibility = 'link_only'; // visible to anyone with the link:
voteChoices = 'only_yes'; // possible answers to a vote choice: only "yes", "yes, maybe, no" voteChoices = 'only_yes'; // possible answers to a vote choice: only "yes", "yes, maybe, no"
creationDate = new Date(); creationDate = new Date();
expirationDate = ''; // expiracy date expirationDate = ''; // expiracy date
voteStackId = null; // id of the vote stack to update voteStackId = null; // id of the vote stack to update
pollId = null; // id of the current poll when created. data given by the backend api pollId = null; // id of the current poll when created. data given by the backend api
pollSlug = null; // id of the current poll when created. data given by the backend api pollSlug = null; // id of the current poll when created. data given by the backend api
currentPoll; // current poll selected with createPoll or getPoll of ConfigService currentPoll; // current poll selected with createPoll or getPoll of ConfigService
passwordAccess = 0; passwordAccess = 0;
password = ''; password = '';
customUrl = ''; // custom slug in the url, must be unique customUrl = ''; // custom slug in the url, must be unique
customUrlIsUnique = null; // given by the backend customUrlIsUnique = null; // given by the backend
urlSlugPublic = null; urlSlugPublic = null;
urlPublic = environment.production ? '' : environment.baseHref + '/#/poll/id/4'; urlPublic = environment.production ? '' : environment.baseHref + '/#/poll/id/4';
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
answers: PollAnswer[] = defaultAnswers; answers: PollAnswer[] = defaultAnswers;
// front end choices // front end choices
themeChoices: string[] = ['light-watermelon', 'dark-crystal', 'hot-covid']; themeChoices: string[] = ['light-watermelon', 'dark-crystal', 'hot-covid'];
themeSelected = 0; themeSelected = 0;
themeClass = 'theme-light-watermelon'; themeClass = 'theme-light-watermelon';
// modals // modals
displayConfirmVoteModalAdmin = false; displayConfirmVoteModalAdmin = false;
resetConfig() { resetConfig() {
const self = this; const self = this;
Object.keys(baseConfigValues).forEach((key) => { Object.keys(baseConfigValues).forEach((key) => {
self[key] = baseConfigValues[key]; self[key] = baseConfigValues[key];
}); });
} }
} }

View File

@ -3,73 +3,73 @@ 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
/** /**
* generate unique id to have a default url for future poll * generate unique id to have a default url for future poll
*/ */
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, const r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8; v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16); return v.toString(16);
}); });
} }
/** /**
* make a uniq slug for the current poll creation * make a uniq slug for the current poll creation
* @param str * @param str
*/ */
makeSlug(config: PollConfig) { makeSlug(config: PollConfig) {
let str = ''; let str = '';
str = str =
config.creationDate.getFullYear() + config.creationDate.getFullYear() +
'_' + '_' +
(config.creationDate.getMonth() + 1) + (config.creationDate.getMonth() + 1) +
'_' + '_' +
config.creationDate.getDate() + config.creationDate.getDate() +
'_' + '_' +
config.myName + config.myName +
'_' + '_' +
config.title; 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 = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;'; const from = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;';
var to = 'aaaaeeeeiiiioooouuuunc------'; const to = 'aaaaeeeeiiiioooouuuunc------';
for (var i = 0, l = from.length; i < l; i++) { for (let i = 0, l = from.length; i < l; i++) {
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i)); str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
} }
str = str str = str
.replace(/[^a-z0-9 -]/g, '') // remove invalid chars .replace(/[^a-z0-9 -]/g, '') // remove invalid chars
.replace(/\s+/g, '-') // collapse whitespace and replace by - .replace(/\s+/g, '-') // collapse whitespace and replace by -
.replace(/-+/g, '-'); // collapse dashes .replace(/-+/g, '-'); // collapse dashes
return str; return str;
} }
/** /**
* prepare headers like the charset and json type for any call to the backend * prepare headers like the charset and json type for any call to the backend
* @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,21 +1,21 @@
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();
@ -24,84 +24,84 @@ const currentDay = new Date().getDate();
export const basicSlicesOfDay: TimeSlices[] = [{ literal: 'matin' }, { literal: 'midi' }, { literal: 'soir' }]; export const basicSlicesOfDay: TimeSlices[] = [{ 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: url:
'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574', '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: url:
'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574', '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: url:
'https://mastodon.cipherbliss.com/system/media_attachments/files/001/439/118/original/6fcf149bd902841b.png?1579471574', '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,22 +1,22 @@
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: text:
'Pokem ipsum dolor sit amet Electric Cottonee Scratch Leech Life Ice Berry Ducklett. Leaf Green Durant Zoroark\n' + 'Pokem ipsum dolor sit amet Electric Cottonee Scratch Leech Life Ice Berry Ducklett. Leaf Green Durant Zoroark\n' +
' Skitty Rock Luxio Surskit. Glacier Badge', ' 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',
}, },
], ],
}; };

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +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, id: 1000002,
title: 'bleh z zr erth tuyjikioy yylil test2', title: 'bleh z zr erth tuyjikioy yylil test2',
customUrl: null, customUrl: null,
description: 'maaaaaaaaaaah 2', description: 'maaaaaaaaaaah 2',
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,
}, },
]; ];

View File

@ -2,9 +2,9 @@ import { Directive, ElementRef, forwardRef, HostListener, Renderer2 } from '@ang
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,
}; };
/** /**
@ -14,36 +14,36 @@ export const DATE_VALUE_ACCESSOR: any = {
* `<input type="date" name="myBirthday" ngModel useValueAsDate>` * `<input type="date" name="myBirthday" ngModel useValueAsDate>`
*/ */
@Directive({ @Directive({
// this selector changes the previous behavior silently and might break existing code // this selector changes the previous behavior silently and might break existing code
// selector: 'input[type=date][formControlName],input[type=date][formControl],input[type=date][ngModel]', // selector: 'input[type=date][formControlName],input[type=date][formControl],input[type=date][ngModel]',
// 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('input', ['$event.target.valueAsDate']) onChange = (_: any) => {};
@HostListener('blur', []) onTouched = () => {}; @HostListener('blur', []) onTouched = () => {};
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {} constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
writeValue(value: Date): void { writeValue(value: Date): void {
if (!value) { if (!value) {
this._renderer.setProperty(this._elementRef.nativeElement, 'value', null); this._renderer.setProperty(this._elementRef.nativeElement, 'value', null);
return; return;
} }
this._renderer.setProperty(this._elementRef.nativeElement, 'valueAsDate', value); this._renderer.setProperty(this._elementRef.nativeElement, 'valueAsDate', value);
} }
registerOnChange(fn: (_: any) => void): void { registerOnChange(fn: (_: any) => void): void {
this.onChange = fn; this.onChange = fn;
} }
registerOnTouched(fn: () => void): void { registerOnTouched(fn: () => void): void {
this.onTouched = fn; this.onTouched = fn;
} }
setDisabledState(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled); this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
} }
} }

View File

@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
import { DateValueAccessor } from './date-value-accessor'; 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,30 +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>étape actuelle {{ config.step }} / {{ config.stepMax }}</li> <!-- <li>étape actuelle {{ config.step }} / {{ config.stepMax }}</li>-->
<li>formulaire valide : {{ formIsValid }}</li> <!-- <li>formulaire valide : {{ formIsValid }}</li>-->
<li>type de formulaire: {{ config.pollType }}</li> <!-- <li>type de formulaire: {{ config.pollType }}</li>-->
</ul> <!-- </ul>-->
<button class="btn btn--primary" i18n (click)="config.createPoll()"> <!-- <button class="btn btn&#45;&#45;primary" i18n (click)="config.createPoll()">-->
Envoyer le formulaire <!-- Envoyer le formulaire-->
</button> <!-- </button>-->
<button class="btn btn--primary" i18n (click)="config.getPollById('1', 'example password')"> <!-- <button class="btn btn&#45;&#45;primary" i18n (click)="config.getPollById('1', 'example password')">-->
get poll 1 <!-- get poll 1-->
</button> <!-- </button>-->
<button class="btn btn--primary" i18n (click)="config.getMyPolls('tktest@tktest.com')"> <!-- <button class="btn btn&#45;&#45;primary" i18n (click)="config.getMyPolls('tktest@tktest.com')">-->
get my polls <!-- get my polls-->
</button> <!-- </button>-->
<button class="btn btn--success" (click)="launchToast()"> <!-- <button class="btn btn&#45;&#45;success" (click)="launchToast()">-->
launch success toast <!-- launch success toast-->
</button> <!-- </button>-->
<a [routerLink]="'/vote/poll/id/3'" class="btn btn--success"> <!-- <a [routerLink]="'/vote/poll/id/3'" class="btn btn&#45;&#45;success">-->
See example of vote page <!-- See example of vote page-->
</a> <!-- </a>-->
</div> <!--</div>-->

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DebuggerComponent } from './debugger.component'; import { DebuggerComponent } from './debugger.component';
describe('DebuggerComponent', () => { describe('DebuggerComponent', () => {
let component: DebuggerComponent; let component: DebuggerComponent;
let fixture: ComponentFixture<DebuggerComponent>; let fixture: ComponentFixture<DebuggerComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [DebuggerComponent], declarations: [DebuggerComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(DebuggerComponent); fixture = TestBed.createComponent(DebuggerComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -2,27 +2,27 @@ 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]) {
return false; return false;
} }
this.config[key] = val; this.config[key] = val;
return true; return true;
} }
launchToast() { launchToast() {
this.config.handleError({ message: 'hop' }); this.config.handleError({ message: 'hop' });
} }
} }

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component'; import { HeaderComponent } from './header.component';
describe('HeaderComponent', () => { describe('HeaderComponent', () => {
let component: HeaderComponent; let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>; let fixture: ComponentFixture<HeaderComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [HeaderComponent], declarations: [HeaderComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent); fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -1,12 +1,12 @@
import { Component, OnInit } from '@angular/core'; 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

@ -1,41 +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, h2,
h1 { 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, select,
input[type='date'] { input[type='date'] {
max-width: 130px; max-width: 130px;
} }
.btn--outline { .btn--outline {
margin-bottom: 70px; margin-bottom: 70px;
} }

View File

@ -2,23 +2,23 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AdminComponent } from './admin.component'; import { AdminComponent } from './admin.component';
describe('AdminComponent', () => { fdescribe('AdminComponent', () => {
let component: AdminComponent; let component: AdminComponent;
let fixture: ComponentFixture<AdminComponent>; let fixture: ComponentFixture<AdminComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [AdminComponent], declarations: [AdminComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(AdminComponent); fixture = TestBed.createComponent(AdminComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -1,76 +1,76 @@
<div class="answers"> <div class="answers">
<h1 i18n> <h1 i18n>
Choisir les propositions Choisir les propositions
</h1> </h1>
<p class="subtitle" i18n> <p 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 #answers *ngFor="let answer of config.answers; index as i; trackBy: trackFunction" class="answer-item"> <li #answers *ngFor="let answer of config.answers; index as i; trackBy: trackFunction" class="answer-item">
<button class="btn btn--default" title="ajouter une image" (click)="showModalForPictureOfAnswer(answer)"> <button class="btn btn--default" title="ajouter une image" (click)="showModalForPictureOfAnswer(answer)">
<i class="fa fa-image"></i> <i class="fa fa-image"></i>
</button> </button>
<label for="answer_{{ answer.id }}_url" (click)="showModalForPictureOfAnswer(answer)"> <label for="answer_{{ answer.id }}_url" (click)="showModalForPictureOfAnswer(answer)">
<img class="img-thumbnail" src="{{ answer.url }}" alt="image {{ answer.url }}" /> <img class="img-thumbnail" src="{{ answer.url }}" alt="image {{ answer.url }}" />
</label> </label>
<p-dialog class="url-dialog" [(visible)]="display" [modal]="true"> <p-dialog class="url-dialog" [(visible)]="display" [modal]="true">
<p-header> <p-header>
{{ answer.text }} {{ answer.text }}
</p-header> </p-header>
<form action="#" (submit)="display = false"> <form action="#" (submit)="display = false">
<label for="answer_{{ answer.id }}_url"> <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 class="btn btn--alert" (click)="config.answers.splice(i, 1)">X</button> <button class="btn btn--alert" (click)="config.answers.splice(i, 1)">X</button>
</li> </li>
</ol> </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 [routerLink]="'/home'" class="prev" i18n> <a [routerLink]="'/home'" class="prev" i18n>
Retour Retour
</a> </a>
</div> </div>

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AnswersComponent } from './answers.component'; import { AnswersComponent } from './answers.component';
describe('AnswersComponent', () => { describe('AnswersComponent', () => {
let component: AnswersComponent; let component: AnswersComponent;
let fixture: ComponentFixture<AnswersComponent>; let fixture: ComponentFixture<AnswersComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [AnswersComponent], declarations: [AnswersComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(AnswersComponent); fixture = TestBed.createComponent(AnswersComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -5,89 +5,89 @@ 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, @Inject(DOCUMENT) private document: any, private cd: ChangeDetectorRef) { constructor(public config: ConfigService, @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;
} }
}); });
} }
ngAfterViewInit() { ngAfterViewInit() {
this.focusOnAnswer(0); this.focusOnAnswer(0);
this.checkValidAnswers(); this.checkValidAnswers();
} }
trackFunction(index: number, item: any): number { trackFunction(index: number, item: any): number {
return item.id; return item.id;
} }
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) {
const AnswersDomToFocus = this.document.querySelectorAll('.answers .answer'); const AnswersDomToFocus = this.document.querySelectorAll('.answers .answer');
const dom = AnswersDomToFocus[i]; const dom = AnswersDomToFocus[i];
if (dom.focus) { if (dom.focus) {
dom.focus(); dom.focus();
} }
if (dom.select) { if (dom.select) {
dom.select(); dom.select();
} }
} }
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);
} }
} }
showModalForPictureOfAnswer(answer) { showModalForPictureOfAnswer(answer) {
// TODO // TODO
this.currentHeader = answer; this.currentHeader = answer;
this.display = true; this.display = true;
// this.config.todo(); // this.config.todo();
} }
} }

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

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { BaseComponent } from './base.component'; import { BaseComponent } from './base.component';
describe('BaseComponent', () => { describe('BaseComponent', () => {
let component: BaseComponent; let component: BaseComponent;
let fixture: ComponentFixture<BaseComponent>; let fixture: ComponentFixture<BaseComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [BaseComponent], declarations: [BaseComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(BaseComponent); fixture = TestBed.createComponent(BaseComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -2,27 +2,27 @@ 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
this.config.todo(); this.config.todo();
return true; return true;
} }
displayErrorMessage() { displayErrorMessage() {
// TODO // TODO
this.config.todo(); this.config.todo();
return true; return true;
} }
} }

View File

@ -1,71 +1,71 @@
<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 class="description margin-btm-x5" i18n>
{{ 'config.description' | translate }} {{ 'config.description' | translate }}
</p> </p>
<div class="btn-next"> <div class="btn-next">
<button [routerLink]="'step/date'" class="btn btn--full btn--primary"> <button [routerLink]="'step/date'" class="btn btn--full btn--primary">
{{ 'config.letsgo' | translate }} {{ 'config.letsgo' | translate }}
</button> </button>
</div> </div>
</section> </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 (ngSubmit)="findMyPollsByEmail(config.myEmail)"> <form (ngSubmit)="findMyPollsByEmail(config.myEmail)">
<label class="description" for="sendemail" i18n> <label class="description" for="sendemail" i18n>
<i class="fa fa-envelope"></i> <i class="fa fa-envelope"></i>
{{ 'config.find_helper' | translate }} : {{ 'config.find_helper' | translate }} :
</label> </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"
required="required" required="required"
type="email" type="email"
/> />
<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 class="list-my-polls" *ngIf="!config.loading"> <section class="list-my-polls" *ngIf="!config.loading">
<h2> <h2>
Mes Sondages trouvés: Mes Sondages trouvés:
</h2> </h2>
<ul class="poll-list" *ngFor="let poll of config.myPolls; index as i; trackBy: trackFunction"> <ul class="poll-list" *ngFor="let poll of config.myPolls; index as i; trackBy: trackFunction">
<li> <li>
<a href="{{ poll.url }}"> <a href="{{ poll.url }}">
{{ poll.title }} {{ poll.title }}
<sub> <sub>
{{ poll.description }} {{ poll.description }}
</sub> </sub>
</a> </a>
</li> </li>
</ul> </ul>
<div class="no-polls" *ngIf="!config.myPolls || !config.myPolls.length"> <div class="no-polls" *ngIf="!config.myPolls || !config.myPolls.length">
Aucun sondage. Aucun sondage.
</div> </div>
</section> </section>
<div class="loading" *ngIf="config.loading"> <div class="loading" *ngIf="config.loading">
<i class="fa fa-refresh fa-spin fa-3x fa-fw"></i> <i class="fa fa-refresh fa-spin fa-3x fa-fw"></i>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,27 +1,27 @@
.container { .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin: auto; margin: auto;
} }
h1 { h1 {
display: inline-block; display: inline-block;
margin-bottom: 3rem; margin-bottom: 3rem;
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;
margin-top: 5px; margin-top: 5px;
margin-right: auto; margin-right: auto;
margin-left: auto; margin-left: auto;
// background-color: $primary_color; // background-color: $primary_color;
} }
} }
label { label {
float: left; float: left;
} }
input[type='email'] { input[type='email'] {
display: block; display: block;
} }

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CreateOrRetrieveComponent } from './create-or-retrieve.component'; import { CreateOrRetrieveComponent } from './create-or-retrieve.component';
describe('CreateOrRetrieveComponent', () => { describe('CreateOrRetrieveComponent', () => {
let component: CreateOrRetrieveComponent; let component: CreateOrRetrieveComponent;
let fixture: ComponentFixture<CreateOrRetrieveComponent>; let fixture: ComponentFixture<CreateOrRetrieveComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [CreateOrRetrieveComponent], declarations: [CreateOrRetrieveComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(CreateOrRetrieveComponent); fixture = TestBed.createComponent(CreateOrRetrieveComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -3,32 +3,32 @@ 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 = false;
constructor(public config: ConfigService) { constructor(public config: ConfigService) {
super(config); super(config);
} }
ngOnInit() { ngOnInit() {
// 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;
} }
trackFunction(index: number, item: any): number { trackFunction(index: number, item: any): number {
return item.id; return item.id;
} }
} }

View File

@ -1,168 +1,168 @@
<h1 class="title is-1"><i class="fa fa-calendar"></i> {{ 'dates.title' | translate }}</h1> <h1 class="title is-1"><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 [(ngModel)]="config.allowSeveralHours" id="multi_hours" name="multi_hours"> <select [(ngModel)]="config.allowSeveralHours" id="multi_hours" name="multi_hours">
<option value="true">{{ 'dates.multiple.different' | translate }}</option> <option value="true">{{ 'dates.multiple.different' | translate }}</option>
<option value="false">{{ 'dates.multiple.identical' | translate }}</option> <option value="false">{{ 'dates.multiple.identical' | translate }}</option>
</select> </select>
<span i18n> <span i18n>
{{ 'dates.hours_each_day' | translate }} {{ 'dates.hours_each_day' | translate }}
</span> </span>
</label> </label>
</div> </div>
<button (click)="addDate()" class="btn btn--primary" id="add_date_button"> <button (click)="addDate()" class="btn btn--primary" id="add_date_button">
<i class="fa fa-plus"></i> <i class="fa fa-plus"></i>
{{ 'dates.add' | translate }} {{ 'dates.add' | translate }}
</button> </button>
<button <button
(click)="showDateInterval = !showDateInterval" (click)="showDateInterval = !showDateInterval"
[ngClass]="{ active: 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 (click)="emptyAll()" class="btn btn--warning" id="empty_button"> <button (click)="emptyAll()" class="btn btn--warning" id="empty_button">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
{{ 'dates.empty' | translate }} {{ 'dates.empty' | translate }}
</button> </button>
<section *ngIf="showDateInterval" class="date-interval"> <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 (change)="countDays()" [(ngModel)]="startDateInterval" type="date" /> <input (change)="countDays()" [(ngModel)]="startDateInterval" type="date" />
{{ 'dates.interval_span' | translate }} {{ 'dates.interval_span' | translate }}
<input (change)="countDays()" [(ngModel)]="endDateInterval" type="date" /> <input (change)="countDays()" [(ngModel)]="endDateInterval" type="date" />
<br /> <br />
</p> </p>
<button (click)="addIntervalOfDates()" class="btn btn-block btn--primary"> <button (click)="addIntervalOfDates()" class="btn btn-block btn--primary">
<i class="fa fa-plus"></i> <i class="fa fa-plus"></i>
{{ 'dates.interval_button' | translate }} {{ 'dates.interval_button' | translate }}
{{ intervalDays }} {{ intervalDays }}
{{ 'dates.interval_button_dates' | translate }} {{ 'dates.interval_button_dates' | translate }}
</button> </button>
<hr /> <hr />
</section> </section>
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
<div class="dates-list"> <div class="dates-list">
<div class="title"> <div class="title">
<span class="count-dates"> <span class="count-dates">
{{ config.timeList.length }} {{ config.timeList.length }}
</span> </span>
<span class="count-dates-txt"> <span class="count-dates-txt">
{{ 'dates.count_time' | translate }} {{ '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 *ngIf="'false' === config.allowSeveralHours" class="identical-dates"> <div *ngIf="'false' === config.allowSeveralHours" class="identical-dates">
<div *ngFor="let time of config.timeList; index as id" class="time-choice"> <div *ngFor="let time of config.timeList; index as id" class="time-choice">
<label for="timeChoices_{{ id }}"> <label for="timeChoices_{{ id }}">
<i class="fa fa-clock-o"></i> <i class="fa fa-clock-o"></i>
</label> </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 (click)="time.timeList.splice(id, 1)" class="btn btn-warning"> <button (click)="time.timeList.splice(id, 1)" class="btn btn-warning">
<i class="fa fa-times"></i> <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 class="btn btn--primary" (click)="addDate()">
{{ 'dates.add' | translate }} {{ 'dates.add' | translate }}
</button> </button>
<div *ngFor="let choice of config.dateList; index as id" class="date-choice"> <div *ngFor="let choice of config.dateList; index as id" class="date-choice">
{{ id }}) {{ 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 (click)="config.dateList.splice(id, 1)" class="btn btn-warning"> <button (click)="config.dateList.splice(id, 1)" class="btn btn-warning">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</button> </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 *ngIf="'true' === config.allowSeveralHours" class="several-times"> <div *ngIf="'true' === config.allowSeveralHours" class="several-times">
<div *ngFor="let timeItem of choice.timeList; index as idTime" class="time-choice"> <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 (click)="choice.timeList.splice(idTime, 1)" class="btn btn-warning"> <button (click)="choice.timeList.splice(idTime, 1)" class="btn btn-warning">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="column"> <div class="column">
<framadate-resume></framadate-resume> <framadate-resume></framadate-resume>
</div> </div>
</div> </div>
<a [routerLink]="'/step/resume'" class="btn btn--full btn--primary"> <a [routerLink]="'/step/resume'" class="btn btn--full btn--primary">
C'est parfait! C'est parfait!
</a> </a>
<a [routerLink]="'/step/home'" class="prev"> <a [routerLink]="'/step/home'" class="prev">
Retour Retour
</a> </a>

View File

@ -1,21 +1,43 @@
.several-times {
padding-left: 1em;
}
.date-interval {
padding: 1em;
margin-bottom: 1em;
}
.title {
font-size: 1.5rem;
}
:host { :host {
input, .several-times {
button { padding-left: 1em;
+ button { }
margin-left: 1em;
} .date-interval {
} padding: 1em;
margin-bottom: 1em;
}
.dates-list {
.btn--primary {
float: right;
}
}
.date-choice {
input {
width: 70%;
}
}
.title {
font-size: 1.5rem;
}
input,
button {
+ button {
margin-left: 1em;
}
}
.columns {
margin-top: 1em;
}
.identical-dates {
label {
width: 3ch;
}
}
} }

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DatesComponent } from './dates.component'; import { DatesComponent } from './dates.component';
describe('DatesComponent', () => { describe('DatesComponent', () => {
let component: DatesComponent; let component: DatesComponent;
let fixture: ComponentFixture<DatesComponent>; let fixture: ComponentFixture<DatesComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [DatesComponent], declarations: [DatesComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(DatesComponent); fixture = TestBed.createComponent(DatesComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -7,131 +7,131 @@ 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 = false;
startDateInterval: any; startDateInterval: any;
intervalDays: any; intervalDays: any;
intervalDaysDefault: number = 7; intervalDaysDefault = 7;
endDateInterval: any; endDateInterval: any;
constructor( constructor(
public config: ConfigService, public config: ConfigService,
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
private messageService: MessageService, private messageService: MessageService,
private dateUtilities: DateUtilities, private dateUtilities: DateUtilities,
@Inject(DOCUMENT) private document: any @Inject(DOCUMENT) private document: any
) { ) {
super(config); super(config);
} }
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);
} }
} }
/** /**
* set the interval options * set the interval options
*/ */
ngOnInit() { ngOnInit() {
let dateCurrent = new Date(); const 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 this.endDateInterval = this.dateUtilities
.addDaysToDate(this.intervalDaysDefault, dateCurrent) .addDaysToDate(this.intervalDaysDefault, dateCurrent)
.toISOString() .toISOString()
.substring(0, 10); .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) + '"]'; const selector = '[ng-reflect-name="dateChoices_' + (this.config.dateList.length - 1) + '"]';
this.cd.detectChanges(); this.cd.detectChanges();
const elem = this.document.querySelector(selector); const elem = this.document.querySelector(selector);
if (elem) { if (elem) {
elem.focus(); elem.focus();
} }
} }
/** /**
* 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() {
this.config.timeList = []; this.config.timeList = [];
} }
resetTimes() { resetTimes() {
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
* @param config * @param config
* @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) + '"]'; const 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);
if (elem) { if (elem) {
elem.focus(); elem.focus();
} }
} }
/** /**
* 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
*/ */
addIntervalOfDates() { addIntervalOfDates() {
let newIntervalArray = this.dateUtilities.getDatesInRange(this.startDateInterval, this.endDateInterval, 1); const 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
this.showDateInterval = false; this.showDateInterval = false;
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,56 +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 « Votre sondage «
<span class="poll-title"> <span class="poll-title">
{{ config.title }} {{ config.title }}
</span> </span>
» a bien été créé ! » a bien été créé !
</p> </p>
<p> <p>
Voici les liens daccès au sondage, conservez-les soigneusement ! (Si vous les perdez vous pourrez toujours les Voici les liens daccès au sondage, conservez-les soigneusement ! (Si vous les perdez vous pourrez toujours les
recevoir par email) recevoir par email)
</p> </p>
<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> <a href="{{ config.urlAdmin }}">{{ config.urlAdmin }} </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 Note : Le sondage sera supprimé {{ config.deletionDateAfterLastModification }} jours après la date de sa
dernière modification. dernière modification.
</p> </p>
</section> </section>
<section class="public"> <section class="public">
<h2 i18n>{{ 'resume.users' | translate }}</h2> <h2 i18n>{{ 'resume.users' | translate }}</h2>
<p> <p>
Pour accéder au sondage : Pour accéder au sondage :
<a href="{{ config.urlPublic }}">{{ config.urlPublic }} </a> <a href="{{ config.urlPublic }}">{{ config.urlPublic }} </a>
</p> </p>
<framadate-copy-text [textToCopy]="config.urlPublic"></framadate-copy-text> <framadate-copy-text [textToCopy]="config.urlPublic"></framadate-copy-text>
<a href="{{ config.urlPublic }}"> <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> <h2 i18n>{{ 'resume.links_mail' | translate }}</h2>
<p> <p>
Pour être sur de retrouver ces liens, nous pouvons vous les envoyer sur votre mail mail : Pour être sur de retrouver ces liens, nous pouvons vous les envoyer sur votre mail mail :
<input type="email" [(ngModel)]="mailToRecieve" paceholder="email" /> <input type="email" [(ngModel)]="mailToRecieve" paceholder="email" />
</p> </p>
<button class="btn btn--primary" (click)="sendToEmail()"> <button class="btn btn--primary" (click)="sendToEmail()">
<i class="fa fa-paper-plane"></i> <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

@ -1,5 +1,5 @@
:host { :host {
button { button {
margin-right: 1em; margin-right: 1em;
} }
} }

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EndConfirmationComponent } from './end-confirmation.component'; import { EndConfirmationComponent } from './end-confirmation.component';
describe('EndConfirmationComponent', () => { describe('EndConfirmationComponent', () => {
let component: EndConfirmationComponent; let component: EndConfirmationComponent;
let fixture: ComponentFixture<EndConfirmationComponent>; let fixture: ComponentFixture<EndConfirmationComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [EndConfirmationComponent], declarations: [EndConfirmationComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(EndConfirmationComponent); fixture = TestBed.createComponent(EndConfirmationComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -5,27 +5,27 @@ 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, public http: HttpClient, private messageService: MessageService) { constructor(public config: ConfigService, 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,92 +1,92 @@
<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 class="pre-selector" i18n> <span class="pre-selector" i18n>
{{ 'creation.want' | translate }} {{ 'creation.want' | translate }}
</span> </span>
<button (click)="config.resetConfig()" class="btn btn--warning"> <button (click)="config.resetConfig()" class="btn btn--warning">
Reset all Reset all
</button> </button>
<select [(ngModel)]="config.pollType" autofocus="autofocus" id="selector" name="polltype"> <select [(ngModel)]="config.pollType" autofocus="autofocus" id="selector" name="polltype">
<option value="dates" name="polltype_date"> <option value="dates" name="polltype_date">
{{ 'creation.kind.date' | translate }} {{ 'creation.kind.date' | translate }}
</option> </option>
<option value="classic" name="polltype_classic"> <option value="classic" name="polltype_classic">
{{ 'creation.kind.classic' | translate }} {{ 'creation.kind.classic' | translate }}
</option> </option>
</select> </select>
<span class="post-selector"> </span> <span class="post-selector"> </span>
<div> <div>
<label class="title-label" for="poll_title" i18n> <label class="title-label" for="poll_title" i18n>
{{ 'creation.choose_title' | translate }} {{ 'creation.choose_title' | translate }}
</label> </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"> {{ 'creation.name' | translate }} : </label> <label for="my_name"> {{ '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 class="title-label" for="poll_description" i18n> <label class="title-label" for="poll_description" i18n>
{{ 'creation.description' | translate }}: {{ 'creation.description' | translate }}:
<framadate-erasable-input [(inputModel)]="config.description"></framadate-erasable-input> <framadate-erasable-input [(inputModel)]="config.description"></framadate-erasable-input>
</label> </label>
<br /> <br />
<textarea <textarea
[(ngModel)]="config.description" [(ngModel)]="config.description"
cols="50" cols="50"
id="poll_description" id="poll_description"
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"
id="email" id="email"
name="mail" name="mail"
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 [routerLink]="'/step/answers'" class="btn btn--primary btn--full" *ngIf="config.pollType == 'classic'" i18n> <button [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 [routerLink]="'/step/date'" class="btn btn--primary btn--full" *ngIf="config.pollType == 'dates'" i18n> <button [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 [routerLink]="'/step/creation'" class="prev" i18n> <a [routerLink]="'/step/creation'" class="prev" i18n>
Retour Retour
</a> </a>
<hr /> <hr />
</div> </div>

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HomeComponent } from './home.component'; import { HomeComponent } from './home.component';
describe('HomeComponent', () => { describe('HomeComponent', () => {
let component: HomeComponent; let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>; let fixture: ComponentFixture<HomeComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [HomeComponent], declarations: [HomeComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent); fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -3,15 +3,15 @@ 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,265 +1,265 @@
<h1>page de démo</h1> <h1>page de démo</h1>
<p> <p>
cette étape est en cours de développement. <br /> cette étape est en cours de développement. <br />
S'inspirer de la page de Home pour réaliser d'autres pages S'inspirer de la page de Home pour réaliser d'autres pages
</p> </p>
<a [routerLink]="'/step/end'" class="btn btn--primary" i18n="@@confirm">C'est parfait!</a> <a [routerLink]="'/step/end'" class="btn btn--primary" 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 [routerLink]="'/home'" class="next"> <a [routerLink]="'/home'" class="next">
<span class="text" i18n> <span class="text" i18n>
C'est parti ! C'est parti !
</span> </span>
</a> </a>
</div> </div>
<div> <div>
<a [routerLink]="'/home'" class="prev"> <a [routerLink]="'/home'" class="prev">
<span class="text" i18n> <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 type="submit" class="btn btn--primary"> <button type="submit" class="btn btn--primary">
primary - default primary - default
</button> </button>
<br /> <br />
<button type="submit" class="btn btn--primary btn--small"> <button type="submit" class="btn btn--primary btn--small">
primary - small primary - small
</button> </button>
<br /> <br />
<a href="#" class="btn btn--primary btn--outline"> <a href="#" class="btn btn--primary btn--outline">
primary - outline - default primary - outline - default
</a> </a>
<br /> <br />
<button type="submit" class="btn btn--primary btn--outline btn--small"> <button type="submit" class="btn btn--primary btn--outline btn--small">
primary - outline - small primary - outline - small
</button> </button>
<br /> <br />
<input type="submit" class="btn btn--alert" value="alert - default" /> <input type="submit" class="btn btn--alert" value="alert - default" />
<br /> <br />
<button type="submit" class="btn btn--alert btn--small"> <button type="submit" class="btn btn--alert btn--small">
alert - small alert - small
</button> </button>
<br /> <br />
<button type="submit" class="btn btn--alert btn--outline"> <button type="submit" class="btn btn--alert btn--outline">
alert - outline - default alert - outline - default
</button> </button>
<br /> <br />
<button type="submit" class="btn btn--alert btn--outline btn--small"> <button type="submit" class="btn btn--alert btn--outline btn--small">
alert - outline - small alert - outline - small
</button> </button>
<br /><br /> <br /><br />
<button type="submit" class="btn btn--primary btn--full"> <button type="submit" class="btn btn--primary btn--full">
primary - full primary - full
</button> </button>
<button type="submit" class="btn btn--primary btn--outline btn--full"> <button type="submit" class="btn btn--primary btn--outline btn--full">
primary - outline - full primary - outline - full
</button> </button>
<button type="submit" class="btn btn--alert btn--full"> <button type="submit" class="btn btn--alert btn--full">
alert - full alert - full
</button> </button>
<button type="submit" class="btn btn--alert btn--outline btn--full"> <button type="submit" class="btn btn--alert btn--outline btn--full">
alert - outline - full alert - outline - full
</button> </button>
</article> </article>
<article> <article>
<h2>Forms element</h2> <h2>Forms element</h2>
<h3>Labels</h3> <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> <h3>Input name</h3>
<input type="name" name="" id="" /><br /> <input type="name" name="" id="" /><br />
<input type="name" name="" id="" value="texte" /> <input type="name" name="" id="" value="texte" />
<h3>Input email</h3> <h3>Input email</h3>
<input type="email" name="" id="" /><br /> <input type="email" name="" id="" /><br />
<input type="email" name="" id="" value="adresse@email.com" /> <input type="email" name="" id="" value="adresse@email.com" />
<h3>Input password</h3> <h3>Input password</h3>
<input type="password" name="" id="" /><br /> <input type="password" name="" id="" /><br />
<input type="password" name="" id="" value="password" /> <input type="password" name="" id="" value="password" />
<h3>Input date</h3> <h3>Input date</h3>
<input type="date" name="" id="" /><br /> <input type="date" name="" id="" /><br />
<input type="date" name="" id="" value="1985-11-23" /> <input type="date" name="" id="" value="1985-11-23" />
<h3>Select</h3> <h3>Select</h3>
<select name="" id=""> <select name="" id="">
<option value=""> <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 name="" id="" cols="30" rows="10"></textarea> <textarea name="" id="" cols="30" rows="10"></textarea>
</article> </article>
<article> <article>
<h2>Paragraphs</h2> <h2>Paragraphs</h2>
<p> <p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Magnam perspiciatis minus libero error dolores. 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! delectus beatae!
</p> </p>
</article> </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 src="http://placekitten.com/200/300" alt="" /> <img src="http://placekitten.com/200/300" alt="" />
</article> </article>
</section> </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 [routerLink]="'/home'" class="next"> <a [routerLink]="'/home'" class="next">
<span class="text" i18n> <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 type="name" name="test-text" id="test-text" /> <input type="name" name="test-text" id="test-text" />
</article> </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 name="test-select" id="test-select"> <select name="test-select" id="test-select">
<option value=""> <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

@ -1,22 +1,22 @@
@charset "UTF-8"; @charset "UTF-8";
section { section {
&:not(:last-of-type) { &:not(:last-of-type) {
border-bottom: 6px solid #000; border-bottom: 6px solid #000;
} }
+ section { + section {
margin: 0 !important; margin: 0 !important;
} }
} }
article { article {
padding: 2rem 0; padding: 2rem 0;
border-top: 3px solid #ffb92c; border-top: 3px solid #ffb92c;
h3 { h3 {
&:not(:first-of-type) { &:not(:first-of-type) {
margin-top: 2rem; margin-top: 2rem;
} }
} }
} }

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { KindComponent } from './kind.component'; import { KindComponent } from './kind.component';
describe('KindComponent', () => { describe('KindComponent', () => {
let component: KindComponent; let component: KindComponent;
let fixture: ComponentFixture<KindComponent>; let fixture: ComponentFixture<KindComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [KindComponent], declarations: [KindComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(KindComponent); fixture = TestBed.createComponent(KindComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -3,14 +3,14 @@ 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

@ -2,11 +2,11 @@
<p class="margin-btm-x6">Ce sondage est protégé par un mot de passe</p> <p class="margin-btm-x6">Ce sondage est protégé par un mot de passe</p>
<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

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PasswordComponent } from './password.component'; import { PasswordComponent } from './password.component';
describe('PasswordComponent', () => { describe('PasswordComponent', () => {
let component: PasswordComponent; let component: PasswordComponent;
let fixture: ComponentFixture<PasswordComponent>; let fixture: ComponentFixture<PasswordComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [PasswordComponent], declarations: [PasswordComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(PasswordComponent); fixture = TestBed.createComponent(PasswordComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -3,14 +3,14 @@ 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

@ -1,5 +1,5 @@
<!--ceci est la popup pour ajouter une image--> <!--ceci est la popup pour ajouter une image-->
<h1 i18n> <h1 i18n>
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

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PicturesComponent } from './pictures.component'; import { PicturesComponent } from './pictures.component';
describe('PicturesComponent', () => { describe('PicturesComponent', () => {
let component: PicturesComponent; let component: PicturesComponent;
let fixture: ComponentFixture<PicturesComponent>; let fixture: ComponentFixture<PicturesComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [PicturesComponent], declarations: [PicturesComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(PicturesComponent); fixture = TestBed.createComponent(PicturesComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

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

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PollDisplayComponent } from './poll-display.component'; import { PollDisplayComponent } from './poll-display.component';
describe('PollDisplayComponent', () => { describe('PollDisplayComponent', () => {
let component: PollDisplayComponent; let component: PollDisplayComponent;
let fixture: ComponentFixture<PollDisplayComponent>; let fixture: ComponentFixture<PollDisplayComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [PollDisplayComponent], declarations: [PollDisplayComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(PollDisplayComponent); fixture = TestBed.createComponent(PollDisplayComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -7,64 +7,64 @@ 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, private router: Router, public activeRoute: ActivatedRoute) { constructor(public config: ConfigService, 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');
if (!this.config.loading) { if (!this.config.loading) {
this.fetchPoll(); this.fetchPoll();
} }
}); });
} }
ngOnInit() {} ngOnInit() {}
// fetch poll with its ID or slug. // fetch poll with its ID or slug.
fetchPoll() { fetchPoll() {
const id = this.activeRoute.snapshot.params.poll; const id = this.activeRoute.snapshot.params.poll;
const pollSlug = this.activeRoute.snapshot.params.pollSlug; const pollSlug = this.activeRoute.snapshot.params.pollSlug;
if (!environment.production) { if (!environment.production) {
console.log('mockPoll3', mockPoll3); console.log('mockPoll3', mockPoll3);
this.config.currentPoll = mockPoll3; this.config.currentPoll = mockPoll3;
return; return;
} }
if (id) { if (id) {
this.config.loading = true; this.config.loading = true;
// store it in the poll property here // store it in the poll property here
this.config.getPollById(id).subscribe( this.config.getPollById(id).subscribe(
(res: any) => { (res: any) => {
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) {
this.config.loading = true; this.config.loading = true;
this.config.getPollByURL(pollSlug).subscribe( this.config.getPollByURL(pollSlug).subscribe(
(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,71 +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 class="preview type-classic" *ngIf="config.pollType == 'classic'"> <section class="preview type-classic" *ngIf="config.pollType == 'classic'">
<ul> <ul>
<li markdown *ngFor="let questions of config.answers"> <li markdown *ngFor="let questions of config.answers">
<img class="img-thumbnail" src="{{ questions.url }}" alt="image {{ questions.url }}" /> <img class="img-thumbnail" src="{{ questions.url }}" alt="image {{ questions.url }}" />
{{ questions.id + 1 }}. {{ questions.text }} {{ questions.id + 1 }}. {{ questions.text }}
</li> </li>
</ul> </ul>
</section> </section>
<section class="type-date" *ngIf="config.pollType !== 'classic'"> <section class="type-date" *ngIf="config.pollType !== 'classic'">
<i class="fa fa-clock-o"></i> <i class="fa fa-clock-o"></i>
<span class="well" *ngIf="'true' === config.allowSeveralHours"> <span class="well" *ngIf="'true' === config.allowSeveralHours">
{{ 'dates.multiple.different' | translate }} {{ 'dates.multiple.different' | translate }}
</span> </span>
<span class="well" *ngIf="'false' === config.allowSeveralHours"> <span class="well" *ngIf="'false' === config.allowSeveralHours">
{{ 'dates.multiple.identical' | translate }} {{ 'dates.multiple.identical' | translate }}
</span> </span>
<div *ngFor="let choice of config.dateList; index as id" class="date-choice"> <div *ngFor="let choice of config.dateList; index as id" class="date-choice">
<div class="only-one-slice" *ngIf="!choice.timeList.length"> <div class="only-one-slice" *ngIf="!choice.timeList.length">
<i class="fa fa-square-o"></i> <i class="fa fa-square-o"></i>
</div> </div>
{{ choice.literal }} {{ choice.literal }}
<!-- CASE different slices of the day--> <!-- CASE different slices of the day-->
<div *ngIf="'true' === config.allowSeveralHours" class="several-times"> <div *ngIf="'true' === config.allowSeveralHours" class="several-times">
<div *ngFor="let time of choice.timeList; index as idTime" class="time-choice"> <div *ngFor="let time of choice.timeList; index as idTime" class="time-choice">
{{ idTime }}) {{ idTime }})
<i class="fa fa-square-o"></i> <i class="fa fa-square-o"></i>
{{ time.literal }} {{ time.literal }}
</div> </div>
</div> </div>
<!-- CASE all dates having the same slices of the day--> <!-- CASE all dates having the same slices of the day-->
<div *ngIf="'false' === config.allowSeveralHours" class="same-times"> <div *ngIf="'false' === config.allowSeveralHours" class="same-times">
<div *ngFor="let time of config.timeList" class="time-choice"> <div *ngFor="let time of config.timeList" class="time-choice">
<i class="fa fa-square-o"></i> <i class="fa fa-square-o"></i>
{{ time.literal }} {{ time.literal }}
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</div> </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 *ngIf="config.pollType == 'classic'" [routerLink]="'/step/answers'" class="prev"> <a *ngIf="config.pollType == 'classic'" [routerLink]="'/step/answers'" class="prev">
Retour Retour
</a> </a>
<a *ngIf="config.pollType == 'dates'" [routerLink]="'/step/date'" class="prev"> <a *ngIf="config.pollType == 'dates'" [routerLink]="'/step/date'" class="prev">
Retour Retour
</a> </a>
</div> </div>

View File

@ -1,9 +1,9 @@
.card { .card {
box-shadow: 0px 0px 0.5em #ccc; box-shadow: 0px 0px 0.5em #ccc;
padding: 2em; padding: 2em;
margin: 1em 0; margin: 1em 0;
} }
.time-choice { .time-choice {
margin-left: 3em; margin-left: 3em;
} }

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ResumeComponent } from './resume.component'; import { ResumeComponent } from './resume.component';
describe('ResumeComponent', () => { describe('ResumeComponent', () => {
let component: ResumeComponent; let component: ResumeComponent;
let fixture: ComponentFixture<ResumeComponent>; let fixture: ComponentFixture<ResumeComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ResumeComponent], declarations: [ResumeComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(ResumeComponent); fixture = TestBed.createComponent(ResumeComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

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

@ -1,5 +1,5 @@
:host { :host {
h2 { h2 {
margin-top: 1em; margin-top: 1em;
} }
} }

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { VisibilityComponent } from './visibility.component'; import { VisibilityComponent } from './visibility.component';
describe('VisibilityComponent', () => { describe('VisibilityComponent', () => {
let component: VisibilityComponent; let component: VisibilityComponent;
let fixture: ComponentFixture<VisibilityComponent>; let fixture: ComponentFixture<VisibilityComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [VisibilityComponent], declarations: [VisibilityComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(VisibilityComponent); fixture = TestBed.createComponent(VisibilityComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -5,28 +5,28 @@ 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, public utils: PollUtilities) { constructor(public config: ConfigService, 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 this.config.expirationDate = this.config
.addDaysToDate(this.config.expiracyDateDefaultInDays, new Date()) .addDaysToDate(this.config.expiracyDateDefaultInDays, new Date())
.toISOString() .toISOString()
.substring(0, 10); .substring(0, 10);
} }
submitCreationAndGoToEnd() { submitCreationAndGoToEnd() {
this.config.createPoll(); this.config.createPoll();
} }
} }

View File

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

View File

@ -1,5 +0,0 @@
.submit-votestack {
position: fixed;
bottom: 5px;
right: 5px;
}

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChoicesListComponent } from './choices-list.component'; import { ChoicesListComponent } from './choices-list.component';
describe('ChoicesListComponent', () => { describe('ChoicesListComponent', () => {
let component: ChoicesListComponent; let component: ChoicesListComponent;
let fixture: ComponentFixture<ChoicesListComponent>; let fixture: ComponentFixture<ChoicesListComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ChoicesListComponent], declarations: [ChoicesListComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(ChoicesListComponent); fixture = TestBed.createComponent(ChoicesListComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -2,10 +2,10 @@ 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,34 +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="name" [(ngModel)]="config.myName" />
<input type="text" name="name" id="email" [(ngModel)]="config.myEmail" /> <input type="text" name="name" id="email" [(ngModel)]="config.myEmail" />
<i class="fa fa-envelope"></i> <i class="fa fa-envelope"></i>
</section> </section>
<div class="comments" id="comments"> <div class="comments" id="comments">
<h2 class="margin-top-x7">Laisser un commentaire</h2> <h2 class="margin-top-x7">Laisser un commentaire</h2>
<label for="crname">Votre nom :</label> <label for="crname">Votre nom :</label>
<input type="text" class="margin-btm-x3" name="crname" [(ngModel)]="config.myName" id="crname" /> <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" /> <input type="text" name="cremail" id="email_comment" [(ngModel)]="config.myEmail" />
<label for="email_comment"> <label for="email_comment">
<i class="fa fa-envelope"></i> <i class="fa fa-envelope"></i>
</label> </label>
<div> <div>
<label for="comment">Votre commentaire :</label> <label for="comment">Votre commentaire :</label>
<br /> <br />
<textarea name="comment" id="comment" [(ngModel)]="config.myComment"> </textarea> <textarea name="comment" id="comment" [(ngModel)]="config.myComment"> </textarea>
</div> </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" *ngIf="config.currentPoll"> <div class="comments-part" *ngIf="config.currentPoll">
<framadate-voting-comment [comment]="c" *ngFor="let c of config.currentPoll.comments"> <framadate-voting-comment [comment]="c" *ngFor="let c of config.currentPoll.comments">
</framadate-voting-comment> </framadate-voting-comment>
</div> </div>
</div> </div>

View File

@ -9,33 +9,33 @@ 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 = jest.fn({ navigateByUrl: jest.fn() });
describe('CommentsListComponent', () => { describe('CommentsListComponent', () => {
let component: CommentsListComponent; let component: CommentsListComponent;
let fixture: ComponentFixture<CommentsListComponent>; let fixture: ComponentFixture<CommentsListComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule], imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule],
declarations: [CommentsListComponent], declarations: [CommentsListComponent],
providers: [ providers: [
HttpClient, HttpClient,
MessageService, MessageService,
ConfirmationService, ConfirmationService,
ConfigService, ConfigService,
{ provide: Router, useValue: routerSpy }, { provide: Router, useValue: routerSpy },
], ],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(CommentsListComponent); fixture = TestBed.createComponent(CommentsListComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -2,10 +2,10 @@ 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,142 +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 manage"
(click)="choice.simpleAnswer = !choice.simpleAnswer" (click)="choice.simpleAnswer = !choice.simpleAnswer"
> >
<i class="fa fa-gears"></i> <i class="fa fa-gears"></i>
</button> </button>
<div class="choicebox__subject"> <div class="choicebox__subject">
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
<div class="text title clickable" (click)="setAnswserTo('yes')"> <div class="text title clickable" (click)="setAnswserTo('yes')">
{{ choice.text }} {{ choice.text }}
</div> </div>
<!-- TEXT CASE --><!-- <!-- 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 *ngIf="choice.url" class="choicebox__img" [src]="choice.url" alt="{{ choice.url }}" /> <img *ngIf="choice.url" class="choicebox__img" [src]="choice.url" alt="{{ choice.url }}" />
<!-- IMG CASE --> <!-- IMG CASE -->
<!-- DATE CASE --> <!-- DATE CASE -->
<div class="dates" *ngIf="pollIsSpecialDate"> <div class="dates" *ngIf="pollIsSpecialDate">
<div class="choicebox__date"> <div class="choicebox__date">
{{ choice.date.date | date: 'EEE' }} {{ choice.date.date | date: 'EEE' }}
<span class="choicebox__day">{{ choice.date.date | date: 'dd' }}</span> <span class="choicebox__day">{{ choice.date.date | date: 'dd' }}</span>
{{ choice.date.date | date: 'LLL' }} {{ 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" alt="" /> <img src="../../../assets/img/check.svg" 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" alt="" /> <img src="../../../assets/img/check-2.svg" 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 src="../../../assets/img/croix.svg" alt="" /> <img src="../../../assets/img/croix.svg" alt="" />
</button> </button>
</span> </span>
</div> </div>
</div> </div>
<div class="column"> <div class="column">
<div class="choicebox__count"> <div class="choicebox__count">
<div class="no-votes" *ngIf="!poll.choices_count.counts[choice.id]"> <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"> <div class="choicebox__vote">
{{ poll.choices_count.counts[choice.id].yes.count }} {{ poll.choices_count.counts[choice.id].yes.count }}
<img width="20px" height="21px" src="../../../assets/img/votant-sur.svg" alt="" /> <img width="20px" height="21px" src="../../../assets/img/votant-sur.svg" alt="" />
</div> </div>
<div class="choicebox__vote"> <div class="choicebox__vote">
{{ poll.choices_count.counts[choice.id].maybe.count }} {{ poll.choices_count.counts[choice.id].maybe.count }}
<img width="22px" height="24px" src="../../../assets/img/votant-pas-sur.svg" alt="" /> <img width="22px" height="24px" src="../../../assets/img/votant-pas-sur.svg" alt="" />
</div> </div>
<div class="choicebox__tooltip" id="choicebox-tooltip"> <div class="choicebox__tooltip" id="choicebox-tooltip">
<div class="choicebox__tooltiplist"> <div class="choicebox__tooltiplist">
<div class="choicebox__tooltipttl"> <div class="choicebox__tooltipttl">
<img width="20px" height="21px" src="../../../assets/img/votant-sur.svg" alt="" /> <img width="20px" height="21px" src="../../../assets/img/votant-sur.svg" alt="" />
{{ poll.choices_count.counts[choice.id].yes.count }} "Oui" {{ poll.choices_count.counts[choice.id].yes.count }} "Oui"
</div> </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"> <li *ngFor="let pseudo of choices_count.counts[choice.id].yes.people">
{{ pseudo }} {{ pseudo }}
</li> </li>
</ul> </ul>
</div> </div>
<div class="choicebox__tooltiplist" *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" {{ poll.choices_count.counts[choice.id].maybe.count }} "Peut-être"
</div> </div>
<ul> <ul>
<li *ngFor="let pseudo of choices_count.counts[choice.id].maybe.people"> <li *ngFor="let pseudo of choices_count.counts[choice.id].maybe.people">
{{ pseudo }} {{ pseudo }}
</li> </li>
</ul> </ul>
</div> </div>
<div class="choicebox__tooltiplist" *ngIf="!simpleAnswer"> <div class="choicebox__tooltiplist" *ngIf="!simpleAnswer">
<div class="choicebox__tooltipttl"> <div class="choicebox__tooltipttl">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
{{ poll.choices_count.counts[choice.id].no.count }} "Non" {{ poll.choices_count.counts[choice.id].no.count }} "Non"
</div> </div>
<ul> <ul>
<li *ngFor="let pseudo of choices_count.counts[choice.id].no.people"> <li *ngFor="let pseudo of choices_count.counts[choice.id].no.people">
{{ pseudo }} {{ pseudo }}
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
</button> </button>
<div class="choicebox__countxt"> <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

@ -23,240 +23,239 @@ $breakpoint-responsive: 640px; // à définir
// ---------------------------- // ----------------------------
.choicebox { .choicebox {
position: relative; position: relative;
min-width: 32rem; min-height: 10rem;
min-height: 16rem; display: block;
display: block; 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 0.6rem 0 rgba($black, 0.2);
box-shadow: 0 0 0.6rem 0 rgba($black, 0.2);
&--active { &--active {
padding-left: $box-padding; padding-left: $box-padding;
border-left-color: $primary_color; border-left-color: $primary_color;
} }
&.selection-yes { &.selection-yes {
font-weight: 700; font-weight: 700;
background: #e9bdeb; background: #e9bdeb;
} }
} }
.choicebox__subject { .choicebox__subject {
margin-bottom: 3rem; margin-bottom: 3rem;
padding-right: $btn-wrap-size; padding-right: $btn-wrap-size;
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
margin-bottom: 0; margin-bottom: 0;
padding-right: 0; padding-right: 0;
} }
} }
// -- DATE // -- DATE
// ---------------------------- // ----------------------------
.choicebox__date { .choicebox__date {
font-size: 1.8rem; font-size: 1.8rem;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
white-space: nowrap; white-space: nowrap;
text-transform: capitalize; text-transform: capitalize;
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
margin-bottom: 0; margin-bottom: 0;
} }
} }
.choicebox__day { .choicebox__day {
font-size: 2.4rem; font-size: 2.4rem;
font-weight: bold; font-weight: bold;
} }
// -- IMG // -- IMG
// ---------------------------- // ----------------------------
.choicebox__img { .choicebox__img {
max-width: 100%; max-width: 100%;
max-height: $img-maxheight; max-height: $img-maxheight;
} }
// -- TXT // -- TXT
// ---------------------------- // ----------------------------
.choicebox__txt { .choicebox__txt {
margin: 0; margin: 0;
font-size: 1.8rem; font-size: 1.8rem;
min-width: 10em; min-width: 10em;
} }
// -- VOTE BTNS // -- VOTE BTNS
// ---------------------------- // ----------------------------
.choicebox__actions { .choicebox__actions {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
max-width: $btn-wrap-size; max-width: $btn-wrap-size;
top: 50%; top: 50%;
right: $box-padding; right: $box-padding;
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
position: static; position: static;
max-width: none; max-width: none;
transform: none; transform: none;
margin: 0 1.5rem; margin: 0 1.5rem;
} }
} }
.choicebox__btn { .choicebox__btn {
width: $btn-size; width: $btn-size;
height: $btn-size; height: $btn-size;
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: 0.3rem solid #ccc9c9; border: 0.3rem solid #ccc9c9;
background-color: transparent; background-color: transparent;
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
float: left; float: left;
&--maybe { &--maybe {
position: relative; position: relative;
top: calc((#{$btn-size} + 2 * #{$btn-margin-y}) / 2); top: calc((#{$btn-size} + 2 * #{$btn-margin-y}) / 2);
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
top: auto; top: auto;
left: auto; left: auto;
} }
} }
&:focus, &:focus,
&:active { &: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
// ---------------------------- // ----------------------------
.choicebox__count { .choicebox__count {
position: relative; position: relative;
padding-right: $btn-wrap-size; padding-right: $btn-wrap-size;
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
text-align: right; text-align: right;
padding-right: 0; padding-right: 0;
} }
} }
.choicebox__votes { .choicebox__votes {
border: 0; border: 0;
padding: 0; padding: 0;
line-height: normal; line-height: normal;
background-color: transparent; background-color: transparent;
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
padding: 1.5rem; padding: 1.5rem;
} }
} }
.choicebox__vote { .choicebox__vote {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
& + .choicebox__vote { & + .choicebox__vote {
margin-left: 1.5rem; margin-left: 1.5rem;
} }
} }
.choicebox__countxt { .choicebox__countxt {
display: none; display: none;
margin-top: 0.5rem; margin-top: 0.5rem;
.choicebox--active & { .choicebox--active & {
display: block; display: block;
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
display: none; display: none;
} }
} }
} }
// -- TOOLTIP // -- TOOLTIP
// ---------------------------- // ----------------------------
.choicebox__tooltip { .choicebox__tooltip {
display: none; display: none;
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
position: absolute; position: absolute;
min-width: 18rem; min-width: 18rem;
font-weight: normal; font-weight: normal;
top: 5rem; top: 5rem;
left: 50%; left: 50%;
z-index: 1; z-index: 1;
padding: 2rem; padding: 2rem;
border: 0.1rem solid rgba($black, 0.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%);
&::after, &::after,
&::before { &::before {
position: absolute; position: absolute;
width: 0; width: 0;
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;
} }
&::after { &::after {
margin-left: -1.5rem; margin-left: -1.5rem;
border-width: 1.5rem; border-width: 1.5rem;
border-color: rgba($white, 0); border-color: rgba($white, 0);
border-bottom-color: #fff; border-bottom-color: #fff;
} }
&::before { &::before {
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, 0.1); border-bottom-color: rgba($black, 0.1);
} }
ul { ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
} }
} }
} }
.choicebox__tooltiplist { .choicebox__tooltiplist {
& + .choicebox__tooltiplist { & + .choicebox__tooltiplist {
padding-left: 3rem; padding-left: 3rem;
} }
ul { ul {
max-height: 11rem; max-height: 11rem;
overflow: auto; overflow: auto;
} }
} }
.choicebox__tooltipttl { .choicebox__tooltipttl {
@media (min-width: $breakpoint-responsive) { @media (min-width: $breakpoint-responsive) {
margin-bottom: 1rem; margin-bottom: 1rem;
font-size: 1.6rem; font-size: 1.6rem;
font-weight: bold; font-weight: bold;
white-space: nowrap; white-space: nowrap;
img { img {
margin-right: 0.5rem; margin-right: 0.5rem;
vertical-align: sub; vertical-align: sub;
} }
& ~ .choicebox__tooltipttl { & ~ .choicebox__tooltipttl {
margin-top: 3rem; margin-top: 3rem;
} }
} }
} }

View File

@ -10,72 +10,72 @@ 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 = jest.fn({ navigateByUrl: jest.fn() });
describe('VotingChoiceComponent', () => { describe('VotingChoiceComponent', () => {
let component: VotingChoiceComponent; let component: VotingChoiceComponent;
let fixture: ComponentFixture<VotingChoiceComponent>; let fixture: ComponentFixture<VotingChoiceComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule], imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule],
declarations: [VotingChoiceComponent], declarations: [VotingChoiceComponent],
providers: [ providers: [
HttpClient, 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;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
it('should have nothing specified as an answer by default', () => { it('should have nothing specified as an answer by default', () => {
expect(component.choice.answer).toBeFalsy(); expect(component.choice.answer).toBeFalsy();
}); });
it('should set answer to yes', () => { it('should set answer to yes', () => {
component.setAnswserTo('yes'); component.setAnswserTo('yes');
expect(component.choice.answer).toBe('yes'); expect(component.choice.answer).toBe('yes');
}); });
it('should set answer to maybe', () => { it('should set answer to maybe', () => {
component.setAnswserTo('maybe'); component.setAnswserTo('maybe');
expect(component.choice.answer).toBe('maybe'); expect(component.choice.answer).toBe('maybe');
}); });
it('should set answer to no', () => { it('should set answer to no', () => {
component.setAnswserTo('no'); component.setAnswserTo('no');
expect(component.choice.answer).toBe('no'); expect(component.choice.answer).toBe('no');
}); });
it('should set answer to no after 2 set on yes', () => { it('should set answer to no after 2 set on yes', () => {
component.setAnswserTo('yes'); component.setAnswserTo('yes');
component.setAnswserTo('yes'); component.setAnswserTo('yes');
expect(component.choice.answer).toBe('no'); expect(component.choice.answer).toBe('no');
}); });
it('should stay on maybe after 2 set on maybe', () => { it('should stay on maybe after 2 set on maybe', () => {
component.setAnswserTo('maybe'); component.setAnswserTo('maybe');
component.setAnswserTo('maybe'); component.setAnswserTo('maybe');
expect(component.choice.answer).toBe('maybe'); expect(component.choice.answer).toBe('maybe');
}); });
it('should stay on no after 2 set on no', () => { it('should stay on no after 2 set on no', () => {
component.setAnswserTo('no'); component.setAnswserTo('no');
component.setAnswserTo('no'); component.setAnswserTo('no');
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

@ -2,17 +2,17 @@ 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"
} }
/** /**
@ -20,45 +20,45 @@ interface VoteChoice {
* this component is used to select a date choice, or a name answer * this component is used to select a date choice, or a name answer
*/ */
@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;
@Input() public choice_id: any; @Input() public choice_id: any;
@Input() public poll: any; @Input() public poll: any;
@Input() public simpleAnswer: boolean = true; @Input() public simpleAnswer = true;
@Input() public pollIsSpecialDate: boolean = false; @Input() public pollIsSpecialDate = false;
constructor(private el: ElementRef, private config: ConfigService) { constructor(private el: ElementRef, 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;
} }
} }
setAnswserTo(newAnswer: 'yes' | 'no' | 'maybe' | null) { setAnswserTo(newAnswer: 'yes' | 'no' | 'maybe' | null) {
if (this.simpleAnswer) { if (this.simpleAnswer) {
// only toggle yes to no // only toggle yes to no
if (this.choice.answer && this.choice.answer === 'yes') { if (this.choice.answer && this.choice.answer === 'yes') {
this.choice.answer = 'no'; this.choice.answer = 'no';
this.config.myTempVoteStack--; this.config.myTempVoteStack--;
} else { } else {
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) {
if (newAnswer == 'maybe' || newAnswer == 'yes') { if (newAnswer == 'maybe' || newAnswer == 'yes') {
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,11 +1,11 @@
<div class="comment"> <div class="comment">
<span class="cname"> {{ comment.pseudo }} </span>, le <span class="cname"> {{ comment.pseudo }} </span>, le
<span class="date padding-btm-x1"> <span class="date padding-btm-x1">
{{ comment.date.date }} {{ comment.date.date }}
</span> </span>
<blockquote> <blockquote>
<p class="text"> <p class="text">
{{ comment.text }} {{ comment.text }}
</p> </p>
</blockquote> </blockquote>
</div> </div>

View File

@ -3,22 +3,22 @@ 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;
let fixture: ComponentFixture<VotingCommentComponent>; let fixture: ComponentFixture<VotingCommentComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [VotingCommentComponent], declarations: [VotingCommentComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(VotingCommentComponent); fixture = TestBed.createComponent(VotingCommentComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -2,14 +2,14 @@ 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

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { VotingGraphComponent } from './voting-graph.component'; import { VotingGraphComponent } from './voting-graph.component';
describe('VotingGraphComponent', () => { describe('VotingGraphComponent', () => {
let component: VotingGraphComponent; let component: VotingGraphComponent;
let fixture: ComponentFixture<VotingGraphComponent>; let fixture: ComponentFixture<VotingGraphComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [VotingGraphComponent], declarations: [VotingGraphComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(VotingGraphComponent); fixture = TestBed.createComponent(VotingGraphComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -3,14 +3,14 @@ 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,31 +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 *ngIf="config.currentPoll && config.currentPoll.comments" class="comments-count"> <span *ngIf="config.currentPoll && config.currentPoll.comments" class="comments-count">
{{ config.currentPoll.comments.length }} {{ config.currentPoll.comments.length }}
</span> </span>
commentaires commentaires
</a> </a>
</li> </li>
</ul> </ul>
</nav> </nav>
</nav> </nav>

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { VotingNavigationComponent } from './voting-navigation.component'; import { VotingNavigationComponent } from './voting-navigation.component';
describe('VotingNavigationComponent', () => { describe('VotingNavigationComponent', () => {
let component: VotingNavigationComponent; let component: VotingNavigationComponent;
let fixture: ComponentFixture<VotingNavigationComponent>; let fixture: ComponentFixture<VotingNavigationComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [VotingNavigationComponent], declarations: [VotingNavigationComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(VotingNavigationComponent); fixture = TestBed.createComponent(VotingNavigationComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -2,10 +2,10 @@ 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,152 +1,155 @@
<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"> Créé le {{ config.currentPoll.poll.creationDate.date }} </span> <span class="creationDate"> Créé le {{ config.currentPoll.poll.creationDate.date }} </span>
<span class="expiracyDate"> Expire le {{ config.currentPoll.poll.expiracyDate.date }} </span> <span class="expiracyDate"> Expire le {{ config.currentPoll.poll.expiracyDate.date }} </span>
<div class="votants"> <div class="votants">
<i class="fa fa-users"></i> <i class="fa fa-users"></i>
{{ config.currentPoll.stacks.length }} votants, {{ config.currentPoll.choices.length }} choix, {{ config.currentPoll.stacks.length }} votants, {{ config.currentPoll.choices.length }} choix,
</div> </div>
</div> </div>
</div> </div>
<div class="preferred"> <div class="preferred">
<i class="fa fa-star"></i> <i class="fa fa-star"></i>
Pour l'instant, Pour l'instant,
<span *ngIf="severalPreferred"> <span *ngIf="severalPreferred">
les les
</span> </span>
<span *ngIf="!severalPreferred"> <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>
<span *ngIf="!severalPreferred"> <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"> <div class="table-container">
<thead> <table class="table is-striped is-bordered is-hoverable">
<tr *ngIf="config.currentPoll.choices && config.currentPoll.choices_count"> <thead>
<td> <tr *ngIf="config.currentPoll.choices && config.currentPoll.choices_count">
Pseudo <td>
</td> Pseudo
<td *ngFor="let choice of config.currentPoll.choices"> </td>
{{ choice.text }} <td *ngFor="let choice of config.currentPoll.choices">
</td> {{ choice.text }}
</tr> </td>
<!-- somme des points, dont un demi point pour les "peut être" --> </tr>
</thead> <!-- somme des points, dont un demi point pour les "peut être" -->
<tbody> </thead>
<tr title='somme des points, dont un demi point pour les "peut être"'> <tbody>
<td><i class="fa fa-plus-circle"></i> points</td> <tr title='somme des points, dont un demi point pour les "peut être"'>
<!-- <td--> <td><i class="fa fa-plus-circle"></i> points</td>
<!-- *ngFor='let choice of config.currentPoll.choices'--> <!-- <td-->
<!-- [ngClass]='{"has-max-score" : config.currentPoll.choices_count.maxScore === config.currentPoll.choices_count.counts[choice.id].score}' >--> <!-- *ngFor='let choice of config.currentPoll.choices'-->
<!-- {{config.currentPoll.choices[choice.id].score}}--> <!-- [ngClass]='{"has-max-score" : config.currentPoll.choices_count.maxScore === config.currentPoll.choices_count.counts[choice.id].score}' >-->
<!-- </td >--> <!-- {{config.currentPoll.choices[choice.id].score}}-->
<td *ngFor="let choice of config.currentPoll.choices"> <!-- </td >-->
{{ pollconfig.choices_count.counts[this.pollconfig.choices[2].id].score }} <td *ngFor="let choice of config.currentPoll.choices">
</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 }}
<!-- yes {{config.currentPoll.choices_count.counts[choice.id].yes.count}}--> <br />
<!-- <br >--> <!-- yes {{config.currentPoll.choices_count.counts[choice.id].yes.count}}-->
<!-- maybe--> <!-- <br >-->
<!-- {{(config.currentPoll.choices_count.counts[k].yes.maybe ? config.currentPoll.choices_count.counts[k].yes.count * 0.5 : 0)}}--> <!-- maybe-->
<!-- {{(config.currentPoll.choices_count.counts[k].yes.maybe ? config.currentPoll.choices_count.counts[k].yes.count * 0.5 : 0)}}-->
<!-- <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 class="votes-of-the-person" *ngFor="let voteStack of config.currentPoll.stacks">
<td> <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">
<img
*ngIf="voteStack.votes[v].value == 'yes'"
src="../../../../assets/img/votant-sur.svg"
alt="yes"
/>
<img
*ngIf="voteStack.votes[v].value == 'maybe'"
src="../../../../assets/img/votant-pas-sur.svg"
alt="yes"
/>
</span>
</td>
</tr>
<!-- bottom line shows each answer details-->
</tbody>
</table>
</div>
{{ voteStack.pseudo }}
</td>
<td *ngFor="let v of getKeys(voteStack.votes)">
<span *ngIf="voteStack.votes[v].value">
<img
*ngIf="voteStack.votes[v].value == 'yes'"
src="../../../../assets/img/votant-sur.svg"
alt="yes"
/>
<img
*ngIf="voteStack.votes[v].value == 'maybe'"
src="../../../../assets/img/votant-pas-sur.svg"
alt="yes"
/>
</span>
</td>
</tr>
<!-- bottom line shows each answer details-->
</tbody>
</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"
[baseZIndex]="10000" [baseZIndex]="10000"
[draggable]="false" [draggable]="false"
[resizable]="false" [resizable]="false"
[showHeader]="false" [showHeader]="false"
[transitionOptions]="'200ms'" [transitionOptions]="'200ms'"
> >
<div style="max-width: 30em; padding: 2em 1em;"> <div style="max-width: 30em; padding: 2em 1em;">
<h4 class="title"> <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 l'édition de votre vote Votre vote a bien été pris en compte, mais faites attention, ce sondage n'autorise l'édition de votre vote
qu'avec le lien personnalisé suivant : qu'avec le lien personnalisé suivant :
</p> </p>
<br /> <br />
<a href="{{ config.urlAdmin }}" class="text-ellipsis">{{ config.urlAdmin }}</a> <a href="{{ config.urlAdmin }}" class="text-ellipsis">{{ config.urlAdmin }}</a>
<framadate-copy-text [textToCopy]="config.urlAdmin"></framadate-copy-text> <framadate-copy-text [textToCopy]="config.urlAdmin"></framadate-copy-text>
<br /> <br />
<p class="margin-btm-x6 margin-top-x2">Conservez-le précieusement !</p> <p class="margin-btm-x6 margin-top-x2">Conservez-le précieusement !</p>
<br /> <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,26 +1,26 @@
@import '../../../../assets/scss/variables'; @import '../../../../assets/scss/variables';
.person { .person {
font-weight: 700; font-weight: 700;
} }
.preferred-result { .preferred-result {
font-weight: 700; font-weight: 700;
font-size: 1.5em; font-size: 1.5em;
} }
thead { thead {
font-size: 1.25em; font-size: 1.25em;
font-weight: 700; font-weight: 700;
} }
tbody { tbody {
text-align: right; text-align: right;
} }
td { td {
&.has-max-score { &.has-max-score {
background: $primary_color; background: $primary_color;
font-weight: 800; font-weight: 800;
} }
} }

View File

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { VotingSummaryComponent } from './voting-summary.component'; import { VotingSummaryComponent } from './voting-summary.component';
describe('VotingSummaryComponent', () => { describe('VotingSummaryComponent', () => {
let component: VotingSummaryComponent; let component: VotingSummaryComponent;
let fixture: ComponentFixture<VotingSummaryComponent>; let fixture: ComponentFixture<VotingSummaryComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [VotingSummaryComponent], declarations: [VotingSummaryComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(VotingSummaryComponent); fixture = TestBed.createComponent(VotingSummaryComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -3,48 +3,48 @@ 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 = 'rien';
severalPreferred: boolean = false; severalPreferred = 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);
} }
/** /**
* find the most "yes" * find the most "yes"
*/ */
computePreferred() { computePreferred() {
let keys = Object.keys(this.pollconfig.choices_count.counts); const keys = Object.keys(this.pollconfig.choices_count.counts);
this.preferred = ''; this.preferred = '';
this.severalPreferred = false; this.severalPreferred = false;
let maxScore = this.pollconfig.choices_count.maxScore; const 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,10 +1,10 @@
<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>
<p class="comment"> <p class="comment">
<span class="cname">Pikachu </span> <span class="cname">Pikachu </span>
<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

@ -3,22 +3,22 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { VotingComponent } from './voting.component'; import { VotingComponent } from './voting.component';
describe('VotingComponent', () => { describe('VotingComponent', () => {
let component: VotingComponent; let component: VotingComponent;
let fixture: ComponentFixture<VotingComponent>; let fixture: ComponentFixture<VotingComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [VotingComponent], declarations: [VotingComponent],
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(VotingComponent); fixture = TestBed.createComponent(VotingComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -1,13 +1,13 @@
import { Component, OnInit } from '@angular/core'; 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() {}
} }

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