created trash screen with placeholders

This commit is contained in:
Dan Percic 2021-06-30 00:54:46 +03:00
parent 57d1b2c3d2
commit 9011427c06
7 changed files with 339 additions and 25 deletions

View File

@ -94,30 +94,26 @@
*ngIf="userPreferenceService.areDevFeaturesEnabled"
class="mr-8"
></redaction-notifications>
<redaction-user-button
[matMenuTriggerFor]="userMenu"
[showDot]="showPendingDownloadsDot"
[user]="user"
></redaction-user-button>
<mat-menu #userMenu="matMenu" class="user-menu" xPosition="before">
<button
[routerLink]="'/main/my-profile'"
mat-menu-item
translate="top-bar.navigation-items.my-account.children.my-profile"
></button>
<button
(click)="appStateService.reset()"
*ngIf="permissionsService.isManager() || permissionsService.isUserAdmin()"
[routerLink]="'/main/admin'"
mat-menu-item
translate="top-bar.navigation-items.my-account.children.admin"
></button>
<button
*ngIf="permissionsService.isUser()"
[routerLink]="'/main/downloads'"
mat-menu-item
translate="top-bar.navigation-items.my-account.children.downloads"
></button>
<mat-menu #userMenu="matMenu" xPosition="before">
<ng-container *ngFor="let item of userMenuItems">
<button
(click)="(item.action)"
*ngIf="item.show"
[routerLink]="item.routerLink"
mat-menu-item
translate
>
{{ item.name }}
</button>
</ng-container>
<button (click)="logout()" mat-menu-item>
<mat-icon svgIcon="red:logout"></mat-icon>
<span translate="top-bar.navigation-items.my-account.children.logout"> </span>

View File

@ -4,32 +4,58 @@ 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 { AppConfigService } from '@app-config/app-config.service';
import { Title } from '@angular/platform-browser';
import { FileDownloadService } from '@upload-download/services/file-download.service';
import { StatusOverlayService } from '@upload-download/services/status-overlay.service';
import { TranslateService } from '@ngx-translate/core';
interface MenuItem {
name: string;
routerLink?: string;
show: boolean;
action?: () => void;
}
@Component({
selector: 'redaction-base-screen',
templateUrl: './base-screen.component.html',
styleUrls: ['./base-screen.component.scss']
})
export class BaseScreenComponent {
readonly userMenuItems: MenuItem[] = [
{
name: 'top-bar.navigation-items.my-account.children.my-profile',
routerLink: '/main/my-profile',
show: true
},
{
name: 'top-bar.navigation-items.my-account.children.admin',
routerLink: '/main/admin',
show: this.permissionsService.isManager() || this.permissionsService.isUserAdmin(),
action: this.appStateService.reset
},
{
name: 'top-bar.navigation-items.my-account.children.downloads',
routerLink: '/main/downloads',
show: this.permissionsService.isUser()
},
{
name: 'top-bar.navigation-items.my-account.children.trash',
routerLink: '/main/admin/trash',
show: this.permissionsService.isManager() || this.permissionsService.isUserAdmin()
}
];
constructor(
readonly appStateService: AppStateService,
readonly permissionsService: PermissionsService,
readonly userPreferenceService: UserPreferenceService,
readonly titleService: Title,
readonly fileDownloadService: FileDownloadService,
private readonly _statusOverlayService: StatusOverlayService,
private readonly _appConfigService: AppConfigService,
private readonly _router: Router,
private readonly _userService: UserService,
private readonly _translateService: TranslateService
) {
_router.events.subscribe(() => {
this._dossiersView = this._router.url.indexOf('/main/dossiers') === 0;
this._dossiersView = _router.url.indexOf('/main/dossiers') === 0;
});
}
@ -54,4 +80,12 @@ export class BaseScreenComponent {
logout() {
this._userService.logout();
}
changeLanguage(language: string) {
this._languageService.changeLanguage(language);
}
trackByName(index: number, item: MenuItem) {
return item.name;
}
}

View File

@ -19,6 +19,7 @@ import { RouterModule } from '@angular/router';
import { SmtpConfigScreenComponent } from './screens/smtp-config/smtp-config-screen.component';
import { ReportsScreenComponent } from './screens/reports/reports-screen.component';
import { DossierAttributesListingScreenComponent } from './screens/dossier-attributes-listing/dossier-attributes-listing-screen.component';
import { TrashScreenComponent } from './screens/trash/trash-screen.component';
const routes = [
{ path: '', redirectTo: 'dossier-templates', pathMatch: 'full' },
@ -151,6 +152,14 @@ const routes = [
data: {
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
}
},
{
path: 'trash',
component: TrashScreenComponent,
canActivate: [CompositeRouteGuard],
data: {
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
}
}
];

View File

@ -38,6 +38,7 @@ import { ResetPasswordComponent } from './dialogs/add-edit-user-dialog/reset-pas
import { UserDetailsComponent } from './dialogs/add-edit-user-dialog/user-details/user-details.component';
import { AddEditDossierAttributeDialogComponent } from './dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component';
import { DossierAttributesListingScreenComponent } from './screens/dossier-attributes-listing/dossier-attributes-listing-screen.component';
import { TrashScreenComponent } from './screens/trash/trash-screen.component';
const dialogs = [
AddEditDossierTemplateDialogComponent,
@ -67,6 +68,7 @@ const screens = [
SmtpConfigScreenComponent,
ReportsScreenComponent,
DossierAttributesListingScreenComponent
TrashScreenComponent
];
const components = [

View File

@ -0,0 +1,187 @@
<section>
<div class="overlay-shadow"></div>
<div class="page-header">
<div class="breadcrumb" translate="trash.label"></div>
<redaction-circle-button
*ngIf="permissionsService.isUser()"
icon="red:close"
redactionNavigateLastDossiersScreen
tooltip="common.close"
tooltipPosition="below"
></redaction-circle-button>
</div>
<div class="red-content-inner">
<div class="content-container">
<div class="header-item">
<div class="select-all-container">
<redaction-round-checkbox
(click)="toggleSelectAll()"
[active]="areAllEntitiesSelected"
[indeterminate]="areSomeEntitiesSelected && !areAllEntitiesSelected"
></redaction-round-checkbox>
</div>
<span class="all-caps-label">
{{
'trash.table-header.title' | translate: { length: displayedEntities.length }
}}
</span>
<ng-container *ngIf="areSomeEntitiesSelected">
<redaction-circle-button
*ngIf="permissionsService.isAdmin()"
icon="red:trash"
tooltip="trash.bulk.delete"
type="dark-bg"
></redaction-circle-button>
</ng-container>
<div class="actions flex-1">
<redaction-input-with-action
[form]="searchForm"
[placeholder]="'trash.search'"
type="search"
></redaction-input-with-action>
</div>
</div>
<div
[class.no-data]="!allEntities.length"
class="table-header"
redactionSyncWidth="table-item"
>
<div class="select-oval-placeholder"></div>
<redaction-table-col-name
(toggleSort)="toggleSort($event)"
[activeSortingOption]="sortingOption"
[withSort]="true"
column="name"
label="trash.table-col-names.name"
></redaction-table-col-name>
<redaction-table-col-name
class="user-column"
label="trash.table-col-names.owner"
></redaction-table-col-name>
<redaction-table-col-name
(toggleSort)="toggleSort($event)"
[activeSortingOption]="sortingOption"
[withSort]="true"
column="dateDeleted"
label="trash.table-col-names.deleted-on"
></redaction-table-col-name>
<redaction-table-col-name
(toggleSort)="toggleSort($event)"
[activeSortingOption]="sortingOption"
[withSort]="true"
column="timeToRestore"
label="trash.table-col-names.time-to-restore"
></redaction-table-col-name>
<div class="scrollbar-placeholder"></div>
</div>
<redaction-empty-state
*ngIf="!allEntities.length"
icon="red:template"
screen="trash"
></redaction-empty-state>
<redaction-empty-state
*ngIf="allEntities.length && !displayedEntities.length"
screen="trash"
type="no-match"
></redaction-empty-state>
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
<div
*cdkVirtualFor="
let dw of displayedEntities
| sortBy: sortingOption.order:sortingOption.column
"
class="table-item"
>
<div (click)="toggleEntitySelected($event, dw)" class="selection-column">
<redaction-round-checkbox
[active]="isEntitySelected(dw)"
></redaction-round-checkbox>
</div>
<div class="filename">
<div
class="table-item-title heading"
[matTooltip]="dw.dossierName"
matTooltipPosition="above"
>
{{ dw.dossierName }}
</div>
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:template"></mat-icon>
{{ getDossierTemplate(dw).name }}
</div>
</div>
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:document"></mat-icon>
{{ dw.files.length }}
</div>
<div>
<mat-icon svgIcon="red:pages"></mat-icon>
{{ dw.totalNumberOfPages }}
</div>
<div>
<mat-icon svgIcon="red:user"></mat-icon>
{{ dw.numberOfMembers }}
</div>
<div>
<mat-icon svgIcon="red:calendar"></mat-icon>
{{ dw.dossier.date | date: 'mediumDate' }}
</div>
<div *ngIf="dw.dossier.dueDate">
<mat-icon svgIcon="red:lightning"></mat-icon>
{{ dw.dossier.dueDate | date: 'mediumDate' }}
</div>
</div>
</div>
<div class="user-column">
<redaction-initials-avatar
[userId]="dw.dossier.ownerId"
[withName]="true"
></redaction-initials-avatar>
</div>
<div class="small-label">
{{ dw.dossierDate | date: 'd MMM. yyyy' }}
</div>
<div>
<div class="small-label">
{{ dw.dossier.date | date: 'd MMM. yyyy' }}
</div>
<div class="action-buttons">
<redaction-circle-button
*ngIf="permissionsService.isManager()"
icon="red:undo"
tooltip="trash.action.restore"
type="dark-bg"
></redaction-circle-button>
<redaction-circle-button
*ngIf="permissionsService.isManager()"
icon="red:trash"
tooltip="trash.action.delete"
type="dark-bg"
></redaction-circle-button>
</div>
</div>
<div class="scrollbar-placeholder"></div>
</div>
</cdk-virtual-scroll-viewport>
</div>
</div>
</section>

View File

@ -0,0 +1,44 @@
@import '../../../../../assets/styles/red-variables';
@import '../../../../../assets/styles/red-mixins';
.header-item {
padding: 0 24px 0 10px;
}
redaction-table-col-name::ng-deep {
> div {
padding-left: 10px !important;
}
}
.content-container {
cdk-virtual-scroll-viewport {
::ng-deep.cdk-virtual-scroll-content-wrapper {
grid-template-columns: auto 1fr 1fr 1fr 1fr 11px;
.table-item {
> div:not(.scrollbar-placeholder) {
padding-left: 10px;
.stats-subtitle {
margin-top: 4px;
}
.table-item-title {
max-width: 100%;
}
}
}
}
&.has-scrollbar:hover {
::ng-deep.cdk-virtual-scroll-content-wrapper {
grid-template-columns: auto 1fr 1fr 1fr 1fr;
}
}
}
}
.page-header .actions > *:not(:last-child) {
margin-right: 16px;
}

View File

@ -0,0 +1,42 @@
import { Component, Injector, OnInit } from '@angular/core';
import { BaseListingComponent } from '@shared/base/base-listing.component';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
import { UserPreferenceService } from '@services/user-preference.service';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { DossierTemplateModel } from '@redaction/red-ui-http';
@Component({
templateUrl: './trash-screen.component.html',
styleUrls: ['./trash-screen.component.scss']
})
export class TrashScreenComponent extends BaseListingComponent<DossierWrapper> implements OnInit {
readonly itemSize = 85;
protected readonly _searchKey = 'name';
protected readonly _selectionKey = 'dossierId';
protected readonly _sortKey = 'dossier-listing';
constructor(
private readonly _dialogService: AdminDialogService,
private readonly _appStateService: AppStateService,
readonly permissionsService: PermissionsService,
protected readonly _injector: Injector
) {
super(_injector);
}
ngOnInit(): void {
this.loadDossierTemplatesData();
}
loadDossierTemplatesData() {
this.allEntities = this._appStateService.allDossiers;
this._executeSearchImmediately();
}
getDossierTemplate(dw: DossierWrapper): DossierTemplateModel {
return this._appStateService.getDossierTemplateById(dw.dossier.dossierTemplateId);
}
}