diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 9f102748e0710c63413fe8a07fbba34afae76ac2..629e4b28590c8729f353903b485d8f39c4832ff6 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -5,12 +5,12 @@ display: grid; grid-template-columns: 50px auto; grid-template-rows: 60px minmax(calc(100vh - 60px), auto); - overflow: hidden; + // overflow: hidden; } .main-header { grid-row: 1; - grid-column: 1 / -1; + grid-column: 1 / span 2; display: flex; flex-flow: row; @@ -45,11 +45,14 @@ .main-nav { grid-row: 2; - grid-column: 1 / span 1; + grid-column: 1; width: 50px; + height: 100vh; z-index: 200; transition: all .2s linear; background-color: #333745; + position: sticky; + top: 0px; &.is-active { width: 200px; @@ -58,7 +61,7 @@ .main-content { grid-row: 2; - grid-column: 2 / -1; + grid-column: 2; margin-left: 150px; background-color: $grey-background-color; transition: all 200ms cubic-bezier(0.7, 0, 0.3, 1); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 262e49f46d8724fc0f00840f94de303a9b8af72a..994fd9e1ac95c651f574ab12b569a2e5710c373c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,6 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { UserService } from './user/services'; -import { Router } from '@angular/router'; +import { Router, NavigationEnd } from '@angular/router'; +import { filter } from 'rxjs/operators'; +import { NavigationHistoryService } from './services'; @Component({ selector: 'app-root', @@ -16,10 +18,18 @@ export class AppComponent implements OnInit { constructor( private _userService: UserService, private _router: Router, + private _navigationHistoryService: NavigationHistoryService, ) { } ngOnInit(): void { this.sidebarOpened = true; + + // Activate navigation history + this._router.events.pipe( + filter(e => e instanceof NavigationEnd), + ).subscribe((e) => { + this._navigationHistoryService.add(e['urlAfterRedirects']); + }); } get loggedInUserFullname() { diff --git a/src/app/app.routing.module.ts b/src/app/app.routing.module.ts index c1a910231bcbbe34245b967fd0a9fe980d362bbd..f58c4ca7d2b473f77f8e8f9d00f94bf8bc158155 100644 --- a/src/app/app.routing.module.ts +++ b/src/app/app.routing.module.ts @@ -20,7 +20,7 @@ const appRoutes: Routes = [ component: OrganizationsComponent, canActivate: [AuthenticatedGuard], data: { - title: 'Producteur-de-donnees', + title: 'Producteur de donnees', }, }, { @@ -44,7 +44,7 @@ const appRoutes: Routes = [ component: OrganizationDetailComponent, canActivate: [AuthenticatedGuard], data: { - title: 'Producteur de données', + title: 'Detail du producteur de données', }, }, { @@ -76,7 +76,7 @@ const appRoutes: Routes = [ component: ResourceDetailComponent, canActivate: [AuthenticatedGuard], data: { - title: 'Ressource', + title: 'Detail de la ressource', }, }, { @@ -108,7 +108,7 @@ const appRoutes: Routes = [ component: FormatDetailComponent, canActivate: [AuthenticatedGuard], data: { - title: 'Format', + title: 'Detail du format', }, }, ]; diff --git a/src/app/components/formats/detail/format-detail.component.html b/src/app/components/formats/detail/format-detail.component.html index 064569e10d7d0053978eb236b6998d0667cefdc2..4e96e4bc012d215778937107ef3595f4fb4932da 100644 --- a/src/app/components/formats/detail/format-detail.component.html +++ b/src/app/components/formats/detail/format-detail.component.html @@ -1,30 +1,27 @@ -<ng-container *ngIf="format"> +<section class="section page-container" *ngIf="format"> + <app-page-header [pageInfo]="{title: title}"></app-page-header> - <app-back-button [route]="'/formats'" [title]="'Retourner à la liste des formats'"></app-back-button> - - <section class="section"> - <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"> - {{format.name}} + <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"> + {{format.name}} + </p> + </header> + <div class="card-content"> + <div class="content"> + <p> + <span class="has-text-weight-bold">Id: </span> + <span>{{format.id}}</span> + </p> + <p> + <span class="has-text-weight-bold">Type MapServer: </span> + <span>{{format.mapServerType}}</span> </p> - </header> - <div class="card-content"> - <div class="content"> - <p> - <span class="has-text-weight-bold">Id: </span> - <span>{{format.id}}</span> - </p> - <p> - <span class="has-text-weight-bold">Type MapServer: </span> - <span>{{format.mapServerType}}</span> - </p> - </div> </div> </div> </div> </div> - </section> -</ng-container> \ No newline at end of file + </div> +</section> \ No newline at end of file diff --git a/src/app/components/formats/detail/format-detail.component.ts b/src/app/components/formats/detail/format-detail.component.ts index 52b8bf8ce53e15d473d61a1639262df97609b87b..2cff26276db89db09a1c436cb6534c7c18706715 100644 --- a/src/app/components/formats/detail/format-detail.component.ts +++ b/src/app/components/formats/detail/format-detail.component.ts @@ -13,6 +13,7 @@ import { Format } from 'src/app/models/format.model'; export class FormatDetailComponent implements OnInit { format: Format; + title: string; constructor( private _route: ActivatedRoute, @@ -21,6 +22,7 @@ export class FormatDetailComponent implements OnInit { } ngOnInit(): void { + this.title = this._route.snapshot.data.title; this._route.paramMap.pipe( switchMap((params: ParamMap) => this._formatService.findById(params.get('id')))) .subscribe((format: Format) => this.format = format); diff --git a/src/app/components/formats/edit/format-form.component.html b/src/app/components/formats/edit/format-form.component.html index dc9588a857641d4e0dcaff8b6343ca0fc2d66df4..b4042a8203e825f720cbfaad75bd7c9c16edfa30 100644 --- a/src/app/components/formats/edit/format-form.component.html +++ b/src/app/components/formats/edit/format-form.component.html @@ -1,8 +1,5 @@ -<ng-container *ngIf="format"> - - <app-back-button [route]="'/formats'" [title]="'Retourner à la liste des formats'"></app-back-button> - - <h1>{{ title }}</h1> +<section class="section page-container" *ngIf="format"> + <app-page-header [pageInfo]="{title: title}"></app-page-header> <form [formGroup]="form" (ngSubmit)="onSubmit()" class="columns is-centered is-marginless"> <div class="column is-7"> @@ -38,4 +35,4 @@ </div> </div> </form> -</ng-container> \ No newline at end of file +</section> \ No newline at end of file diff --git a/src/app/components/formats/list/formats.component.html b/src/app/components/formats/list/formats.component.html index 2f14f472a42f5adf51ba09e656df3cb07a85a534..21681fd61701b3a8b2360be75b1c6a71631eaed4 100644 --- a/src/app/components/formats/list/formats.component.html +++ b/src/app/components/formats/list/formats.component.html @@ -1,78 +1,68 @@ -<ng-container *ngIf="formats"> - <div> - <div class="section"> - <div class="columns is-centered is-marginless"> - <div class="column has-text-centered"> - <h2>{{ totalElement }} formats trouvés</h2> - </div> - </div> - <div class="add-item-link has-text-right"> - <a class="button button-gl" [routerLink]="['new']"> - Ajouter - </a> +<section class="section page-container" *ngIf="formats"> + <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="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="table entity-list-table"> - <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> + <div class="column is-2"> + <span (click)="sortBy('mapServerType')" class="is-sortable"> + <span class="sort-icons"> + <span class="icon"> + <i class="fas fa-sort-up" + [ngClass]="{'icon-red': sortOptions.value === 'mapServerType' && sortOptions.order === 'desc'}"></i> </span> - </div> - <div class="column is-2"> - <span (click)="sortBy('mapServerType')" class="is-sortable"> - <span class="sort-icons"> - <span class="icon"> - <i class="fas fa-sort-up" - [ngClass]="{'icon-red': sortOptions.value === 'mapServerType' && sortOptions.order === 'desc'}"></i> - </span> - <span class="icon"> - <i class="fas fa-sort-down" - [ngClass]="{'icon-red': sortOptions.value === 'mapServerType' && sortOptions.order === 'asc'}"></i> - </span> - </span> - <span class="column-title" [ngClass]="{'active': sortOptions.value === mapServerType}">Type - MapServer</span> + <span class="icon"> + <i class="fas fa-sort-down" + [ngClass]="{'icon-red': sortOptions.value === 'mapServerType' && sortOptions.order === 'asc'}"></i> </span> - </div> - <div class="column is-offset-7 is-1 has-text-centered"> - <span class="column-title">Actions</span> - </div> + </span> + <span class="column-title" [ngClass]="{'active': sortOptions.value === mapServerType}">Type + MapServer</span> + </span> + </div> + <div class="column is-offset-7 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 format of formats; let i=index; let odd=odd; let even=even;" [ngClass]="{ odd: odd, even: even }"> + <div class="column is-2"> + <span>{{ format.name}}</span> </div> - <div class="data-list"> - <div class="data columns is-multiline is-vcentered is-marginless" - *ngFor="let format of formats; let i=index; let odd=odd; let even=even;" - [ngClass]="{ odd: odd, even: even }"> - <div class="column is-2"> - <span>{{ format.name}}</span> - </div> - <div class="column is-2"> - <span>{{ format.mapServerType}}</span> - </div> - <div class="column is-offset-7 is-1 has-text-centered actions"> - <app-crud-buttons [id]="format.id" (delete)="displayDeletePopup($event)"></app-crud-buttons> - </div> - </div> + <div class="column is-2"> + <span>{{ format.mapServerType}}</span> </div> - <div class="columns is-marginless"> - <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)" - (pageSizeChanged)="changePageSize($event)"> - </app-paginator> - </div> + <div class="column is-offset-7 is-1 has-text-centered actions"> + <app-crud-buttons [id]="format.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)" (pageSizeChanged)="changePageSize($event)"> + </app-paginator> + </div> + </div> </div> -</ng-container> \ No newline at end of file +</section> \ No newline at end of file diff --git a/src/app/components/formats/list/formats.component.scss b/src/app/components/formats/list/formats.component.scss index 60e54cc57c1c724a268114806e46807cba7cf38e..8b137891791fe96927ad78e64b0aad7bded08bdc 100644 --- a/src/app/components/formats/list/formats.component.scss +++ b/src/app/components/formats/list/formats.component.scss @@ -1,3 +1 @@ -.section { - padding-top: 0; -} + diff --git a/src/app/components/formats/list/formats.component.ts b/src/app/components/formats/list/formats.component.ts index 0efba29653deeaa91189cc967d4cfe9a8edea5bb..950708a57bc2a87bbf015edbf48ff40fb99248a6 100644 --- a/src/app/components/formats/list/formats.component.ts +++ b/src/app/components/formats/list/formats.component.ts @@ -3,6 +3,7 @@ import { FormatService } from 'src/app/services/format.service'; import { Subscription } from 'rxjs'; import { PaginatorOptions } from 'src/app/models/paginator-options.model'; import { Format, FormatRO } from 'src/app/models/format.model'; +import { IPageHeaderInfo } from '../../../models/page.model'; @Component({ selector: 'app-formats', @@ -11,6 +12,9 @@ import { Format, FormatRO } from 'src/app/models/format.model'; }) export class FormatsComponent implements OnInit { + pageHeaderInfo: IPageHeaderInfo = { + title: '', + }; formats: Format[]; searchChangeSub: Subscription; @@ -58,6 +62,8 @@ export class FormatsComponent implements OnInit { this.formats = items.formats; this.totalElement = items.totalCount; + this.pageHeaderInfo.title = `${this.totalElement} formats trouvés`; + this.paginator.limit = this.formatsService.limit; this.paginator.pageIndex = this.formatsService.pageNumber; this.paginator.length = items.totalCount; diff --git a/src/app/components/image-upload/image-upload.component.html b/src/app/components/image-upload/image-upload.component.html index 72e3400a5b9ffda47784a569bdcaca09f18d99ff..acf76a9096674091801f6144bfb7a73773f005d3 100644 --- a/src/app/components/image-upload/image-upload.component.html +++ b/src/app/components/image-upload/image-upload.component.html @@ -1,5 +1,6 @@ <div class="field"> - <label class="label" [for]="fieldParams.inputName">{{ fieldParams.label }}</label> + <label class="label" [ngClass]="{'required': fieldParams.isRequired}" + [for]="fieldParams.inputName">{{ fieldParams.label }}</label> <div class="image-preview-container" *ngIf="fieldParams.existingImageUrl && !removeImageBtnClicked"> <button class="button" (click)="removeImage()"><i class="far fa-times-circle"></i></button> <img [src]="fieldParams.existingImageUrl" alt="" class="image-preview"> diff --git a/src/app/components/index.ts b/src/app/components/index.ts index a2edd109b7a99747ce8fefaae83fefc0343944e1..90f5e966751673233933f0a7cb01fc0caef66634 100644 --- a/src/app/components/index.ts +++ b/src/app/components/index.ts @@ -13,6 +13,7 @@ import { FormatDetailComponent } from './formats/detail/format-detail.component' import { FormatFormComponent } from './formats/edit/format-form.component'; import { ImageUploadComponent } from './image-upload/image-upload.component'; import { NotificationsComponent } from './notifications/notifications.component'; +import { PageHeaderComponent } from './page-header/page-header.component'; export { MenuComponent, @@ -30,6 +31,7 @@ export { FormatFormComponent, ImageUploadComponent, NotificationsComponent, + PageHeaderComponent, }; // tslint:disable-next-line:variable-name @@ -49,4 +51,5 @@ export const AppComponents = [ FormatFormComponent, ImageUploadComponent, NotificationsComponent, + PageHeaderComponent, ]; diff --git a/src/app/components/organizations/detail/organization-detail.component.html b/src/app/components/organizations/detail/organization-detail.component.html index 56d16c9fb072a8e26c86b743abe97ee16a7781f1..fcde85111da378bd3530e34756395e9fa74f2396 100644 --- a/src/app/components/organizations/detail/organization-detail.component.html +++ b/src/app/components/organizations/detail/organization-detail.component.html @@ -1,53 +1,43 @@ -<ng-container *ngIf="organization"> - - <app-back-button [route]="'/producteur-de-donnees'" [title]="'Retourner à la liste des organisations'"> - </app-back-button> - - <section class="section"> - <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"> - {{organization.name}} - </p> - </header> - <div class="card-image"> - <figure class="image"> - <img [src]="organization.logo" alt="Logo du producteur de données"> - </figure> - </div> - <div class="card-content"> - - <div class="content"> - <div> - <p>{{organization.description}}</p> - </div> - <br> - <div> - <p><span class="has-text-weight-bold">Id:</span> {{ organization.id}}</p> - </div> - <br> - <div> - <p class="has-text-weight-bold">Nom ElasticSearch de l'organisation:</p> - <p>{{ organization.elasticSearchName}}</p> - </div> - <br> - <div> - <p class="has-text-weight-bold">Liens</p> - <p *ngFor="let link of organization.links"> - <a href="{{ link.url }}" target="_blank">{{link.url}}</a> - </p> - </div> +<section class="section page-container" *ngIf="organization"> + <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"> + {{organization.name}} + </p> + </header> + <div class="card-image"> + <figure class="image"> + <img [src]="organization.logo" alt="Logo du producteur de données"> + </figure> + </div> + <div class="card-content"> + <div class="content"> + <div> + <p>{{organization.description}}</p> + </div> + <br> + <div> + <p><span class="has-text-weight-bold">Id:</span> {{ organization.id}}</p> + </div> + <br> + <div> + <p class="has-text-weight-bold">Nom ElasticSearch de l'organisation:</p> + <p>{{ organization.elasticSearchName}}</p> + </div> + <br> + <div> + <p class="has-text-weight-bold">Liens</p> + <p *ngFor="let link of organization.links"> + <a href="{{ link.url }}" target="_blank">{{link.url}}</a> + </p> </div> </div> </div> </div> - </div> - - - </section> - -</ng-container> \ No newline at end of file + </div> +</section> \ No newline at end of file diff --git a/src/app/components/organizations/detail/organization-detail.component.ts b/src/app/components/organizations/detail/organization-detail.component.ts index 459164c4e696a5965f18fc7adece80e6c8c6165a..b0f291aee1562aeb3824a1c3468ab5fbbe4920ab 100644 --- a/src/app/components/organizations/detail/organization-detail.component.ts +++ b/src/app/components/organizations/detail/organization-detail.component.ts @@ -14,16 +14,18 @@ import { OrganizationService } from 'src/app/services/organization.service'; export class OrganizationDetailComponent implements OnInit { organization: Organization; + title: string; constructor( - private route: ActivatedRoute, - private organizationService: OrganizationService, + private _route: ActivatedRoute, + private _organizationService: OrganizationService, ) { } ngOnInit(): void { - this.route.paramMap.pipe( - switchMap((params: ParamMap) => this.organizationService.findById(params.get('id')))) + this.title = this._route.snapshot.data.title; + this._route.paramMap.pipe( + switchMap((params: ParamMap) => this._organizationService.findById(params.get('id')))) .subscribe((organization: Organization) => this.organization = organization); } } diff --git a/src/app/components/organizations/edit/organization-form.component.html b/src/app/components/organizations/edit/organization-form.component.html index 70d9104a369d463daa8d6dda80b571884ab2f634..dc8ea2d64fa1c4dad0e86a157b1f452201085088 100644 --- a/src/app/components/organizations/edit/organization-form.component.html +++ b/src/app/components/organizations/edit/organization-form.component.html @@ -1,9 +1,5 @@ -<ng-container *ngIf="organization"> - - <app-back-button [route]="'/producteur-de-donnees'" [title]="'Retourner à la liste des producteurs de données'"> - </app-back-button> - - <h1>{{ title }}</h1> +<section class="section page-container" *ngIf="organization"> + <app-page-header [pageInfo]="{title: title}"></app-page-header> <form [formGroup]="form" (ngSubmit)="onSubmit()" class="columns is-centered is-marginless"> <div class="column is-7"> @@ -88,4 +84,4 @@ </div> </div> </form> -</ng-container> \ No newline at end of file +</section> \ 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 65ec6c114da38c1d157b24fbfec20011888c34de..b8a22a5f7fee592f7a91fbfb7863edc7f4d49832 100644 --- a/src/app/components/organizations/edit/organization-form.component.ts +++ b/src/app/components/organizations/edit/organization-form.component.ts @@ -21,6 +21,7 @@ export class OrganizationFormComponent implements OnInit { inputName: 'logo', label: 'Logo', existingImageUrl: null, + isRequired: true, }; logo: File; title: string; diff --git a/src/app/components/organizations/list/organizations.component.html b/src/app/components/organizations/list/organizations.component.html index bc595889e145217813e2c2514bf8044e0c915a85..f30fe6a126772c926a0eefc3db29202345127685 100644 --- a/src/app/components/organizations/list/organizations.component.html +++ b/src/app/components/organizations/list/organizations.component.html @@ -1,92 +1,83 @@ -<ng-container *ngIf="organizations"> - <div> - <div class="section"> - <div class="columns is-centered is-marginless"> - <div class="column has-text-centered"> - <h2>{{ totalElement }} producteurs de données trouvés</h2> - </div> +<div class="section page-container" *ngIf="organizations"> + <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="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="add-item-link has-text-right"> - <a class="button button-gl" [routerLink]="['new']"> - Ajouter - </a> + <div class="column is-2 has-text-centered"> + <span class="column-title">Logo</span> </div> - <div class="table entity-list-table"> - <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> + <div class="column is-4"> + <span (click)="sortBy('description')" class="is-sortable"> + <span class="sort-icons"> + <span class="icon"> + <i class="fas fa-sort-up" + [ngClass]="{'icon-red': sortOptions.value === 'description' && sortOptions.order === 'desc'}"></i> </span> - </div> - <div class="column is-2 has-text-centered"> - <span class="column-title">Logo</span> - </div> - <div class="column is-4"> - <span (click)="sortBy('description')" class="is-sortable"> - <span class="sort-icons"> - <span class="icon"> - <i class="fas fa-sort-up" - [ngClass]="{'icon-red': sortOptions.value === 'description' && sortOptions.order === 'desc'}"></i> - </span> - <span class="icon"> - <i class="fas fa-sort-down" - [ngClass]="{'icon-red': sortOptions.value === 'description' && sortOptions.order === 'asc'}"></i> - </span> - </span> - <span class="column-title">Description</span> + <span class="icon"> + <i class="fas fa-sort-down" + [ngClass]="{'icon-red': sortOptions.value === 'description' && sortOptions.order === 'asc'}"></i> </span> - </div> - <div class="column is-3"> - <span class="column-title">Liens</span> - </div> - <div class="column is-1 has-text-centered"> - <span class="column-title">Actions</span> - </div> + </span> + <span class="column-title">Description</span> + </span> + </div> + <div class="column is-3"> + <span class="column-title">Liens</span> + </div> + <div class="column 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 organization of organizations; let i=index; let odd=odd; let even=even;" + [ngClass]="{ odd: odd, even: even }"> + <div class="column is-2"> + <span>{{ organization.name}}</span> </div> - <div class="data-list"> - <div class="data columns is-multiline is-vcentered is-marginless" - *ngFor="let organization of organizations; let i=index; let odd=odd; let even=even;" - [ngClass]="{ odd: odd, even: even }"> - <div class="column is-2"> - <span>{{ organization.name}}</span> - </div> - <div class="column is-2 has-text-centered"> - <img src="{{organization.logo}}" alt=""> - </div> - <div class="column is-4"> - <span>{{ organization.description | slice:0:200}}...</span> - </div> - <div class="column is-3"> - <p *ngFor="let link of organization.links"> - <a href="{{ link.url }}" target="_blank">{{link.url}}</a> - </p> - </div> - <div class="column is-1 has-text-centered actions"> - <app-crud-buttons [id]="organization.id" (delete)="displayDeletePopup($event)"></app-crud-buttons> - </div> - - </div> + <div class="column is-2 has-text-centered"> + <img src="{{organization.logo}}" alt=""> + </div> + <div class="column is-4"> + <span>{{ organization.description | slice:0:200}}...</span> + </div> + <div class="column is-3"> + <p *ngFor="let link of organization.links"> + <a href="{{ link.url }}" target="_blank">{{link.url}}</a> + </p> </div> - <div class="columns is-marginless"> - <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)" - (pageSizeChanged)="changePageSize($event)"> - </app-paginator> - </div> + <div class="column is-1 has-text-centered actions"> + <app-crud-buttons [id]="organization.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)" (pageSizeChanged)="changePageSize($event)"> + </app-paginator> </div> </div> </div> -</ng-container> \ No newline at end of file +</div> \ No newline at end of file diff --git a/src/app/components/organizations/list/organizations.component.scss b/src/app/components/organizations/list/organizations.component.scss index 75967d55481be1eec5cd3650d95b0685f4668141..d1ab57677f61171791f67b163f6b933ef1dd4a41 100644 --- a/src/app/components/organizations/list/organizations.component.scss +++ b/src/app/components/organizations/list/organizations.component.scss @@ -1,7 +1,3 @@ -.section { - padding-top: 0; -} - img { max-width: 100px; } diff --git a/src/app/components/organizations/list/organizations.component.ts b/src/app/components/organizations/list/organizations.component.ts index 327fe012ed20fd276129103cde21ed8ac9bd0b57..c2c4551db3b71a1ab7a5903a0b57b62760762ad7 100644 --- a/src/app/components/organizations/list/organizations.component.ts +++ b/src/app/components/organizations/list/organizations.component.ts @@ -3,6 +3,7 @@ import { Organization, OrganizationRO } from 'src/app/models/organization.model' import { OrganizationService } from 'src/app/services/organization.service'; import { Subscription } from 'rxjs'; import { PaginatorOptions } from 'src/app/models/paginator-options.model'; +import { IPageHeaderInfo } from '../../../models/page.model'; @Component({ selector: 'app-organizations', @@ -11,6 +12,9 @@ import { PaginatorOptions } from 'src/app/models/paginator-options.model'; }) export class OrganizationsComponent implements OnInit { + pageHeaderInfo: IPageHeaderInfo = { + title: '', + }; organizations: Organization[]; searchChangeSub: Subscription; @@ -58,6 +62,8 @@ export class OrganizationsComponent implements OnInit { this.organizations = items.organizations; this.totalElement = items.totalCount; + this.pageHeaderInfo.title = `${this.totalElement} producteurs de données trouvés`; + this.paginator.limit = this.organizationsService.limit; this.paginator.pageIndex = this.organizationsService.pageNumber; this.paginator.length = items.totalCount; diff --git a/src/app/components/page-header/page-header.component.html b/src/app/components/page-header/page-header.component.html new file mode 100644 index 0000000000000000000000000000000000000000..fa2b49d223e9f3932a5e7273e68c800008000196 --- /dev/null +++ b/src/app/components/page-header/page-header.component.html @@ -0,0 +1,21 @@ +<div class="page-header"> + <div class="back-button" (click)="goToPreviousPage()" + [ngClass]="{'has-beta-style': pageInfo.hasBetaStyle, 'hidden': hideBackButton}"> + <img class="icon-left-arrow" src="./assets/img/left_arrow.svg" alt="Picto de la flèche retour"> + <span>Retour</span> + </div> + + <div class="page-title" [ngClass]="{'has-surtitle': pageInfo.surtitle}"> + <div class="surtitle-item" *ngIf="pageInfo.surtitle"> + <span>{{ pageInfo.surtitle }}</span> + </div> + <div class="title-item"> + {{ pageInfo.title }} <span class="metadataSubtitle" *ngIf="pageInfo.metadataSubtitle"> - + {{ pageInfo.metadataSubtitle }} </span> + </div> + + <div class="subtitle-item" *ngIf="pageInfo.subtitle"> + <span>{{ pageInfo.subtitle }}</span> + </div> + </div> +</div> \ No newline at end of file diff --git a/src/app/components/page-header/page-header.component.scss b/src/app/components/page-header/page-header.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..f2646b90d894da46aae7a30c9d66fe68e26b256d --- /dev/null +++ b/src/app/components/page-header/page-header.component.scss @@ -0,0 +1,88 @@ +@import '../../../scss/variables.scss'; +@import '../../../../node_modules/bulma/sass/utilities/_all.sass'; + +.page-header { + display: flex; + padding-top: 1.875rem; + padding-bottom: 1.875rem; +} + +.back-button { + color: $grey-dark-color; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + padding: 1.125rem 1rem 1.125rem 0; + width: 6rem; + white-space: nowrap; + align-items: center; + align-self: flex-start; + flex-shrink: 0; + justify-content: center; + // Hide back button for mobile + display: none; + + &.hidden { + display: none; + } + + @media screen and (min-width: $tablet) { + display: flex; + } + + .icon-left-arrow { + margin-right: 0.5rem; + } + + &:hover { + text-decoration: underline; + } +} + +.page-title { + align-self: center; + padding-left: 1rem; + + border-left: 4px solid $tomato-color; + + &.has-beta-style { + border-left-color: $yellow-dd-color; + } +} + +.page-title.has-surtitle { + display: flex; + flex-direction: column; + justify-content: space-between; + align-self: unset; +} + +.surtitle-item span { + margin-bottom: 0.5rem; + font-size: 0.75rem; + text-transform: uppercase; + color: $grey-dark-color; + line-height: 1; + vertical-align: text-top; +} + +.subtitle-item span { + margin-top: 0.5rem; + font-size: 1rem; + color: $grey-dark-color; + line-height: 1; + vertical-align: text-bottom; +} + +.metadataSubtitle { + color: $grey-dark-color; + font-weight: 300; + font-size: inherit; +} + +.title-item { + font-size: 1.75rem; + font-weight: bold; + line-height: 1.15; + color: $brand-color; +} diff --git a/src/app/components/page-header/page-header.component.spec.ts b/src/app/components/page-header/page-header.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..21189ddf954f43c25ddee7be4bfb6b9724f9e3bc --- /dev/null +++ b/src/app/components/page-header/page-header.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PageHeaderComponent } from './page-header.component'; + +describe('PageHeaderComponent', () => { + let component: PageHeaderComponent; + let fixture: ComponentFixture<PageHeaderComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [PageHeaderComponent], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PageHeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/page-header/page-header.component.ts b/src/app/components/page-header/page-header.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..0d824ad8570f807af5ec8d8e5de919426a609ce4 --- /dev/null +++ b/src/app/components/page-header/page-header.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Router } from '@angular/router'; +import { NavigationHistoryService } from '../../services'; +import { IPageHeaderInfo } from '../../models/page.model'; + +@Component({ + selector: 'app-page-header', + templateUrl: './page-header.component.html', + styleUrls: ['./page-header.component.scss'], +}) +export class PageHeaderComponent implements OnInit { + + constructor( + private _navigationHistoryService: NavigationHistoryService, + private _router: Router, + ) { } + + @Input() pageInfo: IPageHeaderInfo; + @Input() customGoToPreviousPage: any; + @Input() hideBackButton: boolean; + + ngOnInit() { + } + + goToPreviousPage() { + if (this.customGoToPreviousPage) { + this.customGoToPreviousPage(); + } else { + const index = 1; // Start to retrieve the previous element + let url = this._navigationHistoryService.getFromLast(index); + + // If url is null then redirect to home page + if (url == null) { + url = '/'; + } + this._router.navigateByUrl(url); + } + } + +} diff --git a/src/app/components/paginator/paginator.component.html b/src/app/components/paginator/paginator.component.html index 157567c077ff9adbcdd5030fc9ebf3d2898ffbec..dd5cef2baa36e77bcc7b6e4d0b78cd735587fa33 100644 --- a/src/app/components/paginator/paginator.component.html +++ b/src/app/components/paginator/paginator.component.html @@ -1,84 +1,64 @@ <div class="columns"> - <div class="column is-narrow has-text-centered"> - <!-- Dropdown list of pageSize number --> - <div class="dropdown" [ngClass]="{'is-active': pageSizeDropdownToggle}" (click)="pageSizeDropdownToggle=!pageSizeDropdownToggle"> - <div class="dropdown-trigger"> - <button class="button is-small" aria-haspopup="true" aria-controls="dropdown-menu"> - <span>{{ pageSize }}</span> - <span class="icon is-small"> - <i class="fas fa-angle-down" aria-hidden="true"></i> - </span> - </button> - </div> - <div class="dropdown-menu" id="dropdown-menu" role="menu"> - <div class="dropdown-content"> - <span role="button" - tabindex="0" - class="dropdown-item" - [ngClass]="{'is-active': nb === pageSize}" - *ngFor="let nb of pageSizeOptions" - (click)="changePageSize(nb)" - (keyup.enter)="changePageSize(nb)"> - {{ nb }} - </span> - </div> - </div> - </div> - </div> <div class="column"> - <div class="pagination is-centered is-small" role="navigation" aria-label="pagination" *ngIf="length > 0"> - <!-- First button --> - <button class="pagination-previous button" *ngIf="pageIndex === 1 || loading; else activeFirstPageLink" disabled> - <i class="fas fa-angle-double-left"></i> - </button> - <ng-template #activeFirstPageLink> - <button class="pagination-previous button" (click)="onPage(1)"> - <i class="fas fa-angle-double-left"></i> - </button> - </ng-template> - + <div class="pagination-dgl is-centered is-small" role="navigation" aria-label="pagination" *ngIf="length > 0"> <!-- Previous button --> - <button class="pagination-previous button" *ngIf="pageIndex === 1 || loading; else activePreviousLink" disabled> - <i class="fas fa-angle-left"></i> + <button class="button previous" *ngIf="pageIndex === 1 || loading; else activePreviousLink" disabled> + <svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9"> + <path + d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" + class="brandcolor" /> + <path + d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" + class="brandcolor" /> + </svg> </button> <ng-template #activePreviousLink> - <button class="pagination-previous button" (click)="onPrev()"> - <i class="fas fa-angle-left"></i> + <button class="button previous" (click)="onPrev()"> + <svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9"> + <path + d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" + class="brandcolor" /> + <path + d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" + class="brandcolor" /> + </svg> </button> </ng-template> <!-- List of pages number --> - <ul class="pagination-list"> + <ul> <ng-container *ngFor="let pageNum of getPages(); let i = index"> - <li *ngIf="displayEllipsis(i)"> - <span class="pagination-ellipsis">…</span> - </li> <li> - <button *ngIf="!loading; else pageNumberDisabled" (click)="onPage(pageNum)" class="pagination-link button" [ngClass]="{'is-current': pageNum === pageIndex}">{{ pageNum }}</button> + <button *ngIf="!loading; else pageNumberDisabled" (click)="onPage(pageNum)" class="button" + [ngClass]="{'is-current': pageNum === pageIndex}">{{ pageNum }}</button> <ng-template #pageNumberDisabled> - <button class="pagination-link button" [ngClass]="{'is-current': pageNum === pageIndex}" disabled>{{ pageNum }}</button> + <button class="button" [ngClass]="{'is-current': pageNum === pageIndex}" disabled>{{ pageNum }}</button> </ng-template> </li> </ng-container> </ul> <!-- Next button --> - <button class="pagination-next button" *ngIf="lastPage() || loading; else activeNextLink" disabled> - <i class="fas fa-angle-right"></i> + <button class="button" *ngIf="lastPage() || loading; else activeNextLink" disabled> + <svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9"> + <path + d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" + class="brandcolor" /> + <path + d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" + class="brandcolor" /> + </svg> </button> <ng-template #activeNextLink> - <button class="pagination-next button" (click)="onNext()"> - <i class="fas fa-angle-right"></i> - </button> - </ng-template> - - <!-- Last button --> - <button class="pagination-next button" *ngIf="lastPage() || loading; else activeLastPageLink" disabled> - <i class="fas fa-angle-double-right"></i> - </button> - <ng-template #activeLastPageLink> - <button class="pagination-next button" (click)="onPage(totalPages())"> - <i class="fas fa-angle-double-right"></i> + <button class="button next" (click)="onNext()"> + <svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9"> + <path + d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" + class="brandcolor" /> + <path + d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z" + class="brandcolor" /> + </svg> </button> </ng-template> </div> diff --git a/src/app/components/paginator/paginator.component.scss b/src/app/components/paginator/paginator.component.scss index 37b33eca9ad0a4062c594698265b4ef71b05d2a3..a1becd90948a55e867c9a99d9d62493aaa4a9cc5 100644 --- a/src/app/components/paginator/paginator.component.scss +++ b/src/app/components/paginator/paginator.component.scss @@ -1,10 +1,49 @@ +@import "./../../../scss/variables.scss"; + .dropdown-menu { min-width: unset; } + .dropdown-content { padding-top: unset; padding-bottom: unset; } + .dropdown-item { padding: 0.3rem 1rem; -} \ No newline at end of file +} + +ul, +li { + display: inline-block; +} + +.pagination-dgl { + text-align: center; + + .button { + border: none; + color: $grey-dark-color; + padding-left: 0.5em; + padding-right: 0.5em; + margin-left: 0.25rem; + + &:hover { + text-decoration: underline; + } + + &.is-current { + color: $tomato-color; + } + } +} + +svg { + width: 13px; + fill: $grey-dark-color; + transform: rotate(-90deg); +} + +.previous svg { + transform: rotate(90deg); +} diff --git a/src/app/components/paginator/paginator.component.spec.ts b/src/app/components/paginator/paginator.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..b842808244f54cb38f5b1a699512cf14220547f1 --- /dev/null +++ b/src/app/components/paginator/paginator.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PaginatorComponent } from './paginator.component'; + +describe('PaginatorComponent', () => { + let component: PaginatorComponent; + let fixture: ComponentFixture<PaginatorComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [PaginatorComponent], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PaginatorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/paginator/paginator.component.ts b/src/app/components/paginator/paginator.component.ts index c0ba5eeca447e2fab2d95edf0f8b5885bdbacacf..0debb3cfb0985ef9dcbd7c8d8542880645b099d7 100644 --- a/src/app/components/paginator/paginator.component.ts +++ b/src/app/components/paginator/paginator.component.ts @@ -63,10 +63,11 @@ export class PaginatorComponent implements OnInit { getPages(): number[] { const totalP = Math.ceil(this.length / this.pageSize); // Total number of page const p = this.pageIndex || 1; // Current page index - const pagesToShow = this.pagesToShow || 5; // Total number of pages to be displayed in the paginator + const midPage = Math.round(totalP / 2); + const pagesToShow = 3; // Total number of pages to be displayed in the paginator const pages: number[] = []; // Page number to be displayed pages.push(p); // Push the current page index - let times = pagesToShow - 1; // Number of page to be added to the displayed page + let times = pagesToShow; // Number of page to be added to the displayed page if (p !== 1) { // If current page is different from the first page remove one (first page automatically // added to the array at the end of the function) @@ -110,6 +111,10 @@ export class PaginatorComponent implements OnInit { if (pages.indexOf(totalP) === -1) { pages.push(totalP); } + // Adding half page if not already in the array + if (pages.indexOf(midPage) === -1) { + pages.push(midPage); + } // Reordering the array pages.sort((a, b) => a - b); return pages; diff --git a/src/app/components/resources/detail/resource-detail.component.html b/src/app/components/resources/detail/resource-detail.component.html index 60a5b0114ad29ff66798be9b4543a00585edf42a..142398b016a9d9ce69cb516509d3ad70298f52df 100644 --- a/src/app/components/resources/detail/resource-detail.component.html +++ b/src/app/components/resources/detail/resource-detail.component.html @@ -1,113 +1,105 @@ -<ng-container *ngIf="resource"> - - <app-back-button [route]="'/resources'" [title]="'Retourner à la liste des ressources'"></app-back-button> - - <section class="section"> - <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"> - {{resource.name}} +<section class="section page-container" *ngIf="resource"> + <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"> + {{resource.name}} + </p> + </header> + <div class="card-content"> + <div class="content"> + <p> + <span class="has-text-weight-bold">Id: </span> + <span>{{resource.id}}</span> + </p> + <p> + <span class="has-text-weight-bold">Acronyme: </span> + <span *ngIf="resource.acronym; else emptyAcronymWarning">{{resource.acronym}}</span> + <ng-template #emptyAcronymWarning> + <span class="empty-property">Non renseigné</span> + </ng-template> </p> - </header> - <div class="card-content"> - <div class="content"> - <p> - <span class="has-text-weight-bold">Id: </span> - <span>{{resource.id}}</span> - </p> - <p> - <span class="has-text-weight-bold">Acronyme: </span> - <span *ngIf="resource.acronym; else emptyAcronymWarning">{{resource.acronym}}</span> - <ng-template #emptyAcronymWarning> - <span class="empty-property">Non renseigné</span> - </ng-template> - </p> - - <p> - <span class="has-text-weight-bold">Type: </span> - <span *ngIf="resource.type; else emptyTypeWarning">{{resource.type}}</span> - <ng-template #emptyTypeWarning> - <span class="empty-property">Non renseigné</span> - </ng-template> - </p> - - <div *ngIf="resource.description"> - <span class="has-text-weight-bold">Description: </span> - <span *ngIf="resource.description; else emptyDescriptionWarning">{{resource.description}}</span> - <ng-template #emptyDescriptionWarning> - <span class="empty-property">Non renseigné</span> - </ng-template> - </div> - - <p> - <span class="has-text-weight-bold">Requêtable: </span> - <span class="icon has-text-success" - [ngClass]="{'has-text-success': resource.isQueryable, 'has-text-danger': !resource.isQueryable}"> - <i class="far fa-check-circle" - [ngClass]="{'fa-check-circle': resource.isQueryable, 'fa-times-circle': !resource.isQueryable}"></i> - </span> - </p> - <p> - <span class="has-text-weight-bold">Téléchargeable: </span> - <span class="icon has-text-success" - [ngClass]="{'has-text-success': resource.isDownloadable, 'has-text-danger': !resource.isDownloadable}"> - <i class="far fa-check-circle" - [ngClass]="{'fa-check-circle': resource.isDownloadable, 'fa-times-circle': !resource.isDownloadable}"></i> - </span> - </p> + <p> + <span class="has-text-weight-bold">Type: </span> + <span *ngIf="resource.type; else emptyTypeWarning">{{resource.type}}</span> + <ng-template #emptyTypeWarning> + <span class="empty-property">Non renseigné</span> + </ng-template> + </p> - <p> - <span class="has-text-weight-bold">Standardisé: </span> - <span class="icon has-text-success" - [ngClass]="{'has-text-success': resource.isStandard, 'has-text-danger': !resource.isStandard}"> - <i class="far fa-check-circle" - [ngClass]="{'fa-check-circle': resource.isStandard, 'fa-times-circle': !resource.isStandard}"></i> - </span> - </p> + <div *ngIf="resource.description"> + <span class="has-text-weight-bold">Description: </span> + <span *ngIf="resource.description; else emptyDescriptionWarning">{{resource.description}}</span> + <ng-template #emptyDescriptionWarning> + <span class="empty-property">Non renseigné</span> + </ng-template> + </div> - <div *ngIf="resource.parametersUrl"> - <span class="has-text-weight-bold">Parametres URL: </span> - <span *ngIf="resource.parametersUrl; else emptyParameterUrlWarning">{{resource.parametersUrl}}</span> - <ng-template #emptyParameterUrlWarning> - <span class="empty-property">Non renseigné</span> - </ng-template> - </div> + <p> + <span class="has-text-weight-bold">Requêtable: </span> + <span class="icon has-text-success" + [ngClass]="{'has-text-success': resource.isQueryable, 'has-text-danger': !resource.isQueryable}"> + <i class="far fa-check-circle" + [ngClass]="{'fa-check-circle': resource.isQueryable, 'fa-times-circle': !resource.isQueryable}"></i> + </span> + </p> - <div *ngIf="resource.messageWarning"> - <span class="has-text-weight-bold">Message d'alerte: </span> - <span *ngIf="resource.messageWarning; else emptyMessageWarning">{{resource.messageWarning}}</span> - <ng-template #emptyMessageWarning> - <span class="empty-property">Non renseigné</span> - </ng-template> - </div> - <br> + <p> + <span class="has-text-weight-bold">Téléchargeable: </span> + <span class="icon has-text-success" + [ngClass]="{'has-text-success': resource.isDownloadable, 'has-text-danger': !resource.isDownloadable}"> + <i class="far fa-check-circle" + [ngClass]="{'fa-check-circle': resource.isDownloadable, 'fa-times-circle': !resource.isDownloadable}"></i> + </span> + </p> - <div> - <span class="has-text-weight-bold">Formats de sortie: </span> - <ul - *ngIf="resource.resourceFormats && resource.resourceFormats.length > 0; else noResourceFormatTemplate"> - <li *ngFor="let resourceFormat of resource.resourceFormats"> - {{ resourceFormat.format.name }}<span *ngIf="resourceFormat.isCuttable">, découpable</span><span - *ngIf="resourceFormat.isProjectable">, projectable</span> - </li> - </ul> - <ng-template #noResourceFormatTemplate> - <span class="empty-property">Non renseigné</span> - </ng-template> - </div> + <p> + <span class="has-text-weight-bold">Standardisé: </span> + <span class="icon has-text-success" + [ngClass]="{'has-text-success': resource.isStandard, 'has-text-danger': !resource.isStandard}"> + <i class="far fa-check-circle" + [ngClass]="{'fa-check-circle': resource.isStandard, 'fa-times-circle': !resource.isStandard}"></i> + </span> + </p> + <div *ngIf="resource.parametersUrl"> + <span class="has-text-weight-bold">Parametres URL: </span> + <span *ngIf="resource.parametersUrl; else emptyParameterUrlWarning">{{resource.parametersUrl}}</span> + <ng-template #emptyParameterUrlWarning> + <span class="empty-property">Non renseigné</span> + </ng-template> + </div> + <div *ngIf="resource.messageWarning"> + <span class="has-text-weight-bold">Message d'alerte: </span> + <span *ngIf="resource.messageWarning; else emptyMessageWarning">{{resource.messageWarning}}</span> + <ng-template #emptyMessageWarning> + <span class="empty-property">Non renseigné</span> + </ng-template> </div> + <br> + + <div> + <span class="has-text-weight-bold">Formats de sortie: </span> + <ul + *ngIf="resource.resourceFormats && resource.resourceFormats.length > 0; else noResourceFormatTemplate"> + <li *ngFor="let resourceFormat of resource.resourceFormats"> + {{ resourceFormat.format.name }}<span *ngIf="resourceFormat.isCuttable">, découpable</span><span + *ngIf="resourceFormat.isProjectable">, projectable</span> + </li> + </ul> + <ng-template #noResourceFormatTemplate> + <span class="empty-property">Non renseigné</span> + </ng-template> + </div> + </div> </div> </div> - </div> - - - </section> - -</ng-container> \ No newline at end of file + </div> +</section> \ No newline at end of file diff --git a/src/app/components/resources/detail/resource-detail.component.ts b/src/app/components/resources/detail/resource-detail.component.ts index 161b88bc0c5108afa75b8504b380fe1381b6504b..d2ab5ad766194db926d0ed3a31d93925dde380b0 100644 --- a/src/app/components/resources/detail/resource-detail.component.ts +++ b/src/app/components/resources/detail/resource-detail.component.ts @@ -14,16 +14,18 @@ import { ResourceService } from 'src/app/services/resource.service'; export class ResourceDetailComponent implements OnInit { resource: Resource; + title: string; constructor( - private route: ActivatedRoute, - private resourceService: ResourceService, + private _route: ActivatedRoute, + private _resourceService: ResourceService, ) { } ngOnInit(): void { - this.route.paramMap.pipe( - switchMap((params: ParamMap) => this.resourceService.findById(params.get('id')))) + this.title = this._route.snapshot.data.title; + this._route.paramMap.pipe( + switchMap((params: ParamMap) => this._resourceService.findById(params.get('id')))) .subscribe((resource: Resource) => this.resource = resource); } } diff --git a/src/app/components/resources/edit/resource-form.component.html b/src/app/components/resources/edit/resource-form.component.html index 9e24f8e03eb9db223d6f6fd09aaab963021582af..c41e9d4629578b708384787c031f58495eeb5a53 100644 --- a/src/app/components/resources/edit/resource-form.component.html +++ b/src/app/components/resources/edit/resource-form.component.html @@ -1,8 +1,5 @@ -<ng-container *ngIf="resource"> - - <app-back-button [route]="'/resources'" [title]="'Retourner à la liste des ressources'"></app-back-button> - - <h1>{{ title }}</h1> +<section class="section page-container" *ngIf="resource"> + <app-page-header [pageInfo]="{title: title}"></app-page-header> <form [formGroup]="form" (ngSubmit)="onSubmit()" class="columns is-centered is-marginless"> <div class="column is-7"> @@ -90,14 +87,14 @@ </div> <div class="field"> - <label class="label required" for="parametersUrl">Paramètres URL</label> + <label class="label" for="parametersUrl">Paramètres URL</label> <div class="control"> <input class="input" type="text" formControlName="parametersUrl" id="parametersUrl"> </div> </div> <div class="field"> - <label class="label required" for="messageWarning">Message d'alerte</label> + <label class="label" for="messageWarning">Message d'alerte</label> <div class="control"> <input class="input" type="text" formControlName="messageWarning" id="messageWarning"> </div> @@ -178,4 +175,4 @@ </div> </form> -</ng-container> \ No newline at end of file +</section> \ No newline at end of file diff --git a/src/app/components/resources/edit/resource-form.component.ts b/src/app/components/resources/edit/resource-form.component.ts index b40283eb2dbed3b4d2148c60ebd4bb3e6e048052..c379dc1024d744291b88030815c2df643de0114f 100644 --- a/src/app/components/resources/edit/resource-form.component.ts +++ b/src/app/components/resources/edit/resource-form.component.ts @@ -52,8 +52,8 @@ export class ResourceFormComponent implements OnInit { this.resource.resourceFormats.forEach((resourceFormat) => { resourceFormats.push(this._fb.group({ formatId: [resourceFormat.format.id, Validators.required], - isProjectable: resourceFormat.isProjectable, - isCuttable: resourceFormat.isCuttable, + isProjectable: [resourceFormat.isProjectable, Validators.required], + isCuttable: [resourceFormat.isCuttable, Validators.required], id: resourceFormat.id, })); }); diff --git a/src/app/components/resources/list/resources.component.html b/src/app/components/resources/list/resources.component.html index 298d7dde393c10b9dadd503158e8a3858c9c3d9d..f544a69abeaaa7d31ac75a5bf05f4ade9253d221 100644 --- a/src/app/components/resources/list/resources.component.html +++ b/src/app/components/resources/list/resources.component.html @@ -1,194 +1,186 @@ <ng-container *ngIf="resources"> - <div> - <div class="section"> - <div class="columns is-centered is-marginless"> - <div class="column has-text-centered"> - <h2>{{ totalElement }} ressources trouvées</h2> + <div 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="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"> + <span (click)="sortBy('acronym')" class="is-sortable"> + <span class="sort-icons"> + <span class="icon"> + <i class="fas fa-sort-up" + [ngClass]="{'icon-red': sortOptions.value === 'acronym' && sortOptions.order === 'desc'}"></i> + </span> + <span class="icon"> + <i class="fas fa-sort-down" + [ngClass]="{'icon-red': sortOptions.value === 'acronym' && sortOptions.order === 'asc'}"></i> + </span> + </span> + <span class="column-title" [ngClass]="{'active': sortOptions.value === acronym}">Acronyme</span> + </span> + </div> + <div class="column is-1"> + <span (click)="sortBy('type')" class="is-sortable"> + <span class="sort-icons"> + <span class="icon"> + <i class="fas fa-sort-up" + [ngClass]="{'icon-red': sortOptions.value === 'type' && sortOptions.order === 'desc'}"></i> + </span> + <span class="icon"> + <i class="fas fa-sort-down" + [ngClass]="{'icon-red': sortOptions.value === 'type' && sortOptions.order === 'asc'}"></i> + </span> + </span> + <span class="column-title" [ngClass]="{'active': sortOptions.value === type}">Type</span> + </span> + </div> + <div class="column is-4"> + <span (click)="sortBy('description')" class="is-sortable"> + <span class="sort-icons"> + <span class="icon"> + <i class="fas fa-sort-up" + [ngClass]="{'icon-red': sortOptions.value === 'description' && sortOptions.order === 'desc'}"></i> + </span> + <span class="icon"> + <i class="fas fa-sort-down" + [ngClass]="{'icon-red': sortOptions.value === 'description' && sortOptions.order === 'asc'}"></i> + </span> + </span> + <span class="column-title" [ngClass]="{'active': sortOptions.value === description}">Description</span> + </span> + </div> + <div class="column is-1 has-text-centered"> + <span (click)="sortBy('isQueryable')" class="is-sortable"> + <span class="sort-icons"> + <span class="icon"> + <i class="fas fa-sort-up" + [ngClass]="{'icon-red': sortOptions.value === 'isQueryable' && sortOptions.order === 'desc'}"></i> + </span> + <span class="icon"> + <i class="fas fa-sort-down" + [ngClass]="{'icon-red': sortOptions.value === 'isQueryable' && sortOptions.order === 'asc'}"></i> + </span> + </span> + <span class="column-title" [ngClass]="{'active': sortOptions.value === isQueryable}">Requêtable</span> + </span> + </div> + <div class="column is-1 has-text-centered"> + <span (click)="sortBy('isDownloadable')" class="is-sortable"> + <span class="sort-icons"> + <span class="icon"> + <i class="fas fa-sort-up" + [ngClass]="{'icon-red': sortOptions.value === 'isDownloadable' && sortOptions.order === 'desc'}"></i> + </span> + <span class="icon"> + <i class="fas fa-sort-down" + [ngClass]="{'icon-red': sortOptions.value === 'isDownloadable' && sortOptions.order === 'asc'}"></i> + </span> + </span> + <span class="column-title" + [ngClass]="{'active': sortOptions.value === isDownloadable}">Téléchargeable</span> + </span> + </div> + <div class="column is-1 has-text-centered"> + <span (click)="sortBy('isStandard')" class="is-sortable"> + <span class="sort-icons"> + <span class="icon"> + <i class="fas fa-sort-up" + [ngClass]="{'icon-red': sortOptions.value === 'isStandard' && sortOptions.order === 'desc'}"></i> + </span> + <span class="icon"> + <i class="fas fa-sort-down" + [ngClass]="{'icon-red': sortOptions.value === 'isStandard' && sortOptions.order === 'asc'}"></i> + </span> + </span> + <span class="column-title" [ngClass]="{'active': sortOptions.value === isStandard}">Standard</span> + </span> + </div> + <div class="column is-1 has-text-centered"> + <span class="column-title">Actions</span> </div> </div> - <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="header columns is-marginless"> + <div class="data-list"> + <div class="data columns is-multiline is-vcentered is-marginless" + *ngFor="let resource of resources; let i=index; let odd=odd; let even=even;" + [ngClass]="{ odd: odd, even: even }"> <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> + {{ resource.name}} </span> + </div> <div class="column is-1"> - <span (click)="sortBy('acronym')" class="is-sortable"> - <span class="sort-icons"> - <span class="icon"> - <i class="fas fa-sort-up" - [ngClass]="{'icon-red': sortOptions.value === 'acronym' && sortOptions.order === 'desc'}"></i> - </span> - <span class="icon"> - <i class="fas fa-sort-down" - [ngClass]="{'icon-red': sortOptions.value === 'acronym' && sortOptions.order === 'asc'}"></i> - </span> - </span> - <span class="column-title" [ngClass]="{'active': sortOptions.value === acronym}">Acronyme</span> + <span> + {{ resource.acronym}} </span> + </div> <div class="column is-1"> - <span (click)="sortBy('type')" class="is-sortable"> - <span class="sort-icons"> - <span class="icon"> - <i class="fas fa-sort-up" - [ngClass]="{'icon-red': sortOptions.value === 'type' && sortOptions.order === 'desc'}"></i> - </span> - <span class="icon"> - <i class="fas fa-sort-down" - [ngClass]="{'icon-red': sortOptions.value === 'type' && sortOptions.order === 'asc'}"></i> - </span> - </span> - <span class="column-title" [ngClass]="{'active': sortOptions.value === type}">Type</span> + <span> + {{ resource.type}} </span> + </div> <div class="column is-4"> - <span (click)="sortBy('description')" class="is-sortable"> - <span class="sort-icons"> - <span class="icon"> - <i class="fas fa-sort-up" - [ngClass]="{'icon-red': sortOptions.value === 'description' && sortOptions.order === 'desc'}"></i> - </span> - <span class="icon"> - <i class="fas fa-sort-down" - [ngClass]="{'icon-red': sortOptions.value === 'description' && sortOptions.order === 'asc'}"></i> - </span> - </span> - <span class="column-title" [ngClass]="{'active': sortOptions.value === description}">Description</span> + <span> + {{ resource.description | slice:0:300}} </span> </div> <div class="column is-1 has-text-centered"> - <span (click)="sortBy('isQueryable')" class="is-sortable"> - <span class="sort-icons"> - <span class="icon"> - <i class="fas fa-sort-up" - [ngClass]="{'icon-red': sortOptions.value === 'isQueryable' && sortOptions.order === 'desc'}"></i> - </span> - <span class="icon"> - <i class="fas fa-sort-down" - [ngClass]="{'icon-red': sortOptions.value === 'isQueryable' && sortOptions.order === 'asc'}"></i> - </span> - </span> - <span class="column-title" [ngClass]="{'active': sortOptions.value === isQueryable}">Requêtable</span> + <span class="icon has-text-success" *ngIf="resource.isQueryable"> + <i class="far fa-check-circle"></i> + </span> + <span class="icon has-text-danger" *ngIf="!resource.isQueryable"> + <i class="far fa-times-circle"></i> </span> </div> <div class="column is-1 has-text-centered"> - <span (click)="sortBy('isDownloadable')" class="is-sortable"> - <span class="sort-icons"> - <span class="icon"> - <i class="fas fa-sort-up" - [ngClass]="{'icon-red': sortOptions.value === 'isDownloadable' && sortOptions.order === 'desc'}"></i> - </span> - <span class="icon"> - <i class="fas fa-sort-down" - [ngClass]="{'icon-red': sortOptions.value === 'isDownloadable' && sortOptions.order === 'asc'}"></i> - </span> - </span> - <span class="column-title" - [ngClass]="{'active': sortOptions.value === isDownloadable}">Téléchargeable</span> + <span class="icon has-text-success" *ngIf="resource.isDownloadable"> + <i class="far fa-check-circle"></i> + </span> + <span class="icon has-text-danger" *ngIf="!resource.isDownloadable"> + <i class="far fa-times-circle"></i> </span> </div> <div class="column is-1 has-text-centered"> - <span (click)="sortBy('isStandard')" class="is-sortable"> - <span class="sort-icons"> - <span class="icon"> - <i class="fas fa-sort-up" - [ngClass]="{'icon-red': sortOptions.value === 'isStandard' && sortOptions.order === 'desc'}"></i> - </span> - <span class="icon"> - <i class="fas fa-sort-down" - [ngClass]="{'icon-red': sortOptions.value === 'isStandard' && sortOptions.order === 'asc'}"></i> - </span> - </span> - <span class="column-title" [ngClass]="{'active': sortOptions.value === isStandard}">Standard</span> + <span class="icon has-text-success" *ngIf="resource.isStandard"> + <i class="far fa-check-circle"></i> + </span> + <span class="icon has-text-danger" *ngIf="!resource.isStandard"> + <i class="far fa-times-circle"></i> </span> </div> <div class="column is-1 has-text-centered"> - <span class="column-title">Actions</span> + <app-crud-buttons [id]="resource.id" (delete)="displayDeletePopup($event)"></app-crud-buttons> </div> </div> - <div class="data-list"> - <div class="data columns is-multiline is-vcentered is-marginless" - *ngFor="let resource of resources; let i=index; let odd=odd; let even=even;" - [ngClass]="{ odd: odd, even: even }"> - <div class="column is-2"> - <span> - {{ resource.name}} - </span> - - </div> - <div class="column is-1"> - <span> - {{ resource.acronym}} - </span> - - </div> - <div class="column is-1"> - <span> - {{ resource.type}} - </span> - - </div> - <div class="column is-4"> - <span> - {{ resource.description | slice:0:300}} - </span> - </div> - <div class="column is-1 has-text-centered"> - <span class="icon has-text-success" *ngIf="resource.isQueryable"> - <i class="far fa-check-circle"></i> - </span> - <span class="icon has-text-danger" *ngIf="!resource.isQueryable"> - <i class="far fa-times-circle"></i> - </span> - </div> - <div class="column is-1 has-text-centered"> - <span class="icon has-text-success" *ngIf="resource.isDownloadable"> - <i class="far fa-check-circle"></i> - </span> - <span class="icon has-text-danger" *ngIf="!resource.isDownloadable"> - <i class="far fa-times-circle"></i> - </span> - </div> - <div class="column is-1 has-text-centered"> - <span class="icon has-text-success" *ngIf="resource.isStandard"> - <i class="far fa-check-circle"></i> - </span> - <span class="icon has-text-danger" *ngIf="!resource.isStandard"> - <i class="far fa-times-circle"></i> - </span> - </div> - <div class="column is-1 has-text-centered"> - <app-crud-buttons [id]="resource.id" (delete)="displayDeletePopup($event)"></app-crud-buttons> - </div> - </div> - </div> - <div class="columns is-marginless"> - <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)" - (pageSizeChanged)="changePageSize($event)"> - </app-paginator> - </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)" (pageSizeChanged)="changePageSize($event)"> + </app-paginator> </div> </div> </div> - </div> -</ng-container> \ No newline at end of file + </div> \ No newline at end of file diff --git a/src/app/components/resources/list/resources.component.scss b/src/app/components/resources/list/resources.component.scss index 60e54cc57c1c724a268114806e46807cba7cf38e..8b137891791fe96927ad78e64b0aad7bded08bdc 100644 --- a/src/app/components/resources/list/resources.component.scss +++ b/src/app/components/resources/list/resources.component.scss @@ -1,3 +1 @@ -.section { - padding-top: 0; -} + diff --git a/src/app/components/resources/list/resources.component.ts b/src/app/components/resources/list/resources.component.ts index a56ed6ddeeaf05512edcd33cddbfa12247c45bb7..b19fe3e458a99f7a4a7a0818d03fe2929d81b218 100644 --- a/src/app/components/resources/list/resources.component.ts +++ b/src/app/components/resources/list/resources.component.ts @@ -1,8 +1,9 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { Resource, ResourceRO } from 'src/app/models/resource.model'; import { ResourceService } from 'src/app/services/resource.service'; import { Subscription } from 'rxjs'; import { PaginatorOptions } from 'src/app/models/paginator-options.model'; +import { IPageHeaderInfo } from '../../../models/page.model'; @Component({ selector: 'app-resources', @@ -11,6 +12,9 @@ import { PaginatorOptions } from 'src/app/models/paginator-options.model'; }) export class ResourcesComponent implements OnInit { + pageHeaderInfo: IPageHeaderInfo = { + title: '', + }; resources: Resource[]; searchChangeSub: Subscription; @@ -58,6 +62,8 @@ export class ResourcesComponent implements OnInit { this.resources = items.resources; this.totalElement = items.totalCount; + this.pageHeaderInfo.title = `${this.totalElement} ressources trouvées`; + this.paginator.limit = this.resourcesService.limit; this.paginator.pageIndex = this.resourcesService.pageNumber; this.paginator.length = items.totalCount; diff --git a/src/app/models/image-upload.model.ts b/src/app/models/image-upload.model.ts index 0c4a768dc92888a6ef1f8ee5f8f0ceba92f32b4e..26160e8663126e184ff817ee60af6e6c416aa053 100644 --- a/src/app/models/image-upload.model.ts +++ b/src/app/models/image-upload.model.ts @@ -2,4 +2,5 @@ export interface IImageUploadFieldParams { label: string; inputName: string; existingImageUrl?: string; + isRequired?: boolean; } diff --git a/src/app/models/page.model.ts b/src/app/models/page.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..94a75073ebfe5a78ff3286f7dd6c0341153ad309 --- /dev/null +++ b/src/app/models/page.model.ts @@ -0,0 +1,7 @@ +export interface IPageHeaderInfo { + title: string; + metadataSubtitle?: string; + surtitle?: string; + subtitle?: string; + hasBetaStyle?: boolean; +} diff --git a/src/app/services/index.ts b/src/app/services/index.ts index 34d4ee52b65425a4c8e071ecb732d74c314446ec..22c1f82163fa750ff151a10e41d7464774c781ee 100644 --- a/src/app/services/index.ts +++ b/src/app/services/index.ts @@ -3,6 +3,7 @@ import { OrganizationService } from './organization.service'; import { ResourceService } from './resource.service'; import { FormatService } from './format.service'; import { NotificationService } from './notification.service'; +import { NavigationHistoryService } from './navigation-history.service'; export { AppConfigService, @@ -10,6 +11,7 @@ export { ResourceService, FormatService, NotificationService, + NavigationHistoryService, }; // tslint:disable-next-line:variable-name @@ -19,4 +21,5 @@ export const AppServices = [ ResourceService, FormatService, NotificationService, + NavigationHistoryService, ]; diff --git a/src/app/services/navigation-history.service.ts b/src/app/services/navigation-history.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..608c4a52fc5ea94113eb2967ddc079e1b4524f5d --- /dev/null +++ b/src/app/services/navigation-history.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; + +@Injectable() +export class NavigationHistoryService { + history: string[] = []; + maxHistoryLength = 20; // Avoid to store too many url limite back history to 20 + + constructor( + ) { } + + add(url: string) { + // If max size reach remove the oldest url + if (this.history.length >= this.maxHistoryLength) { + this.history.shift(); + } + this.history.push(url); + } + + getFromLast(index: number): string { + const position = this.history.length - 1 - index; + let res = null; + if (position >= 0) { + res = this.history[position]; + } + return res; + } +} diff --git a/src/assets/img/left_arrow.svg b/src/assets/img/left_arrow.svg new file mode 100644 index 0000000000000000000000000000000000000000..ecd6f771dd0432615fe78f566f1e804fd2b5e344 --- /dev/null +++ b/src/assets/img/left_arrow.svg @@ -0,0 +1,3 @@ +<svg width="6" height="10" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M5 1L1 5L5 9" stroke="#818080" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/src/styles.scss b/src/styles.scss index ff7533ca18b7d85d0cdc1cacad4c1407f9e4d9f1..09822331d571d2ba51805064dfcb6a158b662a04 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -137,6 +137,17 @@ textarea.ng-invalid:not(form).ng-touched { } } +.page-container { + min-height: calc(100% - 1rem); + max-width: 100%; + background-color: white; + padding-top: 0; + + @media screen and (min-width: $tablet) { + margin: 1rem 1rem 0 1rem; + } +} + // Style for tables .add-item-link { margin-bottom: 1.25rem; @@ -188,4 +199,8 @@ textarea.ng-invalid:not(form).ng-touched { .is-sortable .column-title { cursor: pointer; } + + .paginator { + border-top: 1px solid $grey-super-light-color; + } }