diff --git a/static/directives/header-bar.html b/static/directives/header-bar.html index 52118403a..63c72c91a 100644 --- a/static/directives/header-bar.html +++ b/static/directives/header-bar.html @@ -25,7 +25,7 @@
  • Tutorial
  • Pricing
  • Docs
  • -
  • Blog
  • +
  • Blog
  • @@ -34,7 +34,7 @@
  • Repositories
  • Tutorial
  • Docs
  • -
  • Blog
  • +
  • Blog
  • diff --git a/static/js/directives/quay-layout.js b/static/js/directives/quay-layout.js index 139a00b07..bd0e1f3f9 100644 --- a/static/js/directives/quay-layout.js +++ b/static/js/directives/quay-layout.js @@ -2,20 +2,6 @@ * Directives which show, hide, include or otherwise mutate the DOM based on Features and Config. */ -/** - * Adds a quay-require attribute includes an element in the DOM iff the features specified are true. - */ -angular.module('quay').directive('quayRequire', function ($animate, Features, AngularHelper) { - return { - transclude: 'element', - priority: 600, - terminal: true, - restrict: 'A', - link: AngularHelper.buildConditionalLinker($animate, 'quayRequire', function(value) { - return Features.matchesFeatures(value); - }) - }; -}); /** * Adds a quay-show attribute that shows the element only if the attribute evaluates to true. diff --git a/static/js/directives/structural/quay-require/quay-require.directive.spec.ts b/static/js/directives/structural/quay-require/quay-require.directive.spec.ts new file mode 100644 index 000000000..7e236bf41 --- /dev/null +++ b/static/js/directives/structural/quay-require/quay-require.directive.spec.ts @@ -0,0 +1,59 @@ +import { QuayRequireDirective } from './quay-require.directive'; +import { Mock } from 'ts-mocks'; +import Spy = jasmine.Spy; + + +describe("QuayRequireDirective", () => { + var directive: QuayRequireDirective; + var featuresMock: Mock; + var $elementMock: Mock; + var $scopeMock: Mock; + var $transcludeMock: Mock; + var ngIfDirectiveMock: Mock; + + beforeEach(() => { + featuresMock = new Mock(); + $elementMock = new Mock(); + $scopeMock = new Mock(); + $transcludeMock = new Mock(); + ngIfDirectiveMock = new Mock(); + + directive = new QuayRequireDirective(featuresMock.Object, + $elementMock.Object, + $scopeMock.Object, + $transcludeMock.Object, + [ngIfDirectiveMock.Object]); + directive.requiredFeatures = ['BILLING', 'SOME_OTHER_FEATURE']; + }); + + describe("ngAfterContentInit", () => { + var linkMock: Mock; + + beforeEach(() => { + linkMock = new Mock(); + linkMock.setup(mock => (mock).apply); + ngIfDirectiveMock.setup(mock => mock.link).is(linkMock.Object); + }); + + it("calls ngIfDirective link method with own element's arguments to achieve ngIf functionality", () => { + featuresMock.setup(mock => mock.matchesFeatures).is((features) => false); + directive.ngAfterContentInit(); + + expect(((linkMock.Object).apply).calls.argsFor(0)[0]).toEqual(ngIfDirectiveMock.Object); + expect(((linkMock.Object).apply).calls.argsFor(0)[1][0]).toEqual($elementMock.Object); + expect(((linkMock.Object).apply).calls.argsFor(0)[1][1]).toEqual($scopeMock.Object); + expect(Object.keys(((linkMock.Object).apply).calls.argsFor(0)[1][2])).toEqual(['ngIf']); + expect(((linkMock.Object).apply).calls.argsFor(0)[1][3]).toEqual(null); + expect(((linkMock.Object).apply).calls.argsFor(0)[1][4]).toEqual($transcludeMock.Object); + }); + + it("calls feature service to check if given features are present in application", () => { + featuresMock.setup(mock => mock.matchesFeatures).is((features) => false); + directive.ngAfterContentInit(); + + expect(((linkMock.Object).apply).calls.argsFor(0)[1][2]['ngIf']()).toBe(false); + expect(featuresMock.Object.matchesFeatures).toHaveBeenCalled(); + expect((featuresMock.Object.matchesFeatures).calls.argsFor(0)[0]).toEqual(directive.requiredFeatures); + }); + }); +}); diff --git a/static/js/directives/structural/quay-require/quay-require.directive.ts b/static/js/directives/structural/quay-require/quay-require.directive.ts new file mode 100644 index 000000000..32b15341a --- /dev/null +++ b/static/js/directives/structural/quay-require/quay-require.directive.ts @@ -0,0 +1,41 @@ +import { Directive, Inject, Input, AfterContentInit } from 'ng-metadata/core'; + + +/** + * Structural directive that adds/removes its host element if the given list of feature flags are set. + * Utilizes the existing AngularJS ngIf directive by applying its 'link' function to the host element's properties. + * + * Inspired by http://stackoverflow.com/a/29010910 + */ +@Directive({ + selector: '[quayRequire]', + legacy: { + transclude: 'element', + } +}) +export class QuayRequireDirective implements AfterContentInit { + + @Input(' this.features.matchesFeatures(this.requiredFeatures)}; + + (this.ngIfDirective.link).apply(this.ngIfDirective, + [ + this.$scope, + this.$element, + attrs, + null, + this.$transclude + ]); + } +} \ No newline at end of file diff --git a/static/js/quay.module.ts b/static/js/quay.module.ts index 36006547e..6c554fd17 100644 --- a/static/js/quay.module.ts +++ b/static/js/quay.module.ts @@ -19,6 +19,7 @@ import { AvatarServiceImpl } from './services/avatar/avatar.service.impl'; import { DockerfileServiceImpl } from './services/dockerfile/dockerfile.service.impl'; import { DataFileServiceImpl } from './services/datafile/datafile.service.impl'; import { UtilServiceImpl } from './services/util/util.service.impl'; +import { QuayRequireDirective } from './directives/structural/quay-require/quay-require.directive'; /** @@ -42,6 +43,7 @@ import { UtilServiceImpl } from './services/util/util.service.impl'; CorTableComponent, CorTableColumn, ChannelIconComponent, + QuayRequireDirective, ], providers: [ ViewArrayImpl, diff --git a/yarn.lock b/yarn.lock index 3486c702d..c9261bb5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,10 +30,6 @@ version "0.9.39" resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-0.9.39.tgz#9b3d9869c2b7de02d372d32d6c6d9f5db3178c65" -"@types/es6-shim@^0.31.32": - version "0.31.32" - resolved "https://registry.yarnpkg.com/@types/es6-shim/-/es6-shim-0.31.32.tgz#8196c09e1e40ac977c713bf258090989f501d8ff" - "@types/jasmine@^2.5.41": version "2.5.43" resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.5.43.tgz#6328a8c26082f2fd84f043c802c9ed7fa110b2dd"