Merge pull request #961 from theseyi/tabbed-routes

implements tabbed routes for datasets
This commit is contained in:
Seyi Adebajo 2018-02-09 12:02:04 -08:00 committed by GitHub
commit 068cf873ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 219 additions and 40 deletions

View File

@ -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 = <DatasetController>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 };

View File

@ -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'));
}
}

View File

@ -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() {

View File

@ -0,0 +1,3 @@
import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared';
export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Comments });

View File

@ -0,0 +1,3 @@
import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared';
export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Compliance });

View File

@ -0,0 +1,3 @@
import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared';
export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Ownership });

View File

@ -0,0 +1,3 @@
import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared';
export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Properties });

View File

@ -0,0 +1,3 @@
import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared';
export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Relations });

View File

@ -0,0 +1,3 @@
import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared';
export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.SampleData });

View File

@ -0,0 +1,3 @@
import { descendantDatasetRouteClassFactory, Tabs } from 'wherehows-web/constants/datasets/shared';
export default descendantDatasetRouteClassFactory({ selectedTab: Tabs.Schema });

View File

@ -29,7 +29,8 @@
{{/if}}
{{#if datasetView.deprecated}}
<a data-toggle="tab" href="#propertiestab" {{action "showProperties" preventDefault=false}}>
{{#link-to "datasets.dataset.properties" datasetId}}
<span class="deprecated-dataset">
DEPRECATED
</span>
@ -43,7 +44,8 @@
}}
</span>
</sup>
</a>
{{/link-to}}
{{/if}}
<h3>{{ model.name }}</h3>
@ -152,32 +154,35 @@
{{/if}}
</div>
{{#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--}}
<span style="display:none">
{{#tablist.tab "Access" on-select=(action (mut selection))}}ACL Access{{/tablist.tab}}
{{#tablist.tab tabIds.Access on-select=(action "tabSelectionChanged")}}ACL Access{{/tablist.tab}}
</span>
{{#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}}
<span class="notification-dot notification-dot--on-tab" aria-hidden="true"></span>
{{/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

View File

@ -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';

View File

@ -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);

View File

@ -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);
});

View File

@ -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);
});

View File

@ -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);
});

View File

@ -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);
});

View File

@ -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);
});

View File

@ -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);
});

View File

@ -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);
});