update paths & refactor imports
This commit is contained in:
parent
f46dacc380
commit
7b31e4c59c
@ -1,14 +1,14 @@
|
||||
import { AuthErrorComponent } from './components/auth-error/auth-error.component';
|
||||
import { AuthErrorComponent } from '@components/auth-error/auth-error.component';
|
||||
import { AuthGuard } from './modules/auth/auth.guard';
|
||||
import { CompositeRouteGuard } from './guards/composite-route.guard';
|
||||
import { CompositeRouteGuard } from '@guards/composite-route.guard';
|
||||
import { RedRoleGuard } from './modules/auth/red-role.guard';
|
||||
import { BaseScreenComponent } from './components/base-screen/base-screen.component';
|
||||
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
|
||||
import { RouteReuseStrategy, RouterModule } from '@angular/router';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { DownloadsListScreenComponent } from './components/downloads-list-screen/downloads-list-screen.component';
|
||||
import { AppStateGuard } from './state/app-state.guard';
|
||||
import { UserProfileScreenComponent } from './components/user-profile/user-profile-screen.component';
|
||||
import { CustomRouteReuseStrategy } from './utils/custom-route-reuse.strategy';
|
||||
import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component';
|
||||
import { AppStateGuard } from '@state/app-state.guard';
|
||||
import { UserProfileScreenComponent } from '@components/user-profile/user-profile-screen.component';
|
||||
import { CustomRouteReuseStrategy } from '@utils/custom-route-reuse.strategy';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { AppLoadStateService } from './services/app-load-state.service';
|
||||
import { RouterHistoryService } from './services/router-history.service';
|
||||
import { AppLoadStateService } from '@services/app-load-state.service';
|
||||
import { RouterHistoryService } from '@services/router-history.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-root',
|
||||
|
||||
@ -4,28 +4,28 @@ import { AppComponent } from './app.component';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http';
|
||||
import { BaseScreenComponent } from './components/base-screen/base-screen.component';
|
||||
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
|
||||
import { ApiModule } from '@redaction/red-ui-http';
|
||||
import { ApiPathInterceptor } from './utils/api-path-interceptor';
|
||||
import { ApiPathInterceptor } from '@utils/api-path-interceptor';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||
import { languageInitializer } from './i18n/language.initializer';
|
||||
import { LanguageService } from './i18n/language.service';
|
||||
import { languageInitializer } from '@i18n/language.initializer';
|
||||
import { LanguageService } from '@i18n/language.service';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { environment } from '../environments/environment';
|
||||
import { environment } from '@environments/environment';
|
||||
import { AuthModule } from './modules/auth/auth.module';
|
||||
import { LogoComponent } from './components/logo/logo.component';
|
||||
import { AuthErrorComponent } from './components/auth-error/auth-error.component';
|
||||
import { ToastComponent } from './components/toast/toast.component';
|
||||
import { LogoComponent } from '@components/logo/logo.component';
|
||||
import { AuthErrorComponent } from '@components/auth-error/auth-error.component';
|
||||
import { ToastComponent } from '@components/toast/toast.component';
|
||||
import { HttpCacheInterceptor } from '@redaction/red-cache';
|
||||
import { NotificationsComponent } from './components/notifications/notifications.component';
|
||||
import { NotificationsComponent } from '@components/notifications/notifications.component';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { DownloadsListScreenComponent } from './components/downloads-list-screen/downloads-list-screen.component';
|
||||
import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { SharedModule } from './modules/shared/shared.module';
|
||||
import { FileUploadDownloadModule } from './modules/upload-download/file-upload-download.module';
|
||||
import { UserProfileScreenComponent } from './components/user-profile/user-profile-screen.component';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { FileUploadDownloadModule } from '@upload-download/file-upload-download.module';
|
||||
import { UserProfileScreenComponent } from '@components/user-profile/user-profile-screen.component';
|
||||
import { PlatformLocation } from '@angular/common';
|
||||
import { BASE_HREF } from './tokens';
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import { AppConfigKey, AppConfigService } from '../../modules/app-config/app-config.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-auth-error',
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import { AppStateService } from '../../state/app-state.service';
|
||||
import { LanguageService } from '../../i18n/language.service';
|
||||
import { PermissionsService } from '../../services/permissions.service';
|
||||
import { UserPreferenceService } from '../../services/user-preference.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { LanguageService } from '@i18n/language.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { AppConfigService } from '../../modules/app-config/app-config.service';
|
||||
import { AppConfigService } from '@app-config/app-config.service';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { FileDownloadService } from '../../modules/upload-download/services/file-download.service';
|
||||
import { StatusOverlayService } from '../../modules/upload-download/services/status-overlay.service';
|
||||
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
||||
import { StatusOverlayService } from '@upload-download/services/status-overlay.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
@ -17,12 +17,6 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
styleUrls: ['./base-screen.component.scss']
|
||||
})
|
||||
export class BaseScreenComponent {
|
||||
private _projectsView: boolean;
|
||||
|
||||
get user() {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
constructor(
|
||||
readonly appStateService: AppStateService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
@ -41,10 +35,16 @@ export class BaseScreenComponent {
|
||||
});
|
||||
}
|
||||
|
||||
private _projectsView: boolean;
|
||||
|
||||
get projectsView() {
|
||||
return this._projectsView;
|
||||
}
|
||||
|
||||
get user() {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
get showPendingDownloadsDot() {
|
||||
return this.fileDownloadService.hasPendingDownloads;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FileDownloadService } from '../../modules/upload-download/services/file-download.service';
|
||||
import { DownloadStatusWrapper } from '../../modules/upload-download/model/download-status.wrapper';
|
||||
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
||||
import { DownloadStatusWrapper } from '@upload-download/model/download-status.wrapper';
|
||||
import { DownloadControllerService } from '@redaction/red-ui-http';
|
||||
|
||||
@Component({
|
||||
@ -11,14 +11,14 @@ import { DownloadControllerService } from '@redaction/red-ui-http';
|
||||
export class DownloadsListScreenComponent implements OnInit {
|
||||
constructor(readonly fileDownloadService: FileDownloadService, private readonly _downloadControllerService: DownloadControllerService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.fileDownloadService.getDownloadStatus().subscribe();
|
||||
}
|
||||
|
||||
get noData(): boolean {
|
||||
return this.fileDownloadService.downloads.length === 0;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.fileDownloadService.getDownloadStatus().subscribe();
|
||||
}
|
||||
|
||||
async downloadItem(download: DownloadStatusWrapper) {
|
||||
await this.fileDownloadService.performDownload(download);
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<redaction-circle-button [matMenuTriggerFor]="overlay" icon="red:notification" [showDot]="hasUnread"></redaction-circle-button>
|
||||
<mat-menu #overlay="matMenu" class="notifications-menu" backdropClass="notifications-backdrop" xPosition="before">
|
||||
<redaction-circle-button [matMenuTriggerFor]="overlay" [showDot]="hasUnread" icon="red:notification"></redaction-circle-button>
|
||||
<mat-menu #overlay="matMenu" backdropClass="notifications-backdrop" class="notifications-menu" xPosition="before">
|
||||
<div *ngFor="let group of groupedNotifications | sortBy: 'desc':'dateString'">
|
||||
<div class="all-caps-label">{{ day(group) }}</div>
|
||||
<div
|
||||
class="notification"
|
||||
mat-menu-item
|
||||
*ngFor="let notification of group.notifications | sortBy: 'desc':'eventTime'"
|
||||
[class.unread]="!notification.read"
|
||||
class="notification"
|
||||
mat-menu-item
|
||||
>
|
||||
<redaction-initials-avatar></redaction-initials-avatar>
|
||||
<div class="notification-content">
|
||||
@ -14,9 +14,9 @@
|
||||
<div class="small-label mt-2">{{ eventTime(notification.eventTime) }}</div>
|
||||
</div>
|
||||
<div
|
||||
class="dot"
|
||||
(click)="toggleRead(notification, $event)"
|
||||
[matTooltip]="(notification.read ? 'notifications.mark-unread' : 'notifications.mark-read') | translate"
|
||||
class="dot"
|
||||
matTooltipPosition="before"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
@ -15,7 +15,11 @@ interface Notification {
|
||||
})
|
||||
export class NotificationsComponent {
|
||||
notifications: Notification[] = [
|
||||
{ message: 'This is a notification with longer text wrapping on multiple lines', eventTime: 1607340971000, read: false },
|
||||
{
|
||||
message: 'This is a notification with longer text wrapping on multiple lines',
|
||||
eventTime: 1607340971000,
|
||||
read: false
|
||||
},
|
||||
{ message: 'This is a <a>link</a>', eventTime: 1607254981000, read: true },
|
||||
{ message: 'This is a <b>notification 1</b>', eventTime: 1607254571000, read: false },
|
||||
{ message: 'Notification', eventTime: 1607385727000, read: true },
|
||||
@ -31,18 +35,6 @@ export class NotificationsComponent {
|
||||
return this.notifications.filter((notification) => !notification.read).length > 0;
|
||||
}
|
||||
|
||||
private _groupNotifications() {
|
||||
const res = {};
|
||||
for (const notification of this.notifications) {
|
||||
const date = moment(notification.eventTime).format('YYYY-MM-DD');
|
||||
if (!res[date]) res[date] = [];
|
||||
res[date].push(notification);
|
||||
}
|
||||
for (const key of Object.keys(res)) {
|
||||
this.groupedNotifications.push({ dateString: key, notifications: res[key] });
|
||||
}
|
||||
}
|
||||
|
||||
day(group: { dateString: string; notifications: Notification[] }): string {
|
||||
moment.locale(this._translateService.currentLang);
|
||||
return moment(group.notifications[0].eventTime).calendar({
|
||||
@ -68,4 +60,16 @@ export class NotificationsComponent {
|
||||
$event.stopPropagation();
|
||||
notification.read = !notification.read;
|
||||
}
|
||||
|
||||
private _groupNotifications() {
|
||||
const res = {};
|
||||
for (const notification of this.notifications) {
|
||||
const date = moment(notification.eventTime).format('YYYY-MM-DD');
|
||||
if (!res[date]) res[date] = [];
|
||||
res[date].push(notification);
|
||||
}
|
||||
for (const key of Object.keys(res)) {
|
||||
this.groupedNotifications.push({ dateString: key, notifications: res[key] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import { PermissionsService } from '../../services/permissions.service';
|
||||
import { LanguageService } from '../../i18n/language.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { LanguageService } from '@i18n/language.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { UserControllerService } from '@redaction/red-ui-http';
|
||||
|
||||
@ -39,10 +39,6 @@ export class UserProfileScreenComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this._initializeForm();
|
||||
}
|
||||
|
||||
get languageChanged(): boolean {
|
||||
return this._profileModel['language'] !== this.formGroup.get('language').value;
|
||||
}
|
||||
@ -64,6 +60,10 @@ export class UserProfileScreenComponent implements OnInit {
|
||||
return this._translateService.langs;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this._initializeForm();
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
this.viewReady = false;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { from, of } from 'rxjs';
|
||||
import { AppLoadStateService } from '../services/app-load-state.service';
|
||||
import { AppLoadStateService } from '@services/app-load-state.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { UserWrapper } from '../../services/user.service';
|
||||
import { UserWrapper } from '@services/user.service';
|
||||
import { AnnotationWrapper } from './annotation.wrapper';
|
||||
|
||||
export class AnnotationPermissions {
|
||||
@ -16,6 +16,16 @@ export class AnnotationPermissions {
|
||||
|
||||
canForceRedaction: boolean;
|
||||
|
||||
get canPerformMultipleRemoveActions() {
|
||||
return (
|
||||
<any>this.canMarkTextOnlyAsFalsePositive +
|
||||
<any>this.canMarkAsFalsePositive +
|
||||
<any>this.canRemoveOrSuggestToRemoveFromDictionary +
|
||||
<any>this.canRemoveOrSuggestToRemoveOnlyHere >=
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
static forUser(isManagerAndOwner: boolean, user: UserWrapper, annotation: AnnotationWrapper) {
|
||||
const permissions: AnnotationPermissions = new AnnotationPermissions();
|
||||
|
||||
@ -40,14 +50,4 @@ export class AnnotationPermissions {
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
get canPerformMultipleRemoveActions() {
|
||||
return (
|
||||
<any>this.canMarkTextOnlyAsFalsePositive +
|
||||
<any>this.canMarkAsFalsePositive +
|
||||
<any>this.canRemoveOrSuggestToRemoveFromDictionary +
|
||||
<any>this.canRemoveOrSuggestToRemoveOnlyHere >=
|
||||
2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
ViewedPages
|
||||
} from '@redaction/red-ui-http';
|
||||
import { FileStatusWrapper } from './file-status.wrapper';
|
||||
import { UserWrapper } from '../../services/user.service';
|
||||
import { UserWrapper } from '@services/user.service';
|
||||
import { AnnotationWrapper } from './annotation.wrapper';
|
||||
import { RedactionLogEntryWrapper } from './redaction-log-entry.wrapper';
|
||||
import { ViewMode } from './view-mode';
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { FileAttributesConfig, FileStatus } from '@redaction/red-ui-http';
|
||||
import { StatusSorter } from '../../utils/sorters/status-sorter';
|
||||
import { StatusSorter } from '@utils/sorters/status-sorter';
|
||||
|
||||
export class FileStatusWrapper {
|
||||
primaryAttribute: string;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Rectangle, Comment } from '@redaction/red-ui-http';
|
||||
import { Comment, Rectangle } from '@redaction/red-ui-http';
|
||||
|
||||
export interface RedactionLogEntryWrapper {
|
||||
color?: Array<number>;
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { AuthGuard } from '../auth/auth.guard';
|
||||
import { CompositeRouteGuard } from '../../guards/composite-route.guard';
|
||||
import { CompositeRouteGuard } from '@guards/composite-route.guard';
|
||||
import { RedRoleGuard } from '../auth/red-role.guard';
|
||||
import { AppStateGuard } from '../../state/app-state.guard';
|
||||
import { AppStateGuard } from '@state/app-state.guard';
|
||||
import { RuleSetsListingScreenComponent } from './screens/rule-sets-listing/rule-sets-listing-screen.component';
|
||||
import { DictionaryListingScreenComponent } from './screens/dictionary-listing/dictionary-listing-screen.component';
|
||||
import { DictionaryOverviewScreenComponent } from './screens/dictionary-overview/dictionary-overview-screen.component';
|
||||
import { PendingChangesGuard } from '../../guards/can-deactivate.guard';
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
import { RulesScreenComponent } from './screens/rules/rules-screen.component';
|
||||
import { FileAttributesListingScreenComponent } from './screens/file-attributes-listing/file-attributes-listing-screen.component';
|
||||
import { WatermarkScreenComponent } from './screens/watermark/watermark-screen.component';
|
||||
|
||||
@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { AdminRoutingModule } from './admin-routing.module';
|
||||
import { RulesScreenComponent } from './screens/rules/rules-screen.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { RuleSetsListingScreenComponent } from './screens/rule-sets-listing/rule-sets-listing-screen.component';
|
||||
import { AuditScreenComponent } from './screens/audit/audit-screen.component';
|
||||
import { DefaultColorsScreenComponent } from './screens/default-colors/default-colors-screen.component';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { UserPreferenceService } from '../../../../services/user-preference.service';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-admin-breadcrumbs',
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Component, Input, ViewEncapsulation, Output, EventEmitter, ViewChild, HostListener, ContentChild, TemplateRef } from '@angular/core';
|
||||
import { Component, ContentChild, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { curveLinear } from 'd3-shape';
|
||||
import { scaleBand, scaleLinear, scalePoint, scaleTime } from 'd3-scale';
|
||||
import { BaseChartComponent, LineSeriesComponent, ViewDimensions, ColorHelper, calculateViewDimensions } from '@swimlane/ngx-charts';
|
||||
import { BaseChartComponent, calculateViewDimensions, ColorHelper, LineSeriesComponent, ViewDimensions } from '@swimlane/ngx-charts';
|
||||
|
||||
@Component({
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { UserPreferenceService } from '../../../../services/user-preference.service';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-side-nav',
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-users-stats',
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { DictionaryControllerService, TypeValue } from '@redaction/red-ui-http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<div class="dialog-content">
|
||||
<div class="red-input-group required w-300">
|
||||
<label translate="add-edit-file-attribute.form.name"></label>
|
||||
<input formControlName="label" name="label" type="text" placeholder="{{ 'add-edit-file-attribute.form.name-placeholder' | translate }}" />
|
||||
<input formControlName="label" name="label" placeholder="{{ 'add-edit-file-attribute.form.name-placeholder' | translate }}" type="text" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required w-300">
|
||||
@ -15,8 +15,8 @@
|
||||
<input
|
||||
formControlName="csvColumnHeader"
|
||||
name="csvColumnHeader"
|
||||
type="text"
|
||||
placeholder="{{ 'add-edit-file-attribute.form.column-header-placeholder' | translate }}"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -31,11 +31,11 @@
|
||||
|
||||
<div class="options-wrapper">
|
||||
<div class="red-input-group">
|
||||
<mat-slide-toggle formControlName="readonly" color="primary">{{ 'add-edit-file-attribute.form.read-only' | translate }}</mat-slide-toggle>
|
||||
<mat-slide-toggle color="primary" formControlName="readonly">{{ 'add-edit-file-attribute.form.read-only' | translate }}</mat-slide-toggle>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group mt-0">
|
||||
<mat-checkbox name="primaryAttribute" formControlName="primaryAttribute" color="primary">
|
||||
<mat-checkbox color="primary" formControlName="primaryAttribute" name="primaryAttribute">
|
||||
{{ 'add-edit-file-attribute.form.primary' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
@ -48,5 +48,5 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<redaction-circle-button icon="red:close" mat-dialog-close class="dialog-close"></redaction-circle-button>
|
||||
<redaction-circle-button class="dialog-close" icon="red:close" mat-dialog-close></redaction-circle-button>
|
||||
</section>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FileAttributeConfig } from '@redaction/red-ui-http';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import * as moment from 'moment';
|
||||
import { Moment } from 'moment';
|
||||
import { RuleSetControllerService, RuleSetModel } from '@redaction/red-ui-http';
|
||||
import { applyIntervalConstraints } from '../../../../utils/date-inputs-utils';
|
||||
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-add-edit-rule-set-dialog',
|
||||
@ -53,28 +53,6 @@ export class AddEditRuleSetDialogComponent {
|
||||
});
|
||||
}
|
||||
|
||||
private _applyValidityIntervalConstraints(value): boolean {
|
||||
if (applyIntervalConstraints(value, this._previousValidFrom, this._previousValidTo, this.ruleSetForm, 'validFrom', 'validTo')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this._previousValidFrom = this.ruleSetForm.get('validFrom').value;
|
||||
this._previousValidTo = this.ruleSetForm.get('validTo').value;
|
||||
return false;
|
||||
}
|
||||
|
||||
private _requiredIfValidator(predicate) {
|
||||
return (formControl) => {
|
||||
if (!formControl.parent) {
|
||||
return null;
|
||||
}
|
||||
if (predicate()) {
|
||||
return Validators.required(formControl);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
if (!this.ruleSet) return true;
|
||||
|
||||
@ -113,4 +91,26 @@ export class AddEditRuleSetDialogComponent {
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this.dialogRef.close({ ruleSet });
|
||||
}
|
||||
|
||||
private _applyValidityIntervalConstraints(value): boolean {
|
||||
if (applyIntervalConstraints(value, this._previousValidFrom, this._previousValidTo, this.ruleSetForm, 'validFrom', 'validTo')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this._previousValidFrom = this.ruleSetForm.get('validFrom').value;
|
||||
this._previousValidTo = this.ruleSetForm.get('validTo').value;
|
||||
return false;
|
||||
}
|
||||
|
||||
private _requiredIfValidator(predicate) {
|
||||
return (formControl) => {
|
||||
if (!formControl.parent) {
|
||||
return null;
|
||||
}
|
||||
if (predicate()) {
|
||||
return Validators.required(formControl);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { Component, Inject } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-add-edit-user-dialog',
|
||||
@ -47,19 +47,6 @@ export class AddEditUserDialogComponent {
|
||||
this._setRolesRequirements();
|
||||
}
|
||||
|
||||
private _setRolesRequirements() {
|
||||
for (const key of Object.keys(this._ROLE_REQUIREMENTS)) {
|
||||
this.userForm.controls[key].valueChanges.subscribe((checked) => {
|
||||
if (checked) {
|
||||
this.userForm.patchValue({ [this._ROLE_REQUIREMENTS[key]]: true });
|
||||
this.userForm.controls[this._ROLE_REQUIREMENTS[key]].disable();
|
||||
} else {
|
||||
this.userForm.controls[this._ROLE_REQUIREMENTS[key]].enable();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
if (!this.user) return true;
|
||||
|
||||
@ -72,6 +59,15 @@ export class AddEditUserDialogComponent {
|
||||
return false;
|
||||
}
|
||||
|
||||
get activeRoles(): string[] {
|
||||
return this.ROLES.reduce((acc, role) => {
|
||||
if (this.userForm.get(role).value) {
|
||||
acc.push(role);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
async save() {
|
||||
this.dialogRef.close({
|
||||
action: this.user ? 'UPDATE' : 'CREATE',
|
||||
@ -83,12 +79,16 @@ export class AddEditUserDialogComponent {
|
||||
this.dialogRef.close('DELETE');
|
||||
}
|
||||
|
||||
get activeRoles(): string[] {
|
||||
return this.ROLES.reduce((acc, role) => {
|
||||
if (this.userForm.get(role).value) {
|
||||
acc.push(role);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
private _setRolesRequirements() {
|
||||
for (const key of Object.keys(this._ROLE_REQUIREMENTS)) {
|
||||
this.userForm.controls[key].valueChanges.subscribe((checked) => {
|
||||
if (checked) {
|
||||
this.userForm.patchValue({ [this._ROLE_REQUIREMENTS[key]]: true });
|
||||
this.userForm.controls[this._ROLE_REQUIREMENTS[key]].disable();
|
||||
} else {
|
||||
this.userForm.controls[this._ROLE_REQUIREMENTS[key]].enable();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FileAttributeConfig } from '@redaction/red-ui-http';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
@ -28,6 +28,10 @@ export class ConfirmDeleteFileAttributeDialogComponent {
|
||||
return this.checkboxes[0].value && this.checkboxes[1].value;
|
||||
}
|
||||
|
||||
get type(): 'bulk' | 'single' {
|
||||
return !this.fileAttribute ? 'bulk' : 'single';
|
||||
}
|
||||
|
||||
deleteFileAttribute() {
|
||||
if (this.valid) {
|
||||
this.dialogRef.close(true);
|
||||
@ -36,10 +40,6 @@ export class ConfirmDeleteFileAttributeDialogComponent {
|
||||
}
|
||||
}
|
||||
|
||||
get type(): 'bulk' | 'single' {
|
||||
return !this.fileAttribute ? 'bulk' : 'single';
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-confirm-delete-users-dialog',
|
||||
@ -31,6 +31,14 @@ export class ConfirmDeleteUsersDialogComponent {
|
||||
}).length;
|
||||
}
|
||||
|
||||
get valid() {
|
||||
return this.checkboxes[0].value && this.checkboxes[1].value;
|
||||
}
|
||||
|
||||
get type(): 'bulk' | 'single' {
|
||||
return this.users.length > 1 ? 'bulk' : 'single';
|
||||
}
|
||||
|
||||
async deleteUser() {
|
||||
if (this.valid) {
|
||||
this.dialogRef.close(true);
|
||||
@ -39,15 +47,7 @@ export class ConfirmDeleteUsersDialogComponent {
|
||||
}
|
||||
}
|
||||
|
||||
get valid() {
|
||||
return this.checkboxes[0].value && this.checkboxes[1].value;
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
get type(): 'bulk' | 'single' {
|
||||
return this.users.length > 1 ? 'bulk' : 'single';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Colors, DictionaryControllerService } from '@redaction/red-ui-http';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@ -13,9 +13,9 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
export class EditColorDialogComponent {
|
||||
readonly colors: Colors;
|
||||
readonly colorKey: string;
|
||||
colorForm: FormGroup;
|
||||
private readonly _initialColor: string;
|
||||
private readonly _ruleSetId: string;
|
||||
colorForm: FormGroup;
|
||||
|
||||
constructor(
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, EventEmitter, Injector, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { BaseListingComponent } from '../../../../shared/base/base-listing.component';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { Field } from '../file-attributes-csv-import-dialog.component';
|
||||
import { FileAttributeConfig } from '@redaction/red-ui-http';
|
||||
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import { Component, Inject, Injector, ViewChild } from '@angular/core';
|
||||
import { AbstractControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import * as Papa from 'papaparse';
|
||||
import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
export interface Field {
|
||||
@ -28,8 +28,6 @@ export interface Field {
|
||||
styleUrls: ['./file-attributes-csv-import-dialog.component.scss']
|
||||
})
|
||||
export class FileAttributesCsvImportDialogComponent extends BaseListingComponent<Field> {
|
||||
protected readonly _searchKey = 'csvColumn';
|
||||
|
||||
csvFile: File;
|
||||
ruleSetId: string;
|
||||
parseResult: { data: any[]; errors: any[]; meta: any; fields: Field[] };
|
||||
@ -42,8 +40,8 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
|
||||
keepPreview = false;
|
||||
columnSample = [];
|
||||
initialParseConfig: { delimiter?: string; encoding?: string } = {};
|
||||
|
||||
@ViewChild(CdkVirtualScrollViewport, { static: false }) cdkVirtualScrollViewport: CdkVirtualScrollViewport;
|
||||
protected readonly _searchKey = 'csvColumn';
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
@ -67,13 +65,11 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
|
||||
this.readFile();
|
||||
}
|
||||
|
||||
private _autocompleteStringValidator(): ValidatorFn {
|
||||
return (control: AbstractControl): { [key: string]: any } | null => {
|
||||
if ((this.parseResult?.meta?.fields || []).indexOf(control.value) !== -1) {
|
||||
return null; /* valid option selected */
|
||||
}
|
||||
return { invalidAutocompleteString: { value: control.value } };
|
||||
};
|
||||
get changedParseConfig(): boolean {
|
||||
return (
|
||||
this.initialParseConfig.delimiter !== this.baseConfigForm.get('delimiter').value ||
|
||||
this.initialParseConfig.encoding !== this.baseConfigForm.get('encoding').value
|
||||
);
|
||||
}
|
||||
|
||||
readFile() {
|
||||
@ -161,19 +157,6 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
|
||||
}
|
||||
}
|
||||
|
||||
private _buildAttribute(csvColumn: string): Field {
|
||||
const sample = this.getSample(csvColumn);
|
||||
const isNumber = sample && !isNaN(sample);
|
||||
return {
|
||||
csvColumn,
|
||||
name: csvColumn,
|
||||
temporaryName: csvColumn,
|
||||
type: isNumber ? FileAttributeConfig.TypeEnum.NUMBER : FileAttributeConfig.TypeEnum.TEXT,
|
||||
readonly: false,
|
||||
primaryAttribute: false
|
||||
};
|
||||
}
|
||||
|
||||
activateAll() {
|
||||
this.activeFields = [...this.allEntities];
|
||||
}
|
||||
@ -239,10 +222,25 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
|
||||
}, 0);
|
||||
}
|
||||
|
||||
get changedParseConfig(): boolean {
|
||||
return (
|
||||
this.initialParseConfig.delimiter !== this.baseConfigForm.get('delimiter').value ||
|
||||
this.initialParseConfig.encoding !== this.baseConfigForm.get('encoding').value
|
||||
);
|
||||
private _autocompleteStringValidator(): ValidatorFn {
|
||||
return (control: AbstractControl): { [key: string]: any } | null => {
|
||||
if ((this.parseResult?.meta?.fields || []).indexOf(control.value) !== -1) {
|
||||
return null; /* valid option selected */
|
||||
}
|
||||
return { invalidAutocompleteString: { value: control.value } };
|
||||
};
|
||||
}
|
||||
|
||||
private _buildAttribute(csvColumn: string): Field {
|
||||
const sample = this.getSample(csvColumn);
|
||||
const isNumber = sample && !isNaN(sample);
|
||||
return {
|
||||
csvColumn,
|
||||
name: csvColumn,
|
||||
temporaryName: csvColumn,
|
||||
type: isNumber ? FileAttributeConfig.TypeEnum.NUMBER : FileAttributeConfig.TypeEnum.TEXT,
|
||||
readonly: false,
|
||||
primaryAttribute: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { SMTPConfigurationModel } from '@redaction/red-ui-http';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { AuditControllerService, AuditResponse, AuditSearchRequest } from '@redaction/red-ui-http';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Moment } from 'moment';
|
||||
import { applyIntervalConstraints } from '../../../../utils/date-inputs-utils';
|
||||
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
|
||||
|
||||
const PAGE_SIZE = 50;
|
||||
|
||||
@ -49,6 +49,17 @@ export class AuditScreenComponent {
|
||||
this._fetchData();
|
||||
}
|
||||
|
||||
get totalPages(): number {
|
||||
if (!this.logs) {
|
||||
return 0;
|
||||
}
|
||||
return Math.ceil(this.logs.totalHits / PAGE_SIZE);
|
||||
}
|
||||
|
||||
pageChanged(page: number) {
|
||||
this._fetchData(page);
|
||||
}
|
||||
|
||||
private _updateDateFilters(value): boolean {
|
||||
if (applyIntervalConstraints(value, this._previousFrom, this._previousTo, this.filterForm, 'from', 'to')) {
|
||||
return true;
|
||||
@ -93,15 +104,4 @@ export class AuditScreenComponent {
|
||||
this.viewReady = true;
|
||||
});
|
||||
}
|
||||
|
||||
get totalPages(): number {
|
||||
if (!this.logs) {
|
||||
return 0;
|
||||
}
|
||||
return Math.ceil(this.logs.totalHits / PAGE_SIZE);
|
||||
}
|
||||
|
||||
pageChanged(page: number) {
|
||||
this._fetchData(page);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Component, Injector } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Colors, DictionaryControllerService } from '@redaction/red-ui-http';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-default-colors-screen',
|
||||
@ -12,9 +12,8 @@ import { BaseListingComponent } from '../../../shared/base/base-listing.componen
|
||||
styleUrls: ['./default-colors-screen.component.scss']
|
||||
})
|
||||
export class DefaultColorsScreenComponent extends BaseListingComponent<{ key: string; value: string }> {
|
||||
protected readonly _sortKey = 'default-colors';
|
||||
|
||||
viewReady = false;
|
||||
protected readonly _sortKey = 'default-colors';
|
||||
private _colorsObj: Colors;
|
||||
|
||||
constructor(
|
||||
@ -34,6 +33,13 @@ export class DefaultColorsScreenComponent extends BaseListingComponent<{ key: st
|
||||
await this._appStateService.loadAllRuleSets();
|
||||
}
|
||||
|
||||
openEditColorDialog($event: any, color: { key: string; value: string }) {
|
||||
$event.stopPropagation();
|
||||
this._dialogService.openEditColorsDialog(this._colorsObj, color.key, this._appStateService.activeRuleSetId, async () => {
|
||||
this._loadColors();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadColors() {
|
||||
this._dictionaryControllerService
|
||||
.getColors(this._appStateService.activeRuleSetId)
|
||||
@ -47,11 +53,4 @@ export class DefaultColorsScreenComponent extends BaseListingComponent<{ key: st
|
||||
this.viewReady = true;
|
||||
});
|
||||
}
|
||||
|
||||
openEditColorDialog($event: any, color: { key: string; value: string }) {
|
||||
$event.stopPropagation();
|
||||
this._dialogService.openEditColorsDialog(this._colorsObj, color.key, this._appStateService.activeRuleSetId, async () => {
|
||||
this._loadColors();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Component, Injector, OnInit } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { DictionaryControllerService, TypeValue } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { defaultIfEmpty, tap } from 'rxjs/operators';
|
||||
import { forkJoin } from 'rxjs';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dictionary-listing-screen',
|
||||
@ -15,13 +15,12 @@ import { BaseListingComponent } from '../../../shared/base/base-listing.componen
|
||||
styleUrls: ['./dictionary-listing-screen.component.scss']
|
||||
})
|
||||
export class DictionaryListingScreenComponent extends BaseListingComponent<TypeValue> implements OnInit {
|
||||
viewReady = false;
|
||||
chartData: DoughnutChartConfig[] = [];
|
||||
protected readonly _searchKey = 'label';
|
||||
protected readonly _selectionKey = 'type';
|
||||
protected readonly _sortKey = 'dictionary-listing';
|
||||
|
||||
viewReady = false;
|
||||
chartData: DoughnutChartConfig[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _dictionaryControllerService: DictionaryControllerService,
|
||||
@ -38,6 +37,23 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
|
||||
this._loadDictionaryData();
|
||||
}
|
||||
|
||||
openAddEditDictionaryDialog($event?: MouseEvent, dict?: TypeValue) {
|
||||
$event?.stopPropagation();
|
||||
this._dialogService.openAddEditDictionaryDialog(dict, this._appStateService.activeRuleSetId, async (newDictionary) => {
|
||||
if (newDictionary) {
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadDictionaryData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
openDeleteDictionaryDialog($event: any, dict: TypeValue) {
|
||||
this._dialogService.openDeleteDictionaryDialog($event, dict, this._appStateService.activeRuleSetId, async () => {
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadDictionaryData();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadDictionaryData() {
|
||||
const appStateDictionaryData = this._appStateService.dictionaryData[this._appStateService.activeRuleSetId];
|
||||
this.allEntities = Object.keys(appStateDictionaryData)
|
||||
@ -71,21 +87,4 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
|
||||
this.chartData.sort((a, b) => (a.label < b.label ? -1 : 1));
|
||||
this.viewReady = true;
|
||||
}
|
||||
|
||||
openAddEditDictionaryDialog($event?: MouseEvent, dict?: TypeValue) {
|
||||
$event?.stopPropagation();
|
||||
this._dialogService.openAddEditDictionaryDialog(dict, this._appStateService.activeRuleSetId, async (newDictionary) => {
|
||||
if (newDictionary) {
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadDictionaryData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
openDeleteDictionaryDialog($event: any, dict: TypeValue) {
|
||||
this._dialogService.openDeleteDictionaryDialog($event, dict, this._appStateService.activeRuleSetId, async () => {
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadDictionaryData();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { DictionaryControllerService, RuleSetModel, TypeValue } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AceEditorComponent } from 'ng2-ace-editor';
|
||||
import { debounce } from '../../../../utils/debounce';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { debounce } from '@utils/debounce';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { ComponentHasChanges } from '../../../../guards/can-deactivate.guard';
|
||||
import { ComponentHasChanges } from '@guards/can-deactivate.guard';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { DigitalSignature, DigitalSignatureControllerService } from '@redaction/red-ui-http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { lastIndexOfEnd } from '../../../../utils/functions';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { lastIndexOfEnd } from '@utils/functions';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-digital-signature-screen',
|
||||
@ -28,6 +28,10 @@ export class DigitalSignatureScreenComponent {
|
||||
this.loadDigitalSignatureAndInitializeForm();
|
||||
}
|
||||
|
||||
get hasDigitalSignatureSet() {
|
||||
return this.digitalSignatureExists || !!this.digitalSignatureForm.get('base64EncodedPrivateKey').value;
|
||||
}
|
||||
|
||||
saveDigitalSignature() {
|
||||
const digitalSignature = {
|
||||
...this.digitalSignatureForm.getRawValue()
|
||||
@ -119,6 +123,8 @@ export class DigitalSignatureScreenComponent {
|
||||
});
|
||||
}
|
||||
|
||||
formChanged() {}
|
||||
|
||||
private _initForm() {
|
||||
this.digitalSignatureForm = this._formBuilder.group({
|
||||
certificateName: [this.digitalSignature.certificateName, Validators.required],
|
||||
@ -129,10 +135,4 @@ export class DigitalSignatureScreenComponent {
|
||||
base64EncodedPrivateKey: this.digitalSignatureExists ? null : [this.digitalSignature.base64EncodedPrivateKey, Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
get hasDigitalSignatureSet() {
|
||||
return this.digitalSignatureExists || !!this.digitalSignatureForm.get('base64EncodedPrivateKey').value;
|
||||
}
|
||||
|
||||
formChanged() {}
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-attributes-listing-screen',
|
||||
@ -12,13 +12,11 @@ import { BaseListingComponent } from '../../../shared/base/base-listing.componen
|
||||
styleUrls: ['./file-attributes-listing-screen.component.scss']
|
||||
})
|
||||
export class FileAttributesListingScreenComponent extends BaseListingComponent<FileAttributeConfig> implements OnInit {
|
||||
viewReady = false;
|
||||
loading = false;
|
||||
protected readonly _searchKey = 'label';
|
||||
protected readonly _selectionKey = 'id';
|
||||
protected readonly _sortKey = 'file-attributes-listing';
|
||||
|
||||
viewReady = false;
|
||||
loading = false;
|
||||
|
||||
private _existingConfiguration: FileAttributesConfig;
|
||||
|
||||
@ViewChild('fileInput') private _fileInput: ElementRef;
|
||||
@ -39,19 +37,6 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
try {
|
||||
const response = await this._fileAttributesService.getFileAttributesConfiguration(this._appStateService.activeRuleSetId).toPromise();
|
||||
this._existingConfiguration = response;
|
||||
this.allEntities = response?.fileAttributeConfigs || [];
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this._executeSearchImmediately();
|
||||
this.viewReady = true;
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
openAddEditAttributeDialog($event: MouseEvent, fileAttribute?: FileAttributeConfig) {
|
||||
$event.stopPropagation();
|
||||
this._dialogService.openAddEditFileAttributeDialog(fileAttribute, this._appStateService.activeRuleSetId, async (newValue: FileAttributeConfig) => {
|
||||
@ -82,4 +67,17 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
try {
|
||||
const response = await this._fileAttributesService.getFileAttributesConfiguration(this._appStateService.activeRuleSetId).toPromise();
|
||||
this._existingConfiguration = response;
|
||||
this.allEntities = response?.fileAttributeConfigs || [];
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this._executeSearchImmediately();
|
||||
this.viewReady = true;
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { LicenseReport, LicenseReportControllerService } from '@redaction/red-ui-http';
|
||||
import { AppConfigService } from '../../../app-config/app-config.service';
|
||||
import { AppConfigService } from '@app-config/app-config.service';
|
||||
import * as moment from 'moment';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@ -11,6 +11,27 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
styleUrls: ['./license-information-screen.component.scss']
|
||||
})
|
||||
export class LicenseInformationScreenComponent implements OnInit {
|
||||
currentInfo: LicenseReport = {};
|
||||
totalInfo: LicenseReport = {};
|
||||
unlicensedInfo: LicenseReport = {};
|
||||
totalLicensedNumberOfPages = 0;
|
||||
analysisPercentageOfLicense = 100;
|
||||
viewReady = false;
|
||||
barChart: any[] = [];
|
||||
lineChartSeries: any[] = [];
|
||||
yAxisLabel = this._translateService.instant('license-info-screen.chart.pages-per-month');
|
||||
yAxisLabelRight = this._translateService.instant('license-info-screen.chart.total-pages');
|
||||
lineChartScheme = {
|
||||
selectable: true,
|
||||
group: 'Ordinal',
|
||||
domain: ['#dd4d50', '#5ce594', '#0389ec']
|
||||
};
|
||||
comboBarScheme = {
|
||||
selectable: true,
|
||||
group: 'Ordinal',
|
||||
domain: ['#0389ec']
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly appConfigService: AppConfigService,
|
||||
@ -21,30 +42,6 @@ export class LicenseInformationScreenComponent implements OnInit {
|
||||
get currentYear(): number {
|
||||
return new Date().getFullYear();
|
||||
}
|
||||
currentInfo: LicenseReport = {};
|
||||
totalInfo: LicenseReport = {};
|
||||
unlicensedInfo: LicenseReport = {};
|
||||
totalLicensedNumberOfPages = 0;
|
||||
analysisPercentageOfLicense = 100;
|
||||
viewReady = false;
|
||||
|
||||
barChart: any[] = [];
|
||||
lineChartSeries: any[] = [];
|
||||
|
||||
yAxisLabel = this._translateService.instant('license-info-screen.chart.pages-per-month');
|
||||
yAxisLabelRight = this._translateService.instant('license-info-screen.chart.total-pages');
|
||||
|
||||
lineChartScheme = {
|
||||
selectable: true,
|
||||
group: 'Ordinal',
|
||||
domain: ['#dd4d50', '#5ce594', '#0389ec']
|
||||
};
|
||||
|
||||
comboBarScheme = {
|
||||
selectable: true,
|
||||
group: 'Ordinal',
|
||||
domain: ['#0389ec']
|
||||
};
|
||||
|
||||
async ngOnInit() {
|
||||
this.totalLicensedNumberOfPages = this.appConfigService.getConfig('LICENSE_PAGE_COUNT', 0);
|
||||
@ -74,6 +71,16 @@ export class LicenseInformationScreenComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
sendMail(): void {
|
||||
const licenseCustomer = this.appConfigService.getConfig('LICENSE_CUSTOMER');
|
||||
const subject = this._translateService.instant('license-info-screen.email.title', { licenseCustomer });
|
||||
const body = [
|
||||
this._translateService.instant('license-info-screen.email.body.analyzed', { pages: this.currentInfo.numberOfAnalyzedPages }),
|
||||
this._translateService.instant('license-info-screen.email.body.licensed', { pages: this.totalLicensedNumberOfPages })
|
||||
].join('%0D%0A');
|
||||
window.location.href = `mailto:${this.appConfigService.getConfig('LICENSE_EMAIL')}?subject=${subject}&body=${body}`;
|
||||
}
|
||||
|
||||
private async _setMonthlyStats(startDate: moment.Moment, endDate: moment.Moment) {
|
||||
const [startMonth, startYear] = [startDate.month(), startDate.year()];
|
||||
const [endMonth, endYear] = [endDate.month(), endDate.year()];
|
||||
@ -144,14 +151,4 @@ export class LicenseInformationScreenComponent implements OnInit {
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
sendMail(): void {
|
||||
const licenseCustomer = this.appConfigService.getConfig('LICENSE_CUSTOMER');
|
||||
const subject = this._translateService.instant('license-info-screen.email.title', { licenseCustomer });
|
||||
const body = [
|
||||
this._translateService.instant('license-info-screen.email.body.analyzed', { pages: this.currentInfo.numberOfAnalyzedPages }),
|
||||
this._translateService.instant('license-info-screen.email.body.licensed', { pages: this.totalLicensedNumberOfPages })
|
||||
].join('%0D%0A');
|
||||
window.location.href = `mailto:${this.appConfigService.getConfig('LICENSE_EMAIL')}?subject=${subject}&body=${body}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Component, Injector, OnInit } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { UserPreferenceService } from '../../../../services/user-preference.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { RuleSetModel } from '@redaction/red-ui-http';
|
||||
|
||||
@Component({
|
||||
@ -37,6 +37,14 @@ export class RuleSetsListingScreenComponent extends BaseListingComponent<RuleSet
|
||||
this._loadRuleSetStats();
|
||||
}
|
||||
|
||||
openAddRuleSetDialog() {
|
||||
this._dialogService.openAddEditRuleSetDialog(null, async (newRuleSet) => {
|
||||
if (newRuleSet) {
|
||||
this.loadRuleSetsData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _loadRuleSetStats() {
|
||||
this.allEntities.forEach((rs) => {
|
||||
const dictionaries = this._appStateService.dictionaryData[rs.ruleSetId];
|
||||
@ -50,12 +58,4 @@ export class RuleSetsListingScreenComponent extends BaseListingComponent<RuleSet
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
openAddRuleSetDialog() {
|
||||
this._dialogService.openAddEditRuleSetDialog(null, async (newRuleSet) => {
|
||||
if (newRuleSet) {
|
||||
this.loadRuleSetsData();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Component, ElementRef, ViewChild } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { AceEditorComponent } from 'ng2-ace-editor';
|
||||
import { RulesControllerService } from '@redaction/red-ui-http';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { ComponentHasChanges } from '../../../../guards/can-deactivate.guard';
|
||||
import { ComponentHasChanges } from '@guards/can-deactivate.guard';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
|
||||
declare let ace;
|
||||
|
||||
@ -45,16 +45,8 @@ export class RulesScreenComponent extends ComponentHasChanges {
|
||||
this._initialize();
|
||||
}
|
||||
|
||||
private _initialize() {
|
||||
this._rulesControllerService.downloadRules(this._appStateService.activeRuleSetId).subscribe(
|
||||
(rules) => {
|
||||
this.rules = rules.rules;
|
||||
this.revert();
|
||||
},
|
||||
() => {
|
||||
this.processing = false;
|
||||
}
|
||||
);
|
||||
get hasChanges(): boolean {
|
||||
return this.activeEditMarkers.length > 0;
|
||||
}
|
||||
|
||||
textChanged($event: any) {
|
||||
@ -82,10 +74,6 @@ export class RulesScreenComponent extends ComponentHasChanges {
|
||||
}
|
||||
}
|
||||
|
||||
get hasChanges(): boolean {
|
||||
return this.activeEditMarkers.length > 0;
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
this.processing = true;
|
||||
this._rulesControllerService
|
||||
@ -136,4 +124,16 @@ export class RulesScreenComponent extends ComponentHasChanges {
|
||||
fileReader.readAsText(file);
|
||||
}
|
||||
}
|
||||
|
||||
private _initialize() {
|
||||
this._rulesControllerService.downloadRules(this._appStateService.activeRuleSetId).subscribe(
|
||||
(rules) => {
|
||||
this.rules = rules.rules;
|
||||
this.revert();
|
||||
},
|
||||
() => {
|
||||
this.processing = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { SmtpConfigurationControllerService, SMTPConfigurationModel } from '@redaction/red-ui-http';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
@ -46,19 +46,6 @@ export class SmtpConfigScreenComponent implements OnInit {
|
||||
}
|
||||
});
|
||||
}
|
||||
async ngOnInit() {
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
try {
|
||||
this._initialValue = await this._smtpConfigService.getCurrentSMTPConfiguration().toPromise();
|
||||
this.configForm.patchValue(this._initialValue, { emitEvent: false });
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this.viewReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
if (!this._initialValue) return true;
|
||||
@ -72,6 +59,10 @@ export class SmtpConfigScreenComponent implements OnInit {
|
||||
return false;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
async save() {
|
||||
this.viewReady = false;
|
||||
await this._smtpConfigService.updateSMTPConfiguration(this.configForm.getRawValue()).toPromise();
|
||||
@ -104,4 +95,14 @@ export class SmtpConfigScreenComponent implements OnInit {
|
||||
this.viewReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
try {
|
||||
this._initialValue = await this._smtpConfigService.getCurrentSMTPConfiguration().toPromise();
|
||||
this.configForm.patchValue(this._initialValue, { emitEvent: false });
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this.viewReady = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { Component, Injector, OnInit } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { TranslateChartService } from '../../../../services/translate-chart.service';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-user-listing-screen',
|
||||
@ -14,12 +14,11 @@ import { BaseListingComponent } from '../../../shared/base/base-listing.componen
|
||||
styleUrls: ['./user-listing-screen.component.scss']
|
||||
})
|
||||
export class UserListingScreenComponent extends BaseListingComponent<User> implements OnInit {
|
||||
protected readonly _selectionKey = 'userId';
|
||||
|
||||
viewReady = false;
|
||||
loading = false;
|
||||
collapsedDetails = false;
|
||||
chartData: DoughnutChartConfig[] = [];
|
||||
protected readonly _selectionKey = 'userId';
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
@ -33,12 +32,12 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
super(_injector);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this._loadData();
|
||||
get canDeleteSelected(): boolean {
|
||||
return this.selectedEntitiesIds.indexOf(this.userService.userId) === -1;
|
||||
}
|
||||
|
||||
protected _searchField(user: any): string {
|
||||
return this.userService.getName(user);
|
||||
async ngOnInit() {
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
openAddEditUserDialog($event: MouseEvent, user?: User) {
|
||||
@ -67,6 +66,29 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
});
|
||||
}
|
||||
|
||||
getDisplayRoles(user: User) {
|
||||
return user.roles.map((role) => this._translateService.instant('roles.' + role)).join(', ') || this._translateService.instant('roles.NO_ROLE');
|
||||
}
|
||||
|
||||
async toggleActive(user: User) {
|
||||
this.loading = true;
|
||||
user.roles = this.userService.isActive(user) ? [] : ['RED_USER'];
|
||||
await this._userControllerService.addRoleToUsers(user.roles, user.userId).toPromise();
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
toggleCollapsedDetails() {
|
||||
this.collapsedDetails = !this.collapsedDetails;
|
||||
}
|
||||
|
||||
async bulkDelete() {
|
||||
this.openDeleteUserDialog(this.allEntities.filter((u) => this.isEntitySelected(u)));
|
||||
}
|
||||
|
||||
protected _searchField(user: any): string {
|
||||
return this.userService.getName(user);
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
this.allEntities = await this._userControllerService.getAllUsers().toPromise();
|
||||
this._executeSearchImmediately();
|
||||
@ -111,27 +133,4 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
].filter((type) => type.value > 0)
|
||||
);
|
||||
}
|
||||
|
||||
getDisplayRoles(user: User) {
|
||||
return user.roles.map((role) => this._translateService.instant('roles.' + role)).join(', ') || this._translateService.instant('roles.NO_ROLE');
|
||||
}
|
||||
|
||||
async toggleActive(user: User) {
|
||||
this.loading = true;
|
||||
user.roles = this.userService.isActive(user) ? [] : ['RED_USER'];
|
||||
await this._userControllerService.addRoleToUsers(user.roles, user.userId).toPromise();
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
toggleCollapsedDetails() {
|
||||
this.collapsedDetails = !this.collapsedDetails;
|
||||
}
|
||||
|
||||
async bulkDelete() {
|
||||
this.openDeleteUserDialog(this.allEntities.filter((u) => this.isEntitySelected(u)));
|
||||
}
|
||||
|
||||
get canDeleteSelected(): boolean {
|
||||
return this.selectedEntitiesIds.indexOf(this.userService.userId) === -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
import { ChangeDetectorRef, Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import WebViewer, { WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { environment } from '@environments/environment';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { debounce } from '../../../../utils/debounce';
|
||||
import { debounce } from '@utils/debounce';
|
||||
import { WatermarkControllerService, WatermarkModel } from '@redaction/red-ui-http';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { hexToRgb } from '../../../../utils/functions';
|
||||
import { hexToRgb } from '@utils/functions';
|
||||
import { BASE_HREF } from '../../../../tokens';
|
||||
|
||||
export const DEFAULT_WATERMARK: WatermarkModel = {
|
||||
@ -28,26 +28,12 @@ export const DEFAULT_WATERMARK: WatermarkModel = {
|
||||
styleUrls: ['./watermark-screen.component.scss']
|
||||
})
|
||||
export class WatermarkScreenComponent implements OnInit {
|
||||
private _instance: WebViewerInstance;
|
||||
private _watermark: WatermarkModel = {};
|
||||
|
||||
@ViewChild('viewer', { static: true })
|
||||
private _viewer: ElementRef;
|
||||
|
||||
viewReady = false;
|
||||
configForm: FormGroup;
|
||||
|
||||
get changed(): boolean {
|
||||
if (this._watermark === DEFAULT_WATERMARK) {
|
||||
return true;
|
||||
}
|
||||
for (const key of Object.keys(this._watermark)) {
|
||||
if (this._watermark[key] !== this.configForm.get(key)?.value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private _instance: WebViewerInstance;
|
||||
private _watermark: WatermarkModel = {};
|
||||
@ViewChild('viewer', { static: true })
|
||||
private _viewer: ElementRef;
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
@ -65,23 +51,20 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
this._initForm();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._loadWatermark();
|
||||
get changed(): boolean {
|
||||
if (this._watermark === DEFAULT_WATERMARK) {
|
||||
return true;
|
||||
}
|
||||
for (const key of Object.keys(this._watermark)) {
|
||||
if (this._watermark[key] !== this.configForm.get(key)?.value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _loadWatermark() {
|
||||
this._watermarkControllerService.getWatermark(this.appStateService.activeRuleSetId).subscribe(
|
||||
(watermark) => {
|
||||
this._watermark = watermark;
|
||||
this.configForm.setValue({ ...this._watermark });
|
||||
this._loadViewer();
|
||||
},
|
||||
() => {
|
||||
this._watermark = DEFAULT_WATERMARK;
|
||||
this.configForm.setValue({ ...this._watermark });
|
||||
this._loadViewer();
|
||||
}
|
||||
);
|
||||
ngOnInit(): void {
|
||||
this._loadWatermark();
|
||||
}
|
||||
|
||||
@debounce()
|
||||
@ -120,6 +103,28 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
|
||||
triggerChanges() {}
|
||||
|
||||
setValue(type: 'fontType' | 'orientation' | 'hexColor', value: any) {
|
||||
if (!this.configForm.get(type).disabled) {
|
||||
this.configForm.get(type).setValue(value);
|
||||
this.configChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private _loadWatermark() {
|
||||
this._watermarkControllerService.getWatermark(this.appStateService.activeRuleSetId).subscribe(
|
||||
(watermark) => {
|
||||
this._watermark = watermark;
|
||||
this.configForm.setValue({ ...this._watermark });
|
||||
this._loadViewer();
|
||||
},
|
||||
() => {
|
||||
this._watermark = DEFAULT_WATERMARK;
|
||||
this.configForm.setValue({ ...this._watermark });
|
||||
this._loadViewer();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private _loadViewer() {
|
||||
if (!this._instance) {
|
||||
WebViewer(
|
||||
@ -219,13 +224,6 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
setValue(type: 'fontType' | 'orientation' | 'hexColor', value: any) {
|
||||
if (!this.configForm.get(type).disabled) {
|
||||
this.configForm.get(type).setValue(value);
|
||||
this.configChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private _convertFont(fontType: any): number {
|
||||
switch (fontType) {
|
||||
case 'times-new-roman':
|
||||
|
||||
@ -16,9 +16,9 @@ import {
|
||||
import { AddEditFileAttributeDialogComponent } from '../dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
|
||||
import { AddEditDictionaryDialogComponent } from '../dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component';
|
||||
import { AddEditRuleSetDialogComponent } from '../dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component';
|
||||
import { NotificationService } from '../../../services/notification.service';
|
||||
import { ConfirmationDialogComponent } from '../../shared/dialogs/confirmation-dialog/confirmation-dialog.component';
|
||||
import { AppStateService } from '../../../state/app-state.service';
|
||||
import { NotificationService } from '@services/notification.service';
|
||||
import { ConfirmationDialogComponent } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { ConfirmDeleteFileAttributeDialogComponent } from '../dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component';
|
||||
import { EditColorDialogComponent } from '../dialogs/edit-color-dialog/edit-color-dialog.component';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import { AppLoadStateService } from '../../services/app-load-state.service';
|
||||
import { AppConfigKey, AppConfigService } from '../app-config/app-config.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { AppLoadStateService } from '@services/app-load-state.service';
|
||||
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||
import { BASE_HREF } from '../../tokens';
|
||||
|
||||
@Injectable({
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AppConfigModule } from '../app-config/app-config.module';
|
||||
import { AppConfigModule } from '@app-config/app-config.module';
|
||||
|
||||
import { KeycloakAngularModule, KeycloakOptions, KeycloakService } from 'keycloak-angular';
|
||||
import { AppConfigKey, AppConfigService } from '../app-config/app-config.service';
|
||||
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||
import { BASE_HREF } from '../../tokens';
|
||||
|
||||
export function keycloakInitializer(keycloak: KeycloakService, appConfigService: AppConfigService, baseUrl) {
|
||||
return () => appConfigService
|
||||
return () =>
|
||||
appConfigService
|
||||
.loadAppConfig()
|
||||
.toPromise()
|
||||
.then(() => {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import { AppLoadStateService } from '../../services/app-load-state.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { AppLoadStateService } from '@services/app-load-state.service';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { AnnotationPermissions } from '../../../../models/file/annotation.permissions';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||
import { AnnotationActionsService } from '../../services/annotation-actions.service';
|
||||
import { Annotations, WebViewerInstance } from '@pdftron/webviewer';
|
||||
|
||||
@ -27,6 +27,10 @@ export class AnnotationActionsComponent implements OnInit {
|
||||
private _permissionsService: PermissionsService
|
||||
) {}
|
||||
|
||||
get viewerAnnotation(): Annotations.Annotation {
|
||||
return this.viewer.annotManager.getAnnotationById(this.annotation.id);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.annotationPermissions = AnnotationPermissions.forUser(
|
||||
this._permissionsService.isManagerAndOwner(),
|
||||
@ -35,10 +39,6 @@ export class AnnotationActionsComponent implements OnInit {
|
||||
);
|
||||
}
|
||||
|
||||
get viewerAnnotation(): Annotations.Annotation {
|
||||
return this.viewer.annotManager.getAnnotationById(this.annotation.id);
|
||||
}
|
||||
|
||||
hideAnnotation($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
this.viewer.annotManager.hideAnnotations([this.viewerAnnotation]);
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { AnnotationActionsService } from '../../services/annotation-actions.service';
|
||||
import { AnnotationPermissions } from '../../../../models/file/annotation.permissions';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { MatMenuTrigger } from '@angular/material/menu';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FileManagementControllerService, ReanalysisControllerService } from '@redaction/red-ui-http';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { FileActionService } from '../../services/file-action.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { StatusOverlayService } from '../../../upload-download/services/status-overlay.service';
|
||||
import { StatusOverlayService } from '@upload-download/services/status-overlay.service';
|
||||
import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
|
||||
@Component({
|
||||
@ -16,8 +16,8 @@ import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
})
|
||||
export class ProjectOverviewBulkActionsComponent {
|
||||
@Input() selectedFileIds: string[];
|
||||
@Output() private _reload = new EventEmitter();
|
||||
loading = false;
|
||||
@Output() private _reload = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
@ -67,6 +67,30 @@ export class ProjectOverviewBulkActionsComponent {
|
||||
return this.selectedFiles.map((file) => file.fileStatus.status);
|
||||
}
|
||||
|
||||
// Under review
|
||||
get canSetToUnderReview() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true);
|
||||
}
|
||||
|
||||
// Under approval
|
||||
get canSetToUnderApproval() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file), true);
|
||||
}
|
||||
|
||||
// Approve
|
||||
get isReadyForApproval() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true);
|
||||
}
|
||||
|
||||
get canApprove() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canApprove(file), true);
|
||||
}
|
||||
|
||||
// Undo approval
|
||||
get canUndoApproval() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canUndoApproval(file), true);
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.loading = true;
|
||||
this._dialogService.openDeleteFilesDialog(null, this._appStateService.activeProject.project.projectId, this.selectedFileIds, () => {
|
||||
@ -93,42 +117,18 @@ export class ProjectOverviewBulkActionsComponent {
|
||||
this._performBulkAction(this._fileActionService.ocrFile(this.selectedFiles));
|
||||
}
|
||||
|
||||
// Under review
|
||||
get canSetToUnderReview() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true);
|
||||
}
|
||||
|
||||
setToUnderReview() {
|
||||
this._performBulkAction(this._fileActionService.setFileUnderReview(this.selectedFiles));
|
||||
}
|
||||
|
||||
// Under approval
|
||||
get canSetToUnderApproval() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file), true);
|
||||
}
|
||||
|
||||
setToUnderApproval() {
|
||||
this._performBulkAction(this._fileActionService.setFileUnderApproval(this.selectedFiles));
|
||||
}
|
||||
|
||||
// Approve
|
||||
get isReadyForApproval() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true);
|
||||
}
|
||||
|
||||
get canApprove() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canApprove(file), true);
|
||||
}
|
||||
|
||||
approveDocuments() {
|
||||
this._performBulkAction(this._fileActionService.setFileApproved(this.selectedFiles));
|
||||
}
|
||||
|
||||
// Undo approval
|
||||
get canUndoApproval() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canUndoApproval(file), true);
|
||||
}
|
||||
|
||||
private _performBulkAction(obs: Observable<any>) {
|
||||
this.loading = true;
|
||||
obs.subscribe().add(() => {
|
||||
|
||||
@ -2,11 +2,11 @@ import { ChangeDetectorRef, Component, Input } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Comment } from '@redaction/red-ui-http';
|
||||
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
||||
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-comments',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { FileAttributesConfig, FileStatus } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
|
||||
@Component({
|
||||
@ -22,11 +22,11 @@ export class DocumentInfoComponent {
|
||||
return this._appStateService.getProjectById(this.file.projectId);
|
||||
}
|
||||
|
||||
edit() {
|
||||
this._dialogService.openDocumentInfoDialog(this.file);
|
||||
}
|
||||
|
||||
get ruleSetName(): string {
|
||||
return this._appStateService.getRuleSetById(this.project.ruleSetId).name;
|
||||
}
|
||||
|
||||
edit() {
|
||||
this._dialogService.openDocumentInfoDialog(this.file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FileActionService } from '../../services/file-action.service';
|
||||
import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
|
||||
@ -25,6 +25,22 @@ export class FileActionsComponent implements OnInit {
|
||||
private readonly _fileActionService: FileActionService
|
||||
) {}
|
||||
|
||||
get tooltipPosition() {
|
||||
return this.screen === 'file-preview' ? 'below' : 'above';
|
||||
}
|
||||
|
||||
get buttonType() {
|
||||
return this.screen === 'file-preview' ? 'default' : 'dark-bg';
|
||||
}
|
||||
|
||||
get toggleTooltip(): string {
|
||||
if (!this.permissionsService.isManager()) {
|
||||
return 'file-preview.toggle-analysis.only-managers';
|
||||
}
|
||||
|
||||
return this.fileStatus?.isExcluded ? 'file-preview.toggle-analysis.enable' : 'file-preview.toggle-analysis.disable';
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!this.fileStatus) {
|
||||
this.fileStatus = this.appStateService.activeFile;
|
||||
@ -43,14 +59,6 @@ export class FileActionsComponent implements OnInit {
|
||||
this.actionPerformed.emit('view-document-info');
|
||||
}
|
||||
|
||||
get tooltipPosition() {
|
||||
return this.screen === 'file-preview' ? 'below' : 'above';
|
||||
}
|
||||
|
||||
get buttonType() {
|
||||
return this.screen === 'file-preview' ? 'default' : 'dark-bg';
|
||||
}
|
||||
|
||||
openDeleteFileDialog($event: MouseEvent, fileStatusWrapper: FileStatusWrapper) {
|
||||
this._dialogService.openDeleteFilesDialog($event, fileStatusWrapper.projectId, [fileStatusWrapper.fileId], () => {
|
||||
this.actionPerformed.emit('delete');
|
||||
@ -110,12 +118,4 @@ export class FileActionsComponent implements OnInit {
|
||||
await this.appStateService.getFiles();
|
||||
this.actionPerformed.emit(this.fileStatus?.isExcluded ? 'enable-analysis' : 'disable-analysis');
|
||||
}
|
||||
|
||||
get toggleTooltip(): string {
|
||||
if (!this.permissionsService.isManager()) {
|
||||
return 'file-preview.toggle-analysis.only-managers';
|
||||
}
|
||||
|
||||
return this.fileStatus?.isExcluded ? 'file-preview.toggle-analysis.enable' : 'file-preview.toggle-analysis.disable';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { FilterModel } from '../../../shared/components/filter/model/filter.model';
|
||||
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
|
||||
import { FilterModel } from '@shared/components/filter/model/filter.model';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
|
||||
import { MatDialogRef, MatDialogState } from '@angular/material/dialog';
|
||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||
import { debounce } from '../../../../utils/debounce';
|
||||
import { FileDataModel } from '../../../../models/file/file-data.model';
|
||||
import { debounce } from '@utils/debounce';
|
||||
import { FileDataModel } from '@models/file/file-data.model';
|
||||
|
||||
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
|
||||
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
||||
@ -17,13 +17,6 @@ const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
||||
})
|
||||
export class FileWorkloadComponent {
|
||||
displayedAnnotations: { [key: number]: { annotations: AnnotationWrapper[] } } = {};
|
||||
private _annotations: AnnotationWrapper[];
|
||||
|
||||
@Input()
|
||||
set annotations(value: AnnotationWrapper[]) {
|
||||
this._annotations = value;
|
||||
}
|
||||
|
||||
@Input() selectedAnnotations: AnnotationWrapper[];
|
||||
@Input() activeViewerPage: number;
|
||||
@Input() shouldDeselectAnnotationsOnPageChange: boolean;
|
||||
@ -33,22 +26,28 @@ export class FileWorkloadComponent {
|
||||
@Input() fileData: FileDataModel;
|
||||
@Input() hideSkipped: boolean;
|
||||
@Input() annotationActionsTemplate: TemplateRef<any>;
|
||||
|
||||
@Output() shouldDeselectAnnotationsOnPageChangeChange = new EventEmitter<boolean>();
|
||||
@Output() selectAnnotations = new EventEmitter<AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }>();
|
||||
@Output() deselectAnnotations = new EventEmitter<AnnotationWrapper[]>();
|
||||
@Output() selectPage = new EventEmitter<number>();
|
||||
@Output() toggleSkipped = new EventEmitter<any>();
|
||||
@Output() annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
||||
|
||||
quickScrollFirstEnabled = false;
|
||||
quickScrollLastEnabled = false;
|
||||
displayedPages: number[] = [];
|
||||
pagesPanelActive = true;
|
||||
|
||||
@ViewChild('annotationsElement') private _annotationsElement: ElementRef;
|
||||
@ViewChild('quickNavigation') private _quickNavigationElement: ElementRef;
|
||||
|
||||
constructor(private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _annotationProcessingService: AnnotationProcessingService) {}
|
||||
|
||||
private _annotations: AnnotationWrapper[];
|
||||
|
||||
@Input()
|
||||
set annotations(value: AnnotationWrapper[]) {
|
||||
this._annotations = value;
|
||||
}
|
||||
|
||||
private _multiSelectActive = false;
|
||||
|
||||
get multiSelectActive(): boolean {
|
||||
@ -65,8 +64,6 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _annotationProcessingService: AnnotationProcessingService) {}
|
||||
|
||||
private get _firstSelectedAnnotation() {
|
||||
return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null;
|
||||
}
|
||||
@ -218,6 +215,18 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
}
|
||||
|
||||
jumpToPreviousWithAnnotations() {
|
||||
this.selectPage.emit(this._prevPageWithAnnotations());
|
||||
}
|
||||
|
||||
jumpToNextWithAnnotations() {
|
||||
this.selectPage.emit(this._nextPageWithAnnotations());
|
||||
}
|
||||
|
||||
_(filter): FilterModel {
|
||||
return filter as FilterModel;
|
||||
}
|
||||
|
||||
private _selectFirstAnnotationOnCurrentPageIfNecessary() {
|
||||
if (
|
||||
(!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) &&
|
||||
@ -227,14 +236,6 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
}
|
||||
|
||||
jumpToPreviousWithAnnotations() {
|
||||
this.selectPage.emit(this._prevPageWithAnnotations());
|
||||
}
|
||||
|
||||
jumpToNextWithAnnotations() {
|
||||
this.selectPage.emit(this._nextPageWithAnnotations());
|
||||
}
|
||||
|
||||
private _navigateAnnotations($event: KeyboardEvent) {
|
||||
if (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) {
|
||||
const pageIdx = this.displayedPages.indexOf(this.activeViewerPage);
|
||||
@ -347,8 +348,4 @@ export class FileWorkloadComponent {
|
||||
const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(`#quick-nav-page-${page}`);
|
||||
FileWorkloadComponent._scrollToFirstElement(elements);
|
||||
}
|
||||
|
||||
_(filter): FilterModel {
|
||||
return filter as FilterModel;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
||||
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-needs-work-badge',
|
||||
@ -14,14 +14,6 @@ export class NeedsWorkBadgeComponent {
|
||||
|
||||
constructor(private readonly _appStateService: AppStateService, private readonly _permissionsService: PermissionsService) {}
|
||||
|
||||
reanalysisRequired() {
|
||||
if (this.needsWorkInput instanceof ProjectWrapper) {
|
||||
return this._permissionsService.projectReanalysisRequired(this.needsWorkInput);
|
||||
} else {
|
||||
return this._permissionsService.fileRequiresReanalysis(this.needsWorkInput);
|
||||
}
|
||||
}
|
||||
|
||||
get suggestionColor() {
|
||||
return this._getDictionaryColor('suggestion');
|
||||
}
|
||||
@ -58,6 +50,14 @@ export class NeedsWorkBadgeComponent {
|
||||
return this.needsWorkInput instanceof FileStatusWrapper && (<any>this.needsWorkInput).hasAnnotationComments;
|
||||
}
|
||||
|
||||
reanalysisRequired() {
|
||||
if (this.needsWorkInput instanceof ProjectWrapper) {
|
||||
return this._permissionsService.projectReanalysisRequired(this.needsWorkInput);
|
||||
} else {
|
||||
return this._permissionsService.fileRequiresReanalysis(this.needsWorkInput);
|
||||
}
|
||||
}
|
||||
|
||||
private _getDictionaryColor(type: string) {
|
||||
let ruleSetId = null;
|
||||
if (this.needsWorkInput instanceof ProjectWrapper) {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core';
|
||||
import { ViewedPages, ViewedPagesControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
@ -29,6 +29,10 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy {
|
||||
private readonly _permissionService: PermissionsService
|
||||
) {}
|
||||
|
||||
get read() {
|
||||
return this.viewedPages?.pages?.indexOf(this.number) >= 0;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._subscription = this._appStateService.fileChanged.subscribe(() => {
|
||||
this.canMarkPagesAsViewed = this._permissionService.canMarkPagesAsViewed();
|
||||
@ -41,8 +45,20 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
get read() {
|
||||
return this.viewedPages?.pages?.indexOf(this.number) >= 0;
|
||||
toggleReadState() {
|
||||
if (this.canMarkPagesAsViewed) {
|
||||
if (this.read) {
|
||||
this._markPageUnread();
|
||||
} else {
|
||||
this._markPageRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this._subscription) {
|
||||
this._subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
private _handlePageRead() {
|
||||
@ -60,20 +76,6 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
private _markPageRead() {
|
||||
this._viewedPagesControllerService
|
||||
.addPage({ page: this.number }, this._appStateService.activeProjectId, this._appStateService.activeFileId)
|
||||
.subscribe(() => {
|
||||
this.viewedPages?.pages?.push(this.number);
|
||||
});
|
||||
}
|
||||
|
||||
private _markPageUnread() {
|
||||
this._viewedPagesControllerService.removePage(this._appStateService.activeProjectId, this._appStateService.activeFileId, this.number).subscribe(() => {
|
||||
this.viewedPages?.pages?.splice(this.viewedPages?.pages?.indexOf(this.number), 1);
|
||||
});
|
||||
}
|
||||
|
||||
// @HostListener('window:keydown', ['$event'])
|
||||
// handleKeyDown(event: KeyboardEvent) {
|
||||
// if (this.canMarkPagesAsViewed) {
|
||||
@ -91,19 +93,17 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy {
|
||||
// }
|
||||
// }
|
||||
|
||||
toggleReadState() {
|
||||
if (this.canMarkPagesAsViewed) {
|
||||
if (this.read) {
|
||||
this._markPageUnread();
|
||||
} else {
|
||||
this._markPageRead();
|
||||
}
|
||||
}
|
||||
private _markPageRead() {
|
||||
this._viewedPagesControllerService
|
||||
.addPage({ page: this.number }, this._appStateService.activeProjectId, this._appStateService.activeFileId)
|
||||
.subscribe(() => {
|
||||
this.viewedPages?.pages?.push(this.number);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this._subscription) {
|
||||
this._subscription.unsubscribe();
|
||||
}
|
||||
private _markPageUnread() {
|
||||
this._viewedPagesControllerService.removePage(this._appStateService.activeProjectId, this._appStateService.activeFileId, this.number).subscribe(() => {
|
||||
this.viewedPages?.pages?.splice(this.viewedPages?.pages?.indexOf(this.number), 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,15 +2,15 @@ import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Input, NgZo
|
||||
import { ManualRedactionEntry, Rectangle } from '@redaction/red-ui-http';
|
||||
import WebViewer, { Annotations, Tools, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ManualRedactionEntryWrapper } from '../../../../models/file/manual-redaction-entry.wrapper';
|
||||
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
|
||||
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
||||
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { environment } from '@environments/environment';
|
||||
import { AnnotationDrawService } from '../../services/annotation-draw.service';
|
||||
import { AnnotationActionsService } from '../../services/annotation-actions.service';
|
||||
import { UserPreferenceService } from '../../../../services/user-preference.service';
|
||||
import { translateQuads } from '../../../../utils/pdf-coordinates';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { translateQuads } from '@utils/pdf-coordinates';
|
||||
import { BASE_HREF } from '../../../../tokens';
|
||||
import Tool = Tools.Tool;
|
||||
|
||||
@ -20,17 +20,12 @@ import Tool = Tools.Tool;
|
||||
styleUrls: ['./pdf-viewer.component.scss']
|
||||
})
|
||||
export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
private _selectedText = '';
|
||||
private _defaultTool: Tool;
|
||||
private readonly _allowedKeyboardShortcuts = ['+', '-', 'p', 'r', 'Escape'];
|
||||
|
||||
@Input() fileData: Blob;
|
||||
@Input() fileStatus: FileStatusWrapper;
|
||||
@Input() canPerformActions = false;
|
||||
@Input() annotations: AnnotationWrapper[];
|
||||
@Input() shouldDeselectAnnotationsOnPageChange = true;
|
||||
@Input() multiSelectActive: boolean;
|
||||
|
||||
@Output() fileReady = new EventEmitter();
|
||||
@Output() annotationSelected = new EventEmitter<string[]>();
|
||||
@Output() manualAnnotationRequested = new EventEmitter<ManualRedactionEntryWrapper>();
|
||||
@ -38,9 +33,11 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
@Output() keyUp = new EventEmitter<KeyboardEvent>();
|
||||
@Output() viewerReady = new EventEmitter<WebViewerInstance>();
|
||||
@Output() annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
||||
|
||||
@ViewChild('viewer', { static: true }) viewer: ElementRef;
|
||||
instance: WebViewerInstance;
|
||||
private _selectedText = '';
|
||||
private _defaultTool: Tool;
|
||||
private readonly _allowedKeyboardShortcuts = ['+', '-', 'p', 'r', 'Escape'];
|
||||
|
||||
constructor(
|
||||
@Inject(BASE_HREF) private readonly _baseHref: string,
|
||||
@ -71,6 +68,50 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
this._loadViewer();
|
||||
}
|
||||
|
||||
deselectAllAnnotations() {
|
||||
this.instance.annotManager.deselectAllAnnotations();
|
||||
}
|
||||
|
||||
selectAnnotations($event: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }) {
|
||||
let annotations: AnnotationWrapper[];
|
||||
let multiSelect: boolean;
|
||||
if ($event instanceof Array) {
|
||||
annotations = $event;
|
||||
multiSelect = false;
|
||||
} else {
|
||||
annotations = $event.annotations;
|
||||
multiSelect = $event.multiSelect;
|
||||
}
|
||||
|
||||
if (!this.multiSelectActive && !multiSelect) {
|
||||
this.deselectAllAnnotations();
|
||||
}
|
||||
|
||||
const annotationsFromViewer = annotations.map((ann) => this.instance.annotManager.getAnnotationById(ann.id));
|
||||
this.instance.annotManager.selectAnnotations(annotationsFromViewer);
|
||||
this.navigateToPage(annotations[0].pageNumber);
|
||||
this.instance.annotManager.jumpToAnnotation(annotationsFromViewer[0]);
|
||||
}
|
||||
|
||||
deselectAnnotations(annotations: AnnotationWrapper[]) {
|
||||
this.instance.annotManager.deselectAnnotations(annotations.map((ann) => this.instance.annotManager.getAnnotationById(ann.id)));
|
||||
}
|
||||
|
||||
navigateToPage(pageNumber: number) {
|
||||
const activePage = this.instance.docViewer.getCurrentPage();
|
||||
if (activePage !== pageNumber) {
|
||||
this.instance.docViewer.displayPageLocation(pageNumber, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
setInitialViewerState() {
|
||||
// viewer init
|
||||
this.instance.setFitMode('FitPage');
|
||||
const instanceDisplayMode = this.instance.docViewer.getDisplayModeManager().getDisplayMode();
|
||||
instanceDisplayMode.mode = 'Single';
|
||||
this.instance.docViewer.getDisplayModeManager().setDisplayMode(instanceDisplayMode);
|
||||
}
|
||||
|
||||
private _loadViewer() {
|
||||
WebViewer(
|
||||
{
|
||||
@ -394,42 +435,6 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
};
|
||||
}
|
||||
|
||||
deselectAllAnnotations() {
|
||||
this.instance.annotManager.deselectAllAnnotations();
|
||||
}
|
||||
|
||||
selectAnnotations($event: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }) {
|
||||
let annotations: AnnotationWrapper[];
|
||||
let multiSelect: boolean;
|
||||
if ($event instanceof Array) {
|
||||
annotations = $event;
|
||||
multiSelect = false;
|
||||
} else {
|
||||
annotations = $event.annotations;
|
||||
multiSelect = $event.multiSelect;
|
||||
}
|
||||
|
||||
if (!this.multiSelectActive && !multiSelect) {
|
||||
this.deselectAllAnnotations();
|
||||
}
|
||||
|
||||
const annotationsFromViewer = annotations.map((ann) => this.instance.annotManager.getAnnotationById(ann.id));
|
||||
this.instance.annotManager.selectAnnotations(annotationsFromViewer);
|
||||
this.navigateToPage(annotations[0].pageNumber);
|
||||
this.instance.annotManager.jumpToAnnotation(annotationsFromViewer[0]);
|
||||
}
|
||||
|
||||
deselectAnnotations(annotations: AnnotationWrapper[]) {
|
||||
this.instance.annotManager.deselectAnnotations(annotations.map((ann) => this.instance.annotManager.getAnnotationById(ann.id)));
|
||||
}
|
||||
|
||||
navigateToPage(pageNumber: number) {
|
||||
const activePage = this.instance.docViewer.getCurrentPage();
|
||||
if (activePage !== pageNumber) {
|
||||
this.instance.docViewer.displayPageLocation(pageNumber, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private _loadDocument() {
|
||||
if (this.fileData) {
|
||||
this.instance.loadDocument(this.fileData, {
|
||||
@ -446,14 +451,6 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
});
|
||||
}
|
||||
|
||||
setInitialViewerState() {
|
||||
// viewer init
|
||||
this.instance.setFitMode('FitPage');
|
||||
const instanceDisplayMode = this.instance.docViewer.getDisplayModeManager().getDisplayMode();
|
||||
instanceDisplayMode.mode = 'Single';
|
||||
this.instance.docViewer.getDisplayModeManager().setDisplayMode(instanceDisplayMode);
|
||||
}
|
||||
|
||||
private _disableHotkeys() {
|
||||
this.instance.hotkeys.off('CTRL+SHIFT+EQUAL');
|
||||
this.instance.hotkeys.off('COMMAND+SHIFT+EQUAL');
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { groupBy } from '../../../../utils/functions';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { groupBy } from '@utils/functions';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { Router } from '@angular/router';
|
||||
import { FilterModel } from '../../../shared/components/filter/model/filter.model';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { TranslateChartService } from '../../../../services/translate-chart.service';
|
||||
import { StatusSorter } from '../../../../utils/sorters/status-sorter';
|
||||
import { FilterModel } from '@shared/components/filter/model/filter.model';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { StatusSorter } from '@utils/sorters/status-sorter';
|
||||
import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
|
||||
@Component({
|
||||
@ -30,6 +30,14 @@ export class ProjectDetailsComponent implements OnInit {
|
||||
private readonly _router: Router
|
||||
) {}
|
||||
|
||||
get memberIds(): string[] {
|
||||
return this.appStateService.activeProject.project.memberIds;
|
||||
}
|
||||
|
||||
get hasFiles(): boolean {
|
||||
return this.appStateService.activeProject.hasFiles;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.calculateChartConfig();
|
||||
this.appStateService.fileChanged.subscribe(() => {
|
||||
@ -37,10 +45,6 @@ export class ProjectDetailsComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
get memberIds(): string[] {
|
||||
return this.appStateService.activeProject.project.memberIds;
|
||||
}
|
||||
|
||||
calculateChartConfig(): void {
|
||||
if (this.appStateService.activeProject) {
|
||||
const groups = groupBy(this.appStateService.activeProject?.files, 'status');
|
||||
@ -54,10 +58,6 @@ export class ProjectDetailsComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
get hasFiles(): boolean {
|
||||
return this.appStateService.activeProject.hasFiles;
|
||||
}
|
||||
|
||||
toggleFilter(filterType: 'needsWorkFilters' | 'statusFilters', key: string): void {
|
||||
const filter = this.filters[filterType].find((f) => f.key === key);
|
||||
filter.checked = !filter.checked;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
||||
import { StatusSorter } from '../../../../utils/sorters/status-sorter';
|
||||
import { download } from '../../../../utils/file-download-utils';
|
||||
import { computerize } from '../../../../utils/functions';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
import { StatusSorter } from '@utils/sorters/status-sorter';
|
||||
import { download } from '@utils/file-download-utils';
|
||||
import { computerize } from '@utils/functions';
|
||||
import { FileManagementControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { FilterModel } from '../../../shared/components/filter/model/filter.model';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FilterModel } from '@shared/components/filter/model/filter.model';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-listing-details',
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-team-members',
|
||||
@ -30,14 +30,14 @@ export class TeamMembersComponent {
|
||||
return this.expandedTeam || !this.overflowCount ? this.memberIds : this.memberIds.slice(0, this.maxTeamMembersBeforeExpand - 1);
|
||||
}
|
||||
|
||||
toggleExpandedTeam() {
|
||||
this.expandedTeam = !this.expandedTeam;
|
||||
}
|
||||
|
||||
get overflowCount() {
|
||||
return this.memberIds.length > this.maxTeamMembersBeforeExpand ? this.memberIds.length - (this.maxTeamMembersBeforeExpand - 1) : 0;
|
||||
}
|
||||
|
||||
toggleExpandedTeam() {
|
||||
this.expandedTeam = !this.expandedTeam;
|
||||
}
|
||||
|
||||
canRemoveMember(userId: string) {
|
||||
return this.canRemove && this.unremovableMembers.indexOf(userId) === -1;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-type-annotation-icon',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FilterModel } from '../../../shared/components/filter/model/filter.model';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { FilterModel } from '@shared/components/filter/model/filter.model';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-type-filter',
|
||||
@ -22,11 +22,12 @@ export class TypeFilterComponent implements OnInit {
|
||||
];
|
||||
private _needsAnalysisKeys = ['add-dictionary', 'remove-dictionary', 'remove-only-here', 'pending-analysis', 'analysis'];
|
||||
|
||||
isSuggestion = (key: string) => this._suggestionsKeys.includes(key);
|
||||
needsAnalysis = (key: string) => this._needsAnalysisKeys.includes(key);
|
||||
|
||||
constructor(private readonly _appStateService: AppStateService) {}
|
||||
|
||||
isSuggestion = (key: string) => this._suggestionsKeys.includes(key);
|
||||
|
||||
needsAnalysis = (key: string) => this._needsAnalysisKeys.includes(key);
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dictionaryColor = this._appStateService.getDictionaryColor(this.filter.key);
|
||||
}
|
||||
|
||||
@ -2,8 +2,8 @@ import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Project, RuleSetModel } from '@redaction/red-ui-http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
import * as moment from 'moment';
|
||||
|
||||
@Component({
|
||||
@ -44,17 +44,6 @@ export class AddEditProjectDialogComponent {
|
||||
return this.projectForm.controls['downloadFileTypes']?.value?.length ? this.projectForm.controls['downloadFileTypes'].value.length : 0;
|
||||
}
|
||||
|
||||
private _filterInvalidRuleSets() {
|
||||
this.ruleSets = this._appStateService.ruleSets.filter((r) => {
|
||||
if (this.project?.ruleSetId === r.ruleSetId) {
|
||||
return true;
|
||||
}
|
||||
const notYetValid = !!r.validFrom && moment(r.validFrom).isAfter(moment());
|
||||
const notValidAnymore = !!r.validTo && moment(r.validTo).add(1, 'd').isBefore(moment());
|
||||
return !(notYetValid || notValidAnymore);
|
||||
});
|
||||
}
|
||||
|
||||
get changed() {
|
||||
if (!this.project) {
|
||||
return true;
|
||||
@ -103,17 +92,6 @@ export class AddEditProjectDialogComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private _formToObject(): Project {
|
||||
return {
|
||||
projectName: this.projectForm.get('projectName').value,
|
||||
description: this.projectForm.get('description').value,
|
||||
dueDate: this.hasDueDate ? this.projectForm.get('dueDate').value : undefined,
|
||||
ruleSetId: this.projectForm.get('ruleSetId').value,
|
||||
downloadFileTypes: this.projectForm.get('downloadFileTypes').value,
|
||||
reportTypes: this.projectForm.get('reportTypes').value
|
||||
};
|
||||
}
|
||||
|
||||
async saveProjectAndAddMembers() {
|
||||
const project: Project = this._formToObject();
|
||||
project.projectId = this.project?.projectId;
|
||||
@ -140,4 +118,26 @@ export class AddEditProjectDialogComponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _filterInvalidRuleSets() {
|
||||
this.ruleSets = this._appStateService.ruleSets.filter((r) => {
|
||||
if (this.project?.ruleSetId === r.ruleSetId) {
|
||||
return true;
|
||||
}
|
||||
const notYetValid = !!r.validFrom && moment(r.validFrom).isAfter(moment());
|
||||
const notValidAnymore = !!r.validTo && moment(r.validTo).add(1, 'd').isBefore(moment());
|
||||
return !(notYetValid || notValidAnymore);
|
||||
});
|
||||
}
|
||||
|
||||
private _formToObject(): Project {
|
||||
return {
|
||||
projectName: this.projectForm.get('projectName').value,
|
||||
description: this.projectForm.get('description').value,
|
||||
dueDate: this.hasDueDate ? this.projectForm.get('dueDate').value : undefined,
|
||||
ruleSetId: this.projectForm.get('ruleSetId').value,
|
||||
downloadFileTypes: this.projectForm.get('downloadFileTypes').value,
|
||||
reportTypes: this.projectForm.get('reportTypes').value
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { ProjectControllerService, StatusControllerService } from '@redaction/red-ui-http';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
||||
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
|
||||
class DialogData {
|
||||
type: 'file' | 'project';
|
||||
@ -37,39 +37,6 @@ export class AssignOwnerDialogComponent {
|
||||
this._loadData();
|
||||
}
|
||||
|
||||
private _loadData() {
|
||||
if (this.data.type === 'project') {
|
||||
const project = this.data.project;
|
||||
this.usersForm = this._formBuilder.group({
|
||||
singleUser: [project?.ownerId, Validators.required],
|
||||
approvers: [[...project?.approverIds]],
|
||||
members: [[...project?.memberIds]]
|
||||
});
|
||||
this.searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
this.usersForm.get('singleUser').valueChanges.subscribe((singleUser) => {
|
||||
if (!this.isApprover(singleUser)) {
|
||||
this.toggleApprover(singleUser);
|
||||
}
|
||||
// If it is an approver, it is already a member, no need to check
|
||||
});
|
||||
}
|
||||
|
||||
if (this.data.type === 'file') {
|
||||
const uniqueReviewers = new Set<string>();
|
||||
for (const file of this.data.files) {
|
||||
if (file.currentReviewer) {
|
||||
uniqueReviewers.add(file.currentReviewer);
|
||||
}
|
||||
}
|
||||
const singleUser = uniqueReviewers.size === 1 ? uniqueReviewers.values().next().value : this.userService.userId;
|
||||
this.usersForm = this._formBuilder.group({
|
||||
singleUser: [singleUser]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get selectedSingleUser(): string {
|
||||
return this.usersForm.get('singleUser').value;
|
||||
}
|
||||
@ -86,6 +53,49 @@ export class AssignOwnerDialogComponent {
|
||||
return this.usersForm.get('members').value;
|
||||
}
|
||||
|
||||
get singleUsersSelectOptions() {
|
||||
return this.data.type === 'file' ? this._appStateService.activeProject.memberIds : this.userService.managerUsers.map((m) => m.userId);
|
||||
}
|
||||
|
||||
get multiUsersSelectOptions() {
|
||||
const searchQuery = this.searchForm.get('query').value;
|
||||
return this.userService.eligibleUsers
|
||||
.filter((user) => this.userService.getNameForId(user.userId).toLowerCase().includes(searchQuery.toLowerCase()))
|
||||
.map((user) => user.userId);
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
if (this.data.ignoreChanged) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.data.type === 'project') {
|
||||
if (this.data.project.ownerId !== this.selectedSingleUser) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const initialMembers = this.data.project.memberIds.sort();
|
||||
const currentMembers = this.selectedUsersList.sort();
|
||||
|
||||
const initialApprovers = this.data.project.approverIds.sort();
|
||||
const currentApprovers = this.selectedApproversList.sort();
|
||||
|
||||
if (this._compareLists(initialMembers, currentMembers) || this._compareLists(initialApprovers, currentApprovers)) {
|
||||
return true;
|
||||
}
|
||||
} else if (this.data.type === 'file') {
|
||||
const reviewerId = this.selectedSingleUser;
|
||||
|
||||
for (const file of this.data.files) {
|
||||
if (file.currentReviewer !== reviewerId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
isOwner(userId: string): boolean {
|
||||
return userId === this.selectedSingleUser;
|
||||
}
|
||||
@ -127,17 +137,6 @@ export class AssignOwnerDialogComponent {
|
||||
this.dialogRef.close(result);
|
||||
}
|
||||
|
||||
get singleUsersSelectOptions() {
|
||||
return this.data.type === 'file' ? this._appStateService.activeProject.memberIds : this.userService.managerUsers.map((m) => m.userId);
|
||||
}
|
||||
|
||||
get multiUsersSelectOptions() {
|
||||
const searchQuery = this.searchForm.get('query').value;
|
||||
return this.userService.eligibleUsers
|
||||
.filter((user) => this.userService.getNameForId(user.userId).toLowerCase().includes(searchQuery.toLowerCase()))
|
||||
.map((user) => user.userId);
|
||||
}
|
||||
|
||||
isMemberSelected(userId: string): boolean {
|
||||
return this.selectedUsersList.indexOf(userId) !== -1;
|
||||
}
|
||||
@ -175,6 +174,39 @@ export class AssignOwnerDialogComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private _loadData() {
|
||||
if (this.data.type === 'project') {
|
||||
const project = this.data.project;
|
||||
this.usersForm = this._formBuilder.group({
|
||||
singleUser: [project?.ownerId, Validators.required],
|
||||
approvers: [[...project?.approverIds]],
|
||||
members: [[...project?.memberIds]]
|
||||
});
|
||||
this.searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
this.usersForm.get('singleUser').valueChanges.subscribe((singleUser) => {
|
||||
if (!this.isApprover(singleUser)) {
|
||||
this.toggleApprover(singleUser);
|
||||
}
|
||||
// If it is an approver, it is already a member, no need to check
|
||||
});
|
||||
}
|
||||
|
||||
if (this.data.type === 'file') {
|
||||
const uniqueReviewers = new Set<string>();
|
||||
for (const file of this.data.files) {
|
||||
if (file.currentReviewer) {
|
||||
uniqueReviewers.add(file.currentReviewer);
|
||||
}
|
||||
}
|
||||
const singleUser = uniqueReviewers.size === 1 ? uniqueReviewers.values().next().value : this.userService.userId;
|
||||
this.usersForm = this._formBuilder.group({
|
||||
singleUser: [singleUser]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _compareLists(l1: string[], l2: string[]) {
|
||||
if (l1.length !== l2.length) {
|
||||
return true;
|
||||
@ -188,36 +220,4 @@ export class AssignOwnerDialogComponent {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
if (this.data.ignoreChanged) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.data.type === 'project') {
|
||||
if (this.data.project.ownerId !== this.selectedSingleUser) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const initialMembers = this.data.project.memberIds.sort();
|
||||
const currentMembers = this.selectedUsersList.sort();
|
||||
|
||||
const initialApprovers = this.data.project.approverIds.sort();
|
||||
const currentApprovers = this.selectedApproversList.sort();
|
||||
|
||||
if (this._compareLists(initialMembers, currentMembers) || this._compareLists(initialApprovers, currentApprovers)) {
|
||||
return true;
|
||||
}
|
||||
} else if (this.data.type === 'file') {
|
||||
const reviewerId = this.selectedSingleUser;
|
||||
|
||||
for (const file of this.data.files) {
|
||||
if (file.currentReviewer !== reviewerId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { FileAttributeConfig, FileAttributesControllerService, FileStatus } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-document-info-dialog',
|
||||
@ -32,7 +32,13 @@ export class DocumentInfoDialogComponent implements OnInit {
|
||||
this.attributes = (await this._fileAttributesService.getFileAttributesConfiguration(this._project.ruleSetId).toPromise()).fileAttributeConfigs.filter(
|
||||
(attr) => attr.editable
|
||||
);
|
||||
const formConfig = this.attributes.reduce((acc, attr) => ({ ...acc, [attr.id]: [this.file.fileAttributes?.attributeIdToValue[attr.id]] }), {});
|
||||
const formConfig = this.attributes.reduce(
|
||||
(acc, attr) => ({
|
||||
...acc,
|
||||
[attr.id]: [this.file.fileAttributes?.attributeIdToValue[attr.id]]
|
||||
}),
|
||||
{}
|
||||
);
|
||||
this.documentInfoForm = this._formBuilder.group(formConfig);
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { ForceRedactionRequest, LegalBasisMappingControllerService } from '@redaction/red-ui-http';
|
||||
import { NotificationService } from '../../../../services/notification.service';
|
||||
import { NotificationService } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
export interface LegalBasisOption {
|
||||
label?: string;
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { AddRedactionRequest, LegalBasisMappingControllerService, TypeValue } from '@redaction/red-ui-http';
|
||||
import { NotificationService } from '../../../../services/notification.service';
|
||||
import { NotificationService } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { ManualRedactionEntryWrapper } from '../../../../models/file/manual-redaction-entry.wrapper';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
||||
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
||||
import { ManualAnnotationResponse } from '../../../../models/file/manual-annotation-response';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { ManualAnnotationResponse } from '@models/file/manual-annotation-response';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
export interface LegalBasisOption {
|
||||
label?: string;
|
||||
@ -32,10 +32,6 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
redactionDictionaries: TypeValue[] = [];
|
||||
legalOptions: LegalBasisOption[] = [];
|
||||
|
||||
get title() {
|
||||
return this._manualAnnotationService.getTitle(this.manualRedactionEntryWrapper.type);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _userService: UserService,
|
||||
@ -49,6 +45,18 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
@Inject(MAT_DIALOG_DATA) public manualRedactionEntryWrapper: ManualRedactionEntryWrapper
|
||||
) {}
|
||||
|
||||
get title() {
|
||||
return this._manualAnnotationService.getTitle(this.manualRedactionEntryWrapper.type);
|
||||
}
|
||||
|
||||
get displayedDictionaryLabel() {
|
||||
const dictType = this.redactionForm.get('dictionary').value;
|
||||
if (dictType) {
|
||||
return this.redactionDictionaries.find((d) => d.type === dictType).label;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this._legalBasisMappingControllerService.getLegalBasisMapping(this._appStateService.activeProject.ruleSetId).subscribe((data) => {
|
||||
data.map((lbm) => {
|
||||
@ -84,14 +92,6 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
this.redactionDictionaries.sort((a, b) => a.label.localeCompare(b.label));
|
||||
}
|
||||
|
||||
get displayedDictionaryLabel() {
|
||||
const dictType = this.redactionForm.get('dictionary').value;
|
||||
if (dictType) {
|
||||
return this.redactionDictionaries.find((d) => d.type === dictType).label;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
handleAddRedaction() {
|
||||
this._enhanceManualRedaction(this.manualRedactionEntryWrapper.manualRedactionEntry);
|
||||
this._manualAnnotationService.addAnnotation(this.manualRedactionEntryWrapper.manualRedactionEntry).subscribe(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { ProjectListingScreenComponent } from './screens/project-listing-screen/project-listing-screen.component';
|
||||
import { CompositeRouteGuard } from '../../guards/composite-route.guard';
|
||||
import { CompositeRouteGuard } from '@guards/composite-route.guard';
|
||||
import { AuthGuard } from '../auth/auth.guard';
|
||||
import { RedRoleGuard } from '../auth/red-role.guard';
|
||||
import { AppStateGuard } from '../../state/app-state.guard';
|
||||
import { AppStateGuard } from '@state/app-state.guard';
|
||||
import { ProjectOverviewScreenComponent } from './screens/project-overview-screen/project-overview-screen.component';
|
||||
import { FilePreviewScreenComponent } from './screens/file-preview-screen/file-preview-screen.component';
|
||||
|
||||
|
||||
@ -24,9 +24,9 @@ import { TeamMembersComponent } from './components/team-members/team-members.com
|
||||
import { ProjectListingActionsComponent } from './components/project-listing-actions/project-listing-actions.component';
|
||||
import { DocumentInfoComponent } from './components/document-info/document-info.component';
|
||||
import { FileWorkloadComponent } from './components/file-workload/file-workload.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { ProjectsRoutingModule } from './projects-routing.module';
|
||||
import { FileUploadDownloadModule } from '../upload-download/file-upload-download.module';
|
||||
import { FileUploadDownloadModule } from '@upload-download/file-upload-download.module';
|
||||
import { ProjectsDialogService } from './services/projects-dialog.service';
|
||||
import { AnnotationActionsService } from './services/annotation-actions.service';
|
||||
import { FileActionService } from './services/file-action.service';
|
||||
|
||||
@ -1,34 +1,34 @@
|
||||
import { ChangeDetectorRef, Component, HostListener, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { ActivatedRoute, ActivatedRouteSnapshot, Router } from '@angular/router';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { PdfViewerComponent } from '../../components/pdf-viewer/pdf-viewer.component';
|
||||
import { debounce } from '../../../../utils/debounce';
|
||||
import { debounce } from '@utils/debounce';
|
||||
import { MatDialogRef, MatDialogState } from '@angular/material/dialog';
|
||||
import { ManualRedactionEntryWrapper } from '../../../../models/file/manual-redaction-entry.wrapper';
|
||||
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
|
||||
import { ManualAnnotationResponse } from '../../../../models/file/manual-annotation-response';
|
||||
import { AnnotationData, FileDataModel } from '../../../../models/file/file-data.model';
|
||||
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { ManualAnnotationResponse } from '@models/file/manual-annotation-response';
|
||||
import { AnnotationData, FileDataModel } from '@models/file/file-data.model';
|
||||
import { FileActionService } from '../../services/file-action.service';
|
||||
import { AnnotationDrawService } from '../../services/annotation-draw.service';
|
||||
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
|
||||
import { FilterModel } from '../../../shared/components/filter/model/filter.model';
|
||||
import { FilterModel } from '@shared/components/filter/model/filter.model';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { NotificationService } from '../../../../services/notification.service';
|
||||
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { NotificationService } from '@services/notification.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { Subscription, timer } from 'rxjs';
|
||||
import { handleFilterDelta, processFilters } from '../../../shared/components/filter/utils/filter-utils';
|
||||
import { UserPreferenceService } from '../../../../services/user-preference.service';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { handleFilterDelta, processFilters } from '@shared/components/filter/utils/filter-utils';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { FileManagementControllerService, StatusControllerService } from '@redaction/red-ui-http';
|
||||
import { PdfViewerDataService } from '../../services/pdf-viewer-data.service';
|
||||
import { download } from '../../../../utils/file-download-utils';
|
||||
import { ViewMode } from '../../../../models/file/view-mode';
|
||||
import { download } from '@utils/file-download-utils';
|
||||
import { ViewMode } from '@models/file/view-mode';
|
||||
import { FileWorkloadComponent } from '../../components/file-workload/file-workload.component';
|
||||
import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
import { OnAttach, OnDetach } from '../../../../utils/custom-route-reuse.strategy';
|
||||
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
||||
|
||||
@ -60,12 +60,11 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
hideSkipped = false;
|
||||
displayPDFViewer = false;
|
||||
viewDocumentInfo = false;
|
||||
@ViewChild(FileWorkloadComponent) fileWorkloadComponent: FileWorkloadComponent;
|
||||
private _instance: WebViewerInstance;
|
||||
private _lastPage: string;
|
||||
|
||||
@ViewChild('fileWorkloadComponent') private _workloadComponent: FileWorkloadComponent;
|
||||
@ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent;
|
||||
@ViewChild(FileWorkloadComponent) fileWorkloadComponent: FileWorkloadComponent;
|
||||
|
||||
constructor(
|
||||
readonly appStateService: AppStateService,
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
import { Component, Injector, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { Project, RuleSetModel } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { groupBy } from '../../../../utils/functions';
|
||||
import { FilterModel } from '../../../shared/components/filter/model/filter.model';
|
||||
import { Project, RuleSetModel, User } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { groupBy } from '@utils/functions';
|
||||
import { FilterModel } from '@shared/components/filter/model/filter.model';
|
||||
import {
|
||||
annotationFilterChecker,
|
||||
processFilters,
|
||||
projectMemberChecker,
|
||||
projectStatusChecker,
|
||||
ruleSetChecker
|
||||
} from '../../../shared/components/filter/utils/filter-utils';
|
||||
} from '@shared/components/filter/utils/filter-utils';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
import { Subscription, timer } from 'rxjs';
|
||||
import { filter, tap } from 'rxjs/operators';
|
||||
import { TranslateChartService } from '../../../../services/translate-chart.service';
|
||||
import { RedactionFilterSorter } from '../../../../utils/sorters/redaction-filter-sorter';
|
||||
import { StatusSorter } from '../../../../utils/sorters/status-sorter';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { RedactionFilterSorter } from '@utils/sorters/redaction-filter-sorter';
|
||||
import { StatusSorter } from '@utils/sorters/status-sorter';
|
||||
import { NavigationEnd, NavigationStart, Router } from '@angular/router';
|
||||
import { FilterComponent } from '../../../shared/components/filter/filter.component';
|
||||
import { FilterComponent } from '@shared/components/filter/filter.component';
|
||||
import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { OnAttach, OnDetach } from '../../../../utils/custom-route-reuse.strategy';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-listing-screen',
|
||||
@ -33,23 +33,19 @@ import { OnAttach, OnDetach } from '../../../../utils/custom-route-reuse.strateg
|
||||
styleUrls: ['./project-listing-screen.component.scss']
|
||||
})
|
||||
export class ProjectListingScreenComponent extends BaseListingComponent<ProjectWrapper> implements OnInit, OnDestroy, OnAttach, OnDetach {
|
||||
protected readonly _searchKey = 'name';
|
||||
protected readonly _sortKey = 'project-listing';
|
||||
|
||||
projectsChartData: DoughnutChartConfig[] = [];
|
||||
documentsChartData: DoughnutChartConfig[] = [];
|
||||
|
||||
statusFilters: FilterModel[];
|
||||
peopleFilters: FilterModel[];
|
||||
needsWorkFilters: FilterModel[];
|
||||
ruleSetFilters: FilterModel[];
|
||||
|
||||
detailsContainerFilters: {
|
||||
statusFilters: FilterModel[];
|
||||
} = {
|
||||
statusFilters: []
|
||||
};
|
||||
|
||||
protected readonly _searchKey = 'name';
|
||||
protected readonly _sortKey = 'project-listing';
|
||||
private _projectAutoUpdateTimer: Subscription;
|
||||
private _lastScrollPosition: number;
|
||||
|
||||
@ -78,6 +74,40 @@ export class ProjectListingScreenComponent extends BaseListingComponent<ProjectW
|
||||
this._loadEntitiesFromState();
|
||||
}
|
||||
|
||||
get noData() {
|
||||
return this.allEntities.length === 0;
|
||||
}
|
||||
|
||||
get user() {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
get activeProjectsCount() {
|
||||
return this.allEntities.filter((p) => p.project.status === Project.StatusEnum.ACTIVE).length;
|
||||
}
|
||||
|
||||
get inactiveProjectsCount() {
|
||||
return this.allEntities.length - this.activeProjectsCount;
|
||||
}
|
||||
|
||||
protected get _filterComponents(): FilterComponent[] {
|
||||
return [this._statusFilterComponent, this._peopleFilterComponent, this._needsWorkFilterComponent, this._ruleSetFilterComponent];
|
||||
}
|
||||
|
||||
protected get _filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] {
|
||||
return [
|
||||
{ values: this.statusFilters, checker: projectStatusChecker },
|
||||
{ values: this.peopleFilters, checker: projectMemberChecker },
|
||||
{
|
||||
values: this.needsWorkFilters,
|
||||
checker: annotationFilterChecker,
|
||||
matchAll: true,
|
||||
checkerArgs: this.permissionsService
|
||||
},
|
||||
{ values: this.ruleSetFilters, checker: ruleSetChecker }
|
||||
];
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._calculateData();
|
||||
|
||||
@ -120,49 +150,8 @@ export class ProjectListingScreenComponent extends BaseListingComponent<ProjectW
|
||||
this._fileChangedSub.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadEntitiesFromState() {
|
||||
this.allEntities = this._appStateService.allProjects;
|
||||
}
|
||||
|
||||
get noData() {
|
||||
return this.allEntities.length === 0;
|
||||
}
|
||||
|
||||
protected get _filterComponents(): FilterComponent[] {
|
||||
return [this._statusFilterComponent, this._peopleFilterComponent, this._needsWorkFilterComponent, this._ruleSetFilterComponent];
|
||||
}
|
||||
|
||||
private _calculateData() {
|
||||
this._computeAllFilters();
|
||||
this._filterEntities();
|
||||
this.projectsChartData = [
|
||||
{ value: this.activeProjectsCount, color: 'ACTIVE', label: 'active' },
|
||||
{ value: this.inactiveProjectsCount, color: 'DELETED', label: 'archived' }
|
||||
];
|
||||
const groups = groupBy(this._appStateService.aggregatedFiles, 'status');
|
||||
this.documentsChartData = [];
|
||||
for (const key of Object.keys(groups)) {
|
||||
this.documentsChartData.push({
|
||||
value: groups[key].length,
|
||||
color: key,
|
||||
label: key,
|
||||
key: key
|
||||
});
|
||||
}
|
||||
this.documentsChartData.sort((a, b) => StatusSorter[a.key] - StatusSorter[b.key]);
|
||||
this.documentsChartData = this._translateChartService.translateStatus(this.documentsChartData);
|
||||
}
|
||||
|
||||
get user() {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
get activeProjectsCount() {
|
||||
return this.allEntities.filter((p) => p.project.status === Project.StatusEnum.ACTIVE).length;
|
||||
}
|
||||
|
||||
get inactiveProjectsCount() {
|
||||
return this.allEntities.length - this.activeProjectsCount;
|
||||
getUser(id: string): User {
|
||||
return this._userService.getUserById(id);
|
||||
}
|
||||
|
||||
documentCount(project: ProjectWrapper) {
|
||||
@ -195,6 +184,41 @@ export class ProjectListingScreenComponent extends BaseListingComponent<ProjectW
|
||||
this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project);
|
||||
}
|
||||
|
||||
actionPerformed() {
|
||||
this._calculateData();
|
||||
}
|
||||
|
||||
protected _preFilter() {
|
||||
this.detailsContainerFilters = {
|
||||
statusFilters: this.statusFilters.map((f) => ({ ...f }))
|
||||
};
|
||||
}
|
||||
|
||||
private _loadEntitiesFromState() {
|
||||
this.allEntities = this._appStateService.allProjects;
|
||||
}
|
||||
|
||||
private _calculateData() {
|
||||
this._computeAllFilters();
|
||||
this._filterEntities();
|
||||
this.projectsChartData = [
|
||||
{ value: this.activeProjectsCount, color: 'ACTIVE', label: 'active' },
|
||||
{ value: this.inactiveProjectsCount, color: 'DELETED', label: 'archived' }
|
||||
];
|
||||
const groups = groupBy(this._appStateService.aggregatedFiles, 'status');
|
||||
this.documentsChartData = [];
|
||||
for (const key of Object.keys(groups)) {
|
||||
this.documentsChartData.push({
|
||||
value: groups[key].length,
|
||||
color: key,
|
||||
label: key,
|
||||
key: key
|
||||
});
|
||||
}
|
||||
this.documentsChartData.sort((a, b) => StatusSorter[a.key] - StatusSorter[b.key]);
|
||||
this.documentsChartData = this._translateChartService.translateStatus(this.documentsChartData);
|
||||
}
|
||||
|
||||
private _computeAllFilters() {
|
||||
const allDistinctFileStatus = new Set<string>();
|
||||
const allDistinctPeople = new Set<string>();
|
||||
@ -260,28 +284,4 @@ export class ProjectListingScreenComponent extends BaseListingComponent<ProjectW
|
||||
});
|
||||
this.ruleSetFilters = processFilters(this.ruleSetFilters, ruleSetFilters);
|
||||
}
|
||||
|
||||
protected get _filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] {
|
||||
return [
|
||||
{ values: this.statusFilters, checker: projectStatusChecker },
|
||||
{ values: this.peopleFilters, checker: projectMemberChecker },
|
||||
{
|
||||
values: this.needsWorkFilters,
|
||||
checker: annotationFilterChecker,
|
||||
matchAll: true,
|
||||
checkerArgs: this.permissionsService
|
||||
},
|
||||
{ values: this.ruleSetFilters, checker: ruleSetChecker }
|
||||
];
|
||||
}
|
||||
|
||||
protected _preFilter() {
|
||||
this.detailsContainerFilters = {
|
||||
statusFilters: this.statusFilters.map((f) => ({ ...f }))
|
||||
};
|
||||
}
|
||||
|
||||
actionPerformed() {
|
||||
this._calculateData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
import { Component, HostListener, Injector, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { NavigationEnd, NavigationStart, Router } from '@angular/router';
|
||||
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { FileDropOverlayService } from '../../../upload-download/services/file-drop-overlay.service';
|
||||
import { FileUploadModel } from '../../../upload-download/model/file-upload.model';
|
||||
import { FileUploadService } from '../../../upload-download/services/file-upload.service';
|
||||
import { StatusOverlayService } from '../../../upload-download/services/status-overlay.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FileDropOverlayService } from '@upload-download/services/file-drop-overlay.service';
|
||||
import { FileUploadModel } from '@upload-download/model/file-upload.model';
|
||||
import { FileUploadService } from '@upload-download/services/file-upload.service';
|
||||
import { StatusOverlayService } from '@upload-download/services/status-overlay.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { FilterModel } from '../../../shared/components/filter/model/filter.model';
|
||||
import { FilterModel } from '@shared/components/filter/model/filter.model';
|
||||
import * as moment from 'moment';
|
||||
import { ProjectDetailsComponent } from '../../components/project-details/project-details.component';
|
||||
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
||||
import { annotationFilterChecker, keyChecker, processFilters } from '../../../shared/components/filter/utils/filter-utils';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { annotationFilterChecker, keyChecker, processFilters } from '@shared/components/filter/utils/filter-utils';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FileStatus } from '@redaction/red-ui-http';
|
||||
import { Subscription, timer } from 'rxjs';
|
||||
import { filter, tap } from 'rxjs/operators';
|
||||
import { RedactionFilterSorter } from '../../../../utils/sorters/redaction-filter-sorter';
|
||||
import { StatusSorter } from '../../../../utils/sorters/status-sorter';
|
||||
import { convertFiles, handleFileDrop } from '../../../../utils/file-drop-utils';
|
||||
import { FilterComponent } from '../../../shared/components/filter/filter.component';
|
||||
import { RedactionFilterSorter } from '@utils/sorters/redaction-filter-sorter';
|
||||
import { StatusSorter } from '@utils/sorters/status-sorter';
|
||||
import { convertFiles, handleFileDrop } from '@utils/file-drop-utils';
|
||||
import { FilterComponent } from '@shared/components/filter/filter.component';
|
||||
import { ProjectsDialogService } from '../../services/projects-dialog.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { ProjectWrapper } from '../../../../state/model/project.wrapper';
|
||||
import { OnAttach, OnDetach } from '../../../../utils/custom-route-reuse.strategy';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-overview-screen',
|
||||
@ -33,20 +33,17 @@ import { OnAttach, OnDetach } from '../../../../utils/custom-route-reuse.strateg
|
||||
styleUrls: ['./project-overview-screen.component.scss']
|
||||
})
|
||||
export class ProjectOverviewScreenComponent extends BaseListingComponent<FileStatusWrapper> implements OnInit, OnDestroy, OnDetach, OnAttach {
|
||||
protected readonly _searchKey = 'searchField';
|
||||
protected readonly _selectionKey = 'fileId';
|
||||
protected readonly _sortKey = 'project-overview';
|
||||
|
||||
statusFilters: FilterModel[];
|
||||
peopleFilters: FilterModel[];
|
||||
needsWorkFilters: FilterModel[];
|
||||
collapsedDetails = false;
|
||||
|
||||
detailsContainerFilters: {
|
||||
needsWorkFilters: FilterModel[];
|
||||
statusFilters: FilterModel[];
|
||||
} = { needsWorkFilters: [], statusFilters: [] };
|
||||
|
||||
protected readonly _searchKey = 'searchField';
|
||||
protected readonly _selectionKey = 'fileId';
|
||||
protected readonly _sortKey = 'project-overview';
|
||||
@ViewChild('projectDetailsComponent', { static: false })
|
||||
private _projectDetailsComponent: ProjectDetailsComponent;
|
||||
private _filesAutoUpdateTimer: Subscription;
|
||||
@ -77,6 +74,27 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
||||
this._loadEntitiesFromState();
|
||||
}
|
||||
|
||||
get activeProject(): ProjectWrapper {
|
||||
return this._appStateService.activeProject;
|
||||
}
|
||||
|
||||
protected get _filterComponents(): FilterComponent[] {
|
||||
return [this._statusFilterComponent, this._peopleFilterComponent, this._needsWorkFilterComponent];
|
||||
}
|
||||
|
||||
protected get _filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] {
|
||||
return [
|
||||
{ values: this.statusFilters, checker: keyChecker('status') },
|
||||
{ values: this.peopleFilters, checker: keyChecker('currentReviewer') },
|
||||
{
|
||||
values: this.needsWorkFilters,
|
||||
checker: annotationFilterChecker,
|
||||
matchAll: true,
|
||||
checkerArgs: this.permissionsService
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._fileDropOverlayService.initFileDropHandling();
|
||||
|
||||
@ -121,10 +139,6 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
||||
this.ngOnDestroy();
|
||||
}
|
||||
|
||||
get activeProject(): ProjectWrapper {
|
||||
return this._appStateService.activeProject;
|
||||
}
|
||||
|
||||
reanalyseProject() {
|
||||
return this._appStateService
|
||||
.reanalyzeProject()
|
||||
@ -157,14 +171,6 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
||||
return [FileStatus.StatusEnum.REPROCESS, FileStatus.StatusEnum.FULLREPROCESS, FileStatus.StatusEnum.PROCESSING].includes(fileStatusWrapper.status);
|
||||
}
|
||||
|
||||
protected get _filterComponents(): FilterComponent[] {
|
||||
return [this._statusFilterComponent, this._peopleFilterComponent, this._needsWorkFilterComponent];
|
||||
}
|
||||
|
||||
private _loadEntitiesFromState() {
|
||||
if (this.activeProject) this.allEntities = this.activeProject.files;
|
||||
}
|
||||
|
||||
reloadProjects() {
|
||||
this._appStateService.getFiles(this._appStateService.activeProject, false).then(() => {
|
||||
this.calculateData();
|
||||
@ -201,6 +207,46 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
||||
await this._uploadFiles(convertFiles(files, this.activeProject));
|
||||
}
|
||||
|
||||
fileLink(fileStatus: FileStatusWrapper) {
|
||||
return this.permissionsService.canOpenFile(fileStatus) ? ['/main/projects/' + this.activeProject.project.projectId + '/file/' + fileStatus.fileId] : [];
|
||||
}
|
||||
|
||||
bulkActionPerformed() {
|
||||
this.selectedEntitiesIds = [];
|
||||
this.reloadProjects();
|
||||
}
|
||||
|
||||
openEditProjectDialog($event: MouseEvent) {
|
||||
this._dialogService.openEditProjectDialog($event, this.activeProject);
|
||||
}
|
||||
|
||||
openDeleteProjectDialog($event: MouseEvent) {
|
||||
this._dialogService.openDeleteProjectDialog($event, this.activeProject, () => {
|
||||
this._router.navigate(['/main/projects']);
|
||||
});
|
||||
}
|
||||
|
||||
openAssignProjectMembersDialog(): void {
|
||||
this._dialogService.openAssignProjectMembersAndOwnerDialog(null, this.activeProject, () => {
|
||||
this.reloadProjects();
|
||||
});
|
||||
}
|
||||
|
||||
toggleCollapsedDetails() {
|
||||
this.collapsedDetails = !this.collapsedDetails;
|
||||
}
|
||||
|
||||
protected _preFilter() {
|
||||
this.detailsContainerFilters = {
|
||||
needsWorkFilters: this.needsWorkFilters.map((f) => ({ ...f })),
|
||||
statusFilters: this.statusFilters.map((f) => ({ ...f }))
|
||||
};
|
||||
}
|
||||
|
||||
private _loadEntitiesFromState() {
|
||||
if (this.activeProject) this.allEntities = this.activeProject.files;
|
||||
}
|
||||
|
||||
private async _uploadFiles(files: FileUploadModel[]) {
|
||||
const fileCount = await this._fileUploadService.uploadFiles(files);
|
||||
if (fileCount) {
|
||||
@ -277,53 +323,4 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent<FileSta
|
||||
needsWorkFilters.sort((a, b) => RedactionFilterSorter[a.key] - RedactionFilterSorter[b.key]);
|
||||
this.needsWorkFilters = processFilters(this.needsWorkFilters, needsWorkFilters);
|
||||
}
|
||||
|
||||
fileLink(fileStatus: FileStatusWrapper) {
|
||||
return this.permissionsService.canOpenFile(fileStatus) ? ['/main/projects/' + this.activeProject.project.projectId + '/file/' + fileStatus.fileId] : [];
|
||||
}
|
||||
|
||||
protected get _filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] {
|
||||
return [
|
||||
{ values: this.statusFilters, checker: keyChecker('status') },
|
||||
{ values: this.peopleFilters, checker: keyChecker('currentReviewer') },
|
||||
{
|
||||
values: this.needsWorkFilters,
|
||||
checker: annotationFilterChecker,
|
||||
matchAll: true,
|
||||
checkerArgs: this.permissionsService
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
protected _preFilter() {
|
||||
this.detailsContainerFilters = {
|
||||
needsWorkFilters: this.needsWorkFilters.map((f) => ({ ...f })),
|
||||
statusFilters: this.statusFilters.map((f) => ({ ...f }))
|
||||
};
|
||||
}
|
||||
|
||||
bulkActionPerformed() {
|
||||
this.selectedEntitiesIds = [];
|
||||
this.reloadProjects();
|
||||
}
|
||||
|
||||
openEditProjectDialog($event: MouseEvent) {
|
||||
this._dialogService.openEditProjectDialog($event, this.activeProject);
|
||||
}
|
||||
|
||||
openDeleteProjectDialog($event: MouseEvent) {
|
||||
this._dialogService.openDeleteProjectDialog($event, this.activeProject, () => {
|
||||
this._router.navigate(['/main/projects']);
|
||||
});
|
||||
}
|
||||
|
||||
openAssignProjectMembersDialog(): void {
|
||||
this._dialogService.openAssignProjectMembersAndOwnerDialog(null, this.activeProject, () => {
|
||||
this.reloadProjects();
|
||||
});
|
||||
}
|
||||
|
||||
toggleCollapsedDetails() {
|
||||
this.collapsedDetails = !this.collapsedDetails;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { EventEmitter, Inject, Injectable, NgZone } from '@angular/core';
|
||||
import { PermissionsService } from '../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ManualAnnotationService } from './manual-annotation.service';
|
||||
import { AnnotationWrapper } from '../../../models/file/annotation.wrapper';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { AddRedactionRequest } from '@redaction/red-ui-http';
|
||||
import { getFirstRelevantTextPart } from '../../../utils/functions';
|
||||
import { AnnotationPermissions } from '../../../models/file/annotation.permissions';
|
||||
import { getFirstRelevantTextPart } from '@utils/functions';
|
||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||
import { ProjectsDialogService } from './projects-dialog.service';
|
||||
import { BASE_HREF } from '../../../tokens';
|
||||
|
||||
@ -90,17 +90,6 @@ export class AnnotationActionsService {
|
||||
});
|
||||
}
|
||||
|
||||
private _processObsAndEmit(obs: Observable<any>, annotation: AnnotationWrapper, annotationsChanged: EventEmitter<AnnotationWrapper>) {
|
||||
obs.subscribe(
|
||||
() => {
|
||||
annotationsChanged.emit(annotation);
|
||||
},
|
||||
() => {
|
||||
annotationsChanged.emit();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getViewerAvailableActions(annotations: AnnotationWrapper[], annotationsChanged: EventEmitter<AnnotationWrapper>): Record<string, unknown>[] {
|
||||
const availableActions = [];
|
||||
|
||||
@ -233,6 +222,17 @@ export class AnnotationActionsService {
|
||||
return availableActions;
|
||||
}
|
||||
|
||||
private _processObsAndEmit(obs: Observable<any>, annotation: AnnotationWrapper, annotationsChanged: EventEmitter<AnnotationWrapper>) {
|
||||
obs.subscribe(
|
||||
() => {
|
||||
annotationsChanged.emit(annotation);
|
||||
},
|
||||
() => {
|
||||
annotationsChanged.emit();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private _getFalsePositiveText(annotation: AnnotationWrapper) {
|
||||
if (annotation.canBeMarkedAsFalsePositive) {
|
||||
let text;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Annotations, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { Rectangle, RedactionLogControllerService, SectionGrid, SectionRectangle } from '@redaction/red-ui-http';
|
||||
import { hexToRgb } from '../../../utils/functions';
|
||||
import { AppStateService } from '../../../state/app-state.service';
|
||||
import { AnnotationWrapper } from '../../../models/file/annotation.wrapper';
|
||||
import { UserPreferenceService } from '../../../services/user-preference.service';
|
||||
import { hexToRgb } from '@utils/functions';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationDrawService {
|
||||
@ -112,6 +112,22 @@ export class AnnotationDrawService {
|
||||
return new activeViewer.Annotations.Color(rgbColor.r, rgbColor.g, rgbColor.b);
|
||||
}
|
||||
|
||||
annotationToQuads(annotation: Annotations.Annotation, activeViewer: WebViewerInstance) {
|
||||
const x1 = annotation.getRect().x1;
|
||||
const y1 = annotation.getRect().y1 + annotation.getRect().getHeight();
|
||||
|
||||
const x2 = annotation.getRect().x1 + annotation.getRect().getWidth();
|
||||
const y2 = annotation.getRect().y1 + annotation.getRect().getHeight();
|
||||
|
||||
const x3 = annotation.getRect().x1 + annotation.getRect().getWidth();
|
||||
const y3 = annotation.getRect().y1;
|
||||
|
||||
const x4 = annotation.getRect().x1;
|
||||
const y4 = annotation.getRect().y1;
|
||||
|
||||
return new activeViewer.CoreControls.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
private _rectanglesToQuads(positions: Rectangle[], activeViewer: WebViewerInstance, pageNumber: number): any[] {
|
||||
const pageHeight = activeViewer.docViewer.getPageHeight(pageNumber);
|
||||
return positions.map((p) => this._rectangleToQuad(p, activeViewer, pageHeight));
|
||||
@ -132,20 +148,4 @@ export class AnnotationDrawService {
|
||||
|
||||
return new activeViewer.CoreControls.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
annotationToQuads(annotation: Annotations.Annotation, activeViewer: WebViewerInstance) {
|
||||
const x1 = annotation.getRect().x1;
|
||||
const y1 = annotation.getRect().y1 + annotation.getRect().getHeight();
|
||||
|
||||
const x2 = annotation.getRect().x1 + annotation.getRect().getWidth();
|
||||
const y2 = annotation.getRect().y1 + annotation.getRect().getHeight();
|
||||
|
||||
const x3 = annotation.getRect().x1 + annotation.getRect().getWidth();
|
||||
const y3 = annotation.getRect().y1;
|
||||
|
||||
const x4 = annotation.getRect().x1;
|
||||
const y4 = annotation.getRect().y1;
|
||||
|
||||
return new activeViewer.CoreControls.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,25 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AnnotationWrapper } from '../../../models/file/annotation.wrapper';
|
||||
import { FilterModel } from '../../shared/components/filter/model/filter.model';
|
||||
import { handleCheckedValue } from '../../shared/components/filter/utils/filter-utils';
|
||||
import { SuperTypeSorter } from '../../../utils/sorters/super-type-sorter';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { FilterModel } from '@shared/components/filter/model/filter.model';
|
||||
import { handleCheckedValue } from '@shared/components/filter/utils/filter-utils';
|
||||
import { SuperTypeSorter } from '@utils/sorters/super-type-sorter';
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationProcessingService {
|
||||
static get secondaryAnnotationFilters(): FilterModel[] {
|
||||
return [
|
||||
{
|
||||
key: 'with-comments',
|
||||
icon: 'red:comment',
|
||||
label: 'filter-menu.with-comments',
|
||||
checked: false,
|
||||
topLevelFilter: true,
|
||||
filters: [],
|
||||
checker: (annotation: AnnotationWrapper) => annotation?.comments?.length > 0
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
getAnnotationFilter(annotations: AnnotationWrapper[]): FilterModel[] {
|
||||
const filterMap = new Map<string, FilterModel>();
|
||||
const filters: FilterModel[] = [];
|
||||
@ -51,19 +65,6 @@ export class AnnotationProcessingService {
|
||||
return filters.sort((a, b) => SuperTypeSorter[a.key] - SuperTypeSorter[b.key]);
|
||||
}
|
||||
|
||||
private _createParentFilter(key: string, filterMap: Map<string, FilterModel>, filters: FilterModel[]) {
|
||||
const filter: FilterModel = {
|
||||
key: key,
|
||||
topLevelFilter: true,
|
||||
matches: 1,
|
||||
label: 'annotation-type.' + key,
|
||||
filters: []
|
||||
};
|
||||
filterMap.set(key, filter);
|
||||
filters.push(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
filterAndGroupAnnotations(
|
||||
annotations: AnnotationWrapper[],
|
||||
primaryFilters: FilterModel[],
|
||||
@ -106,6 +107,19 @@ export class AnnotationProcessingService {
|
||||
return obj;
|
||||
}
|
||||
|
||||
private _createParentFilter(key: string, filterMap: Map<string, FilterModel>, filters: FilterModel[]) {
|
||||
const filter: FilterModel = {
|
||||
key: key,
|
||||
topLevelFilter: true,
|
||||
matches: 1,
|
||||
label: 'annotation-type.' + key,
|
||||
filters: []
|
||||
};
|
||||
filterMap.set(key, filter);
|
||||
filters.push(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
private _getFlatFilters(filters: FilterModel[], filterBy?: (f: FilterModel) => boolean) {
|
||||
const flatFilters: FilterModel[] = [];
|
||||
|
||||
@ -156,18 +170,4 @@ export class AnnotationProcessingService {
|
||||
return ann1.pageNumber < ann2.pageNumber ? -1 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
static get secondaryAnnotationFilters(): FilterModel[] {
|
||||
return [
|
||||
{
|
||||
key: 'with-comments',
|
||||
icon: 'red:comment',
|
||||
label: 'filter-menu.with-comments',
|
||||
checked: false,
|
||||
topLevelFilter: true,
|
||||
filters: [],
|
||||
checker: (annotation: AnnotationWrapper) => annotation?.comments?.length > 0
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AppStateService } from '../../../state/app-state.service';
|
||||
import { UserService } from '../../../services/user.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FileStatus, ReanalysisControllerService, StatusControllerService } from '@redaction/red-ui-http';
|
||||
import { FileStatusWrapper } from '../../../models/file/file-status.wrapper';
|
||||
import { PermissionsService } from '../../../services/permissions.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { isArray } from 'rxjs/internal-compatibility';
|
||||
import { ProjectsDialogService } from './projects-dialog.service';
|
||||
|
||||
@ -40,15 +40,6 @@ export class FileActionService {
|
||||
}
|
||||
}
|
||||
|
||||
private _openAssignReviewerDialog(file?: FileStatusWrapper, callback?: Function) {
|
||||
this._dialogService.openAssignFileReviewerDialog(file ? file : this._appStateService.activeFile, async () => {
|
||||
await this._appStateService.reloadActiveProjectFiles();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
assignProjectReviewer(file?: FileStatus, callback?: Function, ignoreDialogChanges = false) {
|
||||
this._dialogService.openAssignFileReviewerDialog(
|
||||
file ? file : this._appStateService.activeFile,
|
||||
@ -72,14 +63,6 @@ export class FileActionService {
|
||||
}
|
||||
}
|
||||
|
||||
private async _assignReviewerToCurrentUser(file?: FileStatus, callback?: Function) {
|
||||
await this._statusControllerService.setFileReviewer(this._appStateService.activeProjectId, file.fileId, this._userService.userId).toPromise();
|
||||
await this._appStateService.reloadActiveProjectFiles();
|
||||
if (callback) {
|
||||
await callback();
|
||||
}
|
||||
}
|
||||
|
||||
setFileUnderApproval(fileStatus: FileStatusWrapper | FileStatusWrapper[]) {
|
||||
if (!isArray(fileStatus)) {
|
||||
fileStatus = [fileStatus];
|
||||
@ -119,4 +102,21 @@ export class FileActionService {
|
||||
this._appStateService.activeProjectId
|
||||
);
|
||||
}
|
||||
|
||||
private _openAssignReviewerDialog(file?: FileStatusWrapper, callback?: Function) {
|
||||
this._dialogService.openAssignFileReviewerDialog(file ? file : this._appStateService.activeFile, async () => {
|
||||
await this._appStateService.reloadActiveProjectFiles();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async _assignReviewerToCurrentUser(file?: FileStatus, callback?: Function) {
|
||||
await this._statusControllerService.setFileReviewer(this._appStateService.activeProjectId, file.fileId, this._userService.userId).toPromise();
|
||||
await this._appStateService.reloadActiveProjectFiles();
|
||||
if (callback) {
|
||||
await callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AppStateService } from '../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { AddRedactionRequest, DictionaryControllerService, ForceRedactionRequest, ManualRedactionControllerService } from '@redaction/red-ui-http';
|
||||
import { AnnotationWrapper } from '../../../models/file/annotation.wrapper';
|
||||
import { NotificationService, NotificationType } from '../../../services/notification.service';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { UserService } from '../../../services/user.service';
|
||||
import { PermissionsService } from '../../../services/permissions.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
@Injectable()
|
||||
export class ManualAnnotationService {
|
||||
@ -182,6 +182,28 @@ export class ManualAnnotationService {
|
||||
}
|
||||
}
|
||||
|
||||
getTitle(type: 'DICTIONARY' | 'REDACTION' | 'FALSE_POSITIVE') {
|
||||
if (this._permissionsService.isManagerAndOwner()) {
|
||||
switch (type) {
|
||||
case 'DICTIONARY':
|
||||
return 'manual-annotation.dialog.header.dictionary';
|
||||
case 'FALSE_POSITIVE':
|
||||
return 'manual-annotation.dialog.header.false-positive';
|
||||
case 'REDACTION':
|
||||
return 'manual-annotation.dialog.header.redaction';
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case 'DICTIONARY':
|
||||
return 'manual-annotation.dialog.header.request-dictionary';
|
||||
case 'FALSE_POSITIVE':
|
||||
return 'manual-annotation.dialog.header.request-false-positive';
|
||||
case 'REDACTION':
|
||||
return 'manual-annotation.dialog.header.request-redaction';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _makeForceRedactionRequest(forceRedactionRequest: ForceRedactionRequest) {
|
||||
return this._manualRedactionControllerService
|
||||
.requestForceRedaction(forceRedactionRequest, this._appStateService.activeProject.project.projectId, this._appStateService.activeFile.fileId)
|
||||
@ -233,28 +255,6 @@ export class ManualAnnotationService {
|
||||
});
|
||||
}
|
||||
|
||||
getTitle(type: 'DICTIONARY' | 'REDACTION' | 'FALSE_POSITIVE') {
|
||||
if (this._permissionsService.isManagerAndOwner()) {
|
||||
switch (type) {
|
||||
case 'DICTIONARY':
|
||||
return 'manual-annotation.dialog.header.dictionary';
|
||||
case 'FALSE_POSITIVE':
|
||||
return 'manual-annotation.dialog.header.false-positive';
|
||||
case 'REDACTION':
|
||||
return 'manual-annotation.dialog.header.redaction';
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case 'DICTIONARY':
|
||||
return 'manual-annotation.dialog.header.request-dictionary';
|
||||
case 'FALSE_POSITIVE':
|
||||
return 'manual-annotation.dialog.header.request-false-positive';
|
||||
case 'REDACTION':
|
||||
return 'manual-annotation.dialog.header.request-redaction';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _getMessage(
|
||||
mode: 'add' | 'remove' | 'request-remove' | 'suggest' | 'approve' | 'decline' | 'undo',
|
||||
modifyDictionary?: boolean,
|
||||
|
||||
@ -7,10 +7,10 @@ import {
|
||||
RedactionLogControllerService,
|
||||
ViewedPagesControllerService
|
||||
} from '@redaction/red-ui-http';
|
||||
import { FileDataModel } from '../../../models/file/file-data.model';
|
||||
import { AppStateService } from '../../../state/app-state.service';
|
||||
import { PermissionsService } from '../../../services/permissions.service';
|
||||
import { FileStatusWrapper } from '../../../models/file/file-status.wrapper';
|
||||
import { FileDataModel } from '@models/file/file-data.model';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
|
||||
@Injectable()
|
||||
export class PdfViewerDataService {
|
||||
|
||||
@ -9,14 +9,14 @@ import {
|
||||
} from '@redaction/red-ui-http';
|
||||
import { AddEditProjectDialogComponent } from '../dialogs/add-edit-project-dialog/add-edit-project-dialog.component';
|
||||
import { RemoveAnnotationsDialogComponent } from '../dialogs/remove-annotations-dialog/remove-annotations-dialog.component';
|
||||
import { NotificationService, NotificationType } from '../../../services/notification.service';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
import { ForceRedactionDialogComponent } from '../dialogs/force-redaction-dialog/force-redaction-dialog.component';
|
||||
import { AnnotationWrapper } from '../../../models/file/annotation.wrapper';
|
||||
import { ConfirmationDialogComponent, ConfirmationDialogInput } from '../../shared/dialogs/confirmation-dialog/confirmation-dialog.component';
|
||||
import { ProjectWrapper } from '../../../state/model/project.wrapper';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { ConfirmationDialogComponent, ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component';
|
||||
import { AppStateService } from '../../../state/app-state.service';
|
||||
import { ManualRedactionEntryWrapper } from '../../../models/file/manual-redaction-entry.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
||||
import { ManualAnnotationService } from './manual-annotation.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
||||
|
||||
@ -3,8 +3,8 @@ import { FilterModel } from '../components/filter/model/filter.model';
|
||||
import { getFilteredEntities } from '../components/filter/utils/filter-utils';
|
||||
import { FilterComponent } from '../components/filter/filter.component';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { debounce } from '../../../utils/debounce';
|
||||
import { ScreenName, SortingOption, SortingService } from '../../../services/sorting.service';
|
||||
import { debounce } from '@utils/debounce';
|
||||
import { ScreenName, SortingOption, SortingService } from '@services/sorting.service';
|
||||
|
||||
// Functionalities: Filter, search, select, sort
|
||||
|
||||
@ -28,12 +28,50 @@ export abstract class BaseListingComponent<T = any> {
|
||||
protected readonly _selectionKey: string;
|
||||
protected readonly _sortKey: ScreenName;
|
||||
|
||||
protected constructor(protected readonly _injector: Injector) {
|
||||
this._formBuilder = this._injector.get<FormBuilder>(FormBuilder);
|
||||
this._changeDetectorRef = this._injector.get<ChangeDetectorRef>(ChangeDetectorRef);
|
||||
this._sortingService = this._injector.get<SortingService>(SortingService);
|
||||
this._initSearch();
|
||||
}
|
||||
|
||||
get hasActiveFilters() {
|
||||
return (
|
||||
this._filterComponents.filter((f) => !!f).reduce((prev, component) => prev || component?.hasActiveFilters, false) ||
|
||||
this.searchForm.get('query').value
|
||||
);
|
||||
}
|
||||
|
||||
get areAllEntitiesSelected() {
|
||||
return this.displayedEntities.length !== 0 && this.selectedEntitiesIds.length === this.displayedEntities.length;
|
||||
}
|
||||
|
||||
get areSomeEntitiesSelected() {
|
||||
return this.selectedEntitiesIds.length > 0;
|
||||
}
|
||||
|
||||
get sortingOption(): SortingOption {
|
||||
return this._sortingService.getSortingOption(this._getSortKey);
|
||||
}
|
||||
|
||||
protected get _filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected get _filterComponents(): FilterComponent[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
private get _getSearchKey(): string {
|
||||
if (!this._searchKey) throw new Error('Not implemented');
|
||||
|
||||
return this._searchKey;
|
||||
}
|
||||
|
||||
// Search
|
||||
|
||||
private get _getSelectionKey(): string {
|
||||
if (!this._selectionKey) throw new Error('Not implemented');
|
||||
|
||||
@ -46,41 +84,63 @@ export abstract class BaseListingComponent<T = any> {
|
||||
return this._sortKey;
|
||||
}
|
||||
|
||||
protected get _filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] {
|
||||
return [];
|
||||
filtersChanged(filters?: { [key: string]: FilterModel[] }): void {
|
||||
if (filters) {
|
||||
for (const key of Object.keys(filters)) {
|
||||
for (let idx = 0; idx < this[key].length; ++idx) {
|
||||
this[key][idx] = filters[key][idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
this._filterEntities();
|
||||
}
|
||||
|
||||
resetFilters() {
|
||||
for (const filterComponent of this._filterComponents.filter((f) => !!f)) {
|
||||
filterComponent.deactivateAllFilters();
|
||||
}
|
||||
this.filtersChanged();
|
||||
this.searchForm.reset({ query: '' });
|
||||
}
|
||||
|
||||
// Filter
|
||||
|
||||
toggleEntitySelected($event: MouseEvent, entity: T) {
|
||||
$event.stopPropagation();
|
||||
const idx = this.selectedEntitiesIds.indexOf(entity[this._getSelectionKey]);
|
||||
if (idx === -1) {
|
||||
this.selectedEntitiesIds.push(entity[this._getSelectionKey]);
|
||||
} else {
|
||||
this.selectedEntitiesIds.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
toggleSelectAll() {
|
||||
if (this.areSomeEntitiesSelected) {
|
||||
this.selectedEntitiesIds = [];
|
||||
} else {
|
||||
this.selectedEntitiesIds = this.displayedEntities.map((entity) => entity[this._getSelectionKey]);
|
||||
}
|
||||
}
|
||||
|
||||
isEntitySelected(entity: T) {
|
||||
return this.selectedEntitiesIds.indexOf(entity[this._getSelectionKey]) !== -1;
|
||||
}
|
||||
|
||||
toggleSort($event) {
|
||||
this._sortingService.toggleSort(this._getSortKey, $event);
|
||||
}
|
||||
|
||||
// Selection
|
||||
|
||||
protected _preFilter() {
|
||||
return;
|
||||
}
|
||||
|
||||
protected get _filterComponents(): FilterComponent[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected _searchField(entity: T): string {
|
||||
return entity[this._getSearchKey];
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
protected constructor(protected readonly _injector: Injector) {
|
||||
this._formBuilder = this._injector.get<FormBuilder>(FormBuilder);
|
||||
this._changeDetectorRef = this._injector.get<ChangeDetectorRef>(ChangeDetectorRef);
|
||||
this._sortingService = this._injector.get<SortingService>(SortingService);
|
||||
this._initSearch();
|
||||
}
|
||||
|
||||
// Search
|
||||
|
||||
private _initSearch() {
|
||||
this.searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
|
||||
this.searchForm.valueChanges.subscribe(() => this._executeSearch());
|
||||
}
|
||||
|
||||
@debounce(200)
|
||||
protected _executeSearch() {
|
||||
this._executeSearchImmediately();
|
||||
@ -101,18 +161,7 @@ export abstract class BaseListingComponent<T = any> {
|
||||
}
|
||||
}
|
||||
|
||||
// Filter
|
||||
|
||||
filtersChanged(filters?: { [key: string]: FilterModel[] }): void {
|
||||
if (filters) {
|
||||
for (const key of Object.keys(filters)) {
|
||||
for (let idx = 0; idx < this[key].length; ++idx) {
|
||||
this[key][idx] = filters[key][idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
this._filterEntities();
|
||||
}
|
||||
// Sort
|
||||
|
||||
protected _filterEntities() {
|
||||
this._preFilter();
|
||||
@ -121,60 +170,11 @@ export abstract class BaseListingComponent<T = any> {
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
resetFilters() {
|
||||
for (const filterComponent of this._filterComponents.filter((f) => !!f)) {
|
||||
filterComponent.deactivateAllFilters();
|
||||
}
|
||||
this.filtersChanged();
|
||||
this.searchForm.reset({ query: '' });
|
||||
}
|
||||
private _initSearch() {
|
||||
this.searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
|
||||
get hasActiveFilters() {
|
||||
return (
|
||||
this._filterComponents.filter((f) => !!f).reduce((prev, component) => prev || component?.hasActiveFilters, false) ||
|
||||
this.searchForm.get('query').value
|
||||
);
|
||||
}
|
||||
|
||||
// Selection
|
||||
|
||||
toggleEntitySelected($event: MouseEvent, entity: T) {
|
||||
$event.stopPropagation();
|
||||
const idx = this.selectedEntitiesIds.indexOf(entity[this._getSelectionKey]);
|
||||
if (idx === -1) {
|
||||
this.selectedEntitiesIds.push(entity[this._getSelectionKey]);
|
||||
} else {
|
||||
this.selectedEntitiesIds.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
toggleSelectAll() {
|
||||
if (this.areSomeEntitiesSelected) {
|
||||
this.selectedEntitiesIds = [];
|
||||
} else {
|
||||
this.selectedEntitiesIds = this.displayedEntities.map((entity) => entity[this._getSelectionKey]);
|
||||
}
|
||||
}
|
||||
|
||||
get areAllEntitiesSelected() {
|
||||
return this.displayedEntities.length !== 0 && this.selectedEntitiesIds.length === this.displayedEntities.length;
|
||||
}
|
||||
|
||||
get areSomeEntitiesSelected() {
|
||||
return this.selectedEntitiesIds.length > 0;
|
||||
}
|
||||
|
||||
isEntitySelected(entity: T) {
|
||||
return this.selectedEntitiesIds.indexOf(entity[this._getSelectionKey]) !== -1;
|
||||
}
|
||||
|
||||
// Sort
|
||||
|
||||
get sortingOption(): SortingOption {
|
||||
return this._sortingService.getSortingOption(this._getSortKey);
|
||||
}
|
||||
|
||||
toggleSort($event) {
|
||||
this._sortingService.toggleSort(this._getSortKey, $event);
|
||||
this.searchForm.valueChanges.subscribe(() => this._executeSearch());
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,10 +16,6 @@ export class AnnotationIconComponent implements OnInit {
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {
|
||||
this.icon.nativeElement.style.setProperty('--color', this.backgroundColor);
|
||||
}
|
||||
|
||||
get isHint() {
|
||||
return this.type === 'circle' || this.dictType?.type === 'hint';
|
||||
}
|
||||
@ -35,4 +31,8 @@ export class AnnotationIconComponent implements OnInit {
|
||||
get backgroundColor() {
|
||||
return this.color || this.dictType?.hexColor;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.icon.nativeElement.style.setProperty('--color', this.backgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { PermissionsService } from '../../../../../services/permissions.service';
|
||||
import { ProjectWrapper } from '../../../../../state/model/project.wrapper';
|
||||
import { FileStatusWrapper } from '../../../../../models/file/file-status.wrapper';
|
||||
import { FileDownloadService } from '../../../../upload-download/services/file-download.service';
|
||||
import { NotificationService } from '../../../../../services/notification.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
||||
import { NotificationService } from '@services/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
export type MenuState = 'OPEN' | 'CLOSED';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-icon-button',
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { UserWrapper } from '../../../../../services/user.service';
|
||||
import { UserWrapper } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-user-button',
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { TypeValue } from '@redaction/red-ui-http';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -35,6 +35,19 @@ export class FilterComponent implements OnChanges {
|
||||
|
||||
constructor(private readonly _changeDetectorRef: ChangeDetectorRef) {}
|
||||
|
||||
get hasActiveFilters(): boolean {
|
||||
for (const filter of this._allFilters) {
|
||||
if (filter.checked || filter.indeterminate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private get _allFilters(): FilterModel[] {
|
||||
return [...(this.primaryFilters ?? []), ...(this.secondaryFilters ?? [])];
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.atLeastOneFilterIsExpandable = false;
|
||||
this.atLeastOneSecondaryFilterIsExpandable = false;
|
||||
@ -71,15 +84,6 @@ export class FilterComponent implements OnChanges {
|
||||
this._setAllFilters(false);
|
||||
}
|
||||
|
||||
get hasActiveFilters(): boolean {
|
||||
for (const filter of this._allFilters) {
|
||||
if (filter.checked || filter.indeterminate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
applyFilters() {
|
||||
this.filtersChanged.emit({ primary: this.primaryFilters, secondary: this.secondaryFilters });
|
||||
}
|
||||
@ -89,21 +93,6 @@ export class FilterComponent implements OnChanges {
|
||||
filter.expanded = !filter.expanded;
|
||||
}
|
||||
|
||||
private _setAllFilters(value: boolean) {
|
||||
const filters = value ? this.primaryFilters : this._allFilters;
|
||||
filters.forEach((f) => {
|
||||
f.checked = value;
|
||||
f.indeterminate = false;
|
||||
f.filters?.forEach((ff) => {
|
||||
ff.checked = value;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private get _allFilters(): FilterModel[] {
|
||||
return [...(this.primaryFilters ?? []), ...(this.secondaryFilters ?? [])];
|
||||
}
|
||||
|
||||
filterMouseEnter() {
|
||||
this.mouseOver = true;
|
||||
if (this.mouseOverTimeout) {
|
||||
@ -125,4 +114,15 @@ export class FilterComponent implements OnChanges {
|
||||
_(obj): FilterModel {
|
||||
return obj as FilterModel;
|
||||
}
|
||||
|
||||
private _setAllFilters(value: boolean) {
|
||||
const filters = value ? this.primaryFilters : this._allFilters;
|
||||
filters.forEach((f) => {
|
||||
f.checked = value;
|
||||
f.indeterminate = false;
|
||||
f.filters?.forEach((ff) => {
|
||||
ff.checked = value;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { FilterModel } from '../model/filter.model';
|
||||
import { FileStatusWrapper } from '../../../../../models/file/file-status.wrapper';
|
||||
import { ProjectWrapper } from '../../../../../state/model/project.wrapper';
|
||||
import { PermissionsService } from '../../../../../services/permissions.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { ProjectWrapper } from '@state/model/project.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
export function processFilters(oldFilters: FilterModel[], newFilters: FilterModel[]) {
|
||||
copySettings(oldFilters, newFilters);
|
||||
|
||||
@ -6,11 +6,10 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
styleUrls: ['./hidden-action.component.scss']
|
||||
})
|
||||
export class HiddenActionComponent {
|
||||
private _clickCount = 0;
|
||||
private _clickCountTimeout: any;
|
||||
|
||||
@Input() requiredClicks = 4;
|
||||
@Output() action = new EventEmitter();
|
||||
private _clickCount = 0;
|
||||
private _clickCountTimeout: any;
|
||||
|
||||
countActions() {
|
||||
this._clickCount += 1;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@ -25,6 +25,27 @@ export class InitialsAvatarComponent implements OnChanges {
|
||||
|
||||
constructor(private readonly _userService: UserService, private readonly _translateService: TranslateService) {}
|
||||
|
||||
get hasBorder(): boolean {
|
||||
return !!this.user && this._userService.userId !== this.userId && this._userService.isManager(this.user);
|
||||
}
|
||||
|
||||
get disabled(): boolean {
|
||||
return !this._userService.isActive(this.user);
|
||||
}
|
||||
|
||||
private get _colorClass() {
|
||||
if (this._userService.userId === this.userId) {
|
||||
return 'red-white';
|
||||
}
|
||||
if (this.disabled) {
|
||||
return 'inactive';
|
||||
}
|
||||
if (this.color.includes('-')) {
|
||||
return this.color;
|
||||
}
|
||||
return `${this.color}-dark`;
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
const isSystemUser = this.userId && this.userId.toLowerCase() === 'system';
|
||||
if (isSystemUser) {
|
||||
|
||||
@ -8,10 +8,21 @@ const DISPLAYED_ITEMS = 5;
|
||||
styleUrls: ['./pagination.component.scss']
|
||||
})
|
||||
export class PaginationComponent {
|
||||
displayedPages: (number | string)[];
|
||||
@Output() pageChanged = new EventEmitter<number>();
|
||||
displayed;
|
||||
|
||||
private _currentPage: number;
|
||||
|
||||
get currentPage() {
|
||||
return this._currentPage;
|
||||
}
|
||||
|
||||
private _totalPages: number;
|
||||
|
||||
displayedPages: (number | string)[];
|
||||
get totalPages() {
|
||||
return this._totalPages;
|
||||
}
|
||||
|
||||
@Input()
|
||||
set settings(value: { currentPage: number; totalPages: number }) {
|
||||
@ -20,17 +31,19 @@ export class PaginationComponent {
|
||||
this._updatePagesArray();
|
||||
}
|
||||
|
||||
get currentPage() {
|
||||
return this._currentPage;
|
||||
get allDisplayed(): boolean {
|
||||
return this.totalPages > DISPLAYED_ITEMS;
|
||||
}
|
||||
|
||||
get totalPages() {
|
||||
return this._totalPages;
|
||||
selectPage(page: number | string) {
|
||||
if (page !== '...') {
|
||||
this.pageChanged.emit(page as number);
|
||||
}
|
||||
}
|
||||
|
||||
@Output() pageChanged = new EventEmitter<number>();
|
||||
|
||||
displayed;
|
||||
displayValue(page: number | string) {
|
||||
return page === '...' ? page : (page as number) + 1;
|
||||
}
|
||||
|
||||
private _updatePagesArray() {
|
||||
this.displayedPages = [0];
|
||||
@ -47,18 +60,4 @@ export class PaginationComponent {
|
||||
this.displayedPages.push(this.totalPages - 1);
|
||||
}
|
||||
}
|
||||
|
||||
get allDisplayed(): boolean {
|
||||
return this.totalPages > DISPLAYED_ITEMS;
|
||||
}
|
||||
|
||||
selectPage(page: number | string) {
|
||||
if (page !== '...') {
|
||||
this.pageChanged.emit(page as number);
|
||||
}
|
||||
}
|
||||
|
||||
displayValue(page: number | string) {
|
||||
return page === '...' ? page : (page as number) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,11 +15,11 @@ export class SearchInputComponent {
|
||||
return !!this.form.get('query').value.length;
|
||||
}
|
||||
|
||||
clearContent() {
|
||||
this.form.patchValue({ query: '' });
|
||||
}
|
||||
|
||||
get computedWidth() {
|
||||
return this.width === 'full' ? '100%' : `${this.width}px`;
|
||||
}
|
||||
|
||||
clearContent() {
|
||||
this.form.patchValue({ query: '' });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
|
||||
import { Color } from '../../../../utils/types';
|
||||
import { Color } from '@utils/types';
|
||||
import { FilterModel } from '../filter/model/filter.model';
|
||||
|
||||
export class DoughnutChartConfig {
|
||||
@ -36,17 +36,6 @@ export class SimpleDoughnutChartComponent implements OnChanges {
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.calculateChartData();
|
||||
this.cx = this.radius + this.strokeWidth / 2;
|
||||
this.cy = this.radius + this.strokeWidth / 2;
|
||||
this.size = this.strokeWidth + this.radius * 2;
|
||||
this.parsedConfig = this.config.map((el) => ({
|
||||
...el,
|
||||
checked: this.filter?.find((f) => f.key === el.key)?.checked
|
||||
}));
|
||||
}
|
||||
|
||||
get circumference() {
|
||||
return 2 * Math.PI * this.radius;
|
||||
}
|
||||
@ -59,6 +48,17 @@ export class SimpleDoughnutChartComponent implements OnChanges {
|
||||
return this.totalType === 'sum' ? this.dataTotal : this.config.length;
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.calculateChartData();
|
||||
this.cx = this.radius + this.strokeWidth / 2;
|
||||
this.cy = this.radius + this.strokeWidth / 2;
|
||||
this.size = this.strokeWidth + this.radius * 2;
|
||||
this.parsedConfig = this.config.map((el) => ({
|
||||
...el,
|
||||
checked: this.filter?.find((f) => f.key === el.key)?.checked
|
||||
}));
|
||||
}
|
||||
|
||||
calculateChartData() {
|
||||
const newData = [];
|
||||
let angleOffset = -90;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { Color } from '../../../../utils/types';
|
||||
import { Color } from '@utils/types';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-status-bar',
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { SortingOption } from '../../../../services/sorting.service';
|
||||
import { SortingOption } from '@services/sorting.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-table-col-name',
|
||||
|
||||
@ -5,9 +5,13 @@ import { AfterContentChecked, Directive, ElementRef, HostBinding } from '@angula
|
||||
exportAs: 'redactionHasScrollbar'
|
||||
})
|
||||
export class HasScrollbarDirective implements AfterContentChecked {
|
||||
@HostBinding('class') class = '';
|
||||
|
||||
constructor(private readonly _elementRef: ElementRef) {}
|
||||
|
||||
@HostBinding('class') class = '';
|
||||
get hasScrollbar() {
|
||||
return this._elementRef?.nativeElement.clientHeight < this._elementRef?.nativeElement.scrollHeight;
|
||||
}
|
||||
|
||||
ngAfterContentChecked() {
|
||||
this._process();
|
||||
@ -19,8 +23,4 @@ export class HasScrollbarDirective implements AfterContentChecked {
|
||||
this.class = newClass;
|
||||
}
|
||||
}
|
||||
|
||||
get hasScrollbar() {
|
||||
return this._elementRef?.nativeElement.clientHeight < this._elementRef?.nativeElement.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Directive, HostListener } from '@angular/core';
|
||||
import { RouterHistoryService } from '../../../services/router-history.service';
|
||||
import { RouterHistoryService } from '@services/router-history.service';
|
||||
|
||||
@Directive({
|
||||
selector: '[redactionNavigateLastProjectsScreen]'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user