mirror of
https://framagit.org/framasoft/framadate/funky-framadate-front.git
synced 2023-08-25 13:53:14 +02:00
add user settings button & modal
This commit is contained in:
parent
4f0a29e806
commit
355fed53f3
@ -28,6 +28,7 @@
|
|||||||
"node_modules/primeicons/primeicons.css",
|
"node_modules/primeicons/primeicons.css",
|
||||||
"node_modules/primeng/resources/themes/nova-light/theme.css",
|
"node_modules/primeng/resources/themes/nova-light/theme.css",
|
||||||
"node_modules/primeng/resources/primeng.min.css",
|
"node_modules/primeng/resources/primeng.min.css",
|
||||||
|
"node_modules/primeflex/primeflex.css",
|
||||||
"src/styles.scss"
|
"src/styles.scss"
|
||||||
],
|
],
|
||||||
"scripts": [
|
"scripts": [
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
"ngx-clipboard": "^13.0.0",
|
"ngx-clipboard": "^13.0.0",
|
||||||
"ngx-markdown": "^9.0.0",
|
"ngx-markdown": "^9.0.0",
|
||||||
"ngx-webstorage": "^5.0.0",
|
"ngx-webstorage": "^5.0.0",
|
||||||
|
"primeflex": "^1.0.0",
|
||||||
"primeicons": "^2.0.0",
|
"primeicons": "^2.0.0",
|
||||||
"primeng": "^9.0.6",
|
"primeng": "^9.0.6",
|
||||||
"quill": "^1.3.7",
|
"quill": "^1.3.7",
|
||||||
@ -67,12 +68,12 @@
|
|||||||
"@types/uuid": "^7.0.2",
|
"@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-jest": "^25.4.0",
|
"babel-jest": "^26.0.0",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-config-prettier": "^6.11.0",
|
"eslint-config-prettier": "^6.11.0",
|
||||||
"eslint-plugin-prettier": "^3.1.3",
|
"eslint-plugin-prettier": "^3.1.3",
|
||||||
"husky": "^4.2.5",
|
"husky": "^4.2.5",
|
||||||
"jest": "^25.5.1",
|
"jest": "^26.0.0",
|
||||||
"jest-environment-jsdom-sixteen": "^1.0.3",
|
"jest-environment-jsdom-sixteen": "^1.0.3",
|
||||||
"jest-preset-angular": "^8.1.3",
|
"jest-preset-angular": "^8.1.3",
|
||||||
"lint-staged": "^10.1.7",
|
"lint-staged": "^10.1.7",
|
||||||
|
@ -2,12 +2,10 @@ import { NgModule } from '@angular/core';
|
|||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
import { HomeComponent } from './core/components/home/home.component';
|
import { HomeComponent } from './core/components/home/home.component';
|
||||||
import { LoginComponent } from './core/components/login/login.component';
|
|
||||||
import { PageNotFoundComponent } from './shared/components/page-not-found/page-not-found.component';
|
import { PageNotFoundComponent } from './shared/components/page-not-found/page-not-found.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', component: HomeComponent },
|
{ path: '', component: HomeComponent },
|
||||||
{ path: 'login', component: LoginComponent },
|
|
||||||
{
|
{
|
||||||
path: 'administration',
|
path: 'administration',
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
|
@ -5,6 +5,8 @@ import { Subscription } from 'rxjs';
|
|||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { Theme } from './core/enums/theme.enum';
|
import { Theme } from './core/enums/theme.enum';
|
||||||
import { UserRole } from './core/enums/user-role.enum';
|
import { UserRole } from './core/enums/user-role.enum';
|
||||||
|
import { User } from './core/models/user.model';
|
||||||
|
import { LanguageService } from './core/services/language.service';
|
||||||
import { MockingService } from './core/services/mocking.service';
|
import { MockingService } from './core/services/mocking.service';
|
||||||
import { ThemeService } from './core/services/theme.service';
|
import { ThemeService } from './core/services/theme.service';
|
||||||
|
|
||||||
@ -22,15 +24,18 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
private titleService: Title,
|
private titleService: Title,
|
||||||
private themeService: ThemeService,
|
private themeService: ThemeService,
|
||||||
|
private languageService: LanguageService,
|
||||||
private mockingService: MockingService
|
private mockingService: MockingService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (!environment.production) {
|
if (!environment.production) {
|
||||||
this.appTitle += ' [DEV]';
|
this.appTitle += ' [DEV]';
|
||||||
this.mockingService.loadUser(UserRole.REGISTERED);
|
// TODO: to be removed
|
||||||
|
this.mockingService.loadUser(new User('TOTO', 'toto@gafam.com', UserRole.REGISTERED, false));
|
||||||
}
|
}
|
||||||
this.titleService.setTitle(this.appTitle);
|
this.titleService.setTitle(this.appTitle);
|
||||||
|
this.languageService.configureAndInitTranslations();
|
||||||
this.themeSubscription = this.themeService.theme.subscribe((theme: Theme) => {
|
this.themeSubscription = this.themeService.theme.subscribe((theme: Theme) => {
|
||||||
switch (theme) {
|
switch (theme) {
|
||||||
case Theme.DARK:
|
case Theme.DARK:
|
||||||
|
@ -40,8 +40,12 @@
|
|||||||
<a class="navbar-item" routerLink="administration" routerLinkActive="is-active">
|
<a class="navbar-item" routerLink="administration" routerLinkActive="is-active">
|
||||||
Administration
|
Administration
|
||||||
</a>
|
</a>
|
||||||
<a class="navbar-item" routerLink="participation" routerLinkActive="is-active">
|
<a
|
||||||
Participation
|
class="navbar-item"
|
||||||
|
routerLink="participation/poll/citron_ou_orange"
|
||||||
|
routerLinkActive="is-active"
|
||||||
|
>
|
||||||
|
Participation à citron_ou_orange
|
||||||
</a>
|
</a>
|
||||||
<a class="navbar-item" routerLink="oldstuff" routerLinkActive="is-active">
|
<a class="navbar-item" routerLink="oldstuff" routerLinkActive="is-active">
|
||||||
Old stuff
|
Old stuff
|
||||||
@ -50,22 +54,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="navbar-item">
|
|
||||||
<app-theme-selector></app-theme-selector>
|
|
||||||
</div>
|
|
||||||
<div class="navbar-item">
|
|
||||||
<app-language-selector></app-language-selector>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-end">
|
<div class="navbar-end">
|
||||||
<div class="navbar-item">
|
<div class="navbar-item" #container>
|
||||||
<div class="buttons">
|
<div class="buttons has-addons is-centered clickable" (click)="openDialog()">
|
||||||
<a class="button is-primary">
|
<button class="button is-static"><i class="fa fa-user-circle"></i></button>
|
||||||
<strong>Sign up</strong>
|
<button class="button is-static" *ngIf="_user | async as user">
|
||||||
</a>
|
{{ user.pseudo || 'anonyme' }}
|
||||||
<a class="button is-light">
|
</button>
|
||||||
Log in
|
<button class="button is-static"><i class="fa fa-cogs"></i></button>
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { Component, EventEmitter, Output, Input } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { User } from '../../models/user.model';
|
||||||
|
import { ModalService } from '../../services/modal.service';
|
||||||
|
import { UserService } from '../../services/user.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
@ -9,6 +14,14 @@ export class HeaderComponent {
|
|||||||
@Input() isSidebarOpened: boolean;
|
@Input() isSidebarOpened: boolean;
|
||||||
@Output() toggleSidebarEE = new EventEmitter<boolean>();
|
@Output() toggleSidebarEE = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
public _user: Observable<User> = this.userService.user;
|
||||||
|
|
||||||
|
constructor(private userService: UserService, private modalService: ModalService) {}
|
||||||
|
|
||||||
|
public openDialog(): void {
|
||||||
|
this.modalService.openSettingsComponent();
|
||||||
|
}
|
||||||
|
|
||||||
public toggleSidebarOpening(): void {
|
public toggleSidebarOpening(): void {
|
||||||
this.isSidebarOpened = !this.isSidebarOpened;
|
this.isSidebarOpened = !this.isSidebarOpened;
|
||||||
this.toggleSidebarEE.emit(this.isSidebarOpened);
|
this.toggleSidebarEE.emit(this.isSidebarOpened);
|
||||||
|
@ -1 +0,0 @@
|
|||||||
<p>login works!</p>
|
|
@ -1,12 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-login',
|
|
||||||
templateUrl: './login.component.html',
|
|
||||||
styleUrls: ['./login.component.scss'],
|
|
||||||
})
|
|
||||||
export class LoginComponent implements OnInit {
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
ngOnInit(): void {}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<div class="control has-icons-left">
|
|
||||||
<select class="select is-small" [(ngModel)]="currentLang">
|
|
||||||
<ng-container *ngFor="let language of languagesAvailable">
|
|
||||||
<option value="{{ language }}">{{ 'LANGUAGES.' + language | translate }}</option>
|
|
||||||
</ng-container>
|
|
||||||
</select>
|
|
||||||
<div class="icon is-left">
|
|
||||||
<i class="fa fa-globe"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,38 +0,0 @@
|
|||||||
import { Component, DoCheck, OnInit } from '@angular/core';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
|
|
||||||
import { Language } from '../../../enums/language.enum';
|
|
||||||
import { StorageService } from '../../../services/storage.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-language-selector',
|
|
||||||
templateUrl: './language-selector.component.html',
|
|
||||||
styleUrls: ['./language-selector.component.scss'],
|
|
||||||
})
|
|
||||||
export class LanguageSelectorComponent implements OnInit, DoCheck {
|
|
||||||
public currentLang: Language;
|
|
||||||
public languagesAvailable: string[] = Object.values(Language);
|
|
||||||
|
|
||||||
constructor(private translate: TranslateService, private storageService: StorageService) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
const currentBrowserLanguage: Language = this.translate.getBrowserLang().toUpperCase() as Language;
|
|
||||||
if (this.storageService.language && Object.keys(Language).includes(this.storageService.language)) {
|
|
||||||
this.currentLang = this.storageService.language;
|
|
||||||
} else if (Object.keys(Language).includes(currentBrowserLanguage)) {
|
|
||||||
this.currentLang = currentBrowserLanguage;
|
|
||||||
} else {
|
|
||||||
this.currentLang = Language.EN;
|
|
||||||
}
|
|
||||||
this.updateLanguage();
|
|
||||||
}
|
|
||||||
|
|
||||||
ngDoCheck(): void {
|
|
||||||
this.updateLanguage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public updateLanguage(): void {
|
|
||||||
this.translate.use(this.currentLang.toString().toUpperCase());
|
|
||||||
this.storageService.language = this.currentLang;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
<div class="buttons has-addons is-centered">
|
|
||||||
<button class="button is-small is-static">Theme</button>
|
|
||||||
<button
|
|
||||||
class="button is-small"
|
|
||||||
[ngClass]="{ 'is-active': (currentTheme | async) === themeEnum.LIGHT }"
|
|
||||||
(click)="selectTheme('LIGHT')"
|
|
||||||
>
|
|
||||||
<i class="fa fa-sun-o"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="button is-small"
|
|
||||||
[ngClass]="{ 'is-active': (currentTheme | async) === themeEnum.DARK }"
|
|
||||||
(click)="selectTheme('DARK')"
|
|
||||||
>
|
|
||||||
<i class="fa fa-moon"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="button is-small"
|
|
||||||
[ngClass]="{ 'is-active': (currentTheme | async) === themeEnum.RED }"
|
|
||||||
(click)="selectTheme('RED')"
|
|
||||||
>
|
|
||||||
<i class="fa fa-adjust"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
@ -7,26 +7,14 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||||||
import { FooterComponent } from './components/footer/footer.component';
|
import { FooterComponent } from './components/footer/footer.component';
|
||||||
import { HeaderComponent } from './components/header/header.component';
|
import { HeaderComponent } from './components/header/header.component';
|
||||||
import { HomeComponent } from './components/home/home.component';
|
import { HomeComponent } from './components/home/home.component';
|
||||||
import { LoginComponent } from './components/login/login.component';
|
|
||||||
import { LogoComponent } from './components/logo/logo.component';
|
import { LogoComponent } from './components/logo/logo.component';
|
||||||
import { LanguageSelectorComponent } from './components/selectors/language-selector/language-selector.component';
|
|
||||||
import { ThemeSelectorComponent } from './components/selectors/theme-selector/theme-selector.component';
|
|
||||||
import { NavigationComponent } from './components/sibebar/navigation/navigation.component';
|
import { NavigationComponent } from './components/sibebar/navigation/navigation.component';
|
||||||
import { throwIfAlreadyLoaded } from './guards/module-import.guard';
|
import { throwIfAlreadyLoaded } from './guards/module-import.guard';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [FooterComponent, HeaderComponent, HomeComponent, LogoComponent, NavigationComponent],
|
||||||
FooterComponent,
|
|
||||||
HeaderComponent,
|
|
||||||
HomeComponent,
|
|
||||||
LanguageSelectorComponent,
|
|
||||||
LoginComponent,
|
|
||||||
LogoComponent,
|
|
||||||
NavigationComponent,
|
|
||||||
ThemeSelectorComponent,
|
|
||||||
],
|
|
||||||
imports: [CommonModule, FormsModule, RouterModule, TranslateModule],
|
imports: [CommonModule, FormsModule, RouterModule, TranslateModule],
|
||||||
exports: [HeaderComponent, FooterComponent, NavigationComponent, LoginComponent, LogoComponent],
|
exports: [HeaderComponent, FooterComponent, NavigationComponent, LogoComponent],
|
||||||
})
|
})
|
||||||
export class CoreModule {
|
export class CoreModule {
|
||||||
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
|
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
export enum AnswerGranularity {
|
|
||||||
BASIC = 'BASIC',
|
|
||||||
COMPLEX = 'COMPLEX',
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
export enum AnswerType {
|
export enum Response {
|
||||||
YES = 'YES',
|
YES = 'YES',
|
||||||
NO = 'NO',
|
NO = 'NO',
|
||||||
MAYBE = 'MAYBE',
|
MAYBE = 'MAYBE',
|
@ -1,5 +1,5 @@
|
|||||||
export enum UserRole {
|
export enum UserRole {
|
||||||
ANONYMOUS = 'ANONYMOUS',
|
ANONYMOUS = 'ANONYMOUS',
|
||||||
REGISTERED = 'ADMIN',
|
REGISTERED = 'REGISTERED',
|
||||||
ADMIN = 'ADMIN',
|
ADMIN = 'ADMIN',
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export enum WorkflowStep {
|
export enum WorkflowStep {
|
||||||
DESCRIPTION = 'DESCRIPTION',
|
DESCRIPTION = 'DESCRIPTION',
|
||||||
OPTIONS = 'OPTIONS',
|
CHOICES = 'CHOICES',
|
||||||
CONFIGURATION = 'CONFIGURATION',
|
CONFIGURATION = 'CONFIGURATION',
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
export interface DateOption {
|
|
||||||
timeList: any;
|
|
||||||
literal: string;
|
|
||||||
date_object?: object;
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
import { AnswerType } from '../enums/answer-type.enum';
|
import { Response } from '../enums/response.enum';
|
||||||
import { PollOption } from './poll-options.model';
|
import { Choice } from './choice.model';
|
||||||
|
|
||||||
export class Answer {
|
export class Answer {
|
||||||
constructor(public pollOption: PollOption, public type: AnswerType, public userPseudo: string) {}
|
constructor(public author: string, public choice: Choice, public response: Response) {}
|
||||||
}
|
}
|
||||||
|
5
src/app/core/models/choice.model.ts
Normal file
5
src/app/core/models/choice.model.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { Response } from '../enums/response.enum';
|
||||||
|
|
||||||
|
export class Choice {
|
||||||
|
constructor(public label: string, public responses: Response[] = [Response.YES, Response.NO]) {}
|
||||||
|
}
|
3
src/app/core/models/comment.model.ts
Normal file
3
src/app/core/models/comment.model.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export class Comment {
|
||||||
|
constructor(public author: string, public content: string) {}
|
||||||
|
}
|
26
src/app/core/models/configuration.model.ts
Normal file
26
src/app/core/models/configuration.model.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
import { DateUtilsService } from '../utils/date-utils.service';
|
||||||
|
|
||||||
|
export class Configuration {
|
||||||
|
constructor(
|
||||||
|
public isAboutDate: boolean = false,
|
||||||
|
public slug: string = uuidv4(),
|
||||||
|
public isProtectedByPassword: boolean = false,
|
||||||
|
public isMaybeAnswerAvailable: boolean = false,
|
||||||
|
public creationDate: Date = new Date(Date.now()),
|
||||||
|
public expirationDate: Date = DateUtilsService.addDaysToDate(
|
||||||
|
environment.poll.defaultConfig.expiracyInDays,
|
||||||
|
new Date(Date.now())
|
||||||
|
)
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public getAdministrationUrl(): string {
|
||||||
|
return `${environment.api.baseHref}/administration/${environment.api.endpoints.polls}/${this.slug}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getParticipationUrl(): string {
|
||||||
|
return `${environment.api.baseHref}/participation/${environment.api.endpoints.polls}/${this.slug}`;
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +0,0 @@
|
|||||||
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
|
|
||||||
) {}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
import * as moment from 'moment';
|
|
||||||
|
|
||||||
export class PollOption {
|
|
||||||
constructor(public label: string, public url?: string, public subOptions?: PollOption[]) {}
|
|
||||||
|
|
||||||
public isDatePoll(): boolean {
|
|
||||||
return moment(this.label).isValid();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +1,17 @@
|
|||||||
import { Answer } from './answer.model';
|
import { Answer } from './answer.model';
|
||||||
import { PollConfig } from './poll-config.model';
|
import { Choice } from './choice.model';
|
||||||
import { PollOption } from './poll-options.model';
|
import { Comment } from './comment.model';
|
||||||
|
import { Configuration } from './configuration.model';
|
||||||
|
import { Question } from './question.model';
|
||||||
import { User } from './user.model';
|
import { User } from './user.model';
|
||||||
import { environment } from 'src/environments/environment';
|
|
||||||
|
|
||||||
export class Poll {
|
export class Poll {
|
||||||
constructor(
|
constructor(
|
||||||
public isDateType: boolean,
|
public owner: User,
|
||||||
public title: string,
|
public question: Question,
|
||||||
public description: string,
|
public choices: Choice[],
|
||||||
public slug: string,
|
public configuration: Configuration = new Configuration(),
|
||||||
public id: string,
|
public answers: Answer[] = [],
|
||||||
public owner?: User,
|
public comments: Comment[] = []
|
||||||
public config?: PollConfig,
|
|
||||||
public options: PollOption[] = [],
|
|
||||||
public answers: Answer[] = []
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public getUrl(): string {
|
|
||||||
return `${environment.api.baseHref}/${this.slug}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
3
src/app/core/models/question.model.ts
Normal file
3
src/app/core/models/question.model.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export class Question {
|
||||||
|
constructor(public label: string, public description: string) {}
|
||||||
|
}
|
@ -1,12 +1,12 @@
|
|||||||
import { Poll } from './poll.model';
|
|
||||||
import { UserRole } from '../enums/user-role.enum';
|
import { UserRole } from '../enums/user-role.enum';
|
||||||
|
import { Poll } from './poll.model';
|
||||||
|
|
||||||
export class User {
|
export class User {
|
||||||
constructor(
|
constructor(
|
||||||
|
public pseudo: string,
|
||||||
|
public email: string,
|
||||||
public role: UserRole = UserRole.ANONYMOUS,
|
public role: UserRole = UserRole.ANONYMOUS,
|
||||||
public isOwner: boolean = false,
|
public isOwner: boolean = false,
|
||||||
public pseudo?: string,
|
|
||||||
public email?: string,
|
|
||||||
public polls?: Poll[]
|
public polls?: Poll[]
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export class ApiService {
|
|||||||
private readonly commentsEndpoint = environment.api.endpoints.polls.comments.name;
|
private readonly commentsEndpoint = environment.api.endpoints.polls.comments.name;
|
||||||
private readonly votesEndpoint = environment.api.endpoints.polls.votes.name;
|
private readonly votesEndpoint = environment.api.endpoints.polls.votes.name;
|
||||||
private readonly slugsEndpoint = environment.api.endpoints.polls.slugs.name;
|
private readonly slugsEndpoint = environment.api.endpoints.polls.slugs.name;
|
||||||
private readonly votesStacksEndpoint = environment.api.endpoints.voteStack.name;
|
private readonly votesStacksEndpoint = environment.api.endpoints.polls.votesStacks.name;
|
||||||
private readonly usersEndpoint = environment.api.endpoints.users.name;
|
private readonly usersEndpoint = environment.api.endpoints.users.name;
|
||||||
private readonly usersPollsEndpoint = environment.api.endpoints.users.polls.name;
|
private readonly usersPollsEndpoint = environment.api.endpoints.users.polls.name;
|
||||||
private readonly usersPollsSendEmailEndpoint = environment.api.endpoints.users.polls.sendEmail.name;
|
private readonly usersPollsSendEmailEndpoint = environment.api.endpoints.users.polls.sendEmail.name;
|
||||||
@ -28,7 +28,7 @@ export class ApiService {
|
|||||||
////////////
|
////////////
|
||||||
public async savePoll(poll: Poll): Promise<void> {
|
public async savePoll(poll: Poll): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.axiosInstance.post(`${this.pollsEndpoint}`, { params: { config: poll.config } });
|
await this.axiosInstance.post(`${this.pollsEndpoint}`, poll);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError(error);
|
this.handleError(error);
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ export class ApiService {
|
|||||||
public async saveVote(poll: Poll): Promise<void> {
|
public async saveVote(poll: Poll): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// TODO: add the votestack in the params
|
// TODO: add the votestack in the params
|
||||||
await this.axiosInstance.post(`${this.pollsEndpoint}/${poll.id}${this.votesEndpoint}`, {
|
await this.axiosInstance.post(`${this.pollsEndpoint}/${poll.configuration.slug}${this.votesEndpoint}`, {
|
||||||
params: { voteStack: {} },
|
params: { voteStack: {} },
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -48,9 +48,10 @@ export class ApiService {
|
|||||||
public async saveComment(poll: Poll, comment: string): Promise<void> {
|
public async saveComment(poll: Poll, comment: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// TODO: add the comment in the params
|
// TODO: add the comment in the params
|
||||||
await this.axiosInstance.post(`${this.pollsEndpoint}/${poll.id}${this.commentsEndpoint}`, {
|
await this.axiosInstance.post(
|
||||||
params: { comment },
|
`${this.pollsEndpoint}/${poll.configuration.slug}${this.commentsEndpoint}`,
|
||||||
});
|
comment
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError(error);
|
this.handleError(error);
|
||||||
}
|
}
|
||||||
@ -104,9 +105,17 @@ export class ApiService {
|
|||||||
public async getPollByIdentifier(identifier: string): Promise<Poll | undefined> {
|
public async getPollByIdentifier(identifier: string): Promise<Poll | undefined> {
|
||||||
// TODO: identifier should be decided according to backend : Id || Slug ?
|
// TODO: identifier should be decided according to backend : Id || Slug ?
|
||||||
try {
|
try {
|
||||||
|
// TODO: this interceptor should not be existing, backend should return the good object poll
|
||||||
|
const adapterInterceptor: number = this.axiosInstance.interceptors.response.use(
|
||||||
|
(response): AxiosResponse => {
|
||||||
|
response.data = response.data['poll'];
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
);
|
||||||
const response: AxiosResponse<Poll> = await this.axiosInstance.get<Poll>(
|
const response: AxiosResponse<Poll> = await this.axiosInstance.get<Poll>(
|
||||||
`${this.pollsEndpoint}/${identifier}`
|
`${this.pollsEndpoint}/${identifier}`
|
||||||
);
|
);
|
||||||
|
axios.interceptors.request.eject(adapterInterceptor);
|
||||||
return response?.data;
|
return response?.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.response?.status === 404) {
|
if (error.response?.status === 404) {
|
||||||
@ -123,7 +132,7 @@ export class ApiService {
|
|||||||
public async updatePoll(poll: Poll): Promise<void> {
|
public async updatePoll(poll: Poll): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// TODO: implement the params when entities are finalized.
|
// TODO: implement the params when entities are finalized.
|
||||||
await this.axiosInstance.put(`${this.pollsEndpoint}/${poll.id}`, {
|
await this.axiosInstance.put(`${this.pollsEndpoint}/${poll.configuration.slug}`, {
|
||||||
params: { voteStack: {}, token: '' },
|
params: { voteStack: {}, token: '' },
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -145,10 +154,9 @@ export class ApiService {
|
|||||||
////////////
|
////////////
|
||||||
// DELETE //
|
// DELETE //
|
||||||
////////////
|
////////////
|
||||||
|
|
||||||
public async deletePoll(poll: Poll): Promise<void> {
|
public async deletePoll(poll: Poll): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.axiosInstance.delete(`${this.pollsEndpoint}${poll.id}`, {});
|
await this.axiosInstance.delete(`${this.pollsEndpoint}${poll.configuration.slug}`, {});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError(error);
|
this.handleError(error);
|
||||||
}
|
}
|
||||||
@ -157,7 +165,7 @@ export class ApiService {
|
|||||||
public async deletePollVotes(poll: Poll): Promise<void> {
|
public async deletePollVotes(poll: Poll): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// TODO: update endpoint in Backend
|
// TODO: update endpoint in Backend
|
||||||
await this.axiosInstance.delete(`${this.pollsEndpoint}${poll.id}${this.votesEndpoint}`);
|
await this.axiosInstance.delete(`${this.pollsEndpoint}${poll.configuration.slug}${this.votesEndpoint}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError(error);
|
this.handleError(error);
|
||||||
}
|
}
|
||||||
@ -166,7 +174,7 @@ export class ApiService {
|
|||||||
public async deletePollComments(poll: Poll): Promise<void> {
|
public async deletePollComments(poll: Poll): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// TODO: modify endpoint in Backend
|
// TODO: modify endpoint in Backend
|
||||||
await this.axiosInstance.delete(`${this.pollsEndpoint}${poll.id}${this.commentsEndpoint}`);
|
await this.axiosInstance.delete(`${this.pollsEndpoint}${poll.configuration.slug}${this.commentsEndpoint}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError(error);
|
this.handleError(error);
|
||||||
}
|
}
|
||||||
@ -192,5 +200,6 @@ export class ApiService {
|
|||||||
console.log('Error', error.message);
|
console.log('Error', error.message);
|
||||||
}
|
}
|
||||||
console.log(error.config);
|
console.log(error.config);
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/app/core/services/language.service.spec.ts
Normal file
16
src/app/core/services/language.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LanguageService } from './language.service';
|
||||||
|
|
||||||
|
describe('LanguageService', () => {
|
||||||
|
let service: LanguageService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(LanguageService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
66
src/app/core/services/language.service.ts
Normal file
66
src/app/core/services/language.service.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { TranslateService, LangChangeEvent } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { Language } from '../enums/language.enum';
|
||||||
|
import { StorageService } from './storage.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class LanguageService {
|
||||||
|
constructor(private translate: TranslateService, private storageService: StorageService) {}
|
||||||
|
|
||||||
|
public getLangage(): Language {
|
||||||
|
return this.translate.currentLang as Language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setLanguage(language: Language): void {
|
||||||
|
this.translate.use(language.toString().toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAvailableLanguages(): string[] {
|
||||||
|
return this.translate.getLangs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public configureAndInitTranslations(): void {
|
||||||
|
// always save in storage the currentLang used
|
||||||
|
this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
|
||||||
|
this.storageService.language = event.lang as Language;
|
||||||
|
});
|
||||||
|
|
||||||
|
// set all languages available
|
||||||
|
this.translate.addLangs(Object.keys(Language));
|
||||||
|
|
||||||
|
// set language
|
||||||
|
this.setLanguageOnInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setLanguageOnInit(): void {
|
||||||
|
// set language from storage
|
||||||
|
if (!this.translate.currentLang) {
|
||||||
|
this.setLanguageFromStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// or set language from browser
|
||||||
|
if (!this.translate.currentLang) {
|
||||||
|
this.setLanguageFromBrowser();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set default language
|
||||||
|
if (!this.translate.currentLang) {
|
||||||
|
this.setLanguage(Language.EN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setLanguageFromStorage(): void {
|
||||||
|
if (this.storageService.language && this.translate.getLangs().includes(this.storageService.language)) {
|
||||||
|
this.setLanguage(this.storageService.language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private setLanguageFromBrowser(): void {
|
||||||
|
const currentBrowserLanguage: Language = this.translate.getBrowserLang().toUpperCase() as Language;
|
||||||
|
if (this.translate.getLangs().includes(currentBrowserLanguage)) {
|
||||||
|
this.setLanguage(currentBrowserLanguage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
src/app/core/services/loader.service.spec.ts
Normal file
16
src/app/core/services/loader.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoaderService } from './loader.service';
|
||||||
|
|
||||||
|
describe('LoaderService', () => {
|
||||||
|
let service: LoaderService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(LoaderService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
14
src/app/core/services/loader.service.ts
Normal file
14
src/app/core/services/loader.service.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class LoaderService {
|
||||||
|
private _loadingStatus: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
|
||||||
|
public readonly isLoading: Observable<boolean> = this._loadingStatus.asObservable();
|
||||||
|
|
||||||
|
public setStatus(status: boolean): void {
|
||||||
|
this._loadingStatus.next(status);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { UserRole } from '../enums/user-role.enum';
|
import { UserRole } from '../enums/user-role.enum';
|
||||||
|
import { Choice } from '../models/choice.model';
|
||||||
import { Poll } from '../models/poll.model';
|
import { Poll } from '../models/poll.model';
|
||||||
|
import { Question } from '../models/question.model';
|
||||||
import { User } from '../models/user.model';
|
import { User } from '../models/user.model';
|
||||||
import { PollService } from './poll.service';
|
import { PollService } from './poll.service';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
@ -10,28 +12,33 @@ import { UserService } from './user.service';
|
|||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class MockingService {
|
export class MockingService {
|
||||||
public pollsDatabase: Poll[];
|
private user: User;
|
||||||
|
public pollsDatabase: Poll[] = [];
|
||||||
|
|
||||||
private user: User = new User(UserRole.ANONYMOUS, false, 'toto', 'toto@gafam.com', []);
|
private poll1: Poll = new Poll(this.user, new Question('Quand le picnic ?', 'Pour faire la teuf'), [
|
||||||
private poll1: Poll = new Poll(false, 'mon super sondage', 'super description 1', 'super_slug_1', 'id1');
|
new Choice('mardi prochain'),
|
||||||
private poll2: Poll = new Poll(false, 'mon autre sondage', 'super description 2', 'super_slug_2', 'id2');
|
new Choice('mercredi'),
|
||||||
|
]);
|
||||||
|
private poll2: Poll = new Poll(this.user, new Question('On fait quoi à la soirée ?', 'Balancez vos idées'), [
|
||||||
|
new Choice('jeux'),
|
||||||
|
new Choice('danser'),
|
||||||
|
new Choice('discuter en picolant'),
|
||||||
|
]);
|
||||||
|
|
||||||
constructor(private userService: UserService, private pollService: PollService) {
|
constructor(private userService: UserService, private pollService: PollService) {
|
||||||
this.pollsDatabase = [this.poll1, this.poll2];
|
this.pollsDatabase = [this.poll1, this.poll2];
|
||||||
this.user.polls = this.pollsDatabase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadUser(role: UserRole): void {
|
public loadUser(user: User): void {
|
||||||
this.user.role = role;
|
this.user = user;
|
||||||
|
this.user.polls = this.pollsDatabase;
|
||||||
console.info('MOCKING user', { user: this.user });
|
console.info('MOCKING user', { user: this.user });
|
||||||
this.userService.updateUser(this.user);
|
this.userService.updateUser(this.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadPoll(slug: string): void {
|
public loadPoll(slug: string): void {
|
||||||
const poll: Poll | undefined = this.pollsDatabase.find((poll: Poll) => poll.slug === slug);
|
this.poll1.configuration.slug = slug;
|
||||||
if (poll) {
|
console.info('MOCKING poll', { poll: this.poll1 });
|
||||||
console.info('MOCKING poll', { poll });
|
this.pollService.updateCurrentPoll(this.poll1);
|
||||||
this.pollService.updateCurrentPoll(poll);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/app/core/services/modal.service.spec.ts
Normal file
16
src/app/core/services/modal.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ModalService } from './modal.service';
|
||||||
|
|
||||||
|
describe('ModalService', () => {
|
||||||
|
let service: ModalService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(ModalService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
15
src/app/core/services/modal.service.ts
Normal file
15
src/app/core/services/modal.service.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { DialogService } from 'primeng';
|
||||||
|
|
||||||
|
import { SettingsComponent } from '../../shared/components/settings/settings.component';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class ModalService {
|
||||||
|
constructor(public dialogService: DialogService) {}
|
||||||
|
|
||||||
|
public openSettingsComponent(): void {
|
||||||
|
this.dialogService.open(SettingsComponent, { header: 'Paramètres', dismissableMask: true });
|
||||||
|
}
|
||||||
|
}
|
@ -37,7 +37,10 @@ export class PollService {
|
|||||||
|
|
||||||
// GET
|
// GET
|
||||||
public async getPollByIdentifier(slug: string): Promise<void> {
|
public async getPollByIdentifier(slug: string): Promise<void> {
|
||||||
this.updateCurrentPoll(await this.apiService.getPollByIdentifier(slug));
|
const poll: Poll | undefined = await this.apiService.getPollByIdentifier(slug);
|
||||||
|
if (poll) {
|
||||||
|
this.updateCurrentPoll(poll);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
|
@ -16,4 +16,7 @@ export class StorageService {
|
|||||||
|
|
||||||
@LocalStorage()
|
@LocalStorage()
|
||||||
public userPollsIds: string[];
|
public userPollsIds: string[];
|
||||||
|
|
||||||
|
@LocalStorage()
|
||||||
|
public pseudo: string;
|
||||||
}
|
}
|
||||||
|
16
src/app/core/services/url.service.spec.ts
Normal file
16
src/app/core/services/url.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UrlService } from './url.service';
|
||||||
|
|
||||||
|
describe('UrlService', () => {
|
||||||
|
let service: UrlService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(UrlService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
23
src/app/core/services/url.service.ts
Normal file
23
src/app/core/services/url.service.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ActivatedRoute, UrlSegment } from '@angular/router';
|
||||||
|
|
||||||
|
import { LoaderService } from './loader.service';
|
||||||
|
import { PollService } from './poll.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class UrlService {
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private pollService: PollService,
|
||||||
|
private loaderService: LoaderService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async loadPollFromUrl(): Promise<void> {
|
||||||
|
this.loaderService.setStatus(true);
|
||||||
|
const wantedSlug: string = this.route.snapshot.firstChild.firstChild.url[1].path;
|
||||||
|
await this.pollService.getPollByIdentifier(wantedSlug);
|
||||||
|
this.loaderService.setStatus(false);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { DialogService } from 'primeng';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { UserRole } from '../enums/user-role.enum';
|
||||||
import { User } from '../models/user.model';
|
import { User } from '../models/user.model';
|
||||||
import { ApiService } from './api.service';
|
import { ApiService } from './api.service';
|
||||||
|
|
||||||
@ -8,16 +10,21 @@ import { ApiService } from './api.service';
|
|||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class UserService {
|
export class UserService {
|
||||||
public anonymous: User = new User();
|
public anonymous: User = new User('', '', UserRole.ANONYMOUS, false);
|
||||||
|
|
||||||
private _user: BehaviorSubject<User> = new BehaviorSubject<User>(this.anonymous);
|
private _user: BehaviorSubject<User> = new BehaviorSubject<User>(this.anonymous);
|
||||||
public readonly user: Observable<User> = this._user.asObservable();
|
public readonly user: Observable<User> = this._user.asObservable();
|
||||||
|
|
||||||
constructor(private apiService: ApiService) {}
|
constructor(private apiService: ApiService, public dialogService: DialogService) {}
|
||||||
|
|
||||||
public updateUser(user: User): void {
|
public updateUser(user: User): void {
|
||||||
this._user.next(user);
|
this._user.next(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isCurrentUserIdentifiable(): boolean {
|
||||||
|
return this._user.getValue().pseudo ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
// GET
|
// GET
|
||||||
public async getUserPolls(): Promise<void> {
|
public async getUserPolls(): Promise<void> {
|
||||||
const currentUser: User = this._user.getValue();
|
const currentUser: User = this._user.getValue();
|
||||||
|
@ -7,7 +7,7 @@ import { WorkflowStep } from '../enums/workflow-step.enum';
|
|||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class WorkflowService {
|
export class WorkflowService {
|
||||||
private steps = [WorkflowStep.DESCRIPTION, WorkflowStep.OPTIONS, WorkflowStep.CONFIGURATION];
|
private steps = [WorkflowStep.DESCRIPTION, WorkflowStep.CHOICES, WorkflowStep.CONFIGURATION];
|
||||||
|
|
||||||
private _currentStep: BehaviorSubject<WorkflowStep> = new BehaviorSubject<WorkflowStep>(WorkflowStep[0]);
|
private _currentStep: BehaviorSubject<WorkflowStep> = new BehaviorSubject<WorkflowStep>(WorkflowStep[0]);
|
||||||
public readonly currentStep: Observable<WorkflowStep> = this._currentStep.asObservable();
|
public readonly currentStep: Observable<WorkflowStep> = this._currentStep.asObservable();
|
||||||
|
@ -16,35 +16,4 @@ export class DateUtilsService {
|
|||||||
public static formatDate(date): string {
|
public static formatDate(date): string {
|
||||||
return moment(date).format('yyyy-MM-dd');
|
return moment(date).format('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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,10 @@ export class EditDescriptionComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.pollForm = this.fb.group({
|
this.pollForm = this.fb.group({
|
||||||
type: [this.poll ? this.poll.isDateType : false, [Validators.required]],
|
type: [this.poll ? this.poll.configuration.isAboutDate : false, [Validators.required]],
|
||||||
title: [this.poll ? this.poll.title : '', [Validators.required]],
|
title: [this.poll ? this.poll.question.label : '', [Validators.required]],
|
||||||
description: [this.poll ? this.poll.description : ''],
|
description: [this.poll ? this.poll.question.description : ''],
|
||||||
slug: [this.poll ? this.poll.slug : this.generateRandomSlug(), [Validators.required]],
|
slug: [this.poll ? this.poll.configuration.slug : this.generateRandomSlug(), [Validators.required]],
|
||||||
address: this.fb.group({
|
address: this.fb.group({
|
||||||
street: [''],
|
street: [''],
|
||||||
city: [''],
|
city: [''],
|
||||||
|
@ -18,10 +18,10 @@ export class PollEditComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.pollForm = this.fb.group({
|
this.pollForm = this.fb.group({
|
||||||
type: [this.poll ? this.poll.isDateType : false, [Validators.required]],
|
type: [this.poll ? this.poll.configuration.isAboutDate : false, [Validators.required]],
|
||||||
title: [this.poll ? this.poll.title : '', [Validators.required]],
|
title: [this.poll ? this.poll.question.label : '', [Validators.required]],
|
||||||
description: [this.poll ? this.poll.description : ''],
|
description: [this.poll ? this.poll.question.description : ''],
|
||||||
slug: [this.poll ? this.poll.slug : this.generateRandomSlug(), [Validators.required]],
|
slug: [this.poll ? this.poll.configuration.slug : this.generateRandomSlug(), [Validators.required]],
|
||||||
address: this.fb.group({
|
address: this.fb.group({
|
||||||
street: [''],
|
street: [''],
|
||||||
city: [''],
|
city: [''],
|
||||||
|
@ -11,10 +11,10 @@
|
|||||||
<thead></thead>
|
<thead></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let poll of (_user | async)?.polls">
|
<tr *ngFor="let poll of (_user | async)?.polls">
|
||||||
<th>{{ poll.title }}</th>
|
<th>{{ poll.question.label }}</th>
|
||||||
<td>
|
<td>
|
||||||
<a routerLink="{{ '/administration/edit/description/' + poll.slug }}">
|
<a routerLink="{{ '/administration/edit/description/' + poll.configuration.slug }}">
|
||||||
{{ poll.getUrl() }}
|
{{ poll.configuration.getAdministrationUrl() }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -26,7 +26,7 @@
|
|||||||
<ng-container *ngIf="['ANONYMOUS'].includes((_user | async)?.role)">
|
<ng-container *ngIf="['ANONYMOUS'].includes((_user | async)?.role)">
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<a class="button is-primary" role="button" routerLink="/login">
|
<a class="button is-primary" role="button" routerLink="/">
|
||||||
J’ai un compte, je me connecte
|
J’ai un compte, je me connecte
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,14 +10,13 @@ import { UserService } from '../../../core/services/user.service';
|
|||||||
styleUrls: ['./profile.component.scss'],
|
styleUrls: ['./profile.component.scss'],
|
||||||
})
|
})
|
||||||
export class ProfileComponent implements OnInit {
|
export class ProfileComponent implements OnInit {
|
||||||
public _user: Observable<User>;
|
public _user: Observable<User> = this.userService.user;
|
||||||
public isModalOpened = false;
|
public isModalOpened = false;
|
||||||
|
|
||||||
constructor(private userService: UserService) {}
|
constructor(private userService: UserService) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {}
|
||||||
this._user = this.userService.user;
|
|
||||||
}
|
|
||||||
public toggleModal(): void {
|
public toggleModal(): void {
|
||||||
this.isModalOpened = !this.isModalOpened;
|
this.isModalOpened = !this.isModalOpened;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export class StepperComponent implements OnInit {
|
|||||||
};
|
};
|
||||||
public itemOptions: MenuItem = {
|
public itemOptions: MenuItem = {
|
||||||
id: '2',
|
id: '2',
|
||||||
label: WorkflowStep.OPTIONS,
|
label: WorkflowStep.CHOICES,
|
||||||
title: 'Je renseigne les différentes options sur lesquelles les gens vont donner leur avis',
|
title: 'Je renseigne les différentes options sur lesquelles les gens vont donner leur avis',
|
||||||
routerLink: './options',
|
routerLink: './options',
|
||||||
command: () => {},
|
command: () => {},
|
||||||
|
@ -32,8 +32,8 @@ const routes: Routes = [
|
|||||||
{ path: 'step/resume', component: ResumeComponent },
|
{ path: 'step/resume', component: ResumeComponent },
|
||||||
{ path: 'step/end', component: EndConfirmationComponent },
|
{ path: 'step/end', component: EndConfirmationComponent },
|
||||||
{ path: 'graphic/:poll', component: PollGraphicComponent },
|
{ path: 'graphic/:poll', component: PollGraphicComponent },
|
||||||
{ path: 'vote/poll/id/:poll', component: PollDisplayComponent },
|
{ path: 'vote/poll/id/:id', component: PollDisplayComponent },
|
||||||
{ path: 'vote/poll/slug/:pollSlug', component: PollDisplayComponent },
|
{ path: 'vote/poll/slug/:slug', component: PollDisplayComponent },
|
||||||
{ path: 'votingchoice', component: VotingChoiceComponent },
|
{ path: 'votingchoice', component: VotingChoiceComponent },
|
||||||
{ path: 'voting', component: VotingComponent },
|
{ path: 'voting', component: VotingComponent },
|
||||||
];
|
];
|
||||||
|
@ -51,9 +51,9 @@
|
|||||||
<ul class="poll-list" *ngFor="let poll of config.myPolls; index as i; trackBy: trackFunction">
|
<ul class="poll-list" *ngFor="let poll of config.myPolls; index as i; trackBy: trackFunction">
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ poll.url }}">
|
<a href="{{ poll.url }}">
|
||||||
{{ poll.title }}
|
{{ poll.question.label }}
|
||||||
<sub>
|
<sub>
|
||||||
{{ poll.description }}
|
{{ poll.question.description }}
|
||||||
</sub>
|
</sub>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="title">
|
<a href="title">
|
||||||
{{ config.currentPoll.poll.title }}
|
{{ config.currentPoll.poll.question.label }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<h2>Résumé</h2>
|
<h2>Résumé</h2>
|
||||||
<div class="heading">
|
<div class="heading">
|
||||||
<div class="col-xs-6">
|
<div class="col-xs-6">
|
||||||
<h1 id="title">{{ config.currentPoll.poll.title }}</h1>
|
<h1 id="title">{{ config.currentPoll.poll.question.label }}</h1>
|
||||||
<p>{{ config.currentPoll.poll.description }}</p>
|
<p>{{ config.currentPoll.poll.question.description }}</p>
|
||||||
<span class="creationDate"> Créé le {{ config.currentPoll.poll.creationDate.date }} </span>
|
<span class="creationDate"> Créé le {{ config.currentPoll.poll.creationDate.date }} </span>
|
||||||
<span class="expiracyDate"> Expire le {{ config.currentPoll.poll.expiracyDate.date }} </span>
|
<span class="expiracyDate"> Expire le {{ config.currentPoll.poll.expiracyDate.date }} </span>
|
||||||
<div class="votants">
|
<div class="votants">
|
||||||
|
@ -2,14 +2,12 @@ import { NgModule } from '@angular/core';
|
|||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
import { ParticipationComponent } from './participation.component';
|
import { ParticipationComponent } from './participation.component';
|
||||||
import { PollComponent } from './poll/poll.component';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{ path: '', redirectTo: 'poll', pathMatch: 'full' },
|
||||||
path: '',
|
{ path: 'poll', component: ParticipationComponent },
|
||||||
component: ParticipationComponent,
|
{ path: ':slug', redirectTo: 'poll/:slug', pathMatch: 'full' },
|
||||||
children: [{ path: 'poll/:slug', component: PollComponent }],
|
{ path: 'poll/:slug', component: ParticipationComponent },
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -1,7 +1,30 @@
|
|||||||
<h1>Participation</h1>
|
<div class="p-grid">
|
||||||
|
<div class="p-col has-text-centered">
|
||||||
|
<h1>Participation</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a role="button" class="button" routerLink="../participation/poll/groSlug">
|
<div *ngIf="_isLoading | async" class="p-grid p-justify-center">
|
||||||
Participer au sondage « Gros slug »
|
<div class="p-col has-text-centered">
|
||||||
</a>
|
<p-progressSpinner></p-progressSpinner>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<router-outlet></router-outlet>
|
<ng-container *ngIf="!(_isLoading | async)">
|
||||||
|
<ng-container *ngIf="!(_poll | async)">
|
||||||
|
<app-page-not-found [message]="'PAGE_NOT_FOUND.POLL'"></app-page-not-found>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="_poll | async">
|
||||||
|
<div class="p-grid">
|
||||||
|
<div class="p-col">
|
||||||
|
<app-poll></app-poll>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-grid">
|
||||||
|
<div class="p-col">
|
||||||
|
<app-poll-comment></app-poll-comment>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { Poll } from '../../core/models/poll.model';
|
||||||
|
import { LoaderService } from '../../core/services/loader.service';
|
||||||
|
import { ModalService } from '../../core/services/modal.service';
|
||||||
|
import { PollService } from '../../core/services/poll.service';
|
||||||
|
import { UrlService } from '../../core/services/url.service';
|
||||||
|
import { UserService } from '../../core/services/user.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-participation',
|
selector: 'app-participation',
|
||||||
@ -6,7 +14,21 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
styleUrls: ['./participation.component.scss'],
|
styleUrls: ['./participation.component.scss'],
|
||||||
})
|
})
|
||||||
export class ParticipationComponent implements OnInit {
|
export class ParticipationComponent implements OnInit {
|
||||||
constructor() {}
|
public _isLoading: Observable<boolean> = this.loaderService.isLoading;
|
||||||
|
public _poll: Observable<Poll> = this.pollService.poll;
|
||||||
|
|
||||||
ngOnInit(): void {}
|
constructor(
|
||||||
|
private urlService: UrlService,
|
||||||
|
private loaderService: LoaderService,
|
||||||
|
private pollService: PollService,
|
||||||
|
private userService: UserService,
|
||||||
|
private modalService: ModalService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
if (!this.userService.isCurrentUserIdentifiable()) {
|
||||||
|
this.modalService.openSettingsComponent();
|
||||||
|
}
|
||||||
|
this.urlService.loadPollFromUrl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,10 @@ import { SharedModule } from '../../shared/shared.module';
|
|||||||
import { ParticipationRoutingModule } from './participation-routing.module';
|
import { ParticipationRoutingModule } from './participation-routing.module';
|
||||||
import { ParticipationComponent } from './participation.component';
|
import { ParticipationComponent } from './participation.component';
|
||||||
import { PollComponent } from './poll/poll.component';
|
import { PollComponent } from './poll/poll.component';
|
||||||
|
import { PollCommentComponent } from './poll-comment/poll-comment.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [ParticipationComponent, PollComponent],
|
declarations: [ParticipationComponent, PollComponent, PollCommentComponent],
|
||||||
imports: [CommonModule, ParticipationRoutingModule, SharedModule, TranslateModule.forChild({ extend: true })],
|
imports: [CommonModule, ParticipationRoutingModule, SharedModule, TranslateModule.forChild({ extend: true })],
|
||||||
exports: [],
|
exports: [],
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
<p>poll-comment works!</p>
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PollCommentComponent } from './poll-comment.component';
|
||||||
|
|
||||||
|
describe('PollCommentComponent', () => {
|
||||||
|
let component: PollCommentComponent;
|
||||||
|
let fixture: ComponentFixture<PollCommentComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [PollCommentComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PollCommentComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,12 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-poll-comment',
|
||||||
|
templateUrl: './poll-comment.component.html',
|
||||||
|
styleUrls: ['./poll-comment.component.scss'],
|
||||||
|
})
|
||||||
|
export class PollCommentComponent implements OnInit {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
}
|
@ -1,12 +1,6 @@
|
|||||||
<p-progressSpinner *ngIf="isLoading" class="has-text-centered"></p-progressSpinner>
|
<ng-container *ngIf="_poll | async as poll">
|
||||||
|
<h1>Titre:{{ poll.question.label }}</h1>
|
||||||
<ng-container *ngIf="!isLoading">
|
<p>description: {{ poll.question.description }}</p>
|
||||||
<ng-container *ngIf="poll | async">
|
<p>isDateType:{{ poll.configuration.isAboutDate }}</p>
|
||||||
<!-- <app-poll-presentation></app-poll-presentation> -->
|
<p>slug:{{ poll.configuration.slug }}</p>
|
||||||
<h1>Sondage : {{ poll.title | async }}</h1>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngIf="!(poll | async)">
|
|
||||||
<app-page-not-found [message]="'PAGE_NOT_FOUND.POLL'"></app-page-not-found>
|
|
||||||
</ng-container>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Poll } from '../../../core/models/poll.model';
|
import { Poll } from '../../../core/models/poll.model';
|
||||||
@ -11,24 +10,9 @@ import { PollService } from '../../../core/services/poll.service';
|
|||||||
styleUrls: ['./poll.component.scss'],
|
styleUrls: ['./poll.component.scss'],
|
||||||
})
|
})
|
||||||
export class PollComponent implements OnInit {
|
export class PollComponent implements OnInit {
|
||||||
public isLoading = false;
|
public _poll: Observable<Poll> = this.pollService.poll;
|
||||||
public wantedSlug: string;
|
|
||||||
public poll: Observable<Poll>;
|
|
||||||
public slugFromUrl: string;
|
|
||||||
private readonly urlMatcher: RegExp = new RegExp(/participation\/poll\/(\w+)/);
|
|
||||||
|
|
||||||
constructor(private router: Router, private pollService: PollService) {}
|
constructor(private pollService: PollService) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {}
|
||||||
this.wantedSlug = this.urlMatcher.exec(this.router.url)[1];
|
|
||||||
this.poll = this.pollService.poll;
|
|
||||||
|
|
||||||
this.loadPollFromUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async loadPollFromUrl(): Promise<void> {
|
|
||||||
this.isLoading = true;
|
|
||||||
await this.pollService.getPollByIdentifier(this.wantedSlug);
|
|
||||||
this.isLoading = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
<div class="p-grid p-align-center p-justify-between">
|
||||||
|
<div class="p-col">
|
||||||
|
<p>Langue</p>
|
||||||
|
</div>
|
||||||
|
<div class="p-col">
|
||||||
|
<div class="buttons has-addons">
|
||||||
|
<select class="select" [(ngModel)]="currentLang">
|
||||||
|
<option *ngFor="let language of availableLanguages" value="{{ language }}">
|
||||||
|
{{ 'LANGUAGES.' + language | translate }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,27 @@
|
|||||||
|
import { Component, DoCheck, OnInit } from '@angular/core';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { Language } from '../../../../core/enums/language.enum';
|
||||||
|
import { StorageService } from '../../../../core/services/storage.service';
|
||||||
|
import { LanguageService } from '../../../../core/services/language.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-language-selector',
|
||||||
|
templateUrl: './language-selector.component.html',
|
||||||
|
styleUrls: ['./language-selector.component.scss'],
|
||||||
|
})
|
||||||
|
export class LanguageSelectorComponent implements OnInit, DoCheck {
|
||||||
|
public currentLang: Language;
|
||||||
|
public availableLanguages: string[] = [];
|
||||||
|
|
||||||
|
constructor(private languageService: LanguageService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.availableLanguages = this.languageService.getAvailableLanguages();
|
||||||
|
this.currentLang = this.languageService.getLangage();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngDoCheck(): void {
|
||||||
|
this.languageService.setLanguage(this.currentLang);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<div class="p-grid p-align-center p-justify-between">
|
||||||
|
<div class="p-col">
|
||||||
|
<p>Theme</p>
|
||||||
|
</div>
|
||||||
|
<div class="p-col">
|
||||||
|
<div class="buttons has-addons">
|
||||||
|
<button
|
||||||
|
class="button"
|
||||||
|
[ngClass]="{ 'is-active': (currentTheme | async) === themeEnum.LIGHT }"
|
||||||
|
(click)="selectTheme('LIGHT')"
|
||||||
|
>
|
||||||
|
<i class="fa fa-sun-o"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="button"
|
||||||
|
[ngClass]="{ 'is-active': (currentTheme | async) === themeEnum.DARK }"
|
||||||
|
(click)="selectTheme('DARK')"
|
||||||
|
>
|
||||||
|
<i class="fa fa-moon"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="button"
|
||||||
|
[ngClass]="{ 'is-active': (currentTheme | async) === themeEnum.RED }"
|
||||||
|
(click)="selectTheme('RED')"
|
||||||
|
>
|
||||||
|
<i class="fa fa-adjust"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -1,8 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import { Theme } from '../../../enums/theme.enum';
|
import { Theme } from '../../../../core/enums/theme.enum';
|
||||||
import { ThemeService } from '../../../services/theme.service';
|
import { ThemeService } from '../../../../core/services/theme.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-theme-selector',
|
selector: 'app-theme-selector',
|
||||||
@ -11,13 +11,11 @@ import { ThemeService } from '../../../services/theme.service';
|
|||||||
})
|
})
|
||||||
export class ThemeSelectorComponent implements OnInit {
|
export class ThemeSelectorComponent implements OnInit {
|
||||||
public themeEnum = Theme;
|
public themeEnum = Theme;
|
||||||
public currentTheme: Observable<Theme>;
|
public currentTheme: Observable<Theme> = this.themeService.theme;
|
||||||
|
|
||||||
constructor(private themeService: ThemeService) {}
|
constructor(private themeService: ThemeService) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {}
|
||||||
this.currentTheme = this.themeService.theme;
|
|
||||||
}
|
|
||||||
|
|
||||||
public selectTheme(theme: string): void {
|
public selectTheme(theme: string): void {
|
||||||
this.themeService.selectTheme(theme as Theme);
|
this.themeService.selectTheme(theme as Theme);
|
33
src/app/shared/components/settings/settings.component.html
Normal file
33
src/app/shared/components/settings/settings.component.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<p-fieldset legend="Mes données personnelles">
|
||||||
|
<app-language-selector></app-language-selector>
|
||||||
|
<app-theme-selector></app-theme-selector>
|
||||||
|
<div class="p-grid p-align-center p-justify-between">
|
||||||
|
<div class="p-col">
|
||||||
|
<p>Pseudo, nom ou prénom :</p>
|
||||||
|
</div>
|
||||||
|
<div class="p-col" pFocusTrap>
|
||||||
|
<input
|
||||||
|
pInputText
|
||||||
|
type="text"
|
||||||
|
[(ngModel)]="user.pseudo"
|
||||||
|
(keydown.enter)="saveChanges()"
|
||||||
|
autofocus
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-grid p-align-center">
|
||||||
|
<div class="p-col">
|
||||||
|
<p>Email :</p>
|
||||||
|
</div>
|
||||||
|
<div class="p-col">
|
||||||
|
<input pInputText type="text" [(ngModel)]="user.email" (keydown.enter)="saveChanges()" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div class="p-grid">
|
||||||
|
<button class="p-col" pButton (click)="saveChanges()">Enregistrer</button>
|
||||||
|
</div>
|
||||||
|
</p-fieldset>
|
@ -1,19 +1,19 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { LoginComponent } from './login.component';
|
import { SettingsComponent } from './settings.component';
|
||||||
|
|
||||||
describe('LoginComponent', () => {
|
describe('SettingsComponent', () => {
|
||||||
let component: LoginComponent;
|
let component: SettingsComponent;
|
||||||
let fixture: ComponentFixture<LoginComponent>;
|
let fixture: ComponentFixture<SettingsComponent>;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [LoginComponent],
|
declarations: [SettingsComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(LoginComponent);
|
fixture = TestBed.createComponent(SettingsComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
41
src/app/shared/components/settings/settings.component.ts
Normal file
41
src/app/shared/components/settings/settings.component.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { DynamicDialogConfig, DynamicDialogRef } from 'primeng';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
|
import { User } from '../../../core/models/user.model';
|
||||||
|
import { UserService } from '../../../core/services/user.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-settings',
|
||||||
|
templateUrl: './settings.component.html',
|
||||||
|
styleUrls: ['./settings.component.scss'],
|
||||||
|
})
|
||||||
|
export class SettingsComponent implements OnInit {
|
||||||
|
public user: User;
|
||||||
|
private userSubscription: Subscription;
|
||||||
|
|
||||||
|
constructor(public ref: DynamicDialogRef, public config: DynamicDialogConfig, private userService: UserService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.userSubscription = this.userService.user.subscribe((user: User) => {
|
||||||
|
this.user = user;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.userSubscription) {
|
||||||
|
this.userSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveChanges(): void {
|
||||||
|
if (this.user?.pseudo?.length > 0) {
|
||||||
|
this.userService.updateUser(this.user);
|
||||||
|
}
|
||||||
|
this.closeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeDialog(): void {
|
||||||
|
this.ref.close();
|
||||||
|
}
|
||||||
|
}
|
@ -1,55 +1,67 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { ChartsModule } from 'ng2-charts';
|
import { ChartsModule } from 'ng2-charts';
|
||||||
import {
|
import {
|
||||||
|
ButtonModule,
|
||||||
ConfirmDialogModule,
|
ConfirmDialogModule,
|
||||||
DialogModule,
|
DialogModule,
|
||||||
|
DialogService,
|
||||||
|
DynamicDialogModule,
|
||||||
|
FieldsetModule,
|
||||||
|
FocusTrapModule,
|
||||||
InputSwitchModule,
|
InputSwitchModule,
|
||||||
InputTextareaModule,
|
InputTextareaModule,
|
||||||
MessageModule,
|
MessageModule,
|
||||||
|
PanelModule,
|
||||||
ProgressSpinnerModule,
|
ProgressSpinnerModule,
|
||||||
SidebarModule,
|
SidebarModule,
|
||||||
StepsModule,
|
StepsModule,
|
||||||
ToastModule,
|
ToastModule,
|
||||||
|
TooltipModule,
|
||||||
} from 'primeng';
|
} from 'primeng';
|
||||||
import { ConfirmationService, MessageService } from 'primeng/api';
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||||
|
|
||||||
|
import { FeedbackComponent } from './components/feedback/feedback.component';
|
||||||
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
|
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
|
||||||
import { PollPageComponent } from './components/poll-page/poll-page.component';
|
import { PollPageComponent } from './components/poll-page/poll-page.component';
|
||||||
import { FeedbackComponent } from './components/feedback/feedback.component';
|
import { LanguageSelectorComponent } from './components/selectors/language-selector/language-selector.component';
|
||||||
|
import { ThemeSelectorComponent } from './components/selectors/theme-selector/theme-selector.component';
|
||||||
|
import { SettingsComponent } from './components/settings/settings.component';
|
||||||
|
|
||||||
|
const MODULE_LIST = [CommonModule, ChartsModule, FormsModule, TranslateModule];
|
||||||
|
const PRIMENG_MODULE_LIST = [
|
||||||
|
ButtonModule,
|
||||||
|
ConfirmDialogModule,
|
||||||
|
DialogModule,
|
||||||
|
DynamicDialogModule,
|
||||||
|
FieldsetModule,
|
||||||
|
FocusTrapModule,
|
||||||
|
InputSwitchModule,
|
||||||
|
InputTextareaModule,
|
||||||
|
MessageModule,
|
||||||
|
PanelModule,
|
||||||
|
ProgressSpinnerModule,
|
||||||
|
SidebarModule,
|
||||||
|
StepsModule,
|
||||||
|
ToastModule,
|
||||||
|
TooltipModule,
|
||||||
|
];
|
||||||
|
const COMPONENT_LIST = [
|
||||||
|
ThemeSelectorComponent,
|
||||||
|
LanguageSelectorComponent,
|
||||||
|
PageNotFoundComponent,
|
||||||
|
PollPageComponent,
|
||||||
|
SettingsComponent,
|
||||||
|
FeedbackComponent,
|
||||||
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [PageNotFoundComponent, PollPageComponent, FeedbackComponent],
|
declarations: COMPONENT_LIST,
|
||||||
imports: [
|
imports: [...MODULE_LIST, ...PRIMENG_MODULE_LIST],
|
||||||
CommonModule,
|
exports: [...MODULE_LIST, ...PRIMENG_MODULE_LIST, ...COMPONENT_LIST],
|
||||||
ChartsModule,
|
providers: [ConfirmationService, MessageService, DialogService],
|
||||||
ConfirmDialogModule,
|
entryComponents: [SettingsComponent],
|
||||||
DialogModule,
|
|
||||||
InputSwitchModule,
|
|
||||||
InputTextareaModule,
|
|
||||||
MessageModule,
|
|
||||||
ProgressSpinnerModule,
|
|
||||||
SidebarModule,
|
|
||||||
StepsModule,
|
|
||||||
ToastModule,
|
|
||||||
],
|
|
||||||
exports: [
|
|
||||||
TranslateModule,
|
|
||||||
ChartsModule,
|
|
||||||
ConfirmDialogModule,
|
|
||||||
DialogModule,
|
|
||||||
FeedbackComponent,
|
|
||||||
InputSwitchModule,
|
|
||||||
InputTextareaModule,
|
|
||||||
MessageModule,
|
|
||||||
ProgressSpinnerModule,
|
|
||||||
SidebarModule,
|
|
||||||
StepsModule,
|
|
||||||
ToastModule,
|
|
||||||
PageNotFoundComponent,
|
|
||||||
PollPageComponent,
|
|
||||||
],
|
|
||||||
providers: [ConfirmationService, MessageService],
|
|
||||||
})
|
})
|
||||||
export class SharedModule {}
|
export class SharedModule {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const backendApiUrlsInDev = {
|
const backendApiUrlsInDev = {
|
||||||
local: 'http://localhost:8000/api',
|
local: 'http://localhost:8000',
|
||||||
remote: 'https://framadate-api.cipherbliss.com/api/v1',
|
remote: 'https://framadate-api.cipherbliss.com/api/v1',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -9,31 +9,37 @@ export const environment = {
|
|||||||
api: {
|
api: {
|
||||||
baseHref: backendApiUrlsInDev.remote,
|
baseHref: backendApiUrlsInDev.remote,
|
||||||
endpoints: {
|
endpoints: {
|
||||||
poll: {
|
polls: {
|
||||||
name: '/poll',
|
name: '/polls',
|
||||||
vote: {
|
votes: {
|
||||||
name: '/vote',
|
name: '/votes',
|
||||||
},
|
},
|
||||||
comment: {
|
comments: {
|
||||||
name: '/comment',
|
name: '/comments',
|
||||||
},
|
},
|
||||||
slug: {
|
slugs: {
|
||||||
name: '/slug',
|
name: '/slugs',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
user: {
|
voteStack: {
|
||||||
name: '/user',
|
name: '/votes-stacks',
|
||||||
|
},
|
||||||
|
users: {
|
||||||
|
name: '/users',
|
||||||
polls: {
|
polls: {
|
||||||
name: '/polls',
|
name: '/polls',
|
||||||
sendEmail: {
|
sendEmail: {
|
||||||
name: '/polls/send-email',
|
name: '/send-email',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
admin: {
|
admin: {
|
||||||
name: '/admin',
|
name: '/admin',
|
||||||
cleanPolls: {
|
polls: {
|
||||||
name: '/admin/clean-polls',
|
name: '/polls',
|
||||||
|
clean: {
|
||||||
|
name: '/clean',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// The list of file replacements can be found in `angular.json`.
|
// The list of file replacements can be found in `angular.json`.
|
||||||
|
|
||||||
const backendApiUrlsInDev = {
|
const backendApiUrlsInDev = {
|
||||||
local: 'http://localhost:8000',
|
local: 'http://localhost:8000/api/v1',
|
||||||
remote: 'https://framadate-api.cipherbliss.com/api/v1',
|
remote: 'https://framadate-api.cipherbliss.com/api/v1',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -11,13 +11,16 @@ export const environment = {
|
|||||||
production: false,
|
production: false,
|
||||||
appTitle: 'FramaSondage',
|
appTitle: 'FramaSondage',
|
||||||
api: {
|
api: {
|
||||||
baseHref: backendApiUrlsInDev.remote,
|
baseHref: backendApiUrlsInDev.local,
|
||||||
endpoints: {
|
endpoints: {
|
||||||
polls: {
|
polls: {
|
||||||
name: '/polls',
|
name: '/polls',
|
||||||
votes: {
|
votes: {
|
||||||
name: '/votes',
|
name: '/votes',
|
||||||
},
|
},
|
||||||
|
votesStacks: {
|
||||||
|
name: '/votes-stacks',
|
||||||
|
},
|
||||||
comments: {
|
comments: {
|
||||||
name: '/comments',
|
name: '/comments',
|
||||||
},
|
},
|
||||||
@ -25,9 +28,6 @@ export const environment = {
|
|||||||
name: '/slugs',
|
name: '/slugs',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
voteStack: {
|
|
||||||
name: '/votes-stacks',
|
|
||||||
},
|
|
||||||
users: {
|
users: {
|
||||||
name: '/users',
|
name: '/users',
|
||||||
polls: {
|
polls: {
|
||||||
@ -37,15 +37,6 @@ export const environment = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
admin: {
|
|
||||||
name: '/admin',
|
|
||||||
polls: {
|
|
||||||
name: '/polls',
|
|
||||||
clean: {
|
|
||||||
name: '/clean',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
poll: {
|
poll: {
|
||||||
|
Loading…
Reference in New Issue
Block a user