diff --git a/src/frontend/app/administration/administration-routing.module.ts b/src/frontend/app/administration/administration-routing.module.ts index ec2770c5abb51e494e4be3b2695218cb7aec161f..a3123301763de36d8e44e11e117dc0115181cb0d 100755 --- a/src/frontend/app/administration/administration-routing.module.ts +++ b/src/frontend/app/administration/administration-routing.module.ts @@ -50,6 +50,7 @@ import { AlfrescoAdministrationComponent } from './alfresco/alfresco-administrat import { AlfrescoListAdministrationComponent } from './alfresco/alfresco-list-administration.component'; import { ContactDuplicateComponent } from './contact/contact-duplicate/contact-duplicate.component'; import { IssuingSiteListComponent } from './registered-mail/issuing-site/issuing-site-list.component'; +import { IssuingSiteComponent } from './registered-mail/issuing-site/issuing-site.component'; @NgModule({ imports: [ @@ -119,6 +120,7 @@ import { IssuingSiteListComponent } from './registered-mail/issuing-site/issuing { path: 'alfresco/new', canActivate: [AppGuard], component: AlfrescoAdministrationComponent }, { path: 'alfresco/:id', canActivate: [AppGuard], component: AlfrescoAdministrationComponent }, { path: 'issuingSite', canActivate: [AppGuard], component: IssuingSiteListComponent }, + { path: 'issuingSite/new', canActivate: [AppGuard], component: IssuingSiteComponent }, ]), ], exports: [ diff --git a/src/frontend/app/administration/administration.module.ts b/src/frontend/app/administration/administration.module.ts index 35f246d4641b35ceae7a3eead3366fa5c17750aa..d722b9221ec1fa959f66a4ac3ff0e7691111d710 100755 --- a/src/frontend/app/administration/administration.module.ts +++ b/src/frontend/app/administration/administration.module.ts @@ -73,6 +73,7 @@ import { TranslateService } from '@ngx-translate/core'; import {EntitiesExportComponent} from './entity/export/entities-export.component'; import { RegisteredMailComponent } from './registered-mail/registered-mail.component'; import { IssuingSiteListComponent } from './registered-mail/issuing-site/issuing-site-list.component'; +import { IssuingSiteComponent } from './registered-mail/issuing-site/issuing-site.component'; @NgModule({ @@ -154,6 +155,7 @@ import { IssuingSiteListComponent } from './registered-mail/issuing-site/issuing EntitiesExportComponent, RegisteredMailComponent, IssuingSiteListComponent, + IssuingSiteComponent, ], entryComponents: [ AccountLinkComponent, diff --git a/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.html b/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.html new file mode 100644 index 0000000000000000000000000000000000000000..66ee0dec8ac63094aeaa88d9c3dbc03bc9a97335 --- /dev/null +++ b/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.html @@ -0,0 +1,123 @@ +<mat-sidenav-container autosize class="maarch-container"> + <mat-sidenav-content> + <div class="bg-head"> + <div class="bg-head-title" [class.customContainerRight]="appService.getViewMode()"> + <div class="bg-head-title-label"> + <header-left></header-left> + </div> + <div class="bg-head-title-tool"> + <header-right></header-right> + </div> + </div> + <div class="bg-head-content" [class.fullContainer]="appService.getViewMode()"> + </div> + </div> + <div class="container" [class.fullContainer]="appService.getViewMode()"> + <div class="container-content"> + <div *ngIf="loading" style="display:flex;height:100%;"> + <mat-spinner style="margin:auto;"></mat-spinner> + </div> + <mat-card *ngIf="!loading" class="card-app-content"> + <form style="display: contents;" (ngSubmit)="onSubmit()" [formGroup]="adminFormGroup"> + <div> + <mat-form-field> + <mat-label>{{'lang.siteName' | translate}}</mat-label> + <input matInput formControlName="siteLabel"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.coclicoNumber' | translate}}</mat-label> + <input matInput formControlName="accountNumber"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.postOffice' | translate}}</mat-label> + <input matInput formControlName="postOfficeLabel"> + </mat-form-field> + <div class="formType ratio-1 col-sm-12"> + <div class="formType-title"> + {{'lang.address' | translate}} + </div> + <mat-form-field appearance='outline' class="smallInput"> + <button mat-button matSuffix [matMenuTriggerFor]="menuDep" + (click)="$event.stopPropagation();" [title]="this.translate.instant('lang.targetDepartment')"> + {{addressBANCurrentDepartment}} <i class="fa fa-chevron-down"></i> + </button> + <mat-menu #menuDep="matMenu"> + <button mat-menu-item *ngFor="let dep of departmentList" + (click)="addressBANCurrentDepartment = dep">{{dep}}</button> + </mat-menu> + <mat-icon color="primary" class="fa fa-search" matPrefix + style="font-size: 15px;"></mat-icon> + <input type="text" #autoCompleteInput [placeholder]="this.translate.instant('lang.searchAddressBan')" + matInput [formControl]="addressBANControl" [matAutocomplete]="auto" + (click)="$event.stopPropagation()" (focus)="resetAutocompleteAddressBan()" + maxlength="128"> + <mat-autocomplete #auto="matAutocomplete" + (optionSelected)="selectAddressBan($event)"> + <ng-container *ngIf="addressBANResult.length > 0 && !addressBANLoading"> + <mat-option + *ngFor="let addressBANResult of addressBANFilteredResult | async" + [value]="addressBANResult"> + {{addressBANResult.address}} + </mat-option> + </ng-container> + <mat-option class="autoCompleteInfoResult smallInputInfo" + *ngIf="addressBANResult.length === 0 && !addressBANLoading" disabled + [innerHTML]="addressBANInfo"> + </mat-option> + <mat-option *ngIf="addressBANLoading" disabled> + <mat-spinner diameter="20"></mat-spinner> + </mat-option> + </mat-autocomplete> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.addressName' | translate}}</mat-label> + <input matInput formControlName="addressName"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.contactsParameters_addressNumber' | translate}}</mat-label> + <input matInput formControlName="addressNumber"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.contactsParameters_addressStreet' | translate}}</mat-label> + <input matInput formControlName="addressStreet"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.contactsParameters_addressAdditional1' | translate}}</mat-label> + <input matInput formControlName="addressAdditional1"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.contactsParameters_addressAdditional2' | translate}}</mat-label> + <input matInput formControlName="addressadditional2"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.contactsParameters_addressPostcode' | translate}}</mat-label> + <input matInput formControlName="addressPostcode"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.contactsParameters_addressTown' | translate}}</mat-label> + <input matInput formControlName="addressTown"> + </mat-form-field> + <mat-form-field> + <mat-label>{{'lang.contactsParameters_addressCountry' | translate}}</mat-label> + <input matInput formControlName="addressCountry"> + </mat-form-field> + </div> + </div> + <div style="text-align:center;"> + <button mat-raised-button color="primary" type="submit" [disabled]="!adminFormGroup.valid">{{'lang.save' | translate}}</button> + </div> + </form> + </mat-card> + </div> + </div> + </mat-sidenav-content> + <mat-sidenav #snav2 [mode]="appService.getViewMode() ? 'over' : 'side'" [fixedInViewport]="appService.getViewMode()" + fixedTopGap="56" position='end' [opened]="!appService.getViewMode()" style="overflow-x:hidden;width:400px;"> + <mat-list> + <h3 mat-subheader>{{'lang.chooseEntityAssociationModel' | translate}}</h3> + <div style="padding:10px;"> + <app-maarch-flat-tree #maarchTree *ngIf="entities.length > 0" [rawData]="entities"></app-maarch-flat-tree> + </div> + </mat-list> +</mat-sidenav> +</mat-sidenav-container> diff --git a/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.scss b/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..ee436476a348d56b30ee21aec6ec5a9adebc9904 --- /dev/null +++ b/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.scss @@ -0,0 +1,92 @@ +@import '../../../../css/vars.scss'; + +.formType { + align-items: center; + display: flex; + border-radius: 4px; + border: solid 1px #ccc; + position: relative; + padding: 10px; + padding-left: 20px; + padding-right: 20px; + flex-direction: column; + + &-title { + white-space: pre; + overflow: hidden; + max-width: 85%; + text-overflow: ellipsis; + z-index: 1; + font-size: 10px; + font-weight: bold; + background: white; + position: absolute; + top: -7px; + left: 10px; + padding: 0px; + margin: 0px; + color: #135f7f; + } + + + ::ng-deep.mat-slide-toggle-label { + color: #666; + font-weight: bold; + } + + ::ng-deep.mat-radio-button,::ng-deep.mat-slide-toggle { + opacity: 0.5; + color: #666; + user-select: none; + } + + ::ng-deep.mat-radio-checked,::ng-deep.mat-checked { + opacity: 1; + color: $primary; + } + + + ::ng-deep.mat-checked { + .mat-slide-toggle-label { + color: $primary; + } + } + + ::ng-deep.mat-form-field-suffix { + color: $secondary; + font-size: 15px; + top: 0; + } +} + +.ratio-1 { + flex: 1; +} + +.ratio-2 { + flex: 1; +} + + +.smallInput { + font-size: 11px; + padding-left: 20px; + padding-right: 20px; + + .mat-button { + width: 30px; + height: 25px; + color: $primary; + + ::ng-deep.mat-button-wrapper { + display: flex; + line-height: initial; + align-items: center; + } + } + + ::ng-deep.mat-form-field-infix { + padding: 0px; + padding-bottom: 5px; + } +} \ No newline at end of file diff --git a/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.ts b/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..6f6eb9faf5949670821cc7fc7d86bf0553f23bb2 --- /dev/null +++ b/src/frontend/app/administration/registered-mail/issuing-site/issuing-site.component.ts @@ -0,0 +1,204 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { HttpClient } from '@angular/common/http'; +import { ActivatedRoute, Router } from '@angular/router'; +import { NotificationService } from '../../../../service/notification/notification.service'; +import { HeaderService } from '../../../../service/header.service'; +import { AppService } from '../../../../service/app.service'; +import { MaarchFlatTreeComponent } from '../../../../plugins/tree/maarch-flat-tree.component'; +import { map, tap, catchError, debounceTime, filter, distinctUntilChanged, switchMap } from 'rxjs/operators'; +import { of } from 'rxjs/internal/observable/of'; +import { Observable } from 'rxjs/internal/Observable'; + +@Component({ + selector: 'app-issuing-site', + templateUrl: './issuing-site.component.html', + styleUrls: ['./issuing-site.component.scss'] +}) +export class IssuingSiteComponent implements OnInit { + + creationMode: boolean; + loading: boolean = true; + + adminFormGroup: FormGroup; + entities: any = []; + + addressBANInfo: string = ''; + addressBANMode: boolean = true; + addressBANControl = new FormControl(); + addressBANLoading: boolean = false; + addressBANResult: any[] = []; + addressBANFilteredResult: Observable<string[]>; + addressBANCurrentDepartment: string = '75'; + departmentList: any[] = []; + + @ViewChild('maarchTree', { static: false }) maarchTree: MaarchFlatTreeComponent; + + constructor( + private translate: TranslateService, + public http: HttpClient, + private route: ActivatedRoute, + private router: Router, + private notify: NotificationService, + private headerService: HeaderService, + public appService: AppService, + private _formBuilder: FormBuilder, + ) { } + + ngOnInit(): void { + this.route.params.subscribe((params) => { + + if (typeof params['id'] === 'undefined') { + this.creationMode = true; + + this.headerService.setHeader(this.translate.instant('lang.issuingSiteCreation')); + this.getEntities(); + this.initBanSearch(); + this.initAutocompleteAddressBan(); + this.adminFormGroup = this._formBuilder.group({ + id: [null], + siteLabel: ['', Validators.required], + postOfficeLabel: ['', Validators.required], + accountNumber: ['', Validators.required], + addressName: [''], + addressNumber: [''], + addressStreet: [''], + addressAdditional1: [''], + addressadditional2: [''], + addressPostcode: [''], + addressTown: [''], + addressCountry: [''] + }); + + this.loading = false; + } else { + + /*this.creationMode = false; + this.http.get('../rest/parameters/' + params['id']) + .subscribe((data: any) => { + this.parameter = data.parameter; + this.headerService.setHeader(this.translate.instant('lang.issuingSiteModification'), this.parameter.id); + if (typeof (this.parameter.param_value_int) === 'number') { + this.type = 'int'; + } else if (this.parameter.param_value_date) { + this.type = 'date'; + } else { + this.type = 'string'; + } + + this.loading = false; + }, (err) => { + this.notify.handleErrors(err); + });*/ + } + }); + } + + initBanSearch() { + this.http.get('../rest/ban/availableDepartments').pipe( + tap((data: any) => { + if (data.default !== null && data.departments.indexOf(data.default.toString()) !== - 1) { + this.addressBANCurrentDepartment = data.default; + } + this.departmentList = data.departments; + }), + catchError((err: any) => { + this.notify.handleErrors(err); + return of(false); + }) + ).subscribe(); + } + + initAutocompleteAddressBan() { + this.addressBANInfo = this.translate.instant('lang.autocompleteInfo'); + this.addressBANResult = []; + this.addressBANControl.valueChanges + .pipe( + debounceTime(300), + filter(value => value.length > 2), + distinctUntilChanged(), + tap(() => this.addressBANLoading = true), + switchMap((data: any) => this.http.get('../rest/autocomplete/banAddresses', { params: { 'address': data, 'department': this.addressBANCurrentDepartment } })), + tap((data: any) => { + if (data.length === 0) { + this.addressBANInfo = this.translate.instant('lang.noAvailableValue'); + } else { + this.addressBANInfo = ''; + } + this.addressBANResult = data; + this.addressBANFilteredResult = of(this.addressBANResult); + this.addressBANLoading = false; + }) + ).subscribe(); + } + + resetAutocompleteAddressBan() { + this.addressBANResult = []; + this.addressBANInfo = this.translate.instant('lang.autocompleteInfo'); + } + + selectAddressBan(ev: any) { + this.adminFormGroup.controls['addressNumber'].setValue(ev.option.value.number); + this.adminFormGroup.controls['addressStreet'].setValue(ev.option.value.afnorName); + this.adminFormGroup.controls['addressPostcode'].setValue(ev.option.value.postalCode); + this.adminFormGroup.controls['addressTown'].setValue(ev.option.value.city); + this.adminFormGroup.controls['addressCountry'].setValue('FRANCE'); + this.addressBANControl.setValue(''); + } + + getEntities() { + this.http.get(`../rest/entities`).pipe( + map((data: any) => { + data.entities = data.entities.map((entity: any) => { + return { + text: entity.entity_label, + icon: entity.icon, + parent_id: entity.parentSerialId, + id: entity.serialId, + state: { + opened: true + } + }; + }); + return data.entities; + }), + tap((entities: any) => { + this.entities = entities; + }), + catchError((err: any) => { + this.notify.handleSoftErrors(err); + return of(false); + }) + ).subscribe(); + } + + onSubmit() { + const objToSubmit = {}; + Object.keys(this.adminFormGroup.controls).forEach(key => { + objToSubmit[key] = this.adminFormGroup.controls[key].value; + }); + + objToSubmit['entities'] = this.maarchTree.getSelectedNodes().map((ent: any) => ent.id); + + console.log(objToSubmit); + + if (this.creationMode) { + this.http.post('../rest/recommended/sites', objToSubmit) + .subscribe(() => { + this.notify.success(this.translate.instant('lang.priorityAdded')); + this.router.navigate(['/administration/issuingSite']); + }, (err) => { + this.notify.error(err.error.errors); + }); + } else { + /*this.http.put('../rest/recommended/sites/' + this.id, objToSubmit) + .subscribe(() => { + this.notify.success(this.translate.instant('lang.priorityUpdated')); + this.router.navigate(['/administration/priorities']); + }, (err) => { + this.notify.error(err.error.errors); + });*/ + } + } +} diff --git a/src/lang/lang-fr.json b/src/lang/lang-fr.json index 2948354fb855ffb186f6b45014196362bff7072d..d63ed961841b6237aabcf72b1bce45019f41e9dd 100644 --- a/src/lang/lang-fr.json +++ b/src/lang/lang-fr.json @@ -1898,5 +1898,7 @@ "issuingSites": "Sites émetteurs", "issuingSiteDeleted": "Site émetteur supprimé", "postOffice": "Bureau de poste", - "coclicoNumber": "N° COCLICO" + "coclicoNumber": "N° COCLICO", + "siteName": "Nom du site", + "issuingSiteCreation": "Création d'un site émetteur" }