diff --git a/frontend/app/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts b/frontend/app/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts index c01659e0fc..6f2f08f139 100644 --- a/frontend/app/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts +++ b/frontend/app/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts @@ -14,6 +14,7 @@ import {AuthorisationService} from "core-components/common/model-auth/model-auth import {StateService} from "@uirouter/core"; import {OpModalService} from "core-components/op-modals/op-modal.service"; import {WpDestroyModal} from "core-components/modals/wp-destroy-modal/wp-destroy.modal"; +import {PathHelperService} from "core-components/common/path-helper/path-helper.service"; @Directive({ selector: '[wpSingleContextMenu]' @@ -23,6 +24,7 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger constructor(@Inject(HookServiceToken) readonly HookService:any, @Inject($stateToken) readonly $state:StateService, + readonly PathHelper:PathHelperService, readonly elementRef:ElementRef, readonly opModalService:OpModalService, readonly opContextMenuService:OPContextMenuService, @@ -34,9 +36,8 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger this.workPackage.project.$load().then(() => { this.authorisationService.initModelAuth('work_package', this.workPackage.$links); - var authorization = new WorkPackageAuthorization(this.workPackage); - const permittedActions = angular.extend(this.getPermittedActions(authorization), - this.getPermittedPluginActions(authorization)); + var authorization = new WorkPackageAuthorization(this.workPackage, this.PathHelper, this.$state); + const permittedActions = this.getPermittedActions(authorization); this.buildItems(permittedActions); this.opContextMenu.show(this, evt); @@ -74,26 +75,30 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger } private getPermittedActions(authorization:WorkPackageAuthorization) { - return authorization.permittedActionsWithLinks(PERMITTED_CONTEXT_MENU_ACTIONS); - } + let actions:WorkPackageAction[] = authorization.permittedActionsWithLinks(PERMITTED_CONTEXT_MENU_ACTIONS); - private getPermittedPluginActions(authorization:WorkPackageAuthorization) { - var pluginActions:WorkPackageAction[] = []; - angular.forEach(this.HookService.call('workPackageDetailsMoreMenu'), function(action) { - pluginActions = pluginActions.concat(action); + // Splice plugin actions onto the core actions + _.each(this.getPermittedPluginActions(authorization), (action:WorkPackageAction) => { + let index = action.indexBy ? action.indexBy(actions) : actions.length; + actions.splice(index, 0, action); }); - return authorization.permittedActionsWithLinks(pluginActions); + return actions; + } + + private getPermittedPluginActions(authorization:WorkPackageAuthorization) { + let actions:WorkPackageAction[] = this.HookService.call('workPackageSingleContextMenu'); + return authorization.permittedActionsWithLinks(actions); } protected buildItems(permittedActions:WorkPackageAction[]) { this.items = permittedActions.map((action:WorkPackageAction) => { - const key = action.icon!; + const key = action.key; return { disabled: false, linkText: I18n.t('js.button_' + key), href: action.link, - icon: `icon-${key}`, + icon: action.icon || `icon-${key}`, onClick: ($event:JQueryEventObject) => { if (action.link && LinkHandling.isClickedWithModifier($event)) { return false; diff --git a/frontend/app/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts b/frontend/app/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts index 20c10c165b..0f7d0c59c1 100644 --- a/frontend/app/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts +++ b/frontend/app/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts @@ -1,31 +1,31 @@ export const PERMITTED_CONTEXT_MENU_ACTIONS = [ { - icon: 'log_time', + key: 'log_time', link: 'logTime', resource: 'workPackage' }, { - icon: 'move', + key: 'move', link: 'move', resource: 'workPackage' }, { - icon: 'copy', + key: 'copy', link: 'copy', resource: 'workPackage' }, { - icon: 'delete', + key: 'delete', link: 'delete', resource: 'workPackage' }, { - icon: 'export-pdf', + key: 'export-pdf', link: 'pdf', resource: 'workPackage' }, { - icon: 'export-atom', + key: 'export-atom', link: 'atom', resource: 'workPackage' } diff --git a/frontend/app/components/op-context-menu/wp-context-menu/wp-table-context-menu.directive.ts b/frontend/app/components/op-context-menu/wp-context-menu/wp-table-context-menu.directive.ts index 5b2ff2624f..551bf51308 100644 --- a/frontend/app/components/op-context-menu/wp-context-menu/wp-table-context-menu.directive.ts +++ b/frontend/app/components/op-context-menu/wp-context-menu/wp-table-context-menu.directive.ts @@ -58,7 +58,7 @@ export class OpWorkPackageContextMenu extends OpContextMenuHandler { public triggerContextMenuAction(action:WorkPackageAction) { const link = action.link; - switch (action.icon) { + switch (action.key) { case 'delete': this.deleteSelectedWorkPackages(); break; @@ -138,7 +138,7 @@ export class OpWorkPackageContextMenu extends OpContextMenuHandler { disabled: false, linkText: action.text, href: action.href, - icon: action.icon ? `icon-${action.icon}` : undefined, + icon: action.icon != null ? action.icon : `icon-${action.key}`, onClick: ($event:JQueryEventObject) => { if (action.href && LinkHandling.isClickedWithModifier($event)) { return false; diff --git a/frontend/app/components/work-packages/work-package-authorization.service.ts b/frontend/app/components/work-packages/work-package-authorization.service.ts index 1a70893721..5d8662711c 100644 --- a/frontend/app/components/work-packages/work-package-authorization.service.ts +++ b/frontend/app/components/work-packages/work-package-authorization.service.ts @@ -30,15 +30,15 @@ import {opWorkPackagesModule} from '../../angular-modules'; import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; import {StateService} from '@uirouter/core'; - -var $state:StateService; -var PathHelper:any; +import {PathHelperService} from "core-components/common/path-helper/path-helper.service"; export class WorkPackageAuthorization { public project:any; - constructor(public workPackage:WorkPackageResource) { + constructor(public workPackage:WorkPackageResource, + readonly PathHelper:PathHelperService, + readonly $state:StateService) { this.project = workPackage.project; } @@ -50,12 +50,11 @@ export class WorkPackageAuthorization { } public copyLink() { - const stateName = $state.current.name as string; - if (stateName.indexOf('work-packages.show') === 0) { - return PathHelper.workPackageCopyPath(this.workPackage.id); - } - else if (stateName.indexOf('work-packages.list.details') === 0) { - return PathHelper.workPackageDetailsCopyPath(this.project.identifier, this.workPackage.id); + const stateName = this.$state.current.name as string; + if (stateName.indexOf('work-packages.list.details') === 0) { + return this.PathHelper.workPackageDetailsCopyPath(this.project.identifier, this.workPackage.id); + } else { + return this.PathHelper.workPackageCopyPath(this.workPackage.id); } } @@ -91,15 +90,3 @@ export class WorkPackageAuthorization { return allowed; } } - -function wpAuthorizationService(...args:any[]) { - [$state, PathHelper] = args; - return WorkPackageAuthorization; -} - -wpAuthorizationService.$inject = [ - '$state', - 'PathHelper' -]; - -opWorkPackagesModule.factory('WorkPackageAuthorization', wpAuthorizationService); diff --git a/frontend/app/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts b/frontend/app/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts index 4a3be40c6c..664b519fa2 100644 --- a/frontend/app/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts +++ b/frontend/app/components/wp-table/context-menu-helper/wp-context-menu-helper.service.ts @@ -34,7 +34,9 @@ import {UrlParamsHelperService} from 'core-components/wp-query/url-params-helper export type WorkPackageAction = { text:string; + key:string; icon?:string; + indexBy?:(actions:WorkPackageAction[]) => number, link:string; href?:string; } @@ -45,25 +47,25 @@ export class WorkPackageContextMenuHelperService { private BULK_ACTIONS = [ { text: I18n.t('js.work_packages.bulk_actions.edit'), - icon: 'edit', + key: 'edit', link: 'update', href: this.PathHelper.staticBase + '/work_packages/bulk/edit' }, { text: I18n.t('js.work_packages.bulk_actions.move'), - icon: 'move', + key: 'move', link: 'move', href: this.PathHelper.staticBase + '/work_packages/move/new' }, { text: I18n.t('js.work_packages.bulk_actions.copy'), - icon: 'copy', + key: 'copy', link: 'copy', href: this.PathHelper.staticBase + '/work_packages/move/new?copy=true' }, { text: I18n.t('js.work_packages.bulk_actions.delete'), - icon: 'delete', + key: 'delete', link: 'delete', href: this.PathHelper.staticBase + '/work_packages/bulk?_method=delete' } @@ -82,8 +84,9 @@ export class WorkPackageContextMenuHelperService { angular.forEach(allowedActions, function(allowedAction) { singularPermittedActions.push({ - icon: allowedAction.icon, + key: allowedAction.key, text: allowedAction.text, + icon: allowedAction.icon, link: workPackage[allowedAction.link].href }); }); @@ -102,7 +105,7 @@ export class WorkPackageContextMenuHelperService { angular.forEach(permittedActions, (permittedAction:any) => { bulkPermittedActions.push({ - icon: permittedAction.icon, + key: permittedAction.key, text: permittedAction.text, link: this.getBulkActionLink(permittedAction, workPackages) }); @@ -126,12 +129,12 @@ export class WorkPackageContextMenuHelperService { return link + '?' + queryParts.join('&'); } - public getAllowedActions(workPackage:WorkPackageResource, actions:any):WorkPackageAction[] { - var allowedActions:any[] = []; + public getAllowedActions(workPackage:WorkPackageResource, actions:WorkPackageAction[]):WorkPackageAction[] { + var allowedActions:WorkPackageAction[] = []; angular.forEach(actions, (action) => { if (workPackage.hasOwnProperty(action.link)) { - action.text = action.text || I18n.t('js.button_' + action.icon); + action.text = action.text || I18n.t('js.button_' + action.key); allowedActions.push(action); } }); @@ -145,12 +148,12 @@ export class WorkPackageContextMenuHelperService { if (workPackage.addRelation && this.wpTableTimeline.isVisible) { allowedActions.push({ - icon: "relation-precedes", + key: "relation-precedes", text: I18n.t("js.relation_buttons.add_predecessor"), link: "addRelation" }); allowedActions.push({ - icon: "relation-follows", + key: "relation-follows", text: I18n.t("js.relation_buttons.add_follower"), link: "addRelation" }); @@ -158,7 +161,7 @@ export class WorkPackageContextMenuHelperService { if (!!workPackage.addChild) { allowedActions.push({ - icon: "relation-new-child", + key: "relation-new-child", text: I18n.t("js.relation_buttons.add_new_child"), link: "addChild" });