diff --git a/lang/fr.json b/lang/fr.json
index 689636464f2bfb0c9806214ff6b6c3fead0d3592..690e0e649c2846e2ca91cfc96f2b48bf12242ad9 100755
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -307,7 +307,7 @@
 		"wrongCurrentPassword": "Le mot de passe actuel n'est pas correct",
 		"alreadyUsedPassword": "Le mot de passe a déjà été utilisé",
 		"homePage": "Page d'accueil",
-		"newDocumentToVisa": "Nouveau(x) document(s) à viser / signer",
+		"newDocumentToVisa": "Importer de nouveau(x) document(s)",
 		"searchUser": "Rechercher un utilisateur"
 	}
 }
diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts
index 78f3133ea6c85c219de225b26557fed2a16c7395..76e8b22c63a415ded7ab31821b08e57fd3254370 100755
--- a/src/frontend/app/app.module.ts
+++ b/src/frontend/app/app.module.ts
@@ -24,6 +24,8 @@ import { LatinisePipe } from 'ngx-pipes';
 
 import { AppMaterialModule } from './app-material.module';
 import { AppRoutingModule } from './app-routing.module';
+import { DragDropDirective } from './plugins/upload-file-dnd.directive';
+
 
 // COMPONENTS
 import { AppComponent } from './app.component';
@@ -51,6 +53,7 @@ import { DocumentListComponent } from './document/document-list/document-list.co
 import { MainDocumentDetailComponent } from './document/main-document-detail/main-document-detail.component';
 import { UpdatePasswordComponent } from './login/updatePassword/updatePassword.component';
 import { PasswordModificationComponent } from './login/passwordModification/password-modification.component';
+import { VisaWorkflowModelsComponent } from './document/visa-workflow/models/visa-workflow-models.component';
 
 // ADMINISTRATION
 import { AdminSidebarComponent } from './sidebar/administration/admin-sidebar.component';
@@ -85,6 +88,7 @@ import { SortPipe } from './plugins/sorting.pipe';
 @NgModule({
   declarations: [
     AppComponent,
+    DragDropDirective,
     LoginComponent,
     HomeComponent,
     ForgotPasswordComponent,
@@ -125,7 +129,8 @@ import { SortPipe } from './plugins/sorting.pipe';
     UsersComponent,
     CheckConnectionComponent,
     CheckEmailConnectionComponent,
-    IndexationComponent
+    IndexationComponent,
+    VisaWorkflowModelsComponent
   ],
   imports: [
     FormsModule,
diff --git a/src/frontend/app/document/visa-workflow/models/visa-workflow-models.component.html b/src/frontend/app/document/visa-workflow/models/visa-workflow-models.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..477ac961586ae4c1c4ae5d040663e34cf0ecb918
--- /dev/null
+++ b/src/frontend/app/document/visa-workflow/models/visa-workflow-models.component.html
@@ -0,0 +1,17 @@
+<ion-list lines="none">
+    <ion-list-header>
+        <ion-label color="secondary">Modèles de circuit</ion-label>
+    </ion-list-header>
+    <ion-item button *ngFor="let model of visaWorkflowModels" (click)="loadVisaWorkflow(model)">
+        <ion-label>{{model.title}}</ion-label>
+        <ion-buttons slot="end">
+            <ion-button fill="clear" slot="icon-only" shape="round" color="danger" (click)="$event.stopPropagation();removeModel(model)">
+                <ion-icon slot="icon-only" name="trash-outline"></ion-icon>
+            </ion-button>
+        </ion-buttons>
+    </ion-item>
+    <ion-item button (click)="createModel()" [disabled]="currentWorkflow.length === 0">
+        <ion-icon color="primary" slot="start" name="add-circle-outline"></ion-icon>
+        <ion-label color="primary">Nouveau modèle</ion-label>
+    </ion-item>
+</ion-list>
\ No newline at end of file
diff --git a/src/frontend/app/document/visa-workflow/models/visa-workflow-models.component.scss b/src/frontend/app/document/visa-workflow/models/visa-workflow-models.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/frontend/app/document/visa-workflow/models/visa-workflow-models.component.ts b/src/frontend/app/document/visa-workflow/models/visa-workflow-models.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..088d8ef75c9081ea8a7e60eed989fb7250a0525c
--- /dev/null
+++ b/src/frontend/app/document/visa-workflow/models/visa-workflow-models.component.ts
@@ -0,0 +1,159 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { AlertController, PopoverController } from '@ionic/angular';
+import { NotificationService } from '../../../service/notification.service';
+import { catchError, tap } from 'rxjs/operators';
+import { of } from 'rxjs';
+
+@Component({
+    selector: 'app-visa-workflow-models',
+    templateUrl: 'visa-workflow-models.component.html',
+    styleUrls: ['visa-workflow-models.component.scss'],
+})
+export class VisaWorkflowModelsComponent implements OnInit {
+
+    @Input() currentWorkflow: any[] = [];
+
+    visaWorkflowModels: any[] = [];
+
+    constructor(
+        public http: HttpClient,
+        public popoverController: PopoverController,
+        public alertController: AlertController,
+        public notificationService: NotificationService,
+    ) { }
+
+    ngOnInit(): void {
+        this.getVisaUserModels();
+    }
+
+    async createModel() {
+        const alert = await this.alertController.create({
+            header: 'Nouveau modèle',
+            message: 'Le circuit en cours sera sauvegardé.',
+            inputs: [
+                {
+                    name: 'title',
+                    type: 'text',
+                    placeholder: 'Label'
+                },
+            ],
+            buttons: [
+                {
+                    text: 'Cancel',
+                    role: 'cancel',
+                    cssClass: 'secondary',
+                    handler: (blah) => {
+                        console.log('Confirm Cancel: blah');
+                    }
+                }, {
+                    text: 'Ok',
+                    handler: (data: any) => {
+                        if (data.title !== '') {
+                            this.saveModel(data.title);
+                            return true;
+                        } else {
+                            this.notificationService.error('Label mandatory');
+                            return false;
+                        }
+                    }
+                }
+            ]
+        });
+
+        await alert.present();
+    }
+
+    saveModel(title: string) {
+        const objToSend: any = {
+            title: title,
+            items: this.currentWorkflow.map((item: any) => {
+                return {
+                    userId: item.userId,
+                    mode: item.mode,
+                    signatureMode: 'standard'
+                };
+            })
+        };
+        this.http.post('../rest/workflowTemplates', objToSend).pipe(
+            tap((res: any) => {
+                this.notificationService.success('Modèle créé');
+                this.visaWorkflowModels.push({ id: res.id, title: title });
+            }),
+            catchError(err => {
+                this.notificationService.handleErrors(err);
+                return of(false);
+            })
+        ).subscribe();
+    }
+
+    async removeModel(model: any) {
+        const alert = await this.alertController.create({
+            header: 'Supprimer',
+            message: 'Supprimer le modèle ?',
+            buttons: [
+                {
+                    text: 'Non',
+                    role: 'cancel',
+                    cssClass: 'secondary',
+                    handler: () => { }
+                }, {
+                    text: 'Oui',
+                    handler: () => {
+                        this.http.delete(`../rest/workflowTemplates/${model.id}`).pipe(
+                            tap(() => {
+                                this.visaWorkflowModels = this.visaWorkflowModels.filter((item: any) => item.id !== model.id);
+                                this.notificationService.success(`Modèle ${model.title} supprimé`);
+                            }),
+                            catchError(err => {
+                                this.notificationService.handleErrors(err);
+                                return of(false);
+                            })
+                        ).subscribe();
+                    }
+                }
+            ]
+        });
+
+        await alert.present();
+    }
+
+    getVisaUserModels() {
+        this.http.get('../rest/workflowTemplates').pipe(
+            tap((data: any) => {
+                this.visaWorkflowModels = data.workflowTemplates;
+            }),
+            catchError(err => {
+                this.notificationService.handleErrors(err);
+                return of(false);
+            })
+        ).subscribe();
+    }
+
+    loadVisaWorkflow(model: any) {
+        this.http.get(`../rest/workflowTemplates/${model.id}`).pipe(
+            tap((data: any) => {
+                const workflows: any[] = data.workflowTemplate.items.map((item: any) => {
+                    const obj: any = {
+                        'userId': item.userId,
+                        'userDisplay': item.userLabel,
+                        'mode': item.mode,
+                        'processDate': null,
+                        'current': false,
+                        'modes': [
+                            'visa',
+                            'sign',
+                            'rgs'
+                        ]
+                    };
+                    return obj;
+                });
+                this.popoverController.dismiss(workflows);
+            }),
+            catchError(err => {
+                this.notificationService.handleErrors(err);
+                return of(false);
+            })
+        ).subscribe();
+    }
+}
diff --git a/src/frontend/app/document/visa-workflow/visa-workflow.component.html b/src/frontend/app/document/visa-workflow/visa-workflow.component.html
index 8f690a355f1e9c4cca928021fd53850a9be39a39..3d0bb2a1b3ef5b2c8e2f67e0a14f5c712df82e71 100644
--- a/src/frontend/app/document/visa-workflow/visa-workflow.component.html
+++ b/src/frontend/app/document/visa-workflow/visa-workflow.component.html
@@ -11,11 +11,20 @@
 <ion-content (click)="resetVisaUsersList();">
     <ng-container *ngIf="editMode">
         <ion-item lines="none">
-            <ion-searchbar #searchInput [(ngModel)]="visaUsersSearchVal" [placeholder]="'lang.searchUser' | translate" (ionChange)="getVisaUsers($event)"></ion-searchbar>
+            <ion-searchbar #searchInput [(ngModel)]="visaUsersSearchVal" [placeholder]="'lang.searchUser' | translate"
+                (ionChange)="getVisaUsers($event)" (ionFocus)="visaUsersSearchVal=''"></ion-searchbar>
+            <ion-buttons slot="end">
+                <ion-button fill="clear" slot="icon-only" shape="round" color="primary"
+                    (click)="openVisaWorkflowModels($event)" [title]="'Modèles de circuit'">
+                    <ion-icon slot="icon-only" name="albums-outline"></ion-icon>
+                </ion-button>
+            </ion-buttons>
         </ion-item>
-        <ion-list *ngIf="visaUsersList.length > 0" style="position: absolute;z-index: 1;width: 100%;box-shadow: 0 4px 2px -2px gray;">
+        <ion-list *ngIf="visaUsersList.length > 0"
+            style="position: absolute;z-index: 1;width: 100%;box-shadow: 0 4px 2px -2px gray;">
             <ion-item *ngFor="let user of visaUsersList">
-                <ion-checkbox color="primary" slot="start" [value]="user" (ionChange)="addUser($event.detail.value, searchInput)"></ion-checkbox>
+                <ion-checkbox color="primary" slot="start" [value]="user"
+                    (ionChange)="addUser($event.detail.value, searchInput)"></ion-checkbox>
                 <ion-label>{{ user.firstname }} {{ user.lastname }}</ion-label>
                 <ion-note slot="end">{{ user.email }}</ion-note>
             </ion-item>
@@ -23,7 +32,7 @@
     </ng-container>
     <ion-list *ngIf="visaWorkflow.length === 0">
         <ion-item lines="none">
-            <ion-label color="medium">Aucune personne dans le circuit</ion-label>
+            <ion-label class="ion-text-center" color="medium">Aucune personne dans le circuit</ion-label>
         </ion-item>
     </ion-list>
     <ion-list dnd-sortable-container [dropZones]="['boxers-zone']" [sortableData]="visaWorkflow">
@@ -32,11 +41,11 @@
                 <img [src]="diffusion.userPicture">
             </ion-avatar>
             <ion-label>{{diffusion.userDisplay}}</ion-label>
-            <ion-select [value]="diffusion.mode" interface="popover">
-                <ion-select-option [value]="mode" *ngFor="let mode of diffusion.modes">{{mode}}</ion-select-option>
+            <ion-select [(ngModel)]="diffusion.mode" interface="popover">
+                <ion-select-option [value]="mode" *ngFor="let mode of diffusion.modes">{{'lang.' + mode + 'User' | translate}}</ion-select-option>
             </ion-select>
             <ion-button fill="clear" slot="end" shape="round" color="danger" (click)="removeUser(i)">
-                <ion-icon slot="icon-only"  name="trash-outline"></ion-icon>
+                <ion-icon slot="icon-only" name="trash-outline"></ion-icon>
             </ion-button>
         </ion-item>
     </ion-list>
diff --git a/src/frontend/app/document/visa-workflow/visa-workflow.component.ts b/src/frontend/app/document/visa-workflow/visa-workflow.component.ts
index 5696fd6859e556f770092b315f2e81d902469741..255c8ea6f9a91a5bce19634ca53e9a9fa7903142 100644
--- a/src/frontend/app/document/visa-workflow/visa-workflow.component.ts
+++ b/src/frontend/app/document/visa-workflow/visa-workflow.component.ts
@@ -5,6 +5,8 @@ import { AuthService } from '../../service/auth.service';
 import { catchError, tap } from 'rxjs/operators';
 import { of } from 'rxjs';
 import { NotificationService } from '../../service/notification.service';
+import { PopoverController } from '@ionic/angular';
+import { VisaWorkflowModelsComponent } from './models/visa-workflow-models.component';
 
 @Component({
     selector: 'app-visa-workflow',
@@ -27,6 +29,7 @@ export class VisaWorkflowComponent implements OnInit {
         public signaturesService: SignaturesContentService,
         public authService: AuthService,
         public notificationService: NotificationService,
+        public popoverController: PopoverController
     ) { }
 
     ngOnInit(): void {
@@ -65,7 +68,7 @@ export class VisaWorkflowComponent implements OnInit {
             'mode': 'visa',
             'processDate': null,
             'current': false,
-            'modes' : [
+            'modes': [
                 'visa',
                 'sign',
                 'rgs'
@@ -82,18 +85,44 @@ export class VisaWorkflowComponent implements OnInit {
     }
 
     getAvatarUser(index: number) {
-        this.http.get('../rest/users/' + this.visaWorkflow[index].userId + '/picture').pipe(
-            tap((data: any) => {
-                this.visaWorkflow[index].userPicture = data.picture;
-            }),
-            catchError(err => {
-                this.notificationService.handleErrors(err);
-                return of(false);
-            })
-        ).subscribe();
+        if (this.visaWorkflow[index].userPicture === undefined  && this.visaWorkflow[index].userDisplay !== '') {
+            this.http.get('../rest/users/' + this.visaWorkflow[index].userId + '/picture').pipe(
+                tap((data: any) => {
+                    this.visaWorkflow[index].userPicture = data.picture;
+                }),
+                catchError(err => {
+                    this.notificationService.handleErrors(err);
+                    return of(false);
+                })
+            ).subscribe();
+        }
     }
 
     resetVisaUsersList() {
         this.visaUsersList = [];
     }
+
+    async openVisaWorkflowModels(ev: any) {
+        const popover = await this.popoverController.create({
+            component: VisaWorkflowModelsComponent,
+            componentProps: { currentWorkflow: this.visaWorkflow },
+            event: ev,
+        });
+        await popover.present();
+
+        popover.onDidDismiss()
+            .then((result: any) => {
+                if (result.role !== 'backdrop') {
+                    console.log(result.data);
+                    this.visaWorkflow = this.visaWorkflow.concat(result.data);
+                    this.visaWorkflow.forEach((element: any, index: number) => {
+                        this.getAvatarUser(index);
+                    });
+                }
+        });
+    }
+
+    getCurrentWorkflow() {
+        return this.visaWorkflow;
+    }
 }
diff --git a/src/frontend/app/home/home.component.ts b/src/frontend/app/home/home.component.ts
index 13ae61b449b44cd9873ba788d74cd298b76ceec4..1e366d8aa55641e80fe4116abe4cf9b9b3eb352a 100644
--- a/src/frontend/app/home/home.component.ts
+++ b/src/frontend/app/home/home.component.ts
@@ -19,6 +19,7 @@ export class HomeComponent implements OnInit {
 
     ngOnInit(): void {
         this.menu.enable(true, 'left-menu');
+        this.menu.enable(false, 'right-menu');
         this.menu.open('left-menu');
     }
 
diff --git a/src/frontend/app/plugins/upload-file-dnd.directive.ts b/src/frontend/app/plugins/upload-file-dnd.directive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..737a5590bd82ba5f4a0fcaa565d5bce012a611d2
--- /dev/null
+++ b/src/frontend/app/plugins/upload-file-dnd.directive.ts
@@ -0,0 +1,51 @@
+import { Directive, Output, EventEmitter, HostBinding, HostListener, Input } from '@angular/core';
+
+@Directive({
+    selector: '[appUploadFileDragDrop]'
+})
+export class DragDropDirective {
+
+    @Output() onFileDropped = new EventEmitter<any>();
+    @Input() disabled: boolean = false;
+
+    @HostBinding('style.background-color') private background = 'none';
+    @HostBinding('style.opacity') private opacity = '1';
+
+    // Dragover listener
+    @HostListener('dragover', ['$event']) onDragOver(evt: any) {
+        if (!this.disabled) {
+            evt.preventDefault();
+            evt.stopPropagation();
+            this.background = '#9ecbec';
+            this.opacity = '0.8';
+        }
+
+    }
+
+    // Dragleave listener
+    @HostListener('dragleave', ['$event']) public onDragLeave(evt: any) {
+        if (!this.disabled) {
+            evt.preventDefault();
+            evt.stopPropagation();
+            this.background = 'rgba(255,255,255,0)';
+            this.opacity = '1';
+        }
+
+    }
+
+    // Drop listener
+    @HostListener('drop', ['$event']) public ondrop(evt: any) {
+        if (!this.disabled) {
+            evt.preventDefault();
+            evt.stopPropagation();
+            this.background = 'rgba(255,255,255,0)';
+            this.opacity = '1';
+            const files = evt.dataTransfer.files;
+            if (files.length > 0) {
+                this.onFileDropped.emit(files);
+            }
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/src/frontend/app/sidebar/sidebar.component.html b/src/frontend/app/sidebar/sidebar.component.html
index a89ea54d2f2bfe1cbc82fd12b492fdd0ea84062f..d921121ec816e4741a7c01377928c881a75b686b 100755
--- a/src/frontend/app/sidebar/sidebar.component.html
+++ b/src/frontend/app/sidebar/sidebar.component.html
@@ -21,7 +21,7 @@
             </ion-button>
         </ion-buttons>
         <ion-buttons slot="end">
-            <ion-button (click)="openIndexation()" [title]="'Importer un document'">
+            <ion-button (click)="openIndexation()" [title]="'lang.newDocumentToVisa' | translate">
                 <ion-icon slot="icon-only" name="cloud-upload-outline"></ion-icon>
             </ion-button>
         </ion-buttons>