Skip to content

Commit 83f72f1

Browse files
committed
feat(ui): disable button if not available in task-viewer
Signed-off-by: Thomas Bétrancourt <thomas@betrancourt.net>
1 parent 946a2c2 commit 83f72f1

File tree

2 files changed

+128
-29
lines changed

2 files changed

+128
-29
lines changed

ui/dashboard/projects/utask-lib/src/lib/@routes/task/task.component.ts

Lines changed: 110 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router';
33
import get from 'lodash-es/get';
44
import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
55
import { NzModalService } from 'ng-zorro-antd/modal';
6-
import { BehaviorSubject, combineLatest, interval, Subscription } from 'rxjs';
6+
import { BehaviorSubject, combineLatest, interval, of, Subscription } from 'rxjs';
77
import { concatMap, filter, map, switchMap } from 'rxjs/operators';
88
import { NzNotificationService } from 'ng-zorro-antd/notification';
99
import { ApiService, UTaskLibOptions } from '../../@services/api.service';
@@ -30,19 +30,124 @@ export class TaskComponent implements OnInit, OnDestroy {
3030
private _task$ = new BehaviorSubject<Task | null>(null);
3131
readonly task$ = this._task$.asObservable();
3232

33-
readonly template$ = this.task$.pipe(switchMap(task => this.api.template.get(task.template_name)));
33+
readonly template$ = this.task$.pipe(switchMap(task => {
34+
if (!task) {
35+
return of(null);
36+
}
37+
return this.api.template.get(task.template_name)
38+
}));
3439

3540
private _resolution$ = new BehaviorSubject<Resolution | null>(null);
3641
readonly resolution$ = this._resolution$.asObservable();
3742

38-
readonly startOver$ = combineLatest([this.meta$, this.template$, this.resolution$]).pipe(map(([meta, template, resolution]) => {
39-
if (['PAUSED', 'CANCELLED', 'BLOCKED_BADREQUEST'].indexOf(resolution?.state) === -1) {
43+
private _isResolver$ = combineLatest([
44+
this.meta$, this.template$, this.task$, this.resolution$
45+
]).pipe(map(([meta, template, task, resolution]) => {
46+
if (meta?.user_is_admin) {
47+
return true;
48+
}
49+
50+
// check if the current user is declared as resolver in the task template
51+
if (meta && (template?.allowed_resolver_usernames ?? []).includes(meta.username)) {
52+
return true;
53+
}
54+
55+
// check if the current user has at least one group declared as resolver in the task template
56+
if (meta && (template?.allowed_resolver_groups ?? []).some(v => meta.user_groups.includes(v))) {
57+
return true;
58+
}
59+
60+
// check if the current user is declared as resolver in the task
61+
if (meta && (task?.resolver_usernames ?? []).includes(meta.username)) {
62+
return true;
63+
}
64+
65+
// check if the current user has at least one group declared as resolver in the task
66+
if (meta && (task?.resolver_groups ?? []).some(v => meta.user_groups.includes(v))) {
67+
return true;
68+
}
69+
70+
// check if the current user is the resolution resolver
71+
if (meta && resolution && meta.username === resolution.resolver_username) {
72+
return true;
73+
}
74+
75+
return false;
76+
}))
77+
78+
readonly canStartOver$ = combineLatest([
79+
this.meta$, this.template$, this.resolution$, this._isResolver$
80+
]).pipe(map(([meta, template, resolution, isResolver]) => {
81+
if (!['PAUSED', 'CANCELLED', 'BLOCKED_BADREQUEST'].includes(resolution?.state)) {
4082
return false;
4183
}
4284

43-
return !!meta?.user_is_admin || !!template?.allow_task_start_over;
85+
if (meta?.user_is_admin) {
86+
return true;
87+
}
88+
89+
if (!template?.allow_task_start_over) {
90+
return false;
91+
}
92+
93+
return isResolver;
4494
}));
4595

96+
readonly canRun$ = combineLatest([this.resolution$, this._isResolver$]).pipe(map(([resolution, isResolver]) => {
97+
if (['CANCELLED', 'RUNNING', 'DONE'].includes(resolution?.state)) {
98+
return false;
99+
}
100+
101+
return isResolver;
102+
}));
103+
104+
readonly canPause$ = combineLatest([this.resolution$, this._isResolver$]).pipe(map(([resolution, isResolver]) => {
105+
if (['CANCELLED', 'RUNNING', 'DONE', 'PAUSED'].includes(resolution?.state)) {
106+
return false;
107+
}
108+
109+
return isResolver;
110+
}));
111+
112+
readonly canExtend$ = combineLatest([this.resolution$, this._isResolver$]).pipe(map(([resolution, isResolver]) => {
113+
if (resolution?.state !== 'BLOCKED_MAXRETRIES') {
114+
return false;
115+
}
116+
117+
return isResolver;
118+
}));
119+
120+
readonly canCancel$ = combineLatest([this.resolution$, this._isResolver$]).pipe(map(([resolution, isResolver]) => {
121+
if (['CANCELLED', 'RUNNING', 'DONE'].includes(resolution?.state)) {
122+
return false;
123+
}
124+
125+
return isResolver;
126+
}));
127+
128+
readonly canEdit$ = combineLatest([this.resolution$, this.meta$]).pipe(map(([resolution, meta]) => {
129+
if (resolution?.state !== 'PAUSED') {
130+
return false;
131+
}
132+
133+
return !!meta?.user_is_admin;
134+
}));
135+
136+
readonly canEditRequest$ = combineLatest([this.resolution$, this._isResolver$]).pipe(map(([resolution, isResolver]) => {
137+
if (resolution?.state !== 'PAUSED') {
138+
return false;
139+
}
140+
141+
return isResolver;
142+
}));;
143+
144+
readonly canDeleteRequest$ = combineLatest([this.task$, this.meta$]).pipe(map(([task, meta]) => {
145+
if (['RUNNING', 'BLOCKED'].includes(task?.state)) {
146+
return false;
147+
}
148+
149+
return !!meta?.user_is_admin;
150+
}));
46151

47152
validateResolveForm!: FormGroup;
48153
validateRejectForm!: FormGroup;

ui/dashboard/projects/utask-lib/src/lib/@routes/task/task.html

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,15 @@
6464
Request - {{(task$ | async).id}}
6565
</div>
6666
<nz-button-group nzSize="small" app-box-header-extra>
67-
<button type="button" nz-button title="View as code" (click)="previewTask(); $event.stopPropagation();"><i
68-
nz-icon nzType="file-text"></i></button>
69-
<button type="button" nz-button title="Edit the task"
70-
(click)="editRequest(); $event.stopPropagation();"><i nz-icon nzType="edit"></i></button>
71-
<button type="button" nz-button title="Delete the task"
72-
(click)="deleteTask(); $event.stopPropagation();"><i nz-icon nzType="delete"></i></button>
67+
<button type="button" nz-button title="View as code" (click)="previewTask(); $event.stopPropagation();">
68+
<i nz-icon nzType="file-text"></i>
69+
</button>
70+
<button type="button" nz-button title="Edit the task" (click)="editRequest(); $event.stopPropagation();" [disabled]="!(canEditRequest$ | async)">
71+
<i nz-icon nzType="edit"></i>
72+
</button>
73+
<button type="button" nz-button title="Delete the task" (click)="deleteTask(); $event.stopPropagation();" [disabled]="!(canDeleteRequest$ | async)">
74+
<i nz-icon nzType="delete"></i>
75+
</button>
7376
</nz-button-group>
7477
<div app-box-content>
7578
<nz-descriptions *ngIf="(task$ | async).input" nzBordered [nzSize]="'small'" [nzColumn]="1">
@@ -113,38 +116,28 @@
113116
<div app-box-header>
114117
Execution -
115118
<small>{{resolution.id}}</small> -
116-
<small class="bloc_status resolution_state_{{resolution.state}}">{{resolution.state}}{{resolution.state
117-
===
118-
'ERROR' ? ' (retrying)' : ''}}</small>
119+
<small class="bloc_status resolution_state_{{resolution.state}}">{{resolution.state}}{{resolution.state === 'ERROR' ? ' (retrying)' : ''}}</small>
119120
<span *ngIf="loaders.execution || loaders.refreshTask">&nbsp;<i nz-icon nzType="loading"></i></span>
120121
</div>
121122
<div app-box-header-extra>
122123
<nz-button-group nzSize="small">
123-
<button type="button" nz-button title="Run the waiting steps" (click)="$event.stopPropagation(); runResolution(resolution)">
124+
<button type="button" nz-button title="Run the waiting steps" (click)="$event.stopPropagation(); runResolution(resolution)" [disabled]="!(canRun$ | async)">
124125
<i nz-icon nzType="caret-right"></i>
125126
</button>
126-
<button type="button" nz-button title="Start over the task" (click)="$event.stopPropagation(); display.restartTask = true" [disabled]="!(startOver$ | async)">
127+
<button type="button" nz-button title="Start over the task" (click)="$event.stopPropagation(); display.restartTask = true" [disabled]="!(canStartOver$ | async)">
127128
<i nz-icon nzType="rollback"></i>
128129
</button>
129-
<button type="button" nz-button title="Cancel the resolution" (click)="$event.stopPropagation(); cancelResolution(resolution)">
130+
<button type="button" nz-button title="Cancel the resolution" (click)="$event.stopPropagation(); cancelResolution(resolution)" [disabled]="!(canCancel$ | async)">
130131
<i nz-icon nzType="stop"></i>
131132
</button>
132133
<button type="button" nz-button nz-dropdown [nzDropdownMenu]="menu" [nzPlacement]="'bottomRight'" (click)="$event.stopPropagation()">More</button>
133134
</nz-button-group>
134135
<nz-dropdown-menu #menu="nzDropdownMenu">
135136
<ul nz-menu>
136-
<li nz-menu-item (click)="previewResolution()">
137-
View as code
138-
</li>
139-
<li nz-menu-item (click)="pauseResolution(resolution)">
140-
Pause
141-
</li>
142-
<li nz-menu-item (click)="extendResolution(resolution)">
143-
Extend</li>
144-
<li nz-menu-item (click)="editResolution(resolution)">Edit</li>
145-
<li nz-menu-item
146-
[nzDisabled]="['PAUSED', 'CANCELLED', 'BLOCKED_BADREQUEST'].indexOf(resolution.state) == -1"
147-
(click)="display.restartTask = true;$event.stopPropagation();">Start over</li>
137+
<li nz-menu-item (click)="previewResolution()">View as code</li>
138+
<li nz-menu-item [nzDisabled]="!(canPause$ | async)" (click)="pauseResolution(resolution)">Pause</li>
139+
<li nz-menu-item [nzDisabled]="!(canExtend$ | async)" (click)="extendResolution(resolution)">Extend</li>
140+
<li nz-menu-item [nzDisabled]="!(canEdit$ | async)" (click)="editResolution(resolution)">Edit</li>
148141
</ul>
149142
</nz-dropdown-menu>
150143
</div>
@@ -170,6 +163,7 @@
170163
</lib-utask-steps-list>
171164
</div>
172165
<div nz-col [nzSpan]="16">
166+
<nz-alert *ngIf="canStartOver$ | async" nzBanner nzMessage="It appears that the task is stuck. If you're experiencing difficulties or need to correct the inputs, you can simply click the 'Start Over' button to reset and try again"></nz-alert>
173167
<lib-utask-steps-viewer [resolution]="resolution" (select)="selectStepFromViewer($event)">
174168
</lib-utask-steps-viewer>
175169
</div>

0 commit comments

Comments
 (0)