forked from tykayn/funky-framadate-front
rebase branch 'feature/refacto_1' of https://framagit.org/framasoft/framadate/funky-framadate-front into feature/refacto_1
This commit is contained in:
commit
7a4f16e484
3
.gitignore
vendored
3
.gitignore
vendored
@ -48,3 +48,6 @@ Thumbs.db
|
|||||||
|
|
||||||
# Editor-specific configuration
|
# Editor-specific configuration
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
# linter
|
||||||
|
.eslintcache
|
28
README.md
28
README.md
@ -1,3 +1,30 @@
|
|||||||
|
## LIBRARIES USED
|
||||||
|
|
||||||
|
| lib name | usage |
|
||||||
|
| ------------------------------------------------------------------ | -------------------------------------- |
|
||||||
|
| [axios](https://github.com/axios/axios) | http client |
|
||||||
|
| [bulma](https://bulma.io/) | CSS framework |
|
||||||
|
| [chart.js](https://www.chartjs.org/) | Generate beautiful graphs |
|
||||||
|
| [compodoc](https://compodoc.app/) | Generate technic documentation |
|
||||||
|
| [date-fns](https://date-fns.org) | manipulate dates |
|
||||||
|
| ESlint, Prettier, Lint-staged | Format & lint code |
|
||||||
|
| [font-awesome](https://github.com/FortAwesome/angular-fontawesome) | Icons collection |
|
||||||
|
| [fullcalendar](https://fullcalendar.io/docs/initialize-es6) | Manage & display calendars |
|
||||||
|
| [husky](https://www.npmjs.com/package/husky) | Hook actions on commit |
|
||||||
|
| [jest](https://jestjs.io/) | test engine |
|
||||||
|
| [locale-enum](https://www.npmjs.com/package/locale-enum) | enum of all locales |
|
||||||
|
| [ngx-clipboard](https://www.npmjs.com/package/ngx-clipboard) | Handle clipboard |
|
||||||
|
| [ngx-markdown](https://www.npmjs.com/package/ngx-markdown) | markdown parser |
|
||||||
|
| [ngx-toaster](https://www.npmjs.com/package/ngx-toaster) | toast notifications |
|
||||||
|
| [ngx-webstorage](https://www.npmjs.com/package/ngx-webstorage) | handle localStorage & webStorage |
|
||||||
|
| [primeNG](https://www.primefaces.org/primeng/) | UI components collection |
|
||||||
|
| [quill](https://www.npmjs.com/package/quill) | powerful rich text editor. WYSIWYG. |
|
||||||
|
| [storybook](https://storybook.js.org/) | StyleGuide UI |
|
||||||
|
| [ts-mockito](https://www.npmjs.com/package/ts-mockito) | Mocks for testing. |
|
||||||
|
| [uuid](https://www.npmjs.com/package/uuid) | handle client-side generation of uuids |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Framadate
|
# Framadate
|
||||||
|
|
||||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.1.
|
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.1.
|
||||||
@ -27,4 +54,3 @@ Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protrac
|
|||||||
Before using ng for the first time in this project, use `npm i` to install needed npm modules.
|
Before using ng for the first time in this project, use `npm i` to install needed npm modules.
|
||||||
|
|
||||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||||
|
|
||||||
|
42
backend-api-endpoints-doc.md
Normal file
42
backend-api-endpoints-doc.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* -------------------------- -------- -------- ------ ------------------------------------------------
|
||||||
|
Name Method Scheme Host Path
|
||||||
|
-------------------------- -------- -------- ------ ------------------------------------------------
|
||||||
|
_twig_error_test ANY ANY ANY /_error/{code}.{_format}
|
||||||
|
api_get_poll_comment GET ANY ANY /poll/{id}/comments
|
||||||
|
api_new_comment POST ANY ANY /poll/{id}/comment
|
||||||
|
api_poll_comments_delete DELETE ANY ANY /poll/{id}/comments
|
||||||
|
api_send_user_polls GET ANY ANY /send-polls-to-user/{email}
|
||||||
|
homepageget_default GET ANY ANY /
|
||||||
|
api_get_all_polls GET ANY ANY /poll/
|
||||||
|
api_get_poll GET ANY ANY /poll/{id}
|
||||||
|
api_update_poll PUT ANY ANY /poll/{id}/{token}
|
||||||
|
api_new_poll POST ANY ANY /poll/
|
||||||
|
api_test-mail-poll GET ANY ANY /poll/mail/test-mail-poll/{emailChoice}
|
||||||
|
api_poll_delete DELETE ANY ANY /poll/{id}
|
||||||
|
api_clean_expired_polls GET ANY ANY /poll/clean-polls
|
||||||
|
api_check_slug_is_unique GET ANY ANY /poll/admin/{token}
|
||||||
|
api_new_vote_stack POST ANY ANY /poll/{id}/vote
|
||||||
|
api_update_vote_stack PATCH ANY ANY /vote-stack/{id}/token/{modifierToken}
|
||||||
|
api_poll_votes_delete DELETE ANY ANY /poll/{id}/votes/{accessToken}
|
||||||
|
app.swagger GET ANY ANY /doc.json
|
||||||
|
-------------------------- -------- -------- ------ ------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WANTED CHANGES (seraf)
|
||||||
|
* -------------------------- -------- -------- ------ ------------------------------------------------
|
||||||
|
Name Method Scheme Host Path
|
||||||
|
-------------------------- -------- -------- ------ ------------------------------------------------
|
||||||
|
api_get_poll_comment GET ANY ANY /poll/{id}/comment
|
||||||
|
api_delete_poll_comments DELETE ANY ANY /poll/{id}/comment
|
||||||
|
api_user_polls_send_by_email GET ANY ANY /user/{email}/polls/send-by-email
|
||||||
|
api_get_user_polls GET ANY ANY /user/{email}/polls
|
||||||
|
api_get_poll_slug GET ANY ANY /poll/slug/{id}/{token}
|
||||||
|
api_clean_expired_polls GET ANY ANY /admin/clean-polls/{token}
|
||||||
|
|
||||||
|
api_test-mail-poll GET ANY ANY /poll/mail/test-mail-poll/{emailChoice}
|
||||||
|
api_update_vote_stack PATCH ANY ANY /vote-stack/{id}/token/{modifierToken}
|
||||||
|
-------------------------- -------- -------- ------ ------------------------------------------------
|
||||||
|
*/
|
12
package.json
12
package.json
@ -10,7 +10,6 @@
|
|||||||
"package": "cat dist/framadate/*.js > dist/framadate/framadate-scripts-bundled.js && ls -l dist/framadate",
|
"package": "cat dist/framadate/*.js > dist/framadate/framadate-scripts-bundled.js && ls -l dist/framadate",
|
||||||
"bld:pkg": "npm run build && npm run package",
|
"bld:pkg": "npm run build && npm run package",
|
||||||
"build:demo": "ng build --crossOrigin=anonymous --extractCss=true --progress=true --prod && npm run package",
|
"build:demo": "ng build --crossOrigin=anonymous --extractCss=true --progress=true --prod && npm run package",
|
||||||
"build:demobliss": "ng build --crossOrigin=anonymous --extractCss=true --baseHref=https://framadate-api.cipherbliss.com --progress=true --prod && npm run package",
|
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test:ci": "jest --runInBand",
|
"test:ci": "jest --runInBand",
|
||||||
@ -20,8 +19,7 @@
|
|||||||
"format:all": "prettier --write \"src/**/*.{js,jsx,ts,tsx,md,html,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",
|
"trans": "ng xi18n --output-path=src/locale --i18n-locale=fr",
|
||||||
"storybook": "start-storybook -p 6006",
|
"storybook": "start-storybook -p 6006",
|
||||||
"build-storybook": "build-storybook",
|
"build-storybook": "build-storybook"
|
||||||
"postinstall": "ngcc"
|
|
||||||
},
|
},
|
||||||
"private": false,
|
"private": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -39,13 +37,16 @@
|
|||||||
"@ngx-translate/core": "^12.1.2",
|
"@ngx-translate/core": "^12.1.2",
|
||||||
"@ngx-translate/http-loader": "^4.0.0",
|
"@ngx-translate/http-loader": "^4.0.0",
|
||||||
"angular-date-value-accessor": "^1.0.2",
|
"angular-date-value-accessor": "^1.0.2",
|
||||||
|
"axios": "^0.19.2",
|
||||||
"bulma": "^0.8.2",
|
"bulma": "^0.8.2",
|
||||||
"chart.js": "^2.8.0",
|
"chart.js": "^2.8.0",
|
||||||
|
"date-fns": "^2.12.0",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"jest-preset-angular": "^8.1.3",
|
"jest-preset-angular": "^8.1.3",
|
||||||
"karma-coverage": "^2.0.1",
|
"karma-coverage": "^2.0.1",
|
||||||
"karma-firefox-launcher": "^1.3.0",
|
"karma-firefox-launcher": "^1.3.0",
|
||||||
"karma-phantomjs-launcher": "^1.0.4",
|
"karma-phantomjs-launcher": "^1.0.4",
|
||||||
|
"locale-enum": "^1.1.0",
|
||||||
"ngx-clipboard": "^13.0.0",
|
"ngx-clipboard": "^13.0.0",
|
||||||
"ngx-markdown": "^9.0.0",
|
"ngx-markdown": "^9.0.0",
|
||||||
"ngx-toaster": "^1.0.1",
|
"ngx-toaster": "^1.0.1",
|
||||||
@ -55,6 +56,7 @@
|
|||||||
"rxjs": "^6.5.5",
|
"rxjs": "^6.5.5",
|
||||||
"rxjs-compat": "^6.5.5",
|
"rxjs-compat": "^6.5.5",
|
||||||
"tslib": "^1.11.1",
|
"tslib": "^1.11.1",
|
||||||
|
"uuid": "^7.0.3",
|
||||||
"zone.js": "^0.10.3"
|
"zone.js": "^0.10.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -72,6 +74,7 @@
|
|||||||
"@types/jasminewd2": "~2.0.8",
|
"@types/jasminewd2": "~2.0.8",
|
||||||
"@types/jest": "^25.2.1",
|
"@types/jest": "^25.2.1",
|
||||||
"@types/node": "^13.11.1",
|
"@types/node": "^13.11.1",
|
||||||
|
"@types/uuid": "^7.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.27.0",
|
"@typescript-eslint/eslint-plugin": "^2.27.0",
|
||||||
"@typescript-eslint/parser": "^2.27.0",
|
"@typescript-eslint/parser": "^2.27.0",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
@ -98,7 +101,8 @@
|
|||||||
"src/{app,environments,assets}/**/*.{js,jsx,ts,tsx,md,html,css,scss}": [
|
"src/{app,environments,assets}/**/*.{js,jsx,ts,tsx,md,html,css,scss}": [
|
||||||
"prettier --write",
|
"prettier --write",
|
||||||
"git add"
|
"git add"
|
||||||
]
|
],
|
||||||
|
"*.js": "eslint --cache --fix"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"preset": "jest-preset-angular",
|
"preset": "jest-preset-angular",
|
||||||
|
@ -3,20 +3,20 @@ import { RouterModule, Routes } from '@angular/router';
|
|||||||
|
|
||||||
import { AdminComponent } from './pages/admin/admin.component';
|
import { AdminComponent } from './pages/admin/admin.component';
|
||||||
import { AnswersComponent } from './pages/answers/answers.component';
|
import { AnswersComponent } from './pages/answers/answers.component';
|
||||||
import { BaseComponent } from './pages/base-page/base.component';
|
import { BaseComponent } from './pages/example/base-page/base.component';
|
||||||
import { CreateOrRetrieveComponent } from './pages/create-or-retrieve/create-or-retrieve.component';
|
import { CreateOrRetrieveComponent } from './pages/create-or-retrieve/create-or-retrieve.component';
|
||||||
import { DatesComponent } from './pages/dates/dates.component';
|
import { DatesComponent } from './pages/dates/dates.component';
|
||||||
import { EndConfirmationComponent } from './pages/end-confirmation/end-confirmation.component';
|
import { EndConfirmationComponent } from './pages/end-confirmation/end-confirmation.component';
|
||||||
import { HomeComponent } from './pages/home/home.component';
|
import { HomeComponent } from './pages/home/home.component';
|
||||||
import { KindComponent } from './pages/kind/kind.component';
|
import { KindComponent } from './pages/example/kind/kind.component';
|
||||||
import { PasswordComponent } from './pages/password/password.component';
|
import { PasswordComponent } from './pages/password/password.component';
|
||||||
import { PicturesComponent } from './pages/pictures/pictures.component';
|
import { PicturesComponent } from './pages/example/pictures/pictures.component';
|
||||||
import { PollDisplayComponent } from './pages/poll-display/poll-display.component';
|
import { PollDisplayComponent } from './pages/poll/poll-display/poll-display.component';
|
||||||
import { ResumeComponent } from './pages/resume/resume.component';
|
import { ResumeComponent } from './pages/resume/resume.component';
|
||||||
import { VisibilityComponent } from './pages/visibility/visibility.component';
|
import { VisibilityComponent } from './pages/visibility/visibility.component';
|
||||||
import { VotingChoiceComponent } from './pages/voting/voting-choice/voting-choice.component';
|
import { VotingChoiceComponent } from './pages/voting/voting-choice/voting-choice.component';
|
||||||
import { VotingComponent } from './pages/voting/voting.component';
|
import { VotingComponent } from './pages/voting/voting.component';
|
||||||
import { PollGraphicComponent } from './poll-graphic/poll-graphic.component';
|
import { PollGraphicComponent } from './pages/poll/poll-graphic/poll-graphic.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', redirectTo: 'step/creation', pathMatch: 'full' },
|
{ path: '', redirectTo: 'step/creation', pathMatch: 'full' },
|
||||||
|
@ -24,19 +24,19 @@ import { ToastModule } from 'primeng/toast';
|
|||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { DateValueAccessorModule } from './custom-lib/date-value-accessor';
|
import { DateValueAccessorModule } from './custom-lib/date-value-accessor';
|
||||||
import { DebuggerComponent } from './debugger/debugger.component';
|
import { DebuggerComponent } from './ui/debugger/debugger.component';
|
||||||
import { HeaderComponent } from './header/header.component';
|
import { HeaderComponent } from './ui/navigation/header/header.component';
|
||||||
import { AdminComponent } from './pages/admin/admin.component';
|
import { AdminComponent } from './pages/admin/admin.component';
|
||||||
import { AnswersComponent } from './pages/answers/answers.component';
|
import { AnswersComponent } from './pages/answers/answers.component';
|
||||||
import { BaseComponent } from './pages/base-page/base.component';
|
import { BaseComponent } from './pages/example/base-page/base.component';
|
||||||
import { CreateOrRetrieveComponent } from './pages/create-or-retrieve/create-or-retrieve.component';
|
import { CreateOrRetrieveComponent } from './pages/create-or-retrieve/create-or-retrieve.component';
|
||||||
import { DatesComponent } from './pages/dates/dates.component';
|
import { DatesComponent } from './pages/dates/dates.component';
|
||||||
import { EndConfirmationComponent } from './pages/end-confirmation/end-confirmation.component';
|
import { EndConfirmationComponent } from './pages/end-confirmation/end-confirmation.component';
|
||||||
import { HomeComponent } from './pages/home/home.component';
|
import { HomeComponent } from './pages/home/home.component';
|
||||||
import { KindComponent } from './pages/kind/kind.component';
|
import { KindComponent } from './pages/example/kind/kind.component';
|
||||||
import { PasswordComponent } from './pages/password/password.component';
|
import { PasswordComponent } from './pages/password/password.component';
|
||||||
import { PicturesComponent } from './pages/pictures/pictures.component';
|
import { PicturesComponent } from './pages/example/pictures/pictures.component';
|
||||||
import { PollDisplayComponent } from './pages/poll-display/poll-display.component';
|
import { PollDisplayComponent } from './pages/poll/poll-display/poll-display.component';
|
||||||
import { ResumeComponent } from './pages/resume/resume.component';
|
import { ResumeComponent } from './pages/resume/resume.component';
|
||||||
import { VisibilityComponent } from './pages/visibility/visibility.component';
|
import { VisibilityComponent } from './pages/visibility/visibility.component';
|
||||||
import { ChoicesListComponent } from './pages/voting/choices-list/choices-list.component';
|
import { ChoicesListComponent } from './pages/voting/choices-list/choices-list.component';
|
||||||
@ -47,9 +47,8 @@ import { VotingGraphComponent } from './pages/voting/voting-graph/voting-graph.c
|
|||||||
import { VotingNavigationComponent } from './pages/voting/voting-navigation/voting-navigation.component';
|
import { VotingNavigationComponent } from './pages/voting/voting-navigation/voting-navigation.component';
|
||||||
import { VotingSummaryComponent } from './pages/voting/voting-summary/voting-summary.component';
|
import { VotingSummaryComponent } from './pages/voting/voting-summary/voting-summary.component';
|
||||||
import { VotingComponent } from './pages/voting/voting.component';
|
import { VotingComponent } from './pages/voting/voting.component';
|
||||||
import { PollGraphicComponent } from './poll-graphic/poll-graphic.component';
|
import { PollGraphicComponent } from './pages/poll/poll-graphic/poll-graphic.component';
|
||||||
import { ConfigService } from './services/config.service';
|
import { ConfigService } from './services/config.service';
|
||||||
import { PollService } from './services/poll.service';
|
|
||||||
import { CopyTextComponent } from './ui/copy-text/copy-text.component';
|
import { CopyTextComponent } from './ui/copy-text/copy-text.component';
|
||||||
import { ResettableInputDirective } from './ui/directives/resettable-input.directive';
|
import { ResettableInputDirective } from './ui/directives/resettable-input.directive';
|
||||||
import { ErasableInputComponent } from './ui/erasable-input/erasable-input.component';
|
import { ErasableInputComponent } from './ui/erasable-input/erasable-input.component';
|
||||||
@ -57,7 +56,8 @@ import { MasterHeadComponent } from './ui/navigation/master-head/master-head.com
|
|||||||
import { NavigationComponent } from './ui/navigation/navigation.component';
|
import { NavigationComponent } from './ui/navigation/navigation.component';
|
||||||
import { LanguageComponent } from './ui/selector/language/language.component';
|
import { LanguageComponent } from './ui/selector/language/language.component';
|
||||||
import { SelectorComponent } from './ui/selector/selector.component';
|
import { SelectorComponent } from './ui/selector/selector.component';
|
||||||
import { ThemeSelectorComponent } from './ui/theme-selector/theme-selector.component';
|
import { ThemeSelectorComponent } from './ui/selector/theme-selector/theme-selector.component';
|
||||||
|
import { TwoLinksComponent } from './ui/navigation/two-links/two-links.component';
|
||||||
|
|
||||||
export class MyMissingTranslationHandler implements MissingTranslationHandler {
|
export class MyMissingTranslationHandler implements MissingTranslationHandler {
|
||||||
handle(params: MissingTranslationHandlerParams) {
|
handle(params: MissingTranslationHandlerParams) {
|
||||||
@ -107,6 +107,7 @@ export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
|
|||||||
ThemeSelectorComponent,
|
ThemeSelectorComponent,
|
||||||
MasterHeadComponent,
|
MasterHeadComponent,
|
||||||
LanguageComponent,
|
LanguageComponent,
|
||||||
|
TwoLinksComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
ConfirmDialogModule,
|
ConfirmDialogModule,
|
||||||
@ -135,7 +136,7 @@ export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
|
|||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
],
|
],
|
||||||
providers: [TranslateService, ConfigService, PollService, MessageService, ConfirmationService],
|
providers: [TranslateService, ConfigService, MessageService, ConfirmationService],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
@ -32,7 +32,7 @@ export class DateUtilities {
|
|||||||
});
|
});
|
||||||
d1.setDate(d1.getDate() + interval);
|
d1.setDate(d1.getDate() + interval);
|
||||||
}
|
}
|
||||||
return dates.slice(0);
|
return [...dates];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,8 +57,8 @@ export class PollConfig {
|
|||||||
customUrl = ''; // custom slug in the url, must be unique
|
customUrl = ''; // custom slug in the url, must be unique
|
||||||
customUrlIsUnique = null; // given by the backend
|
customUrlIsUnique = null; // given by the backend
|
||||||
urlSlugPublic = null;
|
urlSlugPublic = null;
|
||||||
urlPublic = environment.production ? '' : environment.baseHref + '/#/poll/id/4';
|
urlPublic = environment.production ? '' : window.location.origin + '/#/poll/id/4';
|
||||||
urlAdmin = environment.baseHref + '/#/admin/d65es45fd45sdf45sd345f312sdf31sgfd345';
|
urlAdmin = window.location.origin + '/#/admin/d65es45fd45sdf45sd345f312sdf31sgfd345';
|
||||||
adminKey = ''; // key to change config of the poll
|
adminKey = ''; // key to change config of the poll
|
||||||
owner_modifier_token = ''; // key to change a vote stack
|
owner_modifier_token = ''; // key to change a vote stack
|
||||||
canModifyAnswers = true; // bool for the frontend selector
|
canModifyAnswers = true; // bool for the frontend selector
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
/**
|
|
||||||
* each step in the form is a component
|
|
||||||
*/
|
|
||||||
export const Routes = [];
|
|
@ -1,24 +0,0 @@
|
|||||||
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,5 +1,5 @@
|
|||||||
import { AfterViewInit, ChangeDetectorRef, Component, Inject, OnChanges, OnInit } from '@angular/core';
|
import { AfterViewInit, ChangeDetectorRef, Component, Inject, OnChanges, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../example/base-page/base.component';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
|
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../example/base-page/base.component';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../example/base-page/base.component';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { MessageService } from 'primeng/api';
|
import { MessageService } from 'primeng/api';
|
||||||
import { otherDefaultDates } from '../../config/defaultConfigs';
|
import { otherDefaultDates } from '../../config/defaultConfigs';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../example/base-page/base.component';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
import { MessageService } from 'primeng/api';
|
import { MessageService } from 'primeng/api';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../../services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'framadate-base-page',
|
selector: 'framadate-base-page',
|
@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../base-page/base.component';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../../services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'framadate-page-kind',
|
selector: 'framadate-page-kind',
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../../services/config.service';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../base-page/base.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../example/base-page/base.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'framadate-home',
|
selector: 'framadate-home',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../example/base-page/base.component';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1 +0,0 @@
|
|||||||
@import '../../../assets/scss/variables';
|
|
@ -0,0 +1,8 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [CommonModule],
|
||||||
|
})
|
||||||
|
export class PollAdministrationModule {}
|
@ -0,0 +1 @@
|
|||||||
|
@import '../../../../assets/scss/variables';
|
@ -1,10 +1,10 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../../example/base-page/base.component';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../../services/config.service';
|
||||||
import { mockComments } from '../../config/mocks/mock-comments';
|
import { mockComments } from '../../../mocks/mock-comments';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { mockPoll3 } from '../../config/mocks/mock-poll3';
|
import { mockPoll3 } from '../../../mocks/mock-poll3';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'framadate-poll-display',
|
selector: 'framadate-poll-display',
|
@ -1,10 +1,9 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
import { Chart } from 'chart.js';
|
import { Chart } from 'chart.js';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { mockGraphConfig } from '../config/mocks/mock-graph';
|
import { mockGraphConfig } from '../../../mocks/mock-graph';
|
||||||
import { graphOptions } from '../config/graph-canevas-options';
|
import { ConfigService } from '../../../services/config.service';
|
||||||
import { ConfigService } from '../services/config.service';
|
import { mockPoll3 } from '../../../mocks/mock-poll3';
|
||||||
import { mockPoll3 } from '../config/mocks/mock-poll3';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'framadate-poll-graphic',
|
selector: 'framadate-poll-graphic',
|
||||||
@ -24,7 +23,7 @@ export class PollGraphicComponent implements OnInit {
|
|||||||
|
|
||||||
constructor(@Inject(DOCUMENT) private document: any, private config: ConfigService) {}
|
constructor(@Inject(DOCUMENT) private document: any, private config: ConfigService) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit(): void {
|
||||||
this.formatDataAnswers(this.graphicConfig);
|
this.formatDataAnswers(this.graphicConfig);
|
||||||
this.isColorblind = false;
|
this.isColorblind = false;
|
||||||
this.pollConfigRetrieved = new Chart(this.document.getElementById('graph'), {
|
this.pollConfigRetrieved = new Chart(this.document.getElementById('graph'), {
|
||||||
@ -52,15 +51,15 @@ export class PollGraphicComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
options: graphOptions,
|
options: this.getSettedGraphOptions(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleColorblind() {
|
public toggleColorblind(): void {
|
||||||
this.isColorblind = !this.isColorblind;
|
this.isColorblind = !this.isColorblind;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatDataAnswers(poll) {
|
public formatDataAnswers(poll): void {
|
||||||
// if (poll && poll.pollType === "date") {
|
// if (poll && poll.pollType === "date") {
|
||||||
this.initPollCounter();
|
this.initPollCounter();
|
||||||
poll.answers.forEach((response) => {
|
poll.answers.forEach((response) => {
|
||||||
@ -79,11 +78,34 @@ export class PollGraphicComponent implements OnInit {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
initPollCounter() {
|
public initPollCounter(): void {
|
||||||
this.nbPoll++;
|
this.nbPoll++;
|
||||||
this.dateList[this.nbPoll - 1] = 'jeudi';
|
this.dateList[this.nbPoll - 1] = 'jeudi';
|
||||||
this.maybeList[this.nbPoll - 1] = 0;
|
this.maybeList[this.nbPoll - 1] = 0;
|
||||||
this.yesList[this.nbPoll - 1] = 0;
|
this.yesList[this.nbPoll - 1] = 0;
|
||||||
this.noList[this.nbPoll - 1] = 0;
|
this.noList[this.nbPoll - 1] = 0;
|
||||||
}
|
}
|
||||||
|
private getSettedGraphOptions(): any {
|
||||||
|
// TODO: create interfaces, or find another way to work. "any" return type should be removed.
|
||||||
|
return {
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [CommonModule],
|
||||||
|
})
|
||||||
|
export class PollParticipationModule {}
|
@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../example/base-page/base.component';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@
|
|||||||
</sub>
|
</sub>
|
||||||
<div class="preview-url">
|
<div class="preview-url">
|
||||||
<a [href]="'/#/vote/poll/slug/' + config.customUrl">
|
<a [href]="'/#/vote/poll/slug/' + config.customUrl">
|
||||||
{{ environment.baseHref + '#/vote/poll/slug/' + config.customUrl }}
|
{{ window.location.origin + '#/vote/poll/slug/' + config.customUrl }}
|
||||||
</a>
|
</a>
|
||||||
<framadate-copy-text [textToCopy]="config.urlPublic"></framadate-copy-text>
|
<framadate-copy-text [textToCopy]="config.urlPublic"></framadate-copy-text>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../base-page/base.component';
|
import { BaseComponent } from '../example/base-page/base.component';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { PollUtilities } from '../../config/PollUtilities';
|
import { PollUtilities } from '../../config/PollUtilities';
|
||||||
@ -11,7 +11,7 @@ import { PollUtilities } from '../../config/PollUtilities';
|
|||||||
})
|
})
|
||||||
export class VisibilityComponent extends BaseComponent implements OnInit {
|
export class VisibilityComponent extends BaseComponent implements OnInit {
|
||||||
showCustomPassword = false;
|
showCustomPassword = false;
|
||||||
baseUrl = environment.baseApiHref;
|
baseUrl = environment.api.baseHref;
|
||||||
environment = environment;
|
environment = environment;
|
||||||
|
|
||||||
constructor(public config: ConfigService, public utils: PollUtilities) {
|
constructor(public config: ConfigService, public utils: PollUtilities) {
|
||||||
|
@ -7,8 +7,8 @@ import { ConfirmationService, MessageService } from 'primeng';
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { ConfigService } from '../../../services/config.service';
|
import { ConfigService } from '../../../services/config.service';
|
||||||
import { VotingChoiceComponent } from './voting-choice.component';
|
import { VotingChoiceComponent } from './voting-choice.component';
|
||||||
import { mockChoice } from '../../../config/mocks/choice';
|
import { mockChoice } from '../../../mocks/choice';
|
||||||
import { mockPoll3 } from '../../../config/mocks/mock-poll3';
|
import { mockPoll3 } from '../../../mocks/mock-poll3';
|
||||||
|
|
||||||
const routerSpy = jest.fn({ navigateByUrl: jest.fn() });
|
const routerSpy = jest.fn({ navigateByUrl: jest.fn() });
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { mockComments } from '../../../config/mocks/mock-comments';
|
import { mockComments } from '../../../mocks/mock-comments';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'framadate-voting-comment',
|
selector: 'framadate-voting-comment',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../../base-page/base.component';
|
import { BaseComponent } from '../../example/base-page/base.component';
|
||||||
import { ConfigService } from '../../../services/config.service';
|
import { ConfigService } from '../../../services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -113,7 +113,7 @@
|
|||||||
<button
|
<button
|
||||||
*ngIf="config.isAdmin"
|
*ngIf="config.isAdmin"
|
||||||
type="button"
|
type="button"
|
||||||
(click)="showModalDialog()"
|
(click)="toggleModalDialogVisibility()"
|
||||||
pButton
|
pButton
|
||||||
icon="pi pi-external-link"
|
icon="pi pi-external-link"
|
||||||
label="Show"
|
label="Show"
|
||||||
@ -121,7 +121,7 @@
|
|||||||
show admin confirmation modal
|
show admin confirmation modal
|
||||||
</button>
|
</button>
|
||||||
<p-dialog
|
<p-dialog
|
||||||
[(visible)]="config.displayConfirmVoteModalAdmin"
|
[visible]="displayConfirmVoteModalAdmin"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
[baseZIndex]="10000"
|
[baseZIndex]="10000"
|
||||||
[draggable]="false"
|
[draggable]="false"
|
||||||
@ -147,7 +147,7 @@
|
|||||||
type="button btn--large btn btn--block"
|
type="button btn--large btn btn--block"
|
||||||
pButton
|
pButton
|
||||||
icon="fa fa-check"
|
icon="fa fa-check"
|
||||||
(click)="config.displayConfirmVoteModalAdmin = false"
|
(click)="toggleModalDialogVisibility()"
|
||||||
label="Revenir au sondage"
|
label="Revenir au sondage"
|
||||||
class="btn btn--primary btn--default btn--purple btn--black-text"
|
class="btn btn--primary btn--default btn--purple btn--black-text"
|
||||||
></button>
|
></button>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { ConfigService } from '../../../services/config.service';
|
import { ConfigService } from '../../../services/config.service';
|
||||||
import { mockPoll3 } from '../../../config/mocks/mock-poll3';
|
import { mockPoll3 } from '../../../mocks/mock-poll3';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'framadate-voting-summary',
|
selector: 'framadate-voting-summary',
|
||||||
@ -8,14 +8,15 @@ import { mockPoll3 } from '../../../config/mocks/mock-poll3';
|
|||||||
styleUrls: ['./voting-summary.component.scss'],
|
styleUrls: ['./voting-summary.component.scss'],
|
||||||
})
|
})
|
||||||
export class VotingSummaryComponent implements OnInit {
|
export class VotingSummaryComponent implements OnInit {
|
||||||
preferred = 'rien';
|
public displayConfirmVoteModalAdmin = false;
|
||||||
severalPreferred = false;
|
public preferred = 'rien';
|
||||||
|
public severalPreferred = false;
|
||||||
|
|
||||||
@Input() pollconfig = mockPoll3;
|
@Input() pollconfig = mockPoll3;
|
||||||
|
|
||||||
constructor(public config: ConfigService) {}
|
constructor(public config: ConfigService) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit(): void {
|
||||||
this.computePreferred();
|
this.computePreferred();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ export class VotingSummaryComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
showModalDialog() {
|
toggleModalDialogVisibility(): void {
|
||||||
this.config.displayConfirmVoteModalAdmin = true;
|
this.displayConfirmVoteModalAdmin = !this.displayConfirmVoteModalAdmin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ import { HttpClient } from '@angular/common/http';
|
|||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { ConfirmationService, MessageService } from 'primeng/api';
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { mockMyPolls } from '../config/mocks/mockmypolls';
|
import { mockMyPolls } from '../mocks/mockmypolls';
|
||||||
import { mockPoll3 } from '../config/mocks/mock-poll3';
|
import { mockPoll3 } from '../mocks/mock-poll3';
|
||||||
import { mockSuccessVote } from '../config/mocks/mock-success-vote';
|
import { mockSuccessVote } from '../mocks/mock-success-vote';
|
||||||
import { PollUtilities } from '../config/PollUtilities';
|
import { PollUtilities } from '../config/PollUtilities';
|
||||||
|
|
||||||
const LocalstoragePreferences = {
|
const LocalstoragePreferences = {
|
||||||
@ -25,7 +25,7 @@ const LocalstoragePreferences = {
|
|||||||
export class ConfigService extends PollConfig {
|
export class ConfigService extends PollConfig {
|
||||||
preferences: any = LocalstoragePreferences; // user specific preferences, stored in localstorage, used for theme.
|
preferences: any = LocalstoragePreferences; // user specific preferences, stored in localstorage, used for theme.
|
||||||
loading = false;
|
loading = false;
|
||||||
baseHref: any = environment.baseApiHref;
|
apiBaseHref: any = environment.api.baseHref;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
@ -148,7 +148,7 @@ export class ConfigService extends PollConfig {
|
|||||||
// TODO
|
// TODO
|
||||||
this.todo('check slug is unique');
|
this.todo('check slug is unique');
|
||||||
this.http
|
this.http
|
||||||
.get(`${this.baseHref}/check-slug-is-uniq/${slug}`, this.utils.makeHeaders({ slug: this.customUrl }))
|
.get(`${this.apiBaseHref}/check-slug-is-uniq/${slug}`, this.utils.makeHeaders({ slug: this.customUrl }))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
this.customUrlIsUnique = res.poll.isUnique;
|
this.customUrlIsUnique = res.poll.isUnique;
|
||||||
@ -170,7 +170,7 @@ export class ConfigService extends PollConfig {
|
|||||||
|
|
||||||
this.todo('send email for real : TODO');
|
this.todo('send email for real : TODO');
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.http.get(`${this.baseHref}/send-polls-to-user/${this.myEmail}`, this.utils.makeHeaders()).subscribe(
|
this.http.get(`${this.apiBaseHref}/send-polls-to-user/${this.myEmail}`, this.utils.makeHeaders()).subscribe(
|
||||||
(res) => {
|
(res) => {
|
||||||
// message: 'Trouvé! Allez voir votre boite email',
|
// message: 'Trouvé! Allez voir votre boite email',
|
||||||
this.myPolls = res;
|
this.myPolls = res;
|
||||||
@ -211,7 +211,7 @@ export class ConfigService extends PollConfig {
|
|||||||
*/
|
*/
|
||||||
getPollByURL(url: string) {
|
getPollByURL(url: string) {
|
||||||
this.todo();
|
this.todo();
|
||||||
return this.http.get(`${this.baseHref}/poll/slug/${url}`, this.utils.makeHeaders());
|
return this.http.get(`${this.apiBaseHref}/poll/slug/${url}`, this.utils.makeHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,7 +220,7 @@ export class ConfigService extends PollConfig {
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
getPollById(id: string, password?: string) {
|
getPollById(id: string, password?: string) {
|
||||||
return this.http.get(`${this.baseHref}/poll/${id}`, this.utils.makeHeaders({ body: password }));
|
return this.http.get(`${this.apiBaseHref}/poll/${id}`, this.utils.makeHeaders({ body: password }));
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchPollFromRoute(event) {
|
fetchPollFromRoute(event) {
|
||||||
@ -233,7 +233,7 @@ export class ConfigService extends PollConfig {
|
|||||||
* @param ownerEmail
|
* @param ownerEmail
|
||||||
*/
|
*/
|
||||||
getMyPolls(ownerEmail: string) {
|
getMyPolls(ownerEmail: string) {
|
||||||
this.http.get(`${this.baseHref}/my-polls`, this.utils.makeHeaders({ ownerEmail })).subscribe(
|
this.http.get(`${this.apiBaseHref}/my-polls`, this.utils.makeHeaders({ ownerEmail })).subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
// this.myPolls = res.poll;
|
// this.myPolls = res.poll;
|
||||||
},
|
},
|
||||||
@ -256,16 +256,16 @@ export class ConfigService extends PollConfig {
|
|||||||
this.currentPoll = res;
|
this.currentPoll = res;
|
||||||
this.pollId = res.poll.id;
|
this.pollId = res.poll.id;
|
||||||
this.owner_modifier_token = res.owner_modifier_token;
|
this.owner_modifier_token = res.owner_modifier_token;
|
||||||
this.urlPublic = this.baseHref + '#/vote/poll/id/' + res.poll.id;
|
this.urlPublic = this.apiBaseHref + '#/vote/poll/id/' + res.poll.id;
|
||||||
this.urlSlugPublic = this.baseHref + '#/vote/poll/slug/' + res.poll.id;
|
this.urlSlugPublic = this.apiBaseHref + '#/vote/poll/slug/' + res.poll.id;
|
||||||
if (res.poll.customUrl) {
|
if (res.poll.customUrl) {
|
||||||
this.urlSlugPublic = this.baseHref + '#/vote/poll/id/' + res.poll.customUrl;
|
this.urlSlugPublic = this.apiBaseHref + '#/vote/poll/id/' + res.poll.customUrl;
|
||||||
}
|
}
|
||||||
if (res.vote_stack) {
|
if (res.vote_stack) {
|
||||||
this.loadVoteStack(res.vote_stack);
|
this.loadVoteStack(res.vote_stack);
|
||||||
}
|
}
|
||||||
this.adminKey = res.admin_key;
|
this.adminKey = res.admin_key;
|
||||||
this.urlAdmin = this.baseHref + '#/admin/' + res.admin_key;
|
this.urlAdmin = this.apiBaseHref + '#/admin/' + res.admin_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
resetCurrentChoicesAnswers() {
|
resetCurrentChoicesAnswers() {
|
||||||
@ -312,7 +312,7 @@ export class ConfigService extends PollConfig {
|
|||||||
createPollFromConfig(config: any) {
|
createPollFromConfig(config: any) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
console.log('config', config);
|
console.log('config', config);
|
||||||
return this.http.post(`${this.baseHref}/poll`, config, this.utils.makeHeaders()).subscribe(
|
return this.http.post(`${this.apiBaseHref}/poll`, config, this.utils.makeHeaders()).subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
// redirect to the page to administrate the new poll
|
// redirect to the page to administrate the new poll
|
||||||
this.messageService.add({ severity: 'success', summary: 'Sondage Créé' });
|
this.messageService.add({ severity: 'success', summary: 'Sondage Créé' });
|
||||||
@ -372,7 +372,7 @@ export class ConfigService extends PollConfig {
|
|||||||
this.handleVoteAdded(mockSuccessVote);
|
this.handleVoteAdded(mockSuccessVote);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.http.post(`${this.baseHref}/poll/${this.pollId}/vote`, voteStack, this.utils.makeHeaders()).subscribe(
|
this.http.post(`${this.apiBaseHref}/poll/${this.pollId}/vote`, voteStack, this.utils.makeHeaders()).subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
this.handleVoteAdded(res);
|
this.handleVoteAdded(res);
|
||||||
},
|
},
|
||||||
@ -384,7 +384,8 @@ export class ConfigService extends PollConfig {
|
|||||||
|
|
||||||
handleVoteAdded(res) {
|
handleVoteAdded(res) {
|
||||||
if (this.isAdmin) {
|
if (this.isAdmin) {
|
||||||
this.displayConfirmVoteModalAdmin = true;
|
// TODO : REFACTO, displayConfirmVoteModalAdmin exists only in voting-summary.component
|
||||||
|
//this.displayConfirmVoteModalAdmin = true;
|
||||||
}
|
}
|
||||||
// save modifier token
|
// save modifier token
|
||||||
this.myVoteStack.modifier_token = res.modifier_token;
|
this.myVoteStack.modifier_token = res.modifier_token;
|
||||||
@ -405,7 +406,7 @@ export class ConfigService extends PollConfig {
|
|||||||
}
|
}
|
||||||
this.http
|
this.http
|
||||||
.patch(
|
.patch(
|
||||||
`${this.baseHref}/vote-stack/${voteStack.id}/token/${this.owner_modifier_token}`,
|
`${this.apiBaseHref}/vote-stack/${voteStack.id}/token/${this.owner_modifier_token}`,
|
||||||
voteStack,
|
voteStack,
|
||||||
this.utils.makeHeaders()
|
this.utils.makeHeaders()
|
||||||
)
|
)
|
||||||
@ -436,7 +437,7 @@ export class ConfigService extends PollConfig {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
console.log('comment', comment);
|
console.log('comment', comment);
|
||||||
this.http.post(`${this.baseHref}/poll/${this.pollId}/comment`, comment, this.utils.makeHeaders()).subscribe(
|
this.http.post(`${this.apiBaseHref}/poll/${this.pollId}/comment`, comment, this.utils.makeHeaders()).subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
this.messageService.add({
|
this.messageService.add({
|
||||||
severity: 'success',
|
severity: 'success',
|
||||||
@ -468,18 +469,20 @@ export class ConfigService extends PollConfig {
|
|||||||
this.title +
|
this.title +
|
||||||
') permanentely?',
|
') permanentely?',
|
||||||
accept: () => {
|
accept: () => {
|
||||||
this.http.delete(`${this.baseHref}/poll/${this.pollId}/comments`, this.utils.makeHeaders()).subscribe(
|
this.http
|
||||||
(res: any) => {
|
.delete(`${this.apiBaseHref}/poll/${this.pollId}/comments`, this.utils.makeHeaders())
|
||||||
this.messageService.add({
|
.subscribe(
|
||||||
severity: 'success',
|
(res: any) => {
|
||||||
summary: 'Commentaires bien supprimés',
|
this.messageService.add({
|
||||||
detail: 'Commentaires du sondage "' + this.title + '" supprimé',
|
severity: 'success',
|
||||||
});
|
summary: 'Commentaires bien supprimés',
|
||||||
},
|
detail: 'Commentaires du sondage "' + this.title + '" supprimé',
|
||||||
(e) => {
|
});
|
||||||
this.handleError(e);
|
},
|
||||||
}
|
(e) => {
|
||||||
);
|
this.handleError(e);
|
||||||
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -492,7 +495,7 @@ export class ConfigService extends PollConfig {
|
|||||||
this.title +
|
this.title +
|
||||||
') permanentely?',
|
') permanentely?',
|
||||||
accept: () => {
|
accept: () => {
|
||||||
this.http.delete(`${this.baseHref}/poll/${this.pollId}/votes`, this.utils.makeHeaders()).subscribe(
|
this.http.delete(`${this.apiBaseHref}/poll/${this.pollId}/votes`, this.utils.makeHeaders()).subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
this.messageService.add({
|
this.messageService.add({
|
||||||
severity: 'success',
|
severity: 'success',
|
||||||
@ -524,7 +527,7 @@ export class ConfigService extends PollConfig {
|
|||||||
self.title +
|
self.title +
|
||||||
') and all is data permanentely?',
|
') and all is data permanentely?',
|
||||||
accept: () => {
|
accept: () => {
|
||||||
this.http.delete(`${this.baseHref}/poll/${this.pollId}`, this.utils.makeHeaders()).subscribe(
|
this.http.delete(`${this.apiBaseHref}/poll/${this.pollId}`, this.utils.makeHeaders()).subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
this.messageService.add({
|
this.messageService.add({
|
||||||
severity: 'success',
|
severity: 'success',
|
||||||
@ -549,7 +552,7 @@ export class ConfigService extends PollConfig {
|
|||||||
* TODO
|
* TODO
|
||||||
*/
|
*/
|
||||||
updatePoll(voteStack: any) {
|
updatePoll(voteStack: any) {
|
||||||
this.http.put(`${this.baseHref}/poll/${this.pollId}`, voteStack, this.utils.makeHeaders()).subscribe(
|
this.http.put(`${this.apiBaseHref}/poll/${this.pollId}`, voteStack, this.utils.makeHeaders()).subscribe(
|
||||||
(res: any) => {
|
(res: any) => {
|
||||||
this.messageService.add({
|
this.messageService.add({
|
||||||
severity: 'success',
|
severity: 'success',
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { environment } from '../../environments/environment';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class PollService {
|
|
||||||
private baseHref: string = environment.baseApiHref;
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { ConfigService } from './config.service';
|
|
||||||
|
|
||||||
describe('ConfigService', () => {
|
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
const service: ConfigService = TestBed.get(ConfigService);
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
4
src/app/shared/enums/answer-granularity.enum.ts
Normal file
4
src/app/shared/enums/answer-granularity.enum.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export enum AnswerGranularity {
|
||||||
|
BASIC = 'BASIC',
|
||||||
|
COMPLEX = 'COMPLEX',
|
||||||
|
}
|
5
src/app/shared/enums/answer-type.enum.ts
Normal file
5
src/app/shared/enums/answer-type.enum.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum AnswerType {
|
||||||
|
YES = 'YES',
|
||||||
|
NO = 'NO',
|
||||||
|
MAYBE = 'MAYBE',
|
||||||
|
}
|
4
src/app/shared/enums/poll-type.enum.ts
Normal file
4
src/app/shared/enums/poll-type.enum.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export enum PollType {
|
||||||
|
CLASSIC = 'CLASSIC',
|
||||||
|
DATES = 'DATES',
|
||||||
|
}
|
5
src/app/shared/enums/theme.enum.ts
Normal file
5
src/app/shared/enums/theme.enum.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum Theme {
|
||||||
|
LIGHT = 'light-watermelon',
|
||||||
|
DARK = 'dark-crystal',
|
||||||
|
RED = 'hot-covid',
|
||||||
|
}
|
5
src/app/shared/interfaces/date-options.interface.ts
Normal file
5
src/app/shared/interfaces/date-options.interface.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface DateOption {
|
||||||
|
timeList: any;
|
||||||
|
literal: string;
|
||||||
|
date_object?: object;
|
||||||
|
}
|
6
src/app/shared/models/answer.model.ts
Normal file
6
src/app/shared/models/answer.model.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { AnswerType } from '../enums/answer-type.enum';
|
||||||
|
import { PollOption } from './poll-options.model';
|
||||||
|
|
||||||
|
export class Answer {
|
||||||
|
constructor(public pollOption: PollOption, public type: AnswerType, public userPseudo: string) {}
|
||||||
|
}
|
13
src/app/shared/models/poll-config.model.ts
Normal file
13
src/app/shared/models/poll-config.model.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { AnswerGranularity } from '../enums/answer-granularity.enum';
|
||||||
|
|
||||||
|
export class PollConfig {
|
||||||
|
constructor(
|
||||||
|
public allowSeveralHours = true,
|
||||||
|
public isVisibleToAnyoneWithTheLink: boolean = true,
|
||||||
|
public answerType: AnswerGranularity = AnswerGranularity.BASIC,
|
||||||
|
public creationDate: Date = new Date(),
|
||||||
|
public expirationDate?: Date,
|
||||||
|
public canVotersModifyTheirAnswers = true,
|
||||||
|
public isProtectedByPassword: boolean = false
|
||||||
|
) {}
|
||||||
|
}
|
9
src/app/shared/models/poll-options.model.ts
Normal file
9
src/app/shared/models/poll-options.model.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { isValid } from 'date-fns';
|
||||||
|
|
||||||
|
export class PollOption {
|
||||||
|
constructor(public label: string, public url?: string, public subOptions?: PollOption[]) {}
|
||||||
|
|
||||||
|
public isDatePoll(): boolean {
|
||||||
|
return isValid(this.label);
|
||||||
|
}
|
||||||
|
}
|
19
src/app/shared/models/poll.model.ts
Normal file
19
src/app/shared/models/poll.model.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { PollType } from '../enums/poll-type.enum';
|
||||||
|
import { Answer } from './answer.model';
|
||||||
|
import { PollConfig } from './poll-config.model';
|
||||||
|
import { PollOption } from './poll-options.model';
|
||||||
|
import { User } from './user.model';
|
||||||
|
|
||||||
|
export class Poll {
|
||||||
|
constructor(
|
||||||
|
public id: string,
|
||||||
|
public slug: string,
|
||||||
|
public type: PollType,
|
||||||
|
public title: string,
|
||||||
|
public description: string,
|
||||||
|
public owner: User,
|
||||||
|
public config: PollConfig,
|
||||||
|
public options: PollOption[] = [],
|
||||||
|
public answers: Answer[] = []
|
||||||
|
) {}
|
||||||
|
}
|
5
src/app/shared/models/ui-config.model.ts
Normal file
5
src/app/shared/models/ui-config.model.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { Theme } from '../enums/theme.enum';
|
||||||
|
|
||||||
|
export class UIConfig {
|
||||||
|
constructor(public isMenuVisible = true, public theme: Theme.LIGHT) {}
|
||||||
|
}
|
10
src/app/shared/models/user.model.ts
Normal file
10
src/app/shared/models/user.model.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Poll } from './poll.model';
|
||||||
|
|
||||||
|
export class User {
|
||||||
|
constructor(
|
||||||
|
public isOwner: boolean = false,
|
||||||
|
public pseudo?: string,
|
||||||
|
public email?: string,
|
||||||
|
public polls?: Poll[]
|
||||||
|
) {}
|
||||||
|
}
|
16
src/app/shared/services/api.service.spec.ts
Normal file
16
src/app/shared/services/api.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ApiService } from './api.service';
|
||||||
|
|
||||||
|
describe('ApiService', () => {
|
||||||
|
let service: ApiService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(ApiService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
195
src/app/shared/services/api.service.ts
Normal file
195
src/app/shared/services/api.service.ts
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import axios, { AxiosResponse } from 'axios';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
|
||||||
|
import { Poll } from '../models/poll.model';
|
||||||
|
import { User } from '../models/user.model';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class ApiService {
|
||||||
|
////////////
|
||||||
|
// CREATE //
|
||||||
|
////////////
|
||||||
|
public async savePoll(poll: Poll): Promise<void> {
|
||||||
|
try {
|
||||||
|
await axios.post(`${environment.api.baseHref}${environment.api.endpoints.poll.name}`, {
|
||||||
|
params: { config: poll.config },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async saveVote(poll: Poll): Promise<void> {
|
||||||
|
try {
|
||||||
|
// TODO: add the votestack in the params
|
||||||
|
await axios.post(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.poll.name}/${poll.id}${environment.api.endpoints.poll.vote.name}`,
|
||||||
|
{ params: { voteStack: {} } }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async saveComment(poll: Poll, comment: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
// TODO: add the comment in the params
|
||||||
|
await axios.post(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.poll.name}/${poll.id}${environment.api.endpoints.poll.comment.name}`,
|
||||||
|
{ params: { comment } }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// READ //
|
||||||
|
//////////
|
||||||
|
public async isSlugAvailable(slug: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
// TODO: scenario should be : if we can get this slug, it exists. if not, it doesn't. It's just a GET.
|
||||||
|
const response: AxiosResponse = await axios.get(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.poll.slug.name}/${slug}`
|
||||||
|
);
|
||||||
|
return response && response.status === 404 ? true : false;
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async sendEmailToUserOfItsPollsList(email: string): Promise<Poll[]> {
|
||||||
|
// If user is not authenticated: the list of polls is send to user's email by the backend.
|
||||||
|
try {
|
||||||
|
const response: AxiosResponse<Poll[]> = await axios.get<Poll[]>(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.user.polls.sendEmail.name}/${email}`
|
||||||
|
);
|
||||||
|
return response ? response.data : [];
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getPollsByUserEmail(user: User): Promise<Poll[]> {
|
||||||
|
// If user is authenticated : retrieve polls & display directly in frontend.
|
||||||
|
// TODO: Backend should handle this case. Actually the endpoint doesn't exist in backend.
|
||||||
|
try {
|
||||||
|
const response: AxiosResponse<Poll[]> = await axios.get<Poll[]>(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.user.polls.name}/${user.email}`
|
||||||
|
);
|
||||||
|
return response ? response.data : [];
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getPollsByUrl(url: string): Promise<Poll[]> {
|
||||||
|
try {
|
||||||
|
const response: AxiosResponse<Poll[]> = await axios.get<Poll[]>(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.poll.name}/${url}`
|
||||||
|
);
|
||||||
|
return response ? response.data : [];
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getPollById(id: string, password?: string): Promise<Poll[]> {
|
||||||
|
try {
|
||||||
|
const response: AxiosResponse<Poll[]> = await axios.get<Poll[]>(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.poll.name}/${id}`,
|
||||||
|
password ? { params: { password } } : {}
|
||||||
|
);
|
||||||
|
return response ? response.data : [];
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
// UPDATE //
|
||||||
|
////////////
|
||||||
|
public async updatePoll(poll: Poll): Promise<void> {
|
||||||
|
try {
|
||||||
|
// TODO: implement the params when entities are finalized.
|
||||||
|
await axios.put(`${environment.api.baseHref}${environment.api.endpoints.poll.name}/${poll.id}`, {
|
||||||
|
params: { voteStack: {}, token: '' },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateVote(voteStack: any): Promise<void> {
|
||||||
|
try {
|
||||||
|
// TODO: implement the params when entities are finalized.
|
||||||
|
await axios.patch(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.poll.vote.name}/${voteStack.id}`,
|
||||||
|
{
|
||||||
|
params: { voteStack: {}, token: '' },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
// DELETE //
|
||||||
|
////////////
|
||||||
|
|
||||||
|
public async deletePoll(poll: Poll): Promise<void> {
|
||||||
|
try {
|
||||||
|
await axios.delete(`${environment.api.baseHref}${environment.api.endpoints.poll.name}${poll.id}`, {});
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deletePollVotes(poll: Poll): Promise<void> {
|
||||||
|
try {
|
||||||
|
// TODO: update endpoint in Backend
|
||||||
|
await axios.delete(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.poll.name}${poll.id}${environment.api.endpoints.poll.vote.name}`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deletePollComments(poll: Poll): Promise<void> {
|
||||||
|
try {
|
||||||
|
// TODO: modify endpoint in Backend
|
||||||
|
await axios.delete(
|
||||||
|
`${environment.api.baseHref}${environment.api.endpoints.poll.name}${poll.id}${environment.api.endpoints.poll.comment.name}`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
// PRIVATE METHODS //
|
||||||
|
/////////////////////
|
||||||
|
private handleError(error): void {
|
||||||
|
if (error.response) {
|
||||||
|
// The request was made and the server responded with a status code
|
||||||
|
// that falls out of the range of 2xx
|
||||||
|
console.log(error.response.data);
|
||||||
|
console.log(error.response.status);
|
||||||
|
console.log(error.response.headers);
|
||||||
|
} else if (error.request) {
|
||||||
|
// The request was made but no response was received
|
||||||
|
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||||
|
// http.ClientRequest in node.js
|
||||||
|
console.log(error.request);
|
||||||
|
} else {
|
||||||
|
// Something happened in setting up the request that triggered an Error
|
||||||
|
console.log('Error', error.message);
|
||||||
|
}
|
||||||
|
console.log(error.config);
|
||||||
|
}
|
||||||
|
}
|
16
src/app/shared/services/comment.service.spec.ts
Normal file
16
src/app/shared/services/comment.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CommentService } from './comment.service';
|
||||||
|
|
||||||
|
describe('CommentService', () => {
|
||||||
|
let service: CommentService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(CommentService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
15
src/app/shared/services/comment.service.ts
Normal file
15
src/app/shared/services/comment.service.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { Poll } from '../models/poll.model';
|
||||||
|
import { ApiService } from './api.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class CommentService {
|
||||||
|
constructor(private apiService: ApiService) {}
|
||||||
|
|
||||||
|
public saveComment(poll: Poll, comment: string): void {
|
||||||
|
this.apiService.saveComment(poll, comment);
|
||||||
|
}
|
||||||
|
}
|
16
src/app/shared/services/date-utils.service.spec.ts
Normal file
16
src/app/shared/services/date-utils.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DateUtilsService } from './date-utils.service';
|
||||||
|
|
||||||
|
describe('DateUtilsService', () => {
|
||||||
|
let service: DateUtilsService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(DateUtilsService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
50
src/app/shared/services/date-utils.service.ts
Normal file
50
src/app/shared/services/date-utils.service.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { addDays, differenceInDays, format } from 'date-fns';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class DateUtilsService {
|
||||||
|
public static addDaysToDate(days: number, date: Date): Date {
|
||||||
|
return addDays(date, days);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static diffInDays(dateLeft: Date, dateRight: Date): number {
|
||||||
|
return differenceInDays(dateLeft, dateRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static formatDate(date): string {
|
||||||
|
return format(date, 'yyyy-MM-dd');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static orderDates(): Date[] {
|
||||||
|
// TODO: to implement
|
||||||
|
const datesOrdered: Date[] = [];
|
||||||
|
return datesOrdered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getDatesInRange(d1: Date, d2: Date, interval: number): Date[] {
|
||||||
|
// TODO: refacto this
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getDoubleDigits(str: string): string {
|
||||||
|
// TODO: ça sert à quoi ça ?
|
||||||
|
// Parce que ajouter 2 caractère à une string et ensuite slicer à partir du 2ème caractère, euh…
|
||||||
|
return ('00' + str).slice(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private isInChronologicalOrder(date1: Date, date2: Date): boolean {
|
||||||
|
return date1 < date2;
|
||||||
|
}
|
||||||
|
}
|
16
src/app/shared/services/poll-utils.service.spec.ts
Normal file
16
src/app/shared/services/poll-utils.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PollUtilsService } from './poll-utils.service';
|
||||||
|
|
||||||
|
describe('PollUtilsService', () => {
|
||||||
|
let service: PollUtilsService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(PollUtilsService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
47
src/app/shared/services/poll-utils.service.ts
Normal file
47
src/app/shared/services/poll-utils.service.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class PollUtilsService {
|
||||||
|
public makeUuid(): string {
|
||||||
|
// TODO: how to be sure the uuid generated in front is available in backend ?
|
||||||
|
// It could be a better way to generate uuids in backend.
|
||||||
|
return uuidv4();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* make a uniq slug for the current poll creation
|
||||||
|
* @param str
|
||||||
|
*/
|
||||||
|
public makeSlug(config: PollConfig): string {
|
||||||
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
@ -2,11 +2,15 @@ import { TestBed } from '@angular/core/testing';
|
|||||||
|
|
||||||
import { PollService } from './poll.service';
|
import { PollService } from './poll.service';
|
||||||
|
|
||||||
describe('PollServiceService', () => {
|
describe('PollService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({}));
|
let service: PollService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(PollService);
|
||||||
|
});
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
const service: PollService = TestBed.get(PollService);
|
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
42
src/app/shared/services/poll.service.ts
Normal file
42
src/app/shared/services/poll.service.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { Poll } from '../models/poll.model';
|
||||||
|
import { ApiService } from './api.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class PollService {
|
||||||
|
private _poll: BehaviorSubject<Poll | undefined> = new BehaviorSubject<Poll | undefined>(undefined);
|
||||||
|
|
||||||
|
constructor(private apiService: ApiService) {}
|
||||||
|
|
||||||
|
public get poll(): Observable<Poll | undefined> {
|
||||||
|
return this._poll.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateCurrentPoll(poll: Poll): void {
|
||||||
|
this._poll.next(poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
public savePoll(poll: Poll): void {
|
||||||
|
this.apiService.savePoll(poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveVote(poll: Poll): void {
|
||||||
|
this.apiService.saveVote(poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveComment(poll: Poll, comment: string): void {
|
||||||
|
this.apiService.saveComment(poll, comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public deletePollVotes(poll: Poll): void {
|
||||||
|
this.apiService.deletePollVotes(poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
public deletePollComments(poll: Poll): void {
|
||||||
|
this.apiService.deletePollComments(poll);
|
||||||
|
}
|
||||||
|
}
|
16
src/app/shared/services/theme.service.spec.ts
Normal file
16
src/app/shared/services/theme.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ThemeService } from './theme.service';
|
||||||
|
|
||||||
|
describe('ThemeService', () => {
|
||||||
|
let service: ThemeService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(ThemeService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
8
src/app/shared/services/theme.service.ts
Normal file
8
src/app/shared/services/theme.service.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class ThemeService {
|
||||||
|
constructor() {}
|
||||||
|
}
|
16
src/app/shared/services/user.service.spec.ts
Normal file
16
src/app/shared/services/user.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
|
describe('UserService', () => {
|
||||||
|
let service: UserService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(UserService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
19
src/app/shared/services/user.service.ts
Normal file
19
src/app/shared/services/user.service.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { User } from '../models/user.model';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class UserService {
|
||||||
|
private _user: BehaviorSubject<User | undefined> = new BehaviorSubject<User | undefined>(undefined);
|
||||||
|
|
||||||
|
public get user(): Observable<User | undefined> {
|
||||||
|
return this._user.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateUser(user: User): void {
|
||||||
|
this._user.next(user);
|
||||||
|
}
|
||||||
|
}
|
16
src/app/shared/services/vote.service.spec.ts
Normal file
16
src/app/shared/services/vote.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { VoteService } from './vote.service';
|
||||||
|
|
||||||
|
describe('VoteService', () => {
|
||||||
|
let service: VoteService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(VoteService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
17
src/app/shared/services/vote.service.ts
Normal file
17
src/app/shared/services/vote.service.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ApiService } from './api.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class VoteService {
|
||||||
|
constructor(private apiService: ApiService) {}
|
||||||
|
|
||||||
|
public saveVote(vote: any): void {
|
||||||
|
this.apiService.saveVote(vote);
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateVote(vote: any): void {
|
||||||
|
this.apiService.updateVote(vote);
|
||||||
|
}
|
||||||
|
}
|
8
src/app/shared/shared.module.ts
Normal file
8
src/app/shared/shared.module.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [CommonModule],
|
||||||
|
})
|
||||||
|
export class SharedModule {}
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ConfigService } from '../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'framadate-debugger',
|
selector: 'framadate-debugger',
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { BaseComponent } from '../../pages/base-page/base.component';
|
import { BaseComponent } from '../../pages/example/base-page/base.component';
|
||||||
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { ConfigService } from '../../services/config.service';
|
import { ConfigService } from '../../services/config.service';
|
||||||
|
8
src/app/ui/navigation/two-links/two-links.component.html
Normal file
8
src/app/ui/navigation/two-links/two-links.component.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<div class="two-links">
|
||||||
|
<a [routerLink]="nextRouteConfig" class="next">
|
||||||
|
C'est parfait!
|
||||||
|
</a>
|
||||||
|
<a [routerLink]="previousRouteConfig" class="prev">
|
||||||
|
Retour
|
||||||
|
</a>
|
||||||
|
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user