Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • web-et-numerique/web-et-numerique-internet/data.grandlyon.com/web-portal/components/custom-apps/admin-gui
1 result
Show changes
Showing
with 659 additions and 449 deletions
<ng-container *ngIf="organization">
<app-back-button [route]="'/organizations'" [title]="'Retourner à la liste des organisations'"></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">
......@@ -15,7 +12,7 @@
</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 l'organisation est obligatoire.
Le nom du producteur de données est obligatoire.
</p>
</div>
</div>
......@@ -33,13 +30,13 @@
</div>
<div *ngIf="description.invalid && (description.dirty || description.touched)" class="alert alert-danger">
<p *ngIf="description.errors['required']" class="help is-danger">
La description de l'organisation est obligatoire.
La description du producteur de données est obligatoire.
</p>
</div>
</div>
<div class="field">
<label class="label" for="elasticSearchName">Nom ElasticSearch de l'organisation</label>
<label class="label" for="elasticSearchName">Nom ElasticSearch du producteur de données</label>
<div class="control">
<input class="input" type="text" [value]="organization.elasticSearchName" formControlName="elasticSearchName"
id="elasticSearchName">
......@@ -87,4 +84,4 @@
</div>
</div>
</form>
</ng-container>
\ No newline at end of file
</section>
\ No newline at end of file
......@@ -21,6 +21,7 @@ export class OrganizationFormComponent implements OnInit {
inputName: 'logo',
label: 'Logo',
existingImageUrl: null,
isRequired: true,
};
logo: File;
title: string;
......@@ -125,14 +126,14 @@ export class OrganizationFormComponent implements OnInit {
action.subscribe(
(organizationCreated) => {
this._notificationService.notify({
message: 'L\'organisation a été créée avec succès.',
message: 'Le producteur de données a été créée avec succès.',
type: 'success',
});
this._router.navigate(['/organizations', organizationCreated.id]);
this._router.navigate(['/producteur-de-donnees', organizationCreated.id]);
},
() => {
this._notificationService.notify({
message: 'Une erreur est survenue lors de la création de l\'organisation.',
message: 'Une erreur est survenue lors de la création du producteur de données.',
type: 'error',
});
},
......
<ng-container *ngIf="organizations">
<div>
<div class="section">
<div class="columns is-centered is-marginless">
<div class="column has-text-centered">
<h2>{{ totalElement }} organisations trouvées</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="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>
</div>
<div class="add-item has-text-right">
<a class="button button-gl" [routerLink]="['new']">
Ajouter
</a>
<div class="column is-3">
<span class="column-title">Liens</span>
</div>
<div class="table">
<div class="header columns is-marginless">
<div class="column is-2 has-text-centered">
<span (click)="sortBy('name')" class="is-sortable">
<span class="column-title" [ngClass]="{'active': sortOptions.value === name}">Name</span>
<span *ngIf="sortOptions.value === 'name'" class="has-text-danger">
<i class="fas sort-order-icon" [ngClass]="{'fa-arrow-up': sortOptions.order === 'asc', 'fa-arrow-down': sortOptions.order === 'desc'}"></i>
</span>
</span>
</div>
<div class="column is-2 has-text-centered">
<span class="column-title">Logo</span>
</div>
<div class="column is-4 has-text-centered">
<span class="column-title">Description</span>
</div>
<div class="column is-3 has-text-centered">
<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 has-text-centered">
{{ organization.name}}
</div>
<div class="column is-2 has-text-centered">
<img src="{{organization.logo}}" alt="">
</div>
<div class="column is-4 has-text-justified">
{{ organization.description | slice:0:200}}...
</div>
<div class="column is-3 has-text-centered">
<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>
<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="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="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>
<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>
</div>
\ No newline at end of file
section {
padding: 20px;
}
.section {
padding-top: 0;
}
.table {
background-color: white;
border: 1px solid lightgray;
}
.center {
text-align: center;
}
img {
max-width: 100px;
}
.header {
border-bottom: 1px solid lightgray;
background-color: #fafafa;
span {
color: #999;
}
}
.is-sortable .column-title {
cursor: pointer;
}
.table .columns {
border-bottom: 1px solid lightgray
}
i {
&.title-icon {
margin-right: 0.75rem;
}
&.sort-order-icon {
padding-left: 0.75rem;
cursor: pointer;
}
}
.add-item {
margin-bottom: 20px;
}
......@@ -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;
......@@ -88,7 +94,7 @@ export class OrganizationsComponent implements OnInit {
}
displayDeletePopup(organizationId) {
const pop = confirm('Etes vous sûr de vouloir supprimer cette organisation ?');
const pop = confirm('Etes vous sûr de vouloir supprimer ce producteur de données ?');
if (pop) {
this.organizationsService.delete(organizationId).subscribe(() => {
this.organizationsService.pageNumber = 1;
......
<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
@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;
}
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();
});
});
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);
}
}
}
<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">&hellip;</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>
......
@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);
}
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();
});
});
......@@ -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;
......
<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
......@@ -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);
}
}
<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
......@@ -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,
}));
});
......
<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>
<div class="add-item has-text-right">
<a class="button button-gl" [routerLink]="['new']">
Ajouter
</a>
</div>
<div class="table">
<div class="header columns is-marginless">
<div class="column is-2 has-text-centered">
<span (click)="sortBy('name')" class="is-sortable">
<span class="column-title" [ngClass]="{'active': sortOptions.value === name}">Nom</span>
<span *ngIf="sortOptions.value === 'name'" class="has-text-danger">
<i class="fas sort-order-icon"
[ngClass]="{'fa-arrow-up': sortOptions.order === 'asc', 'fa-arrow-down': sortOptions.order === 'desc'}"></i>
<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="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 has-text-centered">
<span class="column-title">Acronyme</span>
<div class="column is-1">
<span>
{{ resource.acronym}}
</span>
</div>
<div class="column is-1 has-text-centered">
<span class="column-title">Type</span>
<div class="column is-1">
<span>
{{ resource.type}}
</span>
</div>
<div class="column is-4 has-text-centered">
<span class="column-title">Description</span>
<div class="column is-4">
<span>
{{ resource.description | slice:0:300}}
</span>
</div>
<div class="column is-1 has-text-centered">
<span class="column-title">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 class="column-title">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 class="column-title">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>
</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 has-text-centered">
{{ resource.name}}
</div>
<div class="column is-1 has-text-centered">
{{ resource.acronym}}
</div>
<div class="column is-1 has-text-centered">
{{ resource.type}}
</div>
<div class="column is-4 has-text-centered">
{{ resource.description | slice:0:300}}
</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>
<app-crud-buttons [id]="resource.id" (delete)="displayDeletePopup($event)"></app-crud-buttons>
</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
section {
padding: 20px;
}
.section {
padding-top: 0;
}
.table {
background-color: white;
border: 1px solid lightgray;
}
.center {
text-align: center;
}
img {
max-width: 100px;
}
.header {
border-bottom: 1px solid lightgray;
background-color: #fafafa;
span {
color: #999;
}
}
.is-sortable .column-title {
cursor: pointer;
}
.table .columns {
border-bottom: 1px solid lightgray
}
.icon {
height: unset;
}
i {
&.title-icon {
margin-right: 0.75rem;
}
&.sort-order-icon {
padding-left: 0.75rem;
cursor: pointer;
}
}
.add-item {
margin-bottom: 20px;
}
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;
......