Skip to content
Snippets Groups Projects
Commit c2494434 authored by Alex ORLUC's avatar Alex ORLUC
Browse files

FEAT #11270 TIME 0:05 add admin custom field

parent a7c3cf66
No related branches found
No related tags found
No related merge requests found
<div class="admin-container" [class.admin-is-mobile]="appService.getViewMode()">
<mat-sidenav-container autosize class="admin-sidenav-container">
<mat-sidenav #snav [mode]="appService.getViewMode() ? 'over' : 'side'"
[fixedInViewport]="appService.getViewMode()" fixedTopGap="56"
[opened]="appService.getViewMode() ? false : true">
<menu-shortcut></menu-shortcut>
<menu-nav></menu-nav>
</mat-sidenav>
<mat-sidenav-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">
<mat-tab-group>
<mat-tab label="Champ(s) utilisable">
<div class="alert-message alert-message-info" role="alert"
style="margin-top: 30px;max-width: 100%;" *ngIf="customFields.length === 0"
[innerHTML]="'<b>Aucun champ personnalisé</b> n\'est défini, sélectionner des élément disponible sur le <b>panneau de droite</b> afin de créer de nouveaux champs.'">
</div>
<mat-accordion>
<mat-expansion-panel *ngFor="let custom of customFields;index as indexCustom" (opened)="initCustomFieldCheck(custom)">
<mat-expansion-panel-header>
<mat-panel-title color="primary">
{{custom.label}}
</mat-panel-title>
<mat-panel-description>
{{lang[custom.type + 'Input']}}
</mat-panel-description>
</mat-expansion-panel-header>
<div class="col-md-6">
<mat-form-field>
<input matInput name="label" [(ngModel)]="custom.label" placeholder="Nom"
[value]="custom.label">
</mat-form-field>
</div>
<div class="col-md-6">
<mat-form-field>
<input matInput name="default_value" placeholder="Valeur par défaut"
[(ngModel)]="custom.default_value" [value]="custom.default_value" [disabled]="custom.type === 'date'">
</mat-form-field>
</div>
<div class="col-md-12"
*ngIf="['select', 'radio', 'checkbox'].indexOf(custom.type) > -1">
<mat-expansion-panel class="customFieldValues" opened>
<mat-expansion-panel-header>
<mat-panel-title>
Liste de valeurs
</mat-panel-title>
</mat-expansion-panel-header>
<button mat-raised-button color="primary" (click)="addValue(indexCustom)"> Ajouter
une valeur</button>
<button mat-raised-button color="primary" (click)="sortValues(custom)"> Trier</button>
<div class="col-md-12">
<mat-form-field *ngFor="let value of custom.values;let i=index;">
<input matInput [(ngModel)]="value.label">
<button color="warn" mat-icon-button matSuffix [title]="lang.delete"
(click)="removeValue(custom, i)">
<mat-icon class="fa fa-trash"></mat-icon>
</button>
</mat-form-field>
</div>
</mat-expansion-panel>
</div>
<div class="col-md-12 text-center">
<button mat-raised-button color="primary"
(click)="updateCustomField(custom)" [disabled]="isModified(custom)">{{lang.update}}</button>
<button mat-raised-button color="warn"
(click)="removeCustomField(indexCustom)">{{lang.delete}}</button>
</div>
</mat-expansion-panel>
</mat-accordion>
</mat-tab>
</mat-tab-group>
</mat-card>
</mat-sidenav-content>
<mat-sidenav #snav2 [mode]="appService.getViewMode() ? 'over' : 'side'"
[fixedInViewport]="appService.getViewMode()" fixedTopGap="56" position='end' opened
class="col-md-4 col-sm-12 customFielsdPanel">
<mat-tab-group>
<mat-tab label="Types de champs disponibles">
<div style="display:flex;" *ngFor="let customField of customFieldsTypes">
<div style="justify-content: center;display: flex;align-items: center;width:60px;">
<button mat-icon-button color="primary" (click)="addCustomField(customField)">
<mat-icon class="fas fa-plus-circle fa-2x"></mat-icon>
</button>
</div>
<div style="flex:1;">
<div style="color: rgba(0,0,0,0.54);">{{customField.label}} :</div>
<ng-container *ngIf="customField.type === 'string'">
<mat-form-field class="input-form" floatLabel="never">
<textarea matInput placeholder="Saisisser une valeur" matTextareaAutosize
matAutosizeMinRows="1" cdkAutosizeMaxRows="6"></textarea>
</mat-form-field>
</ng-container>
<ng-container *ngIf="customField.type === 'select'">
<mat-form-field class="input-form" floatLabel="never">
<mat-select placeholder="selectionner une valeur">
<mat-option value="1">
option 1
</mat-option>
<mat-option value="2">
option 2
</mat-option>
</mat-select>
</mat-form-field>
</ng-container>
<ng-container *ngIf="customField.type === 'date'">
<mat-form-field class="input-form" floatLabel="never">
<input matInput [matDatepicker]="picker" placeholder="Selectionner une date"
(click)="picker.open()">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
</ng-container>
<ng-container *ngIf="customField.type === 'radio'">
<mat-radio-group class="radio-form" color="primary">
<mat-radio-button value="1">
choix 1
</mat-radio-button>
<mat-radio-button value="2">
choix 2
</mat-radio-button>
<mat-radio-button value="3">
choix 3
</mat-radio-button>
<mat-radio-button value="4">
choix 4
</mat-radio-button>
</mat-radio-group>
</ng-container>
<ng-container *ngIf="customField.type === 'checkbox'">
<div class="input-form checkbox-form">
<mat-selection-list #shoes class="div-list">
<mat-list-option checkboxPosition="before">
option 1
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 2
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 3
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 4
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 5
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 6
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 7
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 8
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 9
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 10
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 11
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 12
</mat-list-option>
<mat-list-option checkboxPosition="before">
option 13
</mat-list-option>
</mat-selection-list>
</div>
<mat-chip-list class="checkbox-selected-list">
<mat-chip *ngFor="let chip of shoes.selectedOptions.selected" selected>
valeur slectionnée
</mat-chip>
</mat-chip-list>
</ng-container>
</div>
</div>
</mat-tab>
</mat-tab-group>
</mat-sidenav>
</mat-sidenav-container>
</div>
\ No newline at end of file
@import '../../../css/vars.scss';
.mat-divider {
padding-top: 10px;
padding-bottom: 10px;
}
.div-list {
padding: 0px;
max-height: 150px;
overflow: auto;
}
.input-form {
color: #666;
width: 500px;
button {
font-size: 30px;
}
.mat-input-element {
color: $primary;
padding-left: 20px;
}
input {
padding-left: 20px;
}
::ng-deep.mat-select-value-text {
padding-left: 20px;
color: $primary;
}
::ng-deep.mat-form-field-label {
left: 20px;
}
::ng-deep.mat-form-field-infix {
padding-bottom: 15px;
}
::ng-deep.mat-form-field-flex {
background: white;
border-radius: 30px;
border: solid 1px $primary;
}
::ng-deep .mat-form-field-underline {
display: none;
}
::ng-deep.mat-form-field-suffix {
margin-right: 20px;
}
::ng-deep.mat-select-arrow-wrapper {
padding-right: 20px;
}
::ng-deep.mat-list-option {
color: rgba(0, 0, 0, 0.54);
}
textarea.cdk-textarea-autosize-measuring {
padding: 4px 0 !important;
}
}
.checkbox-form {
width: 100%;
padding: 0px;
border: solid 1px $primary;
border-radius: 30px;
overflow: hidden;
}
.checkbox-selected-list {
margin-top: 10px;
display: flex;
justify-content: center;
::ng-deep.mat-chip-list-wrapper {
justify-content: center;
}
}
.radio-form {
display: flex;
.mat-radio-button {
flex: 1;
::ng-deep.mat-radio-label-content {
font-weight: normal;
color: rgba(0, 0, 0, 0.54);
}
}
}
.customFielsdPanel {
padding-left: 0px;
::ng-deep.mat-tab-body-wrapper {
padding-left: 0px;
}
}
.mat-expansion-panel-header-description {
flex-direction: row-reverse;
}
.customFieldValues {
box-shadow: none;
border: 1px solid rgba(0,0,0,0.12);
}
.mat-expansion-panel {
margin: 5px;
}
.mat-accordion {
padding: 5px;
}
.mat-tab-group, .mat-tab-body-wrapper, .mat-tab-body-content {
height: 100%;
}
.actionsCustomFields {
display: flex;
align-items: center;
justify-content: center;
}
\ No newline at end of file
import { Component, OnInit, ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { LANG } from '../../translate.component';
import { NotificationService } from '../../notification.service';
import { HeaderService } from '../../../service/header.service';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { MatSidenav } from '@angular/material/sidenav';
import { AppService } from '../../../service/app.service';
import { tap, catchError, filter, exhaustMap, map, finalize } from 'rxjs/operators';
import { ConfirmComponent } from '../../../plugins/modal/confirm.component';
import { of } from 'rxjs';
import { SortPipe } from '../../../plugins/sorting.pipe';
declare function $j(selector: any): any;
@Component({
templateUrl: "custom-fields-administration.component.html",
styleUrls: ['custom-fields-administration.component.scss'],
providers: [NotificationService, AppService, SortPipe]
})
export class CustomFieldsAdministrationComponent implements OnInit {
@ViewChild('snav', { static: true }) public sidenavLeft: MatSidenav;
@ViewChild('snav2', { static: true }) public sidenavRight: MatSidenav;
lang: any = LANG;
loading: boolean = false;
creationMode: any = false;
customFieldsTypes: any[] = [
{
label: this.lang.stringInput,
type: 'string'
},
{
label: this.lang.selectInput,
type: 'select'
},
{
label: this.lang.dateInput,
type: 'date'
},
{
label: this.lang.radioInput,
type: 'radio'
},
{
label: this.lang.checkboxInput,
type: 'checkbox'
}
]
customFields: any[] = [
{
id: 4,
label: 'Nouveau champ',
type: 'select',
values: [],
default_value: ''
}
];
customFieldClone: any;
dialogRef: MatDialogRef<any>;
constructor(
public http: HttpClient,
private notify: NotificationService,
public dialog: MatDialog,
private headerService: HeaderService,
public appService: AppService,
private sortPipe: SortPipe
) {
}
ngOnInit(): void {
this.headerService.setHeader(this.lang.administration + ' ' + this.lang.customFields);
window['MainHeaderComponent'].setSnav(this.sidenavLeft);
window['MainHeaderComponent'].setSnavRight(this.sidenavRight);
this.http.get("../../rest/customFields").pipe(
// TO FIX DATA BINDING SIMPLE ARRAY VALUES
map((data: any) => {
data.customFields.forEach((element: any) => {
element.values = element.values.map((info: any) => {
return {
label: info
}
});
});
return data;
}),
tap((data: any) => {
this.customFields = data.customFields;
}),
finalize(() => this.loading = false),
catchError((err: any) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
addCustomField(customFieldType: any) {
let newCustomField: any = {};
this.dialogRef = this.dialog.open(ConfirmComponent, { autoFocus: false, disableClose: true, data: { title: this.lang.add, msg: this.lang.confirmAction } });
this.dialogRef.afterClosed().pipe(
filter((data: string) => data === 'ok'),
tap((data: any) => {
newCustomField = {
id: data.customFieldId,
label: 'Nouveau champ',
type: customFieldType.type,
values: [],
default_value: ''
}
}),
exhaustMap((data) => this.http.post('../../rest/customFields', newCustomField)),
tap(() => {
this.customFields.push(newCustomField);
this.notify.success(this.lang.customFieldAdded);
}),
catchError((err: any) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
addValue(indexCustom: number) {
this.customFields[indexCustom].values.push(
{
label: 'Nouvelle donnée'
}
);
}
removeValue(customField: any, indexValue: number) {
customField.values.splice(indexValue, 1);
}
removeCustomField(indexCustom: number) {
this.dialogRef = this.dialog.open(ConfirmComponent, { autoFocus: false, disableClose: true, data: { title: this.lang.delete + ' "' + this.customFields[indexCustom].label + '"', msg: this.lang.confirmAction } });
this.dialogRef.afterClosed().pipe(
filter((data: string) => data === 'ok'),
tap(() => {
this.customFields.splice(indexCustom, 1);
}),
catchError((err: any) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
updateCustomField(customField: any) {
// TO FIX DATA BINDING SIMPLE ARRAY VALUES
const customFieldToUpdate = { ...customField };
customFieldToUpdate.values = customField.values.map((data: any) => data.label)
this.http.put('../../rest/customFields/' + customField.id, customFieldToUpdate).pipe(
tap(() => {
this.notify.success(this.lang.customFieldUpdated);
}),
catchError((err: any) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
sortValues(customField: any) {
customField.values = this.sortPipe.transform(customField.values, 'label');
}
initCustomFieldCheck(customField: any) {
console.log('init');
this.customFieldClone = JSON.parse(JSON.stringify(customField));
}
isModified(customField: any) {
if (JSON.stringify(customField) === JSON.stringify(this.customFieldClone)) {
return true;
} else {
return false;
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment