From 99049bccdc2aefa35dfbaa68df4e197dc31b54d1 Mon Sep 17 00:00:00 2001
From: Alex Orluc <alex.orluc@maarch.org>
Date: Wed, 21 Feb 2018 13:57:42 +0100
Subject: [PATCH] FEAT #74 add css + material components

---
 .../entities-administration.component.html    | 241 +++++++++++++++++-
 .../entities-administration.component.js      | 176 ++++++++++++-
 .../entities-administration.component.ts      | 195 ++++++++++++--
 .../js/angular/app/app-material.module.js     |   7 +-
 .../js/angular/app/app-material.module.ts     |   7 +-
 .../js/angular/app/app.component.js           |   3 +-
 .../js/angular/app/app.component.ts           |   4 +-
 .../js/angular/lang/lang-en.js                |  12 +
 .../js/angular/lang/lang-en.ts                |  12 +
 .../js/angular/lang/lang-fr.js                |   8 +
 .../js/angular/lang/lang-fr.ts                |   8 +
 .../js/angular/plugins/autocomplete.plugin.js |  26 +-
 .../js/angular/plugins/autocomplete.plugin.ts |  39 ++-
 .../js/angular/systemjs.config.js             |   1 +
 modules/entities/xml/services.xml             | 117 ++++-----
 package-lock.json                             | 125 ++++-----
 package.json                                  |   1 +
 17 files changed, 812 insertions(+), 170 deletions(-)

diff --git a/apps/maarch_entreprise/Views/entities-administration.component.html b/apps/maarch_entreprise/Views/entities-administration.component.html
index d51c4a99dbd..eb32a87d333 100644
--- a/apps/maarch_entreprise/Views/entities-administration.component.html
+++ b/apps/maarch_entreprise/Views/entities-administration.component.html
@@ -1,6 +1,235 @@
-<div *ngIf="loading">
-    <i class="fa fa-spinner fa-spin fa-5x" style="margin-left: 50%;margin-top: 16%;font-size: 8em"></i>
-</div>
-<div *ngIf="!loading" class="container-fluid">
-    <h1 style="margin-top: 0"><i class="fa fa-inbox fa-2x"></i> {{lang.administration}}</h1>
-</div>
+<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.entities}}
+            <small [class.hide-for-mobile]="mobileQuery.matches">{{entities.length}} {{lang.entities}}</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 (click)="prepareEntityAdd()">
+                    <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">
+
+                <mat-form-field>
+                    <input matInput id="jstree_search" name="jstree_search" type="text" placeholder="{{lang.searchEntities}}">
+                </mat-form-field>
+                <div id="jstree"></div>
+
+            </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-sm-12">
+
+            <mat-nav-list>
+                <mat-tab-group>
+                    <mat-tab label="Informations">
+                        <form class="form-horizontal" #entityForm="ngForm" style="overflow:hidden;">
+                            <div class="form-group">
+                                <div class="col-sm-12">
+                                    <mat-form-field>
+                                        <mat-select id="entity_type" name="entity_type" title="{{lang.entityType}}" placeholder="{{lang.entityType}}" [(ngModel)]="currentEntity.entity_type">
+                                            <mat-option *ngFor="let entity_type of currentEntity.types" [value]="entity_type.id">
+                                                {{entity_type.label}}
+                                            </mat-option>
+                                        </mat-select>
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-12">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.entity_id" required name="entity_id" id="entity_id" title="{{lang.id}}" type="text"
+                                            placeholder="{{lang.id}}" maxlength="255" [disabled]="!creationMode">
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-12">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.entity_label" required name="entity_label" id="entity_label" title="{{lang.label}}"
+                                            type="text" placeholder="{{lang.label}}" maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-12">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.short_label" required name="short_label" id="short_label" title="{{lang.shortLabel}}"
+                                            type="text" placeholder="{{lang.shortLabel}}" maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-4">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.adrs_1" name="adrs_1" id="adrs_1" title="{{lang.address}}1" type="text" placeholder="{{lang.address}}1"
+                                            maxlength="255">
+                                    </mat-form-field>
+
+                                </div>
+                                <div class="col-sm-4">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.adrs_2" name="adrs_2" id="adrs_2" title="{{lang.address}}2" type="text" placeholder="{{lang.address}}2"
+                                            maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                                <div class="col-sm-4">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.adrs_3" name="adrs_3" id="adrs_3" title="{{lang.address}}3" type="text" placeholder="{{lang.address}}3"
+                                            maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-6">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.zipcode" name="zipcode" id="zipcode" title="{{lang.zipcode}}" type="text" placeholder="{{lang.zipcode}}"
+                                            maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                                <div class="col-sm-6">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.country" name="country" id="country" title="{{lang.country}}" type="text" placeholder="{{lang.country}}"
+                                            maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-12">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.email" name="email" id="email" title="{{lang.email}}" type="text" placeholder="{{lang.email}}"
+                                            maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-12">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.business_id" name="business_id" id="business_id" title="{{lang.siretCode}}" type="text"
+                                            placeholder="{{lang.siretCode}}" maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-sm-6">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.archival_agency" name="archival_agency" id="archival_agency" title="{{lang.archivalAgency}}"
+                                            type="text" placeholder="{{lang.archivalAgency}}" maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                                <div class="col-sm-6">
+                                    <mat-form-field>
+                                        <input matInput [(ngModel)]="currentEntity.archival_agreement" name="archival_agreement" id="archival_agreement" title="{{lang.archivalAgreement}}"
+                                            type="text" placeholder="{{lang.archivalAgreement}}" maxlength="255">
+                                    </mat-form-field>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <div class="col-md-12 text-center" style="padding:10px;">
+                                    <button mat-raised-button [disabled]="!entityForm.form.valid" color="primary" (click)="saveEntity()">{{lang.save}}</button>
+                                    <button mat-raised-button *ngIf="!creationMode" [disabled]="!entityForm.form.valid && this.currentEntity.entity_id != ''"
+                                        color="warn" (click)="removeEntity()">{{lang.delete}}</button>
+                                    <button mat-raised-button *ngIf="creationMode" color="default" (click)="readMode()">{{lang.cancel}}</button>
+                                </div>
+                            </div>
+                        </form>
+                    </mat-tab>
+                    <mat-tab label="Liste de diffusion" *ngIf="!creationMode">
+                        <div class="row" style="margin:0px;">
+                            <div class="col-md-12">
+                                <mat-form-field>
+                                    <input type="text" placeholder="Ajouter une personne / un service" matInput [matAutocomplete]="auto" [formControl]="elementCtrl">
+                                    <mat-autocomplete #auto="matAutocomplete">
+                                        <mat-option *ngFor="let elem of filteredElements | async" [value]="elem.id" (click)="addElemListModel(elem)">
+                                            <p mat-line>
+                                                <i [class]="elem.type == 'entity' ? 'fa fa-sitemap' : 'fa fa-user'"></i> {{ elem.idToDisplay }}
+                                                <small>{{ elem.otherInfo }}</small>
+                                            </p>
+                                        </mat-option>
+                                    </mat-autocomplete>
+                                </mat-form-field>
+                                <mat-list>
+                                    <span *ngFor="let role of currentEntity.roles; let i = index" dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="currentEntity.listTemplate[role.id]">
+                                        <span *ngIf="role.available">
+                                            <h3 mat-subheader>{{role.label}}</h3>
+                                            <mat-list-item *ngFor="let template of currentEntity.listTemplate[role.id]; let i = index" title="deplacer" dnd-sortable
+                                                [sortableIndex]="i">
+                                                <mat-icon color="primary" mat-list-icon [class]="template.type == 'entity' ? 'fa fa-sitemap' : 'fa fa-user'"></mat-icon>
+                                                <p mat-line>{{template.labelToDisplay}}
+                                                    <small style="opacity:0.5;">{{template.descriptionToDisplay}}</small>
+                                                </p>
+                                            </mat-list-item>
+                                        </span>
+                                    </span>
+                                </mat-list>
+                            </div>
+                        </div>
+                    </mat-tab>
+                    <mat-tab label="Circuit de visa" *ngIf="!creationMode">
+                        <div class="row" style="margin:0px;">
+                            <div class="col-md-12">
+                                <mat-form-field>
+                                    <input type="text" placeholder="Ajouter une personne" matInput [matAutocomplete]="auto" [formControl]="elementCtrl">
+                                    <mat-autocomplete #auto="matAutocomplete">
+                                        <mat-option *ngFor="let elem of filteredElements | async" [value]="elem.id" (click)="addElemListModel(elem)">
+                                            <p mat-line>
+                                                <i [class]="elem.type == 'entity' ? 'fa fa-sitemap' : 'fa fa-user'"></i> {{ elem.idToDisplay }}
+                                                <small>{{ elem.otherInfo }}</small>
+                                            </p>
+                                        </mat-option>
+                                    </mat-autocomplete>
+                                </mat-form-field>
+                                <mat-list>
+                                    <span dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="currentEntity.visaTemplate">
+                                        <mat-list-item *ngFor="let template of currentEntity.visaTemplate; let i = index" title="deplacer" dnd-sortable
+                                            [sortableIndex]="i">
+                                            <mat-icon color="primary" mat-list-icon>{{i+1}}</mat-icon>
+                                            <p mat-line>{{template.idToDisplay}}
+                                                <small style="opacity:0.5;">{{template.descriptionToDisplay}}</small>
+                                            </p>
+                                        </mat-list-item>
+                                    </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/js/angular/app/administration/entities-administration.component.js b/apps/maarch_entreprise/js/angular/app/administration/entities-administration.component.js
index 52721d5cfdc..8e015d01ba5 100644
--- a/apps/maarch_entreprise/js/angular/app/administration/entities-administration.component.js
+++ b/apps/maarch_entreprise/js/angular/app/administration/entities-administration.component.js
@@ -1,4 +1,14 @@
 "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);
@@ -10,22 +20,39 @@ var __metadata = (this && this.__metadata) || function (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 EntitiesAdministrationComponent = /** @class */ (function () {
-    function EntitiesAdministrationComponent(http, notify) {
-        this.http = http;
-        this.notify = notify;
-        this.lang = translate_component_1.LANG;
-        this.entities = [];
-        this.loading = false;
+var autocomplete_plugin_1 = require("../../plugins/autocomplete.plugin");
+var EntitiesAdministrationComponent = /** @class */ (function (_super) {
+    __extends(EntitiesAdministrationComponent, _super);
+    function EntitiesAdministrationComponent(changeDetectorRef, media, http, notify) {
+        var _this = _super.call(this, http, 'usersAndEntities') || this;
+        _this.http = http;
+        _this.notify = notify;
+        _this.lang = translate_component_1.LANG;
+        _this.entities = [];
+        _this.entityTypeList = ['Direction', 'Service', 'Bureau'];
+        _this.currentEntity = {};
+        _this.loading = false;
+        _this.creationMode = false;
+        _this.listTeamOne = ['Muhammad Ali', 'George Foreman', 'Joe Frazier', 'Jake LaMotta', 'Joe Louis', 'Jack Dempsey', 'Rocky Marciano', 'Mike Tyson', 'Oscar De La Hoya'];
+        _this.listTeamTwo = ['Sugar Ray Robinson'];
+        $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;
     }
     EntitiesAdministrationComponent.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> > Entités";
         }
     };
+    EntitiesAdministrationComponent.prototype.ngOnDestroy = function () {
+        this.mobileQuery.removeListener(this._mobileQueryListener);
+    };
     EntitiesAdministrationComponent.prototype.ngOnInit = function () {
         var _this = this;
         this.updateBreadcrumb(angularGlobals.applicationName);
@@ -34,11 +61,142 @@ var EntitiesAdministrationComponent = /** @class */ (function () {
         this.http.get(this.coreUrl + "rest/entities")
             .subscribe(function (data) {
             _this.entities = data['entities'];
+            setTimeout(function () {
+                $j('#jstree').jstree({
+                    "checkbox": {
+                        "three_state": false //no cascade selection
+                    },
+                    'core': {
+                        'themes': {
+                            'name': 'proton',
+                            'responsive': true
+                        },
+                        'data': _this.entities,
+                        "check_callback": true
+                    },
+                    "plugins": ["search", "dnd", "contextmenu"],
+                });
+                $j('#jstree')
+                    .on('select_node.jstree', function (e, data) {
+                    if (_this.creationMode == true) {
+                        _this.currentEntity.parent_entity_id = data.node.id;
+                    }
+                    else {
+                        _this.loadEntity(data.node.id);
+                    }
+                }).on('move_node.jstree', function (e, data) {
+                    _this.loadEntity(data.node.id);
+                    _this.currentEntity.parent_entity_id = data.parent;
+                    _this.moveEntity();
+                })
+                    .jstree();
+            }, 0);
+            $j('#jstree').jstree('select_node', _this.entities[0]);
+            var to = false;
+            $j('#jstree_search').keyup(function () {
+                if (to) {
+                    clearTimeout(to);
+                }
+                to = setTimeout(function () {
+                    var v = $j('#jstree_search').val();
+                    $j('#jstree').jstree(true).search(v);
+                }, 250);
+            });
             _this.loading = false;
         }, function () {
             location.href = "index.php";
         });
     };
+    EntitiesAdministrationComponent.prototype.loadEntity = function (entity_id) {
+        var _this = this;
+        this.http.get(this.coreUrl + "rest/entities/" + entity_id + '/details')
+            .subscribe(function (data) {
+            _this.currentEntity = data['entity'];
+        }, function (err) {
+            _this.notify.error(err.error.errors);
+        });
+    };
+    EntitiesAdministrationComponent.prototype.addElemListModel = function (element) {
+        var _this = this;
+        var inListModel = false;
+        var newElemListModel = {
+            "type": element.type,
+            "id": element.id,
+            "labelToDisplay": element.idToDisplay,
+            "descriptionToDisplay": element.otherInfo,
+        };
+        this.currentEntity.roles.forEach(function (role) {
+            if (role.available == true) {
+                if (_this.currentEntity.listTemplate[role.id]) {
+                    _this.currentEntity.listTemplate[role.id].forEach(function (listModel) {
+                        console.log(listModel);
+                        if (listModel.id == element.id) {
+                            inListModel = true;
+                        }
+                    });
+                }
+            }
+        });
+        if (!inListModel) {
+            this.currentEntity.listTemplate.cc.unshift(newElemListModel);
+        }
+    };
+    EntitiesAdministrationComponent.prototype.saveEntity = function () {
+        var _this = this;
+        if (this.creationMode) {
+            this.http.post(this.coreUrl + "rest/entities", this.currentEntity)
+                .subscribe(function (data) {
+                _this.creationMode = false;
+                _this.entities.push(_this.currentEntity);
+                $j('#jstree').jstree("refresh");
+                _this.notify.success(_this.lang.entityAdded);
+            }, function (err) {
+                _this.notify.error(err.error.errors);
+            });
+        }
+        else {
+            this.http.put(this.coreUrl + "rest/entities/" + this.currentEntity.entity_id, this.currentEntity)
+                .subscribe(function (data) {
+                console.log(data);
+                _this.entities = data['entities'];
+                $j('#jstree').jstree(true).settings.core.data = _this.entities;
+                $j('#jstree').jstree("refresh");
+                _this.notify.success(_this.lang.entityUpdated);
+            }, function (err) {
+                _this.notify.error(err.error.errors);
+            });
+        }
+    };
+    EntitiesAdministrationComponent.prototype.moveEntity = function () {
+        var _this = this;
+        this.http.put(this.coreUrl + "rest/entities/" + this.currentEntity.entity_id, this.currentEntity)
+            .subscribe(function (data) {
+            _this.notify.success(_this.lang.entityUpdated);
+        }, function (err) {
+            _this.notify.error(err.error.errors);
+        });
+    };
+    EntitiesAdministrationComponent.prototype.readMode = function () {
+        this.creationMode = false;
+        $j('#jstree').jstree('deselect_all');
+        $j('#jstree').jstree('select_node', this.entities[0]);
+    };
+    EntitiesAdministrationComponent.prototype.removeEntity = function () {
+        var _this = this;
+        this.http.delete(this.coreUrl + "rest/entities/" + this.currentEntity.entity_id)
+            .subscribe(function (data) {
+            _this.entities = data['entities'];
+            $j('#jstree').jstree("refresh");
+            _this.notify.success(_this.lang.entityDeleted);
+        }, function (err) {
+            _this.notify.error(err.error.errors);
+        });
+    };
+    EntitiesAdministrationComponent.prototype.prepareEntityAdd = function () {
+        $j('#jstree').jstree('deselect_all');
+        this.creationMode = true;
+        this.currentEntity = {};
+    };
     EntitiesAdministrationComponent.prototype.updateStatus = function (entity, method) {
         var _this = this;
         this.http.put(this.coreUrl + "rest/entities/" + entity['entity_id'] + "/status", { "method": method })
@@ -63,8 +221,8 @@ var EntitiesAdministrationComponent = /** @class */ (function () {
             templateUrl: angularGlobals["entities-administrationView"],
             providers: [notification_service_1.NotificationService]
         }),
-        __metadata("design:paramtypes", [http_1.HttpClient, notification_service_1.NotificationService])
+        __metadata("design:paramtypes", [core_1.ChangeDetectorRef, layout_1.MediaMatcher, http_1.HttpClient, notification_service_1.NotificationService])
     ], EntitiesAdministrationComponent);
     return EntitiesAdministrationComponent;
-}());
+}(autocomplete_plugin_1.AutoCompletePlugin));
 exports.EntitiesAdministrationComponent = EntitiesAdministrationComponent;
diff --git a/apps/maarch_entreprise/js/angular/app/administration/entities-administration.component.ts b/apps/maarch_entreprise/js/angular/app/administration/entities-administration.component.ts
index 4fcc3cc1a74..afaa7d931a5 100644
--- a/apps/maarch_entreprise/js/angular/app/administration/entities-administration.component.ts
+++ b/apps/maarch_entreprise/js/angular/app/administration/entities-administration.component.ts
@@ -1,28 +1,42 @@
-import { Component, OnInit } from '@angular/core';
+import { ChangeDetectorRef, Component, OnInit } 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';
 
-declare function $j(selector: any) : any;
+import { AutoCompletePlugin } from '../../plugins/autocomplete.plugin';
 
-declare var angularGlobals : any;
+declare function $j(selector: any): any;
+
+declare var angularGlobals: any;
 
 
 @Component({
-    templateUrl : angularGlobals["entities-administrationView"],
-    providers   : [NotificationService]
+    templateUrl: angularGlobals["entities-administrationView"],
+    providers: [NotificationService]
 })
-export class EntitiesAdministrationComponent implements OnInit {
-
-    coreUrl                     : string;
-    lang                        : any       = LANG;
-
-    entities                    : any[]     = [];
-
-    loading                     : boolean   = false;
-
-
-    constructor(public http: HttpClient, private notify: NotificationService) {
+export class EntitiesAdministrationComponent extends AutoCompletePlugin implements OnInit {
+    mobileQuery: MediaQueryList;
+    private _mobileQueryListener: () => void;
+    coreUrl: string;
+    lang: any = LANG;
+
+    entities: any[] = [];
+    entityTypeList: any[] = ['Direction', 'Service', 'Bureau'];
+    currentEntity: any = {};
+
+    loading: boolean = false;
+    creationMode: boolean = false;
+    listTeamOne: Array<string> = ['Muhammad Ali', 'George Foreman', 'Joe Frazier', 'Jake LaMotta', 'Joe Louis', 'Jack Dempsey', 'Rocky Marciano', 'Mike Tyson', 'Oscar De La Hoya'];
+    listTeamTwo: Array<string> = ['Sugar Ray Robinson'];
+
+
+    constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher, public http: HttpClient, private notify: NotificationService) {
+        super(http, 'usersAndEntities');
+        $j("link[href='merged_css.php']").remove();
+        this.mobileQuery = media.matchMedia('(max-width: 768px)');
+        this._mobileQueryListener = () => changeDetectorRef.detectChanges();
+        this.mobileQuery.addListener(this._mobileQueryListener);
     }
 
     updateBreadcrumb(applicationName: string) {
@@ -31,6 +45,10 @@ export class EntitiesAdministrationComponent implements OnInit {
         }
     }
 
+    ngOnDestroy(): void {
+        this.mobileQuery.removeListener(this._mobileQueryListener);
+    }
+
     ngOnInit(): void {
         this.updateBreadcrumb(angularGlobals.applicationName);
         this.coreUrl = angularGlobals.coreUrl;
@@ -38,18 +56,153 @@ export class EntitiesAdministrationComponent implements OnInit {
         this.loading = true;
 
         this.http.get(this.coreUrl + "rest/entities")
-            .subscribe((data : any) => {
+            .subscribe((data: any) => {
                 this.entities = data['entities'];
-
+                setTimeout(() => {
+                    $j('#jstree').jstree({
+                        "checkbox": {
+                            "three_state": false //no cascade selection
+                        },
+                        'core': {
+                            'themes': {
+                                'name': 'proton',
+                                'responsive': true
+                            },
+                            'data': this.entities,
+                            "check_callback": true
+                        },
+                        "plugins": ["search", "dnd", "contextmenu"],
+                    });
+                    $j('#jstree')
+                        // listen for event
+                        .on('select_node.jstree', (e: any, data: any) => {
+                            if (this.creationMode == true) {
+                                this.currentEntity.parent_entity_id = data.node.id;
+                            } else {
+                                this.loadEntity(data.node.id);
+                            }
+
+                        }).on('move_node.jstree', (e: any, data: any) => {
+                            this.loadEntity(data.node.id);
+                            this.currentEntity.parent_entity_id = data.parent;
+                            this.moveEntity();
+                        })
+                        // create the instance
+                        .jstree();
+                }, 0);
+                $j('#jstree').jstree('select_node', this.entities[0]);
+                var to: any = false;
+                $j('#jstree_search').keyup(function () {
+                    if (to) { clearTimeout(to); }
+                    to = setTimeout(function () {
+                        var v = $j('#jstree_search').val();
+                        $j('#jstree').jstree(true).search(v);
+                    }, 250);
+                });
                 this.loading = false;
             }, () => {
                 location.href = "index.php";
             });
     }
 
+    loadEntity(entity_id: any) {
+        this.http.get(this.coreUrl + "rest/entities/" + entity_id + '/details')
+            .subscribe((data: any) => {
+                this.currentEntity = data['entity'];
+            }, (err) => {
+                this.notify.error(err.error.errors);
+            });
+    }
+
+    addElemListModel(element: any) {
+        var inListModel = false;
+        var newElemListModel = {
+            "type": element.type,
+            "id": element.id,
+            "labelToDisplay": element.idToDisplay,
+            "descriptionToDisplay": element.otherInfo,
+        };
+        this.currentEntity.roles.forEach((role: any) => {
+            if (role.available == true) {
+                if (this.currentEntity.listTemplate[role.id]) {
+
+                    this.currentEntity.listTemplate[role.id].forEach((listModel: any) => {
+                        console.log(listModel);
+                        if (listModel.id == element.id) {
+                            inListModel = true;
+                        }
+                    });
+                }
+            }
+        });
+        if (!inListModel) {
+            this.currentEntity.listTemplate.cc.unshift(newElemListModel);
+        }
+
+    }
+
+    saveEntity() {
+        if (this.creationMode) {
+            this.http.post(this.coreUrl + "rest/entities", this.currentEntity)
+                .subscribe((data: any) => {
+                    this.creationMode = false;
+                    this.entities.push(this.currentEntity);
+                    $j('#jstree').jstree("refresh");
+                    this.notify.success(this.lang.entityAdded);
+                }, (err) => {
+                    this.notify.error(err.error.errors);
+                });
+        } else {
+            this.http.put(this.coreUrl + "rest/entities/" + this.currentEntity.entity_id, this.currentEntity)
+                .subscribe((data: any) => {
+                    console.log(data);
+                    this.entities = data['entities'];
+                    $j('#jstree').jstree(true).settings.core.data = this.entities;
+                    $j('#jstree').jstree("refresh");
+                    this.notify.success(this.lang.entityUpdated);
+                }, (err) => {
+                    this.notify.error(err.error.errors);
+                });
+        }
+    }
+
+    moveEntity() {
+        this.http.put(this.coreUrl + "rest/entities/" + this.currentEntity.entity_id, this.currentEntity)
+                .subscribe((data: any) => {
+                    this.notify.success(this.lang.entityUpdated);
+                }, (err) => {
+                    this.notify.error(err.error.errors);
+                });
+
+    }
+
+    readMode() {
+        this.creationMode = false;
+        $j('#jstree').jstree('deselect_all');
+        $j('#jstree').jstree('select_node', this.entities[0]);
+    }
+
+    removeEntity() {
+        this.http.delete(this.coreUrl + "rest/entities/" + this.currentEntity.entity_id)
+            .subscribe((data: any) => {
+                this.entities = data['entities'];
+                $j('#jstree').jstree("refresh");
+                this.notify.success(this.lang.entityDeleted);
+            }, (err) => {
+                this.notify.error(err.error.errors);
+            });
+    }
+
+    prepareEntityAdd() {
+        $j('#jstree').jstree('deselect_all');
+        this.creationMode = true;
+        this.currentEntity = {};
+    }
+
+
     updateStatus(entity: any, method: string) {
-        this.http.put(this.coreUrl + "rest/entities/" + entity['entity_id'] + "/status", {"method" : method})
-            .subscribe((data : any) => {
+        this.http.put(this.coreUrl + "rest/entities/" + entity['entity_id'] + "/status", { "method": method })
+            .subscribe((data: any) => {
                 this.notify.success("");
             }, (err) => {
                 this.notify.error(err.error.errors);
@@ -58,7 +211,7 @@ export class EntitiesAdministrationComponent implements OnInit {
 
     delete(entity: any) {
         this.http.delete(this.coreUrl + "rest/entities/" + entity['entity_id'])
-            .subscribe((data : any) => {
+            .subscribe((data: any) => {
                 this.notify.success(this.lang.entityDeleted);
                 this.entities = data['entities'];
             }, (err) => {
diff --git a/apps/maarch_entreprise/js/angular/app/app-material.module.js b/apps/maarch_entreprise/js/angular/app/app-material.module.js
index be1a0c9cbdb..4a4c07b20e7 100644
--- a/apps/maarch_entreprise/js/angular/app/app-material.module.js
+++ b/apps/maarch_entreprise/js/angular/app/app-material.module.js
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
 };
 Object.defineProperty(exports, "__esModule", { value: true });
 var core_1 = require("@angular/core");
+var ng2_dnd_1 = require("ng2-dnd");
 var material_1 = require("@angular/material");
 var french_paginator_intl_1 = require("./french-paginator-intl");
 var AppMaterialModule = /** @class */ (function () {
@@ -43,7 +44,8 @@ var AppMaterialModule = /** @class */ (function () {
                 material_1.MatChipsModule,
                 material_1.MatStepperModule,
                 material_1.MatRadioModule,
-                material_1.MatSliderModule
+                material_1.MatSliderModule,
+                ng2_dnd_1.DndModule.forRoot()
             ],
             exports: [
                 material_1.MatCheckboxModule,
@@ -74,7 +76,8 @@ var AppMaterialModule = /** @class */ (function () {
                 material_1.MatChipsModule,
                 material_1.MatStepperModule,
                 material_1.MatRadioModule,
-                material_1.MatSliderModule
+                material_1.MatSliderModule,
+                ng2_dnd_1.DndModule
             ],
             providers: [
                 { provide: material_1.MatPaginatorIntl, useValue: french_paginator_intl_1.getFrenchPaginatorIntl() }
diff --git a/apps/maarch_entreprise/js/angular/app/app-material.module.ts b/apps/maarch_entreprise/js/angular/app/app-material.module.ts
index 60f528fa06b..72b3642918e 100644
--- a/apps/maarch_entreprise/js/angular/app/app-material.module.ts
+++ b/apps/maarch_entreprise/js/angular/app/app-material.module.ts
@@ -1,4 +1,5 @@
 import { NgModule } from '@angular/core';
+import { DndModule }                            from 'ng2-dnd';
 import {
     MatSelectModule,
     MatCheckboxModule,
@@ -68,7 +69,8 @@ import { getFrenchPaginatorIntl } from './french-paginator-intl';
         MatChipsModule,
         MatStepperModule,
         MatRadioModule,
-        MatSliderModule
+        MatSliderModule,
+        DndModule.forRoot()
     ],
     exports: [
         MatCheckboxModule,
@@ -99,7 +101,8 @@ import { getFrenchPaginatorIntl } from './french-paginator-intl';
         MatChipsModule,
         MatStepperModule,
         MatRadioModule,
-        MatSliderModule
+        MatSliderModule,
+        DndModule
     ],
     providers: [
         { provide: MatPaginatorIntl, useValue: getFrenchPaginatorIntl() }
diff --git a/apps/maarch_entreprise/js/angular/app/app.component.js b/apps/maarch_entreprise/js/angular/app/app.component.js
index ad7b5edf7ae..09a2fba3346 100755
--- a/apps/maarch_entreprise/js/angular/app/app.component.js
+++ b/apps/maarch_entreprise/js/angular/app/app.component.js
@@ -34,7 +34,8 @@ var AppComponent = /** @class */ (function () {
                 //'../../node_modules/@angular/material/prebuilt-themes/indigo-pink.css',
                 'css/maarch-material.css',
                 'css/engine.css',
-                'css/jstree-custom.min.css' //treejs module
+                'css/jstree-custom.min.css',
+                '../../node_modules/ng2-dnd/bundles/style.css'
             ],
             viewProviders: [material_1.MatIconRegistry],
             providers: [
diff --git a/apps/maarch_entreprise/js/angular/app/app.component.ts b/apps/maarch_entreprise/js/angular/app/app.component.ts
index d74906bb130..d7c183e7db8 100755
--- a/apps/maarch_entreprise/js/angular/app/app.component.ts
+++ b/apps/maarch_entreprise/js/angular/app/app.component.ts
@@ -20,7 +20,9 @@ export const myCustomTooltipDefaults: MatTooltipDefaultOptions = {
         //'../../node_modules/@angular/material/prebuilt-themes/indigo-pink.css',
         'css/maarch-material.css',
         'css/engine.css',
-        'css/jstree-custom.min.css' //treejs module
+        'css/jstree-custom.min.css', //treejs module
+        '../../node_modules/ng2-dnd/bundles/style.css'
+
     ],
     viewProviders: [MatIconRegistry],
     providers: [
diff --git a/apps/maarch_entreprise/js/angular/lang/lang-en.js b/apps/maarch_entreprise/js/angular/lang/lang-en.js
index dc2e1ef3010..9b18b4309de 100755
--- a/apps/maarch_entreprise/js/angular/lang/lang-en.js
+++ b/apps/maarch_entreprise/js/angular/lang/lang-en.js
@@ -18,11 +18,14 @@ exports.LANG_EN = {
     "activateAbsence": "Activate absence",
     "active": "Active",
     "add": "Add",
+    "address": "Address",
     "addStatus": "Add a status",
     "administration": "Administration",
     "administrationServices": "Administration services",
     "allActions": "All actions",
     "application": "Application",
+    "archivalAgency": "Archival agency",
+    "archivalAgreement": "Archival agreement",
     "associatedStatus": "Associated status",
     "attachments": "Attachments",
     "authorize": "Authorize",
@@ -58,6 +61,7 @@ exports.LANG_EN = {
     "clickOn": "Click on",
     "color": "Color",
     "content_management": "Ressource revision",
+    "country": "Country",
     "createScriptNotification": "Create the script",
     "currentPsw": "Current password",
     "default": "default",
@@ -73,6 +77,7 @@ exports.LANG_EN = {
     "entityAdded": "Entité added",
     "entityDeleted": "Entité deleted",
     "entityTooglePrimary": "Pass to primary entity",
+    "entityType": "Entity type",
     "entityUpdated": "Entité updated",
     "export_seda": "Seda export",
     "fileplan": "Fileplan",
@@ -201,6 +206,12 @@ exports.LANG_EN = {
     "secondaryEntity": "Secondary entity",
     "selectAll": "Select all",
     "sendmail": "Sendmail",
+    "shortLabel": "Short label",
+    "signAdded": "Sign added",
+    "signDeleted": "Sign deleted",
+    "signUpdated": "Sign updated",
+    "siretCode": "SIRET code",
+    "status": "Status",
     "statusAdded": "Status added",
     "statusCreation": "Status creation",
     "statusDeleted": "Status deleted",
@@ -247,4 +258,5 @@ exports.LANG_EN = {
     "whereClauseAction": "Where clause condition of action display",
     "workingDays": "Working days",
     "yes": "Yes",
+    "zipcode": "Zip code"
 };
diff --git a/apps/maarch_entreprise/js/angular/lang/lang-en.ts b/apps/maarch_entreprise/js/angular/lang/lang-en.ts
index 0fc5b1fd2a2..17b224f806b 100755
--- a/apps/maarch_entreprise/js/angular/lang/lang-en.ts
+++ b/apps/maarch_entreprise/js/angular/lang/lang-en.ts
@@ -16,11 +16,14 @@ export const LANG_EN = {
     "activateAbsence"           : "Activate absence",
     "active"                    : "Active",
     "add"                       : "Add",
+    "address"                   : "Address",
     "addStatus"                 : "Add a status",
     "administration"            : "Administration",
     "administrationServices"    : "Administration services",
     "allActions"                : "All actions",
     "application"               : "Application",
+    "archivalAgency"            : "Archival agency",
+    "archivalAgreement"         : "Archival agreement",
     "associatedStatus"          : "Associated status",
     "attachments"               : "Attachments",
     "authorize"                 : "Authorize",
@@ -56,6 +59,7 @@ export const LANG_EN = {
     "clickOn"                   : "Click on",
     "color"                     : "Color",
     "content_management"        : "Ressource revision",
+    "country"                   : "Country",
     "createScriptNotification"  : "Create the script",
     "currentPsw"                : "Current password",
     "default"                   : "default",
@@ -71,6 +75,7 @@ export const LANG_EN = {
     "entityAdded"               : "Entité added",
     "entityDeleted"             : "Entité deleted",
     "entityTooglePrimary"       : "Pass to primary entity",
+    "entityType"                : "Entity type",
     "entityUpdated"             : "Entité updated",
     "export_seda"               : "Seda export",
     "fileplan"                  : "Fileplan",
@@ -199,6 +204,12 @@ export const LANG_EN = {
     "secondaryEntity"           : "Secondary entity",
     "selectAll"                 : "Select all",
     "sendmail"                  : "Sendmail",
+    "shortLabel"                : "Short label",
+    "signAdded"                 : "Sign added",
+    "signDeleted"               : "Sign deleted",
+    "signUpdated"               : "Sign updated",
+    "siretCode"                 : "SIRET code",
+    "status"                    : "Status",
     "statusAdded"               : "Status added",
     "statusCreation"            : "Status creation",
     "statusDeleted"             : "Status deleted",
@@ -245,4 +256,5 @@ export const LANG_EN = {
     "whereClauseAction"         : "Where clause condition of action display",
     "workingDays"               : "Working days",
     "yes"                       : "Yes",
+    "zipcode"                   : "Zip code"
 };
diff --git a/apps/maarch_entreprise/js/angular/lang/lang-fr.js b/apps/maarch_entreprise/js/angular/lang/lang-fr.js
index 9390a5f9536..bc315e63dad 100755
--- a/apps/maarch_entreprise/js/angular/lang/lang-fr.js
+++ b/apps/maarch_entreprise/js/angular/lang/lang-fr.js
@@ -21,11 +21,14 @@ exports.LANG_FR = {
     "activateAbsence": "Activer l'absence",
     "active": "Actif",
     "add": "Ajouter",
+    "address": "Adresse",
     "addStatus": "Ajouter un statut",
     "administration": "Administration",
     "administrationServices": "Droits d'administration",
     "allActions": "Toutes les actions",
     "application": "Application",
+    "archivalAgency": "Convention d'archivage",
+    "archivalAgreement": "Service d'archive",
     "associatedStatus": "Statut associé",
     "attachments": "Attachments",
     "authorize": "Autoriser",
@@ -63,6 +66,7 @@ exports.LANG_FR = {
     "color": "Couleur",
     "confirmAction": "Voulez-vous vraiment effectuer cette action ?",
     "content_management": "Versionning de document",
+    "country": "Pays",
     "createScriptNotification": "Créer le script",
     "currentPsw": "Mot de passe actuel",
     "dataOfMonth": "Données du mois",
@@ -81,6 +85,7 @@ exports.LANG_FR = {
     "entityAdded": "Entité ajoutée",
     "entityDeleted": "Entité supprimée",
     "entityTooglePrimary": "Passage en entité primaire",
+    "entityType": "Type d'entité",
     "entityUpdated": "Entité modifiée",
     "entries": "entrée(s)",
     "event": "Événement",
@@ -220,9 +225,11 @@ exports.LANG_FR = {
     "secondaryEntity": "Entitté secondaire",
     "selectAll": "Sélectionner tout",
     "sendmail": "Envoi de mails",
+    "shortLabel": "Libellé court",
     "signAdded": "Signature ajoutée",
     "signDeleted": "Signature supprimée",
     "signUpdated": "Signature modifiée",
+    "siretCode": "Numéro SIRET",
     "status": "Statut",
     "statusAdded": "Statut ajouté",
     "statusCreation": "Création d'un statut",
@@ -277,4 +284,5 @@ exports.LANG_FR = {
     "whereClauseAction": "Condition d'apparition de l'action (where clause)",
     "workingDays": "jour(s) ouvré(s)",
     "yes": "Oui",
+    "zipcode": "Code postal"
 };
diff --git a/apps/maarch_entreprise/js/angular/lang/lang-fr.ts b/apps/maarch_entreprise/js/angular/lang/lang-fr.ts
index 23f2a21ad2f..d8a94d4e6f3 100755
--- a/apps/maarch_entreprise/js/angular/lang/lang-fr.ts
+++ b/apps/maarch_entreprise/js/angular/lang/lang-fr.ts
@@ -19,11 +19,14 @@ export const LANG_FR = {
     "activateAbsence"               : "Activer l'absence",
     "active"                        : "Actif",
     "add"                           : "Ajouter",
+    "address"                       : "Adresse",
     "addStatus"                     : "Ajouter un statut",
     "administration"                : "Administration",
     "administrationServices"        : "Droits d'administration",
     "allActions"                    : "Toutes les actions",
     "application"                   : "Application",
+    "archivalAgency"                : "Convention d'archivage",
+    "archivalAgreement"             : "Service d'archive",
     "associatedStatus"              : "Statut associé",
     "attachments"                   : "Attachments",
     "authorize"                    : "Autoriser",
@@ -61,6 +64,7 @@ export const LANG_FR = {
     "color"                        : "Couleur",
     "confirmAction"                : "Voulez-vous vraiment effectuer cette action ?",
     "content_management"           : "Versionning de document",
+    "country"                      : "Pays",
     "createScriptNotification"     : "Créer le script",
     "currentPsw"                   : "Mot de passe actuel",
     "dataOfMonth"                  : "Données du mois",
@@ -79,6 +83,7 @@ export const LANG_FR = {
     "entityAdded"                  : "Entité ajoutée",
     "entityDeleted"                : "Entité supprimée",
     "entityTooglePrimary"          : "Passage en entité primaire",
+    "entityType"                   : "Type d'entité",
     "entityUpdated"                : "Entité modifiée",
     "entries"                      : "entrée(s)",
     "event"                        : "Événement",
@@ -218,9 +223,11 @@ export const LANG_FR = {
     "secondaryEntity"              : "Entitté secondaire",
     "selectAll"                    : "Sélectionner tout",
     "sendmail"                     : "Envoi de mails",
+    "shortLabel"                   : "Libellé court",
     "signAdded"                    : "Signature ajoutée",
     "signDeleted"                  : "Signature supprimée",
     "signUpdated"                  : "Signature modifiée",
+    "siretCode"                    : "Numéro SIRET",
     "status"                       : "Statut",
     "statusAdded"                  : "Statut ajouté",
     "statusCreation"               : "Création d'un statut",
@@ -275,4 +282,5 @@ export const LANG_FR = {
     "whereClauseAction"            : "Condition d'apparition de l'action (where clause)",
     "workingDays"                   : "jour(s) ouvré(s)",
     "yes"                           : "Oui",
+    "zipcode"                       : "Code postal"
 };
\ No newline at end of file
diff --git a/apps/maarch_entreprise/js/angular/plugins/autocomplete.plugin.js b/apps/maarch_entreprise/js/angular/plugins/autocomplete.plugin.js
index 0dc4a69ecc2..fe80d9ba29c 100644
--- a/apps/maarch_entreprise/js/angular/plugins/autocomplete.plugin.js
+++ b/apps/maarch_entreprise/js/angular/plugins/autocomplete.plugin.js
@@ -8,6 +8,7 @@ var AutoCompletePlugin = /** @class */ (function () {
         var _this = this;
         this.http = http;
         this.userList = [];
+        this.elemList = [];
         this.statusesList = [];
         this.coreUrl = angularGlobals.coreUrl;
         if (target == 'users') {
@@ -32,6 +33,23 @@ var AutoCompletePlugin = /** @class */ (function () {
                 location.href = "index.php";
             });
         }
+        else if (target == 'usersAndEntities') {
+            this.elementCtrl = new forms_1.FormControl();
+            this.elemList = [{
+                    "type": "user",
+                    "id": "bbain",
+                    "idToDisplay": "Barbara BAIN",
+                    "otherInfo": "Pôle jeunesse et sport"
+                },
+                {
+                    "type": "entity",
+                    "id": "DGS",
+                    "idToDisplay": "Direction générale des services",
+                    "otherInfo": ""
+                }];
+            this.filteredElements = this.elementCtrl.valueChanges
+                .pipe(startWith_1.startWith(''), map_1.map(function (elem) { return elem ? _this.autocompleteFilterElements(elem) : _this.elemList.slice(); }));
+        }
         else {
         }
     }
@@ -41,13 +59,15 @@ var AutoCompletePlugin = /** @class */ (function () {
         });
     };
     AutoCompletePlugin.prototype.autocompleteFilterStatuses = function (name) {
-        console.log(this.statusesList.filter(function (status) {
-            return status.label_status.toLowerCase().indexOf(name.toLowerCase()) === 0;
-        }));
         return this.statusesList.filter(function (status) {
             return status.label_status.toLowerCase().indexOf(name.toLowerCase()) === 0;
         });
     };
+    AutoCompletePlugin.prototype.autocompleteFilterElements = function (name) {
+        return this.statusesList.filter(function (elem) {
+            return elem.idToDisplay.toLowerCase().indexOf(name.toLowerCase()) === 0;
+        });
+    };
     return AutoCompletePlugin;
 }());
 exports.AutoCompletePlugin = AutoCompletePlugin;
diff --git a/apps/maarch_entreprise/js/angular/plugins/autocomplete.plugin.ts b/apps/maarch_entreprise/js/angular/plugins/autocomplete.plugin.ts
index 08864640a3b..07c5686801d 100644
--- a/apps/maarch_entreprise/js/angular/plugins/autocomplete.plugin.ts
+++ b/apps/maarch_entreprise/js/angular/plugins/autocomplete.plugin.ts
@@ -11,14 +11,17 @@ export class AutoCompletePlugin {
   coreUrl: string;
   userCtrl: FormControl;
   statusCtrl: FormControl;
+  elementCtrl: FormControl;
   filteredUsers: Observable<any[]>;
+  filteredElements: Observable<any[]>;
   filteredStatuses: Observable<any[]>;
   userList: any[] = [];
+  elemList: any[] = [];
   statusesList: any[] = [];
 
   constructor(public http: HttpClient, target: any) {
     this.coreUrl = angularGlobals.coreUrl;
-  
+
     if (target == 'users') {
       this.userCtrl = new FormControl();
       this.http.get(this.coreUrl + 'rest/users/autocompleter')
@@ -38,13 +41,32 @@ export class AutoCompletePlugin {
         .subscribe((data: any) => {
           this.statusesList = data['statuses'];
           this.filteredStatuses = this.statusCtrl.valueChanges
-          .pipe(
-            startWith(''),
-            map(status => status ? this.autocompleteFilterStatuses(status) : this.statusesList.slice())
-          );
+            .pipe(
+              startWith(''),
+              map(status => status ? this.autocompleteFilterStatuses(status) : this.statusesList.slice())
+            );
         }, () => {
           location.href = "index.php";
         });
+    } else if (target == 'usersAndEntities') {
+      this.elementCtrl = new FormControl();
+      this.elemList = [{
+        "type": "user",
+        "id": "bbain",
+        "idToDisplay": "Barbara BAIN",
+        "otherInfo": "Pôle jeunesse et sport"
+      },
+      {
+        "type": "entity",
+        "id": "DGS",
+        "idToDisplay": "Direction générale des services",
+        "otherInfo": ""
+      }];
+      this.filteredElements = this.elementCtrl.valueChanges
+        .pipe(
+          startWith(''),
+          map(elem => elem ? this.autocompleteFilterElements(elem) : this.elemList.slice())
+        );
     } else {
 
     }
@@ -56,10 +78,13 @@ export class AutoCompletePlugin {
   }
 
   autocompleteFilterStatuses(name: string) {
-    console.log(this.statusesList.filter(status =>
-      status.label_status.toLowerCase().indexOf(name.toLowerCase()) === 0));
     return this.statusesList.filter(status =>
       status.label_status.toLowerCase().indexOf(name.toLowerCase()) === 0);
   }
 
+  autocompleteFilterElements(name: string) {
+    return this.statusesList.filter(elem =>
+      elem.idToDisplay.toLowerCase().indexOf(name.toLowerCase()) === 0);
+  }
+
 }
\ No newline at end of file
diff --git a/apps/maarch_entreprise/js/angular/systemjs.config.js b/apps/maarch_entreprise/js/angular/systemjs.config.js
index 6857769f200..d186bd7231e 100755
--- a/apps/maarch_entreprise/js/angular/systemjs.config.js
+++ b/apps/maarch_entreprise/js/angular/systemjs.config.js
@@ -45,6 +45,7 @@
       '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.min.js',
       '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.min.js',
       '@angular/router': 'npm:@angular/router/bundles/router.umd.min.js',
+      'ng2-dnd': 'npm:ng2-dnd/bundles/ng2-dnd.umd.min.js',
 
       // other libraries
       'rxjs':     'npm:rxjs',
diff --git a/modules/entities/xml/services.xml b/modules/entities/xml/services.xml
index 9414af116c8..1779fc4dd15 100755
--- a/modules/entities/xml/services.xml
+++ b/modules/entities/xml/services.xml
@@ -4,15 +4,16 @@
         <id>manage_entities</id>
         <name>_ENTITIES</name>
         <comment>_MANAGE_ENTITIES_DESC</comment>
-        <servicepage>index.php?page=admin_entities&amp;module=entities</servicepage>
+        <servicepage>/administration/entities</servicepage>
         <servicetype>admin</servicetype>
         <system_service>false</system_service>
         <style>fa fa-sitemap</style>
         <enabled>true</enabled>
-         <WHEREAMIUSED>
-         <page>admin.php</page>
-         <nature>listelement</nature>
-       </WHEREAMIUSED>
+        <WHEREAMIUSED>
+            <page>admin.php</page>
+            <nature>listelement</nature>
+        </WHEREAMIUSED>
+        <angular>true</angular>
     </SERVICE>
     <SERVICE>
         <id>choose_entity</id>
@@ -105,53 +106,53 @@
         </WHEREAMIUSED>
     </SERVICE>
     <SERVICE>
-     <id>param_index_difflist_types</id>
-     <name>_PARAM_AVAILABLE_DIFFLIST_TYPES_ON_GROUP_BASKETS</name>
-     <servicepage>param_index_difflist_types.php</servicepage>
-     <servicetype>use</servicetype>
-     <system_service>true</system_service>
-     <enabled>true</enabled>
-     <WHEREAMIUSED>
-          <page>groupbasket_popup.php</page>
-          <nature>include</nature>
-      </WHEREAMIUSED>
-      <WHEREAMIUSED>
-          <page>manage_group_basket.php</page>
-          <nature>include</nature>
-      </WHEREAMIUSED>
-      <WHEREAMIUSED>
-          <page>load_groupbasket</page>
-          <nature>include</nature>
-      </WHEREAMIUSED>
-      <WHEREAMIUSED>
-          <page>load_groupbasket_db</page>
-          <nature>include</nature>
-      </WHEREAMIUSED>
-   </SERVICE>
-   <SERVICE>
-     <id>param_workflow</id>
-     <name>_PARAM_WORKFLOW</name>
-     <servicepage>param_workflow.php</servicepage>
-     <servicetype>use</servicetype>
-     <system_service>true</system_service>
-     <enabled>true</enabled>
-     <WHEREAMIUSED>
-          <page>groupbasket_popup.php</page>
-          <nature>include</nature>
-      </WHEREAMIUSED>
-      <WHEREAMIUSED>
-          <page>manage_group_basket.php</page>
-          <nature>include</nature>
-      </WHEREAMIUSED>
-      <WHEREAMIUSED>
-          <page>load_groupbasket</page>
-          <nature>include</nature>
-      </WHEREAMIUSED>
-      <WHEREAMIUSED>
-          <page>load_groupbasket_db</page>
-          <nature>include</nature>
-      </WHEREAMIUSED>
-   </SERVICE>
+        <id>param_index_difflist_types</id>
+        <name>_PARAM_AVAILABLE_DIFFLIST_TYPES_ON_GROUP_BASKETS</name>
+        <servicepage>param_index_difflist_types.php</servicepage>
+        <servicetype>use</servicetype>
+        <system_service>true</system_service>
+        <enabled>true</enabled>
+        <WHEREAMIUSED>
+            <page>groupbasket_popup.php</page>
+            <nature>include</nature>
+        </WHEREAMIUSED>
+        <WHEREAMIUSED>
+            <page>manage_group_basket.php</page>
+            <nature>include</nature>
+        </WHEREAMIUSED>
+        <WHEREAMIUSED>
+            <page>load_groupbasket</page>
+            <nature>include</nature>
+        </WHEREAMIUSED>
+        <WHEREAMIUSED>
+            <page>load_groupbasket_db</page>
+            <nature>include</nature>
+        </WHEREAMIUSED>
+    </SERVICE>
+    <SERVICE>
+        <id>param_workflow</id>
+        <name>_PARAM_WORKFLOW</name>
+        <servicepage>param_workflow.php</servicepage>
+        <servicetype>use</servicetype>
+        <system_service>true</system_service>
+        <enabled>true</enabled>
+        <WHEREAMIUSED>
+            <page>groupbasket_popup.php</page>
+            <nature>include</nature>
+        </WHEREAMIUSED>
+        <WHEREAMIUSED>
+            <page>manage_group_basket.php</page>
+            <nature>include</nature>
+        </WHEREAMIUSED>
+        <WHEREAMIUSED>
+            <page>load_groupbasket</page>
+            <nature>include</nature>
+        </WHEREAMIUSED>
+        <WHEREAMIUSED>
+            <page>load_groupbasket_db</page>
+            <nature>include</nature>
+        </WHEREAMIUSED>
+    </SERVICE>
     <SERVICE>
         <id>param_templates_entities</id>
         <name>_PARAM_TEMPLATE_ENTITIES</name>
@@ -293,11 +294,11 @@
         </WHEREAMIUSED>
     </SERVICE>
     <SERVICE>
-       <id>entities_print_sep_mlb</id>
-       <name>_ENTITIES_PRINT_SEP_MLB</name>
-       <comment>_ENTITIES_PRINT_SEP_MLB</comment>
-       <servicetype>menu</servicetype>
-       <system_service>false</system_service>
-       <enabled>true</enabled>
+        <id>entities_print_sep_mlb</id>
+        <name>_ENTITIES_PRINT_SEP_MLB</name>
+        <comment>_ENTITIES_PRINT_SEP_MLB</comment>
+        <servicetype>menu</servicetype>
+        <system_service>false</system_service>
+        <enabled>true</enabled>
     </SERVICE>
 </root>
diff --git a/package-lock.json b/package-lock.json
index 8d3c499f7e4..2e0904b1015 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,7 +6,7 @@
     "@angular/animations": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-5.2.5.tgz",
-      "integrity": "sha512-70ElCmaeDxLQc2OkgYhJjXj4zjtdjI4K1D5ZZm/uSPLlUcqC6uf6skCXlhMawQoPbsL/SXE5xw2HlMgEbhUysw==",
+      "integrity": "sha1-PnIYQyHEl5MFYZx0kCuL6S1223A=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -24,7 +24,7 @@
     "@angular/common": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/common/-/common-5.2.5.tgz",
-      "integrity": "sha512-jagCxo+75pcTwjuO1ZheIiTlKBJ6REFKFWoUPTzaSS6fnzReFJ+VPf4Pb0bWtHL1lWvbvnzmITOJPB9wmuM3fg==",
+      "integrity": "sha1-CN1jb6Rgd9BHBmsToarklAZvbFU=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -33,7 +33,7 @@
     "@angular/compiler": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-5.2.5.tgz",
-      "integrity": "sha512-YU/r5omexkrrBF3bZaseWrc2Iotk6hIdUWkPIL3gPC0hKJ3wBeB3sHCBujPQXktWdMBbQRujNSMZtgra3Oh1xQ==",
+      "integrity": "sha1-XjtRGQYEilefzQB6unKRFHLlqig=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -42,7 +42,7 @@
     "@angular/compiler-cli": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-5.2.5.tgz",
-      "integrity": "sha512-jRFMxUKpodzOBKdZc6OMse+CjK6xfTJssZQrYeIyqz2daobaIsMZP2hZX8s/PCfV8Vxa7XFwCJb7Fq2uyZKfHg==",
+      "integrity": "sha1-sZiLssCpVuf8FjrPjH15SgeojQg=",
       "dev": true,
       "requires": {
         "chokidar": "1.7.0",
@@ -54,7 +54,7 @@
     "@angular/core": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/core/-/core-5.2.5.tgz",
-      "integrity": "sha512-Uo7R3LrsvA24JkRbwXWUZWp7NSEpwdTUxT1NScyjrBK+t8ybSL5/42Jo21md5M4pjeCsIgUXlGoCm1QtT5aYnQ==",
+      "integrity": "sha1-JPnNdcWyco8t3Rhpd3WQ6nF3vKk=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -63,7 +63,7 @@
     "@angular/forms": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-5.2.5.tgz",
-      "integrity": "sha512-3feqqTuv9rIu7ZOsLCtM/ugNFz5RPujLHkE8bU1gsMM4/eMYruIFir2vbjnhMkD3K6KptEg4iO6tDW18diwXug==",
+      "integrity": "sha1-KtekIMbvbNh6NAccUxnsg/ftVqo=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -72,7 +72,7 @@
     "@angular/http": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/http/-/http-5.2.5.tgz",
-      "integrity": "sha512-VqTCkAnebe+M9Bqrfp1QYpBQCTbXide/NxrQfwiJY87kjKFeRBuy9/XH/2S5wIwlF5Yx3bmlaIufd9VI5r/0aQ==",
+      "integrity": "sha1-Egglbjbw5IbZbRCnM/3IQk/6Fr8=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -90,7 +90,7 @@
     "@angular/platform-browser": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-5.2.5.tgz",
-      "integrity": "sha512-iPAuoG/c3pD3hnk1g0VgJu/pzNITvLQyT0W71MDMSuxLxs291kq+U2jklm40pStISd1mPbCNKmvz/7M+WbdLhg==",
+      "integrity": "sha1-6uSvK3QvuQHYTWNnzZn56IECFR8=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -99,7 +99,7 @@
     "@angular/platform-browser-dynamic": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.2.5.tgz",
-      "integrity": "sha512-IMEe2qUTC3CA3KoswmJJs+O2Lkyd5GXgl5ULupqhhm/TOL2FLk00kwv8k3Epaf2d1wXcjK3BMG7aAwc6RLH7QA==",
+      "integrity": "sha1-uJ30EL2VPipoQzJfmsPAmhDq2vA=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -108,7 +108,7 @@
     "@angular/platform-server": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-5.2.5.tgz",
-      "integrity": "sha512-IpuEDNyoVfGO94jd1s+4IgoTBkWigwqD4YQTpcsC1mdY2Ax7NXXTAx28ZQF5EvPbSxsHGB5zG3oR7KE7GMNhYQ==",
+      "integrity": "sha1-IRG/2DahbHh6EPIJmgwmtqOgKwU=",
       "dev": true,
       "requires": {
         "domino": "1.0.30",
@@ -119,7 +119,7 @@
     "@angular/router": {
       "version": "5.2.5",
       "resolved": "https://registry.npmjs.org/@angular/router/-/router-5.2.5.tgz",
-      "integrity": "sha512-I8U0iy59lz0dAxU4zxRQHagfUPWF+MikLNMirRL1lrA49PG+5K1tiuIQ6p+8fZFAJ5UXwNHyXqYuWqsKRiVBHQ==",
+      "integrity": "sha1-+PIg1fuF/BDWD+YGsPKmRzImUUI=",
       "dev": true,
       "requires": {
         "tslib": "1.9.0"
@@ -128,7 +128,7 @@
     "@browserify/acorn5-object-spread": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/@browserify/acorn5-object-spread/-/acorn5-object-spread-5.0.1.tgz",
-      "integrity": "sha512-sFCUPzgeEjdq3rinwy4TFXtak2YZdhqpj6MdNusxkdTFr9TXAUEYK4YQSamR8Joqt/yii1drgl5hk8q/AtJDKA==",
+      "integrity": "sha1-kumzf5e+rJ7EKaPMR53tOAKXVAw=",
       "dev": true,
       "requires": {
         "acorn": "5.3.0"
@@ -137,7 +137,7 @@
         "acorn": {
           "version": "5.3.0",
           "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz",
-          "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==",
+          "integrity": "sha1-dEbTlFnFT7SagObuZHgUm5QOyCI=",
           "dev": true
         }
       }
@@ -145,7 +145,7 @@
     "@types/datatables.net": {
       "version": "1.10.8",
       "resolved": "https://registry.npmjs.org/@types/datatables.net/-/datatables.net-1.10.8.tgz",
-      "integrity": "sha512-5RzUppTRNhVJhAtP1Pq+hFVJgFP7V7yNt8Tjob8cXFg1zo91mtCR6xZn4JJ1hT6fYM1w9Bz9Iy62ja1bbZx7ZA==",
+      "integrity": "sha1-La3k1KULWHq3l0px5J7Q654Y8wA=",
       "dev": true,
       "requires": {
         "@types/jquery": "2.0.48"
@@ -154,13 +154,13 @@
     "@types/jquery": {
       "version": "2.0.48",
       "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-2.0.48.tgz",
-      "integrity": "sha512-nNLzUrVjaRV/Ds1eHZLYTd7IZxs38cwwLSaqMJj8OTXY8xNUbxSK69bi9cMLvQ7dm/IBeQ1wHwQ0S1uYa0rd2w==",
+      "integrity": "sha1-PpDYzeLSkBXlWDAX94MMs5dbLu8=",
       "dev": true
     },
     "@types/node": {
       "version": "7.0.55",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.55.tgz",
-      "integrity": "sha512-diCxfWNT4g2UM9Y+BPgy4s3egcZ2qOXc0mXLauvbsBUq9SBKQfh0SmuEUEhJVFZt/p6UDsjg1s2EgfM6OSlp4g==",
+      "integrity": "sha1-e7YhX/lCWh1xQQa+nw0+DiiCkog=",
       "dev": true
     },
     "JSONStream": {
@@ -182,7 +182,7 @@
     "anymatch": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
-      "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+      "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=",
       "dev": true,
       "requires": {
         "micromatch": "2.3.11",
@@ -201,7 +201,7 @@
     "arr-flatten": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
-      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
       "dev": true
     },
     "array-filter": {
@@ -231,7 +231,7 @@
     "asn1.js": {
       "version": "4.9.2",
       "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz",
-      "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==",
+      "integrity": "sha1-gRfvT37YfNj4kES1v/l6wkOhbJo=",
       "dev": true,
       "requires": {
         "bn.js": "4.11.8",
@@ -272,7 +272,7 @@
     "base64-js": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
-      "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==",
+      "integrity": "sha1-qRlH2h9KUW6jjltOwOw3c2deCIY=",
       "dev": true
     },
     "binary-extensions": {
@@ -284,7 +284,7 @@
     "bn.js": {
       "version": "4.11.8",
       "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
-      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+      "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=",
       "dev": true
     },
     "bootstrap": {
@@ -322,7 +322,7 @@
     "browser-pack": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.3.tgz",
-      "integrity": "sha512-Jo+RYsn8X8OhyP9tMXXg0ueR2fW696HUu1Hf3/DeiwNean1oGiPtdgGRNuUHBpPHzBH3x4n1kzAlgOgHSIq88g==",
+      "integrity": "sha1-kcqWUYWD71gKsGOjCd5i5Ad2ejk=",
       "dev": true,
       "requires": {
         "JSONStream": "1.3.2",
@@ -353,7 +353,7 @@
     "browserify": {
       "version": "15.2.0",
       "resolved": "https://registry.npmjs.org/browserify/-/browserify-15.2.0.tgz",
-      "integrity": "sha512-IHYyFPm2XjJCL+VV0ZtFv8wn/sAHVOm83q3yfSn8YWbZ9jcybgPKxSDdiuMU+35jUL1914l74RnXXPD9Iyo9yg==",
+      "integrity": "sha1-HhIbofpyz5/S2N8AL4Z0totF34k=",
       "dev": true,
       "requires": {
         "JSONStream": "1.3.2",
@@ -409,7 +409,7 @@
     "browserify-aes": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz",
-      "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==",
+      "integrity": "sha1-OLerVe24Bv8tzaGn8WIHc6R3xJ8=",
       "dev": true,
       "requires": {
         "buffer-xor": "1.0.3",
@@ -470,7 +470,7 @@
     "browserify-zlib": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
-      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+      "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=",
       "dev": true,
       "requires": {
         "pako": "1.0.6"
@@ -479,7 +479,7 @@
     "buffer": {
       "version": "5.0.8",
       "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz",
-      "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==",
+      "integrity": "sha1-hNqlLnzy+ozkGVvFzw94CeCTCyQ=",
       "dev": true,
       "requires": {
         "base64-js": "1.2.1",
@@ -529,7 +529,7 @@
     "cipher-base": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
-      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=",
       "dev": true,
       "requires": {
         "inherits": "2.0.3",
@@ -551,7 +551,7 @@
     "commander": {
       "version": "2.14.1",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
-      "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==",
+      "integrity": "sha1-IjUSPjevjKPGXfRbAm29NXsBuao=",
       "dev": true
     },
     "concat-map": {
@@ -664,7 +664,7 @@
     "crypto-browserify": {
       "version": "3.12.0",
       "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
-      "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+      "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=",
       "dev": true,
       "requires": {
         "browserify-cipher": "1.0.0",
@@ -725,7 +725,7 @@
     "detective": {
       "version": "5.0.2",
       "resolved": "https://registry.npmjs.org/detective/-/detective-5.0.2.tgz",
-      "integrity": "sha512-NUsLoezj4wb9o7vpxS9F3L5vcO87ceyRBcl48op06YFNwkyIEY997JpSCA5lDlDuDc6JxOtaL5qfK3muoWxpMA==",
+      "integrity": "sha1-hOwuHFgedCEeKuT/zh7fUsMmP4Q=",
       "dev": true,
       "requires": {
         "@browserify/acorn5-object-spread": "5.0.1",
@@ -736,7 +736,7 @@
         "acorn": {
           "version": "5.3.0",
           "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz",
-          "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==",
+          "integrity": "sha1-dEbTlFnFT7SagObuZHgUm5QOyCI=",
           "dev": true
         }
       }
@@ -761,7 +761,7 @@
     "domino": {
       "version": "1.0.30",
       "resolved": "https://registry.npmjs.org/domino/-/domino-1.0.30.tgz",
-      "integrity": "sha512-ikq8WiDSkICdkElud317F2Sigc6A3EDpWsxWBwIZqOl95km4p/Vc9Rj98id7qKgsjDmExj0AVM7JOd4bb647Xg==",
+      "integrity": "sha1-VKQVTsrpaGFmgPj+ujzt/zVccfQ=",
       "dev": true
     },
     "duplexer2": {
@@ -797,7 +797,7 @@
     "evp_bytestokey": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
-      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+      "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=",
       "dev": true,
       "requires": {
         "md5.js": "1.3.4",
@@ -1778,13 +1778,13 @@
     "function-bind": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=",
       "dev": true
     },
     "glob": {
       "version": "7.1.2",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
-      "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+      "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
       "dev": true,
       "requires": {
         "fs.realpath": "1.0.0",
@@ -1847,7 +1847,7 @@
     "hash.js": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
-      "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
+      "integrity": "sha1-NA3tvmKQGHFRweodd3o0SJNd+EY=",
       "dev": true,
       "requires": {
         "inherits": "2.0.3",
@@ -2034,7 +2034,7 @@
     "jquery": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
-      "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
+      "integrity": "sha1-lYzinoHJeQ8xvneS311NlfxX+8o="
     },
     "jquery-typeahead": {
       "version": "2.10.4",
@@ -2176,7 +2176,7 @@
     "miller-rabin": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
-      "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+      "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=",
       "dev": true,
       "requires": {
         "bn.js": "4.11.8",
@@ -2198,7 +2198,7 @@
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
       "dev": true,
       "requires": {
         "brace-expansion": "1.1.8"
@@ -2230,7 +2230,7 @@
     "module-deps": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-5.0.1.tgz",
-      "integrity": "sha512-sigq/hm/L+Z5IGi1DDl0x2ptkw7S86aFh213QhPLD8v9Opv90IHzKIuWJrRa5bJ77DVKHco2CfIEuThcT/vDJA==",
+      "integrity": "sha1-O8R8FLCm2SWv8uxKF3tFapauA5Y=",
       "dev": true,
       "requires": {
         "JSONStream": "1.3.2",
@@ -2270,6 +2270,11 @@
       "dev": true,
       "optional": true
     },
+    "ng2-dnd": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/ng2-dnd/-/ng2-dnd-5.0.2.tgz",
+      "integrity": "sha512-5mWWBePwvEPsNd/HkdbD543Q9mPyJofL6zkNydl8/Ah3qrrvZT2DaEPbknY08OgkXpI2qUGksc01OzzVlRQ9dQ=="
+    },
     "normalize-path": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
@@ -2307,7 +2312,7 @@
     "pako": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
-      "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==",
+      "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg=",
       "dev": true
     },
     "parents": {
@@ -2371,7 +2376,7 @@
     "pbkdf2": {
       "version": "3.0.14",
       "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
-      "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
+      "integrity": "sha1-o14TxkeZsGzhUyD0WcIw5o5zut4=",
       "dev": true,
       "requires": {
         "create-hash": "1.1.3",
@@ -2438,7 +2443,7 @@
     "randomatic": {
       "version": "1.1.7",
       "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
-      "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+      "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=",
       "dev": true,
       "requires": {
         "is-number": "3.0.0",
@@ -2479,7 +2484,7 @@
     "randombytes": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
-      "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
+      "integrity": "sha1-0wLFIpSFiISKjTAMkytEwkIx2oA=",
       "dev": true,
       "requires": {
         "safe-buffer": "5.1.1"
@@ -2488,7 +2493,7 @@
     "randomfill": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz",
-      "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==",
+      "integrity": "sha1-uWt99YfwHdkXJsQY8wVTsUGOPWI=",
       "dev": true,
       "requires": {
         "randombytes": "2.0.6",
@@ -2507,7 +2512,7 @@
     "readable-stream": {
       "version": "2.3.3",
       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
-      "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+      "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
       "dev": true,
       "requires": {
         "core-util-is": "1.0.2",
@@ -2545,13 +2550,13 @@
     "reflect-metadata": {
       "version": "0.1.12",
       "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz",
-      "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==",
+      "integrity": "sha1-MRvwxrY814LyKKgavhRqK/qcVvI=",
       "dev": true
     },
     "regex-cache": {
       "version": "0.4.4",
       "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
-      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+      "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=",
       "dev": true,
       "requires": {
         "is-equal-shallow": "0.1.3"
@@ -2578,7 +2583,7 @@
     "resolve": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
-      "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
+      "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=",
       "dev": true,
       "requires": {
         "path-parse": "1.0.5"
@@ -2597,7 +2602,7 @@
     "rxjs": {
       "version": "5.5.6",
       "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz",
-      "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==",
+      "integrity": "sha1-4x+5bW/S/x/YS86orpwC0AcXnAI=",
       "dev": true,
       "requires": {
         "symbol-observable": "1.0.1"
@@ -2614,7 +2619,7 @@
     "safe-buffer": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
-      "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+      "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=",
       "dev": true
     },
     "set-immediate-shim": {
@@ -2664,7 +2669,7 @@
     "source-map-support": {
       "version": "0.4.18",
       "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
-      "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
+      "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=",
       "dev": true,
       "requires": {
         "source-map": "0.5.7"
@@ -2693,7 +2698,7 @@
     "stream-http": {
       "version": "2.8.0",
       "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz",
-      "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==",
+      "integrity": "sha1-/YZUbaybHJGv+PxdKHuY+vtBvBA=",
       "dev": true,
       "requires": {
         "builtin-status-codes": "3.0.0",
@@ -2716,7 +2721,7 @@
     "string_decoder": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
-      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+      "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
       "dev": true,
       "requires": {
         "safe-buffer": "5.1.1"
@@ -2743,7 +2748,7 @@
     "systemjs": {
       "version": "0.20.19",
       "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-0.20.19.tgz",
-      "integrity": "sha512-H/rKwNEEyej/+IhkmFNmKFyJul8tbH/muiPq5TyNoVTwsGhUjRsN3NlFnFQUvFXA3+GQmsXkCNXU6QKPl779aw==",
+      "integrity": "sha1-wrnnnBn0vqU6GbHtP5dP+0Y76Uk=",
       "dev": true
     },
     "through": {
@@ -2790,7 +2795,7 @@
     "tsickle": {
       "version": "0.26.0",
       "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.26.0.tgz",
-      "integrity": "sha512-eWJ2CUfttGK0LqF9iJ/Avnxbj4M+fCyJ50Zag3wm73Fut1hsasPRHKxKdrMWVj4BMHnQNx7TO+DdNmLmJTSuNw==",
+      "integrity": "sha1-QLMKLdaryzOxguN1lmdL0c/kA5w=",
       "dev": true,
       "requires": {
         "minimist": "1.2.0",
@@ -2802,7 +2807,7 @@
     "tslib": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz",
-      "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==",
+      "integrity": "sha1-43qG/ajLuvI6BX9HPJ9Nxk5fwug=",
       "dev": true
     },
     "tty-browserify": {
@@ -2826,7 +2831,7 @@
     "uglify-js": {
       "version": "3.3.11",
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.11.tgz",
-      "integrity": "sha512-AKLsYcdV+sS5eAE4NtVXF6f2u/DCQynQm0jTGxF261+Vltu1dYNuHzjqDmk11gInj+H/zJIM2EAwXG3MzPb3VA==",
+      "integrity": "sha1-6dBYsgcVE4u06OXK4upYFoa9quM=",
       "dev": true,
       "requires": {
         "commander": "2.14.1",
@@ -2836,7 +2841,7 @@
         "source-map": {
           "version": "0.6.1",
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
           "dev": true
         }
       }
@@ -2918,7 +2923,7 @@
     "zone.js": {
       "version": "0.8.20",
       "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.20.tgz",
-      "integrity": "sha512-FXlA37ErSXCMy5RNBcGFgCI/Zivqzr0D19GuvDxhcYIJc7xkFp6c29DKyODJu0Zo+EMyur/WPPgcBh1EHjB9jA=="
+      "integrity": "sha1-ohjEjbCUZLGf9vyPDUu1sQRuGF0="
     }
   }
 }
diff --git a/package.json b/package.json
index 943021ae572..3b55b187911 100755
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
     "jquery-typeahead": "^2.8.0",
     "jquery.nicescroll": "~3.6.8",
     "jstree-bootstrap-theme": "^1.0.1",
+    "ng2-dnd": "^5.0.2",
     "photoswipe": "^4.1.2",
     "tinymce": "^4.7.7",
     "tooltipster": "^4.2.6",
-- 
GitLab