2018-01-20 00:46:47 -08:00
|
|
|
import Route from '@ember/routing/route';
|
|
|
|
import { set, get, setProperties } from '@ember/object';
|
|
|
|
import { inject } from '@ember/service';
|
|
|
|
import $ from 'jquery';
|
2017-04-28 13:44:31 -07:00
|
|
|
import { makeUrnBreadcrumbs } from 'wherehows-web/utils/entities';
|
2017-10-16 11:35:13 -07:00
|
|
|
import { readDatasetCompliance, readDatasetComplianceSuggestion } from 'wherehows-web/utils/api/datasets/compliance';
|
2017-10-25 02:11:28 -07:00
|
|
|
import { readNonPinotProperties, readPinotProperties } from 'wherehows-web/utils/api/datasets/properties';
|
2017-09-19 18:20:03 -07:00
|
|
|
import { readDatasetComments } from 'wherehows-web/utils/api/datasets/comments';
|
2017-12-12 14:20:19 -08:00
|
|
|
import { readComplianceDataTypes } from 'wherehows-web/utils/api/list/compliance-datatypes';
|
2017-09-20 14:25:27 -07:00
|
|
|
import {
|
|
|
|
readDatasetColumns,
|
|
|
|
columnDataTypesAndFieldNames,
|
2017-10-23 16:50:48 -07:00
|
|
|
augmentObjectsWithHtmlComments
|
2017-09-20 14:25:27 -07:00
|
|
|
} from 'wherehows-web/utils/api/datasets/columns';
|
|
|
|
|
2018-01-23 13:32:47 -08:00
|
|
|
import { readDatasetOwners, getUserEntities } from 'wherehows-web/utils/api/datasets/owners';
|
|
|
|
import { isRequiredMinOwnersNotConfirmed } from 'wherehows-web/constants/datasets/owner';
|
2017-10-25 02:11:28 -07:00
|
|
|
import { readDataset, datasetUrnToId, readDatasetView } from 'wherehows-web/utils/api/datasets/dataset';
|
2017-09-20 14:25:27 -07:00
|
|
|
import isDatasetUrn from 'wherehows-web/utils/validators/urn';
|
2017-03-24 22:15:48 -07:00
|
|
|
|
2018-01-20 00:46:47 -08:00
|
|
|
const { getJSON } = $;
|
2017-09-20 14:25:27 -07:00
|
|
|
// TODO: DSS-6581 Move to URL retrieval module
|
2017-03-24 22:15:48 -07:00
|
|
|
const datasetsUrlRoot = '/api/v1/datasets';
|
|
|
|
const datasetUrl = id => `${datasetsUrlRoot}/${id}`;
|
|
|
|
const ownerTypeUrlRoot = '/api/v1/owner/types';
|
|
|
|
const getDatasetSampleUrl = id => `${datasetUrl(id)}/sample`;
|
|
|
|
const getDatasetImpactAnalysisUrl = id => `${datasetUrl(id)}/impacts`;
|
|
|
|
const getDatasetDependsUrl = id => `${datasetUrl(id)}/depends`;
|
|
|
|
const getDatasetPartitionsUrl = id => `${datasetUrl(id)}/access`;
|
|
|
|
const getDatasetReferencesUrl = id => `${datasetUrl(id)}/references`;
|
|
|
|
const getDatasetInstanceUrl = id => `${datasetUrl(id)}/instances`;
|
2017-06-19 17:11:53 -07:00
|
|
|
const getDatasetVersionUrl = (id, dbId) => `${datasetUrl(id)}/versions/db/${dbId}`;
|
2017-03-24 22:15:48 -07:00
|
|
|
|
|
|
|
export default Route.extend({
|
2017-06-19 17:11:53 -07:00
|
|
|
/**
|
|
|
|
* Runtime application configuration options
|
|
|
|
* @type {Ember.Service}
|
|
|
|
*/
|
2018-01-20 00:46:47 -08:00
|
|
|
configurator: inject(),
|
2017-06-19 17:11:53 -07:00
|
|
|
|
2017-09-20 16:10:52 -07:00
|
|
|
queryParams: {
|
|
|
|
urn: {
|
|
|
|
refreshModel: true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the dataset given a identifier from the dataset endpoint
|
2018-01-20 00:46:47 -08:00
|
|
|
* @param {string} dataset_id a identifier / id for the dataset to be fetched
|
2017-09-20 16:10:52 -07:00
|
|
|
* @param {string} [urn] optional urn identifier for dataset
|
|
|
|
* @return {Promise<IDataset>}
|
|
|
|
*/
|
2018-01-20 00:46:47 -08:00
|
|
|
async model({ dataset_id, urn }) {
|
|
|
|
let datasetId = dataset_id;
|
2017-09-20 16:10:52 -07:00
|
|
|
|
|
|
|
if (datasetId === 'urn' && isDatasetUrn(urn)) {
|
|
|
|
datasetId = await datasetUrnToId(urn);
|
|
|
|
}
|
|
|
|
|
|
|
|
return await readDataset(datasetId);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* resetting the urn query param when the hook is invoked
|
|
|
|
* @param {Controller} controller
|
|
|
|
*/
|
|
|
|
resetController(controller) {
|
|
|
|
set(controller, 'urn', void 0);
|
|
|
|
},
|
|
|
|
|
2017-03-24 22:15:48 -07:00
|
|
|
//TODO: DSS-6632 Correct server-side if status:error and record not found but response is 200OK
|
2017-02-13 11:26:50 -08:00
|
|
|
setupController(controller, model) {
|
2017-03-24 22:15:48 -07:00
|
|
|
let source = '';
|
2017-08-07 22:21:05 -07:00
|
|
|
let id = 0;
|
|
|
|
let urn = '';
|
2017-02-13 11:26:50 -08:00
|
|
|
|
|
|
|
if (model && model.id) {
|
2017-03-24 22:15:48 -07:00
|
|
|
({ id, source, urn } = model);
|
|
|
|
let { originalSchema = null } = model;
|
2017-02-13 11:26:50 -08:00
|
|
|
|
|
|
|
this.controllerFor('datasets').set('detailview', true);
|
|
|
|
if (originalSchema) {
|
2017-03-24 22:15:48 -07:00
|
|
|
set(model, 'schema', originalSchema);
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
controller.set('model', model);
|
|
|
|
} else if (model.dataset) {
|
2017-03-24 22:15:48 -07:00
|
|
|
({ id, source, urn } = model.dataset);
|
2017-02-13 11:26:50 -08:00
|
|
|
|
|
|
|
controller.set('model', model.dataset);
|
|
|
|
this.controllerFor('datasets').set('detailview', true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't set default zero Ids on controller
|
|
|
|
if (id) {
|
|
|
|
controller.set('datasetId', id);
|
2017-08-07 22:21:05 -07:00
|
|
|
|
|
|
|
/**
|
2017-09-20 14:25:27 -07:00
|
|
|
* ****************************
|
|
|
|
* Note: Refactor in progress *
|
|
|
|
* ****************************
|
2017-08-07 22:21:05 -07:00
|
|
|
* async IIFE sets the the complianceInfo and schemaFieldNamesMappedToDataTypes
|
|
|
|
* at once so observers will be buffered
|
|
|
|
* @param {number} id the dataset id
|
|
|
|
* @return {Promise.<void>}
|
|
|
|
*/
|
|
|
|
(async id => {
|
2017-09-20 14:25:27 -07:00
|
|
|
try {
|
2017-10-25 02:11:28 -07:00
|
|
|
let properties;
|
|
|
|
|
|
|
|
const [
|
2017-12-06 10:23:33 -08:00
|
|
|
{ schemaless, columns },
|
2017-10-25 02:11:28 -07:00
|
|
|
compliance,
|
2017-12-12 14:20:19 -08:00
|
|
|
complianceDataTypes,
|
2017-10-25 02:11:28 -07:00
|
|
|
complianceSuggestion,
|
|
|
|
datasetComments,
|
|
|
|
isInternal,
|
2017-11-13 11:07:38 -08:00
|
|
|
datasetView,
|
|
|
|
owners,
|
|
|
|
{ userEntitiesSource, userEntitiesMaps }
|
2017-10-25 02:11:28 -07:00
|
|
|
] = await Promise.all([
|
2017-09-20 14:25:27 -07:00
|
|
|
readDatasetColumns(id),
|
2017-10-16 11:35:13 -07:00
|
|
|
readDatasetCompliance(id),
|
2017-12-12 14:20:19 -08:00
|
|
|
readComplianceDataTypes(),
|
2017-10-16 11:35:13 -07:00
|
|
|
readDatasetComplianceSuggestion(id),
|
2017-10-24 00:24:19 -07:00
|
|
|
readDatasetComments(id),
|
2017-10-25 02:11:28 -07:00
|
|
|
get(this, 'configurator').getConfig('isInternal'),
|
2017-11-13 11:07:38 -08:00
|
|
|
readDatasetView(id),
|
|
|
|
readDatasetOwners(id),
|
|
|
|
getUserEntities()
|
2017-09-20 14:25:27 -07:00
|
|
|
]);
|
|
|
|
const { complianceInfo, isNewComplianceInfo } = compliance;
|
2017-10-23 16:50:48 -07:00
|
|
|
const schemas = augmentObjectsWithHtmlComments(columns);
|
2017-09-10 19:31:54 -07:00
|
|
|
|
2017-10-25 02:11:28 -07:00
|
|
|
if (String(source).toLowerCase() === 'pinot') {
|
|
|
|
properties = await readPinotProperties(id);
|
|
|
|
} else {
|
|
|
|
properties = { properties: await readNonPinotProperties(id) };
|
|
|
|
}
|
|
|
|
|
2017-09-20 14:25:27 -07:00
|
|
|
setProperties(controller, {
|
|
|
|
complianceInfo,
|
2017-12-12 14:20:19 -08:00
|
|
|
complianceDataTypes,
|
2017-09-20 14:25:27 -07:00
|
|
|
isNewComplianceInfo,
|
|
|
|
complianceSuggestion,
|
|
|
|
datasetComments,
|
2017-12-06 10:23:33 -08:00
|
|
|
schemaless,
|
2017-09-20 14:25:27 -07:00
|
|
|
schemas,
|
2017-10-24 00:24:19 -07:00
|
|
|
isInternal,
|
2017-10-25 02:11:28 -07:00
|
|
|
datasetView,
|
|
|
|
schemaFieldNamesMappedToDataTypes: columnDataTypesAndFieldNames(columns),
|
2017-11-13 11:07:38 -08:00
|
|
|
...properties,
|
|
|
|
owners,
|
|
|
|
userEntitiesMaps,
|
|
|
|
userEntitiesSource,
|
|
|
|
requiredMinNotConfirmed: isRequiredMinOwnersNotConfirmed(owners)
|
2017-09-20 14:25:27 -07:00
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
throw e;
|
|
|
|
}
|
2017-08-07 22:21:05 -07:00
|
|
|
})(id);
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
|
2017-03-24 22:15:48 -07:00
|
|
|
Promise.resolve(getJSON(getDatasetInstanceUrl(id)))
|
|
|
|
.then(({ status, instances = [] }) => {
|
|
|
|
if (status === 'ok' && instances.length) {
|
|
|
|
const [firstInstance = {}] = instances;
|
|
|
|
const { dbId } = firstInstance;
|
|
|
|
|
|
|
|
setProperties(controller, {
|
|
|
|
instances,
|
|
|
|
hasinstances: true,
|
|
|
|
currentInstance: firstInstance,
|
|
|
|
latestInstance: firstInstance
|
|
|
|
});
|
|
|
|
|
2017-06-19 17:11:53 -07:00
|
|
|
return Promise.resolve(getJSON(getDatasetVersionUrl(id, dbId))).then(({ status, versions = [] }) => {
|
2017-03-24 22:15:48 -07:00
|
|
|
if (status === 'ok' && versions.length) {
|
|
|
|
const [firstVersion] = versions;
|
|
|
|
|
|
|
|
setProperties(controller, {
|
|
|
|
versions,
|
|
|
|
hasversions: true,
|
|
|
|
currentVersion: firstVersion,
|
|
|
|
latestVersion: firstVersion
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-06-19 17:11:53 -07:00
|
|
|
return Promise.reject(new Error('Dataset versions request failed.'));
|
2017-03-24 22:15:48 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.reject(new Error('Dataset instances request failed.'));
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
setProperties(controller, {
|
|
|
|
hasinstances: false,
|
|
|
|
hasversions: false,
|
|
|
|
currentInstance: '0',
|
|
|
|
latestInstance: '0',
|
|
|
|
currentVersion: '0',
|
|
|
|
latestVersion: '0'
|
2017-02-13 11:26:50 -08:00
|
|
|
});
|
2017-03-24 22:15:48 -07:00
|
|
|
});
|
2017-02-13 11:26:50 -08:00
|
|
|
|
2017-04-28 13:44:31 -07:00
|
|
|
// 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?
|
2017-02-13 11:26:50 -08:00
|
|
|
if (urn) {
|
2017-04-28 13:44:31 -07:00
|
|
|
set(controller, 'breadcrumbs', makeUrnBreadcrumbs(urn));
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
|
2017-03-25 15:30:47 -07:00
|
|
|
// Get the list of ownerTypes from endpoint,
|
|
|
|
// then prevent display of the `consumer`
|
|
|
|
// insert on controller
|
2017-06-19 17:11:53 -07:00
|
|
|
Promise.resolve(getJSON(ownerTypeUrlRoot)).then(({ status, ownerTypes = [] }) => {
|
|
|
|
ownerTypes = ownerTypes
|
|
|
|
.filter(ownerType => String(ownerType).toLowerCase() !== 'consumer')
|
|
|
|
.sort((a, b) => a.localeCompare(b));
|
2017-03-26 06:36:23 -07:00
|
|
|
|
2017-06-19 17:11:53 -07:00
|
|
|
status === 'ok' && set(controller, 'ownerTypes', ownerTypes);
|
|
|
|
});
|
2017-02-13 11:26:50 -08:00
|
|
|
|
2017-03-24 22:15:48 -07:00
|
|
|
if (source.toLowerCase() !== 'pinot') {
|
|
|
|
Promise.resolve(getJSON(getDatasetSampleUrl(id)))
|
|
|
|
.then(({ status, sampleData = {} }) => {
|
|
|
|
if (status === 'ok') {
|
|
|
|
const { sample = [] } = sampleData;
|
|
|
|
const { length } = sample;
|
|
|
|
if (length) {
|
|
|
|
const samplesObject = sample.reduce(
|
2017-06-19 17:11:53 -07:00
|
|
|
(sampleObject, record, index) => ((sampleObject[`record${index}`] = record), sampleObject),
|
2017-03-24 22:15:48 -07:00
|
|
|
{}
|
|
|
|
);
|
|
|
|
// TODO: DSS-6122 Refactor global function reference
|
|
|
|
const node = window.JsonHuman.format(samplesObject);
|
|
|
|
|
|
|
|
controller.set('hasSamples', true);
|
|
|
|
|
|
|
|
// TODO: DSS-6122 Refactor setTimeout
|
2017-06-19 17:11:53 -07:00
|
|
|
setTimeout(function() {
|
|
|
|
const jsonHuman = document.getElementById('datasetSampleData-json-human');
|
|
|
|
if (jsonHuman) {
|
|
|
|
if (jsonHuman.children && jsonHuman.children.length) {
|
|
|
|
jsonHuman.removeChild(jsonHuman.childNodes[jsonHuman.children.length - 1]);
|
2017-03-24 22:15:48 -07:00
|
|
|
}
|
2017-06-19 17:11:53 -07:00
|
|
|
|
|
|
|
jsonHuman.appendChild(node);
|
|
|
|
}
|
|
|
|
}, 500);
|
2017-03-24 22:15:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
2017-03-24 22:15:48 -07:00
|
|
|
|
|
|
|
return Promise.reject(new Error('Dataset sample request failed.'));
|
|
|
|
})
|
|
|
|
.catch(() => set(controller, 'hasSamples', false));
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
|
2017-03-24 22:15:48 -07:00
|
|
|
Promise.resolve(getJSON(getDatasetImpactAnalysisUrl(id)))
|
|
|
|
.then(({ status, impacts = [] }) => {
|
|
|
|
if (status === 'ok') {
|
|
|
|
if (impacts.length) {
|
|
|
|
return setProperties(controller, {
|
|
|
|
hasImpacts: true,
|
|
|
|
impacts: impacts
|
|
|
|
});
|
|
|
|
}
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
|
2017-06-19 17:11:53 -07:00
|
|
|
return Promise.reject(new Error('Dataset impact analysis request failed.'));
|
2017-03-24 22:15:48 -07:00
|
|
|
})
|
|
|
|
.catch(() => set(controller, 'hasImpacts', false));
|
|
|
|
|
|
|
|
Promise.resolve(getJSON(getDatasetDependsUrl(id)))
|
|
|
|
.then(({ status, depends = [] }) => {
|
|
|
|
if (status === 'ok') {
|
|
|
|
if (depends.length) {
|
|
|
|
// TODO: DSS-6122 Refactor setTimeout,
|
|
|
|
// global function reference
|
|
|
|
setTimeout(window.initializeDependsTreeGrid, 500);
|
|
|
|
return setProperties(controller, {
|
|
|
|
depends,
|
|
|
|
hasDepends: true
|
|
|
|
});
|
|
|
|
}
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
|
2017-03-24 22:15:48 -07:00
|
|
|
return Promise.reject(new Error('Dataset depends request failed.'));
|
|
|
|
})
|
|
|
|
.catch(() => set(controller, 'hasDepends', false));
|
|
|
|
|
|
|
|
Promise.resolve(getJSON(getDatasetPartitionsUrl(id)))
|
|
|
|
.then(({ status, access = [] }) => {
|
|
|
|
if (status === 'ok' && access.length) {
|
|
|
|
return setProperties(controller, {
|
|
|
|
hasAccess: true,
|
|
|
|
accessibilities: access
|
|
|
|
});
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
|
2017-03-24 22:15:48 -07:00
|
|
|
return Promise.reject(new Error('Dataset partitions request failed.'));
|
|
|
|
})
|
|
|
|
.catch(() => set(controller, 'hasAccess', false));
|
|
|
|
|
|
|
|
Promise.resolve(getJSON(getDatasetReferencesUrl(id)))
|
|
|
|
.then(({ status, references = [] }) => {
|
|
|
|
if (status === 'ok' && references.length) {
|
|
|
|
setTimeout(window.initializeReferencesTreeGrid, 500);
|
|
|
|
|
|
|
|
return setProperties(controller, {
|
|
|
|
references,
|
|
|
|
hasReferences: true
|
|
|
|
});
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
|
2017-03-24 22:15:48 -07:00
|
|
|
return Promise.reject(new Error('Dataset references request failed.'));
|
|
|
|
})
|
|
|
|
.catch(() => set(controller, 'hasReferences', false));
|
2017-02-13 11:26:50 -08:00
|
|
|
},
|
|
|
|
|
2017-09-20 14:25:27 -07:00
|
|
|
actions: {
|
2017-03-24 22:15:48 -07:00
|
|
|
getDataset() {
|
2017-06-19 17:11:53 -07:00
|
|
|
Promise.resolve(getJSON(datasetUrl(this.get('controller.model.id')))).then(
|
|
|
|
({ status, dataset }) => status === 'ok' && set(this, 'controller.model', dataset)
|
2017-03-24 22:15:48 -07:00
|
|
|
);
|
2017-02-13 11:26:50 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|