From 1602fb84a429e33041ba167c2ea0d1618cd704f4 Mon Sep 17 00:00:00 2001
From: Alex Orluc <alex.orluc@maarch.org>
Date: Mon, 26 Feb 2018 18:20:26 +0100
Subject: [PATCH] FEAT #73 add diffusionmodels components + views

---
 ...ffusionModel-administration.component.html | 122 ++++++++++++++++++
 ...fusionModels-administration.component.html |  95 ++++++++++++++
 .../administration-routing.module.js          |   4 +
 .../administration-routing.module.ts          |   4 +
 .../administration/administration.module.js   |   6 +-
 .../administration/administration.module.ts   |   6 +-
 ...diffusionModel-administration.component.js | 115 +++++++++++++++++
 ...diffusionModel-administration.component.ts |  95 ++++++++++++++
 ...iffusionModels-administration.component.js |  98 ++++++++++++++
 ...iffusionModels-administration.component.ts |  92 +++++++++++++
 apps/maarch_entreprise/js/angularFunctions.js |   2 +
 modules/entities/xml/services.xml             |  15 +++
 sql/17_xx.sql                                 |   1 +
 sql/data_fr.sql                               |   3 +-
 .../controllers/ListTemplateController.php    |  95 ++++++++------
 15 files changed, 707 insertions(+), 46 deletions(-)
 create mode 100644 apps/maarch_entreprise/Views/diffusionModel-administration.component.html
 create mode 100644 apps/maarch_entreprise/Views/diffusionModels-administration.component.html
 create mode 100644 apps/maarch_entreprise/js/angular/app/administration/diffusionModel-administration.component.js
 create mode 100644 apps/maarch_entreprise/js/angular/app/administration/diffusionModel-administration.component.ts
 create mode 100644 apps/maarch_entreprise/js/angular/app/administration/diffusionModels-administration.component.js
 create mode 100644 apps/maarch_entreprise/js/angular/app/administration/diffusionModels-administration.component.ts

diff --git a/apps/maarch_entreprise/Views/diffusionModel-administration.component.html b/apps/maarch_entreprise/Views/diffusionModel-administration.component.html
new file mode 100644
index 00000000000..6d33ad19f6a
--- /dev/null
+++ b/apps/maarch_entreprise/Views/diffusionModel-administration.component.html
@@ -0,0 +1,122 @@
+<div class="admin-container" [class.admin-is-mobile]="mobileQuery.matches">
+    <mat-toolbar color="primary" class="admin-toolbar">
+        <button mat-button (click)="snav.toggle()">
+            <mat-icon class="maarchLogo" [svgIcon]="mobileQuery.matches ? 'maarchLogoOnly' : 'maarchLogo'"></mat-icon>
+        </button>
+        <h1 class="admin-toolbar-title" *ngIf="!creationMode">{{lang.diffusionModelModification}}
+            <small [class.hide-for-mobile]="mobileQuery.matches">{{diffusionModel.title}} ({{diffusionModel.object_id}})</small>
+        </h1>
+        <h1 class="admin-toolbar-title" *ngIf="creationMode">{{lang.diffusionModelCreation}}
+            <small [class.hide-for-mobile]="mobileQuery.matches">{{diffusionModel.title}} ({{diffusionModel.object_id}})</small>
+        </h1>
+        <span style="flex: 1 1 auto;"></span>
+        <button mat-icon-button (click)="snav2.toggle()">
+            <mat-icon class="fa fa-gear fa-2x"></mat-icon>
+        </button>
+    </mat-toolbar>
+    <mat-sidenav-container class="admin-sidenav-container" [style.marginTop.px]="mobileQuery.matches ? 56 : 0">
+        <mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" fixedTopGap="56"
+            [opened]="mobileQuery.matches ? false : true">
+            <mat-nav-list>
+                <a mat-list-item href="index.php">
+                    <mat-icon color="primary" mat-list-icon class="fa fa-home"></mat-icon>
+                    <p mat-line>
+                        {{lang.home}}
+                    </p>
+                </a>
+                <a mat-list-item routerLink="/administration/diffusionModels">
+                    <mat-icon color="primary" mat-list-icon class="fa fa-chevron-left"></mat-icon>
+                    <p mat-line>
+                        {{lang.back}}
+                    </p>
+                </a>
+            </mat-nav-list>
+            <mat-divider></mat-divider>
+            <mat-nav-list>
+                <h3 mat-subheader>{{lang.tools}}</h3>
+            </mat-nav-list>
+        </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">
+
+                <mat-tab-group [(selectedIndex)]="selectedTabIndex_1">
+                    <mat-tab label="{{lang.informations}}">
+                        <form class="form-horizontal" (ngSubmit)="onSubmit()" #diffusionModelForm="ngForm">
+                            <mat-form-field>
+                                <input matInput *ngIf="creationMode" name="object_id" placeholder="{{lang.id}}" [(ngModel)]="diffusionModel.object_id" pattern="^[\w.-]*$"
+                                    maxlength="32" required>
+                                <input matInput *ngIf="!creationMode" name="object_id" placeholder="{{lang.id}}" title="{{lang.id}}" [(ngModel)]="diffusionModel.object_id"
+                                    disabled>
+                            </mat-form-field>
+                            <mat-form-field>
+                                <input matInput name="title" title="{{lang.label}}" placeholder="{{lang.label}}" [(ngModel)]="diffusionModel.title" maxlength="255"
+                                    required>
+                            </mat-form-field>
+                            <mat-form-field>
+                                <textarea matInput name="description" title="{{lang.description}}" placeholder="{{lang.description}}" [(ngModel)]="diffusionModel.description"
+                                        matTextareaAutosize matAutosizeMinRows="1" matAutosizeMaxRows="5"></textarea>
+                            </mat-form-field>
+                            <div class="col-md-12 text-center" style="padding:10px;">
+                                <button mat-raised-button [disabled]="!diffusionModelForm.form.valid" color="primary">{{lang.save}}</button>
+                            </div>
+                        </form>
+                    </mat-tab>
+                </mat-tab-group>
+
+            </mat-card>
+        </mat-sidenav-content>
+        <mat-sidenav #snav2 [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" fixedTopGap="56"
+            position='end' [opened]="mobileQuery.matches ? false : true" class="col-md-4 col-xs-11">
+
+            <mat-nav-list>
+                <mat-tab-group>
+                    <mat-tab label="Utilisateur(s) associé(s)" *ngIf="!creationMode">
+                        <div class="row" style="margin:0px;">
+                            <div class="col-md-12">
+                                <mat-form-field>
+                                    <input #autocompleteFilter type="text" placeholder="Ajouter une personne" matInput [matAutocomplete]="auto"
+                                        [formControl]="userCtrl">
+                                    <mat-autocomplete #auto="matAutocomplete">
+                                        <mat-option *ngFor="let elem of filteredUsers | async" [value]="elem.id" (click)="addElemListModel(elem)">
+                                            <p mat-line>
+                                                <span class="col-sm-1">
+                                                    <i color="primary" class="fa fa-user fa-2x"></i>
+                                                </span>
+                                                <span class="col-sm-11">
+                                                    {{ elem.idToDisplay }}
+                                                    <small>{{ elem.otherInfo }}</small>
+                                                </span>
+                                            </p>
+                                        </mat-option>
+                                    </mat-autocomplete>
+                                </mat-form-field>
+                                <mat-list>
+                                    <span *ngFor="let role of diffusionModel.roles; let i = index">
+                                        <h3 mat-subheader>{{role.label}}</h3>
+                                        <span dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="diffusionModel.diffusionList">
+                                            <div style="min-height:30px;">
+                                                <mat-list-item disableRipple="true" *ngFor="let template of diffusionModel.diffusionList; let i = index" title="deplacer"
+                                                    dnd-sortable (onDropSuccess)="updateDiffList(template,role.id)" [sortableIndex]="i">
+                                                    <mat-icon color="primary" mat-list-icon class="fa fa-user"></mat-icon>
+                                                    <p mat-line>{{template.item_id}}
+                                                        <small style="opacity:0.5;"></small>
+                                                    </p>
+                                                    <button matTooltip="{{lang.delete}}" mat-icon-button color="warn" (click)="removeDiffList(i,role.id)">
+                                                        <mat-icon class="fa fa-remove"></mat-icon>
+                                                    </button>
+                                                </mat-list-item>
+                                            </div>
+                                        </span>
+                                    </span>
+                                </mat-list>
+                            </div>
+                        </div>
+                    </mat-tab>
+                </mat-tab-group>
+            </mat-nav-list>
+        </mat-sidenav>
+    </mat-sidenav-container>
+</div>
\ No newline at end of file
diff --git a/apps/maarch_entreprise/Views/diffusionModels-administration.component.html b/apps/maarch_entreprise/Views/diffusionModels-administration.component.html
new file mode 100644
index 00000000000..2c084dceece
--- /dev/null
+++ b/apps/maarch_entreprise/Views/diffusionModels-administration.component.html
@@ -0,0 +1,95 @@
+<div class="admin-container" [class.admin-is-mobile]="mobileQuery.matches">
+    <mat-toolbar color="primary" class="admin-toolbar">
+        <button mat-button (click)="snav.toggle()">
+                <mat-icon class="maarchLogo" [svgIcon]="mobileQuery.matches ? 'maarchLogoOnly' : 'maarchLogo'"></mat-icon>
+            </button>
+        <h1 class="admin-toolbar-title">{{lang.administration}} {{lang.diffusionModels}}
+            <small [class.hide-for-mobile]="mobileQuery.matches">{{listTemplates.length}} {{lang.diffusionModels}}</small>
+        </h1>
+        <span style="flex: 1 1 auto;"></span>
+        <button mat-icon-button (click)="snav2.toggle()">
+            <mat-icon class="fa fa-gear fa-2x"></mat-icon>
+        </button>
+    </mat-toolbar>
+    <mat-sidenav-container class="admin-sidenav-container" [style.marginTop.px]="mobileQuery.matches ? 56 : 0">
+        <mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" fixedTopGap="56"
+            [opened]="mobileQuery.matches ? false : true">
+            <mat-nav-list>
+                <a mat-list-item href="index.php">
+                    <mat-icon color="primary" mat-list-icon class="fa fa-home"></mat-icon>
+                    <p mat-line>
+                        {{lang.home}}
+                    </p>
+                </a>
+                <a mat-list-item routerLink="/administration">
+                    <mat-icon color="primary" mat-list-icon class="fa fa-chevron-left"></mat-icon>
+                    <p mat-line>
+                        {{lang.back}}
+                    </p>
+                </a>
+            </mat-nav-list>
+            <mat-divider></mat-divider>
+            <mat-nav-list>
+                <h3 mat-subheader>{{lang.tools}}</h3>
+                <a mat-list-item routerLink="/administration/groups/new">
+                    <mat-icon color="primary" mat-list-icon class="fa fa-plus"></mat-icon>
+                    <p mat-line>
+                        {{lang.add}}
+                    </p>
+                </a>
+            </mat-nav-list>
+        </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">
+                <div class="row" style="margin:0px;">
+                    <div class="col-md-6 col-xs-6">
+                        <mat-form-field>
+                            <input matInput (keyup)="applyFilter($event.target.value)" placeholder="{{lang.filterBy}}">
+                        </mat-form-field>
+                    </div>
+                    <div class="col-md-6 col-xs-6">
+                        <mat-paginator #paginator [length]="100" [pageSize]="10" [pageSizeOptions]="[10, 25, 50, 100]">
+                        </mat-paginator>
+                    </div>
+                </div>
+                <mat-table #table [dataSource]="dataSource" matSort matSortActive="title" matSortDirection="asc">
+                    <ng-container matColumnDef="title">
+                        <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:2;">{{lang.label}}</mat-header-cell>
+                        <mat-cell *matCellDef="let element" matTooltip="{{lang.view}}" style="cursor:pointer;flex:2;" routerLink="/administration/diffusionModels/{{element.id}}">
+                        {{element.title}} </mat-cell>
+                    </ng-container>
+                    <ng-container matColumnDef="description">
+                        <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:2;">{{lang.description}}</mat-header-cell>
+                        <mat-cell *matCellDef="let element" matTooltip="{{lang.view}}" style="cursor:pointer;flex:2;" routerLink="/administration/diffusionModels/{{element.id}}">
+                        {{element.description}} </mat-cell>
+                    </ng-container>
+                    <ng-container matColumnDef="object_type">
+                        <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:2;">{{lang.type}}</mat-header-cell>
+                        <mat-cell *matCellDef="let element" matTooltip="{{lang.view}}" style="cursor:pointer;flex:2;" routerLink="/administration/diffusionModels/{{element.id}}">
+                        {{element.object_type}} </mat-cell>
+                    </ng-container>
+                    <ng-container matColumnDef="actions">
+                        <mat-header-cell *matHeaderCellDef style="flex:1;"></mat-header-cell>
+                        <mat-cell *matCellDef="let element" style="text-align:right;flex:1;">
+                            <button mat-icon-button color="warn" matTooltip="{{lang.delete}}" (click)="preDelete(element)">
+                                <mat-icon class="fa fa-trash fa-2x" aria-hidden="true"></mat-icon>
+                            </button>
+                        </mat-cell>
+                    </ng-container>
+                    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
+                    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
+                </mat-table>
+            </mat-card>
+        </mat-sidenav-content>
+        <mat-sidenav #snav2 [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" fixedTopGap="56"
+            position='end' [opened]="mobileQuery.matches ? false : false">
+
+            <mat-nav-list>
+                <h3 mat-subheader>Actions</h3>
+            </mat-nav-list>
+        </mat-sidenav>
+    </mat-sidenav-container>
+</div>
\ No newline at end of file
diff --git a/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.js b/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.js
index b974c4e8936..3a744f7871c 100644
--- a/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.js
+++ b/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.js
@@ -16,6 +16,8 @@ var group_administration_component_1 = require("./group-administration.component
 var baskets_administration_component_1 = require("./baskets-administration.component");
 var basket_administration_component_1 = require("./basket-administration.component");
 var doctypes_administration_component_1 = require("./doctypes-administration.component");
+var diffusionModels_administration_component_1 = require("./diffusionModels-administration.component");
+var diffusionModel_administration_component_1 = require("./diffusionModel-administration.component");
 var entities_administration_component_1 = require("./entities-administration.component");
 var entity_administration_component_1 = require("./entity-administration.component");
 var statuses_administration_component_1 = require("./statuses-administration.component");
@@ -51,6 +53,8 @@ var AdministrationRoutingModule = /** @class */ (function () {
                     { path: 'administration/baskets/new', component: basket_administration_component_1.BasketAdministrationComponent },
                     { path: 'administration/baskets/:id', component: basket_administration_component_1.BasketAdministrationComponent },
                     { path: 'administration/doctypes', component: doctypes_administration_component_1.DoctypesAdministrationComponent },
+                    { path: 'administration/diffusionModels', component: diffusionModels_administration_component_1.DiffusionModelsAdministrationComponent },
+                    { path: 'administration/diffusionModels/:id', component: diffusionModel_administration_component_1.DiffusionModelAdministrationComponent },
                     { path: 'administration/entities', component: entities_administration_component_1.EntitiesAdministrationComponent },
                     { path: 'administration/entities/new', component: entity_administration_component_1.EntityAdministrationComponent },
                     { path: 'administration/entities/:id', component: entity_administration_component_1.EntityAdministrationComponent },
diff --git a/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.ts b/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.ts
index 216332871c5..2e5ee0157c5 100755
--- a/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.ts
+++ b/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.ts
@@ -9,6 +9,8 @@ import { GroupAdministrationComponent }                 from './group-administra
 import { BasketsAdministrationComponent }               from './baskets-administration.component';
 import { BasketAdministrationComponent }                from './basket-administration.component';
 import { DoctypesAdministrationComponent }              from './doctypes-administration.component';
+import { DiffusionModelsAdministrationComponent }       from './diffusionModels-administration.component';
+import { DiffusionModelAdministrationComponent }       from './diffusionModel-administration.component';
 import { EntitiesAdministrationComponent }              from './entities-administration.component';
 import { EntityAdministrationComponent }                from './entity-administration.component';
 import { StatusesAdministrationComponent }              from './statuses-administration.component';
@@ -42,6 +44,8 @@ import { UpdateStatusAdministrationComponent }          from './update-status-ad
             { path: 'administration/baskets/new', component: BasketAdministrationComponent },
             { path: 'administration/baskets/:id', component: BasketAdministrationComponent },
             { path: 'administration/doctypes', component: DoctypesAdministrationComponent },
+            { path: 'administration/diffusionModels', component: DiffusionModelsAdministrationComponent },
+            { path: 'administration/diffusionModels/:id', component: DiffusionModelAdministrationComponent },
             { path: 'administration/entities', component: EntitiesAdministrationComponent },
             { path: 'administration/entities/new', component: EntityAdministrationComponent },
             { path: 'administration/entities/:id', component: EntityAdministrationComponent },
diff --git a/apps/maarch_entreprise/js/angular/app/administration/administration.module.js b/apps/maarch_entreprise/js/angular/app/administration/administration.module.js
index 3de7df5861f..ea8ee1fc6d3 100644
--- a/apps/maarch_entreprise/js/angular/app/administration/administration.module.js
+++ b/apps/maarch_entreprise/js/angular/app/administration/administration.module.js
@@ -21,6 +21,8 @@ var baskets_administration_component_1 = require("./baskets-administration.compo
 var basket_administration_component_1 = require("./basket-administration.component");
 var entities_administration_component_1 = require("./entities-administration.component");
 var entity_administration_component_1 = require("./entity-administration.component");
+var diffusionModels_administration_component_1 = require("./diffusionModels-administration.component");
+var diffusionModel_administration_component_1 = require("./diffusionModel-administration.component");
 var doctypes_administration_component_1 = require("./doctypes-administration.component");
 var statuses_administration_component_1 = require("./statuses-administration.component");
 var status_administration_component_1 = require("./status-administration.component");
@@ -80,7 +82,9 @@ var AdministrationModule = /** @class */ (function () {
                 entities_administration_component_1.EntitiesAdministrationRedirectModalComponent,
                 groups_administration_component_1.GroupsAdministrationRedirectModalComponent,
                 basket_administration_component_1.BasketAdministrationSettingsModalComponent,
-                basket_administration_component_1.BasketAdministrationGroupListModalComponent
+                basket_administration_component_1.BasketAdministrationGroupListModalComponent,
+                diffusionModels_administration_component_1.DiffusionModelsAdministrationComponent,
+                diffusionModel_administration_component_1.DiffusionModelAdministrationComponent
             ],
             entryComponents: [
                 users_administration_component_1.UsersAdministrationRedirectModalComponent,
diff --git a/apps/maarch_entreprise/js/angular/app/administration/administration.module.ts b/apps/maarch_entreprise/js/angular/app/administration/administration.module.ts
index 8aaaf06a00b..2ecfe7d8234 100755
--- a/apps/maarch_entreprise/js/angular/app/administration/administration.module.ts
+++ b/apps/maarch_entreprise/js/angular/app/administration/administration.module.ts
@@ -15,6 +15,8 @@ import { BasketsAdministrationComponent }               from './baskets-administ
 import { BasketAdministrationComponent, BasketAdministrationSettingsModalComponent, BasketAdministrationGroupListModalComponent }                from './basket-administration.component';
 import { EntitiesAdministrationComponent, EntitiesAdministrationRedirectModalComponent} from './entities-administration.component';
 import { EntityAdministrationComponent }                from './entity-administration.component';
+import { DiffusionModelsAdministrationComponent }       from './diffusionModels-administration.component';
+import { DiffusionModelAdministrationComponent }        from './diffusionModel-administration.component';
 import { DoctypesAdministrationComponent }              from './doctypes-administration.component';
 import { StatusesAdministrationComponent }              from './statuses-administration.component';
 import { StatusAdministrationComponent }                from './status-administration.component';
@@ -71,7 +73,9 @@ import { NotificationAdministrationComponent }          from './notification-adm
         EntitiesAdministrationRedirectModalComponent,
         GroupsAdministrationRedirectModalComponent,
         BasketAdministrationSettingsModalComponent,
-        BasketAdministrationGroupListModalComponent
+        BasketAdministrationGroupListModalComponent,
+        DiffusionModelsAdministrationComponent,
+        DiffusionModelAdministrationComponent
     ],
     entryComponents: [
         UsersAdministrationRedirectModalComponent,
diff --git a/apps/maarch_entreprise/js/angular/app/administration/diffusionModel-administration.component.js b/apps/maarch_entreprise/js/angular/app/administration/diffusionModel-administration.component.js
new file mode 100644
index 00000000000..55b1d3eed0c
--- /dev/null
+++ b/apps/maarch_entreprise/js/angular/app/administration/diffusionModel-administration.component.js
@@ -0,0 +1,115 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var core_1 = require("@angular/core");
+var layout_1 = require("@angular/cdk/layout");
+var http_1 = require("@angular/common/http");
+var router_1 = require("@angular/router");
+var translate_component_1 = require("../translate.component");
+var notification_service_1 = require("../notification.service");
+var material_1 = require("@angular/material");
+var autocomplete_plugin_1 = require("../../plugins/autocomplete.plugin");
+var DiffusionModelAdministrationComponent = /** @class */ (function (_super) {
+    __extends(DiffusionModelAdministrationComponent, _super);
+    function DiffusionModelAdministrationComponent(changeDetectorRef, media, http, route, router, notify) {
+        var _this = _super.call(this, http, ['users']) || this;
+        _this.http = http;
+        _this.route = route;
+        _this.router = router;
+        _this.notify = notify;
+        _this.lang = translate_component_1.LANG;
+        _this.diffusionModel = {};
+        _this.loading = false;
+        _this.displayedColumns = ['firstname', 'lastname'];
+        $j("link[href='merged_css.php']").remove();
+        _this.mobileQuery = media.matchMedia('(max-width: 768px)');
+        _this._mobileQueryListener = function () { return changeDetectorRef.detectChanges(); };
+        _this.mobileQuery.addListener(_this._mobileQueryListener);
+        return _this;
+    }
+    DiffusionModelAdministrationComponent.prototype.applyFilter = function (filterValue) {
+        filterValue = filterValue.trim(); // Remove whitespace
+        filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
+        this.dataSource.filter = filterValue;
+    };
+    DiffusionModelAdministrationComponent.prototype.ngOnDestroy = function () {
+        this.mobileQuery.removeListener(this._mobileQueryListener);
+    };
+    DiffusionModelAdministrationComponent.prototype.updateBreadcrumb = function (applicationName) {
+        var breadCrumb = "<a href='index.php?reinit=true'>" + applicationName + "</a> > <a onclick='location.hash = \"/administration\"' style='cursor: pointer'>" + this.lang.administration + "</a> > <a onclick='location.hash = \"/administration/groups\"' style='cursor: pointer'>" + this.lang.groups + "</a> > ";
+        if (this.creationMode == true) {
+            breadCrumb += this.lang.groupCreation;
+        }
+        else {
+            breadCrumb += this.lang.groupModification;
+        }
+        $j('#ariane')[0].innerHTML = breadCrumb;
+    };
+    DiffusionModelAdministrationComponent.prototype.ngOnInit = function () {
+        var _this = this;
+        this.coreUrl = angularGlobals.coreUrl;
+        this.loading = true;
+        this.route.params.subscribe(function (params) {
+            if (typeof params['id'] == "undefined") {
+                _this.creationMode = true;
+                _this.loading = false;
+                _this.updateBreadcrumb(angularGlobals.applicationName);
+            }
+            else {
+                _this.creationMode = false;
+                _this.http.get(_this.coreUrl + "rest/listTemplates/" + params['id'])
+                    .subscribe(function (data) {
+                    _this.updateBreadcrumb(angularGlobals.applicationName);
+                    _this.diffusionModel = data['listTemplate'];
+                    _this.diffusionModel.roles = [{
+                            "id": "avis",
+                            "label": "avis"
+                        }];
+                    _this.loading = false;
+                    setTimeout(function () {
+                        _this.dataSource = new material_1.MatTableDataSource(_this.diffusionModel);
+                        _this.dataSource.paginator = _this.paginator;
+                        _this.dataSource.sort = _this.sort;
+                    }, 0);
+                }, function () {
+                    location.href = "index.php";
+                });
+            }
+        });
+    };
+    __decorate([
+        core_1.ViewChild(material_1.MatPaginator),
+        __metadata("design:type", material_1.MatPaginator)
+    ], DiffusionModelAdministrationComponent.prototype, "paginator", void 0);
+    __decorate([
+        core_1.ViewChild(material_1.MatSort),
+        __metadata("design:type", material_1.MatSort)
+    ], DiffusionModelAdministrationComponent.prototype, "sort", void 0);
+    DiffusionModelAdministrationComponent = __decorate([
+        core_1.Component({
+            templateUrl: angularGlobals["diffusionModel-administrationView"],
+            providers: [notification_service_1.NotificationService]
+        }),
+        __metadata("design:paramtypes", [core_1.ChangeDetectorRef, layout_1.MediaMatcher, http_1.HttpClient, router_1.ActivatedRoute, router_1.Router, notification_service_1.NotificationService])
+    ], DiffusionModelAdministrationComponent);
+    return DiffusionModelAdministrationComponent;
+}(autocomplete_plugin_1.AutoCompletePlugin));
+exports.DiffusionModelAdministrationComponent = DiffusionModelAdministrationComponent;
diff --git a/apps/maarch_entreprise/js/angular/app/administration/diffusionModel-administration.component.ts b/apps/maarch_entreprise/js/angular/app/administration/diffusionModel-administration.component.ts
new file mode 100644
index 00000000000..4e0d82ab60a
--- /dev/null
+++ b/apps/maarch_entreprise/js/angular/app/administration/diffusionModel-administration.component.ts
@@ -0,0 +1,95 @@
+import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
+import { MediaMatcher } from '@angular/cdk/layout';
+import { HttpClient } from '@angular/common/http';
+import { ActivatedRoute, Router } from '@angular/router';
+import { LANG } from '../translate.component';
+import { NotificationService } from '../notification.service';
+import { MatPaginator, MatTableDataSource, MatSort} from '@angular/material';
+
+import { AutoCompletePlugin } from '../../plugins/autocomplete.plugin';
+
+declare function $j(selector: any) : any;
+
+declare const angularGlobals : any;
+
+
+@Component({
+    templateUrl : angularGlobals["diffusionModel-administrationView"],
+    providers   : [NotificationService]
+})
+export class DiffusionModelAdministrationComponent extends AutoCompletePlugin implements OnInit {
+    mobileQuery: MediaQueryList;
+    private _mobileQueryListener: () => void;
+    coreUrl                     : string;
+    lang                        : any       = LANG;
+
+    creationMode                : boolean;
+
+    diffusionModel               : any       = {};
+    loading                     : boolean   = false;
+
+    displayedColumns = ['firstname', 'lastname'];
+    dataSource      : any;
+    @ViewChild(MatPaginator) paginator: MatPaginator;
+    @ViewChild(MatSort) sort: MatSort;
+    applyFilter(filterValue: string) {
+        filterValue = filterValue.trim(); // Remove whitespace
+        filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
+        this.dataSource.filter = filterValue;
+    }
+
+    constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher,public http: HttpClient, private route: ActivatedRoute, private router: Router, private notify: NotificationService) {
+        super(http, ['users']);
+        $j("link[href='merged_css.php']").remove();
+        this.mobileQuery = media.matchMedia('(max-width: 768px)');
+        this._mobileQueryListener = () => changeDetectorRef.detectChanges();
+        this.mobileQuery.addListener(this._mobileQueryListener);
+    }
+    ngOnDestroy(): void {
+        this.mobileQuery.removeListener(this._mobileQueryListener);
+    }
+    
+    updateBreadcrumb(applicationName: string) {
+        var breadCrumb = "<a href='index.php?reinit=true'>" + applicationName + "</a> > <a onclick='location.hash = \"/administration\"' style='cursor: pointer'>" + this.lang.administration + "</a> > <a onclick='location.hash = \"/administration/groups\"' style='cursor: pointer'>" + this.lang.groups + "</a> > ";
+        if (this.creationMode == true) {
+            breadCrumb += this.lang.groupCreation;
+        } else {
+            breadCrumb += this.lang.groupModification;
+        }
+        $j('#ariane')[0].innerHTML = breadCrumb;
+    }
+
+    ngOnInit(): void {
+        this.coreUrl = angularGlobals.coreUrl;
+
+        this.loading = true;
+
+        this.route.params.subscribe(params => {
+            if (typeof params['id'] == "undefined") {
+                this.creationMode = true;
+                this.loading = false;
+                this.updateBreadcrumb(angularGlobals.applicationName);
+            } else {
+                this.creationMode = false;
+                this.http.get(this.coreUrl + "rest/listTemplates/" + params['id'])
+                    .subscribe((data : any) => {
+                        this.updateBreadcrumb(angularGlobals.applicationName);
+                        this.diffusionModel = data['listTemplate'];
+                        this.diffusionModel.roles = [{
+                            "id":"avis",
+                            "label":"avis"
+                        }]
+                        this.loading = false;
+                        setTimeout(() => {
+                            this.dataSource = new MatTableDataSource(this.diffusionModel);
+                            this.dataSource.paginator = this.paginator;
+                            this.dataSource.sort = this.sort;
+                        }, 0);
+
+                    }, () => {
+                        location.href = "index.php";
+                    });
+            }
+        });
+    }
+}
diff --git a/apps/maarch_entreprise/js/angular/app/administration/diffusionModels-administration.component.js b/apps/maarch_entreprise/js/angular/app/administration/diffusionModels-administration.component.js
new file mode 100644
index 00000000000..c60adbbc2ae
--- /dev/null
+++ b/apps/maarch_entreprise/js/angular/app/administration/diffusionModels-administration.component.js
@@ -0,0 +1,98 @@
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var core_1 = require("@angular/core");
+var layout_1 = require("@angular/cdk/layout");
+var http_1 = require("@angular/common/http");
+var translate_component_1 = require("../translate.component");
+var notification_service_1 = require("../notification.service");
+var material_1 = require("@angular/material");
+var DiffusionModelsAdministrationComponent = /** @class */ (function () {
+    function DiffusionModelsAdministrationComponent(changeDetectorRef, media, http, notify, dialog) {
+        this.http = http;
+        this.notify = notify;
+        this.dialog = dialog;
+        this.config = {};
+        this.lang = translate_component_1.LANG;
+        this.listTemplates = [];
+        this.listTemplatesForAssign = [];
+        this.loading = false;
+        this.displayedColumns = ['title', 'description', 'object_type', 'actions'];
+        this.dataSource = new material_1.MatTableDataSource(this.listTemplates);
+        $j("link[href='merged_css.php']").remove();
+        this.mobileQuery = media.matchMedia('(max-width: 768px)');
+        this._mobileQueryListener = function () { return changeDetectorRef.detectChanges(); };
+        this.mobileQuery.addListener(this._mobileQueryListener);
+    }
+    DiffusionModelsAdministrationComponent.prototype.applyFilter = function (filterValue) {
+        filterValue = filterValue.trim(); // Remove whitespace
+        filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
+        this.dataSource.filter = filterValue;
+    };
+    DiffusionModelsAdministrationComponent.prototype.ngOnDestroy = function () {
+        this.mobileQuery.removeListener(this._mobileQueryListener);
+    };
+    DiffusionModelsAdministrationComponent.prototype.updateBreadcrumb = function (applicationName) {
+        if ($j('#ariane')[0]) {
+            $j('#ariane')[0].innerHTML = "<a href='index.php?reinit=true'>" + applicationName + "</a> > <a onclick='location.hash = \"/administration\"' style='cursor: pointer'>Administration</a> > Groupes";
+        }
+    };
+    DiffusionModelsAdministrationComponent.prototype.ngOnInit = function () {
+        var _this = this;
+        this.updateBreadcrumb(angularGlobals.applicationName);
+        this.coreUrl = angularGlobals.coreUrl;
+        this.loading = true;
+        this.http.get(this.coreUrl + "rest/listTemplates")
+            .subscribe(function (data) {
+            _this.listTemplates = data['listTemplates'];
+            _this.loading = false;
+            setTimeout(function () {
+                _this.dataSource = new material_1.MatTableDataSource(_this.listTemplates);
+                _this.dataSource.paginator = _this.paginator;
+                _this.dataSource.sort = _this.sort;
+            }, 0);
+        }, function () {
+            location.href = "index.php";
+        });
+    };
+    DiffusionModelsAdministrationComponent.prototype.delete = function (listTemplate) {
+        var _this = this;
+        this.http.delete(this.coreUrl + "rest/listTemplates/" + listTemplate['id'])
+            .subscribe(function (data) {
+            setTimeout(function () {
+                _this.listTemplates = data['listTemplates'];
+                _this.dataSource = new material_1.MatTableDataSource(_this.listTemplates);
+                _this.dataSource.paginator = _this.paginator;
+                _this.dataSource.sort = _this.sort;
+            }, 0);
+            _this.notify.success(_this.lang.groupDeleted);
+        }, function (err) {
+            _this.notify.error(err.error.errors);
+        });
+    };
+    __decorate([
+        core_1.ViewChild(material_1.MatPaginator),
+        __metadata("design:type", material_1.MatPaginator)
+    ], DiffusionModelsAdministrationComponent.prototype, "paginator", void 0);
+    __decorate([
+        core_1.ViewChild(material_1.MatSort),
+        __metadata("design:type", material_1.MatSort)
+    ], DiffusionModelsAdministrationComponent.prototype, "sort", void 0);
+    DiffusionModelsAdministrationComponent = __decorate([
+        core_1.Component({
+            templateUrl: angularGlobals["diffusionModels-administrationView"],
+            providers: [notification_service_1.NotificationService]
+        }),
+        __metadata("design:paramtypes", [core_1.ChangeDetectorRef, layout_1.MediaMatcher, http_1.HttpClient, notification_service_1.NotificationService, material_1.MatDialog])
+    ], DiffusionModelsAdministrationComponent);
+    return DiffusionModelsAdministrationComponent;
+}());
+exports.DiffusionModelsAdministrationComponent = DiffusionModelsAdministrationComponent;
diff --git a/apps/maarch_entreprise/js/angular/app/administration/diffusionModels-administration.component.ts b/apps/maarch_entreprise/js/angular/app/administration/diffusionModels-administration.component.ts
new file mode 100644
index 00000000000..57e7ca0f2b1
--- /dev/null
+++ b/apps/maarch_entreprise/js/angular/app/administration/diffusionModels-administration.component.ts
@@ -0,0 +1,92 @@
+import { ChangeDetectorRef, Component, OnInit, ViewChild, Inject, TemplateRef } from '@angular/core';
+import { MediaMatcher } from '@angular/cdk/layout';
+import { HttpClient } from '@angular/common/http';
+import { LANG } from '../translate.component';
+import { NotificationService } from '../notification.service';
+import { MatPaginator, MatTableDataSource, MatSort, MatDialog, MatDialogConfig, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
+
+declare function $j(selector: any): any;
+
+declare var angularGlobals: any;
+
+
+@Component({
+    templateUrl: angularGlobals["diffusionModels-administrationView"],
+    providers: [NotificationService]
+})
+export class DiffusionModelsAdministrationComponent implements OnInit {
+    mobileQuery: MediaQueryList;
+    dialogRef: MatDialogRef<any>;
+    private _mobileQueryListener: () => void;
+    config: any = {};
+    coreUrl: string;
+    lang: any = LANG;
+
+    listTemplates: any[] = [];
+    listTemplatesForAssign: any[] = [];
+
+    loading: boolean = false;
+
+    displayedColumns = ['title', 'description', 'object_type', 'actions'];
+    dataSource = new MatTableDataSource(this.listTemplates);
+    @ViewChild(MatPaginator) paginator: MatPaginator;
+    @ViewChild(MatSort) sort: MatSort;
+    applyFilter(filterValue: string) {
+        filterValue = filterValue.trim(); // Remove whitespace
+        filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
+        this.dataSource.filter = filterValue;
+    }
+
+    constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher,public http: HttpClient, private notify: NotificationService, public dialog: MatDialog) {
+        $j("link[href='merged_css.php']").remove();
+        this.mobileQuery = media.matchMedia('(max-width: 768px)');
+        this._mobileQueryListener = () => changeDetectorRef.detectChanges();
+        this.mobileQuery.addListener(this._mobileQueryListener);
+    }
+
+    ngOnDestroy(): void {
+        this.mobileQuery.removeListener(this._mobileQueryListener);
+    }
+
+    updateBreadcrumb(applicationName: string) {
+        if ($j('#ariane')[0]) {
+            $j('#ariane')[0].innerHTML = "<a href='index.php?reinit=true'>" + applicationName + "</a> > <a onclick='location.hash = \"/administration\"' style='cursor: pointer'>Administration</a> > Groupes";
+        }
+    }
+
+    ngOnInit(): void {
+        this.updateBreadcrumb(angularGlobals.applicationName);
+        this.coreUrl = angularGlobals.coreUrl;
+
+        this.loading = true;
+
+        this.http.get(this.coreUrl + "rest/listTemplates")
+            .subscribe((data: any) => {
+                this.listTemplates = data['listTemplates'];
+                this.loading = false;
+                setTimeout(() => {
+                    this.dataSource = new MatTableDataSource(this.listTemplates);
+                    this.dataSource.paginator = this.paginator;
+                    this.dataSource.sort = this.sort;
+                }, 0);
+            }, () => {
+                location.href = "index.php";
+            });
+    }
+
+    delete(listTemplate: any) {
+        this.http.delete(this.coreUrl + "rest/listTemplates/" + listTemplate['id'])
+            .subscribe((data: any) => {
+                setTimeout(() => {
+                    this.listTemplates = data['listTemplates'];
+                    this.dataSource = new MatTableDataSource(this.listTemplates);
+                    this.dataSource.paginator = this.paginator;
+                    this.dataSource.sort = this.sort;
+                }, 0);
+                this.notify.success(this.lang.groupDeleted);
+
+            }, (err) => {
+                this.notify.error(err.error.errors);
+            });
+    }
+}
\ No newline at end of file
diff --git a/apps/maarch_entreprise/js/angularFunctions.js b/apps/maarch_entreprise/js/angularFunctions.js
index 7b9b815009c..cbb945a60a7 100755
--- a/apps/maarch_entreprise/js/angularFunctions.js
+++ b/apps/maarch_entreprise/js/angularFunctions.js
@@ -14,6 +14,8 @@ function triggerAngular(prodmode, locationToGo) {
         'basket-administration-settings-modal',
         'basket-administration-groupList-modal',
         'doctypes-administration',
+        'diffusionModels-administration',
+        'diffusionModel-administration',
         'entities-administration',
         'entities-administration-redirect-modal',
         'entity-administration',
diff --git a/modules/entities/xml/services.xml b/modules/entities/xml/services.xml
index 1779fc4dd15..4b977241277 100755
--- a/modules/entities/xml/services.xml
+++ b/modules/entities/xml/services.xml
@@ -15,6 +15,21 @@
         </WHEREAMIUSED>
         <angular>true</angular>
     </SERVICE>
+    <SERVICE>
+        <id>manage_entities</id>
+        <name>_LISTMODELS</name>
+        <comment>_MANAGE_LISTMODELS</comment>
+        <servicepage>/administration/diffusionModels</servicepage>
+        <servicetype>admin</servicetype>
+        <system_service>false</system_service>
+        <style>fa fa-th-list</style>
+        <enabled>true</enabled>
+        <WHEREAMIUSED>
+            <page>admin.php</page>
+            <nature>listelement</nature>
+        </WHEREAMIUSED>
+        <angular>true</angular>
+    </SERVICE>
     <SERVICE>
         <id>choose_entity</id>
         <name>_CHOOSE_ENTITY</name>
diff --git a/sql/17_xx.sql b/sql/17_xx.sql
index e6ed782e61d..07a327822a7 100755
--- a/sql/17_xx.sql
+++ b/sql/17_xx.sql
@@ -376,6 +376,7 @@ DROP TABLE IF EXISTS groupbasket_difflist_roles;
 ALTER TABLE listmodels DROP COLUMN IF EXISTS listmodel_type;
 ALTER TABLE listmodels DROP COLUMN IF EXISTS coll_id;
 ALTER TABLE listmodels ADD COLUMN id serial NOT NULL;
+UPDATE listmodels SET title = description WHERE title = '' OR title ISNULL;
 
 -- ************************************************************************* --
 --                               CONVERT                             --
diff --git a/sql/data_fr.sql b/sql/data_fr.sql
index d63c2a3f7da..c5e19a08085 100755
--- a/sql/data_fr.sql
+++ b/sql/data_fr.sql
@@ -1140,7 +1140,8 @@ TRUNCATE TABLE difflist_types;
 INSERT INTO difflist_types (difflist_type_id, difflist_type_label, difflist_type_roles, allow_entities, is_system) VALUES ('entity_id', 'Diffusion aux services', 'dest copy avis', 'Y', 'Y');
 INSERT INTO difflist_types (difflist_type_id, difflist_type_label, difflist_type_roles, allow_entities, is_system) VALUES ('type_id', 'Diffusion selon le type de document', 'dest copy', 'Y', 'Y');
 INSERT INTO difflist_types (difflist_type_id, difflist_type_label, difflist_type_roles, allow_entities, is_system) VALUES ('foldertype_id', 'Diffusion selon le type de dossiers', 'dest copy', 'Y', 'Y');
-INSERT INTO difflist_types (difflist_type_id, difflist_type_label, difflist_type_roles, allow_entities, is_system) VALUES ('VISA_CIRCUIT', 'Circuit de visa', 'visa sign ', 'N', 'N');
+INSERT INTO difflist_types (difflist_type_id, difflist_type_label, difflist_type_roles, allow_entities, is_system) VALUES ('VISA_CIRCUIT', 'Circuit de visa', 'visa sign ', 'N', 'Y');
+INSERT INTO difflist_types (difflist_type_id, difflist_type_label, difflist_type_roles, allow_entities, is_system) VALUES ('AVIS_CIRCUIT', 'Circuit d''avis', 'avis ', 'N', 'Y');
 ------------
 --ACTIONS
 ------------
diff --git a/src/app/entity/controllers/ListTemplateController.php b/src/app/entity/controllers/ListTemplateController.php
index 983cabc6463..23fea3bc268 100644
--- a/src/app/entity/controllers/ListTemplateController.php
+++ b/src/app/entity/controllers/ListTemplateController.php
@@ -1,16 +1,16 @@
 <?php
 
 /**
-* Copyright Maarch since 2008 under licence GPLv3.
-* See LICENCE.txt file at the root folder for more details.
-* This file is part of Maarch software.
-*
-*/
+ * Copyright Maarch since 2008 under licence GPLv3.
+ * See LICENCE.txt file at the root folder for more details.
+ * This file is part of Maarch software.
+ */
 
 /**
-* @brief List Template Controller
-* @author dev@maarch.org
-*/
+ * @brief List Template Controller
+ *
+ * @author dev@maarch.org
+ */
 
 namespace Entity\controllers;
 
@@ -28,7 +28,7 @@ class ListTemplateController
 {
     public function get(Request $request, Response $response)
     {
-        $rawListTemplates = ListTemplateModel::get(['select' => ['id', 'object_id', 'object_type', 'title', 'description']]);
+        $rawListTemplates = ListTemplateModel::get(['select' => ['id', 'object_id', 'object_type', 'title', 'description'], 'where' => ['(object_type <> ?) AND (object_id LIKE ?)'], 'data' => ['entity_id', 'VISA_CIRCUIT_%']]);
 
         $listTemplates = [];
         $tmpTemplates = [];
@@ -47,9 +47,18 @@ class ListTemplateController
         $listTemplates = ListTemplateModel::getById(['id' => $aArgs['id']]);
         if (empty($listTemplates)) {
             return $response->withStatus(400)->withJson(['errors' => 'List template not found']);
+        } else {
+            $listTemplatesObj = array(
+                'object_id' => $listTemplates[0]['object_id'],
+                'object_type' => $listTemplates[0]['object_type'],
+                'object_type' => $listTemplates[0]['object_type'],
+                'title' => $listTemplates[0]['title'],
+                'description' => $listTemplates[0]['description'],
+                'diffusionList' => [$listTemplates],
+            );
         }
 
-        return $response->withJson(['listTemplate' => $listTemplates]);
+        return $response->withJson(['listTemplate' => $listTemplatesObj]);
     }
 
     public function create(Request $request, Response $response)
@@ -81,34 +90,34 @@ class ListTemplateController
                 }
             }
         } else {
-            $data['object_id'] = $data['object_type'] . '_' . DatabaseModel::uniqueId();
+            $data['object_id'] = $data['object_type'].'_'.DatabaseModel::uniqueId();
         }
 
-        $checkItems = ListTemplateController::checkItems(['items' => $data['items']]);
+        $checkItems = self::checkItems(['items' => $data['items']]);
         if (!empty($checkItems['errors'])) {
             return $response->withStatus(400)->withJson(['errors' => $checkItems['errors']]);
         }
 
         foreach ($data['items'] as $item) {
             ListTemplateModel::create([
-                'object_id'     => $data['object_id'],
-                'object_type'   => $data['object_type'],
-                'title'         => $data['title'],
-                'description'   => $data['description'],
-                'sequence'      => $item['sequence'],
-                'item_id'       => $item['item_id'],
-                'item_type'     => $item['item_type'],
-                'item_mode'     => $item['item_mode'],
+                'object_id' => $data['object_id'],
+                'object_type' => $data['object_type'],
+                'title' => $data['title'],
+                'description' => $data['description'],
+                'sequence' => $item['sequence'],
+                'item_id' => $item['item_id'],
+                'item_type' => $item['item_type'],
+                'item_mode' => $item['item_mode'],
             ]);
         }
 
         HistoryController::add([
             'tableName' => 'listmodels',
-            'recordId'  => $data['object_id'],
+            'recordId' => $data['object_id'],
             'eventType' => 'ADD',
-            'info'      => _LIST_TEMPLATE_CREATION . " : {$data['title']} {$data['description']}",
-            'moduleId'  => 'listTemplate',
-            'eventId'   => 'listTemplateCreation',
+            'info' => _LIST_TEMPLATE_CREATION." : {$data['title']} {$data['description']}",
+            'moduleId' => 'listTemplate',
+            'eventId' => 'listTemplateCreation',
         ]);
 
         return $response->withJson(['success' => 'success']);
@@ -141,35 +150,35 @@ class ListTemplateController
             }
         }
 
-        $checkItems = ListTemplateController::checkItems(['items' => $data['items']]);
+        $checkItems = self::checkItems(['items' => $data['items']]);
         if (!empty($checkItems['errors'])) {
             return $response->withStatus(400)->withJson(['errors' => $checkItems['errors']]);
         }
 
         ListTemplateModel::delete([
             'where' => ['object_id = ?', 'object_type = ?'],
-            'data'  => [$listTemplates[0]['object_id'], $listTemplates[0]['object_type']]
+            'data' => [$listTemplates[0]['object_id'], $listTemplates[0]['object_type']],
         ]);
         foreach ($data['items'] as $item) {
             ListTemplateModel::create([
-                'object_id'     => $listTemplates[0]['object_id'],
-                'object_type'   => $listTemplates[0]['object_type'],
-                'title'         => $data['title'],
-                'description'   => $data['description'],
-                'sequence'      => $item['sequence'],
-                'item_id'       => $item['item_id'],
-                'item_type'     => $item['item_type'],
-                'item_mode'     => $item['item_mode'],
+                'object_id' => $listTemplates[0]['object_id'],
+                'object_type' => $listTemplates[0]['object_type'],
+                'title' => $data['title'],
+                'description' => $data['description'],
+                'sequence' => $item['sequence'],
+                'item_id' => $item['item_id'],
+                'item_type' => $item['item_type'],
+                'item_mode' => $item['item_mode'],
             ]);
         }
 
         HistoryController::add([
             'tableName' => 'listmodels',
-            'recordId'  => $listTemplates[0]['object_id'],
+            'recordId' => $listTemplates[0]['object_id'],
             'eventType' => 'UP',
-            'info'      => _LIST_TEMPLATE_MODIFICATION . " : {$data['title']} {$data['description']}",
-            'moduleId'  => 'listTemplate',
-            'eventId'   => 'listTemplateModification',
+            'info' => _LIST_TEMPLATE_MODIFICATION." : {$data['title']} {$data['description']}",
+            'moduleId' => 'listTemplate',
+            'eventId' => 'listTemplateModification',
         ]);
 
         return $response->withJson(['success' => 'success']);
@@ -197,15 +206,15 @@ class ListTemplateController
 
         ListTemplateModel::delete([
             'where' => ['object_id = ?', 'object_type = ?'],
-            'data'  => [$listTemplates[0]['object_id'], $listTemplates[0]['object_type']]
+            'data' => [$listTemplates[0]['object_id'], $listTemplates[0]['object_type']],
         ]);
         HistoryController::add([
             'tableName' => 'listmodels',
-            'recordId'  => $listTemplates[0]['object_id'],
+            'recordId' => $listTemplates[0]['object_id'],
             'eventType' => 'DEL',
-            'info'      => _LIST_TEMPLATE_SUPPRESSION . " : {$listTemplates[0]['object_id']} {$listTemplates[0]['object_type']}",
-            'moduleId'  => 'listTemplate',
-            'eventId'   => 'listTemplateSuppression',
+            'info' => _LIST_TEMPLATE_SUPPRESSION." : {$listTemplates[0]['object_id']} {$listTemplates[0]['object_type']}",
+            'moduleId' => 'listTemplate',
+            'eventId' => 'listTemplateSuppression',
         ]);
 
         return $response->withJson(['success' => 'success']);
-- 
GitLab