mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-12 18:47:45 +00:00
reenable breadcumb navigation based on li urn format. support either hdfs / non-hdfs. add home
This commit is contained in:
parent
1ce7e05687
commit
86804ac2c9
29
wherehows-web/app/components/datasets/urn-breadcrumbs.ts
Normal file
29
wherehows-web/app/components/datasets/urn-breadcrumbs.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import Component from '@ember/component';
|
||||||
|
import { computed, get } from '@ember/object';
|
||||||
|
import ComputedProperty from '@ember/object/computed';
|
||||||
|
import { bakeUrnBreadcrumbs } from 'wherehows-web/utils/entities';
|
||||||
|
import { IDatasetBreadcrumb } from 'wherehows-web/utils/entities/bake-urn-breadcrumbs';
|
||||||
|
|
||||||
|
export default class UrnBreadcrumbs extends Component {
|
||||||
|
tagName = 'ul';
|
||||||
|
|
||||||
|
classNames = ['nacho-breadcrumbs'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Urn for the dataset to be represented in the breadcrumbs
|
||||||
|
* @type {string}
|
||||||
|
* @memberof UrnBreadcrumbs
|
||||||
|
*/
|
||||||
|
urn: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the breadcrumbs for the dataset with the related urn
|
||||||
|
* @type {ComputedProperty<Array<IDatasetBreadcrumb>>}
|
||||||
|
* @memberof UrnBreadcrumbs
|
||||||
|
*/
|
||||||
|
breadcrumbs: ComputedProperty<Array<IDatasetBreadcrumb>> = computed('urn', function(
|
||||||
|
this: UrnBreadcrumbs
|
||||||
|
): Array<IDatasetBreadcrumb> {
|
||||||
|
return bakeUrnBreadcrumbs(get(this, 'urn'));
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -2,17 +2,6 @@ import Route from '@ember/routing/route';
|
|||||||
import { set, get, setProperties } from '@ember/object';
|
import { set, get, setProperties } from '@ember/object';
|
||||||
import { inject } from '@ember/service';
|
import { inject } from '@ember/service';
|
||||||
import { makeUrnBreadcrumbs } from 'wherehows-web/utils/entities';
|
import { makeUrnBreadcrumbs } from 'wherehows-web/utils/entities';
|
||||||
import { readDatasetCompliance, readDatasetComplianceSuggestion } from 'wherehows-web/utils/api/datasets/compliance';
|
|
||||||
import { readNonPinotProperties, readPinotProperties } from 'wherehows-web/utils/api/datasets/properties';
|
|
||||||
import { readDatasetComments } from 'wherehows-web/utils/api/datasets/comments';
|
|
||||||
import { readComplianceDataTypes } from 'wherehows-web/utils/api/list/compliance-datatypes';
|
|
||||||
import {
|
|
||||||
readDatasetColumns,
|
|
||||||
columnDataTypesAndFieldNames,
|
|
||||||
augmentObjectsWithHtmlComments
|
|
||||||
} from 'wherehows-web/utils/api/datasets/columns';
|
|
||||||
|
|
||||||
import { readDatasetOwners, getUserEntities } from 'wherehows-web/utils/api/datasets/owners';
|
|
||||||
import { isRequiredMinOwnersNotConfirmed } from 'wherehows-web/constants/datasets/owner';
|
import { isRequiredMinOwnersNotConfirmed } from 'wherehows-web/constants/datasets/owner';
|
||||||
import { readDatasetById, readDatasetByUrn } from 'wherehows-web/utils/api/datasets/dataset';
|
import { readDatasetById, readDatasetByUrn } from 'wherehows-web/utils/api/datasets/dataset';
|
||||||
import isUrn, { isWhUrn, isLiUrn, convertWhUrnToLiUrn, encodeUrn, decodeUrn } from 'wherehows-web/utils/validators/urn';
|
import isUrn, { isWhUrn, isLiUrn, convertWhUrnToLiUrn, encodeUrn, decodeUrn } from 'wherehows-web/utils/validators/urn';
|
||||||
@ -74,18 +63,8 @@ export default Route.extend({
|
|||||||
set(controller, 'model', model);
|
set(controller, 'model', model);
|
||||||
setProperties(controller, {
|
setProperties(controller, {
|
||||||
isInternal: await get(this, 'configurator').getConfig('isInternal')
|
isInternal: await get(this, 'configurator').getConfig('isInternal')
|
||||||
// ...properties,
|
|
||||||
// requiredMinNotConfirmed: isRequiredMinOwnersNotConfirmed(owners)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// If urn exists, create a breadcrumb list
|
|
||||||
// TODO: DSS-7068 Refactoring in progress , move this to a computed prop on a container component
|
|
||||||
// FIXME: DSS-7068 browse.entity?urn route does not exist for last item in breadcrumb i.e. the dataset
|
|
||||||
// currently being viewed. Should this even be a link in the first place?
|
|
||||||
if (model.uri) {
|
|
||||||
set(controller, 'breadcrumbs', makeUrnBreadcrumbs(model.uri));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Get current user ACL permission info for ACL access tab
|
// TODO: Get current user ACL permission info for ACL access tab
|
||||||
Promise.resolve(currentUser())
|
Promise.resolve(currentUser())
|
||||||
.then(userInfo => {
|
.then(userInfo => {
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
<li class="nacho-breadcrumbs__crumb">
|
||||||
|
|
||||||
|
{{link-to
|
||||||
|
"datasets"
|
||||||
|
"browse.entity"
|
||||||
|
"datasets"
|
||||||
|
(query-params page=1 prefix="" platform="")
|
||||||
|
class="nacho-breadcrumbs__crumb__grain"
|
||||||
|
}}
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{{#each breadcrumbs as |crumb|}}
|
||||||
|
<li class="nacho-breadcrumbs__crumb">
|
||||||
|
|
||||||
|
{{link-to
|
||||||
|
crumb.crumb
|
||||||
|
"browse.entity"
|
||||||
|
"datasets"
|
||||||
|
(query-params page=1 prefix=crumb.prefix platform=crumb.platform)
|
||||||
|
class="nacho-breadcrumbs__crumb__grain"
|
||||||
|
}}
|
||||||
|
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
@ -1,13 +1,6 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div id="dataset">
|
<div id="dataset">
|
||||||
<ul class="nacho-breadcrumbs">
|
{{datasets/urn-breadcrumbs urn=model.uri}}
|
||||||
{{#each breadcrumbs as |crumb|}}
|
|
||||||
<li class="nacho-breadcrumbs__crumb">
|
|
||||||
{{link-to crumb.crumb "browse.entity" "datasets" (query-params page=1 urn=crumb.urn)
|
|
||||||
class="nacho-breadcrumbs__crumb__grain"}}
|
|
||||||
</li>
|
|
||||||
{{/each}}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-5">
|
<div class="col-xs-5">
|
||||||
@ -51,6 +44,7 @@
|
|||||||
<h3>{{ model.nativeName }}</h3>
|
<h3>{{ model.nativeName }}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{dataset-owner-list owners=owners datasetName=model.nativeName}}
|
{{dataset-owner-list owners=owners datasetName=model.nativeName}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
48
wherehows-web/app/utils/entities/bake-urn-breadcrumbs.ts
Normal file
48
wherehows-web/app/utils/entities/bake-urn-breadcrumbs.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { DatasetPlatform } from 'wherehows-web/constants';
|
||||||
|
import { datasetUrnRegexLI } from 'wherehows-web/utils/validators/urn';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the interface for a breadcrumb object
|
||||||
|
* @interface IDatasetBreadcrumb
|
||||||
|
*/
|
||||||
|
export interface IDatasetBreadcrumb {
|
||||||
|
crumb: string;
|
||||||
|
platform: DatasetPlatform;
|
||||||
|
prefix: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a urn string and parses it into an array of breadcrumb objects with crumb, and query params, prefix and/or platform as
|
||||||
|
* properties.
|
||||||
|
* Hierarchy is implied in element ordering
|
||||||
|
* @param {string} urn the dataset urn in li format
|
||||||
|
* @returns {Array<IDatasetBreadcrumb>}
|
||||||
|
*/
|
||||||
|
export default (urn: string): Array<IDatasetBreadcrumb> => {
|
||||||
|
const liDatasetUrn = datasetUrnRegexLI.exec(urn);
|
||||||
|
const breadcrumbs: Array<IDatasetBreadcrumb> = [];
|
||||||
|
|
||||||
|
if (liDatasetUrn) {
|
||||||
|
const [, platform, segments] = liDatasetUrn;
|
||||||
|
const isHdfs = String(platform).toLowerCase() === DatasetPlatform.HDFS;
|
||||||
|
// For HDFS drop leading slash
|
||||||
|
const hierarchy = isHdfs ? segments.split('/').slice(1) : segments.split('.');
|
||||||
|
|
||||||
|
return [platform, ...hierarchy].reduce((breadcrumbs, crumb, index) => {
|
||||||
|
const previousCrumb = breadcrumbs[index - 1];
|
||||||
|
// if hdfs, precede with slash, otherwise trailing period
|
||||||
|
const prefix = !index ? '' : isHdfs ? `${previousCrumb.prefix}/${crumb}` : `${previousCrumb.prefix}${crumb}.`;
|
||||||
|
|
||||||
|
return [
|
||||||
|
...breadcrumbs,
|
||||||
|
{
|
||||||
|
crumb,
|
||||||
|
prefix,
|
||||||
|
platform: <DatasetPlatform>platform
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}, breadcrumbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return breadcrumbs;
|
||||||
|
};
|
||||||
@ -1,3 +1,3 @@
|
|||||||
import makeUrnBreadcrumbs from 'wherehows-web/utils/entities/make-urn-breadcrumbs';
|
import bakeUrnBreadcrumbs from 'wherehows-web/utils/entities/bake-urn-breadcrumbs';
|
||||||
|
|
||||||
export { makeUrnBreadcrumbs };
|
export { bakeUrnBreadcrumbs };
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
import { datasetUrnRegexWH } from 'wherehows-web/utils/validators/urn';
|
|
||||||
|
|
||||||
interface IBreadCrumb {
|
|
||||||
crumb: string;
|
|
||||||
urn: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a urn string and parse it into an array of breadcrumb objects with crumb, and urn as
|
|
||||||
* properties.
|
|
||||||
* Hierarchy is implied in element ordering
|
|
||||||
* @param {String} urn
|
|
||||||
* @return {Array.<{crumb, urn}>|null}
|
|
||||||
*/
|
|
||||||
export default (urn: string): Array<{ crumb: string; urn: string }> | null => {
|
|
||||||
const urnMatch = datasetUrnRegexWH.exec(urn);
|
|
||||||
|
|
||||||
if (urnMatch) {
|
|
||||||
// Initial element in a match array from RegExp#exec is the full match, not needed here
|
|
||||||
const urnParts = urnMatch.filter((_match, index) => index);
|
|
||||||
// Splits the 2nd captured group into an array of urn names and spreads into a new list
|
|
||||||
const crumbs = [urnParts[0], ...urnParts[1].split('/')];
|
|
||||||
|
|
||||||
// Reduces the crumbs into a list of crumb names and urn paths
|
|
||||||
return crumbs.reduce(
|
|
||||||
(breadcrumbs, crumb, index) => {
|
|
||||||
const previousCrumb = breadcrumbs[index - 1];
|
|
||||||
const breadcrumb: IBreadCrumb = {
|
|
||||||
crumb,
|
|
||||||
// First item is root
|
|
||||||
urn: !index ? `${crumb}:///` : `${previousCrumb.urn}${crumb}/`
|
|
||||||
};
|
|
||||||
|
|
||||||
return [...breadcrumbs, breadcrumb];
|
|
||||||
},
|
|
||||||
<Array<IBreadCrumb>>[]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
@ -1,4 +1,8 @@
|
|||||||
|
import { decodeUrn } from 'wherehows-web/utils/validators/urn';
|
||||||
|
|
||||||
const urn = 'urn:li:dataset:(urn:li:dataPlatform:hdfs,%2Fseg1s%2Fseg2%2Fseg3%2Fseg4%2Fdataset-node,PROD)';
|
const urn = 'urn:li:dataset:(urn:li:dataPlatform:hdfs,%2Fseg1s%2Fseg2%2Fseg3%2Fseg4%2Fdataset-node,PROD)';
|
||||||
|
const nonHdfsUrn = 'urn:li:dataset:(urn:li:dataPlatform:db,ABOOK.ABOOK_DATA,PROD)';
|
||||||
|
const hdfsUrn = decodeUrn(urn);
|
||||||
|
|
||||||
const whUrnToLiUrnMap = [
|
const whUrnToLiUrnMap = [
|
||||||
['espresso:///ETLInfra/AllTables', 'urn:li:dataset:(urn:li:dataPlatform:espresso,ETLInfra.AllTables,PROD)'],
|
['espresso:///ETLInfra/AllTables', 'urn:li:dataset:(urn:li:dataPlatform:espresso,ETLInfra.AllTables,PROD)'],
|
||||||
@ -13,4 +17,4 @@ const whUrnToLiUrnMap = [
|
|||||||
['oracle:///ABOOK/ABOOK_DATA', 'urn:li:dataset:(urn:li:dataPlatform:oracle,ABOOK.ABOOK_DATA,PROD)']
|
['oracle:///ABOOK/ABOOK_DATA', 'urn:li:dataset:(urn:li:dataPlatform:oracle,ABOOK.ABOOK_DATA,PROD)']
|
||||||
];
|
];
|
||||||
|
|
||||||
export { urn, whUrnToLiUrnMap };
|
export { urn, whUrnToLiUrnMap, hdfsUrn, nonHdfsUrn };
|
||||||
|
|||||||
@ -0,0 +1,56 @@
|
|||||||
|
import { moduleForComponent, test } from 'ember-qunit';
|
||||||
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
import { hdfsUrn, nonHdfsUrn } from 'wherehows-web/mirage/fixtures/urn';
|
||||||
|
import { datasetUrnRegexLI } from 'wherehows-web/utils/validators/urn';
|
||||||
|
|
||||||
|
moduleForComponent('datasets/urn-breadcrumbs', 'Integration | Component | datasets/urn breadcrumbs', {
|
||||||
|
integration: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const home = ['datasets'];
|
||||||
|
|
||||||
|
test('it renders only the home breadcrumb without a valid urn', function(assert) {
|
||||||
|
this.render(hbs`{{datasets/urn-breadcrumbs}}`);
|
||||||
|
const homeCrumb = document.querySelector('.nacho-breadcrumbs__crumb');
|
||||||
|
|
||||||
|
assert.equal(homeCrumb.textContent.trim(), 'datasets', 'shows the home breadcrumb');
|
||||||
|
assert.equal(
|
||||||
|
document.querySelectorAll('.nacho-breadcrumbs__crumb').length,
|
||||||
|
1,
|
||||||
|
'only one breadcrumb is rendered when a urn is not provided'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it renders breadcrumbs with a valid hdfs urn', function(assert) {
|
||||||
|
const [, platform, segments] = datasetUrnRegexLI.exec(hdfsUrn);
|
||||||
|
const segmentParts = segments.split('/').slice(1);
|
||||||
|
let crumbs;
|
||||||
|
|
||||||
|
this.set('urn', hdfsUrn);
|
||||||
|
this.render(hbs`{{datasets/urn-breadcrumbs urn=urn}}`);
|
||||||
|
|
||||||
|
crumbs = document.querySelectorAll('.nacho-breadcrumbs__crumb');
|
||||||
|
|
||||||
|
assert.equal(crumbs.length, home.length + [platform].length + segmentParts.length, '');
|
||||||
|
|
||||||
|
[...home, platform, ...segmentParts].forEach((node, index) =>
|
||||||
|
assert.equal(node, crumbs[index].textContent.trim(), `breadcrumb ${index} has expected text ${node}`)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it renders breadcrumbs with a valid non hdfs urn', function(assert) {
|
||||||
|
const [, platform, segments] = datasetUrnRegexLI.exec(nonHdfsUrn);
|
||||||
|
const segmentParts = segments.split('.');
|
||||||
|
let crumbs;
|
||||||
|
|
||||||
|
this.set('urn', nonHdfsUrn);
|
||||||
|
this.render(hbs`{{datasets/urn-breadcrumbs urn=urn}}`);
|
||||||
|
|
||||||
|
crumbs = document.querySelectorAll('.nacho-breadcrumbs__crumb');
|
||||||
|
|
||||||
|
assert.equal(crumbs.length, home.length + [platform].length + segmentParts.length, '');
|
||||||
|
|
||||||
|
[...home, platform, ...segmentParts].forEach((node, index) =>
|
||||||
|
assert.equal(node, crumbs[index].textContent.trim(), `breadcrumb ${index} has expected text ${node}`)
|
||||||
|
);
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user