Pull request #262: Trash screen & dossier templates listing improvements
Merge in RED/ui from trash-screen to master * commit 'dcf62b512e5e566ea49a4c3580ac03a906c995d1': fix rebase Fixes Dossier templates listing header Trash screen & some other improvements
This commit is contained in:
commit
4741eebbc6
@ -7,7 +7,7 @@
|
||||
[bulkActions]="bulkActions"
|
||||
[hasEmptyColumn]="true"
|
||||
[selectionEnabled]="true"
|
||||
[tableColumnConfigs]="tableColConfigs"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
[tableHeaderLabel]="tableHeaderLabel"
|
||||
></redaction-table-header>
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import { DownloadControllerService } from '@redaction/red-ui-http';
|
||||
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 { LoadingService } from '@services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-downloads-list-screen',
|
||||
@ -13,11 +14,11 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
providers: [...DefaultListingServices]
|
||||
})
|
||||
export class DownloadsListScreenComponent extends BaseListingComponent<DownloadStatusWrapper> implements OnInit {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly itemSize = 80;
|
||||
protected readonly _primaryKey = 'storageId';
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly tableHeaderLabel = _('downloads-list.table-header.title');
|
||||
readonly tableColConfigs: TableColumnConfig<DownloadStatusWrapper>[] = [
|
||||
readonly tableColumnConfigs: TableColumnConfig<DownloadStatusWrapper>[] = [
|
||||
{ label: _('downloads-list.table-col-names.name') },
|
||||
{ label: _('downloads-list.table-col-names.size') },
|
||||
{ label: _('downloads-list.table-col-names.date') },
|
||||
@ -27,22 +28,28 @@ export class DownloadsListScreenComponent extends BaseListingComponent<DownloadS
|
||||
constructor(
|
||||
readonly fileDownloadService: FileDownloadService,
|
||||
private readonly _downloadControllerService: DownloadControllerService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
protected readonly _injector: Injector
|
||||
) {
|
||||
super(_injector);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this._loadData();
|
||||
this._loadingService.loadWhile(this._loadData());
|
||||
}
|
||||
|
||||
async downloadItem(download: DownloadStatusWrapper) {
|
||||
await this.fileDownloadService.performDownload(download);
|
||||
downloadItem(download: DownloadStatusWrapper) {
|
||||
this._loadingService.loadWhile(this.fileDownloadService.performDownload(download));
|
||||
}
|
||||
|
||||
async deleteItems(downloads?: DownloadStatusWrapper[]) {
|
||||
deleteItems(downloads?: DownloadStatusWrapper[]) {
|
||||
this._loadingService.loadWhile(this._deleteItems(downloads));
|
||||
}
|
||||
|
||||
private async _deleteItems(downloads?: DownloadStatusWrapper[]) {
|
||||
const storageIds = (downloads || this.entitiesService.selected).map(d => d.storageId);
|
||||
await this._downloadControllerService.deleteDownload({ storageIds }).toPromise();
|
||||
this.entitiesService.setSelected([]);
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
|
||||
@ -33,8 +33,6 @@ export class AddEditDossierTemplateDialogComponent implements OnInit {
|
||||
private _previousValidFrom: Moment;
|
||||
private _previousValidTo: Moment;
|
||||
|
||||
reportTemplateValueMapper = (reportTemplate: ReportTemplate) => reportTemplate.templateId;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
@ -68,11 +66,6 @@ export class AddEditDossierTemplateDialogComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.availableReportTypes =
|
||||
(await this._reportTemplateController.getAvailableReportTemplates(this.dossierTemplate?.dossierTemplateId).toPromise()) || [];
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
if (!this.dossierTemplate) return true;
|
||||
|
||||
@ -105,6 +98,13 @@ export class AddEditDossierTemplateDialogComponent implements OnInit {
|
||||
return false;
|
||||
}
|
||||
|
||||
reportTemplateValueMapper = (reportTemplate: ReportTemplate) => reportTemplate.templateId;
|
||||
|
||||
async ngOnInit() {
|
||||
this.availableReportTypes =
|
||||
(await this._reportTemplateController.getAvailableReportTemplates(this.dossierTemplate?.dossierTemplateId).toPromise()) || [];
|
||||
}
|
||||
|
||||
async saveDossierTemplate() {
|
||||
const dossierTemplate = {
|
||||
dossierTemplateId: this.dossierTemplate?.dossierTemplateId,
|
||||
@ -115,7 +115,7 @@ export class AddEditDossierTemplateDialogComponent implements OnInit {
|
||||
await this._dossierTemplateController.createOrUpdateDossierTemplate(dossierTemplate).toPromise();
|
||||
await this._appStateService.loadAllDossierTemplates();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this.dialogRef.close(dossierTemplate);
|
||||
this.dialogRef.close(true);
|
||||
}
|
||||
|
||||
private _applyValidityIntervalConstraints(value): boolean {
|
||||
|
||||
@ -8,28 +8,12 @@
|
||||
|
||||
<div class="red-content-inner">
|
||||
<div class="content-container">
|
||||
<div class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'dossier-templates-listing.table-header.title'
|
||||
| translate: { length: (entitiesService.displayedLength$ | async) }
|
||||
}}
|
||||
</span>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteTemplatesDialog($event)"
|
||||
*ngIf="canBulkDelete$(currentUser.isAdmin) | async"
|
||||
[tooltip]="'dossier-templates-listing.bulk.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
></iqser-circle-button>
|
||||
|
||||
<redaction-table-header
|
||||
[bulkActions]="bulkActions"
|
||||
[selectionEnabled]="true"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
[tableHeaderLabel]="tableHeaderLabel"
|
||||
>
|
||||
<div class="actions flex-1">
|
||||
<redaction-input-with-action
|
||||
[form]="searchService.searchForm"
|
||||
@ -41,37 +25,11 @@
|
||||
(action)="openAddDossierTemplateDialog()"
|
||||
*ngIf="currentUser.isAdmin && userPreferenceService.areDevFeaturesEnabled"
|
||||
[label]="'dossier-templates-listing.add-new' | translate"
|
||||
icon="red:plus"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="red:plus"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-templates-listing.table-col-names.name' | translate"
|
||||
[withSort]="true"
|
||||
column="name"
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-templates-listing.table-col-names.created-by' | translate"
|
||||
class="user-column"
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-templates-listing.table-col-names.created-on' | translate"
|
||||
[withSort]="true"
|
||||
column="dateAdded"
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'dossier-templates-listing.table-col-names.modified-on' | translate"
|
||||
[withSort]="true"
|
||||
column="dateModified"
|
||||
></iqser-table-column-name>
|
||||
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
</redaction-table-header>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
@ -132,3 +90,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
(action)="openBulkDeleteTemplatesDialog($event)"
|
||||
*ngIf="canBulkDelete$(currentUser.isAdmin) | async"
|
||||
[tooltip]="'dossier-templates-listing.bulk.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:trash"
|
||||
></iqser-circle-button>
|
||||
</ng-template>
|
||||
|
||||
@ -5,9 +5,10 @@ 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 { CircleButtonTypes, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { CircleButtonTypes, IconButtonTypes, TableColumnConfig } from '@iqser/common-ui';
|
||||
import { BaseListingComponent, DefaultListingServices } from '@shared/base/base-listing.component';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-templates-listing-screen.component.html',
|
||||
@ -20,6 +21,25 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableHeaderLabel = _('dossier-templates-listing.table-header.title');
|
||||
tableColumnConfigs: TableColumnConfig<DossierTemplateModelWrapper>[] = [
|
||||
{
|
||||
label: _('dossier-templates-listing.table-col-names.name'),
|
||||
withSort: true,
|
||||
column: 'name'
|
||||
},
|
||||
{ label: _('dossier-templates-listing.table-col-names.created-by'), class: 'user-column' },
|
||||
{
|
||||
label: _('dossier-templates-listing.table-col-names.created-on'),
|
||||
withSort: true,
|
||||
column: 'dateAdded'
|
||||
},
|
||||
{
|
||||
label: _('dossier-templates-listing.table-col-names.modified-on'),
|
||||
withSort: true,
|
||||
column: 'dateModified'
|
||||
}
|
||||
];
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
@ -37,35 +57,32 @@ export class DossierTemplatesListingScreenComponent extends BaseListingComponent
|
||||
this.loadDossierTemplatesData();
|
||||
}
|
||||
|
||||
openDeleteTemplatesDialog($event?: MouseEvent) {
|
||||
openBulkDeleteTemplatesDialog($event?: MouseEvent) {
|
||||
return this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
this._loadingService.start();
|
||||
await this._dossierTemplateControllerService
|
||||
.deleteDossierTemplates(this.entitiesService.selected.map(d => d.dossierTemplateId))
|
||||
.toPromise();
|
||||
this.entitiesService.setSelected([]);
|
||||
await this._appStateService.loadAllDossierTemplates();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this.loadDossierTemplatesData();
|
||||
this._loadingService.loadWhile(this._deleteTemplates());
|
||||
});
|
||||
}
|
||||
|
||||
loadDossierTemplatesData() {
|
||||
this._loadingService.start();
|
||||
this._appStateService.reset();
|
||||
this.entitiesService.setEntities(this._appStateService.dossierTemplates);
|
||||
this._loadDossierTemplateStats();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
openAddDossierTemplateDialog() {
|
||||
this._dialogService.openDialog('addEditDossierTemplate', null, null, async newDossierTemplate => {
|
||||
if (newDossierTemplate) {
|
||||
this.loadDossierTemplatesData();
|
||||
}
|
||||
this._dialogService.openDialog('addEditDossierTemplate', null, null, () => {
|
||||
this.loadDossierTemplatesData();
|
||||
});
|
||||
}
|
||||
|
||||
private async _deleteTemplates(templateIds: string[] = this.entitiesService.selected.map(d => d.dossierTemplateId)) {
|
||||
await this._dossierTemplateControllerService.deleteDossierTemplates(templateIds).toPromise();
|
||||
this.entitiesService.setSelected([]);
|
||||
await this._appStateService.loadAllDossierTemplates();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this.loadDossierTemplatesData();
|
||||
}
|
||||
|
||||
private _loadDossierTemplateStats() {
|
||||
this.entitiesService.all.forEach(rs => {
|
||||
const dictionaries = this._appStateService.dictionaryData[rs.dossierTemplateId];
|
||||
|
||||
@ -5,55 +5,12 @@
|
||||
|
||||
<div class="red-content-inner">
|
||||
<div class="content-container">
|
||||
<div class="header-item">
|
||||
<iqser-round-checkbox
|
||||
(click)="toggleSelectAll()"
|
||||
[active]="entitiesService.areAllSelected$ | async"
|
||||
[indeterminate]="entitiesService.notAllSelected$ | async"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{ 'trash.table-header.title' | translate: { length: (entitiesService.displayedLength$ | async) } }}
|
||||
</span>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="bulkRestore()"
|
||||
*ngIf="entitiesService.areSomeSelected$ | async"
|
||||
[tooltip]="'trash.bulk.restore' | translate"
|
||||
icon="red:put-back"
|
||||
[type]="circleButtonTypes.dark"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="bulkDelete()"
|
||||
*ngIf="entitiesService.areSomeSelected$ | async"
|
||||
[tooltip]="'trash.bulk.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
|
||||
<div [class.no-data]="entitiesService.noData$ | async" class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<iqser-table-column-name
|
||||
[label]="'trash.table-col-names.name' | translate"
|
||||
[withSort]="true"
|
||||
column="dossierName"
|
||||
></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"
|
||||
></iqser-table-column-name>
|
||||
<iqser-table-column-name
|
||||
[label]="'trash.table-col-names.time-to-restore' | translate"
|
||||
[withSort]="true"
|
||||
column="softDeletedTime"
|
||||
></iqser-table-column-name>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
<redaction-table-header
|
||||
[bulkActions]="bulkActions"
|
||||
[selectionEnabled]="true"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
[tableHeaderLabel]="tableHeaderLabel"
|
||||
></redaction-table-header>
|
||||
|
||||
<redaction-empty-state
|
||||
*ngIf="entitiesService.noData$ | async"
|
||||
@ -99,22 +56,22 @@
|
||||
|
||||
<div>
|
||||
<div class="small-label">
|
||||
{{ getRestoreDate(entity.softDeletedTime) | date: 'timeFromNow' }}
|
||||
{{ entity.restoreDate | date: 'timeFromNow' }}
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<iqser-circle-button
|
||||
*ngIf="canRestore(entity.softDeletedTime)"
|
||||
(action)="bulkRestore([entity.dossierId])"
|
||||
(action)="restore([entity])"
|
||||
*ngIf="entity.canRestore"
|
||||
[tooltip]="'trash.action.restore' | translate"
|
||||
icon="red:put-back"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:put-back"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="bulkDelete([entity])"
|
||||
(action)="hardDelete([entity])"
|
||||
[tooltip]="'trash.action.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
@ -125,3 +82,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<div class="bulk-actions">
|
||||
<iqser-circle-button
|
||||
(action)="restore()"
|
||||
*ngIf="canRestoreSelected$ | async"
|
||||
[tooltip]="'trash.bulk.restore' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:put-back"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="hardDelete()"
|
||||
*ngIf="entitiesService.areSomeSelected$ | async"
|
||||
[tooltip]="'trash.bulk.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
@import '../../../../../assets/styles/variables';
|
||||
@import '../../../../../assets/styles/red-mixins';
|
||||
|
||||
.header-item {
|
||||
padding: 0 24px 0 10px;
|
||||
.bulk-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
iqser-circle-button:not(:last-child) {
|
||||
margin-right: 4px !important;
|
||||
> *:not(:last-child) {
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,15 +4,20 @@ 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 { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { CircleButtonTypes, TableColumnConfig } 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 { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { getLeftDateTime } from '@utils/functions';
|
||||
|
||||
const HOURS_IN_A_DAY = 24;
|
||||
const MINUTES_IN_AN_HOUR = 60;
|
||||
interface DossierListItem extends Dossier {
|
||||
readonly canRestore: boolean;
|
||||
readonly restoreDate: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: './trash-screen.component.html',
|
||||
@ -20,11 +25,34 @@ const MINUTES_IN_AN_HOUR = 60;
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [...DefaultListingServices, DossiersService]
|
||||
})
|
||||
export class TrashScreenComponent extends BaseListingComponent<Dossier> implements OnInit {
|
||||
export class TrashScreenComponent extends BaseListingComponent<DossierListItem> implements OnInit {
|
||||
readonly itemSize = 80;
|
||||
protected readonly _primaryKey = 'dossierName';
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly tableHeaderLabel = 'trash.table-header.title';
|
||||
readonly canRestoreSelected$ = this._canRestoreSelected$;
|
||||
private readonly _deleteRetentionHours = this._appConfigService.getConfig(AppConfigKey.DELETE_RETENTION_HOURS);
|
||||
readonly tableColumnConfigs: TableColumnConfig<DossierListItem>[] = [
|
||||
{
|
||||
label: _('trash.table-col-names.name'),
|
||||
withSort: true,
|
||||
column: 'dossierName'
|
||||
},
|
||||
{
|
||||
label: _('trash.table-col-names.owner'),
|
||||
class: 'user-column'
|
||||
},
|
||||
{
|
||||
label: _('trash.table-col-names.deleted-on'),
|
||||
withSort: true,
|
||||
column: 'softDeletedTime'
|
||||
},
|
||||
{
|
||||
label: _('trash.table-col-names.time-to-restore'),
|
||||
withSort: true,
|
||||
column: 'softDeletedTime'
|
||||
}
|
||||
];
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
@ -37,52 +65,24 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
|
||||
super(_injector);
|
||||
}
|
||||
|
||||
private get _canRestoreSelected$(): Observable<boolean> {
|
||||
return this.entitiesService.selected$.pipe(
|
||||
map(entities => entities.length && !entities.find(dossier => !dossier.canRestore)),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
|
||||
await this.loadDossierTemplatesData();
|
||||
|
||||
await this._loadDossiersData();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async loadDossierTemplatesData(): Promise<void> {
|
||||
this.entitiesService.setEntities(await this._dossiersService.getDeleted());
|
||||
}
|
||||
|
||||
canRestore(softDeletedTime: string): boolean {
|
||||
const date = moment(this.getRestoreDate(softDeletedTime));
|
||||
const now = new Date(Date.now());
|
||||
|
||||
const daysLeft = date.diff(now, 'days');
|
||||
const hoursFromNow = date.diff(now, 'hours');
|
||||
const hoursLeft = hoursFromNow - HOURS_IN_A_DAY * daysLeft;
|
||||
const minutesFromNow = date.diff(now, 'minutes');
|
||||
const minutesLeft = minutesFromNow - HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR * daysLeft;
|
||||
|
||||
return daysLeft >= 0 && hoursLeft >= 0 && minutesLeft > 0;
|
||||
}
|
||||
|
||||
getRestoreDate(softDeletedTime: string): string {
|
||||
private _getRestoreDate(softDeletedTime: string): string {
|
||||
return moment(softDeletedTime).add(this._deleteRetentionHours, 'hours').toISOString();
|
||||
}
|
||||
|
||||
bulkDelete(dossiers = this.entitiesService.selected) {
|
||||
this._loadingService.loadWhile(this._hardDelete(dossiers));
|
||||
}
|
||||
|
||||
bulkRestore(dossierIds = this.entitiesService.selected.map(d => d.dossierId)) {
|
||||
this._loadingService.loadWhile(this._restore(dossierIds));
|
||||
}
|
||||
|
||||
private async _restore(dossierIds: string[]): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await this._dossiersService.restore(dossierIds);
|
||||
this._removeFromList(dossierIds);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
private async _hardDelete(dossiers: Dossier[]): Promise<void> {
|
||||
const period = this._appConfigService.getConfig('DELETE_RETENTION_HOURS');
|
||||
hardDelete(dossiers = this.entitiesService.selected) {
|
||||
const data = new ConfirmationDialogInput({
|
||||
title: dossiers.length > 1 ? _('confirmation-dialog.delete-dossier.title-alt') : _('confirmation-dialog.delete-dossier.title'),
|
||||
titleColor: TitleColors.PRIMARY,
|
||||
@ -91,17 +91,55 @@ export class TrashScreenComponent extends BaseListingComponent<Dossier> implemen
|
||||
confirmationText: _('confirmation-dialog.delete-dossier.confirmation-text'),
|
||||
requireInput: true,
|
||||
denyText: _('confirmation-dialog.delete-dossier.deny-text'),
|
||||
translateParams: { dossierName: dossiers[0].dossierName, period: period }
|
||||
translateParams: {
|
||||
dossierName: dossiers[0].dossierName,
|
||||
period: this._deleteRetentionHours
|
||||
}
|
||||
});
|
||||
this._adminDialogService.openDialog('confirm', null, data, async () => {
|
||||
this._loadingService.start();
|
||||
const dossierIds = dossiers.map(d => d.dossierId);
|
||||
await this._dossiersService.hardDelete(dossierIds);
|
||||
this._removeFromList(dossierIds);
|
||||
this._loadingService.stop();
|
||||
this._loadingService.loadWhile(this._hardDelete(dossiers));
|
||||
});
|
||||
}
|
||||
|
||||
restore(dossiers = this.entitiesService.selected) {
|
||||
this._loadingService.loadWhile(this._restore(dossiers));
|
||||
}
|
||||
|
||||
private async _loadDossiersData(): Promise<void> {
|
||||
this.entitiesService.setEntities(this._toListItems(await this._dossiersService.getDeleted()));
|
||||
}
|
||||
|
||||
private _canRestoreDossier(restoreDate: string): boolean {
|
||||
const { daysLeft, hoursLeft, minutesLeft } = getLeftDateTime(restoreDate);
|
||||
|
||||
return daysLeft >= 0 && hoursLeft >= 0 && minutesLeft > 0;
|
||||
}
|
||||
|
||||
private _toListItems(dossiers: Dossier[]): DossierListItem[] {
|
||||
return dossiers.map(dossier => this._toListItem(dossier));
|
||||
}
|
||||
|
||||
private _toListItem(dossier: Dossier): DossierListItem {
|
||||
const restoreDate = this._getRestoreDate(dossier.softDeletedTime);
|
||||
return {
|
||||
...dossier,
|
||||
restoreDate,
|
||||
canRestore: this._canRestoreDossier(restoreDate)
|
||||
};
|
||||
}
|
||||
|
||||
private async _restore(dossiers: DossierListItem[]): Promise<void> {
|
||||
const dossierIds = dossiers.map(d => d.dossierId);
|
||||
await this._dossiersService.restore(dossierIds);
|
||||
this._removeFromList(dossierIds);
|
||||
}
|
||||
|
||||
private async _hardDelete(dossiers: DossierListItem[]) {
|
||||
const dossierIds = dossiers.map(d => d.dossierId);
|
||||
await this._dossiersService.hardDelete(dossierIds);
|
||||
this._removeFromList(dossierIds);
|
||||
}
|
||||
|
||||
private _removeFromList(ids: string[]): void {
|
||||
const entities = this.entitiesService.all.filter(e => !ids.includes(e.dossierId));
|
||||
this.entitiesService.setEntities(entities);
|
||||
|
||||
@ -41,7 +41,7 @@ export class DossierListingScreenComponent
|
||||
extends BaseListingComponent<DossierWrapper>
|
||||
implements OnInit, AfterViewInit, OnDestroy, OnAttach, OnDetach
|
||||
{
|
||||
readonly itemSize = 95;
|
||||
readonly itemSize = 85;
|
||||
protected readonly _primaryKey = 'dossierName';
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableHeaderLabel = _('dossier-listing.table-header.title');
|
||||
|
||||
@ -13,9 +13,17 @@
|
||||
<ng-container [ngTemplateOutlet]="bulkActions"></ng-container>
|
||||
|
||||
<redaction-quick-filters></redaction-quick-filters>
|
||||
|
||||
<!-- Custom content-->
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
||||
<div [class.selection-enabled]="selectionEnabled" class="table-header" redactionSyncWidth="table-item">
|
||||
<div
|
||||
[class.no-data]="entitiesService.noData$ | async"
|
||||
[class.selection-enabled]="selectionEnabled"
|
||||
class="table-header"
|
||||
redactionSyncWidth="table-item"
|
||||
>
|
||||
<div *ngIf="selectionEnabled" class="select-oval-placeholder"></div>
|
||||
|
||||
<iqser-table-column-name
|
||||
|
||||
@ -3,9 +3,8 @@ import * as moment from 'moment';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DatePipe as BaseDatePipe } from '@angular/common';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { getLeftDateTime } from '@utils/functions';
|
||||
|
||||
const HOURS_IN_A_DAY = 24;
|
||||
const MINUTES_IN_AN_HOUR = 60;
|
||||
const MONTH_NAMES = {
|
||||
0: _('months.jan'),
|
||||
1: _('months.feb'),
|
||||
@ -38,15 +37,8 @@ export class DatePipe extends BaseDatePipe implements PipeTransform {
|
||||
return super.transform(value, format, timezone, locale);
|
||||
}
|
||||
|
||||
private _getTimeFromNow(item: string) {
|
||||
const date = moment(item);
|
||||
const now = new Date(Date.now());
|
||||
|
||||
const daysLeft = date.diff(now, 'days');
|
||||
const hoursFromNow = date.diff(now, 'hours');
|
||||
const hoursLeft = hoursFromNow - HOURS_IN_A_DAY * daysLeft;
|
||||
const minutesFromNow = date.diff(now, 'minutes');
|
||||
const minutesLeft = minutesFromNow - HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR * daysLeft;
|
||||
private _getTimeFromNow(value: string) {
|
||||
const { daysLeft, hoursLeft, minutesLeft } = getLeftDateTime(value);
|
||||
|
||||
if (daysLeft === 0 && hoursLeft === 0 && minutesLeft > 0) return this._translateService.instant('time.less-than-an-hour');
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import * as moment from 'moment';
|
||||
|
||||
export const FALLBACK_COLOR = '#CCCCCC';
|
||||
|
||||
export function groupBy(xs: any[], key: string) {
|
||||
@ -67,3 +69,19 @@ export function toNumber(string) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const HOURS_IN_A_DAY = 24;
|
||||
const MINUTES_IN_AN_HOUR = 60;
|
||||
|
||||
export function getLeftDateTime(ISOString: string) {
|
||||
const date = moment(ISOString);
|
||||
const now = new Date(Date.now());
|
||||
|
||||
const daysLeft = date.diff(now, 'days');
|
||||
const hoursFromNow = date.diff(now, 'hours');
|
||||
const hoursLeft = hoursFromNow - HOURS_IN_A_DAY * daysLeft;
|
||||
const minutesFromNow = date.diff(now, 'minutes');
|
||||
const minutesLeft = minutesFromNow - HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR * daysLeft;
|
||||
|
||||
return { daysLeft, hoursLeft, minutesLeft };
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"OAUTH_URL": "https://red-staging.iqser.cloud/auth/realms/redaction",
|
||||
"API_URL": "https://red-staging.iqser.cloud/redaction-gateway-v1",
|
||||
"OAUTH_URL": "https://dev-06.iqser.cloud/auth/realms/redaction",
|
||||
"API_URL": "https://dev-06.iqser.cloud/redaction-gateway-v1",
|
||||
"OAUTH_CLIENT_ID": "redaction",
|
||||
"BACKEND_APP_VERSION": "4.4.40",
|
||||
"FRONTEND_APP_VERSION": "1.1",
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1"
|
||||
<svg height="14px" version="1.1" viewBox="0 0 14 14" width="14px"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<title>B99F3D5E-879A-47E3-A8C7-84877EE418F3</title>
|
||||
<g id="04.Search-all-in-Document" transform="translate(-319.000000, -144.000000)">
|
||||
<g id="Group-30" transform="translate(295.000000, 121.000000)">
|
||||
<g id="collapse" transform="translate(24.000000, 23.000000)" fill="currentColor"
|
||||
fill-rule="nonzero">
|
||||
<g fill="currentColor" fill-rule="nonzero" id="collapse"
|
||||
transform="translate(24.000000, 23.000000)">
|
||||
<path
|
||||
d="M2.38,0 L2.38,7.98 L10.5,7.98 L8.75,6.16 L9.73,5.18 L13.16,8.68 L9.73,12.18 L8.75,11.2 L10.5,9.38 L1.96,9.38 L1.959,9.379 L0.98,9.38 L0.98,0 L2.38,0 Z"
|
||||
id="Combined-Shape"></path>
|
||||
|
||||
|
Before Width: | Height: | Size: 781 B After Width: | Height: | Size: 725 B |
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="14px" version="1.1" viewBox="0 0 14 14" width="14px"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<title>711C9D82-CAA8-47BE-954A-A9DA22CE85E6</title>
|
||||
<g fill="currentColor" fill-rule="evenodd" id="Trash" stroke="none" stroke-width="1">
|
||||
<g id="05.-Trash-bulk-actions" transform="translate(-133.000000, -130.000000)">
|
||||
<g id="Group-36" transform="translate(0.000000, 112.000000)">
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.0 KiB |
Loading…
x
Reference in New Issue
Block a user