Browse Source

Feature/simplify scss

develop
ty kayn 2 years ago
parent
commit
ba7a24708d
  1. 2
      .eslintcache
  2. 16
      .gitlab-ci.yml
  3. 2
      angular.json
  4. 2
      documentation/js/search/search_index.js
  5. 6
      jest.config.js
  6. 205
      package.json
  7. 54
      src/app/app.component.html
  8. 6
      src/app/app.component.scss
  9. 44
      src/app/app.component.spec.ts
  10. 76
      src/app/app.component.ts
  11. 146
      src/app/app.module.ts
  12. 106
      src/app/config/DateUtilities.ts
  13. 122
      src/app/config/PollConfig.ts
  14. 120
      src/app/config/PollUtilities.ts
  15. 154
      src/app/config/defaultConfigs.ts
  16. 44
      src/app/config/graph-canevas-options.ts
  17. 18
      src/app/config/mocks/choice.ts
  18. 40
      src/app/config/mocks/mock-comments.ts
  19. 98
      src/app/config/mocks/mock-graph.ts
  20. 1054
      src/app/config/mocks/mock-poll3.ts
  21. 1312
      src/app/config/mocks/mock-success-vote.ts
  22. 84
      src/app/config/mocks/mockmypolls.ts
  23. 64
      src/app/custom-lib/date-value-accessor/date-value-accessor.ts
  24. 4
      src/app/custom-lib/date-value-accessor/module.ts
  25. 60
      src/app/debugger/debugger.component.html
  26. 30
      src/app/debugger/debugger.component.spec.ts
  27. 32
      src/app/debugger/debugger.component.ts
  28. 30
      src/app/header/header.component.spec.ts
  29. 10
      src/app/header/header.component.ts
  30. 38
      src/app/pages/admin/admin.component.scss
  31. 32
      src/app/pages/admin/admin.component.spec.ts
  32. 140
      src/app/pages/answers/answers.component.html
  33. 30
      src/app/pages/answers/answers.component.spec.ts
  34. 144
      src/app/pages/answers/answers.component.ts
  35. 2
      src/app/pages/base-page/base.component.html
  36. 30
      src/app/pages/base-page/base.component.spec.ts
  37. 30
      src/app/pages/base-page/base.component.ts
  38. 136
      src/app/pages/create-or-retrieve/create-or-retrieve.component.html
  39. 36
      src/app/pages/create-or-retrieve/create-or-retrieve.component.scss
  40. 30
      src/app/pages/create-or-retrieve/create-or-retrieve.component.spec.ts
  41. 44
      src/app/pages/create-or-retrieve/create-or-retrieve.component.ts
  42. 290
      src/app/pages/dates/dates.component.html
  43. 56
      src/app/pages/dates/dates.component.scss
  44. 30
      src/app/pages/dates/dates.component.spec.ts
  45. 226
      src/app/pages/dates/dates.component.ts
  46. 92
      src/app/pages/end-confirmation/end-confirmation.component.html
  47. 6
      src/app/pages/end-confirmation/end-confirmation.component.scss
  48. 30
      src/app/pages/end-confirmation/end-confirmation.component.spec.ts
  49. 34
      src/app/pages/end-confirmation/end-confirmation.component.ts
  50. 168
      src/app/pages/home/home.component.html
  51. 30
      src/app/pages/home/home.component.spec.ts
  52. 16
      src/app/pages/home/home.component.ts
  53. 486
      src/app/pages/kind/kind.component.html
  54. 26
      src/app/pages/kind/kind.component.scss
  55. 30
      src/app/pages/kind/kind.component.spec.ts
  56. 14
      src/app/pages/kind/kind.component.ts
  57. 12
      src/app/pages/password/password.component.html
  58. 12
      src/app/pages/password/password.component.scss
  59. 30
      src/app/pages/password/password.component.spec.ts
  60. 14
      src/app/pages/password/password.component.ts
  61. 2
      src/app/pages/pictures/pictures.component.html
  62. 30
      src/app/pages/pictures/pictures.component.spec.ts
  63. 14
      src/app/pages/pictures/pictures.component.ts
  64. 116
      src/app/pages/poll-display/poll-display.component.html
  65. 30
      src/app/pages/poll-display/poll-display.component.spec.ts
  66. 108
      src/app/pages/poll-display/poll-display.component.ts
  67. 120
      src/app/pages/resume/resume.component.html
  68. 8
      src/app/pages/resume/resume.component.scss
  69. 30
      src/app/pages/resume/resume.component.spec.ts
  70. 12
      src/app/pages/resume/resume.component.ts
  71. 282
      src/app/pages/visibility/visibility.component.html
  72. 6
      src/app/pages/visibility/visibility.component.scss
  73. 30
      src/app/pages/visibility/visibility.component.spec.ts
  74. 38
      src/app/pages/visibility/visibility.component.ts
  75. 51
      src/app/pages/voting/choices-list/choices-list.component.html
  76. 5
      src/app/pages/voting/choices-list/choices-list.component.scss
  77. 30
      src/app/pages/voting/choices-list/choices-list.component.spec.ts
  78. 8
      src/app/pages/voting/choices-list/choices-list.component.ts
  79. 60
      src/app/pages/voting/comments-list/comments-list.component.html
  80. 48
      src/app/pages/voting/comments-list/comments-list.component.spec.ts
  81. 8
      src/app/pages/voting/comments-list/comments-list.component.ts
  82. 266
      src/app/pages/voting/voting-choice/voting-choice.component.html
  83. 349
      src/app/pages/voting/voting-choice/voting-choice.component.scss
  84. 126
      src/app/pages/voting/voting-choice/voting-choice.component.spec.ts
  85. 96
      src/app/pages/voting/voting-choice/voting-choice.component.ts
  86. 18
      src/app/pages/voting/voting-comment/voting-comment.component.html
  87. 30
      src/app/pages/voting/voting-comment/voting-comment.component.spec.ts
  88. 12
      src/app/pages/voting/voting-comment/voting-comment.component.ts
  89. 30
      src/app/pages/voting/voting-graph/voting-graph.component.spec.ts
  90. 14
      src/app/pages/voting/voting-graph/voting-graph.component.ts
  91. 58
      src/app/pages/voting/voting-navigation/voting-navigation.component.html
  92. 30
      src/app/pages/voting/voting-navigation/voting-navigation.component.spec.ts
  93. 8
      src/app/pages/voting/voting-navigation/voting-navigation.component.ts
  94. 279
      src/app/pages/voting/voting-summary/voting-summary.component.html
  95. 20
      src/app/pages/voting/voting-summary/voting-summary.component.scss
  96. 30
      src/app/pages/voting/voting-summary/voting-summary.component.spec.ts
  97. 84
      src/app/pages/voting/voting-summary/voting-summary.component.ts
  98. 14
      src/app/pages/voting/voting.component.html
  99. 30
      src/app/pages/voting/voting.component.spec.ts
  100. 12
      src/app/pages/voting/voting.component.ts
  101. Some files were not shown because too many files have changed in this diff Show More

2
.eslintcache

File diff suppressed because one or more lines are too long

16
.gitlab-ci.yml

@ -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

2
angular.json

@ -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",

2
documentation/js/search/search_index.js

File diff suppressed because one or more lines are too long

6
jest.config.js

@ -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;

205
package.json

@ -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"
}
}

54
src/app/app.component.html

@ -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>

6
src/app/app.component.scss

@ -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;
}

44
src/app/app.component.spec.ts

@ -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!');
});
});

76
src/app/app.component.ts

@ -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';
}
}
}
}

146
src/app/app.module.ts

@ -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 {}

106
src/app/config/DateUtilities.ts

@ -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);
}
}

122
src/app/config/PollConfig.ts

@ -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];
});
}
}

120
src/app/config/PollUtilities.ts

@ -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;
}
}

154
src/app/config/defaultConfigs.ts

@ -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,
},
];

44
src/app/config/graph-canevas-options.ts

@ -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 },