diff --git a/wherehows-web/app/actions/browse.js b/wherehows-web/app/actions/browse.js
index 7c84543036..6e3c75f4c4 100644
--- a/wherehows-web/app/actions/browse.js
+++ b/wherehows-web/app/actions/browse.js
@@ -32,11 +32,11 @@ const asyncRequestBrowseData = (page, entity, urls) =>
try {
const thunks = await Promise.all([
- dispatch(lazyRequestPagedFlows({ baseURL: urls.flows, page })),
- dispatch(lazyRequestPagedMetrics({ baseURL: urls.metrics, page })),
- dispatch(lazyRequestPagedDatasets({ baseURL: urls.datasets, page }))
+ dispatch(lazyRequestPagedFlows({ baseURL: urls.flows, query: { page } })),
+ dispatch(lazyRequestPagedMetrics({ baseURL: urls.metrics, query: { page } })),
+ dispatch(lazyRequestPagedDatasets({ baseURL: urls.datasets, query: { page } }))
]);
- const [...actions] = await Promise.all(thunks);
+ const [...actions] = thunks;
/**
* Check that none of the actions has an error flag in FSA
diff --git a/wherehows-web/app/actions/browse/entity.js b/wherehows-web/app/actions/browse/entity.js
index fb4f76d164..742f700393 100644
--- a/wherehows-web/app/actions/browse/entity.js
+++ b/wherehows-web/app/actions/browse/entity.js
@@ -3,6 +3,8 @@ import { createAction } from 'redux-actions';
import actionSet from 'wherehows-web/actions/action-set';
import { lazyRequestUrnPagedDatasets, lazyRequestDatasetNodes } from 'wherehows-web/actions/datasets';
+import { lazyRequestNamedPagedMetrics, lazyRequestMetricNodes } from 'wherehows-web/actions/metrics';
+import { lazyRequestFlowsNodes, lazyRequestPagedUrnApplicationFlows } from 'wherehows-web/actions/flows';
const { debug } = Ember;
@@ -23,29 +25,41 @@ const receiveNodeList = createAction(ActionTypes.RECEIVE_NODE_LIST);
* @param {String} listURL
* @param {Array} queryParams current list of query parameters for the Ember route
*/
-const asyncRequestNodeList = (params, listURL, { queryParams }) =>
+const asyncRequestEntityQueryData = (params, listURL, { queryParamsKeys: queryParams }) =>
/**
* Async thunk
* @param {Function} dispatch
* @return {Promise.<*>}
*/
async function(dispatch) {
- const { entity, page, urn } = params;
- const query = { page, urn };
+ const { entity, page, urn, name } = params;
+ // Extract relevant query parameters into query object
+ const query = { page, urn, name };
dispatch(requestNodeList({ entity, listURL, query, queryParams }));
+ // For each entity fetch the list of nodes and the actual entities for the given query
try {
let nodesResult = {}, pagedEntities = {};
switch (entity) {
case 'datasets':
- [nodesResult, pagedEntities] = await [
+ [nodesResult, pagedEntities] = await Promise.all([
dispatch(lazyRequestDatasetNodes({ listURL, query })),
dispatch(lazyRequestUrnPagedDatasets({ query }))
- ];
+ ]);
break;
case 'metrics':
+ [nodesResult, pagedEntities] = await Promise.all([
+ dispatch(lazyRequestMetricNodes({ listURL, query })),
+ dispatch(lazyRequestNamedPagedMetrics({ query }))
+ ]);
+ break;
case 'flows':
+ [nodesResult, pagedEntities] = await Promise.all([
+ dispatch(lazyRequestFlowsNodes({ listURL, query })),
+ dispatch(lazyRequestPagedUrnApplicationFlows({ query }))
+ ]);
+ break;
default:
return;
}
@@ -66,4 +80,4 @@ const asyncRequestNodeList = (params, listURL, { queryParams }) =>
}
};
-export { ActionTypes, asyncRequestNodeList };
+export { ActionTypes, asyncRequestEntityQueryData };
diff --git a/wherehows-web/app/actions/entities/entities.js b/wherehows-web/app/actions/entities/entities.js
index fb2d70a166..f7208a127a 100644
--- a/wherehows-web/app/actions/entities/entities.js
+++ b/wherehows-web/app/actions/entities/entities.js
@@ -40,10 +40,10 @@ const createAsyncThunk = (
* @return {Promise.<*>}
*/
) => async (dispatch, getState) => {
- const { status = 'error', data } = await asyncExecutor(getState);
+ const response = await asyncExecutor(getState);
- if (status === 'ok') {
- return dispatch(receiverActionCreator({ data }));
+ if (response.status === 'ok') {
+ return dispatch(receiverActionCreator(response));
}
return dispatch(receiverActionCreator(new Error(`Request failed with status ${status}`)));
diff --git a/wherehows-web/app/actions/entities/entity-request.js b/wherehows-web/app/actions/entities/entity-request.js
index eb3266ebdc..2adb6c0f59 100644
--- a/wherehows-web/app/actions/entities/entity-request.js
+++ b/wherehows-web/app/actions/entities/entity-request.js
@@ -46,6 +46,79 @@ const fetchPagedUrnEntities = entity => getState => {
});
};
+/**
+ * Takes a entity and returns a function to fetch entities by an entity url with a `name` segment
+ * @param {String} entity
+ */
+const fetchNamedPagedEntities = entity => getState => {
+ const { [entity]: { baseURL }, browseEntity: { [entity]: { query } } = {} } = getState();
+ const queryCopy = Object.assign({}, query);
+ const name = queryCopy.name;
+ let baseNameUrl = baseURL;
+
+ if (name) {
+ baseNameUrl = `${baseNameUrl}/name/${name}`;
+ delete queryCopy.name;
+ }
+
+ const namedPageURL = Object.keys(queryCopy).reduce((url, queryKey) => {
+ let queryValue = queryCopy[queryKey];
+ if (queryValue) {
+ return buildUrl(url, queryKey, queryValue);
+ }
+
+ return url;
+ }, baseNameUrl);
+
+ return fetch(namedPageURL).then(response => response.json()).then((payload = {}) => {
+ if (payload.status === 'ok') {
+ payload.data = Object.assign({}, payload.data, {
+ parentName: name || null
+ });
+ }
+
+ return payload;
+ });
+};
+
+/**
+ * Takes a entity name and returns a function the fetches an entity by urn path segment
+ * @param {String} entity
+ */
+const fetchUrnPathEntities = entity => getState => {
+ const { [entity]: { baseURL }, browseEntity: { [entity]: { query } = {} } = {} } = getState();
+ const queryCopy = Object.assign({}, query);
+ const urn = queryCopy.urn;
+ let baseUrnUrl = baseURL;
+
+ // If the urn exists, append its value to the base url for the entity and remove the attribute from the local
+ // copy of the queried parameters
+ if (urn) {
+ baseUrnUrl = `${baseUrnUrl}/${urn}`;
+ delete queryCopy.urn;
+ }
+
+ // Append the left over query params to the constructed url string
+ const urnPathUrl = Object.keys(query).reduce((url, queryKey) => {
+ let queryValue = query[queryKey];
+ if (queryValue) {
+ return buildUrl(url, queryKey, queryValue);
+ }
+
+ return url;
+ }, baseUrnUrl);
+
+ return fetch(urnPathUrl).then(response => response.json()).then((payload = {}) => {
+ if (payload.status === 'ok') {
+ payload.data = Object.assign({}, payload.data, {
+ parentUrn: urn || null
+ });
+ }
+
+ return payload;
+ });
+};
+
/**
* Request urn child nodes/ datasets for the specified entity
* @param entity
@@ -75,7 +148,56 @@ const fetchNodes = entity => getState => {
}, `${listURL}/${entity}`);
// TODO: DSS-7019 remove any parsing from response objects. in createLazyRequest and update all call sites
- return fetch(nodeURL).then(response => response.json()).then(({ status, nodes: data }) => ({ status, data }));
+ return fetch(nodeURL).then(response => response.json()).then((payload = {}) => {
+ return Object.assign({}, payload, {
+ parentUrn: query.urn || null
+ });
+ });
};
-export { fetchPagedEntities, fetchPagedUrnEntities, fetchNodes };
+/**
+ * For a given entity name, fetches the nodes at the list url by appending the entity name and name path as segments
+ * of the request url
+ * @param {String} entity
+ */
+const fetchNamedEntityNodes = entity => getState => {
+ // TODO: DSS-7019 rename queryParams to queryList, don't over load the name `queryParams`
+ const { browseEntity: { [entity]: { listURL = '', query: { name } } = {} } = {} } = getState();
+ const namePath = name ? `/${name}` : '';
+ const nodeURL = `${listURL}/${entity}${namePath}`;
+
+ return fetch(nodeURL).then(response => response.json()).then((payload = {}) => {
+ return Object.assign({}, payload, {
+ //TODO: Should this be namedEntityNodes vs urnPathEntityNodes
+ parentName: name || null
+ });
+ });
+};
+
+/**
+ * For a given entity, fetches the entities nodes at the list url by appending the entity name and the urn path
+ * as segments of the request url
+ * @param {String} entity
+ */
+const fetchUrnPathEntityNodes = entity => getState => {
+ const { browseEntity: { [entity]: { listURL = '', query: { urn } } = {} } = {} } = getState();
+ const urnPath = urn ? `/${urn}` : '';
+ const urnListUrl = `${listURL}/${entity}${urnPath}`;
+
+ return fetch(urnListUrl).then(response => response.json()).then((payload = {}) => {
+ return Object.assign({}, payload, {
+ //TODO: Should this be namedEntityNodes vs urnPathEntityNodes
+ parentUrn: urn || null
+ });
+ });
+};
+
+export {
+ fetchPagedEntities,
+ fetchPagedUrnEntities,
+ fetchNodes,
+ fetchNamedPagedEntities,
+ fetchNamedEntityNodes,
+ fetchUrnPathEntities,
+ fetchUrnPathEntityNodes
+};
diff --git a/wherehows-web/app/actions/entities/index.js b/wherehows-web/app/actions/entities/index.js
index e66b8c571b..23acce739d 100644
--- a/wherehows-web/app/actions/entities/index.js
+++ b/wherehows-web/app/actions/entities/index.js
@@ -1,2 +1,2 @@
export * from 'wherehows-web/actions/entities/entities';
-export { fetchPagedEntities, fetchPagedUrnEntities, fetchNodes } from 'wherehows-web/actions/entities/entity-request';
+export * from 'wherehows-web/actions/entities/entity-request';
diff --git a/wherehows-web/app/actions/flows.js b/wherehows-web/app/actions/flows.js
index 587c40b7c6..0647f0fcc5 100644
--- a/wherehows-web/app/actions/flows.js
+++ b/wherehows-web/app/actions/flows.js
@@ -1,5 +1,10 @@
import { createAction } from 'redux-actions';
-import { createLazyRequest, fetchPagedEntities } from 'wherehows-web/actions/entities';
+import {
+ createLazyRequest,
+ fetchPagedEntities,
+ fetchUrnPathEntityNodes,
+ fetchUrnPathEntities
+} from 'wherehows-web/actions/entities';
import actionSet from 'wherehows-web/actions/action-set';
/**
@@ -9,7 +14,13 @@ import actionSet from 'wherehows-web/actions/action-set';
const ActionTypes = {
REQUEST_PAGED_FLOWS: actionSet('REQUEST_PAGED_FLOWS'),
SELECT_PAGED_FLOWS: actionSet('SELECT_PAGED_FLOWS'),
- RECEIVE_PAGED_FLOWS: actionSet('RECEIVE_PAGED_FLOWS')
+ RECEIVE_PAGED_FLOWS: actionSet('RECEIVE_PAGED_FLOWS'),
+
+ REQUEST_PAGED_URN_FLOWS: actionSet('REQUEST_PAGED_URN_FLOWS'),
+ RECEIVE_PAGED_URN_FLOWS: actionSet('RECEIVE_PAGED_URN_FLOWS'),
+
+ REQUEST_FLOWS_NODES: actionSet('REQUEST_FLOWS_NODES'),
+ RECEIVE_FLOWS_NODES: actionSet('RECEIVE_FLOWS_NODES')
};
const requestPagedFlows = createAction(ActionTypes.REQUEST_PAGED_FLOWS);
@@ -21,7 +32,28 @@ const receivePagedFlows = createAction(
() => ({ receivedAt: Date.now() })
);
+const requestPagedUrnFlows = createAction(ActionTypes.REQUEST_PAGED_URN_FLOWS);
+
+const receivePagedUrnFlows = createAction(
+ ActionTypes.RECEIVE_PAGED_URN_FLOWS,
+ ({ data }) => data,
+ () => ({ receivedAt: Date.now() })
+);
+
+const requestFlowsNodes = createAction(ActionTypes.REQUEST_FLOWS_NODES);
+const receiveFlowsNodes = createAction(
+ ActionTypes.RECEIVE_FLOWS_NODES,
+ response => response,
+ // meta data attached to the ActionTypes.RECEIVE_PAGED_FLOWS action
+ () => ({ receivedAt: Date.now() })
+);
+
// async action/thunk creator for ActionTypes.REQUEST_PAGED_FLOWS
+// TODO: Is this redundant since we can use name without a name queryParam supplied
const lazyRequestPagedFlows = createLazyRequest(requestPagedFlows, receivePagedFlows, fetchPagedEntities('flows'));
-export { ActionTypes, lazyRequestPagedFlows };
+const lazyRequestFlowsNodes = createLazyRequest(requestFlowsNodes, receiveFlowsNodes, fetchUrnPathEntityNodes('flows'));
+
+const lazyRequestPagedUrnApplicationFlows = createLazyRequest(requestPagedUrnFlows, receivePagedUrnFlows, fetchUrnPathEntities('flows'));
+
+export { ActionTypes, lazyRequestPagedFlows, lazyRequestFlowsNodes, lazyRequestPagedUrnApplicationFlows };
diff --git a/wherehows-web/app/actions/metrics.js b/wherehows-web/app/actions/metrics.js
index ac27de0e87..77d2a8f4b9 100644
--- a/wherehows-web/app/actions/metrics.js
+++ b/wherehows-web/app/actions/metrics.js
@@ -1,5 +1,10 @@
import { createAction } from 'redux-actions';
-import { createLazyRequest, fetchPagedEntities } from 'wherehows-web/actions/entities';
+import {
+ createLazyRequest,
+ fetchPagedEntities,
+ fetchNamedEntityNodes,
+ fetchNamedPagedEntities
+} from 'wherehows-web/actions/entities';
import actionSet from 'wherehows-web/actions/action-set';
/**
@@ -9,7 +14,13 @@ import actionSet from 'wherehows-web/actions/action-set';
const ActionTypes = {
REQUEST_PAGED_METRICS: actionSet('REQUEST_PAGED_METRICS'),
SELECT_PAGED_METRICS: actionSet('SELECT_PAGED_METRICS'),
- RECEIVE_PAGED_METRICS: actionSet('RECEIVE_PAGED_METRICS')
+ RECEIVE_PAGED_METRICS: actionSet('RECEIVE_PAGED_METRICS'),
+
+ REQUEST_PAGED_NAMED_METRICS: actionSet('REQUEST_PAGED_NAMED_METRICS'),
+ RECEIVE_PAGED_NAMED_METRICS: actionSet('RECEIVE_PAGED_NAMED_METRICS'),
+
+ REQUEST_METRICS_NODES: actionSet('REQUEST_METRICS_NODES'),
+ RECEIVE_METRICS_NODES: actionSet('RECEIVE_METRICS_NODES')
};
const requestPagedMetrics = createAction(ActionTypes.REQUEST_PAGED_METRICS);
@@ -23,10 +34,47 @@ const receivePagedMetrics = createAction(
() => ({ receivedAt: Date.now() })
);
+const requestPagedNamedMetrics = createAction(ActionTypes.REQUEST_PAGED_NAMED_METRICS);
+
+const receivePagedNamedMetrics = createAction(
+ ActionTypes.RECEIVE_PAGED_NAMED_METRICS,
+ ({ data }) => data,
+ () => ({ receivedAt: Date.now() })
+);
+
+const requestMetricNodes = createAction(ActionTypes.REQUEST_METRICS_NODES);
+const receiveMetricNodes = createAction(
+ ActionTypes.RECEIVE_METRICS_NODES,
+ response => response,
+ // meta data attached to the ActionTypes.RECEIVE_PAGED_METRICS action
+ () => ({ receivedAt: Date.now() })
+);
// async action/thunk creator for ActionTypes.REQUEST_PAGED_METRICS
-const lazyRequestPagedMetrics = createLazyRequest(requestPagedMetrics, receivePagedMetrics, fetchPagedEntities('metrics'));
+const lazyRequestPagedMetrics = createLazyRequest(
+ requestPagedMetrics,
+ receivePagedMetrics,
+ fetchPagedEntities('metrics')
+);
// async action/thunk creator for ActionTypes.SELECT_PAGED_METRICS
-const lazySelectPagedMetrics = createLazyRequest(selectPagedMetrics, receivePagedMetrics, fetchPagedEntities('metrics'));
+const lazySelectPagedMetrics = createLazyRequest(
+ selectPagedMetrics,
+ receivePagedMetrics,
+ fetchPagedEntities('metrics')
+);
-export { ActionTypes, lazyRequestPagedMetrics, lazySelectPagedMetrics };
+const lazyRequestMetricNodes = createLazyRequest(requestMetricNodes, receiveMetricNodes, fetchNamedEntityNodes('metrics'));
+
+const lazyRequestNamedPagedMetrics = createLazyRequest(
+ requestPagedNamedMetrics,
+ receivePagedNamedMetrics,
+ fetchNamedPagedEntities('metrics')
+);
+
+export {
+ ActionTypes,
+ lazyRequestPagedMetrics,
+ lazySelectPagedMetrics,
+ lazyRequestMetricNodes,
+ lazyRequestNamedPagedMetrics
+};
diff --git a/wherehows-web/app/components/ace-editor.js b/wherehows-web/app/components/ace-editor.js
index 76ddc169f5..729763f708 100644
--- a/wherehows-web/app/components/ace-editor.js
+++ b/wherehows-web/app/components/ace-editor.js
@@ -44,15 +44,11 @@ export default Ember.Component.extend({
var url = this.get('savePath');
url = url.replace(/\{.\w+\}/, this.get('itemId'))
var method = 'POST';
- var token = $("#csrfToken").val().replace('/', '');
- var data = {"csrfToken": token};
+ var data = {};
data[this.get('saveParam')] = this.editor.getSession().getValue()
$.ajax({
url: url,
method: method,
- headers: {
- 'Csrf-Token': token
- },
dataType: 'json',
data: data
}).done(function (data, txt, xhr) {
diff --git a/wherehows-web/app/components/browser/containers/browser-rail.js b/wherehows-web/app/components/browser/containers/browser-rail.js
index 81f749465e..c96e2c9cd4 100644
--- a/wherehows-web/app/components/browser/containers/browser-rail.js
+++ b/wherehows-web/app/components/browser/containers/browser-rail.js
@@ -1,6 +1,6 @@
import Ember from 'ember';
import connect from 'ember-redux/components/connect';
-import { urnRegex } from 'wherehows-web/utils/validators/urn';
+import { urnRegex, specialFlowUrnRegex } from 'wherehows-web/utils/validators/urn';
const { Component } = Ember;
@@ -10,13 +10,7 @@ const { Component } = Ember;
* @type {RegExp}
*/
const pageRegex = /\/page\/([0-9]+)/i;
-/**
- * Matches a url string path segment that optionally starts with a hash followed by forward slash,
- * either datasets or flows or metrics, forward slash, number of varying length and optional trailing slash
- * The number is retained
- * @type {RegExp}
- */
-const entityRegex = /^#?\/(?:datasets|metrics|flows)\/([0-9]+)\/?/;
+const nameRegex = /\/name\/([0-9a-z()_{}\[\]\/\s]+)/i;
/**
* Takes a node url and parses out the query params and path spec to be included in the link component
@@ -26,6 +20,8 @@ const entityRegex = /^#?\/(?:datasets|metrics|flows)\/([0-9]+)\/?/;
const nodeUrlToQueryParams = nodeUrl => {
const pageMatch = nodeUrl.match(pageRegex);
const urnMatch = nodeUrl.match(urnRegex);
+ const flowUrnMatch = nodeUrl.match(specialFlowUrnRegex);
+ const nameMatch = nodeUrl.match(nameRegex);
let queryParams = null;
// If we have a page match, append the page number to eventual urn object
@@ -37,17 +33,41 @@ const nodeUrlToQueryParams = nodeUrl => {
});
}
+ if (Array.isArray(nameMatch)) {
+ let match = nameMatch[1];
+ match = match.split('/page')[0];
+
+ queryParams = Object.assign({}, queryParams, {
+ name: match
+ });
+ }
+
// If we have a urn match, append the urn to eventual query params object
- if (Array.isArray(urnMatch)) {
+ if (Array.isArray(urnMatch) || Array.isArray(flowUrnMatch)) {
+ const urn = urnMatch || [flowUrnMatch[1]];
+
queryParams = Object.assign({}, queryParams, {
// Extract the entire match as urn value
- urn: urnMatch[0]
+ urn: urn[0]
});
}
return queryParams;
};
+const getNodes = (entity, state = {}) => query =>
+ ({
+ get datasets() {
+ return state[entity].nodesByUrn[query];
+ },
+ get metrics() {
+ return state[entity].nodesByName[query];
+ },
+ get flows() {
+ return this.datasets;
+ }
+ }[entity]);
+
/**
* Selector function that takes a Redux Store to extract
* state props for the browser-rail
@@ -58,36 +78,52 @@ const stateToComputed = state => {
// Extracts the current entity active in the browse view
const { browseEntity: { currentEntity = '' } = {} } = state;
// Retrieves properties for the current entity from the state tree
- const { [currentEntity]: { nodesByUrn = {}, query: { urn } = {} } } = state;
+ const { browseEntity: { [currentEntity]: { query: { urn, name } } } } = state;
// Removes `s` from the end of each entity name. Ember routes for individual entities are singular, and also
// returned entities contain id prop that is the singular type name, suffixed with Id, e.g. metricId
// datasets -> dataset, metrics -> metric, flows -> flow
const singularName = currentEntity.slice(0, -1);
- let nodes = nodesByUrn[urn] || [];
+ const query =
+ {
+ datasets: urn,
+ metrics: name,
+ flows: urn
+ }[currentEntity] || null;
+ let nodes = getNodes(currentEntity, state)(query) || [];
/**
* Creates dynamic query link params for each node
* @type {Array} list of child nodes or datasets to render
*/
- nodes = nodes.map(({ nodeName, nodeUrl, [`${singularName}Id`]: id }) => {
+ nodes = nodes.map(({ nodeName, nodeUrl, [`${singularName}Id`]: id, application = '' }) => {
nodeUrl = String(nodeUrl);
+ const node = {
+ title: nodeName,
+ text: nodeName
+ };
// If the id prop (datasetId|metricId|flowId) is truthy, then it is a standalone entity
if (id) {
- return {
- title: nodeName,
- text: nodeName,
+ let idNode = Object.assign({}, node);
+
+ if (singularName === 'flow' && application) {
+ idNode = Object.assign({}, idNode, {
+ queryParams: {
+ name: application
+ }
+ });
+ }
+
+ return Object.assign({}, idNode, {
route: `${currentEntity}.${singularName}`,
- model: nodeUrl.match(entityRegex)[1]
- };
+ model: id
+ });
}
- return {
- title: nodeName,
- text: nodeName,
+ return Object.assign({}, node, {
route: `browse.entity`,
model: currentEntity,
queryParams: nodeUrlToQueryParams(nodeUrl)
- };
+ });
});
return { nodes };
diff --git a/wherehows-web/app/components/browser/containers/browser-viewport.js b/wherehows-web/app/components/browser/containers/browser-viewport.js
index 0615947bce..0d7b1b67c1 100644
--- a/wherehows-web/app/components/browser/containers/browser-viewport.js
+++ b/wherehows-web/app/components/browser/containers/browser-viewport.js
@@ -3,6 +3,25 @@ import connect from 'ember-redux/components/connect';
const { Component } = Ember;
+/**
+ * Extract the childIds for an entity under a specific category
+ * @param entity
+ * @param state
+ */
+const getChildIds = (entity, state = {}) => query =>
+ ({
+ get datasets() {
+ return state[entity].byUrn[query];
+ },
+ get metrics() {
+ return state[entity].byName[query];
+ },
+ get flows() {
+ // Flows are retrieved by name as well
+ return this.datasets;
+ }
+ }[entity]);
+
/**
* Selector function that takes a Redux Store to extract
* state props for the browser-rail
@@ -12,12 +31,17 @@ const stateToComputed = state => {
// Extracts the current entity active in the browse view
const { browseEntity: { currentEntity = '' } = {} } = state;
// Retrieves properties for the current entity from the state tree
- let { browseEntity: { [currentEntity]: { query: { urn } } } } = state;
+ const { browseEntity: { [currentEntity]: { query: { urn, name } } } } = state;
// Default urn to null, which represents the top-level parent
- urn = urn || null;
+ const query =
+ {
+ datasets: urn,
+ metrics: name,
+ flows: urn
+ }[currentEntity] || null;
// Read the list of ids child entity ids associated with the urn
- const { [currentEntity]: { byUrn: { [urn]: childIds = [] } } } = state;
+ const childIds = getChildIds(currentEntity, state)(query) || [];
// Read the list of entities, stored in the byId property
const { [currentEntity]: { byId: entities } } = state;
/**
diff --git a/wherehows-web/app/components/dataset-confidential.js b/wherehows-web/app/components/dataset-confidential.js
index 112ffb2491..721a90e1a3 100644
--- a/wherehows-web/app/components/dataset-confidential.js
+++ b/wherehows-web/app/components/dataset-confidential.js
@@ -41,13 +41,13 @@ const datasetClassifiersKeys = Object.keys(datasetClassifiers);
// TODO: DSS-6671 Extract to constants module
const successUpdating = 'Your changes have been successfully saved!';
const failedUpdating = 'Oops! We are having trouble updating this dataset at the moment.';
-const missingTypes = 'Looks like some fields are marked as `Confidential` or ' +
- '`Highly Confidential` but do not have a specified `Field Format`?';
+const missingTypes =
+ 'Looks like some fields are marked as `Confidential` or `Highly Confidential` but do not have a specified `Field Format`?';
const hiddenTrackingFieldsMsg = htmlSafe(
'
Hey! Just a heads up that some fields in this dataset have been hidden from the table(s) below. ' +
- 'These are tracking fields for which we\'ve been able to predetermine the compliance classification.
' +
- '
For example: header.memberId, requestHeader. ' +
- 'Hopefully, this saves you some scrolling!
'
+ "These are tracking fields for which we've been able to predetermine the compliance classification." +
+ '
For example: header.memberId, requestHeader. ' +
+ 'Hopefully, this saves you some scrolling!
'
);
/**
@@ -55,8 +55,7 @@ const hiddenTrackingFieldsMsg = htmlSafe(
* for now, so no need to make into a helper
* @param {String} string
*/
-const formatAsCapitalizedStringWithSpaces = string =>
- string.replace(/[A-Z]/g, match => ` ${match}`).capitalize();
+const formatAsCapitalizedStringWithSpaces = string => string.replace(/[A-Z]/g, match => ` ${match}`).capitalize();
export default Component.extend({
sortColumnWithName: 'identifierField',
@@ -73,10 +72,9 @@ export default Component.extend({
// Map logicalTypes to options better consumed by drop down
logicalTypes: ['', ...logicalTypes.sort()].map(value => {
- const label = value ?
- value.replace(/_/g, ' ')
- .replace(/([A-Z]{3,})/g, f => f.toLowerCase().capitalize()) :
- 'Not Specified';
+ const label = value
+ ? value.replace(/_/g, ' ').replace(/([A-Z]{3,})/g, f => f.toLowerCase().capitalize())
+ : 'Not Specified';
return {
value,
@@ -122,25 +120,26 @@ export default Component.extend({
*/
fieldNameToClass: computed(
`${sourceClassificationKey}.{confidential,limitedDistribution,highlyConfidential}.[]`,
- function () {
+ function() {
const sourceClasses = getWithDefault(this, sourceClassificationKey, []);
// Creates a lookup table of fieldNames to classification
// Also, the expectation is that the association from fieldName -> classification
// is one-to-one hence no check to ensure a fieldName gets clobbered
// in the lookup assignment
- return Object.keys(sourceClasses)
- .reduce((lookup, classificationKey) =>
- // For the provided classificationKey, iterate over it's fieldNames,
- // and assign the classificationKey to the fieldName in the table
- (sourceClasses[classificationKey] || []).reduce((lookup, field) => {
- const { identifierField } = field;
- // cKey -> 1...fieldNameList => fieldName -> cKey
- lookup[identifierField] = classificationKey;
- return lookup;
- }, lookup),
- {}
- );
- }),
+ return Object.keys(sourceClasses).reduce(
+ (lookup, classificationKey) =>
+ // For the provided classificationKey, iterate over it's fieldNames,
+ // and assign the classificationKey to the fieldName in the table
+ (sourceClasses[classificationKey] || []).reduce((lookup, field) => {
+ const { identifierField } = field;
+ // cKey -> 1...fieldNameList => fieldName -> cKey
+ lookup[identifierField] = classificationKey;
+ return lookup;
+ }, lookup),
+ {}
+ );
+ }
+ ),
/**
* Lists all the dataset fields found in the `columns` api, and intersects
@@ -166,10 +165,9 @@ export default Component.extend({
// assign to field, otherwise null
// Rather than assigning the default classification here, nulling gives the benefit of allowing
// subsequent consumer know that this field did not have a previous classification
- const field = classification ?
- get(this, `${sourceClassificationKey}.${classification}`)
- .findBy('identifierField', identifierField) :
- null;
+ const field = classification
+ ? get(this, `${sourceClassificationKey}.${classification}`).findBy('identifierField', identifierField)
+ : null;
// Extract the logicalType from the field
const logicalType = isPresent(field) ? field.logicalType : null;
@@ -190,21 +188,22 @@ export default Component.extend({
* tracking header.
* Used to indicate to viewer that these fields are hidden.
*/
- containsHiddenTrackingFields: computed(
- 'classificationDataFieldsSansHiddenTracking.length',
- function () {
- // If their is a diff in complianceDataFields and complianceDataFieldsSansHiddenTracking,
- // then we have hidden tracking fields
- return get(this, 'classificationDataFieldsSansHiddenTracking.length') !== get(this, 'classificationDataFields.length');
- }),
+ containsHiddenTrackingFields: computed('classificationDataFieldsSansHiddenTracking.length', function() {
+ // If their is a diff in complianceDataFields and complianceDataFieldsSansHiddenTracking,
+ // then we have hidden tracking fields
+ return (
+ get(this, 'classificationDataFieldsSansHiddenTracking.length') !== get(this, 'classificationDataFields.length')
+ );
+ }),
/**
* @type {Array.