mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 871: #1662 TK gelöschte Beiträge
#1662 TK gelöschte Beiträge Related work items: #1662
This commit is contained in:
committed by
Lorenz Hilpert
parent
7c10dde089
commit
4961e580c5
@@ -1,3 +1,3 @@
|
||||
export type ProcessingStatusType = 'Approved' | 'InProcess' | 'Completed' | 'Overdue' | 'Archived' | 'Uncompleted';
|
||||
export type ProcessingStatusType = 'Approved' | 'InProcess' | 'Completed' | 'Overdue' | 'Archived' | 'Uncompleted' | 'Removed';
|
||||
|
||||
export type ProcessingStatusList = ProcessingStatusType[];
|
||||
|
||||
@@ -168,6 +168,10 @@ export class DomainTaskCalendarService {
|
||||
processingStatusList.push('Archived');
|
||||
}
|
||||
|
||||
if (!!(processingStatus & 32)) {
|
||||
processingStatusList.push('Removed');
|
||||
}
|
||||
|
||||
if (!!(processingStatus & 64)) {
|
||||
processingStatusList.push('Uncompleted');
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
:host {
|
||||
@apply flex flex-col;
|
||||
|
||||
&.Removed {
|
||||
@apply opacity-30;
|
||||
}
|
||||
}
|
||||
|
||||
.info-header {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Clipboard } from '@angular/cdk/clipboard';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { Component, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges, Optional } from '@angular/core';
|
||||
import { Component, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges, Optional, HostBinding } from '@angular/core';
|
||||
import { DomainTaskCalendarService } from '@domain/task-calendar';
|
||||
import { FileDTO } from '@swagger/checkout';
|
||||
import { DisplayInfoDTO } from '@swagger/eis';
|
||||
@@ -108,6 +108,11 @@ export class TaskInfoComponent implements OnChanges {
|
||||
)
|
||||
);
|
||||
|
||||
@HostBinding('class')
|
||||
get statusClass() {
|
||||
return this.domainTaskCalendarService.getProcessingStatusList(this.info);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private dateAdapter: DateAdapter,
|
||||
private datePipe: DatePipe,
|
||||
|
||||
@@ -42,3 +42,11 @@
|
||||
@apply opacity-30;
|
||||
}
|
||||
}
|
||||
|
||||
.task-list ::ng-deep page-task-list-item.Removed {
|
||||
.date,
|
||||
.shirt-size,
|
||||
.task-content {
|
||||
@apply opacity-30 line-through;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,8 @@ export class TaskListComponent {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
})
|
||||
}),
|
||||
map((list) => list.sort(this.moveRemovedToEnd.bind(this)))
|
||||
);
|
||||
|
||||
ongoingItems$ = combineLatest([this.items$, this.selected$]).pipe(
|
||||
@@ -81,7 +82,8 @@ export class TaskListComponent {
|
||||
selectedItems$ = combineLatest([this.items$, this.selected$]).pipe(
|
||||
map(([items, date]) => items.filter((item) => this.dateAdapter.equals(this.domainTaskCalendarService.getDisplayInfoDate(item), date))),
|
||||
// Sortierung der aufgaben nach Rot => Gelb => Grau => Grün
|
||||
map((list) => this.sort(list, ['Overdue', 'InProcess', 'Approved', 'Completed']))
|
||||
map((list) => this.sort(list, ['Overdue', 'InProcess', 'Approved', 'Completed', 'Removed'])),
|
||||
map((list) => list.sort(this.moveRemovedToEnd.bind(this)))
|
||||
);
|
||||
|
||||
@Output()
|
||||
@@ -95,6 +97,21 @@ export class TaskListComponent {
|
||||
private domainPrinterService: DomainPrinterService
|
||||
) {}
|
||||
|
||||
moveRemovedToEnd(a: DisplayInfoDTO, b: DisplayInfoDTO) {
|
||||
const statusA = this.domainTaskCalendarService.getProcessingStatusList(a)?.includes('Removed');
|
||||
const statusB = this.domainTaskCalendarService.getProcessingStatusList(b)?.includes('Removed');
|
||||
|
||||
if (statusA && statusB) {
|
||||
return 0;
|
||||
} else if (statusA && !statusB) {
|
||||
return 1;
|
||||
} else if (!statusA && statusB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Array of DisplayInfoDTO, sorted by ProcessingStatus
|
||||
* Ignores Overdue if Task is already Completed
|
||||
@@ -105,8 +122,9 @@ export class TaskListComponent {
|
||||
*/
|
||||
sort(items: DisplayInfoDTO[], order: ProcessingStatusList) {
|
||||
let result = [...items];
|
||||
const reversedOrder = [...order].reverse();
|
||||
|
||||
for (const status of [...order].reverse()) {
|
||||
for (const status of reversedOrder) {
|
||||
result = result?.sort((a, b) => {
|
||||
const statusA = this.domainTaskCalendarService.getProcessingStatusList(a);
|
||||
const statusB = this.domainTaskCalendarService.getProcessingStatusList(b);
|
||||
|
||||
@@ -4,4 +4,10 @@
|
||||
<ui-icon *ngIf="info?.updateComment" icon="refresh" size="22px"></ui-icon>
|
||||
</div>
|
||||
<page-task-info [info]="info"></page-task-info>
|
||||
<button type="button" (click)="close()"><ui-icon icon="close" size="16px"></ui-icon></button>
|
||||
<button class="btn-close" type="button" (click)="close()"><ui-icon icon="close" size="16px"></ui-icon></button>
|
||||
|
||||
<div class="actions">
|
||||
<button *ngIf="showOpenSuccessorCta$ | async" class="btn-cta" type="button" (click)="close(info.successor?.id)">
|
||||
Zur neuen Aufgabe
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
:host {
|
||||
@apply flex flex-col relative;
|
||||
|
||||
&.Removed {
|
||||
h1 {
|
||||
@apply opacity-30 line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -18,10 +24,18 @@ h3 {
|
||||
@apply absolute m-0 -top-4 p-4 pl-0 text-regular text-active-branch uppercase;
|
||||
}
|
||||
|
||||
button {
|
||||
.btn-close {
|
||||
@apply absolute -top-4 -right-4 p-4 outline-none border-none bg-transparent;
|
||||
|
||||
ui-icon {
|
||||
@apply text-inactive-branch;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
@apply text-center mb-5 mt-6 sticky bottom-1;
|
||||
|
||||
.btn-cta {
|
||||
@apply bg-brand text-white font-bold text-lg outline-none border-none rounded-full px-6 py-3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { Component, ChangeDetectionStrategy, HostBinding } from '@angular/core';
|
||||
import { DomainTaskCalendarService } from '@domain/task-calendar';
|
||||
import { DisplayInfoDTO } from '@swagger/eis';
|
||||
import { UiModalRef } from '@ui/modal';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { combineLatest, ReplaySubject } from 'rxjs';
|
||||
import { map, shareReplay } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'page-info-modal',
|
||||
@@ -12,11 +14,31 @@ import { Subscription } from 'rxjs';
|
||||
export class InfoModalComponent {
|
||||
info: DisplayInfoDTO;
|
||||
|
||||
constructor(private modalRef: UiModalRef<DisplayInfoDTO>) {
|
||||
this.info = this.modalRef.data;
|
||||
info$ = new ReplaySubject<DisplayInfoDTO>();
|
||||
|
||||
processingStatus$ = this.info$.pipe(
|
||||
map((info) => this.domainTaskCalendarService.getProcessingStatusList(info)),
|
||||
shareReplay()
|
||||
);
|
||||
|
||||
showOpenSuccessorCta$ = combineLatest([this.processingStatus$, this.info$]).pipe(
|
||||
map(([processingStatus, info]) => processingStatus.includes('Removed') && !!info.successor?.id)
|
||||
);
|
||||
|
||||
@HostBinding('class')
|
||||
get statusClass() {
|
||||
return this.domainTaskCalendarService.getProcessingStatusList(this.info);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.modalRef.close();
|
||||
constructor(
|
||||
private modalRef: UiModalRef<{ successorId: number }, DisplayInfoDTO>,
|
||||
private domainTaskCalendarService: DomainTaskCalendarService
|
||||
) {
|
||||
this.info = this.modalRef.data;
|
||||
this.info$.next(this.info);
|
||||
}
|
||||
|
||||
close(successorId: number = undefined) {
|
||||
this.modalRef.close({ successorId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,10 @@
|
||||
<ui-icon *ngIf="info?.updateComment" icon="refresh" size="22px"></ui-icon>
|
||||
</div>
|
||||
<page-task-info [info]="info" showTaskDate="true"></page-task-info>
|
||||
<button type="button" (click)="close()"><ui-icon icon="close" size="16px"></ui-icon></button>
|
||||
<button class="btn-close" type="button" (click)="close()"><ui-icon icon="close" size="16px"></ui-icon></button>
|
||||
|
||||
<div class="actions">
|
||||
<button *ngIf="showOpenSuccessorCta$ | async" class="btn-cta" type="button" (click)="close(info.successor?.id)">
|
||||
Zur neuen Aufgabe
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
:host {
|
||||
@apply flex flex-col relative;
|
||||
|
||||
&.Removed {
|
||||
h1 {
|
||||
@apply opacity-30 line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -18,10 +24,18 @@ h3 {
|
||||
@apply absolute m-0 -top-4 p-4 pl-0 text-regular text-active-branch uppercase;
|
||||
}
|
||||
|
||||
button {
|
||||
.btn-close {
|
||||
@apply absolute top-0 right-0 outline-none border-none bg-transparent;
|
||||
|
||||
ui-icon {
|
||||
@apply text-inactive-branch;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
@apply text-center mb-5 mt-6 sticky bottom-1;
|
||||
|
||||
.btn-cta {
|
||||
@apply bg-brand text-white font-bold text-lg outline-none border-none rounded-full px-6 py-3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, HostBinding } from '@angular/core';
|
||||
import { DomainTaskCalendarService } from '@domain/task-calendar';
|
||||
import { DisplayInfoDTO } from '@swagger/eis';
|
||||
import { UiModalRef } from '@ui/modal';
|
||||
import { combineLatest, ReplaySubject } from 'rxjs';
|
||||
import { map, shareReplay } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'page-preinfo-modal',
|
||||
@@ -11,11 +14,31 @@ import { UiModalRef } from '@ui/modal';
|
||||
export class PreInfoModalComponent {
|
||||
info: DisplayInfoDTO;
|
||||
|
||||
constructor(private modalRef: UiModalRef<DisplayInfoDTO>) {
|
||||
this.info = this.modalRef.data;
|
||||
info$ = new ReplaySubject<DisplayInfoDTO>();
|
||||
|
||||
processingStatus$ = this.info$.pipe(
|
||||
map((info) => this.domainTaskCalendarService.getProcessingStatusList(info)),
|
||||
shareReplay()
|
||||
);
|
||||
|
||||
showOpenSuccessorCta$ = combineLatest([this.processingStatus$, this.info$]).pipe(
|
||||
map(([processingStatus, info]) => processingStatus.includes('Removed') && !!info.successor?.id)
|
||||
);
|
||||
|
||||
@HostBinding('class')
|
||||
get statusClass() {
|
||||
return this.domainTaskCalendarService.getProcessingStatusList(this.info);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.modalRef.close();
|
||||
constructor(
|
||||
private modalRef: UiModalRef<{ successorId: number }, DisplayInfoDTO>,
|
||||
private domainTaskCalendarService: DomainTaskCalendarService
|
||||
) {
|
||||
this.info = this.modalRef.data;
|
||||
this.info$.next(this.info);
|
||||
}
|
||||
|
||||
close(successorId: number = undefined) {
|
||||
this.modalRef.close({ successorId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
<button *ngIf="showCompleteEditCta$ | async" class="btn-cta" type="button" (click)="completeEdit()" [disabled]="editDisabled$ | async">
|
||||
Bearbeitung abschließen
|
||||
</button>
|
||||
<button *ngIf="showOpenSuccessorCta$ | async" class="btn-cta" type="button" (click)="close(info.successor?.id)">
|
||||
Zur neuen Aufgabe
|
||||
</button>
|
||||
<div *ngIf="showCameraCta$ | async" [disabled]="editDisabled$ | async">
|
||||
<ng-container>
|
||||
<div class="camera-hint">Bitte fotografieren Sie die Präsentation, um die<br />Aufgabe abschließen zu können</div>
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
:host {
|
||||
@apply flex flex-col relative;
|
||||
|
||||
&.Removed {
|
||||
.header {
|
||||
@apply opacity-30 line-through;
|
||||
}
|
||||
.status {
|
||||
@apply opacity-30;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, HostBinding, ViewChild } from '@angular/core';
|
||||
import { DomainTaskCalendarService } from '@domain/task-calendar';
|
||||
import { DisplayInfoDTO } from '@swagger/eis';
|
||||
import { DateAdapter } from '@ui/common';
|
||||
@@ -6,7 +6,7 @@ import { UiMessageModalComponent, UiModalRef, UiModalService } from '@ui/modal';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
import { NativeContainerService } from 'native-container';
|
||||
import { combineLatest, ReplaySubject } from 'rxjs';
|
||||
import { map, tap, shareReplay, switchMap } from 'rxjs/operators';
|
||||
import { map, shareReplay, switchMap } from 'rxjs/operators';
|
||||
import { CameraCaptureModalComponent } from '../camera/camera-capture-modal.component';
|
||||
|
||||
@Component({
|
||||
@@ -44,6 +44,11 @@ export class TaskModalComponent {
|
||||
})
|
||||
);
|
||||
|
||||
@HostBinding('class')
|
||||
get statusClass() {
|
||||
return this.domainTaskCalendarService.getProcessingStatusList(this.info);
|
||||
}
|
||||
|
||||
editDisabled$ = this.info$.pipe(
|
||||
map((info) => {
|
||||
if (info.publicationDate && info.taskDate && info.taskOverdueDate) {
|
||||
@@ -65,22 +70,37 @@ export class TaskModalComponent {
|
||||
showStartEditCta$ = this.processingStatus$.pipe(
|
||||
map(
|
||||
(processingStatus) =>
|
||||
!processingStatus.includes('Uncompleted') && !processingStatus.includes('InProcess') && !processingStatus.includes('Completed')
|
||||
!processingStatus.includes('Uncompleted') &&
|
||||
!processingStatus.includes('InProcess') &&
|
||||
!processingStatus.includes('Completed') &&
|
||||
!processingStatus.includes('Removed')
|
||||
)
|
||||
);
|
||||
|
||||
showCompleteEditCta$ = combineLatest([this.processingStatus$, this.info$]).pipe(
|
||||
map(([processingStatus, info]) => processingStatus.includes('InProcess') && !info.requiresImageOnConfirmation)
|
||||
map(
|
||||
([processingStatus, info]) =>
|
||||
processingStatus.includes('InProcess') && !info.requiresImageOnConfirmation && !processingStatus.includes('Removed')
|
||||
)
|
||||
);
|
||||
|
||||
showCameraCta$ = combineLatest([this.processingStatus$, this.info$]).pipe(
|
||||
map(([processingStatus, info]) => processingStatus.includes('InProcess') && info.requiresImageOnConfirmation)
|
||||
map(
|
||||
([processingStatus, info]) =>
|
||||
processingStatus.includes('InProcess') && info.requiresImageOnConfirmation && !processingStatus.includes('Removed')
|
||||
)
|
||||
);
|
||||
|
||||
showResetEditCta$ = this.processingStatus$.pipe(map((processingStatus) => processingStatus.includes('Completed')));
|
||||
showResetEditCta$ = this.processingStatus$.pipe(
|
||||
map((processingStatus) => processingStatus.includes('Completed') && !processingStatus.includes('Removed'))
|
||||
);
|
||||
|
||||
showOpenSuccessorCta$ = combineLatest([this.processingStatus$, this.info$]).pipe(
|
||||
map(([processingStatus, info]) => processingStatus.includes('Removed') && !!info.successor?.id)
|
||||
);
|
||||
|
||||
constructor(
|
||||
private modalRef: UiModalRef<DisplayInfoDTO>,
|
||||
private modalRef: UiModalRef<{ successorId: number }, DisplayInfoDTO>,
|
||||
private domainTaskCalendarService: DomainTaskCalendarService,
|
||||
private uiModal: UiModalService,
|
||||
private nativeContainer: NativeContainerService,
|
||||
@@ -90,8 +110,8 @@ export class TaskModalComponent {
|
||||
this.info$.next(this.info);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.modalRef.close();
|
||||
close(successorId: number = undefined) {
|
||||
this.modalRef.close({ successorId });
|
||||
}
|
||||
|
||||
async startEdit() {
|
||||
|
||||
@@ -5,10 +5,10 @@ import { DisplayInfoDTO, InputDTO, ResponseArgsOfIEnumerableOfInputDTO } from '@
|
||||
import { CalendarIndicator } from '@ui/calendar';
|
||||
import { DateAdapter } from '@ui/common';
|
||||
import { Filter, FilterOption, SelectFilter, UiFilterMappingService } from '@ui/filter';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { UiMessageModalComponent, UiModalRef, UiModalResult, UiModalService } from '@ui/modal';
|
||||
import { clone } from 'lodash';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged, switchMap, withLatestFrom } from 'rxjs/operators';
|
||||
import { Observable } from 'rxjs';
|
||||
import { debounceTime, map, switchMap, withLatestFrom } from 'rxjs/operators';
|
||||
import { InfoModalComponent } from './modals/info/info-modal.component';
|
||||
import { PreInfoModalComponent } from './modals/preinfo/preinfo-modal.component';
|
||||
import { TaskModalComponent } from './modals/task/task-modal.component';
|
||||
@@ -172,36 +172,45 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> {
|
||||
|
||||
open(displayInfoDTO: DisplayInfoDTO) {
|
||||
const type = this.domainTaskCalendarService.getInfoType(displayInfoDTO);
|
||||
let taskModalRef: UiModalRef<{ successorId: number }, DisplayInfoDTO>;
|
||||
|
||||
switch (type) {
|
||||
case 'Info':
|
||||
this.uiModal.open({
|
||||
taskModalRef = this.uiModal.open({
|
||||
content: InfoModalComponent,
|
||||
data: displayInfoDTO,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'PreInfo':
|
||||
this.uiModal.open({
|
||||
taskModalRef = this.uiModal.open({
|
||||
content: PreInfoModalComponent,
|
||||
data: displayInfoDTO,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'Task':
|
||||
const taskModalRef = this.uiModal.open<string, DisplayInfoDTO>({
|
||||
taskModalRef = this.uiModal.open({
|
||||
content: TaskModalComponent,
|
||||
data: displayInfoDTO,
|
||||
});
|
||||
|
||||
taskModalRef.afterClosed$.subscribe({
|
||||
complete: () => this.loadItems(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Logik welcher Dialog soll angezeigt werden
|
||||
taskModalRef?.afterClosed$.subscribe({
|
||||
next: async (result: UiModalResult<{ successorId: number }>) => {
|
||||
if (result.data?.successorId) {
|
||||
const info = await this.domainTaskCalendarService
|
||||
.getInfoById({ infoId: result.data.successorId })
|
||||
.pipe(map((res) => res.result))
|
||||
.toPromise();
|
||||
if (info) {
|
||||
this.open(info);
|
||||
}
|
||||
}
|
||||
},
|
||||
complete: () => this.loadItems(),
|
||||
});
|
||||
}
|
||||
|
||||
mapInputArrayToFilterArray(source: InputDTO[]): SelectFilter[] {
|
||||
|
||||
Reference in New Issue
Block a user