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:
- test
- e2e
# - e2e
cache:
paths:
@ -13,17 +13,17 @@ test:
script:
- npm i
- pkill Xvfb
- npm run test
- npm run test:ci
artifacts:
paths:
- coverage/
e2e:
stage: e2e
script:
- npm i
- pkill Xvfb
- npm run e2e
#e2e:
# stage: e2e
# script:
# - npm i
# - pkill Xvfb
# - npm run e2e
pages:
stage: .post

View File

@ -32,7 +32,7 @@
"node_modules/font-awesome/css/font-awesome.css",
"node_modules/primeng/resources/themes/nova-light/theme.css",
"node_modules/primeng/resources/primeng.min.css",
"src/styles.scss"
"src/assets/scss/styles.scss"
],
"scripts": [
"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');
//
// module.exports = {
// verbose: 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",
"version": "1.0.0",
"licence": "AGPL-3.0-or-later",
"scripts": {
"ng": "ng",
"start": "ng serve",
"compodoc": "compodoc -p tsconfig.json",
"build": "ng build --crossOrigin=anonymous --prod",
"package": "cat dist/framadate/*.js > dist/framadate/framadate-scripts-bundled.js && ls -l dist/framadate",
"bld:pkg": "npm run build && 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",
"test": "ng test --watch=false",
"lint": "ng lint",
"e2e": "ng e2e",
"format:check": "prettier --list-different \"src/{app,environments,assets}/**/*{.ts,.js,.json,.css,.scss}\"",
"format:all": "prettier --write \"src/**/*.{js,jsx,ts,tsx,md,html,css,scss}\"",
"trans": "ng xi18n --output-path=src/locale --i18n-locale=fr",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"postinstall": "ngcc"
},
"private": false,
"dependencies": {
"@angular/animations": "^9.1.1",
"@angular/cdk": "^9.2.0",
"@angular/common": "^9.0.7",
"@angular/compiler": "^9.0.7",
"@angular/core": "^9.0.7",
"@angular/forms": "^9.0.7",
"@angular/localize": "^9.1.1",
"@angular/platform-browser": "^9.0.7",
"@angular/platform-browser-dynamic": "^9.0.7",
"@angular/router": "^9.0.7",
"@fullcalendar/core": "^4.4.0",
"@ngx-translate/core": "^12.1.2",
"@ngx-translate/http-loader": "^4.0.0",
"angular-date-value-accessor": "^1.0.2",
"bulma": "^0.8.2",
"chart.js": "^2.8.0",
"font-awesome": "^4.7.0",
"karma-coverage": "^2.0.1",
"karma-firefox-launcher": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.4",
"ngx-clipboard": "^13.0.0",
"ngx-markdown": "^9.0.0",
"ngx-toaster": "^1.0.1",
"primeicons": "^2.0.0",
"primeng": "^9.0.5",
"quill": "^1.3.7",
"rxjs": "^6.5.5",
"rxjs-compat": "^6.5.5",
"tslib": "^1.11.1",
"zone.js": "^0.10.3"
},
"devDependencies": {
"@angular-builders/jest": "^9.0.1",
"@angular-devkit/build-angular": "^0.901.1",
"@angular/cli": "^9.0.7",
"@angular/compiler-cli": "^9.1.1",
"@angular/language-service": "^9.0.7",
"@babel/core": "^7.9.0",
"@storybook/addon-actions": "^5.3.18",
"@storybook/addon-links": "^5.3.18",
"@storybook/addon-notes": "^5.3.18",
"@storybook/addons": "^5.3.18",
"@storybook/angular": "^5.3.18",
"@types/jasmine": "^3.5.10",
"@types/jasminewd2": "~2.0.8",
"@types/jest": "^25.2.1",
"@types/node": "^13.11.1",
"@typescript-eslint/eslint-plugin": "^2.27.0",
"@typescript-eslint/parser": "^2.27.0",
"babel-loader": "^8.1.0",
"compodoc": "^0.0.41",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.1",
"eslint-plugin-prettier": "^3.1.3",
"husky": "^4.2.5",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~5.0.1",
"jest": "^25.3.0",
"lint-staged": "^10.1.3",
"prettier": "^2.0.4",
"protractor": "~5.4.3",
"ts-node": "~8.8.2",
"typescript": "~3.8.3"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/{app,environments,assets}/**/*.{js,jsx,ts,tsx,md,html,css,scss}": [
"prettier --write",
"git add"
],
"*.js": "eslint --cache --fix"
}
"name": "framadate-funky-frontend",
"version": "1.0.0",
"licence": "AGPL-3.0-or-later",
"scripts": {
"ng": "ng",
"start": "ng serve",
"compodoc": "compodoc -p tsconfig.json",
"build": "ng build --crossOrigin=anonymous --prod",
"package": "cat dist/framadate/*.js > dist/framadate/framadate-scripts-bundled.js && ls -l dist/framadate",
"bld:pkg": "npm run build && 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",
"test": "jest",
"test:watch": "jest --watch",
"test:ci": "jest --runInBand",
"lint": "ng lint",
"e2e": "ng e2e",
"format:check": "prettier --list-different \"src/{app,environments,assets}/**/*{.ts,.js,.json,.css,.scss}\"",
"format:all": "prettier --write \"src/**/*.{js,jsx,ts,tsx,md,html,css,scss}\"",
"trans": "ng xi18n --output-path=src/locale --i18n-locale=fr",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"postinstall": "ngcc"
},
"private": false,
"dependencies": {
"@angular/animations": "^9.1.1",
"@angular/cdk": "^9.2.0",
"@angular/common": "^9.0.7",
"@angular/compiler": "^9.0.7",
"@angular/core": "^9.0.7",
"@angular/forms": "^9.0.7",
"@angular/localize": "^9.1.1",
"@angular/platform-browser": "^9.0.7",
"@angular/platform-browser-dynamic": "^9.0.7",
"@angular/router": "^9.0.7",
"@fullcalendar/core": "^4.4.0",
"@ngx-translate/core": "^12.1.2",
"@ngx-translate/http-loader": "^4.0.0",
"angular-date-value-accessor": "^1.0.2",
"bulma": "^0.8.2",
"chart.js": "^2.8.0",
"font-awesome": "^4.7.0",
"jest-preset-angular": "^8.1.3",
"karma-coverage": "^2.0.1",
"karma-firefox-launcher": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.4",
"ngx-clipboard": "^13.0.0",
"ngx-markdown": "^9.0.0",
"ngx-toaster": "^1.0.1",
"primeicons": "^2.0.0",
"primeng": "^9.0.5",
"quill": "^1.3.7",
"rxjs": "^6.5.5",
"rxjs-compat": "^6.5.5",
"tslib": "^1.11.1",
"zone.js": "^0.10.3"
},
"devDependencies": {
"@angular-builders/jest": "^9.0.1",
"@angular-devkit/build-angular": "^0.901.1",
"@angular/cli": "^9.0.7",
"@angular/compiler-cli": "^9.1.1",
"@angular/language-service": "^9.0.7",
"@babel/core": "^7.9.0",
"@storybook/addon-actions": "^5.3.18",
"@storybook/addon-links": "^5.3.18",
"@storybook/addon-notes": "^5.3.18",
"@storybook/addons": "^5.3.18",
"@storybook/angular": "^5.3.18",
"@types/jasminewd2": "~2.0.8",
"@types/jest": "^25.2.1",
"@types/node": "^13.11.1",
"@typescript-eslint/eslint-plugin": "^2.27.0",
"@typescript-eslint/parser": "^2.27.0",
"babel-loader": "^8.1.0",
"compodoc": "^0.0.41",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.1",
"eslint-plugin-prettier": "^3.1.3",
"husky": "^4.2.5",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~5.0.1",
"jest": "^25.3.0",
"lint-staged": "^10.1.3",
"prettier": "^2.0.4",
"protractor": "~5.4.3",
"ts-node": "~8.8.2",
"typescript": "~3.8.3"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/{app,environments,assets}/**/*.{js,jsx,ts,tsx,md,html,css,scss}": [
"prettier --write",
"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 }}">
<header class="big-header">
<div class="container">
<div class="columns">
<div class="column">
<framadate-master-head></framadate-master-head>
</div>
<div class="column">
<framadate-language></framadate-language>
</div>
</div>
</div>
</header>
<header class="big-header">
<div class="container">
<div class="columns">
<div class="column">
<framadate-master-head></framadate-master-head>
</div>
<div class="column">
<framadate-language></framadate-language>
</div>
</div>
</div>
</header>
<main>
<div class="container">
<div class="columns">
<div class="column is-one-quarter">
<framadate-theme-selector></framadate-theme-selector>
<main>
<div class="container">
<div class="columns">
<div class="column is-one-quarter togglable-menu" *ngIf="config.menuVisible">
<framadate-theme-selector></framadate-theme-selector>
<framadate-navigation *ngIf="config.menuVisible" [step]="step"></framadate-navigation>
<framadate-debugger *ngIf="isDevelopmentEnv"></framadate-debugger>
<p-toast position="top-right"></p-toast>
</div>
<div class="column">
<router-outlet></router-outlet>
</div>
</div>
</div>
</main>
<framadate-navigation [step]="step"></framadate-navigation>
<framadate-debugger *ngIf="isDevelopmentEnv"></framadate-debugger>
</div>
<div class="column">
<router-outlet></router-outlet>
</div>
</div>
</div>
</main>
<p-toast position="top-right"></p-toast>
</div>

View File

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

View File

@ -3,29 +3,29 @@ import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent],
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'framadate'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('framadate');
});
it(`should have as title 'framadate'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('framadate');
});
it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to framadate!');
});
it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
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';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
step: string;
isDevelopmentEnv = false;
step: string;
isDevelopmentEnv = false;
constructor(
private translate: TranslateService,
public config: ConfigService,
@Inject(DOCUMENT) private document,
private route: Router
) {
this.detectCurrentTabOnRouteChange();
constructor(
private translate: TranslateService,
public config: ConfigService,
@Inject(DOCUMENT) private document,
private route: Router
) {
this.detectCurrentTabOnRouteChange();
this.isDevelopmentEnv = !environment.production;
}
this.isDevelopmentEnv = !environment.production;
}
detectCurrentTabOnRouteChange() {
this.route.events.subscribe((event: any) => {});
this.route.events
.pipe(filter((event) => event instanceof NavigationStart))
.subscribe((event: NavigationStart) => {
this.scrollGoToTop();
this.updateCurrentTab(event);
// only if there is a poll ID
this.config.fetchPollFromRoute(event);
});
}
detectCurrentTabOnRouteChange() {
this.route.events.subscribe((event: any) => {});
this.route.events
.pipe(filter((event) => event instanceof NavigationStart))
.subscribe((event: NavigationStart) => {
this.scrollGoToTop();
this.updateCurrentTab(event);
// only if there is a poll ID
this.config.fetchPollFromRoute(event);
});
}
scrollGoToTop() {
this.document.documentElement.scrollTop = 0;
}
scrollGoToTop() {
this.document.documentElement.scrollTop = 0;
}
updateCurrentTab(event) {
if (event.url) {
const tab = event.url.split('/');
if (tab && tab[2]) {
this.step = tab[2];
} else {
this.step = 'home';
}
}
}
updateCurrentTab(event) {
if (event.url) {
const tab = event.url.split('/');
if (tab && tab[2]) {
this.step = tab[2];
} else {
this.step = 'home';
}
}
}
}

View File

@ -7,11 +7,11 @@ import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
MissingTranslationHandler,
MissingTranslationHandlerParams,
TranslateLoader,
TranslateModule,
TranslateService,
MissingTranslationHandler,
MissingTranslationHandlerParams,
TranslateLoader,
TranslateModule,
TranslateService,
} from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
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';
export class MyMissingTranslationHandler implements MissingTranslationHandler {
handle(params: MissingTranslationHandlerParams) {
return 'some value';
}
handle(params: MissingTranslationHandlerParams) {
return 'some value';
}
}
registerLocaleData(localeFr, 'fr');
registerLocaleData(localeEn, 'en');
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
return new TranslateHttpLoader(http);
return new TranslateHttpLoader(http);
}
@NgModule({
declarations: [
AppComponent,
BaseComponent,
KindComponent,
HeaderComponent,
NavigationComponent,
DatesComponent,
DebuggerComponent,
VisibilityComponent,
ResumeComponent,
PicturesComponent,
AnswersComponent,
EndConfirmationComponent,
CreateOrRetrieveComponent,
VotingSummaryComponent,
VotingGraphComponent,
VotingChoiceComponent,
PasswordComponent,
HomeComponent,
PollGraphicComponent,
AdminComponent,
SelectorComponent,
PollDisplayComponent,
VotingComponent,
VotingCommentComponent,
ResettableInputDirective,
ErasableInputComponent,
CopyTextComponent,
CommentsListComponent,
ChoicesListComponent,
VotingNavigationComponent,
ThemeSelectorComponent,
MasterHeadComponent,
LanguageComponent,
],
imports: [
ConfirmDialogModule,
ClipboardModule,
CommonModule,
BrowserModule,
DialogModule,
DateValueAccessorModule,
BrowserAnimationsModule,
AppRoutingModule,
ToastModule,
MessageModule,
MarkdownModule.forRoot(),
TranslateModule.forRoot({
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler,
},
// useDefaultLang: false,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
}),
HttpClientModule,
FormsModule,
],
providers: [TranslateService, ConfigService, PollService, MessageService, ConfirmationService],
bootstrap: [AppComponent],
declarations: [
AppComponent,
BaseComponent,
KindComponent,
HeaderComponent,
NavigationComponent,
DatesComponent,
DebuggerComponent,
VisibilityComponent,
ResumeComponent,
PicturesComponent,
AnswersComponent,
EndConfirmationComponent,
CreateOrRetrieveComponent,
VotingSummaryComponent,
VotingGraphComponent,
VotingChoiceComponent,
PasswordComponent,
HomeComponent,
PollGraphicComponent,
AdminComponent,
SelectorComponent,
PollDisplayComponent,
VotingComponent,
VotingCommentComponent,
ResettableInputDirective,
ErasableInputComponent,
CopyTextComponent,
CommentsListComponent,
ChoicesListComponent,
VotingNavigationComponent,
ThemeSelectorComponent,
MasterHeadComponent,
LanguageComponent,
],
imports: [
ConfirmDialogModule,
ClipboardModule,
CommonModule,
BrowserModule,
DialogModule,
DateValueAccessorModule,
BrowserAnimationsModule,
AppRoutingModule,
ToastModule,
MessageModule,
MarkdownModule.forRoot(),
TranslateModule.forRoot({
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler,
},
// useDefaultLang: false,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
}),
HttpClientModule,
FormsModule,
],
providers: [TranslateService, ConfigService, PollService, MessageService, ConfirmationService],
bootstrap: [AppComponent],
})
export class AppModule {}

View File

@ -1,63 +1,63 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
providedIn: 'root',
})
export class DateUtilities {
/**
* add some days to a date, to compute intervals
* @param days
* @param date
*/
addDaysToDate(days: number, date: Date) {
date = new Date(date.valueOf());
date.setDate(date.getDate() + days);
return date;
}
/**
* add some days to a date, to compute intervals
* @param days
* @param date
*/
addDaysToDate(days: number, date: Date) {
date = new Date(date.valueOf());
date.setDate(date.getDate() + days);
return date;
}
/**
*
* @param d1
* @param d2
* @param interval
*/
getDatesInRange(d1: Date, d2: Date, interval: number) {
d1 = new Date(d1);
d2 = new Date(d2);
const dates = [];
while (+d1 < +d2) {
dates.push({
literal: this.formateDate(d1),
date_object: d1,
});
d1.setDate(d1.getDate() + interval);
}
return dates.slice(0);
}
/**
*
* @param d1
* @param d2
* @param interval
*/
getDatesInRange(d1: Date, d2: Date, interval: number) {
d1 = new Date(d1);
d2 = new Date(d2);
const dates = [];
while (+d1 < +d2) {
dates.push({
literal: this.formateDate(d1),
date_object: d1,
});
d1.setDate(d1.getDate() + interval);
}
return dates.slice(0);
}
/**
* get the number of days between two dates
* @param d1
* @param d2
*/
dayDiff(d1: Date, d2: Date): Number {
return Number(d2.getTime() - d1.getTime() / 31536000000);
}
/**
* get the number of days between two dates
* @param d1
* @param d2
*/
dayDiff(d1: Date, d2: Date): number {
return Number(d2.getTime() - d1.getTime() / 31536000000);
}
/**
* format a date object to the date format used by the inputs of type date
* YYYY-MM-DD
* @param date
*/
formateDate(date) {
return [
date.getFullYear(),
this.getDoubleDigits(date.getMonth() + 1),
this.getDoubleDigits(date.getDate()),
].join('-');
}
/**
* format a date object to the date format used by the inputs of type date
* YYYY-MM-DD
* @param date
*/
formateDate(date) {
return [
date.getFullYear(),
this.getDoubleDigits(date.getMonth() + 1),
this.getDoubleDigits(date.getDate()),
].join('-');
}
getDoubleDigits(str) {
return ('00' + str).slice(-2);
}
getDoubleDigits(str) {
return ('00' + str).slice(-2);
}
}

View File

@ -5,80 +5,80 @@ import { environment } from '../../environments/environment';
import { DateChoice, defaultAnswers, otherDefaultDates, PollAnswer } from './defaultConfigs';
export interface DateOption {
timeList: any;
literal: string;
date_object?: object;
timeList: any;
literal: string;
date_object?: object;
}
const baseConfigValues = {
pollType: 'dates',
title: '',
description: '',
myName: '',
myEmail: '',
pollType: 'dates',
title: '',
description: '',
myName: '',
myEmail: '',
};
/**
* configuration of the poll, add new fields at will
*/
export class PollConfig {
menuVisible = true;
menuVisible = true;
expiracyDateDefaultInDays = 60;
deletionDateAfterLastModification = 180;
step = 0; // step in the progress of creating a poll
stepMax = 3; // step max in the progress of creating a poll
pollType = 'dates'; // classic or dates
expiracyDateDefaultInDays = 60;
deletionDateAfterLastModification = 180;
step = 0; // step in the progress of creating a poll
stepMax = 3; // step max in the progress of creating a poll
pollType = 'dates'; // classic or dates
title: string = environment.production ? '' : 'titre';
description: string = environment.production ? '' : 'ma description';
myName: string = environment.production ? '' : 'mon pseudo';
myComment: string = environment.production ? '' : 'wouah trop bien framadate!';
isAdmin: boolean = !environment.production;
myVoteStack: any;
myTempVoteStack = 0;
myEmail: string = environment.production ? '' : 'tktest@tktest.com';
myPolls: any = []; // list of retrieved polls from the backend api
/*
title: string = environment.production ? '' : 'titre';
description: string = environment.production ? '' : 'ma description';
myName: string = environment.production ? '' : 'mon pseudo';
myComment: string = environment.production ? '' : 'wouah trop bien framadate!';
isAdmin = !environment.production;
myVoteStack: any;
myTempVoteStack = 0;
myEmail: string = environment.production ? '' : 'tktest@tktest.com';
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
*/
allowSeveralHours = 'true';
// access
visibility = 'link_only'; // visible to anyone with the link:
voteChoices = 'only_yes'; // possible answers to a vote choice: only "yes", "yes, maybe, no"
creationDate = new Date();
expirationDate = ''; // expiracy date
voteStackId = null; // id of the vote stack to update
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
currentPoll; // current poll selected with createPoll or getPoll of ConfigService
passwordAccess = 0;
password = '';
customUrl = ''; // custom slug in the url, must be unique
customUrlIsUnique = null; // given by the backend
urlSlugPublic = null;
urlPublic = environment.production ? '' : environment.baseHref + '/#/poll/id/4';
urlAdmin = environment.baseHref + '/#/admin/d65es45fd45sdf45sd345f312sdf31sgfd345';
adminKey = ''; // key to change config of the poll
owner_modifier_token = ''; // key to change a vote stack
canModifyAnswers = true; // bool for the frontend selector
whoModifiesAnswers = '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
timeList: DateChoice[] = otherDefaultDates; // ranges of time expressed as strings
allowSeveralHours = 'true';
// access
visibility = 'link_only'; // visible to anyone with the link:
voteChoices = 'only_yes'; // possible answers to a vote choice: only "yes", "yes, maybe, no"
creationDate = new Date();
expirationDate = ''; // expiracy date
voteStackId = null; // id of the vote stack to update
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
currentPoll; // current poll selected with createPoll or getPoll of ConfigService
passwordAccess = 0;
password = '';
customUrl = ''; // custom slug in the url, must be unique
customUrlIsUnique = null; // given by the backend
urlSlugPublic = null;
urlPublic = environment.production ? '' : environment.baseHref + '/#/poll/id/4';
urlAdmin = environment.baseHref + '/#/admin/d65es45fd45sdf45sd345f312sdf31sgfd345';
adminKey = ''; // key to change config of the poll
owner_modifier_token = ''; // key to change a vote stack
canModifyAnswers = true; // bool for the frontend selector
whoModifiesAnswers = '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
timeList: DateChoice[] = otherDefaultDates; // ranges of time expressed as strings
answers: PollAnswer[] = defaultAnswers;
// front end choices
themeChoices: string[] = ['light-watermelon', 'dark-crystal', 'hot-covid'];
themeSelected = 0;
themeClass = 'theme-light-watermelon';
// modals
displayConfirmVoteModalAdmin = false;
answers: PollAnswer[] = defaultAnswers;
// front end choices
themeChoices: string[] = ['light-watermelon', 'dark-crystal', 'hot-covid'];
themeSelected = 0;
themeClass = 'theme-light-watermelon';
// modals
displayConfirmVoteModalAdmin = false;
resetConfig() {
const self = this;
Object.keys(baseConfigValues).forEach((key) => {
self[key] = baseConfigValues[key];
});
}
resetConfig() {
const self = this;
Object.keys(baseConfigValues).forEach((key) => {
self[key] = baseConfigValues[key];
});
}
}

View File

@ -3,73 +3,73 @@ import { PollConfig } from './PollConfig';
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
providedIn: 'root',
})
export class PollUtilities {
// utils functions
/**
* generate unique id to have a default url for future poll
*/
makeUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
// utils functions
/**
* generate unique id to have a default url for future poll
*/
makeUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
/**
* make a uniq slug for the current poll creation
* @param str
*/
makeSlug(config: PollConfig) {
let str = '';
str =
config.creationDate.getFullYear() +
'_' +
(config.creationDate.getMonth() + 1) +
'_' +
config.creationDate.getDate() +
'_' +
config.myName +
'_' +
config.title;
str = str.replace(/^\s+|\s+$/g, ''); // trim
str = str.toLowerCase();
/**
* make a uniq slug for the current poll creation
* @param str
*/
makeSlug(config: PollConfig) {
let str = '';
str =
config.creationDate.getFullYear() +
'_' +
(config.creationDate.getMonth() + 1) +
'_' +
config.creationDate.getDate() +
'_' +
config.myName +
'_' +
config.title;
str = str.replace(/^\s+|\s+$/g, ''); // trim
str = str.toLowerCase();
// remove accents, swap ñ for n, etc
var from = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;';
var to = 'aaaaeeeeiiiioooouuuunc------';
for (var i = 0, l = from.length; i < l; i++) {
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
}
// remove accents, swap ñ for n, etc
const from = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;';
const to = 'aaaaeeeeiiiioooouuuunc------';
for (let i = 0, l = from.length; i < l; i++) {
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
}
str = str
.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
.replace(/\s+/g, '-') // collapse whitespace and replace by -
.replace(/-+/g, '-'); // collapse dashes
str = str
.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
.replace(/\s+/g, '-') // collapse whitespace and replace by -
.replace(/-+/g, '-'); // collapse dashes
return str;
}
return str;
}
/**
* prepare headers like the charset and json type for any call to the backend
* @param bodyContent
*/
makeHeaders(bodyContent?: any) {
const headerDict = {
Charset: 'UTF-8',
'Content-Type': 'application/json',
Accept: 'application/json',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Origin': '*',
};
/**
* prepare headers like the charset and json type for any call to the backend
* @param bodyContent
*/
makeHeaders(bodyContent?: any) {
const headerDict = {
Charset: 'UTF-8',
'Content-Type': 'application/json',
Accept: 'application/json',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Origin': '*',
};
const requestOptions = {
headers: new HttpHeaders(headerDict),
body: bodyContent,
};
const requestOptions = {
headers: new HttpHeaders(headerDict),
body: bodyContent,
};
return requestOptions;
}
return requestOptions;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,52 +1,52 @@
export const mockGraphConfig = {
step: 0,
stepMax: 3,
pollType: 'special dates',
title: '',
description: '',
myName: '',
visibility: 'link_only',
// date specific poll
allowSeveralHours: 'true',
dateLgfgfgfgist: ['jeudi', 'vendredi', 'samedi'], // sets of days as strings
timeList: ['08:00', '08:30', '09:00'], // ranges of time expressed as strings
answers: [
{
id: 0,
text: 'no',
},
step: 0,
stepMax: 3,
pollType: 'special dates',
title: '',
description: '',
myName: '',
visibility: 'link_only',
// date specific poll
allowSeveralHours: 'true',
dateLgfgfgfgist: ['jeudi', 'vendredi', 'samedi'], // sets of days as strings
timeList: ['08:00', '08:30', '09:00'], // ranges of time expressed as strings
answers: [
{
id: 0,
text: 'no',
},
{
id: 1,
text: 'yes',
},
{
id: 2,
text: 'maybe',
},
{
id: 3,
text: 'maybe',
},
{
id: 4,
text: 'maybe',
},
{
id: 5,
text: 'maybe',
},
{
id: 6,
text: 'maybe',
},
{
id: 7,
text: 'maybe',
},
{
id: 8,
text: 'maybe',
},
],
{
id: 1,
text: 'yes',
},
{
id: 2,
text: 'maybe',
},
{
id: 3,
text: 'maybe',
},
{
id: 4,
text: 'maybe',
},
{
id: 5,
text: 'maybe',
},
{
id: 6,
text: 'maybe',
},
{
id: 7,
text: 'maybe',
},
{
id: 8,
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 = [
{
id: 1000001,
title: 'blehehehe heh hehhe e test1',
customUrl: null,
description: 'maaaaaaaaaaah',
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' },
owner: null,
kind: 'text',
allowedAnswers: ['yes'],
modificationPolicy: 'nobody',
mailOnComment: null,
mailOnVote: null,
hideResults: null,
showResultEvenIfPasswords: null,
votes: {},
stacksOfVotes: {},
choices: {},
comments: {},
defaultExpiracyDaysFromNow: 60,
},
{
id: 1000002,
title: 'bleh z zr erth tuyjikioy yylil test2',
customUrl: null,
description: 'maaaaaaaaaaah 2',
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' },
owner: null,
kind: 'text',
allowedAnswers: ['yes'],
modificationPolicy: 'nobody',
mailOnComment: null,
mailOnVote: null,
hideResults: null,
showResultEvenIfPasswords: null,
votes: {},
stacksOfVotes: {},
choices: {},
comments: {},
defaultExpiracyDaysFromNow: 60,
},
{
id: 1000001,
title: 'blehehehe heh hehhe e test1',
customUrl: null,
description: 'maaaaaaaaaaah',
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' },
owner: null,
kind: 'text',
allowedAnswers: ['yes'],
modificationPolicy: 'nobody',
mailOnComment: null,
mailOnVote: null,
hideResults: null,
showResultEvenIfPasswords: null,
votes: {},
stacksOfVotes: {},
choices: {},
comments: {},
defaultExpiracyDaysFromNow: 60,
},
{
id: 1000002,
title: 'bleh z zr erth tuyjikioy yylil test2',
customUrl: null,
description: 'maaaaaaaaaaah 2',
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' },
owner: null,
kind: 'text',
allowedAnswers: ['yes'],
modificationPolicy: 'nobody',
mailOnComment: null,
mailOnVote: null,
hideResults: null,
showResultEvenIfPasswords: null,
votes: {},
stacksOfVotes: {},
choices: {},
comments: {},
defaultExpiracyDaysFromNow: 60,
},
];

View File

@ -2,9 +2,9 @@ import { Directive, ElementRef, forwardRef, HostListener, Renderer2 } from '@ang
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
export const DATE_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DateValueAccessor),
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DateValueAccessor),
multi: true,
};
/**
@ -14,36 +14,36 @@ export const DATE_VALUE_ACCESSOR: any = {
* `<input type="date" name="myBirthday" ngModel useValueAsDate>`
*/
@Directive({
// 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]',
// 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]',
// this selector is an opt-in version
selector: '[useValueAsDate]',
providers: [DATE_VALUE_ACCESSOR],
// this selector is an opt-in version
selector: '[useValueAsDate]',
providers: [DATE_VALUE_ACCESSOR],
})
export class DateValueAccessor implements ControlValueAccessor {
@HostListener('input', ['$event.target.valueAsDate']) onChange = (_: any) => {};
@HostListener('blur', []) onTouched = () => {};
@HostListener('input', ['$event.target.valueAsDate']) onChange = (_: any) => {};
@HostListener('blur', []) onTouched = () => {};
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
writeValue(value: Date): void {
if (!value) {
this._renderer.setProperty(this._elementRef.nativeElement, 'value', null);
return;
}
this._renderer.setProperty(this._elementRef.nativeElement, 'valueAsDate', value);
}
writeValue(value: Date): void {
if (!value) {
this._renderer.setProperty(this._elementRef.nativeElement, 'value', null);
return;
}
this._renderer.setProperty(this._elementRef.nativeElement, 'valueAsDate', value);
}
registerOnChange(fn: (_: any) => void): void {
this.onChange = fn;
}
registerOnChange(fn: (_: any) => void): void {
this.onChange = fn;
}
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
}
setDisabledState(isDisabled: boolean): void {
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';
@NgModule({
declarations: [DateValueAccessor],
exports: [DateValueAccessor],
declarations: [DateValueAccessor],
exports: [DateValueAccessor],
})
export class DateValueAccessorModule {}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,41 +1,41 @@
form {
display: flex;
flex-direction: column;
width: 340px;
margin: auto;
display: flex;
flex-direction: column;
width: 340px;
margin: auto;
}
.row {
flex-direction: row;
flex-wrap: wrap;
padding-bottom: 65px;
flex-direction: row;
flex-wrap: wrap;
padding-bottom: 65px;
}
textarea {
height: 115px;
margin-bottom: 50px;
height: 115px;
margin-bottom: 50px;
}
label {
padding-bottom: 10px;
flex-wrap: wrap;
padding-bottom: 10px;
flex-wrap: wrap;
}
h2,
h1 {
margin-bottom: 40px;
margin-bottom: 40px;
}
h2 {
margin-top: 40px;
padding-left: 16px;
margin-top: 40px;
padding-left: 16px;
}
.btn--alert {
font-weight: 600;
font-weight: 600;
}
h3 {
padding-left: 28px;
padding-bottom: 15px;
padding-left: 28px;
padding-bottom: 15px;
}
select,
input[type='date'] {
max-width: 130px;
max-width: 130px;
}
.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';
describe('AdminComponent', () => {
let component: AdminComponent;
let fixture: ComponentFixture<AdminComponent>;
fdescribe('AdminComponent', () => {
let component: AdminComponent;
let fixture: ComponentFixture<AdminComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AdminComponent],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AdminComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AdminComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(AdminComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,27 +1,27 @@
.container {
display: flex;
flex-direction: column;
margin: auto;
display: flex;
flex-direction: column;
margin: auto;
}
h1 {
display: inline-block;
margin-bottom: 3rem;
font-size: 2.6rem;
display: inline-block;
margin-bottom: 3rem;
font-size: 2.6rem;
&::after {
content: '';
display: block;
width: 27.4%;
height: 2px;
margin-top: 5px;
margin-right: auto;
margin-left: auto;
// background-color: $primary_color;
}
&::after {
content: '';
display: block;
width: 27.4%;
height: 2px;
margin-top: 5px;
margin-right: auto;
margin-left: auto;
// background-color: $primary_color;
}
}
label {
float: left;
float: left;
}
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';
describe('CreateOrRetrieveComponent', () => {
let component: CreateOrRetrieveComponent;
let fixture: ComponentFixture<CreateOrRetrieveComponent>;
let component: CreateOrRetrieveComponent;
let fixture: ComponentFixture<CreateOrRetrieveComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [CreateOrRetrieveComponent],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [CreateOrRetrieveComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CreateOrRetrieveComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(CreateOrRetrieveComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,14 +3,14 @@ import { BaseComponent } from '../base-page/base.component';
import { ConfigService } from '../../services/config.service';
@Component({
selector: 'framadate-page-kind',
templateUrl: './kind.component.html',
styleUrls: ['./kind.component.scss'],
selector: 'framadate-page-kind',
templateUrl: './kind.component.html',
styleUrls: ['./kind.component.scss'],
})
export class KindComponent extends BaseComponent implements OnInit {
constructor(public config: ConfigService) {
super(config);
}
constructor(public config: ConfigService) {
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>
<form>
<label for="password">Mot de passe :</label>
<section class="row">
<input class="margin-btm-x5" type="password" name="password" />
<input type="submit" name="view" value="Voir" class="btn btn--small btn--purple" />
</section>
<label for="password">Mot de passe :</label>
<section class="row">
<input class="margin-btm-x5" type="password" name="password" />
<input type="submit" name="view" value="Voir" class="btn btn--small btn--purple" />
</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>

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
<!--ceci est la popup pour ajouter une image-->
<h1 i18n>
Images
Images
</h1>
<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';
describe('PicturesComponent', () => {
let component: PicturesComponent;
let fixture: ComponentFixture<PicturesComponent>;
let component: PicturesComponent;
let fixture: ComponentFixture<PicturesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [PicturesComponent],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [PicturesComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PicturesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(PicturesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

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

View File

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

View File

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

View File

@ -7,64 +7,64 @@ import { environment } from '../../../environments/environment';
import { mockPoll3 } from '../../config/mocks/mock-poll3';
@Component({
selector: 'framadate-poll-display',
templateUrl: './poll-display.component.html',
styleUrls: ['./poll-display.component.scss'],
selector: 'framadate-poll-display',
templateUrl: './poll-display.component.html',
styleUrls: ['./poll-display.component.scss'],
})
export class PollDisplayComponent extends BaseComponent implements OnInit {
comments = mockComments;
comments = mockComments;
constructor(public config: ConfigService, private router: Router, public activeRoute: ActivatedRoute) {
super(config);
this.activeRoute.paramMap.subscribe((params) => {
console.log('params', params);
this.config.pollId = params.get('poll');
this.config.pollSlug = params.get('pollSlug');
if (!this.config.loading) {
this.fetchPoll();
}
});
}
constructor(public config: ConfigService, private router: Router, public activeRoute: ActivatedRoute) {
super(config);
this.activeRoute.paramMap.subscribe((params) => {
console.log('params', params);
this.config.pollId = params.get('poll');
this.config.pollSlug = params.get('pollSlug');
if (!this.config.loading) {
this.fetchPoll();
}
});
}
ngOnInit() {}
ngOnInit() {}
// fetch poll with its ID or slug.
fetchPoll() {
const id = this.activeRoute.snapshot.params.poll;
const pollSlug = this.activeRoute.snapshot.params.pollSlug;
// fetch poll with its ID or slug.
fetchPoll() {
const id = this.activeRoute.snapshot.params.poll;
const pollSlug = this.activeRoute.snapshot.params.pollSlug;
if (!environment.production) {
console.log('mockPoll3', mockPoll3);
this.config.currentPoll = mockPoll3;
return;
}
if (id) {
this.config.loading = true;
// store it in the poll property here
this.config.getPollById(id).subscribe(
(res: any) => {
console.log('res', res);
this.config.updateCurrentPollFromResponse(res);
this.config.loading = false;
},
(e) => {
// handle need for a password
console.log('e', e);
this.config.handleError(e);
}
);
} else if (pollSlug) {
this.config.loading = true;
this.config.getPollByURL(pollSlug).subscribe(
(res: any) => {
this.config.loading = false;
this.config.updateCurrentPollFromResponse(res);
},
(e) => {
// handle need for a password
this.config.handleError(e);
}
);
}
}
if (!environment.production) {
console.log('mockPoll3', mockPoll3);
this.config.currentPoll = mockPoll3;
return;
}
if (id) {
this.config.loading = true;
// store it in the poll property here
this.config.getPollById(id).subscribe(
(res: any) => {
console.log('res', res);
this.config.updateCurrentPollFromResponse(res);
this.config.loading = false;
},
(e) => {
// handle need for a password
console.log('e', e);
this.config.handleError(e);
}
);
} else if (pollSlug) {
this.config.loading = true;
this.config.getPollByURL(pollSlug).subscribe(
(res: any) => {
this.config.loading = false;
this.config.updateCurrentPollFromResponse(res);
},
(e) => {
// handle need for a password
this.config.handleError(e);
}
);
}
}
}

View File

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

View File

@ -1,9 +1,9 @@
.card {
box-shadow: 0px 0px 0.5em #ccc;
padding: 2em;
margin: 1em 0;
box-shadow: 0px 0px 0.5em #ccc;
padding: 2em;
margin: 1em 0;
}
.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';
describe('ResumeComponent', () => {
let component: ResumeComponent;
let fixture: ComponentFixture<ResumeComponent>;
let component: ResumeComponent;
let fixture: ComponentFixture<ResumeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ResumeComponent],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ResumeComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ResumeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(ResumeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,26 +1,29 @@
<div *ngIf="config.currentPoll" class="list-of-choices">
<div *ngFor="let choice of config.currentPoll.choices">
<framadate-voting-choice
[choice]="choice"
[choices_count]="config.currentPoll.choices_count"
[pollIsSpecialDate]="config.currentPoll.poll.kind == 'date'"
[poll]="config.currentPoll"
></framadate-voting-choice>
</div>
<div *ngFor="let choice of config.currentPoll.choices">
<framadate-voting-choice
[choice]="choice"
[choices_count]="config.currentPoll.choices_count"
[pollIsSpecialDate]="config.currentPoll.poll.kind == 'date'"
[poll]="config.currentPoll"
></framadate-voting-choice>
</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>
<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';
describe('ChoicesListComponent', () => {
let component: ChoicesListComponent;
let fixture: ComponentFixture<ChoicesListComponent>;
let component: ChoicesListComponent;
let fixture: ComponentFixture<ChoicesListComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ChoicesListComponent],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ChoicesListComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChoicesListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(ChoicesListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

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

View File

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

View File

@ -9,33 +9,33 @@ import { ConfirmationService, MessageService } from 'primeng';
import { Router } from '@angular/router';
import { ConfigService } from '../../../services/config.service';
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
const routerSpy = jest.fn({ navigateByUrl: jest.fn() });
describe('CommentsListComponent', () => {
let component: CommentsListComponent;
let fixture: ComponentFixture<CommentsListComponent>;
let component: CommentsListComponent;
let fixture: ComponentFixture<CommentsListComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule],
declarations: [CommentsListComponent],
providers: [
HttpClient,
MessageService,
ConfirmationService,
ConfigService,
{ provide: Router, useValue: routerSpy },
],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule],
declarations: [CommentsListComponent],
providers: [
HttpClient,
MessageService,
ConfirmationService,
ConfigService,
{ provide: Router, useValue: routerSpy },
],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CommentsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(CommentsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

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

View File

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

View File

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

View File

@ -10,72 +10,72 @@ import { VotingChoiceComponent } from './voting-choice.component';
import { mockChoice } from '../../../config/mocks/choice';
import { mockPoll3 } from '../../../config/mocks/mock-poll3';
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
const routerSpy = jest.fn({ navigateByUrl: jest.fn() });
describe('VotingChoiceComponent', () => {
let component: VotingChoiceComponent;
let fixture: ComponentFixture<VotingChoiceComponent>;
let component: VotingChoiceComponent;
let fixture: ComponentFixture<VotingChoiceComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule],
declarations: [VotingChoiceComponent],
providers: [
HttpClient,
MessageService,
ConfirmationService,
ConfigService,
{ provide: Router, useValue: routerSpy },
],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [FormsModule, BrowserModule, CommonModule, HttpClientModule],
declarations: [VotingChoiceComponent],
providers: [
HttpClient,
MessageService,
ConfirmationService,
ConfigService,
{ provide: Router, useValue: routerSpy },
],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(VotingChoiceComponent);
component = fixture.componentInstance;
component.choice = { ...mockChoice };
component.choices_count = mockPoll3.choices_count;
component.choice_id = mockChoice.id;
component.poll = mockPoll3.poll;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(VotingChoiceComponent);
component = fixture.componentInstance;
component.choice = { ...mockChoice };
component.choices_count = mockPoll3.choices_count;
component.choice_id = mockChoice.id;
component.poll = mockPoll3.poll;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should have nothing specified as an answer by default', () => {
expect(component.choice.answer).toBeFalsy();
});
it('should set answer to yes', () => {
component.setAnswserTo('yes');
expect(component.choice.answer).toBe('yes');
});
it('should set answer to maybe', () => {
component.setAnswserTo('maybe');
expect(component.choice.answer).toBe('maybe');
});
it('should set answer to no', () => {
component.setAnswserTo('no');
expect(component.choice.answer).toBe('no');
});
it('should set answer to no after 2 set on yes', () => {
component.setAnswserTo('yes');
component.setAnswserTo('yes');
expect(component.choice.answer).toBe('no');
});
it('should stay on maybe after 2 set on maybe', () => {
component.setAnswserTo('maybe');
component.setAnswserTo('maybe');
expect(component.choice.answer).toBe('maybe');
});
it('should stay on no after 2 set on no', () => {
component.setAnswserTo('no');
component.setAnswserTo('no');
expect(component.choice.answer).toBe('no');
});
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.length).toBe(1);
expect(component.simpleAnswer).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should have nothing specified as an answer by default', () => {
expect(component.choice.answer).toBeFalsy();
});
it('should set answer to yes', () => {
component.setAnswserTo('yes');
expect(component.choice.answer).toBe('yes');
});
it('should set answer to maybe', () => {
component.setAnswserTo('maybe');
expect(component.choice.answer).toBe('maybe');
});
it('should set answer to no', () => {
component.setAnswserTo('no');
expect(component.choice.answer).toBe('no');
});
it('should set answer to no after 2 set on yes', () => {
component.setAnswserTo('yes');
component.setAnswserTo('yes');
expect(component.choice.answer).toBe('no');
});
it('should stay on maybe after 2 set on maybe', () => {
component.setAnswserTo('maybe');
component.setAnswserTo('maybe');
expect(component.choice.answer).toBe('maybe');
});
it('should stay on no after 2 set on no', () => {
component.setAnswserTo('no');
component.setAnswserTo('no');
expect(component.choice.answer).toBe('no');
});
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.length).toBe(1);
expect(component.simpleAnswer).toBeTruthy();
});
});

View File

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

View File

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

View File

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

View File

@ -2,14 +2,14 @@ import { Component, Input, OnInit } from '@angular/core';
import { mockComments } from '../../../config/mocks/mock-comments';
@Component({
selector: 'framadate-voting-comment',
templateUrl: './voting-comment.component.html',
styleUrls: ['./voting-comment.component.scss'],
selector: 'framadate-voting-comment',
templateUrl: './voting-comment.component.html',
styleUrls: ['./voting-comment.component.scss'],
})
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';
describe('VotingGraphComponent', () => {
let component: VotingGraphComponent;
let fixture: ComponentFixture<VotingGraphComponent>;
let component: VotingGraphComponent;
let fixture: ComponentFixture<VotingGraphComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [VotingGraphComponent],
}).compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [VotingGraphComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(VotingGraphComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(VotingGraphComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,26 +1,26 @@
@import '../../../../assets/scss/variables';
.person {
font-weight: 700;
font-weight: 700;
}
.preferred-result {
font-weight: 700;
font-size: 1.5em;
font-weight: 700;
font-size: 1.5em;
}
thead {
font-size: 1.25em;
font-weight: 700;
font-size: 1.25em;
font-weight: 700;
}
tbody {
text-align: right;
text-align: right;
}
td {
&.has-max-score {
background: $primary_color;
font-weight: 800;
}
&.has-max-score {
background: $primary_color;
font-weight: 800;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

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