diff --git a/wherehows-web/app/constants/datasets/shared.ts b/wherehows-web/app/constants/datasets/shared.ts new file mode 100644 index 0000000000..dc2087b486 --- /dev/null +++ b/wherehows-web/app/constants/datasets/shared.ts @@ -0,0 +1,52 @@ +import Route from '@ember/routing/route'; +import { assert } from '@ember/debug'; +import { set } from '@ember/object'; +import DatasetController from 'wherehows-web/controllers/datasets/dataset'; + +/** + * Defines id strings for page tabs available on the dataset page, + * these also match up with their respective route names + * @type {string} + */ +enum Tabs { + Properties = 'properties', + Access = 'access', + Comments = 'comments', + Schema = 'schema', + Ownership = 'ownership', + Compliance = 'compliance', + SampleData = 'sample', + Relations = 'relations' +} + +/** + * Sets the tab selection property on the provided route with the currently selected tab + * @param {Route} route the route instance to update + * @param {Tabs} tabSelected identifier for the selected tab + * @returns {Tabs} + */ +const setTabSelectedOnAncestorController = (route: Route, tabSelected: Tabs): Tabs => { + const { routeName, controllerFor } = route; + assert('route should be a descendant of datasets.dataset', !routeName.indexOf('datasets.dataset.')); + const ancestorController = controllerFor.call(route, 'datasets.dataset'); + + return set(ancestorController, 'tabSelected', tabSelected); +}; + +/** + * Factory creates a dataset Route class that sets the currently selected tab on the parent controller + * @param {{ selectedTab: Tabs }} { selectedTab } options bag contains identifier for the current tab + * @returns {typeof Route} the descendant route class + */ +const descendantDatasetRouteClassFactory = ({ selectedTab }: { selectedTab: Tabs }): typeof Route => { + return class DatasetDescendantRoute extends Route { + actions = { + didTransition(this: DatasetDescendantRoute) { + // on successful route transition + setTabSelectedOnAncestorController(this, selectedTab); + } + }; + }; +}; + +export { Tabs, descendantDatasetRouteClassFactory, setTabSelectedOnAncestorController }; diff --git a/wherehows-web/app/controllers/datasets/dataset.js b/wherehows-web/app/controllers/datasets/dataset.js index 6e9a4bef17..1de15d7229 100644 --- a/wherehows-web/app/controllers/datasets/dataset.js +++ b/wherehows-web/app/controllers/datasets/dataset.js @@ -14,10 +14,13 @@ import { import { updateDatasetDeprecation } from 'wherehows-web/utils/api/datasets/properties'; import { readDatasetView } from 'wherehows-web/utils/api/datasets/dataset'; import { readDatasetOwners, updateDatasetOwners } from 'wherehows-web/utils/api/datasets/owners'; +import { Tabs } from 'wherehows-web/constants/datasets/shared'; +import { action } from 'ember-decorators/object'; const { post, getJSON } = $; -export default Controller.extend({ +// gradual refactor into es class, hence extends EmberObject instance +export default class extends Controller.extend({ queryParams: ['urn'], /** * Reference to the application notifications Service @@ -202,20 +205,6 @@ export default Controller.extend({ }, actions: { - /** - * Renders the properties tab elements. - * temporary workaround to query parameters, the file is a holdover from the legacy WH app - */ - showProperties() { - // FIXME: this is a stop gap pending transition to queryParams tabbed nav in datasets. - // :facepalm: - run(() => { - scheduleOnce('afterRender', null, () => { - $('.tabbed-navigation-list li.active:not(#properties)').removeClass('active'); - $('.tabbed-navigation-list #properties').addClass('active'); - }); - }); - }, /** * Updates the dataset's deprecation properties * @param {boolean} isDeprecated @@ -334,4 +323,25 @@ export default Controller.extend({ .catch(this.exceptionOnSave); } } -}); +}) { + tabIds = Tabs; + + tabSelected; + + constructor() { + super(); + this.tabSelected || (this.tabSelected = Tabs.Ownership); + } + + /** + * Handles user generated tab selection action by transitioning to specified route + * @param {Tabs} tabSelected the currently selected tab + */ + @action + tabSelectionChanged(tabSelected) { + // if the tab selection is same as current, noop + return get(this, 'tabSelected') === tabSelected + ? void 0 + : this.transitionToRoute(`datasets.dataset.${tabSelected}`, get(this, 'datasetId')); + } +} diff --git a/wherehows-web/app/router.js b/wherehows-web/app/router.js index 16d7c8e002..379c10e499 100644 --- a/wherehows-web/app/router.js +++ b/wherehows-web/app/router.js @@ -57,9 +57,21 @@ AppRouter.map(function() { path: '/*wildcard' }); this.route('datasets', function() { - this.route('dataset', { - path: '/:dataset_id' - }); + this.route( + 'dataset', + { + path: '/:dataset_id' + }, + function() { + this.route('properties'); + this.route('comments'); + this.route('schema'); + this.route('ownership'); + this.route('compliance'); + this.route('sample'); + this.route('relations'); + } + ); }); this.route('search'); this.route('metrics', function() { diff --git a/wherehows-web/app/routes/datasets/dataset/comments.ts b/wherehows-web/app/routes/datasets/dataset/comments.ts new file mode 100644 index 0000000000..c36c9d3d37 --- /dev/null +++ b/wherehows-web/app/routes/datasets/dataset/comments.ts @@ -0,0 +1,3 @@ +import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared'; + +export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Comments }); diff --git a/wherehows-web/app/routes/datasets/dataset/compliance.ts b/wherehows-web/app/routes/datasets/dataset/compliance.ts new file mode 100644 index 0000000000..37cf11e57d --- /dev/null +++ b/wherehows-web/app/routes/datasets/dataset/compliance.ts @@ -0,0 +1,3 @@ +import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared'; + +export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Compliance }); diff --git a/wherehows-web/app/routes/datasets/dataset/ownership.ts b/wherehows-web/app/routes/datasets/dataset/ownership.ts new file mode 100644 index 0000000000..0c7f604f0d --- /dev/null +++ b/wherehows-web/app/routes/datasets/dataset/ownership.ts @@ -0,0 +1,3 @@ +import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared'; + +export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Ownership }); diff --git a/wherehows-web/app/routes/datasets/dataset/properties.ts b/wherehows-web/app/routes/datasets/dataset/properties.ts new file mode 100644 index 0000000000..fddcb600fb --- /dev/null +++ b/wherehows-web/app/routes/datasets/dataset/properties.ts @@ -0,0 +1,3 @@ +import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared'; + +export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Properties }); diff --git a/wherehows-web/app/routes/datasets/dataset/relations.ts b/wherehows-web/app/routes/datasets/dataset/relations.ts new file mode 100644 index 0000000000..113b91b0bc --- /dev/null +++ b/wherehows-web/app/routes/datasets/dataset/relations.ts @@ -0,0 +1,3 @@ +import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared'; + +export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Relations }); diff --git a/wherehows-web/app/routes/datasets/dataset/sample.ts b/wherehows-web/app/routes/datasets/dataset/sample.ts new file mode 100644 index 0000000000..2b4c90e7a0 --- /dev/null +++ b/wherehows-web/app/routes/datasets/dataset/sample.ts @@ -0,0 +1,3 @@ +import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared'; + +export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.SampleData }); diff --git a/wherehows-web/app/routes/datasets/dataset/schema.ts b/wherehows-web/app/routes/datasets/dataset/schema.ts new file mode 100644 index 0000000000..0da0809283 --- /dev/null +++ b/wherehows-web/app/routes/datasets/dataset/schema.ts @@ -0,0 +1,3 @@ +import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared'; + +export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Schema }); diff --git a/wherehows-web/app/templates/datasets/dataset.hbs b/wherehows-web/app/templates/datasets/dataset.hbs index 758159a0d3..1830740089 100644 --- a/wherehows-web/app/templates/datasets/dataset.hbs +++ b/wherehows-web/app/templates/datasets/dataset.hbs @@ -29,7 +29,8 @@ {{/if}} {{#if datasetView.deprecated}} - + {{#link-to "datasets.dataset.properties" datasetId}} + DEPRECATED @@ -43,7 +44,8 @@ }} - + + {{/link-to}} {{/if}}

{{ model.name }}

@@ -152,32 +154,35 @@ {{/if}} - {{#ivy-tabs selection=selection as |tabs|}} + {{#ivy-tabs selection=tabSelected as |tabs|}} {{#tabs.tablist as |tablist|}} {{#unless isPinot}} - {{#tablist.tab "Properties" on-select=(action (mut selection))}}Properties{{/tablist.tab}} + {{#tablist.tab tabIds.Properties on-select=(action "tabSelectionChanged")}} + Properties + {{/tablist.tab}} {{/unless}} {{!--feature not available--}} - {{#tablist.tab "Access" on-select=(action (mut selection))}}ACL Access{{/tablist.tab}} + {{#tablist.tab tabIds.Access on-select=(action "tabSelectionChanged")}}ACL Access{{/tablist.tab}} - {{#tablist.tab "Comments" on-select=(action (mut selection))}}Comments{{/tablist.tab}} + {{#tablist.tab tabIds.Comments on-select=(action "tabSelectionChanged")}}Comments{{/tablist.tab}} - {{#tablist.tab "Schema" on-select=(action (mut selection))}}Schema{{/tablist.tab}} + {{#tablist.tab tabIds.Schema on-select=(action "tabSelectionChanged")}}Schema{{/tablist.tab}} - {{#tablist.tab "Ownership" on-select=(action (mut selection))}} + {{#tablist.tab tabIds.Ownership on-select=(action "tabSelectionChanged")}} Ownership + {{#if requiredMinNotConfirmed}} {{/if}} {{/tablist.tab}} {{#if isInternal}} - {{#tablist.tab "Compliance" on-select=(action (mut selection))}} + {{#tablist.tab tabIds.Compliance on-select=(action "tabSelectionChanged")}} Compliance {{#if isNewComplianceInfo}} @@ -187,14 +192,16 @@ {{/if}} {{#unless isSFDC}} - {{#tablist.tab "Sample Data" on-select=(action (mut selection))}}Sample Data{{/tablist.tab}} + {{#tablist.tab tabIds.SampleData on-select=(action "tabSelectionChanged")}} + Sample Data{{/tablist.tab}} {{/unless}} - {{#tablist.tab "Relations" on-select=(action (mut selection))}}Relations{{/tablist.tab}} + {{#tablist.tab tabIds.Relations on-select=(action "tabSelectionChanged")}} + Relations{{/tablist.tab}} {{/tabs.tablist}} - {{#tabs.tabpanel "Properties"}} + {{#tabs.tabpanel tabIds.Properties}} {{#unless isPinot}} {{dataset-deprecation deprecated=datasetView.deprecated @@ -206,7 +213,7 @@ {{/unless}} {{/tabs.tabpanel}} - {{#tabs.tabpanel "Comments"}} + {{#tabs.tabpanel tabIds.Comments}} {{dataset-comments comments=datasetComments updateDatasetComment=(action "updateDatasetComment") @@ -215,7 +222,7 @@ }} {{/tabs.tabpanel}} - {{#tabs.tabpanel "Schema"}} + {{#tabs.tabpanel tabIds.Schema}} {{dataset-schema isTable=isTable json=model.schema @@ -223,7 +230,7 @@ }} {{/tabs.tabpanel}} - {{#tabs.tabpanel "Ownership"}} + {{#tabs.tabpanel tabIds.Ownership}} {{dataset-authors owners=owners ownerTypes=ownerTypes @@ -231,19 +238,19 @@ }} {{/tabs.tabpanel}} - {{#tabs.tabpanel "Sample Data"}} + {{#tabs.tabpanel tabIds.SampleData}} {{#unless isSFDC}} {{dataset-sample hasSamples=hasSamples isPinot=isPinot columns=columns samples=samples}} {{/unless}} {{/tabs.tabpanel}} - {{#tabs.tabpanel "Relations"}} + {{#tabs.tabpanel tabIds.Relations}} {{#unless isSFDC}} {{dataset-relations hasDepends=hasDepends depends=depends hasReferences=hasReferences references=references}} {{/unless}} {{/tabs.tabpanel}} - {{#tabs.tabpanel "Compliance"}} + {{#tabs.tabpanel tabIds.Compliance}} {{dataset-compliance datasetName=model.name schemaless=schemaless @@ -258,7 +265,7 @@ }} {{/tabs.tabpanel}} - {{#tabs.tabpanel "Access"}} + {{#tabs.tabpanel tabIds.Access}} {{dataset-aclaccess accessInfo=aclAccessResponse currentUser=currentUserInfo diff --git a/wherehows-web/app/typings/untyped-js-module.d.ts b/wherehows-web/app/typings/untyped-js-module.d.ts index 91dd6742bd..76be22051f 100644 --- a/wherehows-web/app/typings/untyped-js-module.d.ts +++ b/wherehows-web/app/typings/untyped-js-module.d.ts @@ -25,6 +25,14 @@ declare module 'ember-simple-auth/services/session' { } declare module 'wherehows-web/utils/datasets/compliance-policy'; +declare module 'wherehows-web/controllers/datasets/dataset' { + import Controller from '@ember/controller'; + import { Tabs } from 'wherehows-web/constants/datasets/shared'; + + export default class extends Controller { + tabSelected: Tabs; + } +} declare module 'ember-cli-mirage'; diff --git a/wherehows-web/tests/acceptance/browse-test.js b/wherehows-web/tests/acceptance/browse-test.js index f26bd772f7..81fb2b1379 100644 --- a/wherehows-web/tests/acceptance/browse-test.js +++ b/wherehows-web/tests/acceptance/browse-test.js @@ -1,5 +1,4 @@ import { test } from 'qunit'; -import { delay } from 'wherehows-web/utils/promise-delay'; import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance'; import { authenticationUrl, testUser, testPassword } from 'wherehows-web/tests/helpers/login/constants'; import { @@ -8,7 +7,7 @@ import { loginSubmitButton } from 'wherehows-web/tests/helpers/login/page-element-constants'; -moduleForAcceptance('Acceptance | login', { +moduleForAcceptance('Acceptance | browse', { beforeEach() { visit(authenticationUrl); fillIn(loginUserInput, testUser); diff --git a/wherehows-web/tests/unit/routes/datasets/dataset/comments-test.js b/wherehows-web/tests/unit/routes/datasets/dataset/comments-test.js new file mode 100644 index 0000000000..7219f70fb1 --- /dev/null +++ b/wherehows-web/tests/unit/routes/datasets/dataset/comments-test.js @@ -0,0 +1,10 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:datasets/dataset/comments', 'Unit | Route | datasets/dataset/comments', { + needs: ['service:metrics'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +}); diff --git a/wherehows-web/tests/unit/routes/datasets/dataset/compliance-test.js b/wherehows-web/tests/unit/routes/datasets/dataset/compliance-test.js new file mode 100644 index 0000000000..af37e38723 --- /dev/null +++ b/wherehows-web/tests/unit/routes/datasets/dataset/compliance-test.js @@ -0,0 +1,10 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:datasets/dataset/compliance', 'Unit | Route | datasets/dataset/compliance', { + needs: ['service:metrics'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +}); diff --git a/wherehows-web/tests/unit/routes/datasets/dataset/ownership-test.js b/wherehows-web/tests/unit/routes/datasets/dataset/ownership-test.js new file mode 100644 index 0000000000..ddd9c608a5 --- /dev/null +++ b/wherehows-web/tests/unit/routes/datasets/dataset/ownership-test.js @@ -0,0 +1,10 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:datasets/dataset/ownership', 'Unit | Route | datasets/dataset/ownership', { + needs: ['service:metrics'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +}); diff --git a/wherehows-web/tests/unit/routes/datasets/dataset/properties-test.js b/wherehows-web/tests/unit/routes/datasets/dataset/properties-test.js new file mode 100644 index 0000000000..03fd1ad85a --- /dev/null +++ b/wherehows-web/tests/unit/routes/datasets/dataset/properties-test.js @@ -0,0 +1,10 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:datasets/dataset/properties', 'Unit | Route | datasets/dataset/properties', { + needs: ['service:metrics'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +}); diff --git a/wherehows-web/tests/unit/routes/datasets/dataset/relations-test.js b/wherehows-web/tests/unit/routes/datasets/dataset/relations-test.js new file mode 100644 index 0000000000..440a034963 --- /dev/null +++ b/wherehows-web/tests/unit/routes/datasets/dataset/relations-test.js @@ -0,0 +1,10 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:datasets/dataset/relations', 'Unit | Route | datasets/dataset/relations', { + needs: ['service:metrics'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +}); diff --git a/wherehows-web/tests/unit/routes/datasets/dataset/sample-test.js b/wherehows-web/tests/unit/routes/datasets/dataset/sample-test.js new file mode 100644 index 0000000000..e8530e775d --- /dev/null +++ b/wherehows-web/tests/unit/routes/datasets/dataset/sample-test.js @@ -0,0 +1,10 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:datasets/dataset/sample', 'Unit | Route | datasets/dataset/sample', { + needs: ['service:metrics'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +}); diff --git a/wherehows-web/tests/unit/routes/datasets/dataset/schema-test.js b/wherehows-web/tests/unit/routes/datasets/dataset/schema-test.js new file mode 100644 index 0000000000..57675af401 --- /dev/null +++ b/wherehows-web/tests/unit/routes/datasets/dataset/schema-test.js @@ -0,0 +1,10 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:datasets/dataset/schema', 'Unit | Route | datasets/dataset/schema', { + needs: ['service:metrics'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +});