Merge remote-tracking branch 'origin/master' into refactor

This commit is contained in:
Adina Țeudan 2021-11-17 20:15:11 +02:00
commit 3fd9d12526
18 changed files with 80 additions and 47 deletions

View File

@ -157,12 +157,12 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<IFi
async save() {
const newPrimary = !!this.activeFields.find(attr => attr.primaryAttribute);
let fileAttributeConfigs = this.data.existingConfiguration.fileAttributeConfigs;
let fileAttributeConfigs = this.data.existingConfiguration.fileAttributeConfigs ?? [];
if (newPrimary) {
fileAttributeConfigs = fileAttributeConfigs.map(attr => new FileAttributeConfig({ ...attr, primaryAttribute: false }));
}
const fileAttributes = {
const fileAttributes: IFileAttributesConfig = {
...this.baseConfigForm.getRawValue(),
fileAttributeConfigs: [
...fileAttributeConfigs.filter(a => !this.allEntities.find(entity => entity.csvColumn === a.csvColumnHeader)),
@ -173,12 +173,14 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<IFi
label: field.name,
type: field.type,
primaryAttribute: field.primaryAttribute,
displayedInFileList: null,
filterable: null,
})),
],
};
try {
await this._fileAttributesService.setFileAttributesConfig(fileAttributes, this.data.dossierTemplateId).toPromise();
await this._fileAttributesService.setFileAttributeConfig(fileAttributes, this.data.dossierTemplateId).toPromise();
this._toaster.success(_('file-attributes-csv-import.save.success'), { params: { count: this.activeFields.length } });
} catch (e) {
this._toaster.error(_('file-attributes-csv-import.save.error'));

View File

@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router';
import { CompositeRouteGuard } from '@iqser/common-ui';
import { SearchScreenComponent } from './screens/search-screen/search-screen.component';
import { FilePreviewScreenComponent } from './screens/file-preview-screen/file-preview-screen.component';
import { FilesGuard } from './utils/file.guard';
const routes: Routes = [
{
@ -17,6 +18,7 @@ const routes: Routes = [
{
path: ':dossierId/file/:fileId',
component: FilePreviewScreenComponent,
canActivate: [FilesGuard],
data: {
reuse: true,
},

View File

@ -40,6 +40,7 @@ import { OverlayModule } from '@angular/cdk/overlay';
import { SharedDossiersModule } from './shared/shared-dossiers.module';
import { PlatformSearchService } from './shared/services/platform-search.service';
import { ResizeAnnotationDialogComponent } from './dialogs/resize-annotation-dialog/resize-annotation-dialog.component';
import { FilesGuard } from './utils/file.guard';
const screens = [FilePreviewScreenComponent, SearchScreenComponent];
@ -90,7 +91,7 @@ const services = [
@NgModule({
declarations: [...components],
providers: [...services],
providers: [...services, FilesGuard],
imports: [CommonModule, SharedModule, SharedDossiersModule, FileUploadDownloadModule, DossiersRoutingModule, OverlayModule],
})
export class DossiersModule {}

View File

@ -5,8 +5,9 @@ import { DossiersService } from '@services/entity-services/dossiers.service';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
import { FilesService } from '@services/entity-services/files.service';
import { Observable } from 'rxjs';
import { distinctUntilChanged, map } from 'rxjs/operators';
import { map, switchMapTo } from 'rxjs/operators';
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
import { FilesMapService } from '@services/entity-services/files-map.service';
@Component({
selector: 'redaction-dossier-details-stats',
@ -29,14 +30,15 @@ export class DossierDetailsStatsComponent implements OnInit {
private readonly _dialogService: DossiersDialogService,
private readonly _filesService: FilesService,
private readonly _dossierStatsService: DossierStatsService,
private readonly _filesMapService: FilesMapService,
readonly dossiersService: DossiersService,
) {}
ngOnInit() {
this.dossierStats$ = this._dossierStatsService.watch$(this.dossier.dossierId);
this.deletedFilesCount$ = this._filesService.getDeletedFilesFor(this.dossier.id).pipe(
this.deletedFilesCount$ = this._filesMapService.get$(this.dossier.dossierId).pipe(
switchMapTo(this._filesService.getDeletedFilesFor(this.dossier.id)),
map(files => files.length),
distinctUntilChanged(),
);
}

View File

@ -33,7 +33,7 @@
<div class="mt-16">
<div class="all-caps-label" translate="dossier-details.members"></div>
<redaction-team-members
(openAssignDossierMembersDialog)="openAssignDossierMembersDialog.emit()"
(openAssignDossierMembersDialog)="openEditDossierDialog(dossier, 'members')"
[memberIds]="dossier.memberIds"
[perLine]="9"
></redaction-team-members>
@ -66,7 +66,7 @@
<div [class.mt-24]="!stats.hasFiles" class="pb-32">
<redaction-dossier-details-stats
(openDossierDictionaryDialog)="openDossierDictionaryDialog.emit()"
(openDossierDictionaryDialog)="openEditDossierDialog(dossier, 'dossierDictionary')"
[dossierAttributes]="dossierAttributes"
[dossier]="dossier"
></redaction-dossier-details-stats>

View File

@ -12,6 +12,7 @@ import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
import { pluck, switchMap } from 'rxjs/operators';
import { DossiersDialogService } from '../../../../services/dossiers-dialog.service';
@Component({
selector: 'redaction-dossier-details',
@ -22,8 +23,6 @@ import { pluck, switchMap } from 'rxjs/operators';
export class DossierDetailsComponent {
editingOwner = false;
@Input() dossierAttributes: DossierAttributeWithValue[];
@Output() readonly openAssignDossierMembersDialog = new EventEmitter();
@Output() readonly openDossierDictionaryDialog = new EventEmitter();
@Output() readonly toggleCollapse = new EventEmitter();
collapseTooltip = _('dossier-details.collapse');
expandTooltip = _('dossier-details.expand');
@ -43,6 +42,7 @@ export class DossierDetailsComponent {
private readonly _userService: UserService,
private readonly _dossierStatsService: DossierStatsService,
private readonly _toaster: Toaster,
private readonly _dialogService: DossiersDialogService,
activatedRoute: ActivatedRoute,
) {
this.dossierId = activatedRoute.snapshot.paramMap.get('dossierId');
@ -77,4 +77,11 @@ export class DossierDetailsComponent {
const dossierName = dossier.dossierName;
this._toaster.info(_('assignment.owner'), { params: { ownerName, dossierName } });
}
openEditDossierDialog(dossier: Dossier, section: string): void {
const data = { dossierId: this.dossierId, section };
this._dialogService.openDialog('editDossier', null, data, async () => {
await this.appStateService.getFiles(dossier);
});
}
}

View File

@ -46,8 +46,6 @@
<div [class.collapsed]="collapsedDetails" class="right-container" iqserHasScrollbar>
<redaction-dossier-details
(openAssignDossierMembersDialog)="openAssignDossierMembersDialog()"
(openDossierDictionaryDialog)="openDossierDictionaryDialog()"
(toggleCollapse)="collapsedDetails = !collapsedDetails"
[dossierAttributes]="dossierAttributes"
></redaction-dossier-details>

View File

@ -20,7 +20,6 @@ import * as moment from 'moment';
import { Observable, timer } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import { convertFiles, Files, handleFileDrop } from '@utils/index';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import {
CircleButtonTypes,
DefaultListingServices,
@ -84,7 +83,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
private readonly _dossiersService: DossiersService,
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _appConfigService: AppConfigService,
private readonly _dialogService: DossiersDialogService,
private readonly _fileUploadService: FileUploadService,
private readonly _statusOverlayService: StatusOverlayService,
private readonly _fileDropOverlayService: FileDropOverlayService,
@ -150,7 +148,10 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
this.addSubscription = this._fileMapService
.get$(this.dossierId)
.pipe(tap(files => this.entitiesService.setEntities(files)))
.pipe(
tap(files => this.entitiesService.setEntities(files)),
tap(() => this._computeAllFilters()),
)
.subscribe();
this._fileDropOverlayService.initFileDropHandling(this.dossierId);
@ -226,20 +227,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
(this._fileInput as any).nativeElement.value = null;
}
openAssignDossierMembersDialog(): void {
const data = { dossierId: this.dossierId, section: 'members' };
this._dialogService.openDialog('editDossier', null, data, async () => {
await this.reloadFiles();
});
}
openDossierDictionaryDialog() {
const data = { dossierId: this.dossierId, section: 'dossierDictionary' };
this._dialogService.openDialog('editDossier', null, data, async () => {
await this.reloadFiles();
});
}
recentlyModifiedChecker = (file: File) =>
moment(file.lastUpdated).add(this._appConfigService.values.RECENT_PERIOD_IN_HOURS, 'hours').isAfter(moment());

View File

@ -1,6 +1,7 @@
<div>
<redaction-simple-doughnut-chart
[config]="dossiersChartData$ | async"
*ngIf="dossiersChartData$ | async as config"
[config]="config"
[radius]="80"
[strokeWidth]="15"
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate"

View File

@ -3,7 +3,7 @@ import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/si
import { FilterService, mapEach } from '@iqser/common-ui';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { combineLatest, Observable } from 'rxjs';
import { Dossier, DossierStats, DossierStatuses, FileCountPerWorkflowStatus, StatusSorter } from '@red/domain';
import { Dossier, DossierStats, FileCountPerWorkflowStatus, StatusSorter } from '@red/domain';
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
import { TranslateChartService } from '@services/translate-chart.service';
import { filter, map, switchMap } from 'rxjs/operators';
@ -33,16 +33,15 @@ export class DossiersListingDetailsComponent {
map(stats => this._toChartData(stats)),
);
this.dossiersChartData$ = this.dossiersService.all$.pipe(map(dossiers => this._toDossierChartData(dossiers)));
this.dossiersChartData$ = this.dossiersService.all$.pipe(switchMap(dossiers => this._toDossierChartData(dossiers)));
}
private _toDossierChartData(dossiers: Dossier[]): DoughnutChartConfig[] {
const activeDossiersCount = dossiers.filter(p => p.status === DossierStatuses.ACTIVE).length;
const inactiveDossiersCount = dossiers.length - activeDossiersCount;
private async _toDossierChartData(dossiers: Dossier[]): Promise<DoughnutChartConfig[]> {
// TODO: deleted dossiers count should come with stats
const deletedDossiers = await this.dossiersService.getDeleted();
return [
{ value: activeDossiersCount, color: 'ACTIVE', label: _('active') },
{ value: inactiveDossiersCount, color: 'DELETED', label: _('archived') },
{ value: dossiers.length, color: 'ACTIVE', label: _('active') },
{ value: deletedDossiers.length, color: 'DELETED', label: _('archived') },
];
}

View File

@ -0,0 +1,32 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
import { FilesMapService } from '@services/entity-services/files-map.service';
import { AppStateService } from '@state/app-state.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
@Injectable()
export class FilesGuard implements CanActivate {
constructor(
private readonly _filesMapService: FilesMapService,
private readonly _dossiersService: DossiersService,
private readonly _appStateService: AppStateService,
private readonly _router: Router,
) {}
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
const dossierId = route.paramMap.get('dossierId');
const fileId = route.paramMap.get('fileId');
if (!this._filesMapService.get(dossierId, fileId)) {
const dossier = this._dossiersService.find(dossierId);
await this._appStateService.getFiles(dossier);
if (!this._filesMapService.get(dossierId, fileId)) {
await this._router.navigate([dossier.routerLink]);
return false;
}
}
return true;
}
}

View File

@ -41,7 +41,7 @@ export class DossiersService extends EntitiesService<Dossier, IDossier> {
return combineLatest([dossier$, stats$]).pipe(
map(([updatedDossier]) => new Dossier(updatedDossier)),
tap(newDossier => this.replace(newDossier)),
tap(newDossier => this.replace([newDossier])),
catchError(showToast),
);
}

View File

@ -13,6 +13,10 @@ export class FilesMapService {
constructor(private readonly _filesService: FilesService) {}
get$(dossierId: string) {
if (!this._map.has(dossierId)) {
this._map.set(dossierId, new BehaviorSubject<File[]>([]));
}
return this._map.get(dossierId).asObservable();
}

View File

@ -56,7 +56,7 @@ export class UserService extends EntitiesService<User, IUser> {
const userId = (<{ sub: string }>decoded).sub;
const roles = this._keycloakService.getUserRoles(true).filter(role => role.startsWith('RED_'));
this.replace(new User(await this._keycloakService.loadUserProfile(true), roles, userId));
this.replace([new User(await this._keycloakService.loadUserProfile(true), roles, userId)]);
this._currentUser$.next(this.find(userId));
}

View File

@ -112,9 +112,7 @@ export class AppStateService {
const dossierIds = dossiers.map(dossier => dossier.dossierId);
await this._dossierStatsService.getFor(dossierIds).toPromise();
dossiers.forEach(dossier => {
this._dossiersService.replace(new Dossier(dossier));
});
this._dossiersService.replace(dossiers.map(dossier => new Dossier(dossier)));
}
async reloadFile(dossierId: string, fileId: string) {
@ -175,7 +173,7 @@ export class AppStateService {
await this._fileAttributesService.getFileAttributesConfig(dossierTemplateId).toPromise();
const newDossierTemplate = new DossierTemplate(dossierTemplate);
this._dossierTemplatesService.replace(newDossierTemplate);
this._dossierTemplatesService.replace([newDossierTemplate]);
await this.refreshDossierTemplateDictionaryData(dossierTemplateId);
}

@ -1 +1 @@
Subproject commit 74fcbf080b593622220bb2c7de08f69163acab04
Subproject commit 17c65675b934698a61a2c80435f532e5a77f0c97

View File

@ -1,6 +1,6 @@
{
"name": "redaction",
"version": "3.25.0",
"version": "3.30.0",
"private": true,
"license": "MIT",
"scripts": {

Binary file not shown.