Commit 847b5b58 authored by descamps's avatar descamps
Browse files

KDE - 07/12/2021 - Ajout Notice Page accueil

parent 5cc5729a
......@@ -59,6 +59,8 @@ import { UserActionsModule } from './user-actions/user-actions.module';
import { ToastrModule } from 'ngx-toastr';
import { FileTreeModule } from './profile/edit-profile/file-tree/file-tree.module';
import { MainComponent } from './main/main.component';
import {UserActionAddMetadataComponent} from "./user-actions/add-metadata/add-metadata.component";
import {UserActionRemoveMetadataComponent} from "./user-actions/remove-metadata/remove-metadata.component";
/* export function httpLoaderFactory(httpClient: HttpClient): MultiTranslateHttpLoader {
return new MultiTranslateHttpLoader(httpClient, [
......@@ -76,7 +78,9 @@ registerLocaleData(localeFr, 'fr');
@NgModule({
declarations: [
AppComponent,
MainComponent
MainComponent,
UserActionAddMetadataComponent,
UserActionRemoveMetadataComponent
],
imports: [
CoreModule,
......
import { FileNode } from "./file-node";
import {FileNode} from "./file-node";
export interface ProfileResponse{
id:number;
name: string;
profile: FileNode;
notice?: NoticeProfile;
type: string;
export interface ProfileResponse {
id: number;
name: string;
profile: FileNode;
notice?: NoticeProfile;
type: string;
identifier: string;
description?: string;
status?: string;
creationDate: string;
lastUpdate: string;
activationDate?: string;
deactivationDate?: string;
controlSchema?: string;
tenant?: number;
version?: number;
fields?: string[];
path?: string;
format?: string;
}
export interface NoticeProfile{
export interface NoticeProfile {
Description: string;
_id: string;
Name: string;
......
<mat-sidenav-container [autosize]="true" [hasBackdrop]="false">
<mat-sidenav #panel mode="side" position="end" [fixedInViewport]="true">
<profile-preview *ngIf="openedItem" (previewClose)="closePanel()" [inputProfile]="openedItem"></profile-preview>
</mat-sidenav>
<mat-sidenav-content>
......@@ -84,13 +87,14 @@
<div *ngIf="environnement.standalone;else environnement_vitamui" class="vitamui-table-body">
<div class="vitamui-table-rows" *ngFor="let element of retrievedProfiles | filterByType:filterType | filterByStringName:search;">
<div class="vitamui-row d-flex align-items-center">
<div class="col-2">{{element.type}}<i *ngIf="element.type == 'PA'"
<div class="col-2 clickable" (click)="showProfile(element)">
{{element.type}}<i *ngIf="element.type == 'PA'"
class="status-badge-green ml-3"></i>
<i *ngIf="element.type == 'PUA'" class="status-badge-red ml-3"></i>
</div>
<div class="col-3">{{element.id}}</div>
<div class="col-3">{{element.identifier}}</div>
<div class="col-2 mr-3">{{element.lastUpdate}}</div>
<div class="col-3 clickable" (click)="showProfile(element)">{{element.id}}</div>
<div class="col-3 clickable" (click)="showProfile(element)">{{element.identifier}}</div>
<div class="col-2 mr-3 clickable" (click)="showProfile(element)">{{element.lastUpdate}}</div>
<div class="col-2 actions">
<div>
<button class="btn btn-circle primary mr-3" (click)="editProfile(element)">
......@@ -107,14 +111,14 @@
</div>
<ng-template #environnement_vitamui class="vitamui-table-body">
<div class="vitamui-table-rows" *ngFor="let element of retrievedProfiles ">
<div class="vitamui-row d-flex align-items-center">
<div class="col-2">{{element.type}}<i *ngIf="element.status == 'ACTIVE'"
<div (click)="showProfile(element)" class="vitamui-row d-flex align-items-center clickable">
<div class="col-2" >{{element.type}}<i *ngIf="element.status == 'ACTIVE'"
class="status-badge-green ml-3"></i>
<i *ngIf="element.status == 'INACTIVE'" class="status-badge-grey ml-3"></i>
</div>
<div class="col-3">{{element.identifier}}</div>
<div class="col-3">{{element.name}}</div>
<div class="col-2 mr-3">{{element.lastUpdate}}</div>
<div class="col-2" >{{element.lastUpdate}}</div>
<div class="col-2 actions">
<div>
<button class="btn btn-circle primary mr-3" (click)="editProfile(element)">
......
......@@ -40,11 +40,18 @@ import {MatTableDataSource} from '@angular/material/table';
import {NgxUiLoaderService} from 'ngx-ui-loader';
import {ProfileService} from '../../core/services/profile.service';
import {ProfileDescription} from '../../models/profile-description.model';
import {Router} from '@angular/router';
import {ActivatedRoute, Router} from '@angular/router';
import {FileUploader} from 'ng2-file-upload';
import {MetadataHeaders} from '../../core/classes/models';
import {BreadcrumbDataTop} from '../../models/breadcrumb';
import {Direction, StartupService, PageRequest, DEFAULT_PAGE_SIZE} from 'ui-frontend-common';
import {
DEFAULT_PAGE_SIZE,
Direction,
GlobalEventService,
PageRequest,
SidenavPage,
StartupService
} from 'ui-frontend-common';
import {Subject, Subscription} from 'rxjs';
import {environment} from '../../../environments/environment';
......@@ -55,7 +62,7 @@ const URL = 'http://localhost:8080/rest/createprofilefromfile';
templateUrl: './list-profile.component.html',
styleUrls: ['./list-profile.component.scss']
})
export class ListProfileComponent implements OnInit,OnDestroy {
export class ListProfileComponent extends SidenavPage<ProfileDescription> implements OnInit,OnDestroy {
@Input()
uploader: FileUploader = new FileUploader({url: URL});
......@@ -103,9 +110,12 @@ export class ListProfileComponent implements OnInit,OnDestroy {
public breadcrumbDataTop: Array<BreadcrumbDataTop>;
environnement :any;
constructor(private profileService: ProfileService,
private ngxLoader:NgxUiLoaderService, private router:Router,
private startupService: StartupService) { }
private startupService: StartupService ,route: ActivatedRoute, globalEventService: GlobalEventService) {
super(route, globalEventService); }
ngOnInit() {
this.environnement = environment;
......@@ -116,9 +126,18 @@ export class ListProfileComponent implements OnInit,OnDestroy {
// @ts-ignore
this.subscription1$ = this.profileService.getAllProfiles(new PageRequest(0, DEFAULT_PAGE_SIZE,"name",Direction.ASCENDANT)).subscribe(profileList => {
if (profileList) {
profileList.forEach(p => this.retrievedProfiles.push(p));
profileList.forEach(
p => {
if(p.controlSchema){
p.type = "PUA"
}else{
p.type = "PA"
}
this.retrievedProfiles.push(p)
});
console.error("Profiles: ", this.retrievedProfiles);
}
console.error(this.retrievedProfiles)
this.matDataSource = new MatTableDataSource<ProfileDescription>(this.retrievedProfiles);
this.numPA = this.retrievePAorPUA("PA");
this.numPUA = this.retrievePAorPUA("PUA");
......@@ -181,6 +200,8 @@ export class ListProfileComponent implements OnInit,OnDestroy {
}
public onSearchSubmit(search: string): void {
console.log(search)
console.error(new FilterByStringNamePipe().transform(this.retrievedProfiles, search))
this.search = search;
}
......@@ -210,6 +231,10 @@ export class ListProfileComponent implements OnInit,OnDestroy {
}
showProfile(element: ProfileDescription) {
console.log(element)
this.openPanel(element)
}
}
@Pipe({name: 'filterByType'})
......
<form [formGroup]="form" class="side-form" (ngSubmit)="onSubmit()">
<div class="row" >
<div class=" col-6">
<vitamui-common-slide-toggle [formControl]="statusProfile" checked="form.controls.status.value === 'ACTIVE'">
Profile <span *ngIf="form.controls.status.value === 'INACTIVE'">in</span>actif
</vitamui-common-slide-toggle>
</div>
<div class="col-6 mb-3 read-only-field">
<label>type</label>
<div *ngIf="typeProfile==='PA';else pua">Profil d'archivage</div>
<ng-template #pua>Profile Unite Archivistique</ng-template>
</div>
</div>
<div class="row">
<div class="col-10 form-control">
<vitamui-common-input formControlName="name" placeholder="Intitulé"
i18n-placeholder="Name@@profileGroupCreateNamePlaceholder">
</vitamui-common-input>
</div>
</div>
<div class="row">
<div class="col-10 form-control">
<vitamui-common-input formControlName="description" placeholder="Description"
i18n-placeholder="Name@@profileGroupCreateNamePlaceholder">
</vitamui-common-input>
</div>
</div>
<div class="row">
<div class="col-12 mb-3 read-only-field">
<label>Profil attaché</label>
<div *ngIf="isProfileAttache;else pas_profil">Présence d'un profil attaché</div>
<ng-template #pas_profil>Pas de profil attaché</ng-template>
</div>
</div>
<div class="form-group bottom">
<button type="submit" class="btn secondary" [disabled]="isInvalid() || unchanged() || submited">Enregistrer</button>
</div>
</form>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProfileInformationTabComponent } from './profile-information-tab.component';
describe('ProfileInformationTabComponent', () => {
let component: ProfileInformationTabComponent;
let fixture: ComponentFixture<ProfileInformationTabComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ProfileInformationTabComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ProfileInformationTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {diff} from "ui-frontend-common";
import {Observable, of} from "rxjs";
import {catchError, filter, map, switchMap} from "rxjs/operators";
import {extend, isEmpty} from "underscore";
import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
import {ProfileService} from "../../../../core/services/profile.service";
import {ProfileDescription} from "../../../../models/profile-description.model";
@Component({
selector: 'profile-information-tab',
templateUrl: './profile-information-tab.component.html',
styleUrls: ['./profile-information-tab.component.css']
})
export class ProfileInformationTabComponent implements OnInit{
@Output() updated: EventEmitter<boolean> = new EventEmitter<boolean>();
form: FormGroup;
statusProfile = new FormControl();
submited = false;
isProfileAttache : boolean;
typeProfile : string;
private _inputProfile: ProfileDescription;
previousValue = (): ProfileDescription => {
return this._inputProfile;
}
@Input()
set inputProfile(profileDescription: ProfileDescription) {
this._inputProfile = profileDescription;
/** if (!profileDescription.description) {
this._inputProfile.description = '';
}*/
this.resetForm(this.inputProfile);
this.updated.emit(false);
}
get inputProfile(): ProfileDescription {
return this._inputProfile;
}
@Input()
set readOnly(readOnly: boolean) {
if (readOnly && this.form.enabled) {
this.form.disable({emitEvent: false});
} else if (this.form.disabled) {
this.form.enable({emitEvent: false});
this.form.get('identifier').disable({emitEvent: false});
}
}
constructor(private formBuilder: FormBuilder,
private profileService: ProfileService) {
this.form = this.formBuilder.group({
identifier: [null, Validators.required],
id: [null, Validators.required],
type: [null],
description: [null],
name: [null, Validators.required],
creationDate: [null],
status: [null, Validators.required]
});
this.statusProfile.valueChanges.subscribe((value) => {
this.form.controls.status.setValue(value = (value === false) ? 'INACTIVE' : 'ACTIVE');
});
}
isInvalid(): boolean {
return false;
}
isProfiledAttached(inputProfile: ProfileDescription) : boolean{
if(inputProfile.controlSchema != null || inputProfile.path != null)
return true;
}
unchanged(): boolean {
const unchanged = JSON.stringify(diff(this.form.getRawValue(), this.previousValue())) === '{}';
this.updated.emit(!unchanged);
return unchanged;
}
prepareSubmit(): Observable<ProfileDescription> {
let diffValue = diff(this.form.getRawValue(), this.previousValue());
return of(diffValue).pipe(
filter((formData) => !isEmpty(formData)),
map((formData) => extend({id: this.previousValue().id, identifier: this.previousValue().identifier}, formData)),
switchMap((formData: { id: string, [key: string]: any }) => {
console.log(formData);
// @ts-ignore
return this.profileService.uploadProfile(formData).pipe(catchError(() => of(null)));
}));
}
onSubmit() {
this.submited = true;
this.prepareSubmit().subscribe(() => {
this.profileService.getProfile(this._inputProfile).subscribe(
response => {
this.submited = false;
this.inputProfile = response;
}
);
}, () => {
this.submited = false;
});
}
resetForm(profileDescription: ProfileDescription) {
this.statusProfile.setValue(profileDescription.status === 'ACTIVE');
this.form.reset(profileDescription, {emitEvent: false});
}
ngOnInit(): void {
this.isProfileAttache=this.isProfiledAttached(this.inputProfile)
this.typeProfile = this.inputProfile.type
}
}
<div class="vitamui-sidepanel">
<div class="vitamui-sidepanel-header">
<div class="d-flex justify-content-end">
<button class="btn link cancel" (click)="emitClose()">
<i class="vitamui-icon vitamui-icon-close"></i>
</button>
</div>
<div class="title">
<div matTooltipClass="vitamui-tooltip">
<h5 class="m-0 text-primary">{{ inputProfile?.name }}</h5>
<p class="text large light m-0">{{ inputProfile?.identifier }}</p>
</div>
</div>
</div>
<div class="vitamui-sidepanel-body">
<mat-tab-group class="preview-tab-group" #tabs>
<mat-tab label="Notice" i18n-label="Information tab@@ontologyPreviewTabInformation">
<profile-information-tab [inputProfile]="inputProfile" #infoTab
[readOnly]="isPopup" (updated)="updatedChange($event, 0)"></profile-information-tab>
</mat-tab>
<mat-tab label="Historique" i18n-label="History tab@@ontologyPreviewTabHistory">
<vitamui-common-operation-history-tab [id]="inputProfile?.identifier"
[identifier]="inputProfile?.identifier" collectionName="profile">
</vitamui-common-operation-history-tab>
</mat-tab>
</mat-tab-group>
</div>
</div>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProfilePreviewComponent } from './profile-preview.component';
describe('ProfilePreviewComponent', () => {
let component: ProfilePreviewComponent;
let fixture: ComponentFixture<ProfilePreviewComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ProfilePreviewComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ProfilePreviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {AfterViewInit, Component, EventEmitter, HostListener, Input, Output, ViewChild} from '@angular/core';
import {MatTab, MatTabGroup, MatTabHeader} from "@angular/material/tabs";
import {ProfileDescription} from "../../models/profile-description.model";
import {ProfileInformationTabComponent} from "./profile-information-tab/profile-information-tab/profile-information-tab.component";
import {MatDialog} from "@angular/material/dialog";
import {ConfirmActionComponent} from "../../../../../vitamui-library/src/lib/components/confirm-action/confirm-action.component";
import {ProfileService} from "../../core/services/profile.service";
import {Observable} from "rxjs";
@Component({
selector: 'profile-preview',
templateUrl: './profile-preview.component.html',
styleUrls: ['./profile-preview.component.css']
})
export class ProfilePreviewComponent implements AfterViewInit {
@Output()
previewClose: EventEmitter<any> = new EventEmitter();
@Input()
inputProfile: ProfileDescription;
tabUpdated: boolean[] = [false, false];
isPopup: boolean;
@ViewChild('tabs', {static: false}) tabs: MatTabGroup;
tabLinks: Array<ProfileInformationTabComponent> = [];
@ViewChild('infoTab', {static: false}) infoTab: ProfileInformationTabComponent;
@HostListener('window:beforeunload', ['$event'])
beforeunloadHandler(event: any) {
if (this.tabUpdated[this.tabs.selectedIndex]) {
event.preventDefault();
this.checkBeforeExit();
return '';
}
}
constructor(private matDialog: MatDialog, private profileService: ProfileService) {
}
ngAfterViewInit() {
this.tabs._handleClick = this.interceptTabChange.bind(this);
this.tabLinks[0] = this.infoTab;
}
updatedChange(updated: boolean, index: number) {
this.tabUpdated[index] = updated;
}
async checkBeforeExit() {
if (await this.confirmAction()) {
const submitProfileUpdate: Observable<ProfileDescription> = this.tabLinks[this.tabs.selectedIndex].prepareSubmit();
submitProfileUpdate.subscribe(() => {
this.profileService.getProfile(this.inputProfile).subscribe(
response => {
this.inputProfile = response;
}
);
});
} else {
this.tabLinks[this.tabs.selectedIndex].resetForm(this.inputProfile);
}
}
async interceptTabChange(tab: MatTab, tabHeader: MatTabHeader, idx: number) {
if (this.tabUpdated[this.tabs.selectedIndex]) {
await this.checkBeforeExit();
}
const args = [tab, tabHeader, idx];
return MatTabGroup.prototype._handleClick.apply(this.tabs, args);
}
async confirmAction(): Promise<boolean> {
const dialog = this.matDialog.open(ConfirmActionComponent, {panelClass: 'vitamui-confirm-dialog'});
dialog.componentInstance.dialogType = 'changeTab';
return await dialog.afterClosed().toPromise();
}
async emitClose() {
if (this.tabUpdated[this.tabs.selectedIndex]) {
await this.checkBeforeExit();
}