From b720847660ef93b989f35e3d741c4402d613f3cb Mon Sep 17 00:00:00 2001
From: "florian.azizian" <florian.azizian@maarch.org>
Date: Mon, 14 May 2018 13:07:35 +0000
Subject: [PATCH] FEAT #7721 starter contact group front

---
 ...ntacts-group-administration.component.html |  64 +++++++++++
 ...tacts-groups-administration.component.html |  86 +++++++++++++++
 .../admin/contacts/admin_contacts.php         |  11 +-
 .../administration-routing.module.ts          |   5 +
 .../administration/administration.module.ts   |   4 +
 ...contacts-group-administration.component.ts | 100 ++++++++++++++++++
 ...ontacts-groups-administration.component.ts |  98 +++++++++++++++++
 .../js/angular/lang/lang-en.ts                |  10 ++
 .../js/angular/lang/lang-fr.ts                |   7 ++
 apps/maarch_entreprise/lang/en.php            |   7 ++
 apps/maarch_entreprise/lang/fr.php            |   7 ++
 11 files changed, 398 insertions(+), 1 deletion(-)
 create mode 100755 apps/maarch_entreprise/Views/contacts-group-administration.component.html
 create mode 100755 apps/maarch_entreprise/Views/contacts-groups-administration.component.html
 mode change 100644 => 100755 apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.ts
 mode change 100644 => 100755 apps/maarch_entreprise/js/angular/app/administration/administration.module.ts
 create mode 100755 apps/maarch_entreprise/js/angular/app/administration/contacts-group-administration.component.ts
 create mode 100755 apps/maarch_entreprise/js/angular/app/administration/contacts-groups-administration.component.ts

diff --git a/apps/maarch_entreprise/Views/contacts-group-administration.component.html b/apps/maarch_entreprise/Views/contacts-group-administration.component.html
new file mode 100755
index 00000000000..1e2741a3c54
--- /dev/null
+++ b/apps/maarch_entreprise/Views/contacts-group-administration.component.html
@@ -0,0 +1,64 @@
+<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.contactsGroupModification}}
+            <small [class.hide-for-mobile]="mobileQuery.matches">{{action.label_action}}</small>
+        </h1>
+        <h1 class="admin-toolbar-title" *ngIf="creationMode">{{lang.contactGroupCreation}}
+            <small [class.hide-for-mobile]="mobileQuery.matches">{{action.label_action}}</small>
+        </h1>
+        <span style="flex: 1 1 auto;"></span>
+        <menu-top></menu-top>
+    </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">
+            <menu-nav></menu-nav>
+            <mat-divider></mat-divider>
+        </mat-sidenav>
+        <mat-sidenav-content>
+            <div *ngIf="loading" style="display:flex;height:100%;">
+                <mat-spinner style="margin:auto;"></mat-spinner>
+            </div>
+            <mat-card *ngIf="!loading" class="card-app-content">
+                <form class="form-horizontal" (ngSubmit)="onSubmit()" #actionsFormUp="ngForm">
+                    <div class="form-group">
+                        <div class="col-sm-12">
+                            <mat-form-field>
+                                <input matInput [(ngModel)]="action.label_action" required name="action_name" id="action_name" 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)]="action.label_action" required name="description" id="description" title="{{lang.description}}"
+                                    type="text" placeholder="{{lang.description}}" maxlength="255">
+                            </mat-form-field>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <div class="col-sm-6" style="text-align:center;">
+                            <mat-slide-toggle name="history" title="{{lang.contactsGroupDesc}}" id="history" color="primary" [(ngModel)]="action.history"
+                                [checked]="action.history == 'Y'">{{lang.public}}</mat-slide-toggle>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <div class="col-sm-12" style="text-align:center;">
+                            <button mat-raised-button color="primary" type="submit" [disabled]="!actionsFormUp.form.valid">{{lang.save}}</button>
+                        </div>
+                    </div>
+                </form>
+            </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" style="overflow-x:hidden;">
+            <mat-list>
+                <h3 mat-subheader>Action(s)</h3>
+            </mat-list>
+        </mat-sidenav>
+    </mat-sidenav-container>
+</div>
\ No newline at end of file
diff --git a/apps/maarch_entreprise/Views/contacts-groups-administration.component.html b/apps/maarch_entreprise/Views/contacts-groups-administration.component.html
new file mode 100755
index 00000000000..ef3975e4bd5
--- /dev/null
+++ b/apps/maarch_entreprise/Views/contacts-groups-administration.component.html
@@ -0,0 +1,86 @@
+<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.contactsGroups}}
+            <small [class.hide-for-mobile]="mobileQuery.matches">{{actions.length}} {{lang.contactsGroups}}</small>
+        </h1>
+        <span style="flex: 1 1 auto;"></span>
+        <menu-top></menu-top>
+    </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">
+            <menu-nav></menu-nav>
+            <mat-divider></mat-divider>
+            <mat-nav-list>
+                <h3 mat-subheader>{{lang.contactsGroups}}</h3>
+                <a mat-list-item routerLink="/administration/contacts-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-divider></mat-divider>
+            <menu-app></menu-app>
+        </mat-sidenav>
+        <mat-sidenav-content>
+            <div *ngIf="loading" style="display:flex;height:100%;">
+                <mat-spinner style="margin:auto;"></mat-spinner>
+            </div>
+            <mat-card *ngIf="!loading" class="card-app-content">
+                <div class="row">
+                    <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">
+                        </mat-paginator>
+                    </div>
+                </div>
+                <mat-table #table [dataSource]="dataSource" matSort matSortActive="id" matSortDirection="asc">
+                    <ng-container matColumnDef="id">
+                        <mat-header-cell *matHeaderCellDef mat-sort-header [class.hide-for-mobile]="mobileQuery.matches">{{lang.label}}</mat-header-cell>
+                        <mat-cell *matCellDef="let element" [class.hide-for-mobile]="mobileQuery.matches"> {{element.id}} </mat-cell>
+                    </ng-container>
+                    <ng-container matColumnDef="label">
+                        <mat-header-cell *matHeaderCellDef mat-sort-header>{{lang.description}}</mat-header-cell>
+                        <mat-cell *matCellDef="let element"> {{element.label_action}} </mat-cell>
+                    </ng-container>
+                    <ng-container matColumnDef="public">
+                        <mat-header-cell *matHeaderCellDef mat-sort-header [class.hide-for-mobile]="mobileQuery.matches">{{lang.public}}</mat-header-cell>
+                        <mat-cell *matCellDef="let element" [class.hide-for-mobile]="mobileQuery.matches">
+                            <span *ngIf="element.is_folder_action == 'N'"> {{lang.no}} </span>
+                            <span *ngIf="element.is_folder_action == 'Y'"> {{lang.yes}} </span>
+                        </mat-cell>
+                    </ng-container>
+                    <ng-container matColumnDef="owner">
+                        <mat-header-cell *matHeaderCellDef mat-sort-header>{{lang.createdBy}}</mat-header-cell>
+                        <mat-cell *matCellDef="let element"> {{element.label_action}} </mat-cell>
+                    </ng-container>
+                    <ng-container matColumnDef="actions">
+                        <mat-header-cell *matHeaderCellDef></mat-header-cell>
+                        <mat-cell *matCellDef="let element" style="justify-content: flex-end;">
+                            <button mat-icon-button color="warn" [disabled]="element.is_system == 'Y'" matTooltip="{{lang.delete}}" (click)="$event.stopPropagation();deleteContactsGroup(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;" routerLink="/administration/contacts-groups/{{row.id}}" style="cursor:pointer;" matTooltip="{{lang.view}}"></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>{{lang.contactsGroups}}</h3>
+            </mat-nav-list>
+        </mat-sidenav>
+    </mat-sidenav-container>
+</div>
\ No newline at end of file
diff --git a/apps/maarch_entreprise/admin/contacts/admin_contacts.php b/apps/maarch_entreprise/admin/contacts/admin_contacts.php
index 2f8d3f4e731..3dd0378e469 100755
--- a/apps/maarch_entreprise/admin/contacts/admin_contacts.php
+++ b/apps/maarch_entreprise/admin/contacts/admin_contacts.php
@@ -65,7 +65,7 @@ unset($_SESSION['m_admin']);
 
     <div class="admin_item" onclick="window.top.location='<?php echo $_SESSION['config']['businessappurl'];?>index.php?page=contacts_v2';">
         <div>
-            <i class="fa fa-users fa-4x" title="<?php echo _MANAGE_CONTACTS_DESC;?>" ></i>
+            <i class="fa fa-address-book-o fa-4x" title="<?php echo _MANAGE_CONTACTS_DESC;?>" ></i>
         </div>
         <div>
                 <strong><?php echo _MANAGE_CONTACTS;?></strong>
@@ -98,6 +98,15 @@ unset($_SESSION['m_admin']);
                 <strong><?php echo _VIEW_TREE_CONTACTS;?></strong>
          </div>
     </div>
+
+    <div class="admin_item" onclick="triggerAngular('#/administration/contacts-groups')">
+        <div>
+            <i class="fa fa-users fa-4x" title="<?php echo _VIEW_CONTACTS_GROUPS_DESC;?>" ></i>
+        </div>
+        <div>
+                <strong><?php echo _VIEW_CONTACTS_GROUPS;?></strong>
+         </div>
+    </div>
     <div class="clearfix"></div>
 </div>
 </div>
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
old mode 100644
new mode 100755
index ec8ce2c4284..35a9a36c00c
--- a/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.ts
+++ b/apps/maarch_entreprise/js/angular/app/administration/administration-routing.module.ts
@@ -26,6 +26,8 @@ import { NotificationAdministrationComponent }          from './notification-adm
 import { HistoryAdministrationComponent }               from './history-administration.component';
 import { BatchHistoryAdministrationComponent }          from './batchHistory-administration.component';
 import { UpdateStatusAdministrationComponent }          from './update-status-administration.component';
+import { ContactsGroupsAdministrationComponent }        from './contacts-groups-administration.component';
+import { ContactsGroupAdministrationComponent }         from './contacts-group-administration.component';
 
  
 @NgModule({
@@ -65,6 +67,9 @@ import { UpdateStatusAdministrationComponent }          from './update-status-ad
             { path: 'administration/history', component: HistoryAdministrationComponent },
             { path: 'administration/historyBatch', component: BatchHistoryAdministrationComponent },
             { path: 'administration/update-status', component: UpdateStatusAdministrationComponent },
+            { path: 'administration/contacts-groups', component: ContactsGroupsAdministrationComponent },
+            { path: 'administration/contacts-groups/new', component: ContactsGroupAdministrationComponent },
+            { path: 'administration/contacts-groups/:id', component: ContactsGroupAdministrationComponent },
         ]),
     ],
     exports: [
diff --git a/apps/maarch_entreprise/js/angular/app/administration/administration.module.ts b/apps/maarch_entreprise/js/angular/app/administration/administration.module.ts
old mode 100644
new mode 100755
index f6dd882fccd..f27a3543700
--- a/apps/maarch_entreprise/js/angular/app/administration/administration.module.ts
+++ b/apps/maarch_entreprise/js/angular/app/administration/administration.module.ts
@@ -36,6 +36,8 @@ import { BatchHistoryAdministrationComponent }          from './batchHistory-adm
 import { UpdateStatusAdministrationComponent }          from './update-status-administration.component';
 import { NotificationsAdministrationComponent }         from './notifications-administration.component';
 import { NotificationAdministrationComponent }          from './notification-administration.component';
+import { ContactsGroupsAdministrationComponent }        from './contacts-groups-administration.component';
+import { ContactsGroupAdministrationComponent }         from './contacts-group-administration.component';
 
 @NgModule({
     imports:      [
@@ -71,6 +73,8 @@ import { NotificationAdministrationComponent }          from './notification-adm
         HistoryAdministrationComponent,
         BatchHistoryAdministrationComponent,
         UpdateStatusAdministrationComponent,
+        ContactsGroupsAdministrationComponent,
+        ContactsGroupAdministrationComponent,
         NotificationsAdministrationComponent,
         NotificationAdministrationComponent,
         UsersAdministrationRedirectModalComponent,
diff --git a/apps/maarch_entreprise/js/angular/app/administration/contacts-group-administration.component.ts b/apps/maarch_entreprise/js/angular/app/administration/contacts-group-administration.component.ts
new file mode 100755
index 00000000000..47bf7396787
--- /dev/null
+++ b/apps/maarch_entreprise/js/angular/app/administration/contacts-group-administration.component.ts
@@ -0,0 +1,100 @@
+import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
+import { MediaMatcher } from '@angular/cdk/layout';
+import { HttpClient } from '@angular/common/http';
+import { Router, ActivatedRoute } from '@angular/router';
+import { LANG } from '../translate.component';
+import { NotificationService } from '../notification.service';
+
+declare function $j(selector: any): any;
+
+declare var angularGlobals: any;
+
+
+@Component({
+    templateUrl: "../../../../Views/contacts-group-administration.component.html",
+    providers: [NotificationService]
+})
+export class ContactsGroupAdministrationComponent implements OnInit {
+
+    mobileQuery: MediaQueryList;
+    private _mobileQueryListener: () => void;
+    lang: any = LANG;
+    coreUrl: string;
+    creationMode: boolean;
+    action: any = {};
+    statuses: any[] = [];
+    actionPagesList: any[] = [];
+    categoriesList: any[] = [];
+    keywordsList: any[] = [];
+
+    loading: boolean = false;
+
+    constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher, public http: HttpClient, private route: ActivatedRoute, private router: Router, private notify: NotificationService) {
+        $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);
+    }
+
+    ngOnInit(): void {
+        this.coreUrl = angularGlobals.coreUrl;
+        this.loading = true;
+
+        this.route.params.subscribe(params => {
+            if (typeof params['id'] == "undefined") {
+                this.creationMode = true;
+
+                this.http.get(this.coreUrl + 'rest/initAction')
+                    .subscribe((data: any) => {
+                        this.action = data.action;
+                        this.categoriesList = data.categoriesList;
+                        this.statuses = data.statuses;
+
+                        this.actionPagesList = data.action_pagesList;
+                        this.keywordsList = data.keywordsList;
+                        this.loading = false;
+                    });
+            }
+            else {
+                this.creationMode = false;
+
+                this.http.get(this.coreUrl + 'rest/actions/' + params['id'])
+                    .subscribe((data: any) => {
+                        this.action = data.action;
+                        this.categoriesList = data.categoriesList;
+                        this.statuses = data.statuses;
+
+                        this.actionPagesList = data.action_pagesList;
+                        this.keywordsList = data.keywordsList;
+                        this.loading = false;
+                    });
+            }
+        });
+    }
+
+    onSubmit() {
+        if (this.creationMode) {
+            this.http.post(this.coreUrl + 'rest/actions', this.action)
+                .subscribe(() => {
+                    this.router.navigate(['/administration/actions']);
+                    this.notify.success(this.lang.actionAdded);
+
+                }, (err) => {
+                    this.notify.error(err.error.errors);
+                });
+        } else {
+            this.http.put(this.coreUrl + 'rest/actions/' + this.action.id, this.action)
+                .subscribe(() => {
+                    this.router.navigate(['/administration/actions']);
+                    this.notify.success(this.lang.actionUpdated);
+
+                }, (err) => {
+                    this.notify.error(err.error.errors);
+                });
+        }
+    }
+}
\ No newline at end of file
diff --git a/apps/maarch_entreprise/js/angular/app/administration/contacts-groups-administration.component.ts b/apps/maarch_entreprise/js/angular/app/administration/contacts-groups-administration.component.ts
new file mode 100755
index 00000000000..cb4a2da6ffc
--- /dev/null
+++ b/apps/maarch_entreprise/js/angular/app/administration/contacts-groups-administration.component.ts
@@ -0,0 +1,98 @@
+import { ChangeDetectorRef, Component, ViewChild, 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';
+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: "../../../../Views/contacts-groups-administration.component.html",
+    providers: [NotificationService]
+})
+
+export class ContactsGroupsAdministrationComponent implements OnInit {
+    mobileQuery: MediaQueryList;
+    private _mobileQueryListener: () => void;
+    coreUrl: string;
+    lang: any = LANG;
+    search: string = null;
+
+    actions: any[] = [];
+    titles: any[] = [];
+
+    loading: boolean = false;
+
+    displayedColumns = ['id', 'label', 'public', 'owner', 'actions'];
+    dataSource = new MatTableDataSource(this.actions);
+    @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) {
+        $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'>" + this.lang.administration + "</a> > " + this.lang.actions;
+        }
+    }
+
+    ngOnInit(): void {
+        this.coreUrl = angularGlobals.coreUrl;
+
+        this.loading = true;
+
+        this.updateBreadcrumb(angularGlobals.applicationName);
+        $j('#inner_content').remove();
+
+        this.http.get(this.coreUrl + 'rest/actions')
+            .subscribe((data) => {
+                this.actions = data['actions'];
+                this.loading = false;
+                setTimeout(() => {
+                    this.dataSource = new MatTableDataSource(this.actions);
+                    this.dataSource.paginator = this.paginator;
+                    this.dataSource.sort = this.sort;
+                }, 0);
+            }, (err) => {
+                console.log(err);
+                location.href = "index.php";
+            });
+    }
+
+    deleteContactsGroup(contactsGroup: any) {
+        let r = confirm(this.lang.confirmAction + ' ' + this.lang.delete + ' « ' + contactsGroup.label_action + ' »');
+
+        if (r) {
+            this.http.delete(this.coreUrl + 'rest/contactsGroups/' + contactsGroup.id)
+                .subscribe((data: any) => {
+                    this.actions = data.actions;
+                    this.dataSource = new MatTableDataSource(this.actions);
+                    this.dataSource.paginator = this.paginator;
+                    this.dataSource.sort = this.sort;
+                    this.notify.success(this.lang.actionDeleted);
+
+                }, (err) => {
+                    this.notify.error(err.error.errors);
+                });
+        }
+    }
+}
diff --git a/apps/maarch_entreprise/js/angular/lang/lang-en.ts b/apps/maarch_entreprise/js/angular/lang/lang-en.ts
index 1cd759eaa75..b30459ca9ce 100755
--- a/apps/maarch_entreprise/js/angular/lang/lang-en.ts
+++ b/apps/maarch_entreprise/js/angular/lang/lang-en.ts
@@ -444,4 +444,14 @@ export const LANG_EN = {
     "deleteAssignation"                 : "Delete assignation",
     "webserviceAccount"                 : "Webservice account",
     "webserviceAccountDesc"             : "If enabled, this account cannot be used to login in application (in graphic mode).",
+    'contactsGroups'                    : 'Contact(s) group(s)',
+    "contactsGroupModification"         : "Contacts group modification",
+    "contactGroupCreation"              : "Contacts group creation",
+    "private"                           : "Private",
+    "public"                            : "Public",
+    "contactsGroupDesc"                 : "If the grouping is public, all the users will be able to use this one. Otherwise it is private, and only the creator can use it",
+    "createdBy"                         : "Created by",
+
+
+
 };
diff --git a/apps/maarch_entreprise/js/angular/lang/lang-fr.ts b/apps/maarch_entreprise/js/angular/lang/lang-fr.ts
index 5ac72ec15b5..471f3109ec7 100755
--- a/apps/maarch_entreprise/js/angular/lang/lang-fr.ts
+++ b/apps/maarch_entreprise/js/angular/lang/lang-fr.ts
@@ -464,4 +464,11 @@ export const LANG_FR = {
     'inactives'                         : 'Inactif(s)',
     'quota'                             : 'Quota',
     'quotaExceeded'                     : 'Quota dépassé',
+    'contactsGroups'                    : 'Groupement(s) de contact(s)',
+    "contactsGroupModification"         : "Modification du groupement de contact",
+    "contactGroupCreation"              : "Création d'un groupement de contact",
+    "private"                           : "Privé",
+    "public"                            : "Public",
+    "contactsGroupDesc"                 : "Si le groupement est public, tous les utilisateurs pourront utiliser celui-ci. Sinon il est privé, et seul le créateur pourra l'utiliser",
+    "createdBy"                         : "Créé par",
 };
diff --git a/apps/maarch_entreprise/lang/en.php b/apps/maarch_entreprise/lang/en.php
index d936fa8dd02..3e6dd627eb2 100755
--- a/apps/maarch_entreprise/lang/en.php
+++ b/apps/maarch_entreprise/lang/en.php
@@ -2574,6 +2574,13 @@ if (!defined('_VIEW_TREE_CONTACTS')) {
     define('_VIEW_TREE_CONTACTS', 'Contacts tree view');
 }
 
+if (!defined('_VIEW_CONTACTS_GROUPS_DESC')) {
+    define('_VIEW_CONTACTS_GROUPS_DESC', 'Contacts groups');
+}
+if (!defined('_VIEW_CONTACTS_GROUPS')) {
+    define('_VIEW_CONTACTS_GROUPS', 'Contacts groups');
+}
+
 if (!defined('_ADDRESSES_LIST')) {
     define('_ADDRESSES_LIST', 'Addresses list');
 }
diff --git a/apps/maarch_entreprise/lang/fr.php b/apps/maarch_entreprise/lang/fr.php
index 890581ebd9c..a46efe5afe7 100755
--- a/apps/maarch_entreprise/lang/fr.php
+++ b/apps/maarch_entreprise/lang/fr.php
@@ -2605,6 +2605,13 @@ if (!defined('_VIEW_TREE_CONTACTS')) {
     define('_VIEW_TREE_CONTACTS', 'Arborescence des contacts');
 }
 
+if (!defined('_VIEW_CONTACTS_GROUPS_DESC')) {
+    define('_VIEW_CONTACTS_GROUPS_DESC', 'Groupements de contacts utilisés à l\'indexation d\'un courrier');
+}
+if (!defined('_VIEW_CONTACTS_GROUPS')) {
+    define('_VIEW_CONTACTS_GROUPS', 'Groupements de contacts');
+}
+
 if (!defined('_ADDRESSES_LIST')) {
     define('_ADDRESSES_LIST', 'Liste des adresses');
 }
-- 
GitLab