diff --git a/config/config-dev.json b/config/config-dev.json
index f52d6a685b9971d965c8d38de381ecd66c850919..806ab41cf63ec7f0e102bd4b1f71576d8dde4598 100644
--- a/config/config-dev.json
+++ b/config/config-dev.json
@@ -19,5 +19,8 @@
   },
   "credits": {
     "url": "https://kong-dev.alpha.grandlyon.com/credits/credits/"
+  },
+  "reuses": {
+    "url": "https://kong-dev.alpha.grandlyon.com/reuses/"
   }
 }
\ No newline at end of file
diff --git a/config/config-rec.json b/config/config-rec.json
index 099b28ecb05ef11881fc4754a20aa4713bf146be..1fd8cad9fe2f03503a70f12ef8f77ecb58035eaf 100644
--- a/config/config-rec.json
+++ b/config/config-rec.json
@@ -19,5 +19,8 @@
   },
   "credits": {
     "url": "https://kong-rec.alpha.grandlyon.com/credits/credits/"
+  },
+  "reuses": {
+    "url": "https://kong-rec.alpha.grandlyon.com/reuses/"
   }
 }
\ No newline at end of file
diff --git a/src/app/app.routing.module.ts b/src/app/app.routing.module.ts
index bebdc08e030368f0fe038587cf70ba4011daa88c..5f8dd9cba72a90a4d9b33b73b7b0fdbca1698d17 100644
--- a/src/app/app.routing.module.ts
+++ b/src/app/app.routing.module.ts
@@ -6,7 +6,7 @@ import { OrganizationFormComponent } from './components/organizations/edit/organ
 import { ResourcesComponent } from './components/resources/list/resources.component';
 import { ResourceFormComponent } from './components/resources/edit/resource-form.component';
 import { ResourceDetailComponent } from './components/resources/detail/resource-detail.component';
-import { FormatsComponent, FormatDetailComponent, FormatFormComponent, ChangelogDetailComponent, ChangelogFormComponent, CreditsComponent, CreditFormComponent, CreditDetailComponent } from './components';
+import { FormatsComponent, FormatDetailComponent, FormatFormComponent, ChangelogDetailComponent, ChangelogFormComponent, CreditsComponent, CreditFormComponent, CreditDetailComponent, ReusesComponent, ReuseFormComponent, ReuseDetailComponent } from './components';
 import { AuthenticatedGuard } from './user/guards/authenticated.guard';
 import { ChangelogComponent } from './components/changelog/list/changelog.component';
 
@@ -176,6 +176,38 @@ const appRoutes: Routes = [
       title: 'Detail du crédit',
     },
   },
+  {
+    path: 'reutilisations',
+    component: ReusesComponent,
+    canActivate: [AuthenticatedGuard],
+    data: {
+      title: 'Réutilisations',
+    },
+  },
+  {
+    path: 'reutilisations/new',
+    component: ReuseFormComponent,
+    canActivate: [AuthenticatedGuard],
+    data: {
+      title: 'Nouvelle réutilisation',
+    },
+  },
+  {
+    path: 'reutilisations/:id/edit',
+    component: ReuseFormComponent,
+    canActivate: [AuthenticatedGuard],
+    data: {
+      title: 'Modifier la réutilisation',
+    },
+  },
+  {
+    path: 'reutilisations/:id',
+    component: ReuseDetailComponent,
+    canActivate: [AuthenticatedGuard],
+    data: {
+      title: 'Detail de la réutilisation',
+    },
+  },
 ];
 
 @NgModule({
diff --git a/src/app/components/changelog/list/changelog.component.ts b/src/app/components/changelog/list/changelog.component.ts
index ecd52fe85426612de5165cc5dc786d17f00a16cf..169fce8b9b7266bc9e950793d30384030e981082 100644
--- a/src/app/components/changelog/list/changelog.component.ts
+++ b/src/app/components/changelog/list/changelog.component.ts
@@ -65,16 +65,27 @@ export class ChangelogComponent implements OnInit, OnDestroy {
 
   private search() {
     this._changelogService.getChangelogs()
-      .subscribe((items: ChangelogRO) => {
-        this.changelogs = items.changelogs;
-        this.totalElement = items.totalCount;
-
-        this.pageHeaderInfo.title = `${this.totalElement} changelogs trouvés`;
-
-        this.paginator.limit = this._changelogService.limit;
-        this.paginator.pageIndex = this._changelogService.pageNumber;
-        this.paginator.length = items.totalCount;
-      });
+      .subscribe(
+        (items: ChangelogRO) => {
+          this.changelogs = items.changelogs;
+          this.totalElement = items.totalCount;
+
+          this.pageHeaderInfo.title = this.totalElement > 1 ?
+            `${this.totalElement} changelogs trouvés` :
+            `${this.totalElement} changelog trouvé`;
+
+          this.paginator.limit = this._changelogService.limit;
+          this.paginator.pageIndex = this._changelogService.pageNumber;
+          this.paginator.length = items.totalCount;
+        },
+        () => {
+          this.pageHeaderInfo.title = '0 changelog trouvé';
+          this._notificationService.notify({
+            type: 'error',
+            message: 'Une erreur est survenue lors du chargement des changelogs.',
+          });
+        },
+      );
   }
 
   // When pagination is changed by user, we update datasetList with new pagination options
diff --git a/src/app/components/credits/list/credits.component.ts b/src/app/components/credits/list/credits.component.ts
index 0b23700d29a31c67ad889bffd30e48ee1e911137..d417e76fe35c8d1eba3c39f18c7f628a89c58bb9 100644
--- a/src/app/components/credits/list/credits.component.ts
+++ b/src/app/components/credits/list/credits.component.ts
@@ -21,7 +21,7 @@ export class CreditsComponent implements OnInit, OnDestroy {
     cancel: 'Annuler',
     continue: 'Supprimer',
   };
-  credits: Credit[];
+  credits: Credit[] = [];
   searchChangeSub: Subscription;
 
   // Paginator options
@@ -65,17 +65,26 @@ export class CreditsComponent implements OnInit, OnDestroy {
 
   private search() {
     this._creditService.getCredits()
-      .subscribe((items: CreditRO) => {
-        this.credits = items.credits;
-        this.totalElement = items.totalCount;
-
-        this.pageHeaderInfo.title = items.totalCount ?
-          `${this.totalElement} crédits trouvés` : '0 crédit trouvé';
-
-        this.paginator.limit = this._creditService.limit;
-        this.paginator.pageIndex = this._creditService.pageNumber;
-        this.paginator.length = items.totalCount;
-      });
+      .subscribe(
+        (items: CreditRO) => {
+          this.credits = items.credits;
+          this.totalElement = items.totalCount;
+
+          this.pageHeaderInfo.title = this.totalElement > 1 ?
+            `${this.totalElement} crédits trouvés` : `${this.totalElement} crédit trouvé`;
+
+          this.paginator.limit = this._creditService.limit;
+          this.paginator.pageIndex = this._creditService.pageNumber;
+          this.paginator.length = items.totalCount;
+        },
+        () => {
+          this.pageHeaderInfo.title = '0 crédit trouvé';
+          this._notificationService.notify({
+            type: 'error',
+            message: 'Une erreur est survenue lors du chargement des crédits.',
+          });
+        },
+      );
   }
 
   // When pagination is changed by user, we update datasetList with new pagination options
diff --git a/src/app/components/formats/list/formats.component.html b/src/app/components/formats/list/formats.component.html
index 4bcbc8fc3cb0783d9b85aff51b31d1bf36c0c649..987f71d2484d077424d82ae18e4de0f52e8596c8 100644
--- a/src/app/components/formats/list/formats.component.html
+++ b/src/app/components/formats/list/formats.component.html
@@ -1,11 +1,11 @@
-<section class="section page-container" *ngIf="formats">
+<section class="section page-container">
   <app-page-header [pageInfo]="pageHeaderInfo" [hideBackButton]="true"></app-page-header>
   <div class="add-item-link has-text-right">
     <a class="button button-gl" [routerLink]="['new']">
       Ajouter
     </a>
   </div>
-  <div class="table entity-list-table">
+  <div class="table entity-list-table" *ngIf="formats">
     <div class="header columns is-marginless">
       <div class="column is-2">
         <span (click)="sortBy('name')" class="is-sortable">
diff --git a/src/app/components/formats/list/formats.component.ts b/src/app/components/formats/list/formats.component.ts
index 883b02a0613b8a1f53e8fcfcd7d723d04187c82d..93c3b7ad6b10e15a7e6fc0ce399497aab3ff7bd4 100644
--- a/src/app/components/formats/list/formats.component.ts
+++ b/src/app/components/formats/list/formats.component.ts
@@ -22,7 +22,7 @@ export class FormatsComponent implements OnInit, OnDestroy {
     cancel: 'Annuler',
     continue: 'Supprimer',
   };
-  formats: Format[];
+  formats: Format[] = [];
   searchChangeSub: Subscription;
 
   // Paginator options
@@ -66,16 +66,28 @@ export class FormatsComponent implements OnInit, OnDestroy {
 
   private search() {
     this._formatService.getFormats()
-      .subscribe((items: FormatRO) => {
-        this.formats = items.formats;
-        this.totalElement = items.totalCount;
-
-        this.pageHeaderInfo.title = `${this.totalElement} formats trouvés`;
-
-        this.paginator.limit = this._formatService.limit;
-        this.paginator.pageIndex = this._formatService.pageNumber;
-        this.paginator.length = items.totalCount;
-      });
+      .subscribe(
+        (items: FormatRO) => {
+          this.formats = items.formats;
+          this.totalElement = items.totalCount;
+
+          this.pageHeaderInfo.title = `${this.totalElement} formats trouvés`;
+          this.pageHeaderInfo.title = this.totalElement > 1 ?
+            `${this.totalElement} formats trouvés` :
+            `${this.totalElement} format trouvé`;
+
+          this.paginator.limit = this._formatService.limit;
+          this.paginator.pageIndex = this._formatService.pageNumber;
+          this.paginator.length = items.totalCount;
+        },
+        () => {
+          this.pageHeaderInfo.title = '0 format trouvé';
+          this._notificationService.notify({
+            type: 'error',
+            message: 'Une erreur est survenue lors du chargement des formats.',
+          });
+        },
+      );
   }
 
   // When pagination is changed by user, we update datasetList with new pagination options
diff --git a/src/app/components/index.ts b/src/app/components/index.ts
index 5783b1752ff7922c885d41496d135a65469faed4..554e32fe57819dfc71d90451b212a82077d06eab 100644
--- a/src/app/components/index.ts
+++ b/src/app/components/index.ts
@@ -21,6 +21,9 @@ import { ConfirmationModalComponent } from './confirmation-modal/confirmation-mo
 import { CreditDetailComponent } from './credits/detail/credit-detail.component';
 import { CreditFormComponent } from './credits/edit/credit-form.component';
 import { CreditsComponent } from './credits/list/credits.component';
+import { ReusesComponent } from './reuses/list/reuses.component';
+import { ReuseFormComponent } from './reuses/edit/reuse-form.component';
+import { ReuseDetailComponent } from './reuses/detail/reuse-detail.component';
 
 export {
   MenuComponent,
@@ -46,6 +49,9 @@ export {
   CreditDetailComponent,
   CreditFormComponent,
   CreditsComponent,
+  ReuseDetailComponent,
+  ReuseFormComponent,
+  ReusesComponent,
 };
 
 // tslint:disable-next-line:variable-name
@@ -73,4 +79,7 @@ export const AppComponents = [
   CreditDetailComponent,
   CreditFormComponent,
   CreditsComponent,
+  ReuseDetailComponent,
+  ReuseFormComponent,
+  ReusesComponent,
 ];
diff --git a/src/app/components/menu/menu.component.html b/src/app/components/menu/menu.component.html
index 1d0dc5d7e8948b536492d29c6afe1f77d9b33368..8ad8d8d15232a51649b9f2f707f550eab691888a 100644
--- a/src/app/components/menu/menu.component.html
+++ b/src/app/components/menu/menu.component.html
@@ -41,5 +41,12 @@
         <span class="label-menu">Changelog</span>
       </a>
     </li>
+    <li><a [routerLink]="['/', 'reutilisations']" routerLinkActive="active-link">
+        <span class="icon">
+          <i class="fas fa-recycle"></i>
+        </span>
+        <span class="label-menu">Réutilisations</span>
+      </a>
+    </li>
   </ul>
 </aside>
\ No newline at end of file
diff --git a/src/app/components/organizations/edit/organization-form.component.ts b/src/app/components/organizations/edit/organization-form.component.ts
index 7ffac9b3fd4bbd9cd32968b7ad643a63a5039008..10ad776b3840676437420bc006e92c577099c9ba 100644
--- a/src/app/components/organizations/edit/organization-form.component.ts
+++ b/src/app/components/organizations/edit/organization-form.component.ts
@@ -24,7 +24,6 @@ export class OrganizationFormComponent implements OnInit {
     existingImageUrl: null,
     isRequired: true,
   };
-  logo: File;
   title: string;
 
   constructor(
diff --git a/src/app/components/organizations/list/organizations.component.ts b/src/app/components/organizations/list/organizations.component.ts
index 148054266254b56134c91e6b3584383a6c0aa49a..bfaffdf3c409d6df6992a40591b906f0571b465e 100644
--- a/src/app/components/organizations/list/organizations.component.ts
+++ b/src/app/components/organizations/list/organizations.component.ts
@@ -22,7 +22,7 @@ export class OrganizationsComponent implements OnInit, OnDestroy {
     cancel: 'Annuler',
     continue: 'Supprimer',
   };
-  organizations: Organization[];
+  organizations: Organization[] = [];
   searchChangeSub: Subscription;
 
   // Paginator options
@@ -66,17 +66,26 @@ export class OrganizationsComponent implements OnInit, OnDestroy {
 
   private search() {
     this._organizationService.getOrganizations()
-      .subscribe((items: OrganizationRO) => {
-        this.organizations = items.organizations;
-        this.totalElement = items.totalCount;
-
-        this.pageHeaderInfo.title = items.totalCount ?
-          `${this.totalElement} producteurs de données trouvés` : '0 producteur de données trouvé';
-
-        this.paginator.limit = this._organizationService.limit;
-        this.paginator.pageIndex = this._organizationService.pageNumber;
-        this.paginator.length = items.totalCount;
-      });
+      .subscribe(
+        (items: OrganizationRO) => {
+          this.organizations = items.organizations;
+          this.totalElement = items.totalCount;
+
+          this.pageHeaderInfo.title = items.totalCount ?
+            `${this.totalElement} producteurs de données trouvés` : `${this.totalElement} producteur de données trouvé`;
+
+          this.paginator.limit = this._organizationService.limit;
+          this.paginator.pageIndex = this._organizationService.pageNumber;
+          this.paginator.length = items.totalCount;
+        },
+        () => {
+          this.pageHeaderInfo.title = '0 producteur de données trouvé';
+          this._notificationService.notify({
+            type: 'error',
+            message: 'Une erreur est survenue lors du chargement des producteurs de données.',
+          });
+        },
+      );
   }
 
   // When pagination is changed by user, we update datasetList with new pagination options
diff --git a/src/app/components/resources/list/resources.component.ts b/src/app/components/resources/list/resources.component.ts
index 5b4e8680d41de66e401685f2adb4a7a054b8ffb4..f37b37a6e0e1874407b906986921ae87570c2d44 100644
--- a/src/app/components/resources/list/resources.component.ts
+++ b/src/app/components/resources/list/resources.component.ts
@@ -22,7 +22,7 @@ export class ResourcesComponent implements OnInit, OnDestroy {
     cancel: 'Annuler',
     continue: 'Supprimer',
   };
-  resources: Resource[];
+  resources: Resource[] = [];
   searchChangeSub: Subscription;
 
   // Paginator options
@@ -66,16 +66,28 @@ export class ResourcesComponent implements OnInit, OnDestroy {
 
   private search() {
     this._resourceService.getResources()
-      .subscribe((items: ResourceRO) => {
-        this.resources = items.resources;
-        this.totalElement = items.totalCount;
-
-        this.pageHeaderInfo.title = `${this.totalElement} ressources trouvées`;
-
-        this.paginator.limit = this._resourceService.limit;
-        this.paginator.pageIndex = this._resourceService.pageNumber;
-        this.paginator.length = items.totalCount;
-      });
+      .subscribe(
+        (items: ResourceRO) => {
+          this.resources = items.resources;
+          this.totalElement = items.totalCount;
+
+          this.pageHeaderInfo.title = `${this.totalElement} ressources trouvées`;
+          this.pageHeaderInfo.title = this.totalElement > 1 ?
+            `${this.totalElement} ressources trouvées` :
+            `${this.totalElement} ressource trouvée`;
+
+          this.paginator.limit = this._resourceService.limit;
+          this.paginator.pageIndex = this._resourceService.pageNumber;
+          this.paginator.length = items.totalCount;
+        },
+        () => {
+          this.pageHeaderInfo.title = '0 ressource trouvée';
+          this._notificationService.notify({
+            type: 'error',
+            message: 'Une erreur est survenue lors du chargement des ressources.',
+          });
+        },
+      );
   }
 
   // When pagination is changed by user, we update datasetList with new pagination options
diff --git a/src/app/components/reuses/detail/reuse-detail.component.html b/src/app/components/reuses/detail/reuse-detail.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..169e248e423742cfdb487f301fb9aab003bde4dc
--- /dev/null
+++ b/src/app/components/reuses/detail/reuse-detail.component.html
@@ -0,0 +1,66 @@
+<section class="section page-container" *ngIf="reuse">
+  <app-page-header [pageInfo]="{title: title}"></app-page-header>
+
+  <div class="columns is-centered">
+    <div class="column is-8">
+      <div class="card">
+        <header class="card-header">
+          <p class="card-header-title has-text-centered">
+            {{reuse.name}}
+          </p>
+        </header>
+        <div class="card-image">
+          <figure class="image">
+            <img [src]="reuse.logo" alt="Logo de la réutilisation">
+          </figure>
+        </div>
+        <div class="card-content">
+          <div class="content">
+            <p>
+              <span class="has-text-weight-bold">Id: </span>
+              <span>{{reuse._id}}</span>
+            </p>
+            <p>
+              <span class="has-text-weight-bold">Créateur: </span>
+              <span>{{reuse.creator}}</span>
+            </p>
+            <p>
+              <span class="has-text-weight-bold">Date de création: </span>
+              <span>{{reuse.createDate}}</span>
+            </p>
+            <p>
+              <span class="has-text-weight-bold">Date de dernière mise à jour: </span>
+              <span>{{reuse.updateDate}}</span>
+            </p>
+            <div>
+              <p><span class="has-text-weight-bold">Statut:</span> {{ reuse.published ? 'Publié' : 'Brouillon' }}
+              </p>
+            </div>
+            <p>
+              <span class="has-text-weight-bold">Site web: </span>
+              <span><a [href]="reuse.website">{{reuse.website}}</a></span>
+            </p>
+
+            <div class="list-container" *ngIf="reuse.reuseTypes && reuse.reuseTypes.length > 0">
+              <span class="has-text-weight-bold">Type(s) de réutilisation: </span>
+              <ul>
+                <li *ngFor="let reuseType of reuse.reuseTypes">
+                  {{ reuseType }}
+                </li>
+              </ul>
+            </div>
+
+            <div class="list-container" *ngIf="reuse.datasetsUsed && reuse.datasetsUsed.length > 0">
+              <span class="has-text-weight-bold">Jeu(x) de données réutilisé(s): </span>
+              <ul>
+                <li *ngFor="let dataset of reuse.datasetsUsed">
+                  {{ dataset }}
+                </li>
+              </ul>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</section>
\ No newline at end of file
diff --git a/src/app/components/reuses/detail/reuse-detail.component.scss b/src/app/components/reuses/detail/reuse-detail.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..369170463fc9b68f9075aca173452f0c23f1765d
--- /dev/null
+++ b/src/app/components/reuses/detail/reuse-detail.component.scss
@@ -0,0 +1,21 @@
+.card-header-title {
+  justify-content: center;
+}
+
+figure {
+  text-align: center;
+}
+
+figure img {
+  max-width: 150px;
+  display: inline-block;
+  margin-top: 20px;
+}
+
+.list-container:not(:last-of-type) {
+  margin-bottom: 1rem;
+
+  ul {
+    margin-top: 0.5rem;
+  }
+}
diff --git a/src/app/components/reuses/detail/reuse-detail.component.ts b/src/app/components/reuses/detail/reuse-detail.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ffada589a724d80bbaef86d9556a373f4b0f9dd9
--- /dev/null
+++ b/src/app/components/reuses/detail/reuse-detail.component.ts
@@ -0,0 +1,30 @@
+
+import { switchMap } from 'rxjs/operators';
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute, ParamMap } from '@angular/router';
+import { Reuse } from '../../../models/reuse.model';
+import { ReuseService } from '../../../services';
+
+@Component({
+  selector: 'app-reuse-detail',
+  templateUrl: './reuse-detail.component.html',
+  styleUrls: ['./reuse-detail.component.scss'],
+})
+export class ReuseDetailComponent implements OnInit {
+
+  reuse: Reuse;
+  title: string;
+
+  constructor(
+    private _route: ActivatedRoute,
+    private _reuseService: ReuseService,
+  ) {
+  }
+
+  ngOnInit(): void {
+    this.title = this._route.snapshot.data.title;
+    this._route.paramMap.pipe(
+      switchMap((params: ParamMap) => this._reuseService.findById(params.get('id'))))
+      .subscribe((reuse: Reuse) => this.reuse = reuse);
+  }
+}
diff --git a/src/app/components/reuses/edit/reuse-form.component.html b/src/app/components/reuses/edit/reuse-form.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..b3a448ebc261ec2c7fb5193164bc06679f8c6648
--- /dev/null
+++ b/src/app/components/reuses/edit/reuse-form.component.html
@@ -0,0 +1,125 @@
+<section class="section page-container" *ngIf="reuse">
+  <form [formGroup]="form" (ngSubmit)="onSubmit()" class="columns is-centered is-marginless is-multiline">
+    <div class="column is-12 header-with-publication-status">
+      <app-page-header [pageInfo]="{title: title}"></app-page-header>
+      <div class="field status-field">
+        <span class="fake-label" *ngIf="form.get('published').value === true">Publié</span>
+        <span class="fake-label" *ngIf="form.get('published').value === false">Brouillon</span>
+        <input id="published" type="checkbox" formControlName="published" class="switch is-rounded">
+        <label for="published"></label>
+      </div>
+    </div>
+    <div class="column is-7">
+      <input type="hidden" formControlName="_id">
+
+      <div class="field">
+        <label class="label required" for="name">Nom</label>
+        <div class="control">
+          <input class="input" type="text" formControlName="name" id="name" required>
+        </div>
+        <div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger">
+          <p *ngIf="name.errors['required']" class="help is-danger">
+            Le nom de la réutilisation est obligatoire.
+          </p>
+        </div>
+      </div>
+
+      <app-image-upload [fieldParams]="logoFieldParams" (fileChanged)="logoChanged($event)"
+        (imageRemoved)="removeLogo()">
+      </app-image-upload>
+
+      <div class="field">
+        <label class="label required" for="name">Créateur</label>
+        <div class="control">
+          <input class="input" type="text" formControlName="creator" id="creator" required>
+        </div>
+        <div *ngIf="creator.invalid && (creator.dirty || creator.touched)" class="alert alert-danger">
+          <p *ngIf="creator.errors['required']" class="help is-danger">
+            Le créateur est obligatoire.
+          </p>
+        </div>
+      </div>
+
+      <div class="field">
+        <label class="label required" for="name">Site web</label>
+        <div class="control">
+          <input class="input" type="text" formControlName="website" id="website" required>
+        </div>
+        <div *ngIf="website.invalid && (website.dirty || website.touched)" class="alert alert-danger">
+          <p *ngIf="website.errors['required']" class="help is-danger">
+            Le site web est obligatoire.
+          </p>
+        </div>
+      </div>
+
+      <div class="field">
+        <div class="form-array-header">
+          <label class="label">Type de réutilisation</label>
+          <span class="icon" tabindex=0 (click)="addReuseType()" (keyup.enter)="addReuseType()"
+            title="Ajouter un type de réutilisation">
+            <i class="fas fa-plus"></i>
+          </span>
+        </div>
+
+        <div formArrayName="reuseTypes">
+          <div *ngFor="let reuseType of reuseTypes.controls; let i = index;" class="form-array-item">
+            <div class="form-array-input-wrapper">
+              <div class="field">
+                <div class="control">
+                  <div class="select">
+                    <select type="text" [formControlName]="i" required>
+                      <option hidden value="" disabled selected>Selectionnez un type</option>
+                      <option *ngFor="let opt of reuseTypesList" [value]="opt.value">{{opt.label}}</option>
+                    </select>
+                  </div>
+                </div>
+              </div>
+              <div *ngIf="reuseType.invalid && (reuseType.dirty || reuseType.touched)" class="alert alert-danger">
+                <p *ngIf="reuseType.hasError('required')" class="help is-danger">
+                  Vous devez saisir le type de réutilisation.
+                </p>
+              </div>
+            </div>
+            <span class="icon" tabindex=0 (click)="removeReuseType(i)" (keyup.enter)="removeReuseType(i)"
+              title="Supprimer le type de réutilisation">
+              <i class="fas fa-trash"></i>
+            </span>
+          </div>
+        </div>
+      </div>
+
+      <div class="field">
+        <div class="form-array-header">
+          <label class="label">Jeu(x) de données réutilisé(s)</label>
+          <span class="icon" tabindex=0 (click)="addDatasetUsed()" (keyup.enter)="addDatasetUsed()"
+            title="Ajouter un jeu de données réutilisé">
+            <i class="fas fa-plus"></i>
+          </span>
+        </div>
+
+        <div formArrayName="datasetsUsed">
+          <div *ngFor="let datasetUsed of datasetsUsed.controls; let i = index;" class="form-array-item">
+            <div class="form-array-input-wrapper">
+              <div class="control">
+                <input class="input" type="text" [formControlName]="i" required>
+              </div>
+              <div *ngIf="datasetUsed.invalid && (datasetUsed.dirty || datasetUsed.touched)" class="alert alert-danger">
+                <p *ngIf="datasetUsed.hasError('required')" class="help is-danger">
+                  Vous devez saisir le slug du jeu de données réutilisé.
+                </p>
+              </div>
+            </div>
+            <span class="icon" tabindex=0 (click)="removeDatasetUsed(i)" (keyup.enter)="removeDatasetUsed(i)"
+              title="Supprimer le jeu de données réutilisé">
+              <i class="fas fa-trash"></i>
+            </span>
+          </div>
+        </div>
+      </div>
+
+      <div class="has-text-right">
+        <button class="button button-gl" type="submit" [disabled]="formInvalid == true">Valider</button>
+      </div>
+    </div>
+  </form>
+</section>
\ No newline at end of file
diff --git a/src/app/components/reuses/edit/reuse-form.component.scss b/src/app/components/reuses/edit/reuse-form.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..4bc5c21221ab9f7ba636ca989a4038e8b3db6af0
--- /dev/null
+++ b/src/app/components/reuses/edit/reuse-form.component.scss
@@ -0,0 +1,43 @@
+.full-width {
+  width: 100%;
+}
+
+h1 {
+  text-align: center
+}
+
+.icon {
+  cursor: pointer;
+
+  &:hover {
+    .fa-plus {
+      color: lightblue;
+    }
+
+    .fa-trash {
+      color: #d5232a;
+    }
+  }
+}
+
+.form-array-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 0.5em;
+
+  label {
+    margin-bottom: 0;
+  }
+}
+
+.form-array-item {
+  display: flex;
+  align-items: center;
+  margin-bottom: 0.5em;
+}
+
+.form-array-input-wrapper {
+  flex-grow: 1;
+  margin-right: 0.5rem;
+}
diff --git a/src/app/components/reuses/edit/reuse-form.component.ts b/src/app/components/reuses/edit/reuse-form.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e98eb61d09ba1b84ff87d8ddcc72fe1cc3dbf9d2
--- /dev/null
+++ b/src/app/components/reuses/edit/reuse-form.component.ts
@@ -0,0 +1,244 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute, ParamMap, Router } from '@angular/router';
+import { FormBuilder, FormGroup, Validators, FormArray, FormControl, MaxLengthValidator } from '@angular/forms';
+import { filter, switchMap, catchError, mergeMap } from 'rxjs/operators';
+import { NotificationService, ReuseService, MediaService } from 'src/app/services';
+import { Reuse } from '../../../models/reuse.model';
+import { IImageUploadFieldParams } from '../../../models/image-upload.model';
+import { throwError } from 'rxjs';
+
+@Component({
+  selector: 'app-reuse-form',
+  templateUrl: './reuse-form.component.html',
+  styleUrls: ['./reuse-form.component.scss'],
+})
+export class ReuseFormComponent implements OnInit {
+
+  reuse: Reuse = new Reuse();
+  form: FormGroup;
+  logoFile: File;
+  logoFieldParams: IImageUploadFieldParams = {
+    inputName: 'logo',
+    label: 'Logo',
+    existingImageUrl: null,
+    isRequired: true,
+  };
+  title: string;
+
+  constructor(
+    private _reuseService: ReuseService,
+    private _mediaService: MediaService,
+    private _route: ActivatedRoute,
+    private _router: Router,
+    private _fb: FormBuilder,
+    private _notificationService: NotificationService,
+  ) {
+  }
+
+  ngOnInit() {
+    this.title = this._route.snapshot.data.title;
+    this.initForm();
+
+    this._route.paramMap.pipe(
+      filter((paramMap: ParamMap) => (paramMap.get('id') !== null)),
+      switchMap((paramMap: ParamMap) => this._reuseService.findById(paramMap.get('id'))))
+      .subscribe((reuse: Reuse) => {
+
+        this.reuse = reuse;
+
+        this.logoFieldParams.existingImageUrl = reuse.logo;
+
+        this.initForm();
+
+      });
+  }
+
+  initForm() {
+    this.form = this._fb.group({
+      _id: [this.reuse._id],
+      name: [this.reuse.name, Validators.required],
+      creator: [this.reuse.creator, Validators.required],
+      logo: [this.reuse.logo],
+      website: [this.reuse.website, Validators.required],
+      published: [this.reuse.published, Validators.required],
+      reuseTypes: new FormArray(this.reuse.reuseTypes.map(major => new FormControl(major)), Validators.maxLength(3)),
+      datasetsUsed: new FormArray(this.reuse.datasetsUsed.map(minor => new FormControl(minor))),
+    });
+  }
+
+  onSubmit() {
+    console.log(this.form.value)
+    if (!this.formInvalid) {
+      this.reuse = new Reuse(this.form.value);
+
+      if (this.reuse._id) {
+        if (this.logoFile) {
+          this._mediaService.uploadLogo(this.logoFile).pipe(
+            catchError(() => {
+              return throwError('Une erreur est survenue lors de l\'upload du logo de la réutilisation.');
+            }),
+            mergeMap((response: any) => {
+              this.reuse.logo = response.mediaUrl;
+              return this._reuseService.update(this.reuse).pipe(
+                catchError(() => {
+                  return throwError('Une erreur est survenue lors de la mise à jour de la réutilisation.');
+                }),
+              );
+            }),
+          ).subscribe(
+            (reuseUpdated) => {
+              this._notificationService.notify({
+                message: 'La réutilisation a été mise à jour avec succès.',
+                type: 'success',
+              });
+              this._router.navigate(['/reutilisations', reuseUpdated._id]);
+            },
+            (err) => {
+              this._notificationService.notify({
+                message: err,
+                type: 'error',
+              });
+            },
+          );
+        } else {
+          return this._reuseService.update(this.reuse).subscribe(
+            (reuseUpdated) => {
+              this._notificationService.notify({
+                message: 'La réutilisation a été mise à jour avec succès.',
+                type: 'success',
+              });
+              this._router.navigate(['/reutilisations', reuseUpdated._id]);
+            },
+            () => {
+              this._notificationService.notify({
+                message: 'Une erreur est survenue lors de la mise à jour de la réutilisation.',
+                type: 'error',
+              });
+            },
+          );
+        }
+      } else {
+        if (this.logoFile) {
+          this._mediaService.uploadLogo(this.logoFile).pipe(
+            catchError(() => {
+              return throwError('Une erreur est survenue lors de l\'upload du logo de la réutilisation.');
+            }),
+            mergeMap((response: any) => {
+              this.reuse.logo = response.mediaUrl;
+              return this._reuseService.create(this.reuse).pipe(
+                catchError(() => {
+                  return throwError('Une erreur est survenue lors de la création de la réutilisation.');
+                }),
+              );
+            }),
+          ).subscribe(
+            (reutilisationCreated) => {
+              this._notificationService.notify({
+                message: 'La réutilisation a été créée avec succès.',
+                type: 'success',
+              });
+              this._router.navigate(['/reutilisations', reutilisationCreated._id]);
+            },
+            (err) => {
+              this._notificationService.notify({
+                message: err,
+                type: 'error',
+              });
+            },
+          );
+        } else {
+          return this._reuseService.create(this.reuse).subscribe(
+            (reuseCreated) => {
+              this._notificationService.notify({
+                message: 'La réutilisation a été créée avec succès.',
+                type: 'success',
+              });
+              this._router.navigate(['/reutilisations', reuseCreated._id]);
+            },
+            () => {
+              this._notificationService.notify({
+                message: 'Une erreur est survenue lors de la création de la réutilisation.',
+                type: 'error',
+              });
+            },
+          );
+        }
+      }
+    }
+  }
+
+  addReuseType() {
+    if (this.reuseTypes.length < this.reuseTypesList.length) {
+      this.reuseTypes.push(new FormControl(''));
+    }
+  }
+
+  addDatasetUsed() {
+    this.datasetsUsed.push(new FormControl());
+  }
+
+  removeReuseType(index) {
+    this.reuseTypes.removeAt(index);
+  }
+
+  removeDatasetUsed(index) {
+    this.datasetsUsed.removeAt(index);
+  }
+
+  // Getters for each property
+  get name() {
+    return this.form.controls['name'];
+  }
+
+  get creator() {
+    return this.form.controls['creator'];
+  }
+
+  get website() {
+    return this.form.controls['website'];
+  }
+
+  get published() {
+    return this.form.controls['published'];
+  }
+
+  get reuseTypes(): FormArray {
+    return this.form.get('reuseTypes') as FormArray;
+  }
+
+  get datasetsUsed(): FormArray {
+    return this.form.get('datasetsUsed') as FormArray;
+  }
+
+  get formInvalid() {
+    return this.form.invalid;
+  }
+
+  get reuseTypesList() {
+    return [
+      {
+        value: 'app',
+        label: 'Application',
+      },
+      {
+        value: 'web',
+        label: 'Web',
+      },
+      {
+        value: 'article',
+        label: 'Article',
+      },
+    ];
+  }
+
+  logoChanged(fileList: FileList) {
+    if (fileList && fileList.length > 0) {
+      this.logoFile = fileList[0];
+    }
+  }
+
+  removeLogo() {
+    this.form.get('logo').setValue(null);
+  }
+
+}
diff --git a/src/app/components/reuses/list/reuses.component.html b/src/app/components/reuses/list/reuses.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..5f1019fb1b7da7879287bf6a68525b10514e0787
--- /dev/null
+++ b/src/app/components/reuses/list/reuses.component.html
@@ -0,0 +1,112 @@
+<section class="section page-container">
+  <app-page-header [pageInfo]="pageHeaderInfo" [hideBackButton]="true"></app-page-header>
+  <div class="add-item-link has-text-right">
+    <a class="button button-gl" [routerLink]="['new']">
+      Ajouter
+    </a>
+  </div>
+  <div class="table entity-list-table" *ngIf="reuses">
+    <div class="header columns is-marginless">
+      <div class="column is-2">
+        <span (click)="sortBy('name')" class="is-sortable">
+          <span class="sort-icons">
+            <span class="icon">
+              <i class="fas fa-sort-up"
+                [ngClass]="{'icon-red': sortOptions.value === 'name' && sortOptions.order === 'desc'}"></i>
+            </span>
+            <span class="icon">
+              <i class="fas fa-sort-down"
+                [ngClass]="{'icon-red': sortOptions.value === 'name' && sortOptions.order === 'asc'}"></i>
+            </span>
+          </span>
+          <span class="column-title" [ngClass]="{'active': sortOptions.value === 'name'}">Nom</span>
+        </span>
+      </div>
+      <div class="column is-1 has-text-centered">
+        <span (click)="sortBy('published')" class="is-sortable">
+          <span class="sort-icons">
+            <span class="icon">
+              <i class="fas fa-sort-up"
+                [ngClass]="{'icon-red': sortOptions.value === 'published' && sortOptions.order === 'desc'}"></i>
+            </span>
+            <span class="icon">
+              <i class="fas fa-sort-down"
+                [ngClass]="{'icon-red': sortOptions.value === 'published' && sortOptions.order === 'asc'}"></i>
+            </span>
+          </span>
+          <span class="column-title" [ngClass]="{'active': sortOptions.value === published}">Publié</span>
+        </span>
+      </div>
+      <div class="column is-1 has-text-centered">
+        <span class="column-title">Logo</span>
+      </div>
+      <div class="column is-2">
+        <span (click)="sortBy('creator')" class="is-sortable">
+          <span class="sort-icons">
+            <span class="icon">
+              <i class="fas fa-sort-up"
+                [ngClass]="{'icon-red': sortOptions.value === 'creator' && sortOptions.order === 'desc'}"></i>
+            </span>
+            <span class="icon">
+              <i class="fas fa-sort-down"
+                [ngClass]="{'icon-red': sortOptions.value === 'creator' && sortOptions.order === 'asc'}"></i>
+            </span>
+          </span>
+          <span class="column-title" [ngClass]="{'active': sortOptions.value === creator}">Créateur</span>
+        </span>
+      </div>
+      <div class="column is-2">
+        <span class="column-title">Site web</span>
+      </div>
+      <div class="column is-2">
+        <span class="column-title">Type de réutilisation</span>
+      </div>
+      <div class="column is-offset-1 is-1 has-text-centered">
+        <span class="column-title">Actions</span>
+      </div>
+    </div>
+    <div class="data-list">
+      <div class="data columns is-multiline is-vcentered is-marginless"
+        *ngFor="let reuse of reuses; let i=index; let odd=odd; let even=even;" [ngClass]="{ odd: odd, even: even }">
+        <div class="column is-2">
+          <span>{{ reuse.name }}</span>
+        </div>
+        <div class="column is-1 has-text-centered">
+          <span class="icon has-text-success" *ngIf="reuse.published">
+            <i class="far fa-check-circle"></i>
+          </span>
+          <span class="icon has-text-danger" *ngIf="!reuse.published">
+            <i class="far fa-times-circle"></i>
+          </span>
+        </div>
+        <div class="column is-1 has-text-centered">
+          <img class="entity-logo-in-list" [src]="reuse.logo" alt="Logo de la réutilisation">
+        </div>
+        <div class="column is-2">
+          <span>{{ reuse.creator }}</span>
+        </div>
+        <div class="column is-2">
+          <span>{{ reuse.website }}</span>
+        </div>
+        <div class="column is-2">
+          <span>{{ reuse.reuseTypes.join(', ') }}</span>
+        </div>
+        <div class="column is-offset-1 is-1 has-text-centered actions">
+          <app-crud-buttons [id]="reuse._id" (delete)="displayDeletePopup($event)"></app-crud-buttons>
+        </div>
+      </div>
+    </div>
+    <div class="columns is-marginless paginator">
+      <div class="column">
+        <app-paginator *ngIf="paginator.length > 0" [length]="paginator.length" [pageSize]="paginator.limit"
+          [pageSizeOptions]="paginator.pageSizeOptions" [pageIndex]="paginator.pageIndex" [pagesToShow]="5"
+          [showFirstLastButtons]="true" (page)="changePagination($event)">
+        </app-paginator>
+      </div>
+    </div>
+  </div>
+</section>
+
+<app-confirmation-modal (cancel)="objectToBeDeletedId=null" (continue)="deleteChangelog()" [texts]="deleteModalTexts"
+  [isOpened]="objectToBeDeletedId !== null">
+</app-confirmation-modal>
\ No newline at end of file
diff --git a/src/app/components/reuses/list/reuses.component.scss b/src/app/components/reuses/list/reuses.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/components/reuses/list/reuses.component.ts b/src/app/components/reuses/list/reuses.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..13b5572558af69a2970c10b65b1159c462ec8f03
--- /dev/null
+++ b/src/app/components/reuses/list/reuses.component.ts
@@ -0,0 +1,143 @@
+import { Component, OnInit, OnDestroy } from '@angular/core';
+import { PaginatorOptions } from 'src/app/models/paginator-options.model';
+import { IPageHeaderInfo } from '../../../models/page.model';
+import { Subscription } from 'rxjs';
+import { ReuseService, NotificationService } from '../../../services';
+import { Reuse, ReuseRO } from '../../../models/reuse.model';
+
+@Component({
+  selector: 'app-reuses',
+  templateUrl: './reuses.component.html',
+  styleUrls: ['./reuses.component.scss'],
+})
+export class ReusesComponent implements OnInit, OnDestroy {
+
+  pageHeaderInfo: IPageHeaderInfo = {
+    title: '',
+  };
+  objectToBeDeletedId = null;
+  deleteModalTexts = {
+    main: 'Si vous poursuivez, la réutilisation sera définitivement supprimée.',
+    cancel: 'Annuler',
+    continue: 'Supprimer',
+  };
+  reuses: Reuse[] = [];
+  searchChangeSub: Subscription;
+
+  // Paginator options
+  paginator: PaginatorOptions;
+  pageSize = 10;
+  pageSizeOptions = [5, 10, 25, 100];
+
+  sortValue: string;
+
+  totalElement: number;
+  filters = {
+    name: '',
+  };
+  where = {};
+
+  constructor(
+    private _reuseService: ReuseService,
+    private _notificationService: NotificationService,
+  ) {
+    this.paginator = {
+      pageIndex: this._reuseService.pageNumber,
+      length: 0,
+      limit: this._reuseService.limit,
+      pageSizeOptions: [5, 10, 20],
+    };
+  }
+
+  ngOnInit(): void {
+    this._reuseService.sortOptions = {
+      value: 'name',
+      order: 'desc',
+    };
+    this.search();
+
+    this.searchChangeSub = this._reuseService.searchChange$.subscribe(
+      () => {
+        this.search();
+      },
+    );
+  }
+
+  private search() {
+    this._reuseService.getReuses()
+      .subscribe(
+        (items: ReuseRO) => {
+          this.reuses = items.reuses;
+          this.totalElement = items.totalCount;
+
+          this.pageHeaderInfo.title = this.totalElement > 1 ?
+            `${this.totalElement} réutilisations trouvées` :
+            `${this.totalElement} réutilisation trouvée`;
+
+          this.paginator.limit = this._reuseService.limit;
+          this.paginator.pageIndex = this._reuseService.pageNumber;
+          this.paginator.length = items.totalCount;
+        },
+        () => {
+          this.pageHeaderInfo.title = '0 réutilisation trouvée';
+          this._notificationService.notify({
+            type: 'error',
+            message: 'Une erreur est survenue lors du chargement des réutilisations.',
+          });
+        },
+      );
+  }
+
+  changePagination(pageIndex) {
+    this._reuseService.paginationChanged(this.paginator.limit, pageIndex);
+  }
+
+  changePageSize(pageSize) {
+    this._reuseService.paginationChanged(pageSize, 1);
+  }
+
+  sortBy(key: string) {
+    if (this._reuseService.sortOptions.value === key) {
+      this._reuseService.reverseSortOrder();
+    } else {
+      this._reuseService.sortOptions.value = key;
+      this._reuseService.sortOptions.order = 'asc';
+    }
+    this.search();
+  }
+
+  get sortOptions() {
+    return this._reuseService.sortOptions;
+  }
+
+  displayDeletePopup(id) {
+    this.objectToBeDeletedId = id;
+  }
+
+  deleteChangelog() {
+    this._reuseService.delete(this.objectToBeDeletedId).subscribe(
+      () => {
+        this._notificationService.notify({
+          type: 'success',
+          message: 'La réutilisation a été supprimé avec succès.',
+        });
+        this._reuseService.pageNumber = 1;
+        this.search();
+      },
+      () => {
+        this._notificationService.notify({
+          type: 'error',
+          message: 'Une erreur est survenue lors de la suppression de la réutilisation.',
+        });
+      },
+      () => {
+        this.objectToBeDeletedId = null;
+      },
+    );
+
+  }
+
+  ngOnDestroy() {
+    this.searchChangeSub.unsubscribe();
+  }
+}
diff --git a/src/app/models/reuse.model.ts b/src/app/models/reuse.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6b80b2315a1b1bbc04a043c644cab9d673583f91
--- /dev/null
+++ b/src/app/models/reuse.model.ts
@@ -0,0 +1,53 @@
+export class ReuseRO {
+  reuses: Reuse[];
+  totalCount: number;
+
+  constructor(reuses, totalCount) {
+    this.reuses = reuses;
+    this.totalCount = totalCount;
+  }
+}
+
+export class Reuse {
+  _id: string;
+  name: string;
+  creator: string;
+  logo: string;
+  website: string;
+  reuseTypes: string[];
+  datasetsUsed: string[];
+  createDate: Date;
+  updateDate: Date;
+  published: boolean;
+
+  constructor(reuse?: IReuse) {
+    this._id = reuse && reuse._id ? reuse._id : null;
+    this.name = reuse && reuse.name ? reuse.name : null;
+    this.creator = reuse && reuse.creator ? reuse.creator : null;
+    this.logo = reuse && reuse.logo ? reuse.logo : null;
+    this.website = reuse && reuse.website ? reuse.website : null;
+    this.reuseTypes = reuse && reuse.reuseTypes ? reuse.reuseTypes : [];
+    this.datasetsUsed = reuse && reuse.datasetsUsed ? reuse.datasetsUsed : [];
+    if (reuse && reuse.createDate) {
+      this.createDate = reuse.createDate;
+    }
+
+    if (reuse && reuse.updateDate) {
+      this.updateDate = reuse.updateDate;
+    }
+    this.published = reuse && reuse.published ? reuse.published : false;
+  }
+}
+
+export interface IReuse {
+  _id: string;
+  name: string;
+  creator: string;
+  logo: string;
+  website: string;
+  reuseTypes: string[];
+  datasetsUsed: string[];
+  createDate: Date;
+  updateDate: Date;
+  published: boolean;
+}
diff --git a/src/app/services/app-config.service.ts b/src/app/services/app-config.service.ts
index 6d46d729c135f9121176f55f87d60ee3b835aeca..6fd575157106c73012ef4e51cc685656759ab2bc 100644
--- a/src/app/services/app-config.service.ts
+++ b/src/app/services/app-config.service.ts
@@ -22,6 +22,9 @@ export class AppConfig {
   credits: {
     url: string;
   };
+  reuses: {
+    url: string;
+  };
 }
 
 export let APP_CONFIG: AppConfig;
diff --git a/src/app/services/index.ts b/src/app/services/index.ts
index 484bd65dab315967dd84e70fd746163fe4b478c6..196da86731a0fd1ff8684d8b72e732bc05a46f3b 100644
--- a/src/app/services/index.ts
+++ b/src/app/services/index.ts
@@ -7,6 +7,7 @@ import { NavigationHistoryService } from './navigation-history.service';
 import { ChangelogService } from './changelog.service';
 import { CreditService } from './credit.service';
 import { MediaService } from './media.service';
+import { ReuseService } from './reuse.service';
 
 export {
   AppConfigService,
@@ -18,6 +19,7 @@ export {
   ChangelogService,
   CreditService,
   MediaService,
+  ReuseService,
 };
 
 // tslint:disable-next-line:variable-name
@@ -31,4 +33,5 @@ export const AppServices = [
   ChangelogService,
   CreditService,
   MediaService,
+  ReuseService,
 ];
diff --git a/src/app/services/reuse.service.ts b/src/app/services/reuse.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2e63e82a9277daec777de588d2d87e7a9f8153b4
--- /dev/null
+++ b/src/app/services/reuse.service.ts
@@ -0,0 +1,92 @@
+import { Injectable } from '@angular/core';
+import { Observable, Subject } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { HttpClient } from '@angular/common/http';
+import { APP_CONFIG } from './app-config.service';
+import { ReuseRO, IReuse, Reuse } from '../models/reuse.model';
+
+@Injectable()
+export class ReuseService {
+
+  reuseServiceUrl: string;
+  limit: number;
+  pageNumber: number;
+  sortOptions: {
+    value: string,
+    order: string,
+  };
+
+  private _searchChangeSubject: Subject<any>;
+
+  constructor(
+    private _httpClient: HttpClient) {
+    this.reuseServiceUrl = `${APP_CONFIG.reuses.url}reuses/`;
+    this._searchChangeSubject = new Subject<any>();
+    this.limit = 10;
+    this.pageNumber = 1;
+  }
+
+  getReuses(): Observable<ReuseRO> {
+    let query = '?';
+    query += `limit=${(this.limit ? this.limit : 20)}`;
+    query += `&offset=${(this.pageNumber ? (this.pageNumber - 1) * this.limit : 0)}`;
+    query += `&sort_by=${this.sortOptions.value}.${this.sortOptions.order}`;
+
+    return this._httpClient.get<IReuse[]>(this.reuseServiceUrl + query, { observe: 'response' }).pipe(
+      map((response) => {
+        const totalCount = response.headers.get('Content-Range');
+        const reuses = [];
+        response.body.forEach((reuse) => {
+          reuses.push(new Reuse(reuse));
+        });
+        return new ReuseRO(reuses, parseInt(totalCount, 10));
+      }));
+  }
+
+  findById(id): Observable<Reuse> {
+    return this._httpClient.get<IReuse>(this.reuseServiceUrl + id).pipe(
+      map((response) => {
+        return new Reuse(response);
+      }),
+    );
+  }
+
+  delete(id) {
+    return this._httpClient.delete(this.reuseServiceUrl + id, { withCredentials: true });
+  }
+
+  create(data) {
+    return this._httpClient.post<IReuse>(this.reuseServiceUrl, data, { withCredentials: true }).pipe(
+      map((response) => {
+        return new Reuse(response);
+      }),
+    );
+  }
+
+  update(data) {
+    return this._httpClient.put<IReuse>(this.reuseServiceUrl + data._id, data, { withCredentials: true }).pipe(
+      map((response) => {
+        return new Reuse(response);
+      }),
+    );
+  }
+
+  /* PAGINATION */
+  paginationChanged(limit: number, pageNumber: number) {
+    this.limit = limit;
+    this.pageNumber = pageNumber;
+    this._searchChangeSubject.next();
+  }
+
+  reverseSortOrder(): void {
+    if (this.sortOptions.order === 'asc') {
+      this.sortOptions.order = 'desc';
+    } else {
+      this.sortOptions.order = 'asc';
+    }
+  }
+
+  get searchChange$(): Observable<string> {
+    return this._searchChangeSubject.asObservable();
+  }
+}
diff --git a/src/assets/config/config.json b/src/assets/config/config.json
index f52d6a685b9971d965c8d38de381ecd66c850919..58c34dd6438b7815620c6f7c17588c12c3acdd8c 100644
--- a/src/assets/config/config.json
+++ b/src/assets/config/config.json
@@ -19,5 +19,8 @@
   },
   "credits": {
     "url": "https://kong-dev.alpha.grandlyon.com/credits/credits/"
+  },
+  "reuses": {
+    "url": "http://localhost:3008/"
   }
 }
\ No newline at end of file