fix: upon extension error, loading spinner should be removed (#461)

* fix: upon extension error, loading spinner should be removed

* feat: show a message when an extension fails to load actions

* fix: extension state data structure

* fix: initialize extensions state

Co-authored-by: Johnny Almonte <johnny243@users.noreply.github.com>
This commit is contained in:
Johnny A
2020-09-07 07:44:52 -07:00
committed by GitHub
parent d45891569f
commit 6717907dd3
2 changed files with 52 additions and 17 deletions

View File

@@ -24,10 +24,15 @@ type UpdateActionParams = {
subrows?: ActionSubRow[] subrows?: ActionSubRow[]
} }
type ExtensionState = {
hidden: boolean
loading: boolean
error: boolean
}
type ActionsMenuState = { type ActionsMenuState = {
extensions: SNActionsExtension[], extensions: SNActionsExtension[]
hiddenState: Record<UuidString, Boolean> extensionsState: Record<UuidString, ExtensionState>
loadingState: Record<UuidString, Boolean>
} }
class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements ActionsMenuScope { class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements ActionsMenuScope {
@@ -54,10 +59,17 @@ class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements Acti
const extensions = this.application.actionsManager!.getExtensions().sort((a, b) => { const extensions = this.application.actionsManager!.getExtensions().sort((a, b) => {
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
}); });
let extensionsState: Record<UuidString, ExtensionState> = {};
extensions.map((extension) => {
extensionsState[extension.uuid] = {
loading: false,
error: false,
hidden: false
};
});
return { return {
extensions, extensions,
loadingState: {}, extensionsState
hiddenState: {}
}; };
} }
@@ -68,7 +80,11 @@ class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements Acti
extension, extension,
this.item this.item
); );
await this.updateExtension(updatedExtension!); if (updatedExtension) {
await this.updateExtension(updatedExtension!);
} else {
await this.setErrorExtension(extension.uuid, true);
}
await this.setLoadingExtension(extension.uuid, false); await this.setLoadingExtension(extension.uuid, false);
})); }));
} }
@@ -178,29 +194,42 @@ class ActionsMenuCtrl extends PureViewCtrl<{}, ActionsMenuState> implements Acti
} }
private async toggleExtensionVisibility(extensionUuid: UuidString) { private async toggleExtensionVisibility(extensionUuid: UuidString) {
const { hiddenState } = this.state; const { extensionsState } = this.state;
hiddenState[extensionUuid] = !hiddenState[extensionUuid] ?? false; extensionsState[extensionUuid].hidden = !extensionsState[extensionUuid].hidden;
await this.setState({ await this.setState({
hiddenState extensionsState
}); });
} }
private isExtensionVisible(extensionUuid: UuidString) { private isExtensionVisible(extensionUuid: UuidString) {
const { hiddenState } = this.state; const { extensionsState } = this.state;
return hiddenState[extensionUuid] ?? false; return extensionsState[extensionUuid].hidden;
} }
private async setLoadingExtension(extensionUuid: UuidString, value = false) { private async setLoadingExtension(extensionUuid: UuidString, value = false) {
const { loadingState } = this.state; const { extensionsState } = this.state;
loadingState[extensionUuid] = value; extensionsState[extensionUuid].loading = value;
await this.setState({ await this.setState({
loadingState extensionsState
}); });
} }
private isExtensionLoading(extensionUuid: UuidString) { private isExtensionLoading(extensionUuid: UuidString) {
const { loadingState } = this.state; const { extensionsState } = this.state;
return loadingState[extensionUuid] ?? false; return extensionsState[extensionUuid].loading;
}
private async setErrorExtension(extensionUuid: UuidString, value = false) {
const { extensionsState } = this.state;
extensionsState[extensionUuid].error = value;
await this.setState({
extensionsState
});
}
private extensionHasError(extensionUuid: UuidString) {
const { extensionsState } = this.state;
return extensionsState[extensionUuid].error;
} }
} }

View File

@@ -19,7 +19,7 @@
menu-row( menu-row(
action='self.executeAction(action, extension)', action='self.executeAction(action, extension)',
label='action.label', label='action.label',
ng-if='!self.isExtensionVisible(extension.uuid) && !self.isExtensionLoading(extension.uuid)', ng-if='!self.isExtensionVisible(extension.uuid) && !self.isExtensionLoading(extension.uuid) && !self.extensionHasError(extension.uuid)',
ng-repeat='action in extension.actionsWithContextForItem(self.item) track by $index', ng-repeat='action in extension.actionsWithContextForItem(self.item) track by $index',
disabled='action.running' disabled='action.running'
spinner-class="action.running ? 'info' : null", spinner-class="action.running ? 'info' : null",
@@ -35,3 +35,9 @@
label="'No Actions Available'", label="'No Actions Available'",
ng-if='extension.actionsWithContextForItem(self.item).length == 0' ng-if='extension.actionsWithContextForItem(self.item).length == 0'
) )
menu-row(
faded='true',
label="'Error loading actions'",
subtitle="'Please try again later.'"
ng-if='self.extensionHasError(extension.uuid)'
)