diff --git a/frontend/app/angular4-modules.ts b/frontend/app/angular4-modules.ts index 7e783a9c28..1808a4b1a0 100644 --- a/frontend/app/angular4-modules.ts +++ b/frontend/app/angular4-modules.ts @@ -77,7 +77,7 @@ import { NotificationsServiceToken, PathHelperToken, upgradeService, - upgradeServiceWithToken + upgradeServiceWithToken, wpMoreMenuServiceToken } from './angular4-transition-utils'; import {WpCustomActionComponent} from 'core-components/wp-custom-actions/wp-custom-actions/wp-custom-action.component'; import {WpCustomActionsComponent} from 'core-components/wp-custom-actions/wp-custom-actions.component'; @@ -104,7 +104,6 @@ import {Ng1QueryFiltersComponentWrapper} from 'core-components/filters/query-fil import {UIRouterUpgradeModule} from '@uirouter/angular-hybrid'; import {WorkPackageSplitViewComponent} from 'core-components/routing/wp-split-view/wp-split-view.component'; import {WorkPackageBreadcrumbComponent} from 'core-components/work-packages/wp-breadcrumb/wp-breadcrumb.component'; -import {Ng1DetailsToolbarWrapper} from 'core-components/wp-details/wp-details-toolbar-ng1-wrapper'; import {WorkPackageRelationsCountComponent} from 'core-components/work-packages/wp-relations-count/wp-relations-count.component'; import {FirstRouteService} from 'core-components/routing/first-route-service'; import {PathHelperService} from 'core-components/common/path-helper/path-helper.service'; @@ -113,6 +112,8 @@ import {WorkPackageEditFieldGroupDirective} from 'core-components/wp-edit/wp-edi import {ConfigurationService} from 'core-components/common/config/configuration.service'; import {WorkPackageEditFieldComponent} from 'core-components/wp-edit/wp-edit-field/wp-edit-field.component'; import {WorkPackageCreateService} from 'core-components/wp-create/wp-create.service'; +import {WorkPackageWatcherButtonComponent} from 'core-components/work-packages/wp-watcher-button/wp-watcher-button.component'; +import {WorkPackageSplitViewToolbarComponent} from 'core-components/wp-details/wp-details-toolbar.component'; @NgModule({ imports: [ @@ -134,6 +135,7 @@ import {WorkPackageCreateService} from 'core-components/wp-create/wp-create.serv upgradeServiceWithToken('FocusHelper', FocusHelperToken), upgradeServiceWithToken('PathHelper', PathHelperToken), upgradeServiceWithToken('halRequest', halRequestToken), + upgradeServiceWithToken('wpMoreMenuService', wpMoreMenuServiceToken), upgradeService('wpRelations', WorkPackageRelationsService), upgradeService('wpCacheService', WorkPackageCacheService), upgradeService('wpEditing', WorkPackageEditingService), @@ -202,8 +204,9 @@ import {WorkPackageCreateService} from 'core-components/wp-create/wp-create.serv WorkPackageRelationsCountComponent, WorkPackageBreadcrumbComponent, WorkPackageEditFieldGroupDirective, + WorkPackageSplitViewToolbarComponent, + WorkPackageWatcherButtonComponent, WorkPackageSubjectComponent, - Ng1DetailsToolbarWrapper, // WP Edit Fields WorkPackageEditFieldComponent, diff --git a/frontend/app/angular4-transition-utils.ts b/frontend/app/angular4-transition-utils.ts index f9faff7f6b..c0de13f961 100644 --- a/frontend/app/angular4-transition-utils.ts +++ b/frontend/app/angular4-transition-utils.ts @@ -42,6 +42,7 @@ export const NotificationsServiceToken = new InjectionToken('NotificationsS export const v3PathToken = new InjectionToken('v3Path'); export const PathHelperToken = new InjectionToken('PathHelper'); export const halRequestToken = new InjectionToken('halRequest'); +export const wpMoreMenuServiceToken = new InjectionToken('wpMoreMenuService'); export const $httpToken = new InjectionToken('$http'); export const halResourceFactoryToken = new InjectionToken('halResourceFactory'); diff --git a/frontend/app/components/routing/wp-split-view/wp-split-view.html b/frontend/app/components/routing/wp-split-view/wp-split-view.html index 5a053c1754..6b56909b65 100644 --- a/frontend/app/components/routing/wp-split-view/wp-split-view.html +++ b/frontend/app/components/routing/wp-split-view/wp-split-view.html @@ -54,7 +54,7 @@
- +
diff --git a/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.directive.ts b/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.component.ts similarity index 68% rename from frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.directive.ts rename to frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.component.ts index 6f398c0863..3b3d38cccc 100644 --- a/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.directive.ts +++ b/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.component.ts @@ -26,35 +26,47 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ +import {wpDirectivesModule} from '../../../angular-modules'; +import {WorkPackageResourceInterface} from '../../api/api-v3/hal-resources/work-package-resource.service'; +import {WorkPackageCacheService} from '../work-package-cache.service'; +import {Component, Inject, Input, OnDestroy, OnInit} from '@angular/core'; +import {I18nToken} from 'core-app/angular4-transition-utils'; +import {componentDestroyed} from 'ng2-rx-componentdestroyed'; +import {downgradeComponent} from '@angular/upgrade/static'; + +@Component({ + template: require('!!raw-loader!./wp-watcher-button.html'), + selector: 'wp-watcher-button', +}) +export class WorkPackageWatcherButtonComponent implements OnInit, OnDestroy { + @Input('workPackage') public workPackage:WorkPackageResourceInterface; + @Input('showText') public showText:boolean = false; + @Input('disabled') public disabled:boolean = false; -import {wpDirectivesModule} from "../../../angular-modules"; -import {scopedObservable} from "../../../helpers/angular-rx-utils"; -import {WorkPackageResourceInterface} from "../../api/api-v3/hal-resources/work-package-resource.service"; -import {WorkPackageCacheService} from "../work-package-cache.service"; - -export class WorkPackageWatcherButtonController { - - public workPackage:WorkPackageResourceInterface; public buttonText:string; public buttonTitle:string; public buttonClass:string; public buttonId:string; public watchIconClass:string; - constructor(public $scope:ng.IScope, - public $rootScope:ng.IRootScopeService, - public I18n:op.I18n, + constructor(@Inject(I18nToken) readonly I18n:op.I18n, public wpCacheService:WorkPackageCacheService) { + } - scopedObservable( - $scope, - wpCacheService.loadWorkPackage(this.workPackage.id).values$()) + ngOnInit() { + this.wpCacheService.loadWorkPackage(this.workPackage.id) + .values$() + .takeUntil(componentDestroyed(this)) .subscribe((wp: WorkPackageResourceInterface) => { this.workPackage = wp; this.setWatchStatus(); }); } + ngOnDestroy() { + // Nothing to do + } + public get isWatched() { return this.workPackage.hasOwnProperty('unwatch'); } @@ -69,7 +81,7 @@ export class WorkPackageWatcherButtonController { toggleLink(toggleLink.$link.payload).then(() => { this.wpCacheService.loadWorkPackage(this.workPackage.id, true); }); - }; + } public nextStateLink() { const linkName = this.isWatched ? 'unwatch' : 'watch'; @@ -94,23 +106,6 @@ export class WorkPackageWatcherButtonController { } } -function wpWatcherButton():any { - return { - replace: true, - templateUrl: '/components/work-packages/wp-watcher-button/wp-watcher-button.directive.html', - - scope: { - workPackage: '=', - showText: '=', - disabled: '=' - }, - - bindToController: true, - controller: WorkPackageWatcherButtonController, - controllerAs: 'vm' - }; -} - - - -wpDirectivesModule.directive('wpWatcherButton', wpWatcherButton); +wpDirectivesModule.directive('wpWatcherButton', + downgradeComponent({component: WorkPackageWatcherButtonComponent}) +); diff --git a/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.directive.html b/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.directive.html deleted file mode 100644 index c821c633d4..0000000000 --- a/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.directive.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.html b/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.html new file mode 100644 index 0000000000..5179fd69e7 --- /dev/null +++ b/frontend/app/components/work-packages/wp-watcher-button/wp-watcher-button.html @@ -0,0 +1,11 @@ + diff --git a/frontend/app/components/wp-details/wp-details-toolbar-ng1-wrapper.ts b/frontend/app/components/wp-details/wp-details-toolbar-ng1-wrapper.ts deleted file mode 100644 index 751af47444..0000000000 --- a/frontend/app/components/wp-details/wp-details-toolbar-ng1-wrapper.ts +++ /dev/null @@ -1,30 +0,0 @@ -// This Angular directive will act as an interface to the "upgraded" AngularJS component -// query-filters -import { - Directive, DoCheck, ElementRef, Inject, Injector, Input, OnChanges, OnDestroy, - OnInit, SimpleChanges -} from '@angular/core'; -import {UpgradeComponent} from '@angular/upgrade/static'; -import {WorkPackageResourceInterface} from 'core-components/api/api-v3/hal-resources/work-package-resource.service'; - -@Directive({selector: 'ng1-wp-details-toolbar-wrapper'}) -export class Ng1DetailsToolbarWrapper extends UpgradeComponent implements OnInit, OnChanges, DoCheck, OnDestroy { - - @Input('workPackage') workPackage:WorkPackageResourceInterface; - - constructor(@Inject(ElementRef) elementRef:ElementRef, @Inject(Injector) injector:Injector) { - // We must pass the name of the directive as used by AngularJS to the super - super('wpDetailsToolbar', elementRef, injector); - } - - // For this class to work when compiled with AoT, we must implement these lifecycle hooks - // because the AoT compiler will not realise that the super class implements them - ngOnInit() { super.ngOnInit(); } - - ngOnChanges(changes:SimpleChanges) { super.ngOnChanges(changes); } - - ngDoCheck() { super.ngDoCheck(); } - - ngOnDestroy() { super.ngOnDestroy(); } -} - diff --git a/frontend/app/components/wp-details/wp-details-toolbar.directive.ts b/frontend/app/components/wp-details/wp-details-toolbar.component.ts similarity index 50% rename from frontend/app/components/wp-details/wp-details-toolbar.directive.ts rename to frontend/app/components/wp-details/wp-details-toolbar.component.ts index c74abf27bb..c67ca43dfd 100644 --- a/frontend/app/components/wp-details/wp-details-toolbar.directive.ts +++ b/frontend/app/components/wp-details/wp-details-toolbar.component.ts @@ -29,35 +29,44 @@ import {WorkPackageMoreMenuService} from '../work-packages/work-package-more-men import {openprojectModule} from '../../angular-modules'; import {WorkPackageEditingService} from '../wp-edit-form/work-package-editing-service'; -function wpDetailsToolbar( - I18n:op.I18n, - wpEditing:WorkPackageEditingService, - wpMoreMenuService:WorkPackageMoreMenuService):any { +import {I18nToken, wpMoreMenuServiceToken} from 'core-app/angular4-transition-utils'; +import {Component, Inject, Input, OnInit} from '@angular/core'; +import {WorkPackageResourceInterface} from 'core-components/api/api-v3/hal-resources/work-package-resource.service'; +import {downgradeComponent} from '@angular/upgrade/static'; - return { - restrict: 'E', - templateUrl: '/components/wp-details/wp-details-toolbar.directive.html', - scope: { - workPackage: '=' - }, - link: function(scope:any, attr:ng.IAttributes, element:ng.IAugmentedJQuery) { +@Component({ + template: require('!!raw-loader!./wp-details-toolbar.html'), + selector: 'wp-details-toolbar', +}) +export class WorkPackageSplitViewToolbarComponent implements OnInit { + @Input('workPackage') workPackage:WorkPackageResourceInterface; - let wpMoreMenu = new (wpMoreMenuService as any)(scope.workPackage); + public permittedActions:any; + public actionsAvailable:any; + public triggerMoreMenuAction:Function; - wpMoreMenu.initialize().then(() => { - scope.permittedActions = wpMoreMenu.permittedActions; - scope.actionsAvailable = wpMoreMenu.actionsAvailable; - }); + public text = { + button_more: this.I18n.t('js.button_more') + } - scope.triggerMoreMenuAction = wpMoreMenu.triggerMoreMenuAction.bind(wpMoreMenu); +constructor(@Inject(I18nToken) readonly I18n:op.I18n, + public wpEditing:WorkPackageEditingService, + @Inject(wpMoreMenuServiceToken) private wpMoreMenuServiceFactory:any) { + } - scope.displayWatchButton = scope.workPackage.hasOwnProperty('unwatch') || - scope.workPackage.hasOwnProperty('watch'); + ngOnInit() { + let wpMoreMenu = new this.wpMoreMenuServiceFactory(this.workPackage) as WorkPackageMoreMenuService; - scope.I18n = I18n; - } - }; + wpMoreMenu.initialize().then(() => { + this.permittedActions = wpMoreMenu.permittedActions; + this.actionsAvailable = wpMoreMenu.actionsAvailable; + }); + + this.triggerMoreMenuAction = wpMoreMenu.triggerMoreMenuAction.bind(wpMoreMenu); + } } -openprojectModule.directive('wpDetailsToolbar', wpDetailsToolbar); +openprojectModule.directive('wpDetailsToolbar', + downgradeComponent({component: WorkPackageSplitViewToolbarComponent }) +); diff --git a/frontend/app/components/wp-details/wp-details-toolbar.directive.html b/frontend/app/components/wp-details/wp-details-toolbar.directive.html deleted file mode 100644 index 923e80ebb1..0000000000 --- a/frontend/app/components/wp-details/wp-details-toolbar.directive.html +++ /dev/null @@ -1,16 +0,0 @@ -
- - - - -
diff --git a/frontend/app/components/wp-details/wp-details-toolbar.directive.test.ts b/frontend/app/components/wp-details/wp-details-toolbar.directive.test.ts index 84b01d8352..c6205e3d25 100644 --- a/frontend/app/components/wp-details/wp-details-toolbar.directive.test.ts +++ b/frontend/app/components/wp-details/wp-details-toolbar.directive.test.ts @@ -28,6 +28,8 @@ /*jshint expr: true*/ +// TODO convert? + describe('workPackageDetailsToolbar', function() { var I18n:any, $q:any, HookService:any, compile:any, scope:any, element:any, stateParams:any; var html = ` diff --git a/frontend/app/components/wp-details/wp-details-toolbar.html b/frontend/app/components/wp-details/wp-details-toolbar.html new file mode 100644 index 0000000000..2357b2c4a9 --- /dev/null +++ b/frontend/app/components/wp-details/wp-details-toolbar.html @@ -0,0 +1,15 @@ +
+ + + + +