Feedback for triggered actions
Change-Id: Ib93f12bbec4813b7231bb6cdfee2c970db4ff69b
diff --git a/polygerrit-ui/app/api/checks.ts b/polygerrit-ui/app/api/checks.ts
index 799d1f7..4a5ef7e 100644
--- a/polygerrit-ui/app/api/checks.ts
+++ b/polygerrit-ui/app/api/checks.ts
@@ -247,7 +247,7 @@
checkName: string | undefined,
/** Identical to 'name' property of Action entity. */
actionName: string
-) => Promise<ActionResult>;
+) => Promise<ActionResult> | undefined;
export interface ActionResult {
/** An empty errorMessage means success. */
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-tab.ts b/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
index ad4f2ae..e5386f4 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
@@ -28,6 +28,7 @@
allActions$,
allResults$,
allRuns$,
+ someProvidersAreLoading$,
} from '../../services/checks/checks-model';
import './gr-checks-runs';
import './gr-checks-results';
@@ -41,6 +42,10 @@
import {checkRequiredProperty} from '../../utils/common-util';
import {RunSelectedEvent} from './gr-checks-runs';
import {ChecksTabState} from '../../types/events';
+import {fireAlert} from '../../utils/event-util';
+import {appContext} from '../../services/app-context';
+import {from, timer} from 'rxjs';
+import {takeUntil} from 'rxjs/operators';
/**
* The "Checks" tab on the Gerrit change page. Gets its data from plugins that
@@ -64,9 +69,14 @@
@property()
changeNum: NumericChangeId | undefined = undefined;
+ @property()
+ someProvidersAreLoading = false;
+
@internalProperty()
selectedRuns: string[] = [];
+ private readonly checksService = appContext.checksService;
+
constructor() {
super();
this.subscribe('runs', allRuns$);
@@ -74,6 +84,7 @@
this.subscribe('results', allResults$);
this.subscribe('currentPatchNum', currentPatchNum$);
this.subscribe('changeNum', changeNum$);
+ this.subscribe('someProvidersAreLoading', someProvidersAreLoading$);
this.addEventListener('action-triggered', (e: ActionTriggeredEvent) =>
this.handleActionTriggered(e.detail.action, e.detail.run)
@@ -131,6 +142,7 @@
},
]}"
></gr-dropdown-list>
+ <span ?hidden="${!this.someProvidersAreLoading}">Loading...</span>
</div>
<div class="right">
${this.actions.map(this.renderAction)}
@@ -170,10 +182,7 @@
handleActionTriggered(action: Action, run?: CheckRun) {
if (!this.changeNum) return;
if (!this.currentPatchNum) return;
- // TODO(brohlfs): The callback is supposed to be returning a promise.
- // A toast should be displayed until the promise completes. And then the
- // data should be updated.
- action.callback(
+ const promise = action.callback(
this.changeNum,
this.currentPatchNum as number,
run?.attempt,
@@ -181,6 +190,25 @@
run?.checkName,
action.name
);
+ // Plugins *should* return a promise, but you never know ...
+ if (promise?.then) {
+ const prefix = `Triggering action '${action.name}'`;
+ fireAlert(this, `${prefix} ...`);
+ from(promise)
+ // If the action takes longer than 5 seconds, then most likely the
+ // user is either not interested or the result not relevant anymore.
+ .pipe(takeUntil(timer(5000)))
+ .subscribe(result => {
+ if (result.errorMessage) {
+ fireAlert(this, `${prefix} failed with ${result.errorMessage}.`);
+ } else {
+ fireAlert(this, `${prefix} successful.`);
+ this.checksService.reloadForCheck(run?.checkName);
+ }
+ });
+ } else {
+ fireAlert(this, `Action '${action.name}' triggered.`);
+ }
}
handleRunSelected(e: RunSelectedEvent) {
diff --git a/polygerrit-ui/app/services/checks/checks-model.ts b/polygerrit-ui/app/services/checks/checks-model.ts
index 28aca73..d8dc688 100644
--- a/polygerrit-ui/app/services/checks/checks-model.ts
+++ b/polygerrit-ui/app/services/checks/checks-model.ts
@@ -87,6 +87,18 @@
})
);
+export const checkToPluginMap$ = checksState$.pipe(
+ map(state => {
+ const map = new Map<string, string>();
+ for (const [pluginName, providerState] of Object.entries(state)) {
+ for (const run of providerState.runs) {
+ map.set(run.checkName, pluginName);
+ }
+ }
+ return map;
+ })
+);
+
export const allResults$ = checksState$.pipe(
map(state => {
return Object.values(state)
diff --git a/polygerrit-ui/app/services/checks/checks-service.ts b/polygerrit-ui/app/services/checks/checks-service.ts
index b11eada..d2a4775 100644
--- a/polygerrit-ui/app/services/checks/checks-service.ts
+++ b/polygerrit-ui/app/services/checks/checks-service.ts
@@ -32,6 +32,7 @@
import {change$, currentPatchNum$} from '../change/change-model';
import {
updateStateSetLoading,
+ checkToPluginMap$,
updateStateSetProvider,
updateStateSetResults,
} from './checks-model';
@@ -51,6 +52,12 @@
private changeAndPatchNum$ = change$.pipe(withLatestFrom(currentPatchNum$));
+ private checkToPluginMap = new Map<string, string>();
+
+ constructor() {
+ checkToPluginMap$.subscribe(x => (this.checkToPluginMap = x));
+ }
+
reload(pluginName: string) {
this.reloadSubjects[pluginName].next();
}
@@ -59,6 +66,12 @@
Object.keys(this.providers).forEach(key => this.reload(key));
}
+ reloadForCheck(checkName?: string) {
+ if (!checkName) return;
+ const plugin = this.checkToPluginMap.get(checkName);
+ if (plugin) this.reload(plugin);
+ }
+
register(
pluginName: string,
provider: ChecksProvider,