Pull request #261: Common lib
Merge in RED/ui from common-lib to master * commit '9df7530e5db2390971de3beaea78365cdc976c37': update scroll button move entities service to common lib remove duplicated methods update common lib move table column name to common lib move search service, update user wrapper and service move sort and humanize pipe mode sorting to common-lib
This commit is contained in:
commit
1028f97e7a
@ -1,7 +1,7 @@
|
||||
<div class="red-top-bar">
|
||||
<div class="top-bar-row">
|
||||
<div *ngIf="!permissionsService.isUser()" class="menu-placeholder"></div>
|
||||
<div *ngIf="permissionsService.isUser()" class="menu visible-lt-lg">
|
||||
<div *ngIf="!currentUser.isUser" class="menu-placeholder"></div>
|
||||
<div *ngIf="currentUser.isUser" class="menu visible-lt-lg">
|
||||
<button [matMenuTriggerFor]="menuNav" mat-flat-button>
|
||||
<mat-icon svgIcon="red:menu"></mat-icon>
|
||||
</button>
|
||||
@ -23,20 +23,19 @@
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
<div *ngIf="permissionsService.isUser()" class="menu flex-2 visible-lg breadcrumbs-container">
|
||||
<a
|
||||
*ngIf="dossiersView"
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
class="breadcrumb"
|
||||
routerLink="/main/dossiers"
|
||||
routerLinkActive="active"
|
||||
translate="top-bar.navigation-items.dossiers"
|
||||
></a>
|
||||
<a *ngIf="!dossiersView" class="breadcrumb back" redactionNavigateLastDossiersScreen>
|
||||
<div *ngIf="currentUser.isUser" class="menu flex-2 visible-lg breadcrumbs-container">
|
||||
<a *ngIf="(isDossiersView$ | async) === false" class="breadcrumb back" redactionNavigateLastDossiersScreen>
|
||||
<mat-icon svgIcon="red:expand"></mat-icon>
|
||||
{{ 'top-bar.navigation-items.back' | translate }}
|
||||
</a>
|
||||
<ng-container *ngIf="dossiersView">
|
||||
<ng-container *ngIf="isDossiersView$ | async">
|
||||
<a
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
class="breadcrumb"
|
||||
routerLink="/main/dossiers"
|
||||
routerLinkActive="active"
|
||||
translate="top-bar.navigation-items.dossiers"
|
||||
></a>
|
||||
<mat-icon *ngIf="appStateService.activeDossier" svgIcon="red:arrow-right"></mat-icon>
|
||||
<a
|
||||
*ngIf="appStateService.activeDossier"
|
||||
@ -68,7 +67,7 @@
|
||||
<div class="buttons">
|
||||
<iqser-circle-button
|
||||
(action)="openSpotlightSearch()"
|
||||
*ngIf="!isSearchScreen"
|
||||
*ngIf="(isSearchScreen$ | async) === false"
|
||||
[icon]="'red:search'"
|
||||
[tooltip]="'search.header-label' | translate"
|
||||
tooltipPosition="below"
|
||||
@ -76,7 +75,11 @@
|
||||
|
||||
<redaction-notifications *ngIf="userPreferenceService.areDevFeaturesEnabled"></redaction-notifications>
|
||||
</div>
|
||||
<redaction-user-button [matMenuTriggerFor]="userMenu" [showDot]="showPendingDownloadsDot" [user]="user"></redaction-user-button>
|
||||
<redaction-user-button
|
||||
[matMenuTriggerFor]="userMenu"
|
||||
[showDot]="fileDownloadService.hasPendingDownloads"
|
||||
[userId]="currentUser.id"
|
||||
></redaction-user-button>
|
||||
|
||||
<mat-menu #userMenu="matMenu" xPosition="before">
|
||||
<ng-container *ngFor="let item of userMenuItems; trackBy: trackByName">
|
||||
@ -85,7 +88,7 @@
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
<button (click)="logout()" mat-menu-item>
|
||||
<button (click)="userService.logout()" mat-menu-item>
|
||||
<mat-icon svgIcon="red:logout"></mat-icon>
|
||||
<span translate="top-bar.navigation-items.my-account.children.logout"> </span>
|
||||
</button>
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavigationStart, Router } from '@angular/router';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
@ -12,19 +11,33 @@ import { SpotlightSearchComponent } from '@components/spotlight-search/spotlight
|
||||
import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action';
|
||||
import { SpotlightSearchDialogData } from '@components/spotlight-search/spotlight-search-dialog-data';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { distinctUntilChanged, filter, map, startWith } from 'rxjs/operators';
|
||||
|
||||
interface MenuItem {
|
||||
name: string;
|
||||
routerLink?: string;
|
||||
show: boolean;
|
||||
action?: () => void;
|
||||
readonly name: string;
|
||||
readonly routerLink?: string;
|
||||
readonly show: boolean;
|
||||
readonly action?: () => void;
|
||||
}
|
||||
|
||||
const isNavigationStart = event => event instanceof NavigationStart;
|
||||
const isDossiersView = url => url.includes('/main/dossiers') && !url.includes('/search');
|
||||
const isSearchScreen = url => url.includes('/main/dossiers') && url.includes('/search');
|
||||
|
||||
@Component({
|
||||
templateUrl: './base-screen.component.html',
|
||||
styleUrls: ['./base-screen.component.scss']
|
||||
})
|
||||
export class BaseScreenComponent {
|
||||
private readonly _navigationStart$ = this._router.events.pipe(
|
||||
filter(isNavigationStart),
|
||||
map((event: NavigationStart) => event.url),
|
||||
startWith(this._router.url),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
readonly currentUser = this.userService.currentUser;
|
||||
readonly isDossiersView$ = this._navigationStart$.pipe(map(isDossiersView));
|
||||
readonly isSearchScreen$ = this._navigationStart$.pipe(map(isSearchScreen));
|
||||
readonly userMenuItems: MenuItem[] = [
|
||||
{
|
||||
name: _('top-bar.navigation-items.my-account.children.my-profile'),
|
||||
@ -34,60 +47,31 @@ export class BaseScreenComponent {
|
||||
{
|
||||
name: _('top-bar.navigation-items.my-account.children.admin'),
|
||||
routerLink: '/main/admin',
|
||||
show: this.permissionsService.isManager() || this.permissionsService.isUserAdmin(),
|
||||
show: this.currentUser.isManager || this.currentUser.isUserAdmin,
|
||||
action: this.appStateService.reset
|
||||
},
|
||||
{
|
||||
name: _('top-bar.navigation-items.my-account.children.downloads'),
|
||||
routerLink: '/main/downloads',
|
||||
show: this.permissionsService.isUser()
|
||||
show: this.currentUser.isUser
|
||||
},
|
||||
{
|
||||
name: _('top-bar.navigation-items.my-account.children.trash'),
|
||||
routerLink: '/main/admin/trash',
|
||||
show: this.permissionsService.isManager() || this.permissionsService.isUserAdmin()
|
||||
show: this.currentUser.isManager || this.currentUser.isUserAdmin
|
||||
}
|
||||
];
|
||||
|
||||
showSearch = false;
|
||||
|
||||
constructor(
|
||||
readonly appStateService: AppStateService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly userService: UserService,
|
||||
readonly userPreferenceService: UserPreferenceService,
|
||||
readonly titleService: Title,
|
||||
readonly fileDownloadService: FileDownloadService,
|
||||
private readonly _router: Router,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _dialog: MatDialog
|
||||
) {
|
||||
_router.events.subscribe(() => {
|
||||
this._dossiersView = _router.url.includes('/main/dossiers') && !this.isSearchScreen;
|
||||
});
|
||||
}
|
||||
|
||||
private _dossiersView: boolean;
|
||||
|
||||
get dossiersView() {
|
||||
return this._dossiersView;
|
||||
}
|
||||
|
||||
get isSearchScreen() {
|
||||
return this._router.url.includes('/search');
|
||||
}
|
||||
|
||||
get user() {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
get showPendingDownloadsDot() {
|
||||
return this.fileDownloadService.hasPendingDownloads;
|
||||
}
|
||||
|
||||
get languages(): string[] {
|
||||
return this._translateService.langs;
|
||||
}
|
||||
) {}
|
||||
|
||||
openSpotlightSearch() {
|
||||
const spotlightSearchActions: SpotlightSearchAction[] = [
|
||||
@ -95,12 +79,12 @@ export class BaseScreenComponent {
|
||||
text: this._translateService.instant('search.this-dossier'),
|
||||
icon: 'red:enter',
|
||||
hide: !this.appStateService.activeDossier,
|
||||
action: query => this._searchThisDossier(query)
|
||||
action: query => this._search(query, this.appStateService.activeDossier.dossierId)
|
||||
},
|
||||
{
|
||||
text: this._translateService.instant('search.entire-platform'),
|
||||
icon: 'red:enter',
|
||||
action: query => this._searchEntirePlatform(query)
|
||||
action: query => this._search(query)
|
||||
}
|
||||
];
|
||||
|
||||
@ -112,23 +96,9 @@ export class BaseScreenComponent {
|
||||
});
|
||||
}
|
||||
|
||||
private _searchThisDossier(query: string) {
|
||||
this._router
|
||||
.navigate(['main/dossiers/search'], {
|
||||
queryParams: {
|
||||
query: query,
|
||||
dossierId: this.appStateService.activeDossier.dossierId
|
||||
}
|
||||
})
|
||||
.then();
|
||||
}
|
||||
|
||||
private _searchEntirePlatform(query: string) {
|
||||
this._router.navigate(['main/dossiers/search'], { queryParams: { query: query } }).then();
|
||||
}
|
||||
|
||||
logout() {
|
||||
this._userService.logout();
|
||||
private _search(query: string, dossierId?: string) {
|
||||
const queryParams = { query, dossierId };
|
||||
this._router.navigate(['main/dossiers/search'], { queryParams }).then();
|
||||
}
|
||||
|
||||
trackByName(index: number, item: MenuItem) {
|
||||
|
||||
@ -7,12 +7,12 @@
|
||||
[bulkActions]="bulkActions"
|
||||
[hasEmptyColumn]="true"
|
||||
[selectionEnabled]="true"
|
||||
[tableColConfigs]="tableColConfigs"
|
||||
[tableColumnConfigs]="tableColConfigs"
|
||||
[tableHeaderLabel]="tableHeaderLabel"
|
||||
></redaction-table-header>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[text]="'downloads-list.no-data.title' | translate"
|
||||
icon="red:download"
|
||||
></redaction-empty-state>
|
||||
@ -74,7 +74,7 @@
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
(action)="deleteItems()"
|
||||
*ngIf="screenStateService.areSomeEntitiesSelected$ | async"
|
||||
*ngIf="entitiesService.areSomeSelected$ | async"
|
||||
[tooltip]="'downloads-list.bulk.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
|
||||
@ -2,32 +2,27 @@ import { Component, Injector, OnInit } from '@angular/core';
|
||||
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';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { CircleButtonTypes, TableColumnConfig } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { TableColConfig } from '@shared/components/table-col-name/table-col-name.component';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-downloads-list-screen',
|
||||
templateUrl: './downloads-list-screen.component.html',
|
||||
styleUrls: ['./downloads-list-screen.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class DownloadsListScreenComponent extends BaseListingComponent<DownloadStatusWrapper> implements OnInit {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly itemSize = 80;
|
||||
readonly tableColConfigs: TableColConfig[] = [
|
||||
protected readonly _primaryKey = 'storageId';
|
||||
readonly tableHeaderLabel = _('downloads-list.table-header.title');
|
||||
readonly tableColConfigs: TableColumnConfig<DownloadStatusWrapper>[] = [
|
||||
{ label: _('downloads-list.table-col-names.name') },
|
||||
{ label: _('downloads-list.table-col-names.size') },
|
||||
{ label: _('downloads-list.table-col-names.date') },
|
||||
{ label: _('downloads-list.table-col-names.status') }
|
||||
];
|
||||
protected readonly _primaryKey = 'storageId';
|
||||
protected readonly _tableHeaderLabel = _('downloads-list.table-header.title');
|
||||
|
||||
constructor(
|
||||
readonly fileDownloadService: FileDownloadService,
|
||||
@ -46,13 +41,13 @@ export class DownloadsListScreenComponent extends BaseListingComponent<DownloadS
|
||||
}
|
||||
|
||||
async deleteItems(downloads?: DownloadStatusWrapper[]) {
|
||||
const storageIds = (downloads || this.screenStateService.selectedEntities).map(d => d.storageId);
|
||||
const storageIds = (downloads || this.entitiesService.selected).map(d => d.storageId);
|
||||
await this._downloadControllerService.deleteDownload({ storageIds }).toPromise();
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
await this.fileDownloadService.getDownloadStatus().toPromise();
|
||||
this.screenStateService.setEntities(this.fileDownloadService.downloads);
|
||||
this.entitiesService.setEntities(this.fileDownloadService.downloads);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,12 +98,12 @@ export class UserProfileScreenComponent implements OnInit {
|
||||
private _initializeForm(): void {
|
||||
try {
|
||||
this._profileModel = {
|
||||
email: this._userService.user.email,
|
||||
firstName: this._userService.user.firstName,
|
||||
lastName: this._userService.user.lastName,
|
||||
email: this._userService.currentUser.email,
|
||||
firstName: this._userService.currentUser.firstName,
|
||||
lastName: this._userService.currentUser.lastName,
|
||||
language: this._languageService.currentLanguage
|
||||
};
|
||||
if (this._userService.user.email) {
|
||||
if (this._userService.currentUser.email) {
|
||||
// disable email if it's already set
|
||||
this.formGroup.get('email').disable();
|
||||
}
|
||||
|
||||
@ -1,12 +1,7 @@
|
||||
<redaction-side-nav [title]="translations[type] | translate">
|
||||
<ng-container *ngFor="let item of items[type]">
|
||||
<div
|
||||
*ngIf="
|
||||
(!item.onlyAdmin || permissionsService.isAdmin()) &&
|
||||
(!item.onlyDevMode || userPreferenceService.areDevFeaturesEnabled) &&
|
||||
(!item.userManagerOnly || permissionsService.canManageUsers()) &&
|
||||
(!item.onlyManager || permissionsService.isManager())
|
||||
"
|
||||
*ngIf="!item.hideIf"
|
||||
[routerLinkActiveOptions]="{ exact: false }"
|
||||
[routerLink]="prefix + item.screen"
|
||||
class="item"
|
||||
|
||||
@ -1,12 +1,18 @@
|
||||
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 { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { adminSideNavTranslations } from '../translations/admin-side-nav-translations';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
type Type = 'settings' | 'dossierTemplates';
|
||||
|
||||
interface NavItem {
|
||||
readonly label: string;
|
||||
readonly screen: string;
|
||||
readonly hideIf?: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-admin-side-nav',
|
||||
templateUrl: './admin-side-nav.component.html',
|
||||
@ -14,29 +20,42 @@ type Type = 'settings' | 'dossierTemplates';
|
||||
})
|
||||
export class AdminSideNavComponent {
|
||||
@Input() type: Type;
|
||||
translations = adminSideNavTranslations;
|
||||
readonly translations = adminSideNavTranslations;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly prefix = this._appStateService.activeDictionaryType ? '../../' : '../';
|
||||
|
||||
items: {
|
||||
[key in Type]: {
|
||||
screen: string;
|
||||
onlyDevMode?: boolean;
|
||||
onlyAdmin?: boolean;
|
||||
onlyManager?: boolean;
|
||||
userManagerOnly?: boolean;
|
||||
label: string;
|
||||
}[];
|
||||
} = {
|
||||
readonly items: { readonly [key in Type]: NavItem[] } = {
|
||||
settings: [
|
||||
{ screen: 'dossier-templates', label: _('dossier-templates'), onlyManager: true },
|
||||
{ screen: 'digital-signature', label: _('digital-signature'), onlyAdmin: true },
|
||||
{ screen: 'license-info', label: _('license-information'), onlyAdmin: true },
|
||||
{ screen: 'audit', label: _('audit'), onlyAdmin: true },
|
||||
{ screen: 'users', label: _('user-management'), userManagerOnly: true },
|
||||
{ screen: 'general-config', label: _('configurations'), onlyAdmin: true }
|
||||
{
|
||||
screen: 'dossier-templates',
|
||||
label: _('dossier-templates'),
|
||||
hideIf: !this.currentUser.isManager
|
||||
},
|
||||
{
|
||||
screen: 'digital-signature',
|
||||
label: _('digital-signature'),
|
||||
hideIf: !this.currentUser.isAdmin
|
||||
},
|
||||
{
|
||||
screen: 'license-info',
|
||||
label: _('license-information'),
|
||||
hideIf: !this.currentUser.isAdmin
|
||||
},
|
||||
{ screen: 'audit', label: _('audit'), hideIf: !this.currentUser.isAdmin },
|
||||
{ screen: 'users', label: _('user-management'), hideIf: !this.currentUser.isUserAdmin },
|
||||
{
|
||||
screen: 'general-config',
|
||||
label: _('configurations'),
|
||||
hideIf: !this.currentUser.isAdmin
|
||||
}
|
||||
],
|
||||
dossierTemplates: [
|
||||
{ screen: 'dictionaries', label: _('dictionaries') },
|
||||
{ screen: 'rules', onlyDevMode: true, label: _('rule-editor') },
|
||||
{
|
||||
screen: 'rules',
|
||||
label: _('rule-editor'),
|
||||
hideIf: !this.userPreferenceService.areDevFeaturesEnabled
|
||||
},
|
||||
{ screen: 'default-colors', label: _('default-colors') },
|
||||
{ screen: 'watermark', label: _('watermark') },
|
||||
{ screen: 'file-attributes', label: _('file-attributes') },
|
||||
@ -46,16 +65,8 @@ export class AdminSideNavComponent {
|
||||
};
|
||||
|
||||
constructor(
|
||||
private readonly _userService: UserService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
readonly userPreferenceService: UserPreferenceService,
|
||||
readonly permissionsService: PermissionsService
|
||||
readonly userPreferenceService: UserPreferenceService
|
||||
) {}
|
||||
|
||||
get prefix() {
|
||||
if (this._appStateService.activeDictionaryType) {
|
||||
return '../../';
|
||||
}
|
||||
|
||||
return '../';
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,8 +6,8 @@ import { Observable } from 'rxjs';
|
||||
import { Toaster } from '@services/toaster.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
|
||||
import { humanize } from '../../../../utils/functions';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { humanize } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-add-edit-dictionary-dialog',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { UserWrapper } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-add-edit-user-dialog',
|
||||
@ -10,7 +10,7 @@ import { User } from '@redaction/red-ui-http';
|
||||
export class AddEditUserDialogComponent {
|
||||
resettingPassword = false;
|
||||
|
||||
constructor(public dialogRef: MatDialogRef<AddEditUserDialogComponent>, @Inject(MAT_DIALOG_DATA) public user: User) {}
|
||||
constructor(readonly dialogRef: MatDialogRef<AddEditUserDialogComponent>, @Inject(MAT_DIALOG_DATA) readonly user: UserWrapper) {}
|
||||
|
||||
toggleResetPassword() {
|
||||
this.resettingPassword = !this.resettingPassword;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FormBuilder, Validators } from '@angular/forms';
|
||||
import { UserControllerService } from '@redaction/red-ui-http';
|
||||
import { UserService, UserWrapper } from '@services/user.service';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
|
||||
@Component({
|
||||
@ -10,8 +10,10 @@ import { LoadingService } from '@services/loading.service';
|
||||
styleUrls: ['./reset-password.component.scss']
|
||||
})
|
||||
export class ResetPasswordComponent {
|
||||
passwordForm: FormGroup;
|
||||
@Input() user: User;
|
||||
readonly passwordForm = this._formBuilder.group({
|
||||
temporaryPassword: [null, Validators.required]
|
||||
});
|
||||
@Input() user: UserWrapper;
|
||||
@Output() toggleResetPassword = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
@ -19,14 +21,10 @@ export class ResetPasswordComponent {
|
||||
private readonly _userControllerService: UserControllerService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _loadingService: LoadingService
|
||||
) {
|
||||
this.passwordForm = this._formBuilder.group({
|
||||
temporaryPassword: [null, Validators.required]
|
||||
});
|
||||
}
|
||||
) {}
|
||||
|
||||
get userName() {
|
||||
return this._userService.getNameForId(this.user.userId);
|
||||
return this._userService.getNameForId(this.user.id);
|
||||
}
|
||||
|
||||
async save() {
|
||||
@ -37,7 +35,7 @@ export class ResetPasswordComponent {
|
||||
password: this.passwordForm.get('temporaryPassword').value,
|
||||
temporary: true
|
||||
},
|
||||
this.user.userId
|
||||
this.user.id
|
||||
)
|
||||
.toPromise();
|
||||
this._loadingService.stop();
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { UserControllerService } from '@redaction/red-ui-http';
|
||||
import { AdminDialogService } from '../../../services/admin-dialog.service';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { rolesTranslations } from '../../../../../translations/roles-translations';
|
||||
import { IconButtonTypes } from '@iqser/common-ui';
|
||||
import { UserWrapper } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-user-details',
|
||||
@ -14,7 +15,7 @@ import { IconButtonTypes } from '@iqser/common-ui';
|
||||
export class UserDetailsComponent implements OnInit {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
|
||||
@Input() user: User;
|
||||
@Input() user: UserWrapper;
|
||||
@Output() toggleResetPassword = new EventEmitter();
|
||||
@Output() closeDialog = new EventEmitter<any>();
|
||||
userForm: FormGroup;
|
||||
@ -99,7 +100,7 @@ export class UserDetailsComponent implements OnInit {
|
||||
if (!this.user) {
|
||||
await this._userControllerService.createUser(userData).toPromise();
|
||||
} else {
|
||||
await this._userControllerService.updateProfile(userData, this.user.userId).toPromise();
|
||||
await this._userControllerService.updateProfile(userData, this.user.id).toPromise();
|
||||
}
|
||||
|
||||
this.closeDialog.emit(true);
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { UserControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { UserWrapper } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-confirm-delete-users-dialog',
|
||||
@ -11,7 +12,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
styleUrls: ['./confirm-delete-users-dialog.component.scss']
|
||||
})
|
||||
export class ConfirmDeleteUsersDialogComponent {
|
||||
checkboxes = [
|
||||
readonly checkboxes = [
|
||||
{ value: false, label: _('confirm-delete-users.impacted-dossiers') },
|
||||
{ value: false, label: _('confirm-delete-users.impacted-documents') }
|
||||
];
|
||||
@ -22,12 +23,12 @@ export class ConfirmDeleteUsersDialogComponent {
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _userControllerService: UserControllerService,
|
||||
public dialogRef: MatDialogRef<ConfirmDeleteUsersDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public users: User[]
|
||||
readonly dialogRef: MatDialogRef<ConfirmDeleteUsersDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly users: UserWrapper[]
|
||||
) {
|
||||
this.dossiersCount = this._appStateService.allDossiers.filter(dw => {
|
||||
for (const user of this.users) {
|
||||
if (dw.memberIds.indexOf(user.userId) !== -1) {
|
||||
if (dw.memberIds.indexOf(user.id) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -42,7 +43,7 @@ export class ConfirmDeleteUsersDialogComponent {
|
||||
async deleteUser() {
|
||||
if (this.valid) {
|
||||
this._loadingService.start();
|
||||
await this._userControllerService.deleteUsers(this.users.map(u => u.userId)).toPromise();
|
||||
await this._userControllerService.deleteUsers(this.users.map(u => u.id)).toPromise();
|
||||
this.dialogRef.close(true);
|
||||
} else {
|
||||
this.showToast = true;
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
<div class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="screenStateService.areAllEntitiesSelected$ | async"
|
||||
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
<span class="all-caps-label">
|
||||
{{ 'file-attributes-csv-import.table-header.title' | translate: { length: (screenStateService.allEntitiesLength$ | async) } }}
|
||||
{{ 'file-attributes-csv-import.table-header.title' | translate: { length: (entitiesService.allLength$ | async) } }}
|
||||
</span>
|
||||
|
||||
<ng-container *ngIf="screenStateService.areSomeEntitiesSelected$ | async">
|
||||
<ng-container *ngIf="entitiesService.areSomeSelected$ | async">
|
||||
<iqser-circle-button
|
||||
[matMenuTriggerFor]="readOnlyMenu"
|
||||
[tooltip]="'file-attributes-csv-import.table-header.actions.read-only' | translate"
|
||||
@ -54,32 +54,29 @@
|
||||
<div class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
[label]="'file-attributes-csv-import.table-col-names.name' | translate"
|
||||
class="name"
|
||||
></redaction-table-col-name>
|
||||
<iqser-table-column-name [label]="'file-attributes-csv-import.table-col-names.name' | translate" class="name"></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name [label]="'file-attributes-csv-import.table-col-names.type' | translate"></redaction-table-col-name>
|
||||
<iqser-table-column-name [label]="'file-attributes-csv-import.table-col-names.type' | translate"></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'file-attributes-csv-import.table-col-names.read-only' | translate"
|
||||
class="flex-center"
|
||||
leftIcon="red:read-only"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'file-attributes-csv-import.table-col-names.primary' | translate"
|
||||
[rightIconTooltip]="'file-attributes-csv-import.table-col-names.primary-info-tooltip' | translate"
|
||||
class="flex-center"
|
||||
rightIcon="red:status-info"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<div></div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[text]="'file-attributes-csv-import.no-data.title' | translate"
|
||||
icon="red:attribute"
|
||||
></redaction-empty-state>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
@import '../../../../../../assets/styles/variables';
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
iqser-table-column-name::ng-deep {
|
||||
> div {
|
||||
padding: 0 13px 0 10px !important;
|
||||
|
||||
|
||||
@ -1,52 +1,51 @@
|
||||
import { Component, EventEmitter, Injector, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { Field } from '../file-attributes-csv-import-dialog.component';
|
||||
import { FileAttributeConfig } from '@redaction/red-ui-http';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { fileAttributeTypesTranslations } from '../../../translations/file-attribute-types-translations';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { fileAttributeTypesTranslations } from '../../../translations/file-attribute-types-translations';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-active-fields-listing',
|
||||
templateUrl: './active-fields-listing.component.html',
|
||||
styleUrls: ['./active-fields-listing.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class ActiveFieldsListingComponent extends BaseListingComponent<Field> implements OnChanges {
|
||||
protected readonly _primaryKey = 'csvColumn';
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly translations = fileAttributeTypesTranslations;
|
||||
readonly typeOptions = [
|
||||
FileAttributeConfig.TypeEnum.TEXT,
|
||||
FileAttributeConfig.TypeEnum.NUMBER,
|
||||
FileAttributeConfig.TypeEnum.DATE
|
||||
] as const;
|
||||
|
||||
@Input() entities: Field[];
|
||||
@Output() entitiesChange = new EventEmitter<Field[]>();
|
||||
@Output() setHoveredColumn = new EventEmitter<string>();
|
||||
@Output() toggleFieldActive = new EventEmitter<Field>();
|
||||
|
||||
readonly typeOptions = [FileAttributeConfig.TypeEnum.TEXT, FileAttributeConfig.TypeEnum.NUMBER, FileAttributeConfig.TypeEnum.DATE];
|
||||
protected readonly _primaryKey = 'csvColumn';
|
||||
|
||||
constructor(protected readonly _injector: Injector) {
|
||||
super(_injector);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes.entities) {
|
||||
this.screenStateService.setEntities(this.entities);
|
||||
this.screenStateService.updateSelection();
|
||||
this.entitiesService.setEntities(this.entities);
|
||||
this.entitiesService.updateSelection();
|
||||
}
|
||||
}
|
||||
|
||||
deactivateSelection() {
|
||||
this.allEntities.filter(field => this.isSelected(field)).forEach(field => (field.primaryAttribute = false));
|
||||
this.screenStateService.setEntities(this.allEntities.filter(field => !this.isSelected(field)));
|
||||
this.entitiesService.setEntities(this.allEntities.filter(field => !this.isSelected(field)));
|
||||
this.entitiesChange.emit(this.allEntities);
|
||||
this.screenStateService.setSelectedEntities([]);
|
||||
this.entitiesService.setSelected([]);
|
||||
}
|
||||
|
||||
setAttributeForSelection(attribute: string, value: any) {
|
||||
for (const item of this.screenStateService.selectedEntities) {
|
||||
for (const item of this.entitiesService.selected) {
|
||||
this.allEntities.find(f => f.csvColumn === item.csvColumn)[attribute] = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,11 +8,7 @@ import { Observable } from 'rxjs';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { Toaster } from '@services/toaster.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
export interface Field {
|
||||
@ -29,7 +25,7 @@ export interface Field {
|
||||
@Component({
|
||||
templateUrl: './file-attributes-csv-import-dialog.component.html',
|
||||
styleUrls: ['./file-attributes-csv-import-dialog.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class FileAttributesCsvImportDialogComponent extends BaseListingComponent<Field> {
|
||||
protected readonly _primaryKey = 'csvColumn';
|
||||
@ -97,7 +93,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
|
||||
this.parseResult.meta.fields = Object.keys(this.parseResult.data[0]);
|
||||
}
|
||||
|
||||
this.screenStateService.setEntities(this.parseResult.meta.fields.map(field => this._buildAttribute(field)));
|
||||
this.entitiesService.setEntities(this.parseResult.meta.fields.map(field => this._buildAttribute(field)));
|
||||
this.activeFields = [];
|
||||
|
||||
for (const entity of this.allEntities) {
|
||||
|
||||
@ -19,7 +19,7 @@ export class SmtpAuthDialogComponent {
|
||||
@Inject(MAT_DIALOG_DATA) public data: SMTPConfigurationModel
|
||||
) {
|
||||
this.authForm = this._formBuilder.group({
|
||||
user: [data?.user || this._userService.user.email, [Validators.required]],
|
||||
user: [data?.user || this._userService.currentUser.email, [Validators.required]],
|
||||
password: [data?.password, Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
<div class="actions">
|
||||
<iqser-circle-button
|
||||
*ngIf="permissionsService.isUser()"
|
||||
*ngIf="currentUser.isUser"
|
||||
[tooltip]="'common.close' | translate"
|
||||
class="ml-6"
|
||||
icon="red:close"
|
||||
@ -87,23 +87,23 @@
|
||||
</div>
|
||||
|
||||
<div class="table-header" redactionSyncWidth="table-item">
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'audit-screen.table-col-names.message' | translate"
|
||||
column="message"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'audit-screen.table-col-names.date' | translate"
|
||||
column="date"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'audit-screen.table-col-names.user' | translate"
|
||||
class="user-column"
|
||||
column="user"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'audit-screen.table-col-names.category' | translate"
|
||||
column="category"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { AuditControllerService, AuditResponse, AuditSearchRequest } from '@redaction/red-ui-http';
|
||||
import { Moment } from 'moment';
|
||||
@ -8,6 +7,7 @@ import { LoadingService } from '@services/loading.service';
|
||||
import { AutoUnsubscribeComponent } from '@iqser/common-ui';
|
||||
import { auditCategoriesTranslations } from '../../translations/audit-categories-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
const PAGE_SIZE = 50;
|
||||
|
||||
@ -19,7 +19,8 @@ const PAGE_SIZE = 50;
|
||||
export class AuditScreenComponent extends AutoUnsubscribeComponent implements OnDestroy {
|
||||
readonly ALL_CATEGORIES = 'allCategories';
|
||||
readonly ALL_USERS = _('audit-screen.all-users');
|
||||
translations = auditCategoriesTranslations;
|
||||
readonly translations = auditCategoriesTranslations;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
filterForm: FormGroup;
|
||||
categories: string[] = [];
|
||||
@ -30,10 +31,10 @@ export class AuditScreenComponent extends AutoUnsubscribeComponent implements On
|
||||
private _previousTo: Moment;
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _auditControllerService: AuditControllerService,
|
||||
private readonly _loadingService: LoadingService
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _auditControllerService: AuditControllerService
|
||||
) {
|
||||
super();
|
||||
this.filterForm = this._formBuilder.group({
|
||||
|
||||
@ -22,21 +22,21 @@
|
||||
<div class="content-container">
|
||||
<div class="header-item">
|
||||
<span class="all-caps-label">
|
||||
{{ 'default-colors-screen.table-header.title' | translate: { length: screenStateService.allEntitiesLength$ | async } }}
|
||||
{{ 'default-colors-screen.table-header.title' | translate: { length: entitiesService.allLength$ | async } }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="table-header" redactionSyncWidth="table-item">
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'default-colors-screen.table-col-names.key' | translate"
|
||||
[withSort]="true"
|
||||
column="key"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'default-colors-screen.table-col-names.color' | translate"
|
||||
class="flex-center"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<div></div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
|
||||
@ -5,20 +5,16 @@ import { ActivatedRoute } from '@angular/router';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { DefaultColorType } from '@models/default-color-key.model';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { defaultColorsTranslations } from '../../translations/default-colors-translations';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { DefaultColorType } from '@models/default-color-key.model';
|
||||
import { defaultColorsTranslations } from '../../translations/default-colors-translations';
|
||||
|
||||
@Component({
|
||||
templateUrl: './default-colors-screen.component.html',
|
||||
styleUrls: ['./default-colors-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class DefaultColorsScreenComponent
|
||||
extends BaseListingComponent<{
|
||||
@ -70,7 +66,7 @@ export class DefaultColorsScreenComponent
|
||||
key,
|
||||
value: data[key]
|
||||
}));
|
||||
this.screenStateService.setEntities(entities);
|
||||
this.entitiesService.setEntities(entities);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,12 +23,12 @@
|
||||
<div class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="screenStateService.areAllEntitiesSelected$ | async"
|
||||
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{ 'dictionary-listing.table-header.title' | translate: { length: (screenStateService.displayedLength$ | async) } }}
|
||||
{{ 'dictionary-listing.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
|
||||
</span>
|
||||
|
||||
<iqser-circle-button
|
||||
@ -57,33 +57,33 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [class.no-data]="screenStateService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'dictionary-listing.table-col-names.type' | translate"
|
||||
[withSort]="true"
|
||||
column="label"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'dictionary-listing.table-col-names.order-of-importance' | translate"
|
||||
[withSort]="true"
|
||||
class="flex-center"
|
||||
column="rank"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'dictionary-listing.table-col-names.hint-redaction' | translate"
|
||||
class="flex-center"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
<div></div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<redaction-empty-state
|
||||
(action)="openAddEditDictionaryDialog()"
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[buttonLabel]="'dictionary-listing.no-data.action' | translate"
|
||||
[showButton]="permissionsService.isAdmin()"
|
||||
[text]="'dictionary-listing.no-data.title' | translate"
|
||||
@ -156,7 +156,7 @@
|
||||
|
||||
<div class="right-container" redactionHasScrollbar>
|
||||
<redaction-simple-doughnut-chart
|
||||
*ngIf="(screenStateService.noData$ | async) === false"
|
||||
*ngIf="(entitiesService.noData$ | async) === false"
|
||||
[config]="chartData"
|
||||
[counterText]="'dictionary-listing.stats.charts.entries' | translate"
|
||||
[radius]="82"
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
iqser-table-column-name::ng-deep {
|
||||
> div {
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
|
||||
@ -9,13 +9,9 @@ import { ActivatedRoute } from '@angular/router';
|
||||
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
|
||||
const toChartConfig = (dict: TypeValueWrapper): DoughnutChartConfig => ({
|
||||
value: dict.entries?.length ?? 0,
|
||||
@ -27,7 +23,7 @@ const toChartConfig = (dict: TypeValueWrapper): DoughnutChartConfig => ({
|
||||
@Component({
|
||||
templateUrl: './dictionary-listing-screen.component.html',
|
||||
styleUrls: ['./dictionary-listing-screen.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class DictionaryListingScreenComponent extends BaseListingComponent<TypeValueWrapper> implements OnInit {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
@ -56,7 +52,7 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
|
||||
this._loadDictionaryData();
|
||||
}
|
||||
|
||||
openDeleteDictionariesDialog($event?: MouseEvent, types = this.screenStateService.selectedEntities) {
|
||||
openDeleteDictionariesDialog($event?: MouseEvent, types = this.entitiesService.selected) {
|
||||
this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
this._loadingService.start();
|
||||
await this._dictionaryControllerService
|
||||
@ -65,7 +61,7 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
|
||||
this._appStateService.activeDossierTemplateId
|
||||
)
|
||||
.toPromise();
|
||||
this.screenStateService.setSelectedEntities([]);
|
||||
this.entitiesService.setSelected([]);
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadDictionaryData(false);
|
||||
this._calculateData();
|
||||
@ -96,13 +92,13 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
|
||||
const entities = Object.values(appStateDictionaryData).filter(d => !d.virtual);
|
||||
|
||||
if (!loadEntries)
|
||||
this.screenStateService.setEntities(
|
||||
this.entitiesService.setEntities(
|
||||
entities.map(dict => {
|
||||
dict.entries = this.allEntities.find(d => d.type === dict.type)?.entries || [];
|
||||
return dict;
|
||||
})
|
||||
);
|
||||
else this.screenStateService.setEntities(entities);
|
||||
else this.entitiesService.setEntities(entities);
|
||||
|
||||
if (!loadEntries) return;
|
||||
|
||||
|
||||
@ -4,10 +4,7 @@
|
||||
<redaction-admin-side-nav type="settings"></redaction-admin-side-nav>
|
||||
|
||||
<div>
|
||||
<redaction-page-header
|
||||
[pageLabel]="'digital-signature' | translate"
|
||||
[showCloseButton]="permissionsService.isUser()"
|
||||
></redaction-page-header>
|
||||
<redaction-page-header [pageLabel]="'digital-signature' | translate" [showCloseButton]="currentUser.isUser"></redaction-page-header>
|
||||
|
||||
<div class="red-content-inner">
|
||||
<div class="content-container">
|
||||
|
||||
@ -2,12 +2,11 @@ import { Component, OnDestroy } from '@angular/core';
|
||||
import { DigitalSignature, DigitalSignatureControllerService } from '@redaction/red-ui-http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Toaster } from '@services/toaster.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { lastIndexOfEnd } from '@utils/functions';
|
||||
import { AutoUnsubscribeComponent } from '@iqser/common-ui';
|
||||
import { AutoUnsubscribeComponent, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { IconButtonTypes } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-digital-signature-screen',
|
||||
@ -16,6 +15,7 @@ import { IconButtonTypes } from '@iqser/common-ui';
|
||||
})
|
||||
export class DigitalSignatureScreenComponent extends AutoUnsubscribeComponent implements OnDestroy {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
digitalSignature: DigitalSignature;
|
||||
digitalSignatureForm: FormGroup;
|
||||
@ -23,11 +23,11 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribeComponent im
|
||||
digitalSignatureExists = false;
|
||||
|
||||
constructor(
|
||||
private readonly _digitalSignatureControllerService: DigitalSignatureControllerService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
readonly permissionsService: PermissionsService
|
||||
private readonly _digitalSignatureControllerService: DigitalSignatureControllerService
|
||||
) {
|
||||
super();
|
||||
this.loadDigitalSignatureAndInitializeForm();
|
||||
|
||||
@ -20,23 +20,22 @@
|
||||
<redaction-admin-side-nav type="dossierTemplates"></redaction-admin-side-nav>
|
||||
|
||||
<div class="content-container">
|
||||
<div *ngIf="(screenStateService.noData$ | async) === false" class="header-item">
|
||||
<div *ngIf="(entitiesService.noData$ | async) === false" class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="screenStateService.areAllEntitiesSelected$ | async"
|
||||
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'dossier-attributes-listing.table-header.title'
|
||||
| translate: { length: (screenStateService.displayedLength$ | async) }
|
||||
'dossier-attributes-listing.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) }
|
||||
}}
|
||||
</span>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteAttributeDialog($event)"
|
||||
*ngIf="permissionsService.isAdmin() && screenStateService.areSomeEntitiesSelected$ | async"
|
||||
*ngIf="permissionsService.isAdmin() && entitiesService.areSomeSelected$ | async"
|
||||
[tooltip]="'dossier-attributes-listing.bulk.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
@ -59,24 +58,24 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="(screenStateService.noData$ | async) === false" class="table-header" redactionSyncWidth="table-item">
|
||||
<div *ngIf="(entitiesService.noData$ | async) === false" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-attributes-listing.table-col-names.label' | translate"
|
||||
[withSort]="true"
|
||||
column="label"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-attributes-listing.table-col-names.placeholder' | translate"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-attributes-listing.table-col-names.type' | translate"
|
||||
[withSort]="true"
|
||||
column="type"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<div></div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
@ -84,7 +83,7 @@
|
||||
|
||||
<redaction-empty-state
|
||||
(action)="openAddEditAttributeDialog($event)"
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[buttonLabel]="'dossier-attributes-listing.no-data.action' | translate"
|
||||
[showButton]="permissionsService.isAdmin()"
|
||||
[text]="'dossier-attributes-listing.no-data.title' | translate"
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
padding: 0 24px 0 10px;
|
||||
}
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
iqser-table-column-name::ng-deep {
|
||||
> div {
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
|
||||
@ -1,23 +1,19 @@
|
||||
import { Component, Injector, OnInit } from '@angular/core';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { DossierAttributeConfig } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
|
||||
import { dossierAttributeTypesTranslations } from '../../translations/dossier-attribute-types-translations';
|
||||
import { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-attributes-listing-screen.component.html',
|
||||
styleUrls: ['./dossier-attributes-listing-screen.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class DossierAttributesListingScreenComponent extends BaseListingComponent<DossierAttributeConfig> implements OnInit {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
@ -45,7 +41,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
|
||||
openConfirmDeleteAttributeDialog($event: MouseEvent, dossierAttribute?: DossierAttributeConfig) {
|
||||
this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
this._loadingService.start();
|
||||
const ids = dossierAttribute ? [dossierAttribute.id] : this.screenStateService.selectedEntities.map(item => item.id);
|
||||
const ids = dossierAttribute ? [dossierAttribute.id] : this.entitiesService.selected.map(item => item.id);
|
||||
await this._dossierAttributesService.deleteConfigs(ids);
|
||||
await this._loadData();
|
||||
});
|
||||
@ -65,7 +61,7 @@ export class DossierAttributesListingScreenComponent extends BaseListingComponen
|
||||
private async _loadData() {
|
||||
this._loadingService.start();
|
||||
const attributes = await this._dossierAttributesService.getConfig();
|
||||
this.screenStateService.setEntities(attributes);
|
||||
this.entitiesService.setEntities(attributes);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,30 +4,27 @@
|
||||
<redaction-admin-side-nav type="settings"></redaction-admin-side-nav>
|
||||
|
||||
<div>
|
||||
<redaction-page-header
|
||||
[pageLabel]="'dossier-templates' | translate"
|
||||
[showCloseButton]="permissionsService.isUser()"
|
||||
></redaction-page-header>
|
||||
<redaction-page-header [pageLabel]="'dossier-templates' | translate" [showCloseButton]="currentUser.isUser"></redaction-page-header>
|
||||
|
||||
<div class="red-content-inner">
|
||||
<div class="content-container">
|
||||
<div class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="screenStateService.areAllEntitiesSelected$ | async"
|
||||
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'dossier-templates-listing.table-header.title'
|
||||
| translate: { length: (screenStateService.displayedLength$ | async) }
|
||||
| translate: { length: (entitiesService.displayedLength$ | async) }
|
||||
}}
|
||||
</span>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteTemplatesDialog($event)"
|
||||
*ngIf="canBulkDelete$(permissionsService.isAdmin()) | async"
|
||||
*ngIf="canBulkDelete$(currentUser.isAdmin) | async"
|
||||
[tooltip]="'dossier-templates-listing.bulk.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
@ -42,7 +39,7 @@
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="openAddDossierTemplateDialog()"
|
||||
*ngIf="permissionsService.isAdmin() && userPreferenceService.areDevFeaturesEnabled"
|
||||
*ngIf="currentUser.isAdmin && userPreferenceService.areDevFeaturesEnabled"
|
||||
[label]="'dossier-templates-listing.add-new' | translate"
|
||||
icon="red:plus"
|
||||
[type]="iconButtonTypes.primary"
|
||||
@ -50,34 +47,34 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [class.no-data]="screenStateService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-templates-listing.table-col-names.name' | translate"
|
||||
[withSort]="true"
|
||||
column="name"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-templates-listing.table-col-names.created-by' | translate"
|
||||
class="user-column"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-templates-listing.table-col-names.created-on' | translate"
|
||||
[withSort]="true"
|
||||
column="dateAdded"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-templates-listing.table-col-names.modified-on' | translate"
|
||||
[withSort]="true"
|
||||
column="dateModified"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[text]="'dossier-templates-listing.no-data.title' | translate"
|
||||
icon="red:template"
|
||||
></redaction-empty-state>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
padding: 0 24px 0 10px;
|
||||
}
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
iqser-table-column-name::ng-deep {
|
||||
> div {
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
|
||||
@ -1,37 +1,34 @@
|
||||
import { ChangeDetectionStrategy, 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 { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { DossierTemplateModelWrapper } from '@models/file/dossier-template-model.wrapper';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { DossierTemplateControllerService } from '@redaction/red-ui-http';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-templates-listing-screen.component.html',
|
||||
styleUrls: ['./dossier-templates-listing-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class DossierTemplatesListingScreenComponent extends BaseListingComponent<DossierTemplateModelWrapper> implements OnInit {
|
||||
protected readonly _primaryKey = 'name';
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
protected readonly _primaryKey = 'name';
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
constructor(
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossierTemplateControllerService: DossierTemplateControllerService,
|
||||
protected readonly _injector: Injector,
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly userPreferenceService: UserPreferenceService
|
||||
private readonly _userService: UserService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
readonly userPreferenceService: UserPreferenceService,
|
||||
private readonly _dossierTemplateControllerService: DossierTemplateControllerService
|
||||
) {
|
||||
super(_injector);
|
||||
}
|
||||
@ -44,9 +41,9 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
|
||||
return this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
this._loadingService.start();
|
||||
await this._dossierTemplateControllerService
|
||||
.deleteDossierTemplates(this.screenStateService.selectedEntities.map(d => d.dossierTemplateId))
|
||||
.deleteDossierTemplates(this.entitiesService.selected.map(d => d.dossierTemplateId))
|
||||
.toPromise();
|
||||
this.screenStateService.setSelectedEntities([]);
|
||||
this.entitiesService.setSelected([]);
|
||||
await this._appStateService.loadAllDossierTemplates();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this.loadDossierTemplatesData();
|
||||
@ -56,7 +53,7 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
|
||||
loadDossierTemplatesData() {
|
||||
this._loadingService.start();
|
||||
this._appStateService.reset();
|
||||
this.screenStateService.setEntities(this._appStateService.dossierTemplates);
|
||||
this.entitiesService.setEntities(this._appStateService.dossierTemplates);
|
||||
this._loadDossierTemplateStats();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
@ -70,7 +67,7 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
|
||||
}
|
||||
|
||||
private _loadDossierTemplateStats() {
|
||||
this.screenStateService.allEntities.forEach(rs => {
|
||||
this.entitiesService.all.forEach(rs => {
|
||||
const dictionaries = this._appStateService.dictionaryData[rs.dossierTemplateId];
|
||||
if (dictionaries) {
|
||||
rs.dictionariesCount = Object.keys(dictionaries)
|
||||
|
||||
@ -23,14 +23,12 @@
|
||||
<div class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="screenStateService.areAllEntitiesSelected$ | async"
|
||||
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'file-attributes-listing.table-header.title' | translate: { length: (screenStateService.displayedLength$ | async) }
|
||||
}}
|
||||
{{ 'file-attributes-listing.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
|
||||
</span>
|
||||
|
||||
<iqser-circle-button
|
||||
@ -68,38 +66,38 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [class.no-data]="screenStateService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'file-attributes-listing.table-col-names.name' | translate"
|
||||
[withSort]="true"
|
||||
column="label"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'file-attributes-listing.table-col-names.type' | translate"
|
||||
[withSort]="true"
|
||||
column="type"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'file-attributes-listing.table-col-names.read-only' | translate"
|
||||
[withSort]="true"
|
||||
class="flex-center"
|
||||
column="editable"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'file-attributes-listing.table-col-names.csv-column' | translate"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'file-attributes-listing.table-col-names.primary' | translate"
|
||||
[rightIconTooltip]="'file-attributes-listing.table-col-names.primary-info-tooltip' | translate"
|
||||
class="flex-center"
|
||||
rightIcon="red:status-info"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<div></div>
|
||||
|
||||
@ -107,7 +105,7 @@
|
||||
</div>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[text]="'file-attributes-listing.no-data.title' | translate"
|
||||
icon="red:attribute"
|
||||
></redaction-empty-state>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
padding: 0 24px 0 10px;
|
||||
}
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
iqser-table-column-name::ng-deep {
|
||||
> div {
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
|
||||
@ -5,19 +5,15 @@ import { AppStateService } from '@state/app-state.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { fileAttributeTypesTranslations } from '../../translations/file-attribute-types-translations';
|
||||
import { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { fileAttributeTypesTranslations } from '../../translations/file-attribute-types-translations';
|
||||
|
||||
@Component({
|
||||
templateUrl: './file-attributes-listing-screen.component.html',
|
||||
styleUrls: ['./file-attributes-listing-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class FileAttributesListingScreenComponent extends BaseListingComponent<FileAttributeConfig> implements OnInit, OnDestroy {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
@ -69,7 +65,7 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
||||
} else {
|
||||
await this._fileAttributesService
|
||||
.deleteFileAttributes(
|
||||
this.screenStateService.selectedEntities.map(f => f.id),
|
||||
this.entitiesService.selected.map(f => f.id),
|
||||
this._appStateService.activeDossierTemplateId
|
||||
)
|
||||
.toPromise();
|
||||
@ -102,7 +98,7 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent<F
|
||||
.getFileAttributesConfiguration(this._appStateService.activeDossierTemplateId)
|
||||
.toPromise();
|
||||
this._existingConfiguration = response;
|
||||
this.screenStateService.setEntities(response?.fileAttributeConfigs || []);
|
||||
this.entitiesService.setEntities(response?.fileAttributeConfigs || []);
|
||||
} catch (e) {}
|
||||
|
||||
this._loadingService.stop();
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
<div class="actions">
|
||||
<iqser-circle-button
|
||||
*ngIf="permissionsService.isUser()"
|
||||
*ngIf="currentUser.isUser"
|
||||
class="ml-6"
|
||||
icon="red:close"
|
||||
redactionNavigateLastDossiersScreen
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import {
|
||||
@ -9,11 +8,11 @@ import {
|
||||
SMTPConfigurationModel
|
||||
} from '@redaction/red-ui-http';
|
||||
import { AppConfigService } from '@app-config/app-config.service';
|
||||
import { AutoUnsubscribeComponent } from '@iqser/common-ui';
|
||||
import { AutoUnsubscribeComponent, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { Toaster } from '@services/toaster.service';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { IconButtonTypes } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-general-config-screen',
|
||||
@ -22,6 +21,8 @@ import { IconButtonTypes } from '@iqser/common-ui';
|
||||
})
|
||||
export class GeneralConfigScreenComponent extends AutoUnsubscribeComponent implements OnInit, OnDestroy {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
readonly configForm: FormGroup;
|
||||
readonly smtpForm: FormGroup;
|
||||
|
||||
@ -29,14 +30,14 @@ export class GeneralConfigScreenComponent extends AutoUnsubscribeComponent imple
|
||||
private _initialSMTPConfiguration: SMTPConfigurationModel;
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _smtpConfigService: SmtpConfigurationControllerService,
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _generalSettingsControllerService: GeneralSettingsControllerService,
|
||||
private readonly _loadingService: LoadingService
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _smtpConfigService: SmtpConfigurationControllerService,
|
||||
private readonly _generalSettingsControllerService: GeneralSettingsControllerService
|
||||
) {
|
||||
super();
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<redaction-page-header
|
||||
[buttonConfigs]="buttonConfigs"
|
||||
[pageLabel]="'license-information' | translate"
|
||||
[showCloseButton]="permissionsService.isUser()"
|
||||
[showCloseButton]="currentUser.isUser"
|
||||
></redaction-page-header>
|
||||
|
||||
<div class="red-content-inner">
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { LicenseReport, LicenseReportControllerService } from '@redaction/red-ui-http';
|
||||
import { AppConfigService } from '@app-config/app-config.service';
|
||||
import * as moment from 'moment';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
import { ButtonConfig } from '../../../shared/components/page-header/models/button-config.model';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { ButtonConfig } from '@shared/components/page-header/models/button-config.model';
|
||||
import { IconButtonTypes } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-license-information-screen',
|
||||
@ -15,6 +15,15 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
styleUrls: ['./license-information-screen.component.scss']
|
||||
})
|
||||
export class LicenseInformationScreenComponent implements OnInit {
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly buttonConfigs: ButtonConfig[] = [
|
||||
{
|
||||
label: _('license-info-screen.email-report'),
|
||||
action: () => this.sendMail(),
|
||||
type: IconButtonTypes.primary
|
||||
}
|
||||
];
|
||||
|
||||
currentInfo: LicenseReport = {};
|
||||
totalInfo: LicenseReport = {};
|
||||
unlicensedInfo: LicenseReport = {};
|
||||
@ -34,20 +43,13 @@ export class LicenseInformationScreenComponent implements OnInit {
|
||||
group: 'Ordinal',
|
||||
domain: ['#0389ec']
|
||||
};
|
||||
buttonConfigs: ButtonConfig[] = [
|
||||
{
|
||||
label: _('license-info-screen.email-report'),
|
||||
action: () => this.sendMail(),
|
||||
type: IconButtonTypes.primary
|
||||
}
|
||||
];
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _userService: UserService,
|
||||
readonly appConfigService: AppConfigService,
|
||||
private readonly _licenseReportController: LicenseReportControllerService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _loadingService: LoadingService
|
||||
private readonly _licenseReportController: LicenseReportControllerService
|
||||
) {
|
||||
_loadingService.start();
|
||||
}
|
||||
|
||||
@ -8,17 +8,17 @@
|
||||
<div class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="screenStateService.areAllEntitiesSelected$ | async"
|
||||
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{ 'trash.table-header.title' | translate: { length: (screenStateService.displayedLength$ | async) } }}
|
||||
{{ 'trash.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
|
||||
</span>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="bulkRestore()"
|
||||
*ngIf="screenStateService.areSomeEntitiesSelected$ | async"
|
||||
*ngIf="entitiesService.areSomeSelected$ | async"
|
||||
[tooltip]="'trash.bulk.restore' | translate"
|
||||
icon="red:put-back"
|
||||
[type]="circleButtonTypes.dark"
|
||||
@ -26,40 +26,37 @@
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="bulkDelete()"
|
||||
*ngIf="screenStateService.areSomeEntitiesSelected$ | async"
|
||||
*ngIf="entitiesService.areSomeSelected$ | async"
|
||||
[tooltip]="'trash.bulk.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
|
||||
<div [class.no-data]="screenStateService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'trash.table-col-names.name' | translate"
|
||||
[withSort]="true"
|
||||
column="dossierName"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
[label]="'trash.table-col-names.owner' | translate"
|
||||
class="user-column"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name [label]="'trash.table-col-names.owner' | translate" class="user-column"></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'trash.table-col-names.deleted-on' | translate"
|
||||
[withSort]="true"
|
||||
column="softDeletedTime"
|
||||
></redaction-table-col-name>
|
||||
<redaction-table-col-name
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'trash.table-col-names.time-to-restore' | translate"
|
||||
[withSort]="true"
|
||||
column="softDeletedTime"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[text]="'trash.no-data.title' | translate"
|
||||
icon="red:template"
|
||||
></redaction-empty-state>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
iqser-table-column-name::ng-deep {
|
||||
> div {
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
|
||||
@ -4,15 +4,11 @@ import { Dossier } from '@redaction/red-ui-http';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||
import * as moment from 'moment';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { DossiersService } from '../../../dossier/services/dossiers.service';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { DossiersService } from '../../../dossier/services/dossiers.service';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { ConfirmationDialogInput, TitleColors } from '../../../shared/dialogs/confirmation-dialog/confirmation-dialog.component';
|
||||
import { ConfirmationDialogInput, TitleColors } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
const HOURS_IN_A_DAY = 24;
|
||||
@ -22,12 +18,12 @@ const MINUTES_IN_AN_HOUR = 60;
|
||||
templateUrl: './trash-screen.component.html',
|
||||
styleUrls: ['./trash-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService, DossiersService]
|
||||
providers: [...DefaultListingServices, DossiersService]
|
||||
})
|
||||
export class TrashScreenComponent extends BaseListingComponent<Dossier> implements OnInit {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly itemSize = 80;
|
||||
protected readonly _primaryKey = 'dossierName';
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
private readonly _deleteRetentionHours = this._appConfigService.getConfig(AppConfigKey.DELETE_RETENTION_HOURS);
|
||||
|
||||
constructor(
|
||||
@ -50,7 +46,7 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
|
||||
}
|
||||
|
||||
async loadDossierTemplatesData(): Promise<void> {
|
||||
this.screenStateService.setEntities(await this._dossiersService.getDeleted());
|
||||
this.entitiesService.setEntities(await this._dossiersService.getDeleted());
|
||||
}
|
||||
|
||||
canRestore(softDeletedTime: string): boolean {
|
||||
@ -70,11 +66,11 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
|
||||
return moment(softDeletedTime).add(this._deleteRetentionHours, 'hours').toISOString();
|
||||
}
|
||||
|
||||
bulkDelete(dossiers = this.screenStateService.selectedEntities) {
|
||||
bulkDelete(dossiers = this.entitiesService.selected) {
|
||||
this._loadingService.loadWhile(this._hardDelete(dossiers));
|
||||
}
|
||||
|
||||
bulkRestore(dossierIds = this.screenStateService.selectedEntities.map(d => d.dossierId)) {
|
||||
bulkRestore(dossierIds = this.entitiesService.selected.map(d => d.dossierId)) {
|
||||
this._loadingService.loadWhile(this._restore(dossierIds));
|
||||
}
|
||||
|
||||
@ -107,8 +103,8 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
|
||||
}
|
||||
|
||||
private _removeFromList(ids: string[]): void {
|
||||
const entities = this.screenStateService.allEntities.filter(e => !ids.includes(e.dossierId));
|
||||
this.screenStateService.setEntities(entities);
|
||||
this.screenStateService.setSelectedEntities([]);
|
||||
const entities = this.entitiesService.all.filter(e => !ids.includes(e.dossierId));
|
||||
this.entitiesService.setEntities(entities);
|
||||
this.entitiesService.setSelected([]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,13 +15,13 @@
|
||||
></redaction-input-with-action>
|
||||
<iqser-icon-button
|
||||
(action)="openAddEditUserDialog($event)"
|
||||
*ngIf="permissionsService.isUserAdmin()"
|
||||
*ngIf="currentUser.isUserAdmin"
|
||||
[label]="'user-listing.add-new' | translate"
|
||||
icon="red:plus"
|
||||
[type]="iconButtonTypes.primary"
|
||||
></iqser-icon-button>
|
||||
<iqser-circle-button
|
||||
*ngIf="permissionsService.isUser()"
|
||||
*ngIf="currentUser.isUser"
|
||||
[tooltip]="'common.close' | translate"
|
||||
class="ml-6"
|
||||
icon="red:close"
|
||||
@ -36,17 +36,17 @@
|
||||
<div class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="screenStateService.areAllEntitiesSelected$ | async"
|
||||
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{ 'user-listing.table-header.title' | translate: { length: (screenStateService.displayedLength$ | async) } }}
|
||||
{{ 'user-listing.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
|
||||
</span>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="bulkDelete()"
|
||||
*ngIf="screenStateService.areSomeEntitiesSelected$ | async"
|
||||
*ngIf="entitiesService.areSomeSelected$ | async"
|
||||
[disabled]="(canDeleteSelected$ | async) === false"
|
||||
[tooltip]="
|
||||
(canDeleteSelected$ | async)
|
||||
@ -62,16 +62,16 @@
|
||||
<div class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name [label]="'user-listing.table-col-names.name' | translate"></redaction-table-col-name>
|
||||
<iqser-table-column-name [label]="'user-listing.table-col-names.name' | translate"></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name [label]="'user-listing.table-col-names.email' | translate"></redaction-table-col-name>
|
||||
<iqser-table-column-name [label]="'user-listing.table-col-names.email' | translate"></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
<iqser-table-column-name
|
||||
[label]="'user-listing.table-col-names.active' | translate"
|
||||
class="flex-center"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<redaction-table-col-name [label]="'user-listing.table-col-names.roles' | translate"></redaction-table-col-name>
|
||||
<iqser-table-column-name [label]="'user-listing.table-col-names.roles' | translate"></iqser-table-column-name>
|
||||
|
||||
<div></div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
@ -87,17 +87,13 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<redaction-initials-avatar
|
||||
[showYou]="true"
|
||||
[userId]="user.userId"
|
||||
[withName]="true"
|
||||
></redaction-initials-avatar>
|
||||
<redaction-initials-avatar [showYou]="true" [userId]="user.id" [withName]="true"></redaction-initials-avatar>
|
||||
</div>
|
||||
<div class="small-label">{{ user.email || '-' }}</div>
|
||||
<div class="center">
|
||||
<mat-slide-toggle
|
||||
(toggleChange)="toggleActive(user)"
|
||||
[checked]="userService.isActive(user)"
|
||||
[checked]="user.isActive"
|
||||
color="primary"
|
||||
></mat-slide-toggle>
|
||||
</div>
|
||||
@ -112,7 +108,7 @@
|
||||
></iqser-circle-button>
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteUsersDialog([user], $event)"
|
||||
[disabled]="user.userId === userService.userId"
|
||||
[disabled]="user.id === userService.currentUser.id"
|
||||
[tooltip]="'user-listing.action.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
padding: 0 24px 0 10px;
|
||||
}
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
iqser-table-column-name::ng-deep {
|
||||
> div {
|
||||
padding: 0 13px 0 10px !important;
|
||||
}
|
||||
|
||||
@ -1,55 +1,51 @@
|
||||
import { Component, Injector, OnInit, QueryList, ViewChildren } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { UserService, UserWrapper } from '@services/user.service';
|
||||
import { 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 { LoadingService } from '@services/loading.service';
|
||||
import { InitialsAvatarComponent } from '@shared/components/initials-avatar/initials-avatar.component';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { rolesTranslations } from '../../../../translations/roles-translations';
|
||||
import { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
templateUrl: './user-listing-screen.component.html',
|
||||
styleUrls: ['./user-listing-screen.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class UserListingScreenComponent extends BaseListingComponent<User> implements OnInit {
|
||||
export class UserListingScreenComponent extends BaseListingComponent<UserWrapper> implements OnInit {
|
||||
protected readonly _primaryKey = 'id';
|
||||
readonly translations = rolesTranslations;
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this.userService.currentUser;
|
||||
readonly canDeleteSelected$ = this._canDeleteSelected$;
|
||||
|
||||
collapsedDetails = false;
|
||||
chartData: DoughnutChartConfig[] = [];
|
||||
readonly translations = rolesTranslations;
|
||||
protected readonly _primaryKey = 'userId';
|
||||
@ViewChildren(InitialsAvatarComponent)
|
||||
private readonly _avatars: QueryList<InitialsAvatarComponent>;
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly userService: UserService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _userControllerService: UserControllerService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _loadingService: LoadingService,
|
||||
protected readonly _injector: Injector
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _userControllerService: UserControllerService,
|
||||
private readonly _translateChartService: TranslateChartService
|
||||
) {
|
||||
super(_injector);
|
||||
}
|
||||
|
||||
get _canDeleteSelected$(): Observable<boolean> {
|
||||
const entities$ = this.screenStateService.selectedEntities$;
|
||||
return entities$.pipe(map(all => all.indexOf(this.userService.user) === -1));
|
||||
const entities$ = this.entitiesService.selected$;
|
||||
return entities$.pipe(map(all => all.indexOf(this.currentUser) === -1));
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -57,19 +53,19 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
this.searchService.setSearchKey('searchKey');
|
||||
}
|
||||
|
||||
openAddEditUserDialog($event: MouseEvent, user?: User) {
|
||||
openAddEditUserDialog($event: MouseEvent, user?: UserWrapper) {
|
||||
this._dialogService.openDialog('addEditUser', $event, user, async () => {
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
|
||||
openDeleteUsersDialog(users: User[], $event?: MouseEvent) {
|
||||
openDeleteUsersDialog(users: UserWrapper[], $event?: MouseEvent) {
|
||||
this._dialogService.openDialog('deleteUsers', $event, users, async () => {
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
|
||||
getDisplayRoles(user: User) {
|
||||
getDisplayRoles(user: UserWrapper) {
|
||||
const separator = ', ';
|
||||
return (
|
||||
user.roles.map(role => this._translateService.instant(this.translations[role])).join(separator) ||
|
||||
@ -77,20 +73,20 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
);
|
||||
}
|
||||
|
||||
async toggleActive(user: User) {
|
||||
async toggleActive(user: UserWrapper) {
|
||||
this._loadingService.start();
|
||||
user.roles = this.userService.isActive(user) ? [] : ['RED_USER'];
|
||||
await this._userControllerService.updateProfile(user, user.userId).toPromise();
|
||||
user.roles = user.isActive ? [] : ['RED_USER'];
|
||||
await this._userControllerService.updateProfile(user, user.id).toPromise();
|
||||
await this._loadData();
|
||||
this._avatars.find(item => item.userId === user.userId).detectChanges();
|
||||
this._avatars.find(item => item.userId === user.id).detectChanges();
|
||||
}
|
||||
|
||||
bulkDelete() {
|
||||
this.openDeleteUsersDialog(this.screenStateService.allEntities.filter(u => this.isSelected(u)));
|
||||
this.openDeleteUsersDialog(this.entitiesService.all.filter(u => this.isSelected(u)));
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
this.screenStateService.setEntities(await this.userService.loadAllUsers());
|
||||
this.entitiesService.setEntities(await this.userService.loadAllUsers());
|
||||
await this.userService.loadAllUsers();
|
||||
this._computeStats();
|
||||
this._loadingService.stop();
|
||||
@ -100,7 +96,7 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
this.chartData = this._translateChartService.translateRoles(
|
||||
[
|
||||
{
|
||||
value: this.allEntities.filter(user => !this.userService.isActive(user)).length,
|
||||
value: this.allEntities.filter(user => !user.isActive).length,
|
||||
color: 'INACTIVE',
|
||||
label: 'INACTIVE'
|
||||
},
|
||||
@ -110,22 +106,22 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
label: 'REGULAR'
|
||||
},
|
||||
{
|
||||
value: this.allEntities.filter(user => this.userService.isManager(user) && !this.userService.isAdmin(user)).length,
|
||||
value: this.allEntities.filter(user => user.isManager && !user.isAdmin).length,
|
||||
color: 'MANAGER',
|
||||
label: 'RED_MANAGER'
|
||||
},
|
||||
{
|
||||
value: this.allEntities.filter(user => this.userService.isManager(user) && this.userService.isAdmin(user)).length,
|
||||
value: this.allEntities.filter(user => user.isManager && user.isAdmin).length,
|
||||
color: 'MANAGER_ADMIN',
|
||||
label: 'MANAGER_ADMIN'
|
||||
},
|
||||
{
|
||||
value: this.allEntities.filter(user => this.userService.isUserAdmin(user) && !this.userService.isAdmin(user)).length,
|
||||
value: this.allEntities.filter(user => user.isUserAdmin && !user.isAdmin).length,
|
||||
color: 'USER_ADMIN',
|
||||
label: 'RED_USER_ADMIN'
|
||||
},
|
||||
{
|
||||
value: this.allEntities.filter(user => this.userService.isAdmin(user) && !this.userService.isManager(user)).length,
|
||||
value: this.allEntities.filter(user => user.isAdmin && !user.isManager).length,
|
||||
color: 'ADMIN',
|
||||
label: 'RED_ADMIN'
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ export class RedRoleGuard implements CanActivate {
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
|
||||
return new Observable(obs => {
|
||||
if (!this._userService.user.hasAnyREDRoles) {
|
||||
if (!this._userService.currentUser.hasAnyREDRoles) {
|
||||
this._router.navigate(['/auth-error']);
|
||||
this._loadingService.stop();
|
||||
obs.next(false);
|
||||
@ -26,8 +26,8 @@ export class RedRoleGuard implements CanActivate {
|
||||
// we have at least 1 RED Role -> if it's not user he must be admin
|
||||
|
||||
if (
|
||||
this._userService.user.isUserAdmin &&
|
||||
!this._userService.user.isAdmin &&
|
||||
this._userService.currentUser.isUserAdmin &&
|
||||
!this._userService.currentUser.isAdmin &&
|
||||
!(state.url.startsWith('/main/admin/users') || state.url.startsWith('/main/my-profile'))
|
||||
) {
|
||||
this._router.navigate(['/main/admin/users']);
|
||||
@ -36,7 +36,7 @@ export class RedRoleGuard implements CanActivate {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._userService.isUser() && state.url.startsWith('/main/dossiers')) {
|
||||
if (!this._userService.currentUser.isUser && state.url.startsWith('/main/dossiers')) {
|
||||
this._router.navigate(['/main/admin']);
|
||||
obs.next(false);
|
||||
obs.complete();
|
||||
|
||||
@ -5,6 +5,7 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||
import { AnnotationActionsService } from '../../services/annotation-actions.service';
|
||||
import { WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
export const AnnotationButtonTypes = {
|
||||
dark: 'dark',
|
||||
@ -28,9 +29,10 @@ export class AnnotationActionsComponent implements OnInit {
|
||||
annotationPermissions: AnnotationPermissions;
|
||||
|
||||
constructor(
|
||||
public appStateService: AppStateService,
|
||||
public annotationActionsService: AnnotationActionsService,
|
||||
private _permissionsService: PermissionsService
|
||||
readonly appStateService: AppStateService,
|
||||
readonly annotationActionsService: AnnotationActionsService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _userService: UserService
|
||||
) {}
|
||||
|
||||
private _annotations: AnnotationWrapper[];
|
||||
@ -89,7 +91,7 @@ export class AnnotationActionsComponent implements OnInit {
|
||||
private _setPermissions() {
|
||||
this.annotationPermissions = AnnotationPermissions.forUser(
|
||||
this._permissionsService.isApprover(),
|
||||
this._permissionsService.currentUser,
|
||||
this._userService.currentUser,
|
||||
this.annotations
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,10 +8,9 @@ import { from, Observable } from 'rxjs';
|
||||
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { CircleButtonTypes, EntitiesService } from '@iqser/common-ui';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-overview-bulk-actions',
|
||||
@ -33,7 +32,7 @@ export class DossierOverviewBulkActionsComponent {
|
||||
private readonly _fileActionService: FileActionService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _screenStateService: ScreenStateService<FileStatusWrapper>
|
||||
private readonly _entitiesService: EntitiesService<FileStatusWrapper>
|
||||
) {}
|
||||
|
||||
get dossier() {
|
||||
@ -41,7 +40,7 @@ export class DossierOverviewBulkActionsComponent {
|
||||
}
|
||||
|
||||
get selectedFiles(): FileStatusWrapper[] {
|
||||
return this._screenStateService.selectedEntities;
|
||||
return this._entitiesService.selected;
|
||||
}
|
||||
|
||||
get areAllFilesSelected() {
|
||||
@ -146,7 +145,7 @@ export class DossierOverviewBulkActionsComponent {
|
||||
.toPromise();
|
||||
await this._appStateService.reloadActiveDossierFiles();
|
||||
this.reload.emit();
|
||||
this._screenStateService.setSelectedEntities([]);
|
||||
this._entitiesService.setSelected([]);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
);
|
||||
|
||||
@ -39,7 +39,7 @@ export class CommentsComponent {
|
||||
this.annotation.comments.push({
|
||||
text: value,
|
||||
id: commentResponse.commentId,
|
||||
user: this._userService.userId
|
||||
user: this._userService.currentUser.id
|
||||
});
|
||||
});
|
||||
this.commentForm.reset();
|
||||
|
||||
@ -15,11 +15,11 @@
|
||||
<div class="all-caps-label" translate="dossier-details.owner"></div>
|
||||
<div class="mt-12 d-flex">
|
||||
<ng-container *ngIf="!editingOwner; else editOwner">
|
||||
<redaction-initials-avatar [userId]="owner?.userId" [withName]="true" color="gray" size="large"></redaction-initials-avatar>
|
||||
<redaction-initials-avatar [userId]="owner?.id" [withName]="true" color="gray" size="large"></redaction-initials-avatar>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="editingOwner = true"
|
||||
*ngIf="permissionsService.isManager()"
|
||||
*ngIf="currentUser.isManager"
|
||||
[tooltip]="'dossier-details.edit-owner' | translate"
|
||||
class="ml-14"
|
||||
icon="red:edit"
|
||||
|
||||
@ -2,11 +2,9 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } fro
|
||||
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 { PermissionsService } from '@services/permissions.service';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { StatusSorter } from '@utils/sorters/status-sorter';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { UserService, UserWrapper } from '@services/user.service';
|
||||
import { Toaster } from '@services/toaster.service';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
|
||||
@ -20,7 +18,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
})
|
||||
export class DossierDetailsComponent implements OnInit {
|
||||
documentsChartData: DoughnutChartConfig[] = [];
|
||||
owner: User;
|
||||
owner: UserWrapper;
|
||||
editingOwner = false;
|
||||
@Input() dossierAttributes: DossierAttributeWithValue[];
|
||||
@Output() openAssignDossierMembersDialog = new EventEmitter();
|
||||
@ -30,11 +28,11 @@ export class DossierDetailsComponent implements OnInit {
|
||||
expandTooltip = _('dossier-details.expand');
|
||||
|
||||
readonly needsWorkFilters$ = this.filterService.getFilterModels$('needsWorkFilters');
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
constructor(
|
||||
readonly appStateService: AppStateService,
|
||||
readonly translateChartService: TranslateChartService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly filterService: FilterService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _userService: UserService,
|
||||
@ -81,13 +79,13 @@ export class DossierDetailsComponent implements OnInit {
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
async assignOwner(user: User | string) {
|
||||
async assignOwner(user: UserWrapper | string) {
|
||||
this.owner = typeof user === 'string' ? this._userService.getRedUserById(user) : user;
|
||||
const dw = Object.assign({}, this.appStateService.activeDossier);
|
||||
dw.dossier.ownerId = this.owner.userId;
|
||||
dw.dossier.ownerId = this.owner.id;
|
||||
await this.appStateService.createOrUpdateDossier(dw.dossier);
|
||||
|
||||
const ownerName = this._userService.getNameForId(this.owner.userId);
|
||||
const ownerName = this._userService.getNameForId(this.owner.id);
|
||||
const dossierName = this.appStateService.activeDossier.name;
|
||||
const msg = 'Successfully assigned ' + ownerName + ' to dossier: ' + dossierName;
|
||||
this._toaster.info(msg);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<redaction-status-bar [config]="getDossierStatusConfig(dossier)"></redaction-status-bar>
|
||||
<div [class.active]="actionMenuOpen" class="action-buttons">
|
||||
<div class="action-buttons">
|
||||
<iqser-circle-button
|
||||
(action)="openEditDossierDialog($event, dossier)"
|
||||
*ngIf="permissionsService.isManager()"
|
||||
*ngIf="currentUser.isManager"
|
||||
[tooltip]="'dossier-listing.edit.action' | translate"
|
||||
icon="red:edit"
|
||||
[type]="circleButtonTypes.dark"
|
||||
|
||||
@ -5,6 +5,7 @@ import { StatusSorter } from '@utils/sorters/status-sorter';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-listing-actions',
|
||||
@ -13,15 +14,16 @@ import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
})
|
||||
export class DossierListingActionsComponent {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
@Input() dossier: DossierWrapper;
|
||||
@Output() actionPerformed = new EventEmitter<DossierWrapper | undefined>();
|
||||
actionMenuOpen = false;
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly appStateService: AppStateService,
|
||||
private readonly _dialogService: DossiersDialogService
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _userService: UserService
|
||||
) {}
|
||||
|
||||
openEditDossierDialog($event: MouseEvent, dossierWrapper: DossierWrapper) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div *ngIf="screen === 'dossier-overview'" [class.active]="actionMenuOpen" class="action-buttons">
|
||||
<div *ngIf="screen === 'dossier-overview'" class="action-buttons">
|
||||
<ng-container *ngTemplateOutlet="actions"></ng-container>
|
||||
<redaction-status-bar *ngIf="fileStatus?.isWorkable" [config]="statusBarConfig"></redaction-status-bar>
|
||||
</div>
|
||||
|
||||
@ -10,6 +10,7 @@ import { FileManagementControllerService } from '@redaction/red-ui-http';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-actions',
|
||||
@ -18,12 +19,12 @@ import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
})
|
||||
export class FileActionsComponent implements OnInit {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
@Input() fileStatus: FileStatusWrapper;
|
||||
@Input() activeDocumentInfo: boolean;
|
||||
@Input() activeExcludePages: boolean;
|
||||
@Output() actionPerformed = new EventEmitter<string>();
|
||||
actionMenuOpen: boolean;
|
||||
|
||||
screen: 'file-preview' | 'dossier-overview';
|
||||
|
||||
@ -34,7 +35,8 @@ export class FileActionsComponent implements OnInit {
|
||||
private readonly _fileActionService: FileActionService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _fileManagementControllerService: FileManagementControllerService,
|
||||
private readonly _translateService: TranslateService
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _userService: UserService
|
||||
) {}
|
||||
|
||||
get statusBarConfig() {
|
||||
@ -50,7 +52,7 @@ export class FileActionsComponent implements OnInit {
|
||||
}
|
||||
|
||||
get toggleTooltip(): string {
|
||||
if (!this.permissionsService.isManager()) {
|
||||
if (!this.currentUser.isManager) {
|
||||
return _('file-preview.toggle-analysis.only-managers');
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<button (click)="scroll(buttonType.top)" [hidden]="!showScroll(buttonType.top)" class="scroll-button top pointer">
|
||||
<button (click)="scroll(buttonType.top)" [hidden]="(showScrollUp$ | async) === false" class="scroll-button top pointer">
|
||||
<mat-icon svgIcon="red:arrow-down-o"></mat-icon>
|
||||
</button>
|
||||
|
||||
<button (click)="scroll(buttonType.bottom)" [hidden]="!showScroll(buttonType.bottom)" class="scroll-button bottom pointer">
|
||||
<button (click)="scroll(buttonType.bottom)" [hidden]="(showScrollDown$ | async) === false" class="scroll-button bottom pointer">
|
||||
<mat-icon svgIcon="red:arrow-down-o"></mat-icon>
|
||||
</button>
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { Component, HostListener, Input } from '@angular/core';
|
||||
import { Component, HostListener, Input, OnInit } from '@angular/core';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { concatMap, delay, distinctUntilChanged, map, startWith } from 'rxjs/operators';
|
||||
import { Observable, of } from 'rxjs';
|
||||
|
||||
const ButtonTypes = {
|
||||
top: 'top',
|
||||
@ -13,28 +15,40 @@ type ButtonType = keyof typeof ButtonTypes;
|
||||
templateUrl: './scroll-button.component.html',
|
||||
styleUrls: ['./scroll-button.component.scss']
|
||||
})
|
||||
export class ScrollButtonComponent {
|
||||
buttonType = ButtonTypes;
|
||||
export class ScrollButtonComponent implements OnInit {
|
||||
readonly buttonType = ButtonTypes;
|
||||
|
||||
@Input()
|
||||
scrollViewport: CdkVirtualScrollViewport;
|
||||
@Input()
|
||||
itemSize: number;
|
||||
|
||||
showScrollUp$: Observable<boolean>;
|
||||
showScrollDown$: Observable<boolean>;
|
||||
|
||||
ngOnInit() {
|
||||
const scrollSize = () => this.scrollViewport.getDataLength() * this.itemSize;
|
||||
const scrollIsNeeded = () => this.scrollViewport.getViewportSize() < scrollSize();
|
||||
const reachedEnd = (type: ButtonType) => this.scrollViewport.measureScrollOffset(type) === 0;
|
||||
|
||||
const showScrollUp = () => scrollIsNeeded() && !reachedEnd(ButtonTypes.top);
|
||||
const showScrollDown = () => scrollIsNeeded() && !reachedEnd(ButtonTypes.bottom);
|
||||
|
||||
const scroll$ = this.scrollViewport.elementScrolled().pipe(
|
||||
startWith(''),
|
||||
/** Delay first value so that we can wait for items to be rendered in viewport and get correct values */
|
||||
concatMap((value, index) => (index === 0 ? of(value).pipe(delay(0)) : of(value)))
|
||||
);
|
||||
this.showScrollUp$ = scroll$.pipe(map(showScrollUp), distinctUntilChanged());
|
||||
this.showScrollDown$ = scroll$.pipe(map(showScrollDown), distinctUntilChanged());
|
||||
}
|
||||
|
||||
scroll(type: ButtonType): void {
|
||||
const viewportSize = (this.scrollViewport?.getViewportSize() - this.itemSize) * (type === ButtonTypes.top ? -1 : 1);
|
||||
const scrollOffset = this.scrollViewport?.measureScrollOffset('top');
|
||||
this.scrollViewport?.scrollToOffset(scrollOffset + viewportSize, 'smooth');
|
||||
}
|
||||
|
||||
showScroll(type: ButtonType): boolean {
|
||||
const reachedEnd = this.scrollViewport?.measureScrollOffset(type) === 0;
|
||||
const scrollSize = this.scrollViewport?.getDataLength() * this.itemSize;
|
||||
const scrollIsNeeded = this.scrollViewport?.getViewportSize() < scrollSize;
|
||||
|
||||
return scrollIsNeeded && !reachedEnd;
|
||||
}
|
||||
|
||||
@HostListener('document:keyup', ['$event'])
|
||||
spaceAndPageDownScroll(event: KeyboardEvent): void {
|
||||
if (['Space', 'PageDown'].includes(event.code) && (event.target as any).tagName === 'BODY') {
|
||||
|
||||
@ -43,15 +43,15 @@ export class TeamMembersManagerComponent implements OnInit {
|
||||
}
|
||||
|
||||
get ownersSelectOptions() {
|
||||
return this.userService.managerUsers.map(m => m.userId);
|
||||
return this.userService.managerUsers.map(m => m.id);
|
||||
}
|
||||
|
||||
get membersSelectOptions() {
|
||||
const searchQuery = this.searchForm.get('query').value;
|
||||
return this.userService.eligibleUsers
|
||||
.filter(user => this.userService.getNameForId(user.userId).toLowerCase().includes(searchQuery.toLowerCase()))
|
||||
.filter(user => this.selectedOwnerId !== user.userId)
|
||||
.map(user => user.userId);
|
||||
.filter(user => this.userService.getNameForId(user.id).toLowerCase().includes(searchQuery.toLowerCase()))
|
||||
.filter(user => this.selectedOwnerId !== user.id)
|
||||
.map(user => user.id);
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
</div>
|
||||
<iqser-circle-button
|
||||
(action)="openAssignDossierMembersDialog.emit()"
|
||||
*ngIf="permissionsService.isManager() && canAdd"
|
||||
*ngIf="currentUser.isManager && canAdd"
|
||||
[class.large-spacing]="largeSpacing"
|
||||
[size]="32"
|
||||
[tooltip]="'dossier-details.assign-members' | translate"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-team-members',
|
||||
@ -9,6 +9,7 @@ import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
})
|
||||
export class TeamMembersComponent {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
@Input() memberIds: string[];
|
||||
@Input() perLine: number;
|
||||
@ -23,7 +24,7 @@ export class TeamMembersComponent {
|
||||
|
||||
expandedTeam = false;
|
||||
|
||||
constructor(public permissionsService: PermissionsService) {}
|
||||
constructor(private readonly _userService: UserService) {}
|
||||
|
||||
get maxTeamMembersBeforeExpand(): number {
|
||||
return this.perLine - (this.canAdd ? 1 : 0);
|
||||
|
||||
@ -103,7 +103,7 @@ export class AssignReviewerApproverDialogComponent {
|
||||
uniqueReviewers.add(file.currentReviewer);
|
||||
}
|
||||
}
|
||||
let singleUser = uniqueReviewers.size === 1 ? uniqueReviewers.values().next().value : this.userService.userId;
|
||||
let singleUser = uniqueReviewers.size === 1 ? uniqueReviewers.values().next().value : this.userService.currentUser.id;
|
||||
|
||||
singleUser = this.singleUsersSelectOptions.indexOf(singleUser) >= 0 ? singleUser : this.singleUsersSelectOptions[0];
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||
import { AppStateService } from '../../../../../state/app-state.service';
|
||||
import { DossierWrapper } from '../../../../../state/model/dossier.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { TeamMembersManagerComponent } from '../../../components/team-members-manager/team-members-manager.component';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-team-members',
|
||||
@ -11,19 +11,21 @@ import { TeamMembersManagerComponent } from '../../../components/team-members-ma
|
||||
styleUrls: ['./edit-dossier-team-members.component.scss']
|
||||
})
|
||||
export class EditDossierTeamMembersComponent implements EditDossierSectionInterface {
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
@Input() dossierWrapper: DossierWrapper;
|
||||
@Output() updateDossier = new EventEmitter<any>();
|
||||
|
||||
@ViewChild(TeamMembersManagerComponent) managerComponent: TeamMembersManagerComponent;
|
||||
|
||||
constructor(private readonly _appStateService: AppStateService, private readonly _permissionsService: PermissionsService) {}
|
||||
constructor(private readonly _appStateService: AppStateService, private readonly _userService: UserService) {}
|
||||
|
||||
get changed() {
|
||||
return this.managerComponent.changed;
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return !this._permissionsService.isManager();
|
||||
return !this.currentUser.isManager;
|
||||
}
|
||||
|
||||
async save() {
|
||||
|
||||
@ -2,9 +2,9 @@ import { Component, Inject } from '@angular/core';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { humanize } from '../../../../utils/functions';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { humanize } from '@iqser/common-ui';
|
||||
|
||||
export interface RemoveAnnotationsDialogInput {
|
||||
annotationsToRemove: AnnotationWrapper[];
|
||||
|
||||
@ -8,20 +8,23 @@
|
||||
|
||||
<div class="red-content-inner">
|
||||
<div class="content-container">
|
||||
<redaction-table-header [tableColConfigs]="tableColConfigs" [tableHeaderLabel]="tableHeaderLabel"></redaction-table-header>
|
||||
<redaction-table-header
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
[tableHeaderLabel]="tableHeaderLabel"
|
||||
></redaction-table-header>
|
||||
|
||||
<redaction-empty-state
|
||||
(action)="openAddDossierDialog()"
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[buttonLabel]="'dossier-listing.no-data.action' | translate"
|
||||
[showButton]="permissionsService.isManager()"
|
||||
[showButton]="currentUser.isManager"
|
||||
[text]="'dossier-listing.no-data.title' | translate"
|
||||
icon="red:folder"
|
||||
></redaction-empty-state>
|
||||
|
||||
<redaction-empty-state *ngIf="noMatch$ | async" [text]="'dossier-listing.no-match.title' | translate"></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<cdk-virtual-scroll-viewport #scrollViewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="let dw of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
[class.pointer]="!!dw"
|
||||
@ -82,7 +85,7 @@
|
||||
|
||||
<div class="right-container" redactionHasScrollbar>
|
||||
<redaction-dossier-listing-details
|
||||
*ngIf="(screenStateService.noData$ | async) === false"
|
||||
*ngIf="(entitiesService.noData$ | async) === false"
|
||||
[documentsChartData]="documentsChartData"
|
||||
[dossiersChartData]="dossiersChartData"
|
||||
></redaction-dossier-listing-details>
|
||||
|
||||
@ -16,12 +16,8 @@ import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { ButtonConfig } from '@shared/components/page-header/models/button-config.model';
|
||||
import { FilterService, NestedFilter } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { TableColConfig } from '@shared/components/table-col-name/table-col-name.component';
|
||||
import { NestedFilter, TableColumnConfig } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { workloadTranslations } from '../../translations/workload-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
@ -31,29 +27,34 @@ import {
|
||||
dossierStatusChecker,
|
||||
dossierTemplateChecker
|
||||
} from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
|
||||
const isLeavingScreen = event => event instanceof NavigationStart && event.url !== '/main/dossiers';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-listing-screen.component.html',
|
||||
styleUrls: ['./dossier-listing-screen.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class DossierListingScreenComponent
|
||||
extends BaseListingComponent<DossierWrapper>
|
||||
implements OnInit, AfterViewInit, OnDestroy, OnAttach, OnDetach
|
||||
{
|
||||
readonly itemSize = 95;
|
||||
buttonConfigs: ButtonConfig[] = [
|
||||
protected readonly _primaryKey = 'dossierName';
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableHeaderLabel = _('dossier-listing.table-header.title');
|
||||
readonly buttonConfigs: ButtonConfig[] = [
|
||||
{
|
||||
label: _('dossier-listing.add-new'),
|
||||
action: () => this.openAddDossierDialog(),
|
||||
hide: !this.permissionsService.isManager(),
|
||||
hide: !this.currentUser.isManager,
|
||||
icon: 'red:plus',
|
||||
type: 'primary'
|
||||
}
|
||||
];
|
||||
tableColConfigs: TableColConfig[] = [
|
||||
readonly tableColumnConfigs: TableColumnConfig<DossierWrapper>[] = [
|
||||
{
|
||||
label: _('dossier-listing.table-col-names.name'),
|
||||
withSort: true,
|
||||
@ -73,22 +74,23 @@ export class DossierListingScreenComponent
|
||||
];
|
||||
dossiersChartData: DoughnutChartConfig[] = [];
|
||||
documentsChartData: DoughnutChartConfig[] = [];
|
||||
protected readonly _primaryKey = 'dossierName';
|
||||
protected _tableHeaderLabel = _('dossier-listing.table-header.title');
|
||||
private _lastScrollPosition: number;
|
||||
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
|
||||
private readonly _needsWorkTemplate: TemplateRef<any>;
|
||||
@ViewChild(CdkVirtualScrollViewport)
|
||||
private readonly _scrollViewport: CdkVirtualScrollViewport;
|
||||
|
||||
constructor(
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _router: Router,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _userService: UserService,
|
||||
readonly changeDetectorRef: ChangeDetectorRef,
|
||||
protected readonly _injector: Injector
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
private readonly _userPreferenceService: UserPreferenceService
|
||||
) {
|
||||
super(_injector);
|
||||
this._appStateService.reset();
|
||||
@ -96,15 +98,15 @@ export class DossierListingScreenComponent
|
||||
}
|
||||
|
||||
private get _userId() {
|
||||
return this._userService.userId;
|
||||
return this._userService.currentUser.id;
|
||||
}
|
||||
|
||||
private get _activeDossiersCount(): number {
|
||||
return this.screenStateService.allEntities.filter(p => p.dossier.status === Dossier.StatusEnum.ACTIVE).length;
|
||||
return this.entitiesService.all.filter(p => p.dossier.status === Dossier.StatusEnum.ACTIVE).length;
|
||||
}
|
||||
|
||||
private get _inactiveDossiersCount(): number {
|
||||
return this.screenStateService.allEntities.length - this._activeDossiersCount;
|
||||
return this.entitiesService.all.length - this._activeDossiersCount;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -121,7 +123,7 @@ export class DossierListingScreenComponent
|
||||
});
|
||||
|
||||
this.addSubscription = this._router.events.pipe(filter(isLeavingScreen)).subscribe(() => {
|
||||
this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top');
|
||||
this._lastScrollPosition = this._scrollViewport.measureScrollOffset('top');
|
||||
});
|
||||
}
|
||||
|
||||
@ -130,7 +132,7 @@ export class DossierListingScreenComponent
|
||||
}
|
||||
|
||||
ngOnAttach() {
|
||||
this.scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||
this._scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||
this._appStateService.reset();
|
||||
this._loadEntitiesFromState();
|
||||
this.ngOnInit();
|
||||
@ -179,7 +181,7 @@ export class DossierListingScreenComponent
|
||||
}
|
||||
|
||||
private _loadEntitiesFromState() {
|
||||
this.screenStateService.setEntities(this._appStateService.allDossiers);
|
||||
this.entitiesService.setEntities(this._appStateService.allDossiers);
|
||||
}
|
||||
|
||||
private _computeAllFilters() {
|
||||
@ -188,7 +190,7 @@ export class DossierListingScreenComponent
|
||||
const allDistinctNeedsWork = new Set<string>();
|
||||
const allDistinctDossierTemplates = new Set<string>();
|
||||
|
||||
this.screenStateService?.allEntities?.forEach(entry => {
|
||||
this.entitiesService?.all?.forEach(entry => {
|
||||
// all people
|
||||
entry.dossier.memberIds.forEach(f => allDistinctPeople.add(f));
|
||||
// Needs work
|
||||
@ -255,7 +257,7 @@ export class DossierListingScreenComponent
|
||||
slug: 'dossierTemplateFilters',
|
||||
label: this._translateService.instant('filters.dossier-templates'),
|
||||
icon: 'red:template',
|
||||
hide: this.filterService.getFilterGroup('dossierTemplateFilters')?.filters?.length <= 1,
|
||||
hide: this.filterService.getGroup('dossierTemplateFilters')?.filters?.length <= 1,
|
||||
filters: dossierTemplateFilters,
|
||||
checker: dossierTemplateChecker
|
||||
});
|
||||
|
||||
@ -5,17 +5,17 @@
|
||||
[showCloseButton]="true"
|
||||
>
|
||||
<redaction-file-download-btn
|
||||
[disabled]="screenStateService.areSomeEntitiesSelected$ | async"
|
||||
[disabled]="entitiesService.areSomeSelected$ | async"
|
||||
[dossier]="activeDossier"
|
||||
[file]="screenStateService.allEntities$ | async"
|
||||
[file]="entitiesService.all$ | async"
|
||||
tooltipPosition="below"
|
||||
></redaction-file-download-btn>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="reanalyseDossier()"
|
||||
*ngIf="permissionsService.displayReanalyseBtn()"
|
||||
[disabled]="screenStateService.areSomeEntitiesSelected$ | async"
|
||||
[tooltipClass]="'small ' + ((screenStateService.areSomeEntitiesSelected$ | async) ? '' : 'warn')"
|
||||
[disabled]="entitiesService.areSomeSelected$ | async"
|
||||
[tooltipClass]="'small ' + ((entitiesService.areSomeSelected$ | async) ? '' : 'warn')"
|
||||
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
|
||||
icon="red:refresh"
|
||||
tooltipPosition="below"
|
||||
@ -39,13 +39,13 @@
|
||||
<redaction-table-header
|
||||
[bulkActions]="bulkActions"
|
||||
[selectionEnabled]="true"
|
||||
[tableColConfigs]="tableColConfigs"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
[tableHeaderLabel]="tableHeaderLabel"
|
||||
></redaction-table-header>
|
||||
|
||||
<redaction-empty-state
|
||||
(action)="fileInput.click()"
|
||||
*ngIf="screenStateService.noData$ | async"
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
[buttonLabel]="'dossier-overview.no-data.action' | translate"
|
||||
[text]="'dossier-overview.no-data.title' | translate"
|
||||
buttonIcon="red:upload"
|
||||
@ -54,11 +54,11 @@
|
||||
|
||||
<redaction-empty-state *ngIf="noMatch$ | async" [text]="'dossier-overview.no-match.title' | translate"></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<cdk-virtual-scroll-viewport #scrollViewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="let fileStatus of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
[class.disabled]="fileStatus.isExcluded"
|
||||
[class.last-opened]="isLastOpenedFile(fileStatus)"
|
||||
[class.last-opened]="isLastOpenedFile(fileStatus.fileId)"
|
||||
[class.pointer]="permissionsService.canOpenFile(fileStatus)"
|
||||
[routerLink]="fileLink(fileStatus)"
|
||||
class="table-item"
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
padding: 0 24px 0 10px;
|
||||
}
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
iqser-table-column-name::ng-deep {
|
||||
> div {
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
|
||||
@ -21,11 +21,8 @@ import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
|
||||
import { NestedFilter, FilterService, keyChecker } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { CircleButtonTypes, keyChecker, NestedFilter, TableColumnConfig } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
|
||||
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
|
||||
@ -33,36 +30,35 @@ import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { workloadTranslations } from '../../translations/workload-translations';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { TableColConfig } from '@shared/components/table-col-name/table-col-name.component';
|
||||
import { annotationFilterChecker } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-overview-screen.component.html',
|
||||
styleUrls: ['./dossier-overview-screen.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class DossierOverviewScreenComponent
|
||||
extends BaseListingComponent<FileStatusWrapper>
|
||||
implements OnInit, OnDestroy, OnDetach, OnAttach
|
||||
{
|
||||
private readonly _lastOpenedFileKey = 'Dossier-Recent-' + this.activeDossier.dossierId;
|
||||
readonly itemSize = 80;
|
||||
protected readonly _primaryKey = 'filename';
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
protected readonly _tableHeaderLabel = _('dossier-overview.table-header.title');
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableHeaderLabel = _('dossier-overview.table-header.title');
|
||||
private readonly _lastOpenedFileKey = 'Dossier-Recent-' + this.activeDossier.dossierId;
|
||||
|
||||
readonly itemSize = 80;
|
||||
collapsedDetails = false;
|
||||
readonly actionConfigs: ActionConfig[] = [
|
||||
{
|
||||
label: this._translateService.instant('dossier-overview.header-actions.edit'),
|
||||
action: $event => this.openEditDossierDialog($event),
|
||||
icon: 'red:edit',
|
||||
hide: !this.permissionsService.isManager()
|
||||
hide: !this.currentUser.isManager
|
||||
}
|
||||
];
|
||||
dossierAttributes: DossierAttributeWithValue[] = [];
|
||||
tableColConfigs: TableColConfig[] = [
|
||||
readonly tableColumnConfigs: TableColumnConfig<FileStatusWrapper>[] = [
|
||||
{
|
||||
label: _('dossier-overview.table-col-names.name'),
|
||||
withSort: true,
|
||||
@ -94,29 +90,35 @@ export class DossierOverviewScreenComponent
|
||||
column: 'statusSort'
|
||||
}
|
||||
];
|
||||
|
||||
collapsedDetails = false;
|
||||
dossierAttributes: DossierAttributeWithValue[] = [];
|
||||
@ViewChild(DossierDetailsComponent, { static: false })
|
||||
private readonly _dossierDetailsComponent: DossierDetailsComponent;
|
||||
private _lastScrollPosition: number;
|
||||
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
|
||||
private readonly _needsWorkTemplate: TemplateRef<any>;
|
||||
@ViewChild('fileInput') private _fileInput: ElementRef;
|
||||
@ViewChild('fileInput') private readonly _fileInput: ElementRef;
|
||||
@ViewChild(CdkVirtualScrollViewport)
|
||||
private readonly _scrollViewport: CdkVirtualScrollViewport;
|
||||
|
||||
constructor(
|
||||
private readonly _userService: UserService,
|
||||
private readonly _router: Router,
|
||||
private readonly _toaster: Toaster,
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _userService: UserService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _fileUploadService: FileUploadService,
|
||||
private readonly _statusOverlayService: StatusOverlayService,
|
||||
private readonly _router: Router,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _fileDropOverlayService: FileDropOverlayService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossierAttributesService: DossierAttributesService,
|
||||
protected readonly _injector: Injector
|
||||
private readonly _fileDropOverlayService: FileDropOverlayService,
|
||||
private readonly _dossierAttributesService: DossierAttributesService
|
||||
) {
|
||||
super(_injector);
|
||||
this._loadEntitiesFromState();
|
||||
@ -126,19 +128,15 @@ export class DossierOverviewScreenComponent
|
||||
return this._appStateService.activeDossier;
|
||||
}
|
||||
|
||||
get userId() {
|
||||
return this._userService.userId;
|
||||
}
|
||||
|
||||
get checkedRequiredFilters() {
|
||||
return this.filterService.getFilterGroup('quickFilters')?.filters.filter(f => f.required && f.checked);
|
||||
return this.filterService.getGroup('quickFilters')?.filters.filter(f => f.required && f.checked);
|
||||
}
|
||||
|
||||
get checkedNotRequiredFilters() {
|
||||
return this.filterService.getFilterGroup('quickFilters')?.filters.filter(f => !f.required && f.checked);
|
||||
return this.filterService.getGroup('quickFilters')?.filters.filter(f => !f.required && f.checked);
|
||||
}
|
||||
|
||||
isLastOpenedFile({ fileId }: FileStatusWrapper): boolean {
|
||||
isLastOpenedFile(fileId: string): boolean {
|
||||
return this._userPreferenceService.getLastOpenedFileId(this._lastOpenedFileKey) === fileId;
|
||||
}
|
||||
|
||||
@ -162,7 +160,7 @@ export class DossierOverviewScreenComponent
|
||||
.pipe(filter(event => event instanceof NavigationStart))
|
||||
.subscribe((event: NavigationStart) => {
|
||||
if (!event.url.endsWith(this._appStateService.activeDossierId)) {
|
||||
this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top');
|
||||
this._lastScrollPosition = this._scrollViewport.measureScrollOffset('top');
|
||||
}
|
||||
});
|
||||
|
||||
@ -183,7 +181,7 @@ export class DossierOverviewScreenComponent
|
||||
await this._appStateService.reloadActiveDossierFiles();
|
||||
this._loadEntitiesFromState();
|
||||
await this.ngOnInit();
|
||||
this.scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||
this._scrollViewport.scrollTo({ top: this._lastScrollPosition });
|
||||
}
|
||||
|
||||
ngOnDetach() {
|
||||
@ -239,7 +237,7 @@ export class DossierOverviewScreenComponent
|
||||
}
|
||||
|
||||
bulkActionPerformed() {
|
||||
this.screenStateService.setSelectedEntities([]);
|
||||
this.entitiesService.setSelected([]);
|
||||
this.reloadDossiers();
|
||||
}
|
||||
|
||||
@ -275,7 +273,7 @@ export class DossierOverviewScreenComponent
|
||||
moment(file.lastUpdated).add(this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS), 'hours').isAfter(moment());
|
||||
|
||||
private _loadEntitiesFromState() {
|
||||
if (this.activeDossier) this.screenStateService.setEntities(this.activeDossier.files);
|
||||
if (this.activeDossier) this.entitiesService.setEntities(this.activeDossier.files);
|
||||
}
|
||||
|
||||
private async _uploadFiles(files: FileUploadModel[]) {
|
||||
@ -291,7 +289,7 @@ export class DossierOverviewScreenComponent
|
||||
const allDistinctAddedDates = new Set<string>();
|
||||
const allDistinctNeedsWork = new Set<string>();
|
||||
|
||||
this.screenStateService.allEntities.forEach(file => {
|
||||
this.entitiesService.all.forEach(file => {
|
||||
allDistinctPeople.add(file.currentReviewer);
|
||||
allDistinctFileStatusWrapper.add(file.status);
|
||||
allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY'));
|
||||
@ -369,7 +367,7 @@ export class DossierOverviewScreenComponent
|
||||
|
||||
private _createQuickFilters() {
|
||||
let quickFilters = [];
|
||||
if (this.screenStateService.allEntities.filter(this.recentlyModifiedChecker).length > 0) {
|
||||
if (this.entitiesService.all.filter(this.recentlyModifiedChecker).length > 0) {
|
||||
const recentPeriod = this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS);
|
||||
quickFilters = [
|
||||
{
|
||||
@ -388,7 +386,7 @@ export class DossierOverviewScreenComponent
|
||||
{
|
||||
key: 'assigned-to-me',
|
||||
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-me'),
|
||||
checker: (file: FileStatusWrapper) => file.currentReviewer === this.userId
|
||||
checker: (file: FileStatusWrapper) => file.currentReviewer === this.currentUser.id
|
||||
},
|
||||
{
|
||||
key: 'unassigned',
|
||||
@ -398,7 +396,7 @@ export class DossierOverviewScreenComponent
|
||||
{
|
||||
key: 'assigned-to-others',
|
||||
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-others'),
|
||||
checker: (file: FileStatusWrapper) => !!file.currentReviewer && file.currentReviewer !== this.userId
|
||||
checker: (file: FileStatusWrapper) => !!file.currentReviewer && file.currentReviewer !== this.currentUser.id
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@ -17,12 +17,11 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { timer } from 'rxjs';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { UserService, UserWrapper } from '@services/user.service';
|
||||
import {
|
||||
FileManagementControllerService,
|
||||
FileStatus,
|
||||
StatusControllerService,
|
||||
User,
|
||||
UserPreferenceControllerService
|
||||
} from '@redaction/red-ui-http';
|
||||
import { PdfViewerDataService } from '../../services/pdf-viewer-data.service';
|
||||
@ -34,10 +33,8 @@ import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { stampPDFPage } from '@utils/page-stamper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { AutoUnsubscribeComponent, CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { AutoUnsubscribeComponent, CircleButtonTypes, NestedFilter, processFilters } from '@iqser/common-ui';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { NestedFilter } from '@iqser/common-ui';
|
||||
import { processFilters } from '@iqser/common-ui';
|
||||
import { handleFilterDelta } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
||||
@ -276,7 +273,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme
|
||||
const processStartTime = new Date().getTime();
|
||||
this.annotationData = this.fileData.getAnnotations(
|
||||
this.appStateService.dictionaryData[this.appStateService.activeDossier.dossierTemplateId],
|
||||
this.permissionsService.currentUser,
|
||||
this.userService.currentUser,
|
||||
this.viewMode,
|
||||
this.userPreferenceService.areDevFeaturesEnabled
|
||||
);
|
||||
@ -467,8 +464,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme
|
||||
});
|
||||
}
|
||||
|
||||
async assignReviewer(user: User | string) {
|
||||
const reviewerId = typeof user === 'string' ? user : user.userId;
|
||||
async assignReviewer(user: UserWrapper | string) {
|
||||
const reviewerId = typeof user === 'string' ? user : user.id;
|
||||
const reviewerName = this.userService.getNameForId(reviewerId);
|
||||
|
||||
const { dossierId, fileId, filename } = this.fileData.fileStatus;
|
||||
|
||||
@ -10,7 +10,10 @@
|
||||
|
||||
<div class="red-content-inner">
|
||||
<div class="content-container">
|
||||
<redaction-table-header [tableColConfigs]="tableColConfigs" [tableHeaderLabel]="tableHeaderLabel"></redaction-table-header>
|
||||
<redaction-table-header
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
[tableHeaderLabel]="tableHeaderLabel"
|
||||
></redaction-table-header>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="searchResult.length === 0"
|
||||
@ -18,7 +21,7 @@
|
||||
[text]="'search-screen.no-data' | translate"
|
||||
></redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<cdk-virtual-scroll-viewport #scrollViewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="let item of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
[class.pointer]="true"
|
||||
|
||||
@ -1,21 +1,16 @@
|
||||
import { Component, Injector, OnDestroy } from '@angular/core';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { MatchedDocument, SearchControllerService, SearchResult } from '@redaction/red-ui-http';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { debounceTime, map, skip, switchMap, tap } from 'rxjs/operators';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { TableColConfig } from '@shared/components/table-col-name/table-col-name.component';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
import { keyChecker, TableColumnConfig } from '@iqser/common-ui';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { SearchPositions } from '@shared/components/page-header/models/search-positions.type';
|
||||
import { keyChecker } from '@iqser/common-ui';
|
||||
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@ -38,37 +33,29 @@ interface SearchInput {
|
||||
@Component({
|
||||
templateUrl: './search-screen.component.html',
|
||||
styleUrls: ['./search-screen.component.scss'],
|
||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class SearchScreenComponent extends BaseListingComponent<ListItem> implements OnDestroy {
|
||||
readonly fileStatusTranslations = fileStatusTranslations;
|
||||
readonly searchPositions = SearchPositions;
|
||||
|
||||
readonly itemSize = 85;
|
||||
protected readonly _primaryKey = 'filename';
|
||||
readonly tableHeaderLabel = _('search-screen.table-header');
|
||||
readonly tableColumnConfigs: TableColumnConfig<ListItem>[] = [
|
||||
{ label: _('search-screen.cols.document') },
|
||||
{ label: _('search-screen.cols.status') },
|
||||
{ label: _('search-screen.cols.dossier') },
|
||||
{ label: _('search-screen.cols.pages') }
|
||||
];
|
||||
readonly search$ = new BehaviorSubject<SearchInput>(null);
|
||||
readonly searchResults$: Observable<ListItem[]> = this.search$.asObservable().pipe(
|
||||
switchMap(query => this._search(query)),
|
||||
map(searchResult => this._toMatchedDocuments(searchResult)),
|
||||
map(docs => this._toListItems(docs)),
|
||||
tap(result => this.screenStateService.setEntities(result)),
|
||||
tap(result => this.entitiesService.setEntities(result)),
|
||||
tap(() => this._loadingService.stop())
|
||||
);
|
||||
readonly tableColConfigs: TableColConfig[] = [
|
||||
{
|
||||
label: _('search-screen.cols.document')
|
||||
},
|
||||
{
|
||||
label: _('search-screen.cols.status')
|
||||
},
|
||||
{
|
||||
label: _('search-screen.cols.dossier')
|
||||
},
|
||||
{
|
||||
label: _('search-screen.cols.pages')
|
||||
}
|
||||
];
|
||||
protected readonly _primaryKey = 'fileName';
|
||||
protected readonly _tableHeaderLabel = _('search-screen.table-header');
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
|
||||
@ -9,13 +9,15 @@ import { getFirstRelevantTextPart } from '@utils/functions';
|
||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||
import { DossiersDialogService } from './dossiers-dialog.service';
|
||||
import { BASE_HREF } from '../../../tokens';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationActionsService {
|
||||
constructor(
|
||||
@Inject(BASE_HREF) private readonly _baseHref: string,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _ngZone: NgZone,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _manualAnnotationService: ManualAnnotationService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _dialogService: DossiersDialogService
|
||||
@ -89,7 +91,7 @@ export class AnnotationActionsService {
|
||||
annotations.forEach(annotation => {
|
||||
const permissions = AnnotationPermissions.forUser(
|
||||
this._permissionsService.isApprover(),
|
||||
this._permissionsService.currentUser,
|
||||
this._userService.currentUser,
|
||||
annotation
|
||||
);
|
||||
const value = permissions.canMarkTextOnlyAsFalsePositive ? annotation.value : this._getFalsePositiveText(annotation);
|
||||
@ -132,9 +134,9 @@ export class AnnotationActionsService {
|
||||
): Record<string, unknown>[] {
|
||||
const availableActions = [];
|
||||
|
||||
const annotationPermissions = annotations.map(a => ({
|
||||
annotation: a,
|
||||
permissions: AnnotationPermissions.forUser(this._permissionsService.isApprover(), this._permissionsService.currentUser, a)
|
||||
const annotationPermissions = annotations.map(annotation => ({
|
||||
annotation,
|
||||
permissions: AnnotationPermissions.forUser(this._permissionsService.isApprover(), this._userService.currentUser, annotation)
|
||||
}));
|
||||
|
||||
const canRecategorizeImage = annotations.length === 1 && annotationPermissions[0].permissions.canRecategorizeImage;
|
||||
|
||||
@ -154,7 +154,7 @@ export class FileActionService {
|
||||
.setFileReviewerForList(
|
||||
fileStatus.map(f => f.fileId),
|
||||
this._appStateService.activeDossierId,
|
||||
this._userService.userId
|
||||
this._userService.currentUser.id
|
||||
)
|
||||
.toPromise();
|
||||
await this._appStateService.reloadActiveDossierFiles();
|
||||
|
||||
@ -70,8 +70,6 @@ export class IconsModule {
|
||||
'report',
|
||||
'search',
|
||||
'secret',
|
||||
'sort-asc',
|
||||
'sort-desc',
|
||||
'status',
|
||||
'status-collapse',
|
||||
'status-expand',
|
||||
|
||||
@ -1,35 +1,36 @@
|
||||
import { Component, Injector, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { SortingOrders, SortingService } from '@services/sorting.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { SearchService } from '../services/search.service';
|
||||
import { ScreenStateService } from '../services/screen-state.service';
|
||||
import { Component, Injector, OnDestroy } from '@angular/core';
|
||||
import {
|
||||
AutoUnsubscribeComponent,
|
||||
EntitiesService,
|
||||
FilterService,
|
||||
KeysOf,
|
||||
SearchService,
|
||||
SortingOrders,
|
||||
SortingService,
|
||||
TableColumnConfig
|
||||
} from '@iqser/common-ui';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { AutoUnsubscribeComponent } from '@iqser/common-ui';
|
||||
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
|
||||
export const DefaultListingServices = [FilterService, SearchService, EntitiesService, SortingService] as const;
|
||||
|
||||
@Component({ template: '' })
|
||||
export abstract class BaseListingComponent<T> extends AutoUnsubscribeComponent implements OnDestroy {
|
||||
@ViewChild(CdkVirtualScrollViewport)
|
||||
readonly scrollViewport: CdkVirtualScrollViewport;
|
||||
|
||||
readonly permissionsService = this._injector.get(PermissionsService);
|
||||
export abstract class BaseListingComponent<T extends object> extends AutoUnsubscribeComponent implements OnDestroy {
|
||||
readonly filterService = this._injector.get(FilterService);
|
||||
readonly sortingService = this._injector.get(SortingService);
|
||||
readonly searchService = this._injector.get(SearchService);
|
||||
readonly screenStateService = this._injector.get<ScreenStateService<T>>(ScreenStateService);
|
||||
readonly searchService = this._injector.get<SearchService<T>>(SearchService);
|
||||
readonly sortingService = this._injector.get<SortingService<T>>(SortingService);
|
||||
readonly entitiesService = this._injector.get<EntitiesService<T>>(EntitiesService);
|
||||
|
||||
readonly sortedDisplayedEntities$ = this._sortedDisplayedEntities$;
|
||||
readonly noMatch$ = this._noMatch$;
|
||||
readonly sortedDisplayedEntities$ = this._sortedDisplayedEntities$;
|
||||
|
||||
protected readonly _tableHeaderLabel: string;
|
||||
readonly tableColumnConfigs: TableColumnConfig<T>[];
|
||||
/**
|
||||
* Key used in the *trackBy* function with **ngFor* or **cdkVirtualFor*
|
||||
* and in the default sorting and as the search field
|
||||
* @protected
|
||||
*/
|
||||
protected abstract _primaryKey: string;
|
||||
protected readonly _primaryKey: KeysOf<T>;
|
||||
|
||||
protected constructor(protected readonly _injector: Injector) {
|
||||
super();
|
||||
@ -37,26 +38,18 @@ export abstract class BaseListingComponent<T> extends AutoUnsubscribeComponent i
|
||||
setTimeout(() => this.setInitialConfig());
|
||||
}
|
||||
|
||||
get tableHeaderLabel(): string {
|
||||
if (!this._tableHeaderLabel) {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
return this._tableHeaderLabel;
|
||||
}
|
||||
|
||||
get allEntities(): T[] {
|
||||
return this.screenStateService.allEntities;
|
||||
return this.entitiesService.all;
|
||||
}
|
||||
|
||||
private get _sortedDisplayedEntities$(): Observable<T[]> {
|
||||
return this.sortingService.sortingOption$.pipe(
|
||||
switchMap(() => this.screenStateService.displayedEntities$.pipe(map(entities => this.sortingService.defaultSort(entities))))
|
||||
);
|
||||
const sort = entities => this.sortingService.defaultSort(entities);
|
||||
const sortedEntities = () => this.entitiesService.displayed$.pipe(map(sort));
|
||||
return this.sortingService.sortingOption$.pipe(switchMap(sortedEntities));
|
||||
}
|
||||
|
||||
private get _noMatch$(): Observable<boolean> {
|
||||
return combineLatest([this.screenStateService.allEntitiesLength$, this.screenStateService.displayedLength$]).pipe(
|
||||
return combineLatest([this.entitiesService.allLength$, this.entitiesService.displayedLength$]).pipe(
|
||||
map(([hasEntities, hasDisplayedEntities]) => hasEntities && !hasDisplayedEntities),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
@ -70,28 +63,24 @@ export abstract class BaseListingComponent<T> extends AutoUnsubscribeComponent i
|
||||
this.searchService.setSearchKey(this._primaryKey);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
canBulkDelete$(hasPermission = true): Observable<boolean> {
|
||||
return this.screenStateService.areSomeEntitiesSelected$.pipe(
|
||||
return this.entitiesService.areSomeSelected$.pipe(
|
||||
map(areSomeEntitiesSelected => areSomeEntitiesSelected && hasPermission),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
toggleSelectAll() {
|
||||
return this.screenStateService.selectEntities();
|
||||
return this.entitiesService.selectAll();
|
||||
}
|
||||
|
||||
toggleEntitySelected(event: MouseEvent, entity: T) {
|
||||
event.stopPropagation();
|
||||
return this.screenStateService.selectEntities([entity]);
|
||||
return this.entitiesService.select(entity);
|
||||
}
|
||||
|
||||
isSelected(entity: T): boolean {
|
||||
return this.screenStateService.isSelected(entity);
|
||||
return this.entitiesService.isSelected(entity);
|
||||
}
|
||||
|
||||
trackByPrimaryKey(index: number, item: T) {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { UserService, UserWrapper } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-assign-user-dropdown',
|
||||
@ -9,25 +8,25 @@ import { UserService } from '@services/user.service';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AssignUserDropdownComponent {
|
||||
oldUser: User | string;
|
||||
@Input() options: (User | string)[];
|
||||
@Output() save = new EventEmitter<User | string>();
|
||||
oldUser: UserWrapper | string;
|
||||
@Input() options: (UserWrapper | string)[];
|
||||
@Output() save = new EventEmitter<UserWrapper | string>();
|
||||
@Output() cancel = new EventEmitter<never>();
|
||||
private _currentUser: User | string;
|
||||
private _currentUser: UserWrapper | string;
|
||||
|
||||
constructor(private readonly _userService: UserService) {}
|
||||
|
||||
get value(): User | string {
|
||||
get value(): UserWrapper | string {
|
||||
return this._currentUser;
|
||||
}
|
||||
|
||||
@Input()
|
||||
set value(value: User | string) {
|
||||
set value(value: UserWrapper | string) {
|
||||
if (this.oldUser === undefined) this.oldUser = value;
|
||||
this._currentUser = value;
|
||||
}
|
||||
|
||||
getContext(user: User | string) {
|
||||
return { userId: typeof user === 'string' ? user : user?.userId };
|
||||
getContext(user: UserWrapper | string) {
|
||||
return { userId: typeof user === 'string' ? user : user?.id };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<button [class.overlay]="showDot" mat-button>
|
||||
<redaction-initials-avatar [userId]="user.userId" [withName]="true" size="small"></redaction-initials-avatar>
|
||||
<redaction-initials-avatar [userId]="userId" [withName]="true" size="small"></redaction-initials-avatar>
|
||||
<mat-icon svgIcon="iqser:arrow-down"></mat-icon>
|
||||
</button>
|
||||
<div *ngIf="showDot" class="dot"></div>
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { UserWrapper } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-user-button',
|
||||
@ -8,6 +7,6 @@ import { UserWrapper } from '@services/user.service';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class UserButtonComponent {
|
||||
@Input() user: UserWrapper;
|
||||
@Input() userId: string;
|
||||
@Input() showDot = false;
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy } from '@angular/core';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { UserService, UserWrapper } from '@services/user.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { AutoUnsubscribeComponent } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-initials-avatar',
|
||||
@ -10,7 +9,7 @@ import { Subscription } from 'rxjs';
|
||||
styleUrls: ['./initials-avatar.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class InitialsAvatarComponent implements OnChanges, OnDestroy {
|
||||
export class InitialsAvatarComponent extends AutoUnsubscribeComponent implements OnChanges, OnDestroy {
|
||||
@Input() userId: string;
|
||||
@Input() color = 'lightgray';
|
||||
@Input() size: 'small' | 'large' = 'small';
|
||||
@ -21,26 +20,25 @@ export class InitialsAvatarComponent implements OnChanges, OnDestroy {
|
||||
displayName: string;
|
||||
initials: string;
|
||||
colorClass: string;
|
||||
user: User;
|
||||
|
||||
private _subscription: Subscription;
|
||||
user: UserWrapper;
|
||||
|
||||
constructor(
|
||||
private readonly _userService: UserService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef
|
||||
) {
|
||||
this._subscription = _userService.usersReloaded$.subscribe(() => {
|
||||
super();
|
||||
this.addSubscription = _userService.usersReloaded$.subscribe(() => {
|
||||
this.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
get hasBorder(): boolean {
|
||||
return !!this.user && !this._isCurrentUser && this._userService.isManager(this.user);
|
||||
return !!this.user && !this._isCurrentUser && this.user.isManager;
|
||||
}
|
||||
|
||||
get disabled(): boolean {
|
||||
return !this._userService.isActive(this.user);
|
||||
return !this.user?.isActive;
|
||||
}
|
||||
|
||||
private get _colorClass() {
|
||||
@ -52,11 +50,7 @@ export class InitialsAvatarComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
private get _isCurrentUser(): boolean {
|
||||
return this._userService.userId === this.user?.userId;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._subscription?.unsubscribe();
|
||||
return this._userService.currentUser.id === this.user?.id;
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { Component, Input, Optional } from '@angular/core';
|
||||
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
|
||||
import { ButtonConfig } from '@shared/components/page-header/models/button-config.model';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { FilterService, SearchService } from '@iqser/common-ui';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { combineLatest, Observable, of } from 'rxjs';
|
||||
import { SearchPosition, SearchPositions } from '@shared/components/page-header/models/search-positions.type';
|
||||
@ -12,7 +11,7 @@ import { SearchPosition, SearchPositions } from '@shared/components/page-header/
|
||||
templateUrl: './page-header.component.html',
|
||||
styleUrls: ['./page-header.component.scss']
|
||||
})
|
||||
export class PageHeaderComponent {
|
||||
export class PageHeaderComponent<T extends object> {
|
||||
readonly searchPositions = SearchPositions;
|
||||
|
||||
@Input() pageLabel: string;
|
||||
@ -26,7 +25,7 @@ export class PageHeaderComponent {
|
||||
readonly filters$ = this.filterService?.filterGroups$.pipe(map(all => all.filter(f => f.icon)));
|
||||
readonly showResetFilters$ = this._showResetFilters$;
|
||||
|
||||
constructor(@Optional() readonly filterService: FilterService, @Optional() readonly searchService: SearchService) {}
|
||||
constructor(@Optional() readonly filterService: FilterService, @Optional() readonly searchService: SearchService<T>) {}
|
||||
|
||||
get _showResetFilters$(): Observable<boolean> {
|
||||
if (!this.filterService) return of(false);
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
<div (click)="withSort && sortingService?.toggleSort(column)" [class.pointer]="withSort" [ngClass]="class">
|
||||
<mat-icon *ngIf="!!leftIcon" [svgIcon]="leftIcon"></mat-icon>
|
||||
<span class="all-caps-label">{{ label }}</span>
|
||||
<mat-icon *ngIf="!!rightIcon" [matTooltip]="rightIconTooltip" [svgIcon]="rightIcon" matTooltipPosition="above"></mat-icon>
|
||||
|
||||
<ng-container *ngIf="sortingService?.sortingOption$ | async as sortingOption">
|
||||
<div *ngIf="withSort" [class.force-display]="sortingOption.column === column" class="sort-arrows-container">
|
||||
<mat-icon *ngIf="sortingOption.order === 'asc'" svgIcon="red:sort-asc"></mat-icon>
|
||||
<mat-icon *ngIf="sortingOption.order === 'desc'" svgIcon="red:sort-desc"></mat-icon>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
@ -1,51 +0,0 @@
|
||||
@import '../../../../../assets/styles/variables';
|
||||
|
||||
:host {
|
||||
display: flex;
|
||||
height: 30px;
|
||||
flex: 1;
|
||||
|
||||
> div {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
line-height: 11px;
|
||||
padding: 0 24px;
|
||||
|
||||
> mat-icon {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 6px;
|
||||
opacity: 0.7;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flex-end {
|
||||
min-width: 58px;
|
||||
}
|
||||
|
||||
.sort-arrows-container {
|
||||
display: none;
|
||||
color: $primary;
|
||||
margin-left: 8px;
|
||||
|
||||
mat-icon {
|
||||
height: 14px;
|
||||
width: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.sort-arrows-container {
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.sort-arrows-container.force-display {
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
import { Component, Input, Optional } from '@angular/core';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
|
||||
export interface TableColConfig {
|
||||
readonly column?: string;
|
||||
readonly label: string;
|
||||
readonly withSort?: boolean;
|
||||
readonly class?: string;
|
||||
readonly leftIcon?: string;
|
||||
readonly rightIcon?: string;
|
||||
readonly rightIconTooltip?: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-table-col-name',
|
||||
templateUrl: './table-col-name.component.html',
|
||||
styleUrls: ['./table-col-name.component.scss']
|
||||
})
|
||||
export class TableColNameComponent {
|
||||
@Input() column: string;
|
||||
@Input() label: string;
|
||||
@Input() withSort = false;
|
||||
@Input() class: string;
|
||||
@Input() leftIcon: string;
|
||||
@Input() rightIcon: string;
|
||||
@Input() rightIconTooltip: string;
|
||||
|
||||
constructor(@Optional() readonly sortingService: SortingService) {}
|
||||
}
|
||||
@ -1,13 +1,13 @@
|
||||
<div [class.selection-enabled]="selectionEnabled" class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="screenStateService.selectEntities()"
|
||||
(click)="entitiesService.selectAll()"
|
||||
*ngIf="selectionEnabled"
|
||||
[active]="screenStateService.areAllEntitiesSelected$ | async"
|
||||
[indeterminate]="screenStateService.notAllEntitiesSelected$ | async"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{ tableHeaderLabel | translate: { length: (screenStateService.displayedLength$ | async) } }}
|
||||
{{ tableHeaderLabel | translate: { length: (entitiesService.displayedLength$ | async) } }}
|
||||
</span>
|
||||
|
||||
<ng-container [ngTemplateOutlet]="bulkActions"></ng-container>
|
||||
@ -18,8 +18,8 @@
|
||||
<div [class.selection-enabled]="selectionEnabled" class="table-header" redactionSyncWidth="table-item">
|
||||
<div *ngIf="selectionEnabled" class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
*ngFor="let config of tableColConfigs"
|
||||
<iqser-table-column-name
|
||||
*ngFor="let config of tableColumnConfigs"
|
||||
[class]="config.class"
|
||||
[column]="config.column"
|
||||
[label]="config.label | translate"
|
||||
@ -27,7 +27,7 @@
|
||||
[rightIconTooltip]="config.rightIconTooltip"
|
||||
[rightIcon]="config.rightIcon"
|
||||
[withSort]="config.withSort"
|
||||
></redaction-table-col-name>
|
||||
></iqser-table-column-name>
|
||||
|
||||
<div *ngIf="hasEmptyColumn"></div>
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, TemplateRef } from '@angular/core';
|
||||
import { TableColConfig } from '@shared/components/table-col-name/table-col-name.component';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { EntitiesService, Required, TableColumnConfig } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-table-header',
|
||||
@ -8,12 +7,12 @@ import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
styleUrls: ['./table-header.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class TableHeaderComponent<T> {
|
||||
@Input() tableHeaderLabel: string;
|
||||
@Input() tableColConfigs: TableColConfig[];
|
||||
export class TableHeaderComponent<T extends object> {
|
||||
@Input() @Required() tableHeaderLabel: string;
|
||||
@Input() @Required() tableColumnConfigs: TableColumnConfig<T>[];
|
||||
@Input() hasEmptyColumn = false;
|
||||
@Input() selectionEnabled = false;
|
||||
@Input() bulkActions: TemplateRef<any>;
|
||||
|
||||
constructor(readonly screenStateService: ScreenStateService<T>) {}
|
||||
constructor(readonly entitiesService: EntitiesService<T>) {}
|
||||
}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { humanize } from '@utils/functions';
|
||||
|
||||
@Pipe({
|
||||
name: 'humanize'
|
||||
})
|
||||
export class HumanizePipe implements PipeTransform {
|
||||
transform(item: string, lowercase: boolean = false): any {
|
||||
return humanize(item, lowercase);
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
|
||||
@Pipe({ name: 'sortBy' })
|
||||
export class SortByPipe implements PipeTransform {
|
||||
constructor(private readonly _sortingService: SortingService) {}
|
||||
|
||||
transform<T>(value: T[], order = '', column: string = ''): T[] {
|
||||
return this._sortingService.sort(value, order, column);
|
||||
}
|
||||
}
|
||||
@ -1,135 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, combineLatest, Observable, pipe } from 'rxjs';
|
||||
import { distinctUntilChanged, map, tap } from 'rxjs/operators';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { getFilteredEntities } from '@iqser/common-ui';
|
||||
|
||||
const toLengthValue = (entities: unknown[]) => entities?.length ?? 0;
|
||||
const getLength = pipe(map(toLengthValue), distinctUntilChanged());
|
||||
|
||||
@Injectable()
|
||||
export class ScreenStateService<T> {
|
||||
private readonly _allEntities$ = new BehaviorSubject<T[]>([]);
|
||||
readonly allEntities$ = this._allEntities$.asObservable();
|
||||
readonly allEntitiesLength$ = this._allEntities$.pipe(getLength);
|
||||
|
||||
private readonly _displayedEntities$ = new BehaviorSubject<T[]>([]);
|
||||
readonly displayedEntities$ = this._getDisplayedEntities$;
|
||||
readonly displayedLength$ = this._displayedEntities$.pipe(getLength);
|
||||
|
||||
private readonly _selectedEntities$ = new BehaviorSubject<T[]>([]);
|
||||
readonly selectedEntities$ = this._selectedEntities$.asObservable();
|
||||
readonly selectedLength$ = this._selectedEntities$.pipe(getLength);
|
||||
|
||||
readonly noData$ = this._noData$;
|
||||
readonly areAllEntitiesSelected$ = this._areAllEntitiesSelected$;
|
||||
readonly areSomeEntitiesSelected$ = this._areSomeEntitiesSelected$;
|
||||
readonly notAllEntitiesSelected$ = this._notAllEntitiesSelected$;
|
||||
|
||||
constructor(private readonly _filterService: FilterService, private readonly _searchService: SearchService) {
|
||||
// setInterval(() => {
|
||||
// console.log('All entities subs: ', this._allEntities$.observers);
|
||||
// console.log('Displayed entities subs: ', this._displayedEntities$.observers);
|
||||
// console.log('Selected entities subs: ', this._selectedEntities$.observers);
|
||||
// }, 10000);
|
||||
}
|
||||
|
||||
get allEntities(): T[] {
|
||||
return Object.values(this._allEntities$.getValue());
|
||||
}
|
||||
|
||||
get selectedEntities(): T[] {
|
||||
return Object.values(this._selectedEntities$.getValue());
|
||||
}
|
||||
|
||||
get displayedEntities(): T[] {
|
||||
return Object.values(this._displayedEntities$.getValue());
|
||||
}
|
||||
|
||||
get _getDisplayedEntities$(): Observable<T[]> {
|
||||
const filterGroups$ = this._filterService.filterGroups$;
|
||||
const searchValue$ = this._searchService.valueChanges$;
|
||||
|
||||
return combineLatest([this.allEntities$, filterGroups$, searchValue$]).pipe(
|
||||
map(([entities, filterGroups]) => getFilteredEntities(entities, filterGroups)),
|
||||
map(entities => this._searchService.searchIn(entities)),
|
||||
tap(entities => this._displayedEntities$.next(entities))
|
||||
);
|
||||
}
|
||||
|
||||
private get _areAllEntitiesSelected$(): Observable<boolean> {
|
||||
return combineLatest([this.displayedLength$, this.selectedLength$]).pipe(
|
||||
map(([displayedLength, selectedLength]) => displayedLength && displayedLength === selectedLength),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
private get _areSomeEntitiesSelected$(): Observable<boolean> {
|
||||
return this.selectedLength$.pipe(
|
||||
map(value => !!value),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
private get _notAllEntitiesSelected$(): Observable<boolean> {
|
||||
return combineLatest([this.areAllEntitiesSelected$, this.areSomeEntitiesSelected$]).pipe(
|
||||
map(([allEntitiesAreSelected, someEntitiesAreSelected]) => !allEntitiesAreSelected && someEntitiesAreSelected),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
private get _noData$(): Observable<boolean> {
|
||||
return this.allEntitiesLength$.pipe(
|
||||
map(length => length === 0),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
private get _allEntitiesSelected() {
|
||||
return this.displayedEntities.length !== 0 && this.displayedEntities.length === this.selectedEntities.length;
|
||||
}
|
||||
|
||||
setEntities(newEntities: T[]): void {
|
||||
this._allEntities$.next(newEntities);
|
||||
}
|
||||
|
||||
setSelectedEntities(newEntities: T[]): void {
|
||||
this._selectedEntities$.next(newEntities);
|
||||
}
|
||||
|
||||
isSelected(entity: T): boolean {
|
||||
return this.selectedEntities.indexOf(entity) !== -1;
|
||||
}
|
||||
|
||||
selectEntities(entities?: T[]): void {
|
||||
if (entities?.length > 0) {
|
||||
return entities.forEach(entity => this._selectOne(entity));
|
||||
}
|
||||
return this._selectAll();
|
||||
}
|
||||
|
||||
updateSelection(): void {
|
||||
const items = this.displayedEntities.filter(item => this.selectedEntities.includes(item));
|
||||
this.setSelectedEntities(items);
|
||||
}
|
||||
|
||||
logCurrentState(): void {
|
||||
console.log('Entities', this.allEntities);
|
||||
console.log('Displayed', this.displayedEntities);
|
||||
console.log('Selected', this.selectedEntities);
|
||||
}
|
||||
|
||||
private _selectOne(entity: T): void {
|
||||
const currentEntityIdx = this.selectedEntities.indexOf(entity);
|
||||
if (currentEntityIdx === -1) {
|
||||
return this.setSelectedEntities([...this.selectedEntities, entity]);
|
||||
}
|
||||
this.setSelectedEntities(this.selectedEntities.filter((el, idx) => idx !== currentEntityIdx));
|
||||
}
|
||||
|
||||
private _selectAll(): void {
|
||||
if (this._allEntitiesSelected) return this.setSelectedEntities([]);
|
||||
this.setSelectedEntities(this.displayedEntities);
|
||||
}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { startWith } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class SearchService {
|
||||
readonly searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
readonly valueChanges$ = this.searchForm.get('query').valueChanges.pipe(startWith(''));
|
||||
private _searchKey: string;
|
||||
|
||||
constructor(private readonly _formBuilder: FormBuilder) {}
|
||||
|
||||
get searchValue(): string {
|
||||
return this.searchForm.get('query').value;
|
||||
}
|
||||
|
||||
set searchValue(value: string) {
|
||||
this.searchForm.patchValue({ query: value });
|
||||
}
|
||||
|
||||
searchIn<T>(entities: T[]) {
|
||||
if (!this._searchKey) return entities;
|
||||
|
||||
const searchValue = this.searchValue.toLowerCase();
|
||||
return entities.filter(entity => this._searchField(entity).includes(searchValue));
|
||||
}
|
||||
|
||||
setSearchKey(value: string): void {
|
||||
this._searchKey = value;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.searchForm.reset({ query: '' }, { emitEvent: true });
|
||||
}
|
||||
|
||||
private _searchField<T>(entity: T): string {
|
||||
return entity[this._searchKey].toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,6 @@ import { FullPageLoadingIndicatorComponent } from './components/full-page-loadin
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InitialsAvatarComponent } from './components/initials-avatar/initials-avatar.component';
|
||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||
import { TableColNameComponent } from './components/table-col-name/table-col-name.component';
|
||||
import { PaginationComponent } from './components/pagination/pagination.component';
|
||||
import { FileDownloadBtnComponent } from './components/buttons/file-download-btn/file-download-btn.component';
|
||||
import { UserButtonComponent } from './components/buttons/user-button/user-button.component';
|
||||
@ -14,14 +13,13 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { AnnotationIconComponent } from './components/annotation-icon/annotation-icon.component';
|
||||
import { SimpleDoughnutChartComponent } from './components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { StatusBarComponent } from './components/status-bar/status-bar.component';
|
||||
import { HumanizePipe } from './pipes/humanize.pipe';
|
||||
import { SyncWidthDirective } from './directives/sync-width.directive';
|
||||
import { HasScrollbarDirective } from './directives/has-scrollbar.directive';
|
||||
import { DictionaryAnnotationIconComponent } from './components/dictionary-annotation-icon/dictionary-annotation-icon.component';
|
||||
import { HiddenActionComponent } from './components/hidden-action/hidden-action.component';
|
||||
import { ConfirmationDialogComponent } from './dialogs/confirmation-dialog/confirmation-dialog.component';
|
||||
import { EmptyStateComponent } from './components/empty-state/empty-state.component';
|
||||
import { SortByPipe } from './pipes/sort-by.pipe';
|
||||
import { CommonUiModule } from '@iqser/common-ui';
|
||||
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
|
||||
import { MomentDateAdapter } from '@angular/material-moment-adapter';
|
||||
import { SelectComponent } from './components/select/select.component';
|
||||
@ -36,14 +34,13 @@ import { InputWithActionComponent } from '@shared/components/input-with-action/i
|
||||
import { PageHeaderComponent } from './components/page-header/page-header.component';
|
||||
import { DatePipe } from '@shared/pipes/date.pipe';
|
||||
import { TableHeaderComponent } from './components/table-header/table-header.component';
|
||||
import { CommonUiModule } from '@iqser/common-ui';
|
||||
|
||||
const buttons = [FileDownloadBtnComponent, UserButtonComponent];
|
||||
|
||||
const components = [
|
||||
FullPageLoadingIndicatorComponent,
|
||||
InitialsAvatarComponent,
|
||||
TableColNameComponent,
|
||||
TableHeaderComponent,
|
||||
PaginationComponent,
|
||||
InputWithActionComponent,
|
||||
AnnotationIconComponent,
|
||||
@ -54,7 +51,6 @@ const components = [
|
||||
PopupFilterComponent,
|
||||
ConfirmationDialogComponent,
|
||||
EmptyStateComponent,
|
||||
SortByPipe,
|
||||
SelectComponent,
|
||||
SideNavComponent,
|
||||
DictionaryManagerComponent,
|
||||
@ -65,7 +61,7 @@ const components = [
|
||||
...buttons
|
||||
];
|
||||
|
||||
const utils = [HumanizePipe, DatePipe, SyncWidthDirective, HasScrollbarDirective, NavigateLastDossiersScreenDirective];
|
||||
const utils = [DatePipe, SyncWidthDirective, HasScrollbarDirective, NavigateLastDossiersScreenDirective];
|
||||
|
||||
const modules = [MatConfigModule, TranslateModule, ScrollingModule, IconsModule, FormsModule, ReactiveFormsModule, CommonUiModule];
|
||||
|
||||
|
||||
@ -8,8 +8,8 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { mergeMap, tap } from 'rxjs/operators';
|
||||
import { DownloadStatusWrapper } from '../model/download-status.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Injectable()
|
||||
export class FileDownloadService {
|
||||
@ -18,17 +18,17 @@ export class FileDownloadService {
|
||||
hasPendingDownloads;
|
||||
|
||||
constructor(
|
||||
private readonly _userService: UserService,
|
||||
private readonly _applicationRef: ApplicationRef,
|
||||
private readonly _keycloakService: KeycloakService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _downloadControllerService: DownloadControllerService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _keycloakService: KeycloakService,
|
||||
private readonly _downloadControllerService: DownloadControllerService,
|
||||
private readonly _fileManagementControllerService: FileManagementControllerService
|
||||
) {
|
||||
interval(5000).subscribe(() => {
|
||||
if (_permissionsService.isUser()) {
|
||||
if (_userService.currentUser.isUser) {
|
||||
this.getDownloadStatus().subscribe(() => {});
|
||||
}
|
||||
});
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { UserService, UserWrapper } from './user.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { User, Comment } from '@redaction/red-ui-http';
|
||||
import { Comment } from '@redaction/red-ui-http';
|
||||
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
|
||||
@Injectable({
|
||||
@ -11,10 +11,6 @@ import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
export class PermissionsService {
|
||||
constructor(private readonly _appStateService: AppStateService, private readonly _userService: UserService) {}
|
||||
|
||||
get currentUser(): UserWrapper {
|
||||
return this._userService.user;
|
||||
}
|
||||
|
||||
private get _activeFile(): FileStatusWrapper | undefined {
|
||||
return this._appStateService.activeFile;
|
||||
}
|
||||
@ -23,10 +19,6 @@ export class PermissionsService {
|
||||
return this._appStateService.activeDossier;
|
||||
}
|
||||
|
||||
isManager(user?: User) {
|
||||
return this._userService.isManager(user);
|
||||
}
|
||||
|
||||
isReviewerOrApprover(fileStatus?: FileStatusWrapper): boolean {
|
||||
return this.isFileReviewer(fileStatus) || this.isApprover();
|
||||
}
|
||||
@ -44,7 +36,7 @@ export class PermissionsService {
|
||||
}
|
||||
|
||||
canToggleAnalysis(fileStatus: FileStatusWrapper): boolean {
|
||||
return this.isManager() && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status);
|
||||
return this._userService.currentUser.isManager && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status);
|
||||
}
|
||||
|
||||
canReanalyseFile(fileStatus = this._activeFile): boolean {
|
||||
@ -55,7 +47,7 @@ export class PermissionsService {
|
||||
}
|
||||
|
||||
isFileReviewer(fileStatus = this._activeFile): boolean {
|
||||
return fileStatus.currentReviewer === this._userService.userId;
|
||||
return fileStatus.currentReviewer === this._userService.currentUser.id;
|
||||
}
|
||||
|
||||
canDeleteFile(fileStatus = this._activeFile, dossier?: DossierWrapper): boolean {
|
||||
@ -112,19 +104,19 @@ export class PermissionsService {
|
||||
return fileStatus?.isUnderReview && this.isReviewerOrApprover(fileStatus);
|
||||
}
|
||||
|
||||
isOwner(dossier = this._activeDossier, user = this.currentUser): boolean {
|
||||
isOwner(dossier = this._activeDossier, user = this._userService.currentUser): boolean {
|
||||
return dossier?.ownerId === user.id;
|
||||
}
|
||||
|
||||
isApprover(dossier = this._activeDossier, user = this.currentUser): boolean {
|
||||
isApprover(dossier = this._activeDossier, user = this._userService.currentUser): boolean {
|
||||
return dossier?.approverIds.indexOf(user.id) >= 0;
|
||||
}
|
||||
|
||||
isDossierReviewer(dossier = this._activeDossier, user = this.currentUser): boolean {
|
||||
isDossierReviewer(dossier = this._activeDossier, user = this._userService.currentUser): boolean {
|
||||
return this.isDossierMember(dossier, user) && !this.isApprover(dossier, user);
|
||||
}
|
||||
|
||||
isDossierMember(dossier = this._activeDossier, user = this.currentUser): boolean {
|
||||
isDossierMember(dossier = this._activeDossier, user = this._userService.currentUser): boolean {
|
||||
return dossier?.memberIds.includes(user.id);
|
||||
}
|
||||
|
||||
@ -156,29 +148,21 @@ export class PermissionsService {
|
||||
}
|
||||
|
||||
canDeleteDossier(dossier = this._activeDossier): boolean {
|
||||
return dossier.ownerId === this.currentUser.userId;
|
||||
return dossier.ownerId === this._userService.currentUser.id;
|
||||
}
|
||||
|
||||
isAdmin(user = this.currentUser): boolean {
|
||||
isAdmin(user = this._userService.currentUser): boolean {
|
||||
return user.isAdmin;
|
||||
}
|
||||
|
||||
isUserAdmin(user = this.currentUser): boolean {
|
||||
return user.isUserAdmin;
|
||||
}
|
||||
|
||||
isUser(user = this.currentUser): boolean {
|
||||
return user.isUser;
|
||||
}
|
||||
|
||||
canOcrFile(fileStatus = this._activeFile): boolean {
|
||||
return (
|
||||
!fileStatus.isExcluded && !fileStatus.ocrTime && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status)
|
||||
);
|
||||
}
|
||||
|
||||
canManageUsers(user?: UserWrapper): boolean {
|
||||
return this.isUserAdmin(user);
|
||||
canManageUsers(user: UserWrapper = this._userService.currentUser): boolean {
|
||||
return user.isUserAdmin;
|
||||
}
|
||||
|
||||
canAddComment(fileStatus = this._activeFile): boolean {
|
||||
@ -190,6 +174,6 @@ export class PermissionsService {
|
||||
}
|
||||
|
||||
canDeleteComment(comment: Comment, fileStatus = this._activeFile) {
|
||||
return (comment.user === this._userService.userId || this.isApprover()) && !fileStatus.isApproved;
|
||||
return (comment.user === this._userService.currentUser.id || this.isApprover()) && !fileStatus.isApproved;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { orderBy } from 'lodash';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
export const SortingOrders = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
} as const;
|
||||
|
||||
export type SortingOrder = keyof typeof SortingOrders;
|
||||
|
||||
export interface SortingOption {
|
||||
readonly order: SortingOrder;
|
||||
readonly column: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SortingService {
|
||||
private readonly _sortingOption$ = new BehaviorSubject<SortingOption>(null);
|
||||
readonly sortingOption$ = this._sortingOption$.asObservable();
|
||||
|
||||
get sortingOption(): SortingOption {
|
||||
return this._sortingOption$.getValue();
|
||||
}
|
||||
|
||||
setSortingOption(value: SortingOption): void {
|
||||
this._sortingOption$.next(value);
|
||||
}
|
||||
|
||||
sort<T>(values: T[], order?: string, column?: string): T[] {
|
||||
if (!values || !order) {
|
||||
return values;
|
||||
} // no array
|
||||
if (!column) {
|
||||
if (order === SortingOrders.asc) {
|
||||
return values.sort();
|
||||
} else {
|
||||
return values.sort().reverse();
|
||||
}
|
||||
} // sort 1d array
|
||||
if (values.length <= 1) {
|
||||
return values;
|
||||
} // array with only one item
|
||||
return orderBy(values, [column], [order]);
|
||||
}
|
||||
|
||||
defaultSort<T>(values: T[]) {
|
||||
return this.sort(values, this.sortingOption?.order, this.sortingOption?.column);
|
||||
}
|
||||
|
||||
toggleSort(column: string) {
|
||||
if (this.sortingOption.column === column) {
|
||||
this._sortingOption$.next({
|
||||
column,
|
||||
order: this.sortingOption.order === SortingOrders.asc ? SortingOrders.desc : SortingOrders.asc
|
||||
});
|
||||
} else {
|
||||
this._sortingOption$.next({ column, order: SortingOrders.asc });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
import { EventEmitter, Inject, Injectable } from '@angular/core';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { KeycloakProfile } from 'keycloak-js';
|
||||
import jwt_decode from 'jwt-decode';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { wipeCaches } from '@redaction/red-cache';
|
||||
import { BASE_HREF } from '../tokens';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
export interface ProfileModel {
|
||||
username?: string;
|
||||
@ -15,62 +16,28 @@ export interface ProfileModel {
|
||||
}
|
||||
|
||||
export class UserWrapper {
|
||||
name: string;
|
||||
constructor(private readonly _user: KeycloakProfile | User, public roles: string[], public id: string) {}
|
||||
|
||||
constructor(private readonly _currentUser: KeycloakProfile | User, public roles: string[], public id: string) {
|
||||
this.name = this.firstName && this.lastName ? `${this.firstName} ${this.lastName}` : this.username;
|
||||
}
|
||||
email = this._user.email;
|
||||
username = this._user.username || this.email;
|
||||
firstName = this._user.firstName;
|
||||
lastName = this._user.lastName;
|
||||
name = this.firstName && this.lastName ? `${this.firstName} ${this.lastName}` : this.username;
|
||||
searchKey = this.name + this.username + this.email;
|
||||
|
||||
get username() {
|
||||
return this._currentUser.username || this.email;
|
||||
}
|
||||
|
||||
get userId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
get email() {
|
||||
return this._currentUser.email;
|
||||
}
|
||||
|
||||
get firstName() {
|
||||
return this._currentUser.firstName;
|
||||
}
|
||||
|
||||
get lastName() {
|
||||
return this._currentUser.lastName;
|
||||
}
|
||||
|
||||
get searchKey() {
|
||||
return this.name + this.username + this.email;
|
||||
}
|
||||
|
||||
get isManager() {
|
||||
return this.roles.indexOf('RED_MANAGER') >= 0;
|
||||
}
|
||||
|
||||
get isUserAdmin() {
|
||||
return this.roles.indexOf('RED_USER_ADMIN') >= 0;
|
||||
}
|
||||
|
||||
get isUser() {
|
||||
return this.roles.indexOf('RED_USER') >= 0;
|
||||
}
|
||||
|
||||
get isAdmin() {
|
||||
return this.roles.indexOf('RED_ADMIN') >= 0;
|
||||
}
|
||||
|
||||
get hasAnyREDRoles() {
|
||||
return this.isUser || this.isManager || this.isAdmin || this.isUserAdmin;
|
||||
}
|
||||
isActive = this.roles.length > 0;
|
||||
isManager = this.roles.indexOf('RED_MANAGER') >= 0;
|
||||
isUserAdmin = this.roles.indexOf('RED_USER_ADMIN') >= 0;
|
||||
isUser = this.roles.indexOf('RED_USER') >= 0;
|
||||
isAdmin = this.roles.indexOf('RED_ADMIN') >= 0;
|
||||
hasAnyREDRoles = this.isUser || this.isManager || this.isAdmin || this.isUserAdmin;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserService {
|
||||
usersReloaded$: EventEmitter<any> = new EventEmitter<any>();
|
||||
usersReloaded$ = new Subject();
|
||||
private _currentUser: UserWrapper;
|
||||
private _allUsers: UserWrapper[];
|
||||
|
||||
@ -82,35 +49,18 @@ export class UserService {
|
||||
|
||||
private _allRedUsers: UserWrapper[];
|
||||
|
||||
get allRedUsers(): UserWrapper[] {
|
||||
return this._allRedUsers;
|
||||
}
|
||||
|
||||
get userId(): string {
|
||||
return this._currentUser.id;
|
||||
}
|
||||
|
||||
get managerUsers(): UserWrapper[] {
|
||||
return this._allRedUsers.filter(u => u.roles.indexOf('RED_MANAGER') >= 0);
|
||||
return this._allRedUsers.filter(user => user.isManager);
|
||||
}
|
||||
|
||||
get eligibleUsers(): UserWrapper[] {
|
||||
return this._allRedUsers.filter(u => u.roles.indexOf('RED_USER') >= 0 || u.roles.indexOf('RED_MANAGER') >= 0);
|
||||
return this._allRedUsers.filter(user => user.isUser || user.isManager);
|
||||
}
|
||||
|
||||
get user() {
|
||||
get currentUser(): UserWrapper {
|
||||
return this._currentUser;
|
||||
}
|
||||
|
||||
private static _hasAnyRedRole(user: UserWrapper) {
|
||||
return (
|
||||
user.roles.indexOf('RED_USER') >= 0 ||
|
||||
user.roles.indexOf('RED_MANAGER') >= 0 ||
|
||||
user.roles.indexOf('RED_ADMIN') >= 0 ||
|
||||
user.roles.indexOf('RED_USER_ADMIN') >= 0
|
||||
);
|
||||
}
|
||||
|
||||
logout() {
|
||||
wipeCaches().then();
|
||||
this._keycloakService.logout(window.location.origin + this._baseHref).then();
|
||||
@ -123,14 +73,14 @@ export class UserService {
|
||||
}
|
||||
|
||||
async loadAllUsers() {
|
||||
let allUsers = [];
|
||||
let allUsers: User[];
|
||||
if (this._currentUser.isUserAdmin) {
|
||||
allUsers = await this._userControllerService.getAllUsers().toPromise();
|
||||
} else {
|
||||
allUsers = await this._userControllerService.getUsers().toPromise();
|
||||
}
|
||||
this._allUsers = allUsers.map(user => new UserWrapper(user, user.roles, user.userId));
|
||||
this._allRedUsers = this._allUsers.filter(u => UserService._hasAnyRedRole(u));
|
||||
this._allRedUsers = this._allUsers.filter(user => user.hasAnyREDRoles);
|
||||
this.usersReloaded$.next();
|
||||
return this._allUsers;
|
||||
}
|
||||
@ -147,42 +97,27 @@ export class UserService {
|
||||
}
|
||||
|
||||
getRedUserById(id: string) {
|
||||
return this._allRedUsers.find(u => u.userId === id);
|
||||
return this._allRedUsers.find(u => u.id === id);
|
||||
}
|
||||
|
||||
getUserById(id: string) {
|
||||
return this._allUsers ? this._allUsers.find(u => u.userId === id) : this.getRedUserById(id);
|
||||
return this._allUsers ? this._allUsers.find(u => u.id === id) : this.getRedUserById(id);
|
||||
}
|
||||
|
||||
getNameForId(userId: string) {
|
||||
return this.getName(this.getUserById(userId));
|
||||
getNameForId(userId: string): string | undefined {
|
||||
const user = this.getUserById(userId);
|
||||
return user ? this.getName(user) : undefined;
|
||||
}
|
||||
|
||||
getName({ firstName, lastName, username }: User = {}) {
|
||||
getName({ firstName, lastName, username }: UserWrapper) {
|
||||
return firstName && lastName ? `${firstName} ${lastName}` : username;
|
||||
}
|
||||
|
||||
isManager(user: User | UserWrapper = this.user): boolean {
|
||||
isManager(user: UserWrapper = this._currentUser): boolean {
|
||||
return user.roles.indexOf('RED_MANAGER') >= 0;
|
||||
}
|
||||
|
||||
isUser(user: User | UserWrapper = this.user): boolean {
|
||||
return user.roles?.indexOf('RED_USER') >= 0;
|
||||
}
|
||||
|
||||
isUserAdmin(user: User | UserWrapper = this.user): boolean {
|
||||
return user.roles?.indexOf('RED_USER_ADMIN') >= 0;
|
||||
}
|
||||
|
||||
isAdmin(user: User | UserWrapper = this.user): boolean {
|
||||
return user.roles?.indexOf('RED_ADMIN') >= 0;
|
||||
}
|
||||
|
||||
isActive(user: User | UserWrapper = this.user): boolean {
|
||||
return user.roles?.length > 0;
|
||||
}
|
||||
|
||||
hasAnyRole(requiredRoles: string[], user: User | UserWrapper = this.user) {
|
||||
hasAnyRole(requiredRoles: string[], user: UserWrapper = this._currentUser) {
|
||||
if (requiredRoles?.length > 0) {
|
||||
for (const role of requiredRoles) if (user.roles.indexOf(role) >= 0) return true;
|
||||
|
||||
|
||||
@ -14,17 +14,17 @@ export class AppStateGuard implements CanActivate {
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
if (this._userService.user.isUserAdmin) {
|
||||
if (this._userService.currentUser.isUserAdmin) {
|
||||
await this._userService.loadUsersIfNecessary();
|
||||
}
|
||||
|
||||
if (this._userService.user.isUser || this._userService.user.isAdmin) {
|
||||
if (this._userService.currentUser.isUser || this._userService.currentUser.isAdmin) {
|
||||
await this._userService.loadUsersIfNecessary();
|
||||
await this._appStateService.loadDossierTemplatesIfNecessary();
|
||||
await this._appStateService.loadDictionaryDataIfNecessary();
|
||||
}
|
||||
|
||||
if (this._userService.isUser()) {
|
||||
if (this._userService.currentUser.isUser) {
|
||||
await this._appStateService.loadAllDossiersIfNecessary();
|
||||
}
|
||||
|
||||
|
||||
@ -15,13 +15,14 @@ import { Event, NavigationEnd, ResolveStart, Router } from '@angular/router';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { forkJoin, Observable, of } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import { FALLBACK_COLOR, hexToRgb, humanize } from '@utils/functions';
|
||||
import { FALLBACK_COLOR, hexToRgb } from '@utils/functions';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { DossierWrapper } from './model/dossier.wrapper';
|
||||
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
|
||||
import { DossierTemplateModelWrapper } from '@models/file/dossier-template-model.wrapper';
|
||||
import { DossiersService } from '../modules/dossier/services/dossiers.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { humanize } from '@iqser/common-ui';
|
||||
|
||||
export interface AppState {
|
||||
dossiers: DossierWrapper[];
|
||||
|
||||
@ -7,25 +7,6 @@ export function groupBy(xs: any[], key: string) {
|
||||
}, {});
|
||||
}
|
||||
|
||||
export function computerize(str: string) {
|
||||
if (!str) {
|
||||
return undefined;
|
||||
}
|
||||
const frags = str.toLowerCase().split(/[ \-_]+/);
|
||||
return frags.join('_');
|
||||
}
|
||||
|
||||
export function humanize(str: string, lowercase: boolean = true) {
|
||||
if (!str) {
|
||||
return undefined;
|
||||
}
|
||||
const frags = (lowercase ? str.toLowerCase() : str).split(/[ \-_]+/);
|
||||
for (let i = 0; i < frags.length; i++) {
|
||||
frags[i] = frags[i].charAt(0).toUpperCase() + frags[i].slice(1);
|
||||
}
|
||||
return frags.join(' ');
|
||||
}
|
||||
|
||||
export function hexToRgb(hex) {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result
|
||||
@ -37,14 +18,6 @@ export function hexToRgb(hex) {
|
||||
: null;
|
||||
}
|
||||
|
||||
export function keypress(key: string) {
|
||||
document.dispatchEvent(new KeyboardEvent('keypress', { key: key }));
|
||||
}
|
||||
|
||||
export function reference(x: any) {
|
||||
return x;
|
||||
}
|
||||
|
||||
export function getFirstRelevantTextPart(text, direction: 'FORWARD' | 'BACKWARD') {
|
||||
let spaceCount = 0;
|
||||
let accumulator = '';
|
||||
@ -58,11 +31,7 @@ export function getFirstRelevantTextPart(text, direction: 'FORWARD' | 'BACKWARD'
|
||||
|
||||
accumulator += char;
|
||||
|
||||
if (spaceCount >= 2) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return spaceCount >= 2;
|
||||
};
|
||||
|
||||
if (direction === 'FORWARD') {
|
||||
|
||||
@ -1016,7 +1016,7 @@
|
||||
"form": {
|
||||
"forgot-password": ""
|
||||
},
|
||||
"subtitle": "",
|
||||
"subtitle": " ",
|
||||
"title": ""
|
||||
},
|
||||
"subtitle": "Mit SMTP (Simple Mail Transfer Protocol) können Sie Ihre E-Mails über die angegebenen Servereinstellungen senden.",
|
||||
|
||||
@ -1028,7 +1028,7 @@
|
||||
"form": {
|
||||
"forgot-password": "Show Forgot password link on Login screen"
|
||||
},
|
||||
"subtitle": "",
|
||||
"subtitle": " ",
|
||||
"title": "General Configurations"
|
||||
},
|
||||
"subtitle": "SMTP (Simple Mail Transfer Protocol) enables you to send your emails through the specified server settings.",
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="14px" version="1.1" viewBox="0 0 6 14" width="6px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fill-rule="evenodd" id="Icons" stroke="none" stroke-width="1">
|
||||
<g id="Artboard" transform="translate(-1212.000000, -325.000000)">
|
||||
<polygon fill="currentColor" id="Fill-1" points="1215 338 1218 334 1212 334"></polygon>
|
||||
<polygon fill="#28324180" id="Fill-1"
|
||||
points="1215 330 1218 326 1212 326"
|
||||
transform="translate(1215.000000, 328.000000) rotate(-180.000000) translate(-1215.000000, -328.000000) "></polygon>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 669 B |
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