From 45fe64191deef4046ec3b230a331ea3fd0ed64c7 Mon Sep 17 00:00:00 2001 From: Johnny Almonte Date: Thu, 25 Jun 2020 23:37:49 -0400 Subject: [PATCH 1/4] refactor: actions menu --- .../directives/views/actionsMenu.ts | 90 +++++++++++++++---- .../templates/directives/actions-menu.pug | 19 ++-- 2 files changed, 85 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/directives/views/actionsMenu.ts b/app/assets/javascripts/directives/views/actionsMenu.ts index b7a91a709..5e3791568 100644 --- a/app/assets/javascripts/directives/views/actionsMenu.ts +++ b/app/assets/javascripts/directives/views/actionsMenu.ts @@ -2,19 +2,38 @@ import { WebApplication } from '@/ui_models/application'; import { WebDirective } from './../../types'; import template from '%/directives/actions-menu.pug'; import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl'; -import { SNItem, Action, SNActionsExtension } from '@node_modules/snjs/dist/@types'; -import { ActionResponse } from '@node_modules/snjs/dist/@types/services/actions_service'; +import { SNItem, Action, SNActionsExtension } from 'snjs/dist/@types'; +import { ActionResponse } from 'snjs/dist/@types/services/actions_service'; +import { ActionsExtensionMutator } from 'snjs/dist/@types/models/app/extension'; type ActionsMenuScope = { application: WebApplication item: SNItem } +type ActionSubRow = { + onClick: () => void + label: string + subtitle: string + spinnerClass: string | undefined +} + +type UpdateActionParams = { + running?: boolean + error?: boolean + subrows?: ActionSubRow[] +} + +type UpdateExtensionParams = { + hidden?: boolean + loading?: boolean +} + class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { application!: WebApplication item!: SNItem - public loadingState: Partial> = {} + public loadingExtensions: boolean = true /* @ngInject */ constructor( @@ -39,14 +58,15 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; }); for (const extension of extensions) { - this.loadingState[extension.uuid] = true; await this.application.actionsManager!.loadExtensionInContextOfItem( extension, this.props.item ); - this.loadingState[extension.uuid] = false; } - this.setState({ + if (extensions.length == 0) { + this.loadingExtensions = false; + } + await this.setState({ extensions: extensions }); } @@ -54,13 +74,12 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { async executeAction(action: Action, extension: SNActionsExtension) { if (action.verb === 'nested') { if (!action.subrows) { - action.subrows = this.subRowsForAction(action, extension); - } else { - action.subrows = undefined; + const subrows = this.subRowsForAction(action, extension); + await this.updateAction(action, extension, { subrows }); } return; } - action.running = true; + await this.updateAction(action, extension, { running: true }); const response = await this.application.actionsManager!.runAction( action, this.props.item, @@ -69,18 +88,17 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { return ''; } ); - if (action.error) { + if (response.error) { + await this.updateAction(action, extension, { error: true }); return; } - action.running = false; + await this.updateAction(action, extension, { running: false }); this.handleActionResponse(action, response); - await this.application.actionsManager!.loadExtensionInContextOfItem( + const updatedExtension = await this.application.actionsManager!.loadExtensionInContextOfItem( extension, this.props.item ); - this.setState({ - extensions: this.state.extensions - }); + await this.updateExtension(updatedExtension!); } handleActionResponse(action: Action, result: ActionResponse) { @@ -95,7 +113,7 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { } } - subRowsForAction(parentAction: Action, extension: SNActionsExtension) { + subRowsForAction(parentAction: Action, extension: SNActionsExtension): ActionSubRow[] | undefined { if (!parentAction.subactions) { return undefined; } @@ -110,6 +128,44 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { }; }); } + + async updateAction( + action: Action, + extension: SNActionsExtension, + params: UpdateActionParams + ) { + const updatedExtension = await this.application.changeItem(extension.uuid, (mutator) => { + const extensionMutator = mutator as ActionsExtensionMutator; + extensionMutator.actions = extension!.actions.map((act) => { + if (act && params && act.verb === action.verb && act.url === action.url) { + return { + ...action, + running: params?.running, + error: params?.error, + subrows: params?.subrows || act?.subrows, + }; + } + return act; + }); + }) as SNActionsExtension; + await this.updateExtension(updatedExtension); + } + + async updateExtension(extension: SNActionsExtension, params?: UpdateExtensionParams) { + const updatedExtension = await this.application.changeItem(extension.uuid, (mutator) => { + const extensionMutator = mutator as ActionsExtensionMutator; + extensionMutator.hidden = params && params.hidden; + }) as SNActionsExtension; + const updatedExtensions = this.state.extensions.map((ext: SNActionsExtension) => { + if (extension.uuid === ext.uuid) { + return updatedExtension; + } + return ext; + }); + await this.setState({ + extensions: updatedExtensions + }); + } } export class ActionsMenu extends WebDirective { diff --git a/app/assets/templates/directives/actions-menu.pug b/app/assets/templates/directives/actions-menu.pug index 88804429a..21ed0b287 100644 --- a/app/assets/templates/directives/actions-menu.pug +++ b/app/assets/templates/directives/actions-menu.pug @@ -7,19 +7,24 @@ target='blank' ) menu-row(label="'Download Actions'") - div(ng-repeat='extension in self.state.extensions track by extension.uuid') + div(ng-if='self.loadingExtensions') + .sk-menu-panel-header + .sk-menu-panel-column + .sk-menu-panel-header-title Loading... + .sk-spinner.small.loading + div(ng-repeat='extension in self.state.extensions track by extension.uuid; self.loadingExtensions = false') .sk-menu-panel-header( - ng-click='extension.hide = !extension.hide; $event.stopPropagation();' + ng-click='self.updateExtension(extension, { hidden: !extension.hidden }); $event.stopPropagation();' ) .sk-menu-panel-column .sk-menu-panel-header-title {{extension.name}} - .sk-spinner.small.loading(ng-if='self.loadingState[extension.uuid]') - div(ng-if='extension.hide') … + div(ng-if='extension.hidden') … menu-row( - action='self.executeAction(action, extension);', + action='self.executeAction(action, extension)', label='action.label', - ng-if='!extension.hide', - ng-repeat='action in extension.actionsWithContextForItem(self.props.item)', + ng-if='!extension.hidden', + ng-repeat='action in extension.actionsWithContextForItem(self.props.item) track by $index', + disabled='action.running' spinner-class="action.running ? 'info' : null", sub-rows='action.subrows', subtitle='action.desc' From ff20b9d6e624bca11611ee79ebff114b028a08a5 Mon Sep 17 00:00:00 2001 From: Johnny Almonte Date: Fri, 26 Jun 2020 10:55:22 -0400 Subject: [PATCH 2/4] fix: remove unnecessary property --- app/assets/javascripts/directives/views/actionsMenu.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/directives/views/actionsMenu.ts b/app/assets/javascripts/directives/views/actionsMenu.ts index 5e3791568..57ccc7fdb 100644 --- a/app/assets/javascripts/directives/views/actionsMenu.ts +++ b/app/assets/javascripts/directives/views/actionsMenu.ts @@ -26,7 +26,6 @@ type UpdateActionParams = { type UpdateExtensionParams = { hidden?: boolean - loading?: boolean } class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { From 42e71cee5a5a8c7950dd7cb7e2934b4d25eccfbf Mon Sep 17 00:00:00 2001 From: Johnny Almonte Date: Sat, 27 Jun 2020 22:03:30 -0400 Subject: [PATCH 3/4] refactor: actions menu --- .../directives/views/actionsMenu.ts | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/app/assets/javascripts/directives/views/actionsMenu.ts b/app/assets/javascripts/directives/views/actionsMenu.ts index 57ccc7fdb..3d7ee80b5 100644 --- a/app/assets/javascripts/directives/views/actionsMenu.ts +++ b/app/assets/javascripts/directives/views/actionsMenu.ts @@ -53,20 +53,22 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { }; async loadExtensions() { - const extensions = this.application.actionsManager!.getExtensions().sort((a, b) => { + const actionExtensions = this.application.actionsManager!.getExtensions().sort((a, b) => { return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; }); - for (const extension of extensions) { - await this.application.actionsManager!.loadExtensionInContextOfItem( + let extensionsForItem = []; + for (const extension of actionExtensions) { + const extensionInContext = await this.application.actionsManager!.loadExtensionInContextOfItem( extension, this.props.item ); + extensionsForItem.push(extensionInContext); } - if (extensions.length == 0) { + if (actionExtensions.length == 0) { this.loadingExtensions = false; } await this.setState({ - extensions: extensions + extensions: extensionsForItem }); } @@ -93,11 +95,7 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { } await this.updateAction(action, extension, { running: false }); this.handleActionResponse(action, response); - const updatedExtension = await this.application.actionsManager!.loadExtensionInContextOfItem( - extension, - this.props.item - ); - await this.updateExtension(updatedExtension!); + await this.reloadExtension(extension); } handleActionResponse(action: Action, result: ActionResponse) { @@ -112,7 +110,7 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { } } - subRowsForAction(parentAction: Action, extension: SNActionsExtension): ActionSubRow[] | undefined { + private subRowsForAction(parentAction: Action, extension: SNActionsExtension): ActionSubRow[] | undefined { if (!parentAction.subactions) { return undefined; } @@ -128,7 +126,7 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { }); } - async updateAction( + private async updateAction( action: Action, extension: SNActionsExtension, params: UpdateActionParams @@ -150,19 +148,38 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { await this.updateExtension(updatedExtension); } - async updateExtension(extension: SNActionsExtension, params?: UpdateExtensionParams) { + private async updateExtension( + extension: SNActionsExtension, + params?: UpdateExtensionParams + ) { const updatedExtension = await this.application.changeItem(extension.uuid, (mutator) => { const extensionMutator = mutator as ActionsExtensionMutator; extensionMutator.hidden = params && params.hidden; }) as SNActionsExtension; - const updatedExtensions = this.state.extensions.map((ext: SNActionsExtension) => { + const extensions = this.state.extensions.map((ext: SNActionsExtension) => { if (extension.uuid === ext.uuid) { return updatedExtension; } return ext; }); await this.setState({ - extensions: updatedExtensions + extensions: extensions + }); + } + + private async reloadExtension(extension: SNActionsExtension) { + const extensionInContext = await this.application.actionsManager!.loadExtensionInContextOfItem( + extension, + this.props.item + ); + const extensions = this.state.extensions.map((ext: SNActionsExtension) => { + if (extension.uuid === ext.uuid) { + return extensionInContext; + } + return ext; + }); + this.setState({ + extensions: extensions }); } } From 31a1d112aca53140cfddc8ed090595ec48f5844e Mon Sep 17 00:00:00 2001 From: Johnny Almonte Date: Sat, 27 Jun 2020 22:40:29 -0400 Subject: [PATCH 4/4] refactor: loadExtensions method --- app/assets/javascripts/directives/views/actionsMenu.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/directives/views/actionsMenu.ts b/app/assets/javascripts/directives/views/actionsMenu.ts index 3d7ee80b5..a38321c30 100644 --- a/app/assets/javascripts/directives/views/actionsMenu.ts +++ b/app/assets/javascripts/directives/views/actionsMenu.ts @@ -56,15 +56,13 @@ class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope { const actionExtensions = this.application.actionsManager!.getExtensions().sort((a, b) => { return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; }); - let extensionsForItem = []; - for (const extension of actionExtensions) { - const extensionInContext = await this.application.actionsManager!.loadExtensionInContextOfItem( + const extensionsForItem = await Promise.all(actionExtensions.map((extension) => { + return this.application.actionsManager!.loadExtensionInContextOfItem( extension, this.props.item ); - extensionsForItem.push(extensionInContext); - } - if (actionExtensions.length == 0) { + })); + if (extensionsForItem.length == 0) { this.loadingExtensions = false; } await this.setState({