Merge branch 'master' into VM/RED-2614
This commit is contained in:
commit
b36f1ebbab
@ -117,9 +117,10 @@ export class FileDataModel {
|
||||
const relevantChanges = redactionLogEntry.changes.filter(change => moment(change.dateTime).valueOf() > viewTime);
|
||||
// at least one unseen change
|
||||
if (relevantChanges.length > 0) {
|
||||
// at least 1 relevant change
|
||||
wrapper.changeLogType = relevantChanges[relevantChanges.length - 1].type;
|
||||
wrapper.isChangeLogEntry = true;
|
||||
viewedPage.hasChanges = true;
|
||||
viewedPage.showAsUnseen = moment(viewedPage.viewedTime).valueOf() < moment(lastChange.dateTime).valueOf();
|
||||
this.hasChangeLog = true;
|
||||
} else {
|
||||
// no relevant changes - hide removed anyway
|
||||
|
||||
@ -127,7 +127,6 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
|
||||
.setFileAttributesConfig(newValue, this._dossierTemplatesService.activeDossierTemplateId)
|
||||
.toPromise()
|
||||
.catch(error => {
|
||||
console.log('error');
|
||||
if (error.status === HttpStatusCode.Conflict) {
|
||||
this._toaster.error(_('file-attributes-listing.error.conflict'));
|
||||
} else {
|
||||
|
||||
@ -16,12 +16,16 @@
|
||||
class="iqser-input-group"
|
||||
>
|
||||
<label>{{ attr.label }}</label>
|
||||
<input
|
||||
|
||||
<ng-container
|
||||
*ngIf="isSpecificType(attr, dossierAttributeConfigTypes.NUMBER) || isSpecificType(attr, dossierAttributeConfigTypes.TEXT)"
|
||||
[formControlName]="attr.id"
|
||||
[name]="attr.id"
|
||||
[type]="isSpecificType(attr, dossierAttributeConfigTypes.NUMBER) ? 'number' : 'text'"
|
||||
/>
|
||||
>
|
||||
<input
|
||||
[formControlName]="attr.id"
|
||||
[name]="attr.id"
|
||||
[type]="isSpecificType(attr, dossierAttributeConfigTypes.NUMBER) ? 'number' : 'text'"
|
||||
/>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="isSpecificType(attr, dossierAttributeConfigTypes.DATE)">
|
||||
<input [formControlName]="attr.id" [matDatepicker]="picker" placeholder="dd/mm/yy" />
|
||||
|
||||
@ -53,7 +53,7 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
return this.form?.valid;
|
||||
return !!this.form?.valid;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -66,7 +66,9 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
|
||||
async save(): EditDossierSaveResult {
|
||||
const dossierAttributeList = this.attributes.map(attr => ({
|
||||
dossierAttributeConfigId: attr.id,
|
||||
value: this.currentAttrValue(attr),
|
||||
value: this.isSpecificType(attr, DossierAttributeConfigTypes.DATE)
|
||||
? moment(this.currentAttrValue(attr)).format('YYYY-MM-DD')
|
||||
: this.currentAttrValue(attr),
|
||||
}));
|
||||
try {
|
||||
await this._dossierAttributesService.setAttributes(this.dossier, dossierAttributeList).toPromise();
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
[config]="config"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate"
|
||||
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate: { count: config[0].value }"
|
||||
></redaction-simple-doughnut-chart>
|
||||
|
||||
<div *ngIf="dossiersService.generalStats$ | async as stats" class="dossier-stats-container">
|
||||
@ -12,7 +12,7 @@
|
||||
<mat-icon svgIcon="red:needs-work"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ stats.totalAnalyzedPages | number }}</div>
|
||||
<div translate="dossier-listing.stats.analyzed-pages"></div>
|
||||
<div [translateParams]="{ count: stats.totalAnalyzedPages }" [translate]="'dossier-listing.stats.analyzed-pages'"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -161,7 +161,7 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
|
||||
hasOnlyManualRedactionsAndIsExcluded(pageNumber: number): boolean {
|
||||
const hasOnlyManualRedactions = this.displayedAnnotations.get(pageNumber).every(annotation => annotation.manual);
|
||||
const hasOnlyManualRedactions = this.displayedAnnotations.get(pageNumber)?.every(annotation => annotation.manual);
|
||||
return hasOnlyManualRedactions && this.file.excludedPages.includes(pageNumber);
|
||||
}
|
||||
|
||||
@ -207,7 +207,7 @@ export class FileWorkloadComponent {
|
||||
// Disable annotation navigation in multi select mode
|
||||
// => TODO: maybe implement selection on enter?
|
||||
if (!this.multiSelectService.isActive) {
|
||||
this._navigateAnnotations($event);
|
||||
this.navigateAnnotations($event);
|
||||
}
|
||||
} else {
|
||||
this._navigatePages($event);
|
||||
@ -276,38 +276,11 @@ export class FileWorkloadComponent {
|
||||
this.selectPage.emit(this._nextPageWithAnnotations());
|
||||
}
|
||||
|
||||
private _disableMultiSelectAndDocumentInfo(): void {
|
||||
this.multiSelectService.deactivate();
|
||||
this.documentInfoService.hide();
|
||||
}
|
||||
|
||||
private _filterAnnotations(
|
||||
annotations: AnnotationWrapper[],
|
||||
primary: INestedFilter[],
|
||||
secondary: INestedFilter[] = [],
|
||||
): Map<number, AnnotationWrapper[]> {
|
||||
if (!primary) {
|
||||
return;
|
||||
}
|
||||
this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary);
|
||||
this.displayedPages = [...this.displayedAnnotations.keys()];
|
||||
return this.displayedAnnotations;
|
||||
}
|
||||
|
||||
private _selectFirstAnnotationOnCurrentPageIfNecessary() {
|
||||
if (
|
||||
(!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) &&
|
||||
this.displayedPages.indexOf(this.activeViewerPage) >= 0
|
||||
) {
|
||||
this.selectAnnotations.emit([this.activeAnnotations[0]]);
|
||||
}
|
||||
}
|
||||
|
||||
private _navigateAnnotations($event: KeyboardEvent) {
|
||||
navigateAnnotations($event: KeyboardEvent) {
|
||||
if (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) {
|
||||
if (this.displayedPages.indexOf(this.activeViewerPage) !== -1) {
|
||||
// Displayed page has annotations
|
||||
return this.selectAnnotations.emit([this.activeAnnotations[0]]);
|
||||
return this.selectAnnotations.emit(this.activeAnnotations ? [this.activeAnnotations[0]] : null);
|
||||
}
|
||||
// Displayed page doesn't have annotations
|
||||
if ($event.key === 'ArrowDown') {
|
||||
@ -354,6 +327,34 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private _disableMultiSelectAndDocumentInfo(): void {
|
||||
this.multiSelectService.deactivate();
|
||||
this.documentInfoService.hide();
|
||||
}
|
||||
|
||||
private _filterAnnotations(
|
||||
annotations: AnnotationWrapper[],
|
||||
primary: INestedFilter[],
|
||||
secondary: INestedFilter[] = [],
|
||||
): Map<number, AnnotationWrapper[]> {
|
||||
if (!primary || primary.length === 0) {
|
||||
this.displayedPages = Array.from({ length: this.file?.numberOfPages }, (x, i) => i + 1);
|
||||
return;
|
||||
}
|
||||
this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary);
|
||||
this.displayedPages = [...this.displayedAnnotations.keys()];
|
||||
return this.displayedAnnotations;
|
||||
}
|
||||
|
||||
private _selectFirstAnnotationOnCurrentPageIfNecessary() {
|
||||
if (
|
||||
(!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) &&
|
||||
this.displayedPages.indexOf(this.activeViewerPage) >= 0
|
||||
) {
|
||||
this.selectAnnotations.emit([this.activeAnnotations[0]]);
|
||||
}
|
||||
}
|
||||
|
||||
private _navigatePages($event: KeyboardEvent) {
|
||||
const pageIdx = this.displayedPages.indexOf(this.activeViewerPage);
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
|
||||
@Output() readonly pageSelected = new EventEmitter<number>();
|
||||
|
||||
pageReadTimeout: number = null;
|
||||
read = false;
|
||||
|
||||
constructor(
|
||||
private readonly _viewedPagesService: ViewedPagesService,
|
||||
@ -39,16 +40,17 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
|
||||
return this.viewedPages?.find(p => p.page === this.number);
|
||||
}
|
||||
|
||||
get read() {
|
||||
private _setReadState() {
|
||||
const activePage = this.activePage;
|
||||
if (!activePage) {
|
||||
return false;
|
||||
this.read = false;
|
||||
} else {
|
||||
return !activePage.hasChanges;
|
||||
this.read = !activePage.showAsUnseen;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this._setReadState();
|
||||
this.handlePageRead();
|
||||
}
|
||||
|
||||
@ -83,10 +85,11 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
|
||||
private async _markPageRead() {
|
||||
await this._viewedPagesService.addPage({ page: this.number }, this.file.dossierId, this.file.fileId).toPromise();
|
||||
if (this.activePage) {
|
||||
this.activePage.hasChanges = false;
|
||||
this.activePage.showAsUnseen = false;
|
||||
} else {
|
||||
this.viewedPages?.push({ page: this.number, fileId: this.file.fileId });
|
||||
}
|
||||
this._setReadState();
|
||||
}
|
||||
|
||||
private async _markPageUnread() {
|
||||
@ -95,5 +98,6 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
|
||||
this.viewedPages?.findIndex(p => p.page === this.number),
|
||||
1,
|
||||
);
|
||||
this._setReadState();
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,6 @@ export class PdfViewerComponent implements OnInit, OnChanges {
|
||||
annotationManager: Core.AnnotationManager;
|
||||
utils: PdfViewerUtils;
|
||||
private _selectedText = '';
|
||||
private _firstPageChange = true;
|
||||
|
||||
constructor(
|
||||
@Inject(BASE_HREF) private readonly _baseHref: string,
|
||||
@ -248,15 +247,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
|
||||
if (this.shouldDeselectAnnotationsOnPageChange) {
|
||||
this.utils.deselectAllAnnotations();
|
||||
}
|
||||
if (this._firstPageChange && pageNumber === 1) {
|
||||
this._firstPageChange = false;
|
||||
const routePageNumber = this._activatedRoute.snapshot.queryParams.page;
|
||||
if (pageNumber) {
|
||||
this.utils.navigateToPage(parseInt(routePageNumber, 10));
|
||||
}
|
||||
} else {
|
||||
this._ngZone.run(() => this.pageChanged.emit(pageNumber));
|
||||
}
|
||||
this._ngZone.run(() => this.pageChanged.emit(pageNumber));
|
||||
this._handleCustomActions();
|
||||
});
|
||||
|
||||
@ -309,7 +300,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
|
||||
private _setInitialDisplayMode() {
|
||||
this.instance.UI.setFitMode('FitPage');
|
||||
const instanceDisplayMode = this.documentViewer.getDisplayModeManager().getDisplayMode();
|
||||
instanceDisplayMode.mode = this.viewModeService.isStandard ? 'Single' : 'Facing';
|
||||
instanceDisplayMode.mode = this.viewModeService.isCompare ? 'Facing' : 'Single';
|
||||
this.documentViewer.getDisplayModeManager().setDisplayMode(instanceDisplayMode);
|
||||
}
|
||||
|
||||
@ -648,8 +639,9 @@ export class PdfViewerComponent implements OnInit, OnChanges {
|
||||
private _setReadyAndInitialState(): void {
|
||||
this._ngZone.run(() => {
|
||||
this.utils.ready = true;
|
||||
this._firstPageChange = true;
|
||||
this.viewerReady.emit(this.instance);
|
||||
const routePageNumber = this._activatedRoute.snapshot.queryParams.page;
|
||||
this.pageChanged.emit(routePageNumber || 1);
|
||||
this._setInitialDisplayMode();
|
||||
this._updateTooltipsVisibility();
|
||||
});
|
||||
|
||||
@ -95,7 +95,11 @@
|
||||
icon="red:needs-work"
|
||||
></iqser-empty-state>
|
||||
|
||||
<redaction-document-info *ngIf="viewDocumentInfo$ | async" [dossier]="dossier" [file]="file"></redaction-document-info>
|
||||
<redaction-document-info
|
||||
*ngIf="documentInfoService.shown$ | async"
|
||||
[dossier]="dossier"
|
||||
[file]="file"
|
||||
></redaction-document-info>
|
||||
|
||||
<redaction-file-workload
|
||||
#fileWorkloadComponent
|
||||
|
||||
@ -48,7 +48,15 @@ import { ReanalysisService } from '../../../../services/reanalysis.service';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
import PDFNet = Core.PDFNet;
|
||||
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f', 'ArrowUp', 'ArrowDown'];
|
||||
|
||||
function diff<T>(first: readonly T[], second: readonly T[]): T[] {
|
||||
// symmetrical difference between two arrays
|
||||
const a = new Set(first);
|
||||
const b = new Set(second);
|
||||
|
||||
return [...first.filter(x => !b.has(x)), ...second.filter(x => !a.has(x))];
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: './file-preview-screen.component.html',
|
||||
@ -63,14 +71,14 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
shouldDeselectAnnotationsOnPageChange = true;
|
||||
fileData: FileDataModel;
|
||||
annotationData: AnnotationData;
|
||||
selectedAnnotations: AnnotationWrapper[];
|
||||
selectedAnnotations: AnnotationWrapper[] = [];
|
||||
hideSkipped = false;
|
||||
displayPdfViewer = false;
|
||||
activeViewerPage: number = null;
|
||||
@ViewChild(PdfViewerComponent) readonly viewerComponent: PdfViewerComponent;
|
||||
readonly dossierId: string;
|
||||
readonly canPerformAnnotationActions$: Observable<boolean>;
|
||||
readonly dossier$: Observable<Dossier>;
|
||||
readonly viewDocumentInfo$: Observable<boolean>;
|
||||
readonly file$: Observable<File>;
|
||||
readonly fileId: string;
|
||||
ready = false;
|
||||
@ -121,7 +129,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}),
|
||||
shareLast(),
|
||||
);
|
||||
this.viewDocumentInfo$ = this._viewDocumentInfo$;
|
||||
this.canPerformAnnotationActions$ = this._canPerformAnnotationActions$;
|
||||
|
||||
document.documentElement.addEventListener('fullscreenchange', () => {
|
||||
@ -139,24 +146,17 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
get activeViewerPage(): number {
|
||||
private _setActiveViewerPage() {
|
||||
const currentPage = this._instance?.Core.documentViewer?.getCurrentPage();
|
||||
if (!currentPage) {
|
||||
return 0;
|
||||
this.activeViewerPage = 1;
|
||||
} else {
|
||||
this.activeViewerPage = this.viewModeService.isCompare
|
||||
? currentPage % 2 === 0
|
||||
? currentPage / 2
|
||||
: (currentPage + 1) / 2
|
||||
: currentPage;
|
||||
}
|
||||
return this.viewModeService.isStandard ? currentPage : currentPage % 2 === 0 ? currentPage / 2 : (currentPage + 1) / 2;
|
||||
}
|
||||
|
||||
private get _viewDocumentInfo$() {
|
||||
return this.documentInfoService.shown$.pipe(
|
||||
tap(value => {
|
||||
if (value) {
|
||||
this.multiSelectService.deactivate();
|
||||
this.excludedPagesService.hide();
|
||||
}
|
||||
}),
|
||||
shareDistinctLast(),
|
||||
);
|
||||
}
|
||||
|
||||
private get _canPerformAnnotationActions$() {
|
||||
@ -246,8 +246,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
console.log(`[REDACTION] Delete previous annotations time: ${new Date().getTime() - startTime} ms`);
|
||||
}
|
||||
console.log(`[REDACTION] Delete previous annotations time: ${new Date().getTime() - startTime} ms`);
|
||||
const processStartTime = new Date().getTime();
|
||||
const dossier = this._dossiersService.find(this.dossierId);
|
||||
const newAnnotationsData = this.fileData.getAnnotations(
|
||||
@ -275,11 +275,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
filters: processFilters(secondaryFilters, AnnotationProcessingService.secondaryAnnotationFilters(this.fileData?.viewedPages)),
|
||||
});
|
||||
console.log(`[REDACTION] Process time: ${new Date().getTime() - processStartTime} ms`);
|
||||
console.log(
|
||||
`[REDACTION] Annotation Redraw and filter rebuild time: ${new Date().getTime() - startTime} ms for: ${
|
||||
this.annotations.length
|
||||
} annotations`,
|
||||
);
|
||||
console.log(`[REDACTION] Filter rebuild time: ${new Date().getTime() - startTime}`);
|
||||
console.log();
|
||||
}
|
||||
|
||||
handleAnnotationSelected(annotationIds: string[]) {
|
||||
@ -294,12 +291,12 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
@Debounce(0)
|
||||
@Debounce(10)
|
||||
selectAnnotations(annotations?: AnnotationWrapper[]) {
|
||||
if (annotations) {
|
||||
this.viewerComponent?.utils.selectAnnotations(annotations, this.multiSelectService.isActive);
|
||||
this.viewerComponent?.utils?.selectAnnotations(annotations, this.multiSelectService.isActive);
|
||||
} else {
|
||||
this.viewerComponent?.utils.deselectAllAnnotations();
|
||||
this.viewerComponent?.utils?.deselectAllAnnotations();
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +322,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
response.manualRedactionEntryWrapper.rectId,
|
||||
);
|
||||
this._instance.Core.annotationManager.deleteAnnotation(annotation);
|
||||
await this._filesService.reload(this.dossierId, this.fileId).toPromise();
|
||||
// await this._filesService.reload(this.dossierId, this.fileId).toPromise();
|
||||
const distinctPages = manualRedactionEntryWrapper.manualRedactionEntry.positions
|
||||
.map(p => p.page)
|
||||
.filter((item, pos, self) => self.indexOf(item) === pos);
|
||||
@ -357,9 +354,17 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return;
|
||||
}
|
||||
|
||||
if (['ArrowUp', 'ArrowDown'].includes($event.key)) {
|
||||
if (this.selectedAnnotations.length === 1) {
|
||||
this._workloadComponent.navigateAnnotations($event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (['Escape'].includes($event.key)) {
|
||||
this.fullScreen = false;
|
||||
this.closeFullScreen();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
if (['f', 'F'].includes($event.key)) {
|
||||
@ -370,8 +375,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this.toggleFullScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
viewerPageChanged($event: any) {
|
||||
@ -388,9 +391,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
const extras: NavigationExtras = {
|
||||
queryParams: { page: $event },
|
||||
queryParamsHandling: 'merge',
|
||||
replaceUrl: true,
|
||||
};
|
||||
this._router.navigate([], extras).then();
|
||||
|
||||
this._setActiveViewerPage();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
@ -410,7 +415,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
if (pageNumber) {
|
||||
setTimeout(() => {
|
||||
this.selectPage(parseInt(pageNumber, 10));
|
||||
this._setActiveViewerPage();
|
||||
this._scrollViews();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
this._loadingService.stop();
|
||||
});
|
||||
} else {
|
||||
@ -476,7 +483,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
private _setHiddenPropertyToNewAnnotations(newAnnotations: AnnotationWrapper[], oldAnnotations: AnnotationWrapper[]) {
|
||||
newAnnotations.map(newAnnotation => {
|
||||
newAnnotations.forEach(newAnnotation => {
|
||||
const oldAnnotation = oldAnnotations.find(a => a.annotationId === newAnnotation.annotationId);
|
||||
if (oldAnnotation) {
|
||||
newAnnotation.hidden = oldAnnotation.hidden;
|
||||
@ -504,7 +511,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
this._instance.Core.documentViewer.refreshAll();
|
||||
this._instance.Core.documentViewer.updateView([this.activeViewerPage], this.activeViewerPage);
|
||||
this._changeDetectorRef.detectChanges();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
private async _stampPreview(document: PDFNet.PDFDoc, dossierTemplateId: string) {
|
||||
@ -547,8 +554,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
.subscribe(async file => {
|
||||
await this._loadFileData(file, !this._reloadFileOnReanalysis);
|
||||
this._reloadFileOnReanalysis = false;
|
||||
this._loadingService.stop();
|
||||
await this._reloadAnnotations();
|
||||
this._loadingService.stop();
|
||||
});
|
||||
}
|
||||
|
||||
@ -559,21 +566,21 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
const fileData = await this._fileDownloadService.loadDataFor(file).toPromise();
|
||||
|
||||
if (!file.isPending) {
|
||||
let excludedOrIncludedPages = new Set<number>();
|
||||
let currentPageAnnotations: AnnotationWrapper[] = [];
|
||||
if (file.isPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (performUpdate && !!this.fileData) {
|
||||
this.fileData.redactionLog = fileData.redactionLog;
|
||||
this.fileData.viewedPages = fileData.viewedPages;
|
||||
excludedOrIncludedPages = new Set([...this.fileData.file.excludedPages, ...file.excludedPages]);
|
||||
currentPageAnnotations = this.annotations.filter(a => excludedOrIncludedPages.has(a.pageNumber));
|
||||
this.fileData.file = file;
|
||||
} else {
|
||||
this.fileData = fileData;
|
||||
if (performUpdate && !!this.fileData) {
|
||||
this.fileData.redactionLog = fileData.redactionLog;
|
||||
this.fileData.viewedPages = fileData.viewedPages;
|
||||
const excludedOrIncludedPages = new Set(diff(this.fileData.file.excludedPages, file.excludedPages));
|
||||
const currentPageAnnotations = this.annotations.filter(a => excludedOrIncludedPages.has(a.pageNumber));
|
||||
this.fileData.file = file;
|
||||
if (excludedOrIncludedPages?.size) {
|
||||
await this._cleanupAndRedrawAnnotations(currentPageAnnotations, a => excludedOrIncludedPages.has(a.pageNumber));
|
||||
}
|
||||
|
||||
return this._cleanupAndRedrawAnnotations(currentPageAnnotations, a => excludedOrIncludedPages.has(a.pageNumber));
|
||||
} else {
|
||||
this.fileData = fileData;
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,7 +598,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
private async _reloadAnnotationsForPage(page: number) {
|
||||
const currentPageAnnotations = this.annotations.filter(a => a.pageNumber === page);
|
||||
|
||||
await this._filesService.reload(this.dossierId, this.fileId).toPromise();
|
||||
this.fileData.redactionLog = await this._fileDownloadService.loadRedactionLogFor(this.dossierId, this.fileId).toPromise();
|
||||
|
||||
await this._cleanupAndRedrawAnnotations(currentPageAnnotations, annotation => annotation.pageNumber === page);
|
||||
@ -604,12 +610,16 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this.rebuildFilters();
|
||||
|
||||
if (this.viewModeService.viewMode === 'STANDARD') {
|
||||
const startTime = new Date().getTime();
|
||||
annotationsToDelete?.forEach(annotation => {
|
||||
this._findAndDeleteAnnotation(annotation.id);
|
||||
});
|
||||
const newPageAnnotations = newAnnotationsFilter ? this.annotations.filter(newAnnotationsFilter) : this.annotations;
|
||||
this._handleDeltaAnnotationFilters(annotationsToDelete ?? [], newPageAnnotations);
|
||||
await this._redrawAnnotations(newPageAnnotations);
|
||||
const newAnnotations = newAnnotationsFilter ? this.annotations.filter(newAnnotationsFilter) : this.annotations;
|
||||
this._handleDeltaAnnotationFilters(annotationsToDelete ?? [], newAnnotations);
|
||||
await this._redrawAnnotations(newAnnotations);
|
||||
console.log(
|
||||
`[REDACTION] Annotations redraw time: ${new Date().getTime() - startTime} ms for ${newAnnotations.length} annotations`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, merge, Observable } from 'rxjs';
|
||||
import { shareLast } from '@iqser/common-ui';
|
||||
import { filter, map, startWith, withLatestFrom } from 'rxjs/operators';
|
||||
import { filter, map, startWith, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { File, IFileAttributeConfig } from '@red/domain';
|
||||
import { MultiSelectService } from './multi-select.service';
|
||||
import { ExcludedPagesService } from './excluded-pages.service';
|
||||
|
||||
@Injectable()
|
||||
export class DocumentInfoService {
|
||||
@ -17,8 +19,18 @@ export class DocumentInfoService {
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _fileAttributesService: FileAttributesService,
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _multiSelectService: MultiSelectService,
|
||||
private readonly _excludedPagesService: ExcludedPagesService,
|
||||
) {
|
||||
this.shown$ = this._show$.asObservable().pipe(shareLast());
|
||||
this.shown$ = this._show$.asObservable().pipe(
|
||||
tap(show => {
|
||||
if (show) {
|
||||
this._multiSelectService.deactivate();
|
||||
this._excludedPagesService.hide();
|
||||
}
|
||||
}),
|
||||
shareLast(),
|
||||
);
|
||||
this.hidden$ = this.shown$.pipe(
|
||||
map(value => !value),
|
||||
shareLast(),
|
||||
|
||||
@ -120,15 +120,17 @@ export class PdfViewerUtils {
|
||||
this._annotationManager.deselectAllAnnotations();
|
||||
}
|
||||
|
||||
selectAnnotations(annotations: AnnotationWrapper[], multiSelectActive: boolean) {
|
||||
selectAnnotations(annotations?: AnnotationWrapper[], multiSelectActive: boolean = false) {
|
||||
if (!annotations) {
|
||||
return;
|
||||
}
|
||||
if (!multiSelectActive) {
|
||||
this.deselectAllAnnotations();
|
||||
}
|
||||
|
||||
const annotationsFromViewer = annotations.map(ann => this._getAnnotationById(ann.id));
|
||||
this._annotationManager.selectAnnotations(annotationsFromViewer);
|
||||
// this.navigateToPage(annotations[0].pageNumber*this.paginationOffset);
|
||||
this._annotationManager.jumpToAnnotation(annotationsFromViewer[0]);
|
||||
this._annotationManager.selectAnnotations(annotationsFromViewer);
|
||||
}
|
||||
|
||||
deselectAnnotations(annotations: AnnotationWrapper[]) {
|
||||
|
||||
@ -68,12 +68,9 @@ export class UserPreferenceService extends GenericService<UserAttributes> {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
reload(): Promise<void> {
|
||||
return this.getAll<UserAttributes>()
|
||||
.toPromise()
|
||||
.then(attributes => {
|
||||
this._userAttributes = attributes ?? {};
|
||||
});
|
||||
async reload(): Promise<void> {
|
||||
const attributes = await this.getAll<UserAttributes>().toPromise();
|
||||
this._userAttributes = attributes ?? {};
|
||||
}
|
||||
|
||||
@Validate()
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { catchError, filter, mergeMapTo, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { catchError, filter, mergeMap, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { from, of, throwError } from 'rxjs';
|
||||
@ -21,9 +21,10 @@ export function configurationInitializer(
|
||||
filter(event => event.type === KeycloakEventType.OnReady),
|
||||
switchMap(() => from(keycloakService.isLoggedIn())),
|
||||
switchMap(loggedIn => (!loggedIn ? throwError('Not Logged In') : of({}))),
|
||||
mergeMapTo(generalSettingsService.getGeneralConfigurations()),
|
||||
mergeMap(() => generalSettingsService.getGeneralConfigurations()),
|
||||
tap(configuration => configService.updateDisplayName(configuration.displayName)),
|
||||
tap(() => userPreferenceService.reload().then(() => languageService.chooseAndSetInitialLanguage())),
|
||||
switchMap(() => userPreferenceService.reload()),
|
||||
tap(() => languageService.chooseAndSetInitialLanguage()),
|
||||
catchError(() => {
|
||||
title.setTitle('RedactManager');
|
||||
return of({});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"ADMIN_CONTACT_NAME": null,
|
||||
"ADMIN_CONTACT_URL": null,
|
||||
"API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1",
|
||||
"API_URL": "https://dev-03.iqser.cloud/redaction-gateway-v1",
|
||||
"APP_NAME": "RedactManager",
|
||||
"AUTO_READ_TIME": 1.5,
|
||||
"BACKEND_APP_VERSION": "4.4.40",
|
||||
@ -17,7 +17,7 @@
|
||||
"MAX_RETRIES_ON_SERVER_ERROR": 3,
|
||||
"OAUTH_CLIENT_ID": "redaction",
|
||||
"OAUTH_IDP_HINT": null,
|
||||
"OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction",
|
||||
"OAUTH_URL": "https://dev-03.iqser.cloud/auth/realms/redaction",
|
||||
"RECENT_PERIOD_IN_HOURS": 24,
|
||||
"SELECTION_MODE": "structural"
|
||||
}
|
||||
|
||||
@ -663,12 +663,12 @@
|
||||
"action": "Analyze entire dossier"
|
||||
},
|
||||
"stats": {
|
||||
"analyzed-pages": "Pages",
|
||||
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
|
||||
"charts": {
|
||||
"dossiers": "Dossiers",
|
||||
"total-documents": "Total Document(s)"
|
||||
"dossiers": "{count, plural, one{Dossier} other{Dossiers}}",
|
||||
"total-documents": "Total Documents"
|
||||
},
|
||||
"total-people": "Total user(s)"
|
||||
"total-people": "Total users"
|
||||
},
|
||||
"table-col-names": {
|
||||
"name": "Name",
|
||||
|
||||
@ -3,5 +3,5 @@ export interface IViewedPage {
|
||||
page?: number;
|
||||
userId?: string;
|
||||
viewedTime?: string;
|
||||
hasChanges?: boolean;
|
||||
showAsUnseen?: boolean;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "redaction",
|
||||
"version": "3.111.0",
|
||||
"version": "3.115.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user