Browse Source

split config service & dispatch

develop
seraph 2 years ago
parent
commit
3997dd090e
  1. 29
      angular.json
  2. 3
      babel.config.json
  3. 2
      backend-api-endpoints-doc.md
  4. 11
      jest.config.js
  5. 46
      package.json
  6. 20
      src/app/app-routing.module.ts
  7. 29
      src/app/app.component.html
  8. 78
      src/app/app.component.ts
  9. 112
      src/app/app.module.ts
  10. 8
      src/app/config/PollConfig.ts
  11. 1
      src/app/core/components/footer/footer.component.html
  12. 0
      src/app/core/components/footer/footer.component.scss
  13. 12
      src/app/core/components/footer/footer.component.spec.ts
  14. 12
      src/app/core/components/footer/footer.component.ts
  15. 9
      src/app/core/components/logo/logo.component.html
  16. 0
      src/app/core/components/logo/logo.component.scss
  17. 12
      src/app/core/components/logo/logo.component.spec.ts
  18. 8
      src/app/core/components/logo/logo.component.ts
  19. 1
      src/app/core/components/navbar/navbar.component.html
  20. 0
      src/app/core/components/navbar/navbar.component.scss
  21. 12
      src/app/core/components/navbar/navbar.component.spec.ts
  22. 12
      src/app/core/components/navbar/navbar.component.ts
  23. 3
      src/app/core/components/page-not-found/page-not-found.component.html
  24. 0
      src/app/core/components/page-not-found/page-not-found.component.scss
  25. 12
      src/app/core/components/page-not-found/page-not-found.component.spec.ts
  26. 8
      src/app/core/components/page-not-found/page-not-found.component.ts
  27. 20
      src/app/core/core.module.ts
  28. 0
      src/app/core/enums/answer-granularity.enum.ts
  29. 0
      src/app/core/enums/answer-type.enum.ts
  30. 4
      src/app/core/enums/language.enum.ts
  31. 0
      src/app/core/enums/poll-type.enum.ts
  32. 5
      src/app/core/enums/theme.enum.ts
  33. 5
      src/app/core/guards/module-import.guard.ts
  34. 0
      src/app/core/interfaces/date-options.interface.ts
  35. 0
      src/app/core/models/answer.model.ts
  36. 0
      src/app/core/models/poll-config.model.ts
  37. 0
      src/app/core/models/poll-options.model.ts
  38. 0
      src/app/core/models/poll.model.ts
  39. 0
      src/app/core/models/user.model.ts
  40. 0
      src/app/core/services/api.service.spec.ts
  41. 0
      src/app/core/services/api.service.ts
  42. 0
      src/app/core/services/comment.service.spec.ts
  43. 0
      src/app/core/services/comment.service.ts
  44. 0
      src/app/core/services/poll.service.spec.ts
  45. 5
      src/app/core/services/poll.service.ts
  46. 16
      src/app/core/services/storage.service.spec.ts
  47. 19
      src/app/core/services/storage.service.ts
  48. 0
      src/app/core/services/theme.service.spec.ts
  49. 15
      src/app/core/services/theme.service.ts
  50. 0
      src/app/core/services/user.service.spec.ts
  51. 5
      src/app/core/services/user.service.ts
  52. 0
      src/app/core/services/vote.service.spec.ts
  53. 0
      src/app/core/services/vote.service.ts
  54. 0
      src/app/core/utils/date-utils.service.spec.ts
  55. 0
      src/app/core/utils/date-utils.service.ts
  56. 0
      src/app/core/utils/poll-utils.service.spec.ts
  57. 0
      src/app/core/utils/poll-utils.service.ts
  58. 12
      src/app/features/administration/administration-routing.module.ts
  59. 1
      src/app/features/administration/administration.component.html
  60. 0
      src/app/features/administration/administration.component.scss
  61. 24
      src/app/features/administration/administration.component.spec.ts
  62. 12
      src/app/features/administration/administration.component.ts
  63. 13
      src/app/features/administration/administration.module.ts
  64. 12
      src/app/features/participation/participation-routing.module.ts
  65. 2
      src/app/features/participation/participation.component.html
  66. 0
      src/app/features/participation/participation.component.scss
  67. 24
      src/app/features/participation/participation.component.spec.ts
  68. 12
      src/app/features/participation/participation.component.ts
  69. 13
      src/app/features/participation/participation.module.ts
  70. 2
      src/app/pages/admin/admin.component.ts
  71. 2
      src/app/pages/answers/answers.component.ts
  72. 2
      src/app/pages/create-or-retrieve/create-or-retrieve.component.html
  73. 2
      src/app/pages/create-or-retrieve/create-or-retrieve.component.ts
  74. 2
      src/app/pages/dates/dates.component.html
  75. 2
      src/app/pages/dates/dates.component.ts
  76. 4
      src/app/pages/end-confirmation/end-confirmation.component.html
  77. 2
      src/app/pages/end-confirmation/end-confirmation.component.ts
  78. 9
      src/app/pages/example/base-page/base.component.ts
  79. 2
      src/app/pages/example/kind/kind.component.html
  80. 2
      src/app/pages/example/kind/kind.component.ts
  81. 2
      src/app/pages/example/pictures/pictures.component.ts
  82. 8
      src/app/pages/home/home.component.html
  83. 2
      src/app/pages/home/home.component.ts
  84. 2
      src/app/pages/password/password.component.ts
  85. 12
      src/app/pages/poll/poll-display/poll-display.component.html
  86. 2
      src/app/pages/poll/poll-display/poll-display.component.scss
  87. 2
      src/app/pages/poll/poll-display/poll-display.component.ts
  88. 2
      src/app/pages/poll/poll-graphic/poll-graphic.component.ts
  89. 2
      src/app/pages/resume/resume.component.ts
  90. 6
      src/app/pages/visibility/visibility.component.html
  91. 18
      src/app/pages/visibility/visibility.component.ts
  92. 6
      src/app/pages/voting/choices-list/choices-list.component.html
  93. 2
      src/app/pages/voting/choices-list/choices-list.component.ts
  94. 3
      src/app/pages/voting/comments-list/comments-list.component.html
  95. 2
      src/app/pages/voting/comments-list/comments-list.component.ts
  96. 2
      src/app/pages/voting/voting-choice/voting-choice.component.html
  97. 2
      src/app/pages/voting/voting-choice/voting-choice.component.scss
  98. 2
      src/app/pages/voting/voting-choice/voting-choice.component.ts
  99. 2
      src/app/pages/voting/voting-comment/voting-comment.component.ts
  100. 2
      src/app/pages/voting/voting-graph/voting-graph.component.html
  101. Some files were not shown because too many files have changed in this diff Show More

29
angular.json

@ -12,7 +12,7 @@
},
"root": "",
"sourceRoot": "src",
"prefix": "framadate",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
@ -23,16 +23,13 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"assets": ["src/favicon.ico", "src/assets"],
"styles": [
"node_modules/fork-awesome/css/fork-awesome.min.css",
"node_modules/primeicons/primeicons.css",
"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/assets/scss/styles.scss"
"src/styles.scss"
],
"scripts": [
"node_modules/marked/lib/marked.js",
@ -90,20 +87,13 @@
},
"test": {
"builder": "@angular-builders/jest:run",
"options": {
}
"options": {}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
"tsConfig": ["tsconfig.app.json", "tsconfig.spec.json", "e2e/tsconfig.json"],
"exclude": ["**/node_modules/**"]
}
},
"e2e": {
@ -121,5 +111,8 @@
}
}
},
"defaultProject": "framadate"
"defaultProject": "framadate",
"cli": {
"analytics": "0ba9c0a9-850f-4c5f-8124-cbe6f4c79ef1"
}
}

3
babel.config.json

@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env"]
}

2
backend-api-endpoints-doc.md

@ -1,3 +1,5 @@
// TODO: File to be deleted : just temporary documentation of backend API endpoints
/**
*
* -------------------------- -------- -------- ------ ------------------------------------------------

11
jest.config.js

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

46
package.json

@ -1,7 +1,7 @@
{
"name": "framadate-funky-frontend",
"version": "1.0.0",
"licence": "AGPL-3.0-or-later",
"license": "AGPL-3.0-or-later",
"scripts": {
"ng": "ng",
"start": "ng serve",
@ -41,17 +41,14 @@
"bulma": "^0.8.2",
"chart.js": "^2.8.0",
"date-fns": "^2.12.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",
"fork-awesome": "^1.1.7",
"locale-enum": "^1.1.0",
"ngx-clipboard": "^13.0.0",
"ngx-markdown": "^9.0.0",
"ngx-toaster": "^1.0.1",
"ngx-webstorage": "^5.0.0",
"primeicons": "^2.0.0",
"primeng": "^9.0.5",
"primeng": "^9.0.6",
"quill": "^1.3.7",
"rxjs": "^6.5.5",
"rxjs-compat": "^6.5.5",
@ -61,35 +58,39 @@
},
"devDependencies": {
"@angular-builders/jest": "^9.0.1",
"@angular-devkit/build-angular": "^0.901.1",
"@angular/cli": "^9.0.7",
"@angular-devkit/build-angular": "^0.901.2",
"@angular/cli": "^9.1.2",
"@angular/compiler-cli": "^9.1.1",
"@angular/language-service": "^9.0.7",
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"@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",
"@types/node": "^13.13.2",
"@types/uuid": "^7.0.2",
"@typescript-eslint/eslint-plugin": "^2.27.0",
"@typescript-eslint/parser": "^2.27.0",
"babel-jest": "^25.4.0",
"babel-loader": "^8.1.0",
"babel-polyfill": "^6.26.0",
"compodoc": "^0.0.41",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.1",
"eslint-config-prettier": "^6.11.0",
"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",
"jest": "^25.4.0",
"jest-environment-jsdom-sixteen": "^1.0.3",
"jest-preset-angular": "^8.1.3",
"lint-staged": "^10.1.7",
"prettier": "^2.0.5",
"protractor": "~5.4.3",
"ts-node": "~8.8.2",
"ts-jest": "^25.4.0",
"ts-mockito": "^2.5.0",
"ts-node": "~8.9.0",
"typescript": "~3.8.3"
},
"husky": {
@ -106,6 +107,13 @@
},
"jest": {
"preset": "jest-preset-angular",
"setupFilesAfterEnv": "./jest.config.js"
"setupFilesAfterEnv": [
"<rootDir>/src/jest.setup.ts"
],
"testEnvironment": "jest-environment-jsdom-sixteen",
"transform": {
"^.+\\.(ts|html)$": "ts-jest",
"^.+\\.jsx?$": "babel-jest"
}
}
}

20
src/app/app-routing.module.ts

@ -1,22 +1,23 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PageNotFoundComponent } from './core/components/page-not-found/page-not-found.component';
import { AdminComponent } from './pages/admin/admin.component';
import { AnswersComponent } from './pages/answers/answers.component';
import { BaseComponent } from './pages/example/base-page/base.component';
import { CreateOrRetrieveComponent } from './pages/create-or-retrieve/create-or-retrieve.component';
import { DatesComponent } from './pages/dates/dates.component';
import { EndConfirmationComponent } from './pages/end-confirmation/end-confirmation.component';
import { HomeComponent } from './pages/home/home.component';
import { BaseComponent } from './pages/example/base-page/base.component';
import { KindComponent } from './pages/example/kind/kind.component';
import { PasswordComponent } from './pages/password/password.component';
import { PicturesComponent } from './pages/example/pictures/pictures.component';
import { HomeComponent } from './pages/home/home.component';
import { PasswordComponent } from './pages/password/password.component';
import { PollDisplayComponent } from './pages/poll/poll-display/poll-display.component';
import { PollGraphicComponent } from './pages/poll/poll-graphic/poll-graphic.component';
import { ResumeComponent } from './pages/resume/resume.component';
import { VisibilityComponent } from './pages/visibility/visibility.component';
import { VotingChoiceComponent } from './pages/voting/voting-choice/voting-choice.component';
import { VotingComponent } from './pages/voting/voting.component';
import { PollGraphicComponent } from './pages/poll/poll-graphic/poll-graphic.component';
const routes: Routes = [
{ path: '', redirectTo: 'step/creation', pathMatch: 'full' },
@ -39,7 +40,16 @@ const routes: Routes = [
{ path: 'votingchoice', component: VotingChoiceComponent },
{ path: 'voting', component: VotingComponent },
{ path: 'step/password', component: PasswordComponent },
{ path: '**', redirectTo: '/home', pathMatch: 'full' },
{
path: 'administration',
loadChildren: () =>
import('./features/administration/administration.module').then((m) => m.AdministrationModule),
},
{
path: 'participation',
loadChildren: () => import('./features/participation/participation.module').then((m) => m.ParticipationModule),
},
{ path: '**', component: PageNotFoundComponent },
];
@NgModule({

29
src/app/app.component.html

@ -1,12 +1,25 @@
<div id="big_container" class="{{ this.config.preferences.themeClass }}">
<div id="big_container" [class]="themeClass">
<header class="big-header">
<div class="container">
<div class="columns">
<div class="columns is-mobile is-vcentered">
<div class="column is-pulled-left has-addons">
<img
(click)="toggleMenu()"
alt="menu icon"
class="menu_icon clickable"
src="assets/img/icone-menu.svg"
/>
<br />
<span (click)="toggleMenu()" class="menu_label">Menu</span>
</div>
<div class="column">
<app-logo></app-logo>
</div>
<div class="column">
<framadate-master-head></framadate-master-head>
<app-theme-selector></app-theme-selector>
</div>
<div class="column">
<framadate-language></framadate-language>
<app-language-selector></app-language-selector>
</div>
</div>
</div>
@ -14,12 +27,10 @@
<main>
<div class="container">
<div class="columns">
<div class="columns is-mobile">
<div class="column is-one-quarter togglable-menu" *ngIf="config.menuVisible">
<framadate-theme-selector></framadate-theme-selector>
<framadate-navigation [step]="step"></framadate-navigation>
<framadate-debugger *ngIf="isDevelopmentEnv"></framadate-debugger>
<app-navigation [step]="step"></app-navigation>
<app-debugger *ngIf="isDebugMode"></app-debugger>
</div>
<div class="column">
<router-outlet></router-outlet>

78
src/app/app.component.ts

@ -1,34 +1,67 @@
import { Component, Inject } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { NavigationStart, Router } from '@angular/router';
import { DOCUMENT } from '@angular/common';
import { Component, Inject, OnInit, OnDestroy } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { NavigationStart, Router } from '@angular/router';
import { Observable, Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { ConfigService } from './services/config.service';
import { environment } from '../environments/environment';
import { Theme } from './core/enums/theme.enum';
import { ThemeService } from './core/services/theme.service';
import { ConfigService } from './services/config.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
step: string;
isDevelopmentEnv = false;
export class AppComponent implements OnInit, OnDestroy {
public appTitle: string = environment.appTitle;
public themeClass: string;
public isDebugMode = false;
private themeSubscription: Subscription;
public step: string;
constructor(
private translate: TranslateService,
private titleService: Title,
private themeService: ThemeService,
public config: ConfigService,
@Inject(DOCUMENT) private document,
private route: Router
) {
private router: Router
) {}
ngOnInit(): void {
if (!environment.production) {
this.isDebugMode = true;
this.appTitle += ' | DEV';
console.info(' ######### framadate | DEV ######### we are NOT in production env, filling with mock values');
}
this.titleService.setTitle(this.appTitle);
this.themeSubscription = this.themeService.theme.subscribe((theme: Theme) => {
switch (theme) {
case Theme.DARK:
this.themeClass = 'theme-dark-crystal';
break;
case Theme.RED:
this.themeClass = 'theme-hot-covid';
break;
default:
this.themeClass = 'theme-light-watermelon';
}
});
this.detectCurrentTabOnRouteChange();
}
this.isDevelopmentEnv = !environment.production;
ngOnDestroy(): void {
if (this.themeSubscription) {
this.themeSubscription.unsubscribe();
}
}
detectCurrentTabOnRouteChange() {
this.route.events.subscribe((event: any) => {});
this.route.events
public detectCurrentTabOnRouteChange(): void {
this.router.events
.pipe(filter((event) => event instanceof NavigationStart))
.subscribe((event: NavigationStart) => {
this.scrollGoToTop();
@ -38,18 +71,19 @@ export class AppComponent {
});
}
scrollGoToTop() {
public scrollGoToTop(): void {
this.document.documentElement.scrollTop = 0;
}
updateCurrentTab(event) {
public updateCurrentTab(event): void {
if (event.url) {
const tab = event.url.split('/');
if (tab && tab[2]) {
this.step = tab[2];
} else {
this.step = 'home';
}
const tab: string[] = event.url.split('/');
this.step = tab && tab[2] ? tab[2] : 'home';
}
}
public toggleMenu(): void {
// TODO: move this logic elsewhere, probably in Navbar component
this.config.menuVisible = !this.config.menuVisible;
}
}

112
src/app/app.module.ts

@ -1,10 +1,8 @@
import { CommonModule, registerLocaleData } from '@angular/common';
import { CommonModule } from '@angular/common';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import localeEn from '@angular/common/locales/en';
import localeFr from '@angular/common/locales/fr';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserModule, Title } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
MissingTranslationHandler,
@ -16,27 +14,29 @@ import {
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { ClipboardModule } from 'ngx-clipboard';
import { MarkdownModule } from 'ngx-markdown';
import { NgxWebstorageModule } from 'ngx-webstorage';
import { ConfirmationService, MessageModule, MessageService } from 'primeng';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { DialogModule } from 'primeng/dialog';
import { ToastModule } from 'primeng/toast';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';
import { DateValueAccessorModule } from './custom-lib/date-value-accessor';
import { DebuggerComponent } from './ui/debugger/debugger.component';
import { HeaderComponent } from './ui/navigation/header/header.component';
import { AdminComponent } from './pages/admin/admin.component';
import { AnswersComponent } from './pages/answers/answers.component';
import { BaseComponent } from './pages/example/base-page/base.component';
import { CreateOrRetrieveComponent } from './pages/create-or-retrieve/create-or-retrieve.component';
import { DatesComponent } from './pages/dates/dates.component';
import { EndConfirmationComponent } from './pages/end-confirmation/end-confirmation.component';
import { HomeComponent } from './pages/home/home.component';
import { BaseComponent } from './pages/example/base-page/base.component';
import { KindComponent } from './pages/example/kind/kind.component';
import { PasswordComponent } from './pages/password/password.component';
import { PicturesComponent } from './pages/example/pictures/pictures.component';
import { HomeComponent } from './pages/home/home.component';
import { PasswordComponent } from './pages/password/password.component';
import { PollDisplayComponent } from './pages/poll/poll-display/poll-display.component';
import { PollGraphicComponent } from './pages/poll/poll-graphic/poll-graphic.component';
import { ResumeComponent } from './pages/resume/resume.component';
import { VisibilityComponent } from './pages/visibility/visibility.component';
import { ChoicesListComponent } from './pages/voting/choices-list/choices-list.component';
@ -47,96 +47,92 @@ import { VotingGraphComponent } from './pages/voting/voting-graph/voting-graph.c
import { VotingNavigationComponent } from './pages/voting/voting-navigation/voting-navigation.component';
import { VotingSummaryComponent } from './pages/voting/voting-summary/voting-summary.component';
import { VotingComponent } from './pages/voting/voting.component';
import { PollGraphicComponent } from './pages/poll/poll-graphic/poll-graphic.component';
import { ConfigService } from './services/config.service';
import { SharedModule } from './shared/shared.module';
import { CopyTextComponent } from './ui/copy-text/copy-text.component';
import { DebuggerComponent } from './ui/debugger/debugger.component';
import { ResettableInputDirective } from './ui/directives/resettable-input.directive';
import { ErasableInputComponent } from './ui/erasable-input/erasable-input.component';
import { MasterHeadComponent } from './ui/navigation/master-head/master-head.component';
import { NavigationComponent } from './ui/navigation/navigation.component';
import { LanguageComponent } from './ui/selector/language/language.component';
import { SelectorComponent } from './ui/selector/selector.component';
import { ThemeSelectorComponent } from './ui/selector/theme-selector/theme-selector.component';
import { TwoLinksComponent } from './ui/navigation/two-links/two-links.component';
import { LanguageSelectorComponent } from './ui/selectors/language-selector/language-selector.component';
import { ThemeSelectorComponent } from './ui/selectors/theme-selector/theme-selector.component';
export class MyMissingTranslationHandler implements MissingTranslationHandler {
handle(params: MissingTranslationHandlerParams) {
return 'some value';
public handle(params: MissingTranslationHandlerParams): string {
return `MISSING TRANSLATION FOR [${params.key}]`;
}
}
registerLocaleData(localeFr, 'fr');
registerLocaleData(localeEn, 'en');
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
return new TranslateHttpLoader(http);
}
@NgModule({
declarations: [
AdminComponent,
AnswersComponent,
AppComponent,
BaseComponent,
KindComponent,
HeaderComponent,
NavigationComponent,
ChoicesListComponent,
CommentsListComponent,
CopyTextComponent,
CreateOrRetrieveComponent,
DatesComponent,
DebuggerComponent,
VisibilityComponent,
ResumeComponent,
PicturesComponent,
AnswersComponent,
EndConfirmationComponent,
CreateOrRetrieveComponent,
VotingSummaryComponent,
VotingGraphComponent,
VotingChoiceComponent,
PasswordComponent,
ErasableInputComponent,
HomeComponent,
PollGraphicComponent,
AdminComponent,
SelectorComponent,
KindComponent,
NavigationComponent,
PasswordComponent,
PicturesComponent,
PollDisplayComponent,
VotingComponent,
VotingCommentComponent,
PollGraphicComponent,
ResettableInputDirective,
ErasableInputComponent,
CopyTextComponent,
CommentsListComponent,
ChoicesListComponent,
VotingNavigationComponent,
ResumeComponent,
ThemeSelectorComponent,
MasterHeadComponent,
LanguageComponent,
TwoLinksComponent,
VisibilityComponent,
VotingChoiceComponent,
VotingGraphComponent,
VotingComponent,
VotingCommentComponent,
VotingSummaryComponent,
VotingNavigationComponent,
LanguageSelectorComponent,
],
imports: [
ConfirmDialogModule,
AppRoutingModule,
BrowserAnimationsModule,
BrowserModule,
ClipboardModule,
CommonModule,
BrowserModule,
DialogModule,
ConfirmDialogModule,
CoreModule,
DateValueAccessorModule,
BrowserAnimationsModule,
AppRoutingModule,
ToastModule,
MessageModule,
DialogModule,
FormsModule,
HttpClientModule,
MarkdownModule.forRoot(),
MessageModule,
NgxWebstorageModule.forRoot({ prefix: environment.localStorage.key }),
SharedModule,
ToastModule,
TranslateModule.forRoot({
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler,
},
// useDefaultLang: false,
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MyMissingTranslationHandler,
},
useDefaultLang: false,
}),
HttpClientModule,
FormsModule,
],
providers: [TranslateService, ConfigService, MessageService, ConfirmationService],
providers: [ConfigService, ConfirmationService, MessageService, Title, TranslateService],
bootstrap: [AppComponent],
})
export class AppModule {}

8
src/app/config/PollConfig.ts

@ -57,8 +57,8 @@ export class PollConfig {
customUrl = ''; // custom slug in the url, must be unique
customUrlIsUnique = null; // given by the backend
urlSlugPublic = null;
urlPublic = environment.production ? '' : window.location.origin + '/#/poll/id/4';
urlAdmin = window.location.origin + '/#/admin/d65es45fd45sdf45sd345f312sdf31sgfd345';
urlPublic = environment.production ? '' : document.location.href + '/#/poll/id/4';
urlAdmin = document.location.href + '/#/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
@ -68,10 +68,6 @@ export class PollConfig {
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;

1
src/app/core/components/footer/footer.component.html

@ -0,0 +1 @@
<p>footer works!</p>

0
src/app/ui/navigation/header/header.component.scss → src/app/core/components/footer/footer.component.scss

12
src/app/ui/navigation/header/header.component.spec.ts → src/app/core/components/footer/footer.component.spec.ts

@ -1,19 +1,19 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component';
import { FooterComponent } from './footer.component';
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
describe('FooterComponent', () => {
let component: FooterComponent;
let fixture: ComponentFixture<FooterComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [HeaderComponent],
declarations: [FooterComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
fixture = TestBed.createComponent(FooterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

12
src/app/core/components/footer/footer.component.ts

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

9
src/app/ui/navigation/master-head/master-head.component.html → src/app/core/components/logo/logo.component.html

@ -1,14 +1,13 @@
<div class="home_link">
<a [routerLink]="'home'" aria-roledescription="home">
<a class="button" routerLink="/home" aria-roledescription="home">
<h1>
<span class="logo_first">Frama</span>
<span class="logo_second">date</span>
(démo)
<span class="logo_second">Sondage</span>
</h1>
</a>
<div class="legend">
<a class="button legend" href="https://framasoft.org/" target="_blank">
proposé par
<span class="legend_first">Frama</span>
<span class="legend_second">soft</span>
</div>
</a>
</div>

0
src/app/ui/navigation/master-head/master-head.component.scss → src/app/core/components/logo/logo.component.scss

12
src/app/ui/selector/language/language.component.spec.ts → src/app/core/components/logo/logo.component.spec.ts

@ -1,19 +1,19 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LanguageComponent } from './language.component';
import { LogoComponent } from './logo.component';
describe('LanguageComponent', () => {
let component: LanguageComponent;
let fixture: ComponentFixture<LanguageComponent>;
describe('LogoComponent', () => {
let component: LogoComponent;
let fixture: ComponentFixture<LogoComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LanguageComponent],
declarations: [LogoComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LanguageComponent);
fixture = TestBed.createComponent(LogoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

8
src/app/core/components/logo/logo.component.ts

@ -0,0 +1,8 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-logo',
templateUrl: './logo.component.html',
styleUrls: ['./logo.component.scss'],
})
export class LogoComponent {}

1
src/app/core/components/navbar/navbar.component.html

@ -0,0 +1 @@
<p>navbar works!</p>

0
src/app/ui/selector/language/language.component.scss → src/app/core/components/navbar/navbar.component.scss

12
src/app/ui/selector/selector.component.spec.ts → src/app/core/components/navbar/navbar.component.spec.ts

@ -1,19 +1,19 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SelectorComponent } from './selector.component';
import { NavbarComponent } from './navbar.component';
describe('SelectorComponent', () => {
let component: SelectorComponent;
let fixture: ComponentFixture<SelectorComponent>;
describe('NavbarComponent', () => {
let component: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [SelectorComponent],
declarations: [NavbarComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SelectorComponent);
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

12
src/app/core/components/navbar/navbar.component.ts

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

3
src/app/core/components/page-not-found/page-not-found.component.html

@ -0,0 +1,3 @@
<div class="hero">
This page doesn't exist.
</div>

0
src/app/ui/selector/selector.component.scss → src/app/core/components/page-not-found/page-not-found.component.scss

12
src/app/ui/navigation/master-head/master-head.component.spec.ts → src/app/core/components/page-not-found/page-not-found.component.spec.ts

@ -1,19 +1,19 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MasterHeadComponent } from './master-head.component';
import { PageNotFoundComponent } from './page-not-found.component';
describe('MasterHeadComponent', () => {
let component: MasterHeadComponent;
let fixture: ComponentFixture<MasterHeadComponent>;
describe('PageNotFoundComponent', () => {
let component: PageNotFoundComponent;
let fixture: ComponentFixture<PageNotFoundComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MasterHeadComponent],
declarations: [PageNotFoundComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MasterHeadComponent);
fixture = TestBed.createComponent(PageNotFoundComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

8
src/app/core/components/page-not-found/page-not-found.component.ts

@ -0,0 +1,8 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-page-not-found',
templateUrl: './page-not-found.component.html',
styleUrls: ['./page-not-found.component.scss'],
})
export class PageNotFoundComponent {}

20
src/app/core/core.module.ts

@ -0,0 +1,20 @@
import { CommonModule } from '@angular/common';
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FooterComponent } from './components/footer/footer.component';
import { LogoComponent } from './components/logo/logo.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
import { throwIfAlreadyLoaded } from './guards/module-import.guard';
@NgModule({
declarations: [FooterComponent, LogoComponent, NavbarComponent, PageNotFoundComponent],
imports: [CommonModule, RouterModule],
exports: [FooterComponent, LogoComponent, NavbarComponent, PageNotFoundComponent],
})
export class CoreModule {
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
throwIfAlreadyLoaded(parentModule, 'CoreModule');
}
}

0
src/app/shared/enums/answer-granularity.enum.ts → src/app/core/enums/answer-granularity.enum.ts

0
src/app/shared/enums/answer-type.enum.ts → src/app/core/enums/answer-type.enum.ts

4
src/app/core/enums/language.enum.ts

@ -0,0 +1,4 @@
export enum Language {
FR = 'FR',
EN = 'EN',
}

0
src/app/shared/enums/poll-type.enum.ts → src/app/core/enums/poll-type.enum.ts

5
src/app/core/enums/theme.enum.ts

@ -0,0 +1,5 @@
export enum Theme {
LIGHT = 'LIGHT',
DARK = 'DARK',
RED = 'RED',
}

5
src/app/core/guards/module-import.guard.ts

@ -0,0 +1,5 @@
export function throwIfAlreadyLoaded(parentModule: any, moduleName: string): void {
if (parentModule) {
throw new Error(`${moduleName} has already been loaded. Import ${moduleName} in the AppModule only.`);
}
}

0
src/app/shared/interfaces/date-options.interface.ts → src/app/core/interfaces/date-options.interface.ts

0
src/app/shared/models/answer.model.ts → src/app/core/models/answer.model.ts

0
src/app/shared/models/poll-config.model.ts → src/app/core/models/poll-config.model.ts

0
src/app/shared/models/poll-options.model.ts → src/app/core/models/poll-options.model.ts

0
src/app/shared/models/poll.model.ts → src/app/core/models/poll.model.ts

0
src/app/shared/models/user.model.ts → src/app/core/models/user.model.ts

0
src/app/shared/services/api.service.spec.ts → src/app/core/services/api.service.spec.ts

0
src/app/shared/services/api.service.ts → src/app/core/services/api.service.ts

0
src/app/shared/services/comment.service.spec.ts → src/app/core/services/comment.service.spec.ts

0
src/app/shared/services/comment.service.ts → src/app/core/services/comment.service.ts

0
src/app/shared/services/poll.service.spec.ts → src/app/core/services/poll.service.spec.ts

5
src/app/shared/services/poll.service.ts → src/app/core/services/poll.service.ts

@ -9,13 +9,10 @@ import { ApiService } from './api.service';
})
export class PollService {
private _poll: BehaviorSubject<Poll | undefined> = new BehaviorSubject<Poll | undefined>(undefined);
public readonly poll: Observable<Poll | undefined> = this._poll.asObservable();
constructor(private apiService: ApiService) {}
public get poll(): Observable<Poll | undefined> {
return this._poll.asObservable();
}
public updateCurrentPoll(poll: Poll): void {
this._poll.next(poll);
}

16
src/app/core/services/storage.service.spec.ts

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { StorageService } from './storage.service';
describe('StorageService', () => {
let service: StorageService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(StorageService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

19
src/app/core/services/storage.service.ts

@ -0,0 +1,19 @@
import { Injectable } from '@angular/core';
import { LocalStorage } from 'ngx-webstorage';
import { Language } from '../enums/language.enum';
import { Theme } from '../enums/theme.enum';
@Injectable({
providedIn: 'root',
})
export class StorageService {
@LocalStorage()
public theme: Theme;
@LocalStorage()
public language: Language;
@LocalStorage()
public userPollsIds: string[];
}

0
src/app/shared/services/theme.service.spec.ts → src/app/core/services/theme.service.spec.ts

15
src/app/core/services/theme.service.ts

@ -0,0 +1,15 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { Theme } from '../enums/theme.enum';
@Injectable({
providedIn: 'root',
})
export class ThemeService {
private _theme: BehaviorSubject<Theme> = new BehaviorSubject<Theme>(Theme.LIGHT);
public readonly theme: Observable<Theme> = this._theme.asObservable();
public selectTheme(theme: Theme): void {
this._theme.next(theme);
}
}

0
src/app/shared/services/user.service.spec.ts → src/app/core/services/user.service.spec.ts

5
src/app/shared/services/user.service.ts → src/app/core/services/user.service.ts

@ -8,10 +8,7 @@ import { User } from '../models/user.model';
})
export class UserService {
private _user: BehaviorSubject<User | undefined> = new BehaviorSubject<User | undefined>(undefined);
public get user(): Observable<User | undefined> {
return this._user.asObservable();
}
public readonly user: Observable<User | undefined> = this._user.asObservable();
public updateUser(user: User): void {
this._user.next(user);

0
src/app/shared/services/vote.service.spec.ts → src/app/core/services/vote.service.spec.ts

0
src/app/shared/services/vote.service.ts → src/app/core/services/vote.service.ts

0
src/app/shared/services/date-utils.service.spec.ts → src/app/core/utils/date-utils.service.spec.ts

0
src/app/shared/services/date-utils.service.ts → src/app/core/utils/date-utils.service.ts

0
src/app/shared/services/poll-utils.service.spec.ts → src/app/core/utils/poll-utils.service.spec.ts

0
src/app/shared/services/poll-utils.service.ts → src/app/core/utils/poll-utils.service.ts

12
src/app/features/administration/administration-routing.module.ts

@ -0,0 +1,12 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdministrationComponent } from './administration.component';
const routes: Routes = [{ path: '', component: AdministrationComponent }];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class AdministrationRoutingModule {}

1
src/app/features/administration/administration.component.html

@ -0,0 +1 @@
<p>administration works!</p>

0
src/app/features/administration/administration.component.scss

24
src/app/features/administration/administration.component.spec.ts

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

12
src/app/features/administration/administration.component.ts

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

13
src/app/features/administration/administration.module.ts

@ -0,0 +1,13 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { SharedModule } from '../../shared/shared.module';
import { AdministrationRoutingModule } from './administration-routing.module';
import { AdministrationComponent } from './administration.component';
@NgModule({
declarations: [AdministrationComponent],
imports: [CommonModule, AdministrationRoutingModule, SharedModule, TranslateModule.forChild({ extend: true })],
})
export class AdministrationModule {}

12
src/app/features/participation/participation-routing.module.ts

@ -0,0 +1,12 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ParticipationComponent } from './participation.component';
const routes: Routes = [{ path: '', component: ParticipationComponent }];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ParticipationRoutingModule {}

2
src/app/features/participation/participation.component.html

@ -0,0 +1,2 @@
<p>participation works!</p>
<p>It should display an existing poll, which user wants to participate by voting.</p>

0
src/app/features/participation/participation.component.scss

24
src/app/features/participation/participation.component.spec.ts

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

12
src/app/features/participation/participation.component.ts

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

13
src/app/features/participation/participation.module.ts

@ -0,0 +1,13 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { SharedModule } from '../../shared/shared.module';
import { ParticipationRoutingModule } from './participation-routing.module';
import { ParticipationComponent } from './participation.component';
@NgModule({
declarations: [ParticipationComponent],
imports: [CommonModule, ParticipationRoutingModule, SharedModule, TranslateModule.forChild({ extend: true })],
})
export class ParticipationModule {}

2
src/app/pages/admin/admin.component.ts

@ -6,7 +6,7 @@ import { PollUtilities } from '../../config/PollUtilities';
import { environment } from '../../../environments/environment';
@Component({
selector: 'framadate-admin',
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.scss'],
})

2
src/app/pages/answers/answers.component.ts

@ -5,7 +5,7 @@ import { ConfigService } from '../../services/config.service';
import { DOCUMENT } from '@angular/common';
@Component({
selector: 'framadate-answers',
selector: 'app-answers',
templateUrl: './answers.component.html',
styleUrls: ['./answers.component.scss'],
})

2
src/app/pages/create-or-retrieve/create-or-retrieve.component.html

@ -64,7 +64,7 @@
</div>
</section>
<div class="loading" *ngIf="config.loading">
<i class="fa fa-refresh fa-spin fa-3x fa-fw"></i>
<i class="fa fa-refresh fa-spin"></i>
</div>
</div>
</div>

2
src/app/pages/create-or-retrieve/create-or-retrieve.component.ts

@ -3,7 +3,7 @@ import { BaseComponent } from '../example/base-page/base.component';
import { ConfigService } from '../../services/config.service';
@Component({
selector: 'framadate-create-or-retrieve',
selector: 'app-create-or-retrieve',
templateUrl: './create-or-retrieve.component.html',
styleUrls: ['./create-or-retrieve.component.scss'],
})

2
src/app/pages/dates/dates.component.html

@ -156,7 +156,7 @@
</div>
</div>
<div class="column">
<framadate-resume></framadate-resume>
<app-resume></app-resume>
</div>
</div>

2
src/app/pages/dates/dates.component.ts

@ -7,7 +7,7 @@ import { otherDefaultDates } from '../../config/defaultConfigs';
import { DateUtilities } from '../../config/DateUtilities';
@Component({
selector: 'framadate-dates',
selector: 'app-dates',
templateUrl: './dates.component.html',
styleUrls: ['./dates.component.scss'],
})

4
src/app/pages/end-confirmation/end-confirmation.component.html

@ -19,7 +19,7 @@
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>
<app-copy-text [textToCopy]="config.urlAdmin"></app-copy-text>
<a href="{{ config.urlAdmin }}">
Voir le sondage coté administrateur·ice
</a>
@ -34,7 +34,7 @@
Pour accéder au sondage :
<a href="{{ config.urlPublic }}">{{ config.urlPublic }} </a>
</p>