mirror of
https://github.com/datahub-project/datahub.git
synced 2025-07-15 13:14:37 +00:00
v2: add intergration tests for container components. temporarily skips acceptance tests for datasets. further i implementation for v2 api integration and urn handling
This commit is contained in:
parent
1dbcaf1476
commit
0eb87ec99b
@ -71,10 +71,10 @@ export default class DatasetAuthors extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of valid owner type strings returned from the remote api endpoint
|
* A list of valid owner type strings returned from the remote api endpoint
|
||||||
* @type {Array<string>}
|
* @type {Array<OwnerType>}
|
||||||
* @memberof DatasetAuthors
|
* @memberof DatasetAuthors
|
||||||
*/
|
*/
|
||||||
ownerTypes: Array<string>;
|
ownerTypes: Array<OwnerType>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag that resolves in the affirmative if the number of confirmed owner is less the minimum required
|
* Flag that resolves in the affirmative if the number of confirmed owner is less the minimum required
|
||||||
|
@ -204,7 +204,13 @@ export default class DatasetCompliance extends ObservableDecorator {
|
|||||||
isCompliancePolicyAvailable: boolean = false;
|
isCompliancePolicyAvailable: boolean = false;
|
||||||
showAllDatasetMemberData: boolean;
|
showAllDatasetMemberData: boolean;
|
||||||
complianceInfo: void | IComplianceInfo;
|
complianceInfo: void | IComplianceInfo;
|
||||||
complianceSuggestion: IComplianceSuggestion;
|
|
||||||
|
/**
|
||||||
|
* Suggested values for compliance types e.g. identifier type and/or logical type
|
||||||
|
* @type {IComplianceSuggestion | void}
|
||||||
|
*/
|
||||||
|
complianceSuggestion: IComplianceSuggestion | void;
|
||||||
|
|
||||||
schemaFieldNamesMappedToDataTypes: Array<Pick<IDatasetColumn, 'dataType' | 'fieldName'>>;
|
schemaFieldNamesMappedToDataTypes: Array<Pick<IDatasetColumn, 'dataType' | 'fieldName'>>;
|
||||||
onReset: <T extends { status: ApiStatus }>() => Promise<T>;
|
onReset: <T extends { status: ApiStatus }>() => Promise<T>;
|
||||||
onSave: <T extends { status: ApiStatus }>() => Promise<T>;
|
onSave: <T extends { status: ApiStatus }>() => Promise<T>;
|
||||||
@ -676,10 +682,12 @@ export default class DatasetCompliance extends ObservableDecorator {
|
|||||||
function(this: DatasetCompliance): ISchemaFieldsToPolicy {
|
function(this: DatasetCompliance): ISchemaFieldsToPolicy {
|
||||||
const { complianceEntities = [], modifiedTime = '0' } = get(this, 'complianceInfo') || {};
|
const { complianceEntities = [], modifiedTime = '0' } = get(this, 'complianceInfo') || {};
|
||||||
// Truncated list of Dataset field names and data types currently returned from the column endpoint
|
// Truncated list of Dataset field names and data types currently returned from the column endpoint
|
||||||
const columnFieldProps = get(this, 'schemaFieldNamesMappedToDataTypes').map(({ fieldName, dataType }) => ({
|
const columnFieldProps = getWithDefault(this, 'schemaFieldNamesMappedToDataTypes', []).map(
|
||||||
identifierField: fieldName,
|
({ fieldName, dataType }) => ({
|
||||||
dataType
|
identifierField: fieldName,
|
||||||
}));
|
dataType
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return this.mapColumnIdFieldsToCurrentPrivacyPolicy(columnFieldProps, complianceEntities, {
|
return this.mapColumnIdFieldsToCurrentPrivacyPolicy(columnFieldProps, complianceEntities, {
|
||||||
policyModificationTime: modifiedTime
|
policyModificationTime: modifiedTime
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
import { set, get, setProperties, getProperties } from '@ember/object';
|
import { set, get, setProperties, getProperties } from '@ember/object';
|
||||||
import { warn } from '@ember/debug';
|
import { warn } from '@ember/debug';
|
||||||
|
import { action } from 'ember-decorators/object';
|
||||||
|
import { IDatasetColumn, IDatasetColumnWithHtmlComments } from 'wherehows-web/typings/api/datasets/columns';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached module reference to the class name for visually hiding toggled off schema view
|
* Cached module reference to the class name for visually hiding toggled off schema view
|
||||||
@ -23,16 +25,22 @@ export default class DatasetSchema extends Component {
|
|||||||
json = '{}';
|
json = '{}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the jsonViewer dom element
|
* List of schema properties for the dataset
|
||||||
* @type {Element}
|
* @type {IDatasetColumnWithHtmlComments | IDatasetColumn}
|
||||||
*/
|
*/
|
||||||
jsonViewer = <Element | null>null;
|
schemas: Array<IDatasetColumnWithHtmlComments | IDatasetColumn>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the jsonViewer dom element
|
||||||
|
* @type {Element | null}
|
||||||
|
*/
|
||||||
|
jsonViewer: Element | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the jsonTable dom element
|
* Reference to the jsonTable dom element
|
||||||
* @type {Element}
|
* @type {Element | null}
|
||||||
*/
|
*/
|
||||||
jsonTable = <Element | null>null;
|
jsonTable: Element | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a readable JSON structure of the dataset schema
|
* Constructs a readable JSON structure of the dataset schema
|
||||||
@ -54,6 +62,19 @@ export default class DatasetSchema extends Component {
|
|||||||
*/
|
*/
|
||||||
buildTableView = (jsonTable: Element) => $(jsonTable).treegrid();
|
buildTableView = (jsonTable: Element) => $(jsonTable).treegrid();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds or rebuild the dataset schema / json view based on a flag to toggle this behaviour
|
||||||
|
*/
|
||||||
|
buildView() {
|
||||||
|
if (get(this, 'isTable')) {
|
||||||
|
const jsonTable = get(this, 'jsonTable');
|
||||||
|
jsonTable && this.buildTableView(jsonTable);
|
||||||
|
} else {
|
||||||
|
const jsonViewer = get(this, 'jsonViewer');
|
||||||
|
jsonViewer && this.buildJsonView(jsonViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retains references to the DOM elements for showing the schema
|
* Retains references to the DOM elements for showing the schema
|
||||||
*/
|
*/
|
||||||
@ -71,13 +92,7 @@ export default class DatasetSchema extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
didReceiveAttrs(this: DatasetSchema) {
|
didReceiveAttrs(this: DatasetSchema) {
|
||||||
if (get(this, 'isTable')) {
|
this.buildView();
|
||||||
const jsonTable = get(this, 'jsonTable');
|
|
||||||
jsonTable && this.buildTableView(jsonTable);
|
|
||||||
} else {
|
|
||||||
const jsonViewer = get(this, 'jsonViewer');
|
|
||||||
jsonViewer && this.buildJsonView(jsonViewer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
didRender() {
|
didRender() {
|
||||||
@ -91,21 +106,21 @@ export default class DatasetSchema extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
actions = {
|
@action
|
||||||
/**
|
/**
|
||||||
* Handles the toggle for which schema view to be rendered.
|
* Handles the toggling of table vs. json view of dataset schema information
|
||||||
* Currently toggled between a table render and a JSON view
|
* @param {"table" | "json"} view
|
||||||
* @param {"table" | "json"} [view = table]
|
*/
|
||||||
*/
|
showView(this: DatasetSchema, view: 'table' | 'json' = 'table') {
|
||||||
showView(this: DatasetSchema, view: 'table' | 'json' = 'table') {
|
const isTable = set(this, 'isTable', view === 'table');
|
||||||
const isTable = set(this, 'isTable', view === 'table');
|
const { jsonViewer, jsonTable } = getProperties(this, ['jsonTable', 'jsonViewer']);
|
||||||
const { jsonViewer, jsonTable } = getProperties(this, ['jsonTable', 'jsonViewer']);
|
|
||||||
|
|
||||||
if (jsonTable && jsonViewer) {
|
if (jsonTable && jsonViewer) {
|
||||||
isTable
|
this.buildView();
|
||||||
? (jsonViewer.classList.add(hiddenClassName), jsonTable.classList.remove(hiddenClassName))
|
|
||||||
: (jsonViewer.classList.remove(hiddenClassName), jsonTable.classList.add(hiddenClassName));
|
isTable
|
||||||
}
|
? (jsonViewer.classList.add(hiddenClassName), jsonTable.classList.remove(hiddenClassName))
|
||||||
|
: (jsonViewer.classList.remove(hiddenClassName), jsonTable.classList.add(hiddenClassName));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,166 @@
|
|||||||
|
import Component from '@ember/component';
|
||||||
|
import { get, set, setProperties, getProperties } from '@ember/object';
|
||||||
|
import { task, TaskInstance } from 'ember-concurrency';
|
||||||
|
import { action } from 'ember-decorators/object';
|
||||||
|
import { IDatasetColumn } from 'wherehows-web/typings/api/datasets/columns';
|
||||||
|
import { IComplianceInfo, IComplianceSuggestion } from 'wherehows-web/typings/api/datasets/compliance';
|
||||||
|
import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset';
|
||||||
|
import { IDatasetSchema } from 'wherehows-web/typings/api/datasets/schema';
|
||||||
|
import { IComplianceDataType } from 'wherehows-web/typings/api/list/compliance-datatypes';
|
||||||
|
import {
|
||||||
|
IReadComplianceResult,
|
||||||
|
readDatasetComplianceByUrn,
|
||||||
|
readDatasetComplianceSuggestionByUrn,
|
||||||
|
saveDatasetComplianceByUrn
|
||||||
|
} from 'wherehows-web/utils/api';
|
||||||
|
import { columnDataTypesAndFieldNames } from 'wherehows-web/utils/api/datasets/columns';
|
||||||
|
import { readDatasetSchemaByUrn } from 'wherehows-web/utils/api/datasets/schema';
|
||||||
|
import { readComplianceDataTypes } from 'wherehows-web/utils/api/list/compliance-datatypes';
|
||||||
|
|
||||||
|
export default class DatasetComplianceContainer extends Component {
|
||||||
|
/**
|
||||||
|
* Mapping of field names on the dataset schema to the respective dataType
|
||||||
|
* @type {Array<Pick<IDatasetColumn, 'dataType' | 'fieldName'>>}
|
||||||
|
*/
|
||||||
|
schemaFieldNamesMappedToDataTypes: Array<Pick<IDatasetColumn, 'dataType' | 'fieldName'>> = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of compliance data-type objects
|
||||||
|
* @type {Array<IComplianceDataType>}
|
||||||
|
*/
|
||||||
|
complianceDataTypes: Array<IComplianceDataType> = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag indicating that the compliance information for this dataset is new
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
isNewComplianceInfo: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object containing the suggested values for the compliance form
|
||||||
|
* @type {IComplianceSuggestion | void}
|
||||||
|
*/
|
||||||
|
complianceSuggestion: IComplianceSuggestion | void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object containing the compliance information for the dataset
|
||||||
|
* @type {IComplianceInfo | void}
|
||||||
|
*/
|
||||||
|
complianceInfo: IComplianceInfo | void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The platform / db that the dataset is persisted
|
||||||
|
* @type {IDatasetView.platform}
|
||||||
|
*/
|
||||||
|
platform: IDatasetView['platform'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag indicating if the dataset has a schema representation
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
schemaless: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nativeName of the dataset
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
datasetName: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The urn identifier for the dataset
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
urn: string;
|
||||||
|
|
||||||
|
didInsertElement() {
|
||||||
|
get(this, 'getContainerDataTask').perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
didUpdateAttrs() {
|
||||||
|
get(this, 'getContainerDataTask').perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An async parent task to group all data tasks for this container component
|
||||||
|
* @type {Task<TaskInstance<Promise<any>>, (a?: any) => TaskInstance<TaskInstance<Promise<any>>>>}
|
||||||
|
*/
|
||||||
|
getContainerDataTask = task(function*(
|
||||||
|
this: DatasetComplianceContainer
|
||||||
|
): IterableIterator<TaskInstance<Promise<any>>> {
|
||||||
|
const tasks = Object.values(
|
||||||
|
getProperties(this, [
|
||||||
|
'getComplianceTask',
|
||||||
|
'getComplianceDataTypesTask',
|
||||||
|
'getComplianceSuggestionsTask',
|
||||||
|
'getDatasetSchemaTask'
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
yield* tasks.map(task => task.perform());
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the compliance properties for the dataset
|
||||||
|
* @type {Task<Promise<IReadComplianceResult>, (a?: any) => TaskInstance<Promise<IReadComplianceResult>>>}
|
||||||
|
*/
|
||||||
|
getComplianceTask = task(function*(
|
||||||
|
this: DatasetComplianceContainer
|
||||||
|
): IterableIterator<Promise<IReadComplianceResult>> {
|
||||||
|
const { isNewComplianceInfo, complianceInfo } = yield readDatasetComplianceByUrn(get(this, 'urn'));
|
||||||
|
|
||||||
|
setProperties(this, { isNewComplianceInfo, complianceInfo });
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the compliance data types
|
||||||
|
* @type {Task<Promise<Array<IComplianceDataType>>, (a?: any) => TaskInstance<Promise<Array<IComplianceDataType>>>>}
|
||||||
|
*/
|
||||||
|
getComplianceDataTypesTask = task(function*(
|
||||||
|
this: DatasetComplianceContainer
|
||||||
|
): IterableIterator<Promise<Array<IComplianceDataType>>> {
|
||||||
|
const complianceDataTypes = yield readComplianceDataTypes();
|
||||||
|
|
||||||
|
set(this, 'complianceDataTypes', complianceDataTypes);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the suggestions for the compliance properties on the dataset
|
||||||
|
* @type {Task<Promise<IComplianceSuggestion>, (a?: any) => TaskInstance<Promise<IComplianceSuggestion>>>}
|
||||||
|
*/
|
||||||
|
getComplianceSuggestionsTask = task(function*(
|
||||||
|
this: DatasetComplianceContainer
|
||||||
|
): IterableIterator<Promise<IComplianceSuggestion>> {
|
||||||
|
const complianceSuggestion = yield readDatasetComplianceSuggestionByUrn(get(this, 'urn'));
|
||||||
|
|
||||||
|
set(this, 'complianceSuggestion', complianceSuggestion);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the schema properties for the dataset
|
||||||
|
* @type {Task<Promise<IDatasetSchema>, (a?: any) => TaskInstance<Promise<IDatasetSchema>>>}
|
||||||
|
*/
|
||||||
|
getDatasetSchemaTask = task(function*(this: DatasetComplianceContainer): IterableIterator<Promise<IDatasetSchema>> {
|
||||||
|
const { columns, schemaless } = yield readDatasetSchemaByUrn(get(this, 'urn'));
|
||||||
|
const schemaFieldNamesMappedToDataTypes = columnDataTypesAndFieldNames(columns);
|
||||||
|
|
||||||
|
setProperties(this, { schemaFieldNamesMappedToDataTypes, schemaless });
|
||||||
|
});
|
||||||
|
|
||||||
|
@action
|
||||||
|
/**
|
||||||
|
* Persists the updates to the compliance policy on the remote host
|
||||||
|
* @param {IComplianceInfo} complianceInfo
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
savePrivacyCompliancePolicy(complianceInfo: IComplianceInfo): Promise<void> {
|
||||||
|
return saveDatasetComplianceByUrn(get(this, 'urn'), complianceInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
/**
|
||||||
|
* Resets the compliance information for the dataset with the previously persisted properties
|
||||||
|
*/
|
||||||
|
resetPrivacyCompliancePolicy() {
|
||||||
|
get(this, 'getComplianceTask').perform();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
import Component from '@ember/component';
|
||||||
|
import { get, set, getProperties } from '@ember/object';
|
||||||
|
import { task, TaskInstance } from 'ember-concurrency';
|
||||||
|
import { action } from 'ember-decorators/object';
|
||||||
|
import { IOwner } from 'wherehows-web/typings/api/datasets/owners';
|
||||||
|
import {
|
||||||
|
OwnerType,
|
||||||
|
readDatasetOwnersByUrn,
|
||||||
|
readDatasetOwnerTypesWithoutConsumer,
|
||||||
|
updateDatasetOwnersByUrn
|
||||||
|
} from 'wherehows-web/utils/api/datasets/owners';
|
||||||
|
|
||||||
|
export default class DatasetOwnershipContainer extends Component {
|
||||||
|
/**
|
||||||
|
* The urn identifier for the dataset
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
urn: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of owners for the dataset
|
||||||
|
* @type {Array<IOwner>}
|
||||||
|
*/
|
||||||
|
owners: Array<IOwner>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of types available for a dataset owner
|
||||||
|
* @type {Array<OwnerType>}
|
||||||
|
*/
|
||||||
|
ownerTypes: Array<OwnerType>;
|
||||||
|
|
||||||
|
didInsertElement() {
|
||||||
|
get(this, 'getContainerDataTask').perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
didUpdateAttrs() {
|
||||||
|
get(this, 'getContainerDataTask').perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An async parent task to group all data tasks for this container component
|
||||||
|
* @type {Task<TaskInstance<Promise<any>>, (a?: any) => TaskInstance<TaskInstance<Promise<any>>>>}
|
||||||
|
*/
|
||||||
|
getContainerDataTask = task(function*(this: DatasetOwnershipContainer): IterableIterator<TaskInstance<Promise<any>>> {
|
||||||
|
const tasks = Object.values(getProperties(this, ['getDatasetOwnersTask', 'getDatasetOwnerTypesTask']));
|
||||||
|
|
||||||
|
yield* tasks.map(task => task.perform());
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the owners for this dataset
|
||||||
|
* @type {Task<Promise<Array<IOwner>>, (a?: any) => TaskInstance<Promise<Array<IOwner>>>>}
|
||||||
|
*/
|
||||||
|
getDatasetOwnersTask = task(function*(this: DatasetOwnershipContainer): IterableIterator<Promise<Array<IOwner>>> {
|
||||||
|
const owners = yield readDatasetOwnersByUrn(get(this, 'urn'));
|
||||||
|
|
||||||
|
set(this, 'owners', owners);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the owner types available
|
||||||
|
* @type {Task<Promise<Array<OwnerType>>, (a?: any) => TaskInstance<Promise<Array<OwnerType>>>>}
|
||||||
|
*/
|
||||||
|
getDatasetOwnerTypesTask = task(function*(
|
||||||
|
this: DatasetOwnershipContainer
|
||||||
|
): IterableIterator<Promise<Array<OwnerType>>> {
|
||||||
|
const ownerTypes = yield readDatasetOwnerTypesWithoutConsumer();
|
||||||
|
set(this, 'ownerTypes', ownerTypes);
|
||||||
|
});
|
||||||
|
|
||||||
|
@action
|
||||||
|
/**
|
||||||
|
* Persists the changes to the owners list
|
||||||
|
* @param {Array<IOwner>} updatedOwners
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
saveOwnerChanges(updatedOwners: Array<IOwner>): Promise<void> {
|
||||||
|
return updateDatasetOwnersByUrn(get(this, 'urn'), '', updatedOwners);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
import Component from '@ember/component';
|
||||||
|
import { get, setProperties } from '@ember/object';
|
||||||
|
import { task } from 'ember-concurrency';
|
||||||
|
import { action } from 'ember-decorators/object';
|
||||||
|
import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset';
|
||||||
|
import { readDatasetByUrn } from 'wherehows-web/utils/api/datasets/dataset';
|
||||||
|
import { updateDatasetDeprecationByUrn } from 'wherehows-web/utils/api/datasets/properties';
|
||||||
|
|
||||||
|
export default class DatasetPropertiesContainer extends Component {
|
||||||
|
/**
|
||||||
|
* The urn identifier for the dataset
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
urn: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag indicating that the dataset is deprecated
|
||||||
|
* @type {boolean | null}
|
||||||
|
*/
|
||||||
|
deprecated: boolean | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text string, intended to indicate the reason for deprecation
|
||||||
|
* @type {string | null}
|
||||||
|
*/
|
||||||
|
deprecationNote: string | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* THe list of properties for the dataset, currently unavailable for v2
|
||||||
|
* @type {any[]}
|
||||||
|
*/
|
||||||
|
properties: Array<never> = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.deprecationNote || (this.deprecationNote = '');
|
||||||
|
}
|
||||||
|
|
||||||
|
didInsertElement() {
|
||||||
|
get(this, 'getDeprecationPropertiesTask').perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
didUpdateAttrs() {
|
||||||
|
get(this, 'getDeprecationPropertiesTask').perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the persisted deprecation properties for the dataset
|
||||||
|
* @type {Task<Promise<IDatasetView>, (a?: any) => TaskInstance<Promise<IDatasetView>>>}
|
||||||
|
*/
|
||||||
|
getDeprecationPropertiesTask = task(function*(
|
||||||
|
this: DatasetPropertiesContainer
|
||||||
|
): IterableIterator<Promise<IDatasetView>> {
|
||||||
|
const { deprecated, deprecationNote } = yield readDatasetByUrn(get(this, 'urn'));
|
||||||
|
setProperties(this, { deprecated, deprecationNote });
|
||||||
|
});
|
||||||
|
|
||||||
|
@action
|
||||||
|
/**
|
||||||
|
* Persists the changes to the dataset deprecation properties upstream
|
||||||
|
* @param {boolean} isDeprecated
|
||||||
|
* @param {string} updatedDeprecationNote
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
async updateDeprecation(isDeprecated: boolean, updatedDeprecationNote: string): Promise<void> {
|
||||||
|
await updateDatasetDeprecationByUrn(get(this, 'urn'), isDeprecated, updatedDeprecationNote);
|
||||||
|
get(this, 'getDeprecationPropertiesTask').perform();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
import Component from '@ember/component';
|
||||||
|
import { get, setProperties } from '@ember/object';
|
||||||
|
import { task } from 'ember-concurrency';
|
||||||
|
import { IDatasetColumn, IDatasetColumnWithHtmlComments } from 'wherehows-web/typings/api/datasets/columns';
|
||||||
|
import { IDatasetSchema } from 'wherehows-web/typings/api/datasets/schema';
|
||||||
|
import { augmentObjectsWithHtmlComments } from 'wherehows-web/utils/api/datasets/columns';
|
||||||
|
import { readDatasetSchemaByUrn } from 'wherehows-web/utils/api/datasets/schema';
|
||||||
|
|
||||||
|
export default class DatasetSchemaContainer extends Component {
|
||||||
|
/**
|
||||||
|
* The urn identifier for the dataset
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
urn: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* json string for the dataset schema properties
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
json: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of schema properties for the dataset
|
||||||
|
* @type {IDatasetColumnWithHtmlComments | IDatasetColumn}
|
||||||
|
*/
|
||||||
|
schemas: Array<IDatasetColumnWithHtmlComments | IDatasetColumn>;
|
||||||
|
|
||||||
|
didInsertElement() {
|
||||||
|
get(this, 'getDatasetSchemaTask').perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
didUpdateAttrs() {
|
||||||
|
get(this, 'getDatasetSchemaTask').perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the schema for the dataset
|
||||||
|
* @type {Task<Promise<IDatasetSchema>, (a?: any) => TaskInstance<Promise<IDatasetSchema>>>}
|
||||||
|
*/
|
||||||
|
getDatasetSchemaTask = task(function*(this: DatasetSchemaContainer): IterableIterator<Promise<IDatasetSchema>> {
|
||||||
|
let schemas,
|
||||||
|
{ columns, rawSchema: json } = yield readDatasetSchemaByUrn(get(this, 'urn'));
|
||||||
|
schemas = augmentObjectsWithHtmlComments(columns);
|
||||||
|
json || (json = '{}');
|
||||||
|
|
||||||
|
setProperties(this, { schemas, json });
|
||||||
|
});
|
||||||
|
}
|
@ -4,9 +4,6 @@ import $ from 'jquery';
|
|||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
urn: null,
|
urn: null,
|
||||||
currentName: null,
|
|
||||||
urnWatched: false,
|
|
||||||
detailview: true,
|
|
||||||
previousPage: computed('model.data.page', function() {
|
previousPage: computed('model.data.page', function() {
|
||||||
var model = this.get('model');
|
var model = this.get('model');
|
||||||
if (model && model.data && model.data.page) {
|
if (model && model.data && model.data.page) {
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
deleteDatasetComment,
|
deleteDatasetComment,
|
||||||
updateDatasetComment
|
updateDatasetComment
|
||||||
} from 'wherehows-web/utils/api';
|
} from 'wherehows-web/utils/api';
|
||||||
|
import { encodeUrn } from 'wherehows-web/utils/validators/urn';
|
||||||
import { updateDatasetDeprecation } from 'wherehows-web/utils/api/datasets/properties';
|
import { updateDatasetDeprecation } from 'wherehows-web/utils/api/datasets/properties';
|
||||||
import { readDatasetView } from 'wherehows-web/utils/api/datasets/dataset';
|
import { readDatasetView } from 'wherehows-web/utils/api/datasets/dataset';
|
||||||
import { readDatasetOwners, updateDatasetOwners } from 'wherehows-web/utils/api/datasets/owners';
|
import { readDatasetOwners, updateDatasetOwners } from 'wherehows-web/utils/api/datasets/owners';
|
||||||
@ -28,14 +29,8 @@ export default class extends Controller.extend({
|
|||||||
*/
|
*/
|
||||||
notifications: service(),
|
notifications: service(),
|
||||||
|
|
||||||
isTable: true,
|
|
||||||
hasImpacts: false,
|
|
||||||
hasSamples: false,
|
|
||||||
currentVersion: '0',
|
|
||||||
latestVersion: '0',
|
|
||||||
init() {
|
init() {
|
||||||
setProperties(this, {
|
setProperties(this, {
|
||||||
ownerTypes: [],
|
|
||||||
userTypes: [
|
userTypes: [
|
||||||
{ name: 'Corporate User', value: 'urn:li:corpuser' },
|
{ name: 'Corporate User', value: 'urn:li:corpuser' },
|
||||||
{ name: 'Group User', value: 'urn:li:corpGroup' }
|
{ name: 'Group User', value: 'urn:li:corpGroup' }
|
||||||
@ -205,19 +200,6 @@ export default class extends Controller.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
/**
|
|
||||||
* Updates the dataset's deprecation properties
|
|
||||||
* @param {boolean} isDeprecated
|
|
||||||
* @param {string} deprecationNote
|
|
||||||
* @return {IDatasetView}
|
|
||||||
*/
|
|
||||||
async updateDeprecation(isDeprecated, deprecationNote) {
|
|
||||||
const datasetId = get(this, 'datasetId');
|
|
||||||
|
|
||||||
await updateDatasetDeprecation(datasetId, isDeprecated, deprecationNote);
|
|
||||||
return set(this, 'datasetView', await readDatasetView(datasetId));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action handler creates a dataset comment with the type and text pas
|
* Action handler creates a dataset comment with the type and text pas
|
||||||
* @param {CommentTypeUnion} type the comment type
|
* @param {CommentTypeUnion} type the comment type
|
||||||
@ -324,12 +306,29 @@ export default class extends Controller.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
|
/**
|
||||||
|
* Enum of tab properties
|
||||||
|
* @type {Tabs}
|
||||||
|
*/
|
||||||
tabIds = Tabs;
|
tabIds = Tabs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently selected tab in view
|
||||||
|
* @type {Tabs}
|
||||||
|
*/
|
||||||
tabSelected;
|
tabSelected;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the uri on a model to a usable URN format
|
||||||
|
* @type {ComputedProperty<string>}
|
||||||
|
*/
|
||||||
|
encodedUrn = computed('model', function() {
|
||||||
|
const { uri = '' } = get(this, 'model');
|
||||||
|
return encodeUrn(uri);
|
||||||
|
});
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super(...arguments);
|
||||||
this.tabSelected || (this.tabSelected = Tabs.Ownership);
|
this.tabSelected || (this.tabSelected = Tabs.Ownership);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,6 +341,6 @@ export default class extends Controller.extend({
|
|||||||
// if the tab selection is same as current, noop
|
// if the tab selection is same as current, noop
|
||||||
return get(this, 'tabSelected') === tabSelected
|
return get(this, 'tabSelected') === tabSelected
|
||||||
? void 0
|
? void 0
|
||||||
: this.transitionToRoute(`datasets.dataset.${tabSelected}`, get(this, 'datasetId'));
|
: this.transitionToRoute(`datasets.dataset.${tabSelected}`, get(this, 'encodedUrn'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import Route from '@ember/routing/route';
|
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 $ from 'jquery';
|
|
||||||
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 { readDatasetCompliance, readDatasetComplianceSuggestion } from 'wherehows-web/utils/api/datasets/compliance';
|
||||||
import { readNonPinotProperties, readPinotProperties } from 'wherehows-web/utils/api/datasets/properties';
|
import { readNonPinotProperties, readPinotProperties } from 'wherehows-web/utils/api/datasets/properties';
|
||||||
@ -15,29 +14,12 @@ import {
|
|||||||
|
|
||||||
import { readDatasetOwners, getUserEntities } from 'wherehows-web/utils/api/datasets/owners';
|
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 {
|
import { readDatasetById, readDatasetByUrn } from 'wherehows-web/utils/api/datasets/dataset';
|
||||||
readDatasetById,
|
import isUrn, { isWhUrn, isLiUrn, convertWhUrnToLiUrn, encodeUrn, decodeUrn } from 'wherehows-web/utils/validators/urn';
|
||||||
datasetUrnToId,
|
|
||||||
readDatasetView,
|
|
||||||
readDatasetByUrn
|
|
||||||
} from 'wherehows-web/utils/api/datasets/dataset';
|
|
||||||
import { isWhUrn, isLiUrn } from 'wherehows-web/utils/validators/urn';
|
|
||||||
|
|
||||||
import { checkAclAccess } from 'wherehows-web/utils/api/datasets/acl-access';
|
import { checkAclAccess } from 'wherehows-web/utils/api/datasets/acl-access';
|
||||||
import { currentUser } from 'wherehows-web/utils/api/authentication';
|
import { currentUser } from 'wherehows-web/utils/api/authentication';
|
||||||
|
import { refreshModelQueryParams } from 'wherehows-web/utils/helpers/routes';
|
||||||
const { getJSON } = $;
|
|
||||||
// TODO: DSS-6581 Move to URL retrieval module
|
|
||||||
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`;
|
|
||||||
const getDatasetVersionUrl = (id, dbId) => `${datasetUrl(id)}/versions/db/${dbId}`;
|
|
||||||
|
|
||||||
export default Route.extend({
|
export default Route.extend({
|
||||||
/**
|
/**
|
||||||
@ -45,31 +27,39 @@ export default Route.extend({
|
|||||||
* @type {Ember.Service}
|
* @type {Ember.Service}
|
||||||
*/
|
*/
|
||||||
configurator: inject(),
|
configurator: inject(),
|
||||||
|
/**
|
||||||
|
* Reference to the application notifications Service
|
||||||
|
* @type {ComputedProperty<Notifications>}
|
||||||
|
*/
|
||||||
|
notifications: inject(),
|
||||||
|
|
||||||
queryParams: {
|
queryParams: refreshModelQueryParams(['urn']),
|
||||||
urn: {
|
|
||||||
refreshModel: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the dataset given a identifier from the dataset endpoint
|
* Reads the dataset given a identifier from the dataset endpoint
|
||||||
* @param {string} dataset_id a identifier / id for the dataset to be fetched
|
* @param {string} dataset_id a identifier / id for the dataset to be fetched
|
||||||
* @param {string} [urn] optional urn identifier for dataset
|
* @param {string} [urn] optional urn identifier for dataset
|
||||||
* @return {Promise<IDataset>}
|
* @return {Promise<IDataset|IDatasetView>}
|
||||||
*/
|
*/
|
||||||
async model({ dataset_id: datasetId, urn }) {
|
async model({ dataset_id: identifier, urn }) {
|
||||||
if (datasetId === 'urn') {
|
const isIdentifierUrn = isUrn(decodeUrn(String(identifier)));
|
||||||
if (isWhUrn(urn)) {
|
|
||||||
return readDatasetById(await datasetUrnToId(urn));
|
if (identifier === 'urn' || isIdentifierUrn) {
|
||||||
|
isIdentifierUrn && (urn = identifier);
|
||||||
|
const decodedUrn = decodeUrn(urn);
|
||||||
|
|
||||||
|
isWhUrn(decodedUrn) && (urn = convertWhUrnToLiUrn(decodedUrn));
|
||||||
|
|
||||||
|
if (isLiUrn(decodeUrn(urn))) {
|
||||||
|
return await readDatasetByUrn(encodeUrn(urn));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLiUrn(urn)) {
|
get(this, 'notifications.notify')('error', {
|
||||||
return await readDatasetByUrn(urn);
|
content: 'Could not adequately determine the URN for the requested dataset.'
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return await readDatasetById(datasetId);
|
return await readDatasetById(identifier);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,259 +70,22 @@ export default Route.extend({
|
|||||||
set(controller, 'urn', void 0);
|
set(controller, 'urn', void 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
//TODO: DSS-6632 Correct server-side if status:error and record not found but response is 200OK
|
async setupController(controller, model) {
|
||||||
setupController(controller, model) {
|
set(controller, 'model', model);
|
||||||
let source = '';
|
setProperties(controller, {
|
||||||
let id = 0;
|
isInternal: await get(this, 'configurator').getConfig('isInternal')
|
||||||
let urn = '';
|
// ...properties,
|
||||||
|
// requiredMinNotConfirmed: isRequiredMinOwnersNotConfirmed(owners)
|
||||||
if (model && model.id) {
|
});
|
||||||
({ id, source, urn } = model);
|
|
||||||
let { originalSchema = null } = model;
|
|
||||||
|
|
||||||
this.controllerFor('datasets').set('detailview', true);
|
|
||||||
if (originalSchema) {
|
|
||||||
set(model, 'schema', originalSchema);
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.set('model', model);
|
|
||||||
} else if (model.dataset) {
|
|
||||||
({ id, source, urn } = model.dataset);
|
|
||||||
|
|
||||||
controller.set('model', model.dataset);
|
|
||||||
this.controllerFor('datasets').set('detailview', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't set default zero Ids on controller
|
|
||||||
if (id) {
|
|
||||||
id = +id;
|
|
||||||
controller.set('datasetId', id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ****************************
|
|
||||||
* Note: Refactor in progress *
|
|
||||||
* ****************************
|
|
||||||
* 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 => {
|
|
||||||
try {
|
|
||||||
let properties;
|
|
||||||
|
|
||||||
const [
|
|
||||||
{ schemaless, columns },
|
|
||||||
compliance,
|
|
||||||
complianceDataTypes,
|
|
||||||
complianceSuggestion,
|
|
||||||
datasetComments,
|
|
||||||
isInternal,
|
|
||||||
datasetView,
|
|
||||||
owners,
|
|
||||||
{ userEntitiesSource, userEntitiesMaps }
|
|
||||||
] = await Promise.all([
|
|
||||||
readDatasetColumns(id),
|
|
||||||
readDatasetCompliance(id),
|
|
||||||
readComplianceDataTypes(),
|
|
||||||
readDatasetComplianceSuggestion(id),
|
|
||||||
readDatasetComments(id),
|
|
||||||
get(this, 'configurator').getConfig('isInternal'),
|
|
||||||
readDatasetView(id),
|
|
||||||
readDatasetOwners(id),
|
|
||||||
getUserEntities()
|
|
||||||
]);
|
|
||||||
const { complianceInfo, isNewComplianceInfo } = compliance;
|
|
||||||
const schemas = augmentObjectsWithHtmlComments(columns);
|
|
||||||
|
|
||||||
if (String(source).toLowerCase() === 'pinot') {
|
|
||||||
properties = await readPinotProperties(id);
|
|
||||||
} else {
|
|
||||||
properties = { properties: await readNonPinotProperties(id) };
|
|
||||||
}
|
|
||||||
|
|
||||||
setProperties(controller, {
|
|
||||||
complianceInfo,
|
|
||||||
complianceDataTypes,
|
|
||||||
isNewComplianceInfo,
|
|
||||||
complianceSuggestion,
|
|
||||||
datasetComments,
|
|
||||||
schemaless,
|
|
||||||
schemas,
|
|
||||||
isInternal,
|
|
||||||
datasetView,
|
|
||||||
schemaFieldNamesMappedToDataTypes: columnDataTypesAndFieldNames(columns),
|
|
||||||
...properties,
|
|
||||||
owners,
|
|
||||||
userEntitiesMaps,
|
|
||||||
userEntitiesSource,
|
|
||||||
requiredMinNotConfirmed: isRequiredMinOwnersNotConfirmed(owners)
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
})(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.resolve(getJSON(getDatasetVersionUrl(id, dbId))).then(({ status, versions = [] }) => {
|
|
||||||
if (status === 'ok' && versions.length) {
|
|
||||||
const [firstVersion] = versions;
|
|
||||||
|
|
||||||
setProperties(controller, {
|
|
||||||
versions,
|
|
||||||
hasversions: true,
|
|
||||||
currentVersion: firstVersion,
|
|
||||||
latestVersion: firstVersion
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(new Error('Dataset versions request failed.'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(new Error('Dataset instances request failed.'));
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setProperties(controller, {
|
|
||||||
hasinstances: false,
|
|
||||||
hasversions: false,
|
|
||||||
currentInstance: '0',
|
|
||||||
latestInstance: '0',
|
|
||||||
currentVersion: '0',
|
|
||||||
latestVersion: '0'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// If urn exists, create a breadcrumb list
|
// If urn exists, create a breadcrumb list
|
||||||
// TODO: DSS-7068 Refactoring in progress , move this to a computed prop on a container component
|
// 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
|
// 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?
|
// currently being viewed. Should this even be a link in the first place?
|
||||||
if (urn) {
|
if (model.uri) {
|
||||||
set(controller, 'breadcrumbs', makeUrnBreadcrumbs(urn));
|
set(controller, 'breadcrumbs', makeUrnBreadcrumbs(model.uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the list of ownerTypes from endpoint,
|
|
||||||
// then prevent display of the `consumer`
|
|
||||||
// insert on controller
|
|
||||||
Promise.resolve(getJSON(ownerTypeUrlRoot)).then(({ status, ownerTypes = [] }) => {
|
|
||||||
ownerTypes = ownerTypes
|
|
||||||
.filter(ownerType => String(ownerType).toLowerCase() !== 'consumer')
|
|
||||||
.sort((a, b) => a.localeCompare(b));
|
|
||||||
|
|
||||||
status === 'ok' && set(controller, 'ownerTypes', ownerTypes);
|
|
||||||
});
|
|
||||||
|
|
||||||
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(
|
|
||||||
(sampleObject, record, index) => ((sampleObject[`record${index}`] = record), sampleObject),
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
// TODO: DSS-6122 Refactor global function reference
|
|
||||||
const node = window.JsonHuman.format(samplesObject);
|
|
||||||
|
|
||||||
controller.set('hasSamples', true);
|
|
||||||
|
|
||||||
// TODO: DSS-6122 Refactor setTimeout
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonHuman.appendChild(node);
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(new Error('Dataset sample request failed.'));
|
|
||||||
})
|
|
||||||
.catch(() => set(controller, 'hasSamples', false));
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.resolve(getJSON(getDatasetImpactAnalysisUrl(id)))
|
|
||||||
.then(({ status, impacts = [] }) => {
|
|
||||||
if (status === 'ok') {
|
|
||||||
if (impacts.length) {
|
|
||||||
return setProperties(controller, {
|
|
||||||
hasImpacts: true,
|
|
||||||
impacts: impacts
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(new Error('Dataset impact analysis request failed.'));
|
|
||||||
})
|
|
||||||
.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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(new Error('Dataset references request failed.'));
|
|
||||||
})
|
|
||||||
.catch(() => set(controller, 'hasReferences', false));
|
|
||||||
|
|
||||||
// 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 => {
|
||||||
@ -353,13 +106,5 @@ export default Route.extend({
|
|||||||
currentUserInfo: ''
|
currentUserInfo: ''
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
getDataset() {
|
|
||||||
Promise.resolve(getJSON(datasetUrl(this.get('controller.model.id')))).then(
|
|
||||||
({ status, dataset }) => status === 'ok' && set(this, 'controller.model', dataset)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -11,4 +11,15 @@
|
|||||||
&__actions {
|
&__actions {
|
||||||
margin-top: item-spacing(2);
|
margin-top: item-spacing(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__toggle-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: left;
|
||||||
|
margin-bottom: item-spacing(3);
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
margin: item-spacing(0 2 0 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
{{#if isOwnerInActive}}
|
{{#if isOwnerInActive}}
|
||||||
|
|
||||||
|
<br>
|
||||||
<span class="nacho-button nacho-button--small dataset-author-record__indicator--inactive">
|
<span class="nacho-button nacho-button--small dataset-author-record__indicator--inactive">
|
||||||
Inactive
|
Inactive
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
<form {{action "onSave" on="submit"}}>
|
<form {{action "onSave" on="submit"}}>
|
||||||
<label for="dataset-is-deprecated">
|
|
||||||
Dataset is deprecated?
|
|
||||||
</label>
|
|
||||||
|
|
||||||
{{input
|
<div class="dataset-deprecation-toggle__toggle-header">
|
||||||
id="dataset-is-deprecated"
|
|
||||||
type="checkbox"
|
<p class="dataset-deprecation-toggle__toggle-header__label">
|
||||||
title="Is this dataset deprecated?"
|
Is this dataset deprecated?
|
||||||
checked=(readonly deprecatedAlias)
|
</p>
|
||||||
change=(action "toggleDeprecatedStatus")
|
|
||||||
}}
|
{{input
|
||||||
|
id="dataset-is-deprecated"
|
||||||
|
type="checkbox"
|
||||||
|
title="Is this dataset deprecated?"
|
||||||
|
class="toggle-switch toggle-switch--light"
|
||||||
|
checked=(readonly deprecatedAlias)
|
||||||
|
change=(action "toggleDeprecatedStatus")
|
||||||
|
}}
|
||||||
|
<label for="dataset-is-deprecated" class="toggle-button">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
{{#if deprecatedAlias}}
|
{{#if deprecatedAlias}}
|
||||||
|
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
{{dataset-compliance
|
||||||
|
datasetName=datasetName
|
||||||
|
schemaless=schemaless
|
||||||
|
platform=platform
|
||||||
|
complianceInfo=complianceInfo
|
||||||
|
complianceSuggestion=complianceSuggestion
|
||||||
|
isNewComplianceInfo=isNewComplianceInfo
|
||||||
|
schemaFieldNamesMappedToDataTypes=schemaFieldNamesMappedToDataTypes
|
||||||
|
complianceDataTypes=complianceDataTypes
|
||||||
|
onSave=(action "savePrivacyCompliancePolicy")
|
||||||
|
onReset=(action "resetPrivacyCompliancePolicy")
|
||||||
|
}}
|
@ -0,0 +1,5 @@
|
|||||||
|
{{dataset-authors
|
||||||
|
owners=owners
|
||||||
|
ownerTypes=ownerTypes
|
||||||
|
save=(action "saveOwnerChanges")
|
||||||
|
}}
|
@ -0,0 +1,7 @@
|
|||||||
|
{{dataset-deprecation
|
||||||
|
deprecated=deprecated
|
||||||
|
deprecationNote=deprecationNote
|
||||||
|
onUpdateDeprecation=(action "updateDeprecation")
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{dataset-property properties=properties}}
|
@ -0,0 +1,4 @@
|
|||||||
|
{{dataset-schema
|
||||||
|
json=json
|
||||||
|
schemas=schemas
|
||||||
|
}}
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-5">
|
<div class="col-xs-5">
|
||||||
{{#if datasetView.removed}}
|
{{#if model.removed}}
|
||||||
<span class="removed-dataset">
|
<span class="removed-dataset">
|
||||||
REMOVED
|
REMOVED
|
||||||
</span>
|
</span>
|
||||||
@ -28,8 +28,8 @@
|
|||||||
</sup>
|
</sup>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if datasetView.deprecated}}
|
{{#if model.deprecated}}
|
||||||
{{#link-to "datasets.dataset.properties" datasetId}}
|
{{#link-to "datasets.dataset.properties" encodedUrn}}
|
||||||
|
|
||||||
<span class="deprecated-dataset">
|
<span class="deprecated-dataset">
|
||||||
DEPRECATED
|
DEPRECATED
|
||||||
@ -48,110 +48,10 @@
|
|||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<h3>{{ model.name }}</h3>
|
<h3>{{ model.nativeName }}</h3>
|
||||||
</div>
|
|
||||||
<div class="col-xs-7 text-right">
|
|
||||||
<ul class="datasetDetailsLinks">
|
|
||||||
<li>
|
|
||||||
{{#dataset-favorite dataset=model action="didFavorite"}}
|
|
||||||
{{/dataset-favorite}}
|
|
||||||
<span class="hidden-sm hidden-xs">
|
|
||||||
{{#if model.isFavorite}}
|
|
||||||
Unfavorite
|
|
||||||
{{else}}
|
|
||||||
Favorite
|
|
||||||
{{/if}}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
{{#if model.hdfsBrowserLink}}
|
|
||||||
<li>
|
|
||||||
<a target="_blank" href={{model.hdfsBrowserLink}}
|
|
||||||
title="View on HDFS">
|
|
||||||
<i class="fa fa-database"></i>
|
|
||||||
<span class="hidden-sm hidden-xs">
|
|
||||||
HDFS
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{{/if}}
|
|
||||||
<li>
|
|
||||||
{{#link-to 'lineage.dataset' model.id title='View Lineage'}}
|
|
||||||
<i class="fa fa-sitemap"></i>
|
|
||||||
<span class="hidden-sm hidden-xs">Lineage</span>
|
|
||||||
{{/link-to}}
|
|
||||||
</li>
|
|
||||||
{{#if model.hasSchemaHistory}}
|
|
||||||
<li>
|
|
||||||
<a target="_blank" href={{schemaHistoryUrl}}
|
|
||||||
title="View Schema History">
|
|
||||||
<i class="fa fa-history"></i>
|
|
||||||
<span class="hidden-sm hidden-xs">
|
|
||||||
Schema History
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{{/if}}
|
|
||||||
<li>
|
|
||||||
{{#dataset-watch dataset=model getDatasets="getDataset"}}
|
|
||||||
{{/dataset-watch}}
|
|
||||||
<span class="hidden-xs hidden-sm">
|
|
||||||
{{#if model.isWatched}}
|
|
||||||
Unwatch
|
|
||||||
{{else}}
|
|
||||||
Watch
|
|
||||||
{{/if}}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{dataset-owner-list owners=owners datasetName=model.name}}
|
{{dataset-owner-list owners=owners datasetName=model.nativeName}}
|
||||||
|
|
||||||
{{#if hasinstances}}
|
|
||||||
<div class="row">
|
|
||||||
<span class="col-xs-1">Instances:</span>
|
|
||||||
<div class="btn-toolbar col-xs-11" role="toolbar">
|
|
||||||
{{#each instances as |instance index|}}
|
|
||||||
<div class="btn-group" role="group">
|
|
||||||
{{#if index}}
|
|
||||||
<button type="button" data-value="{{ instance.dbCode }}" class="btn btn-default instance-btn" {{action
|
|
||||||
"updateInstance" instance}}>
|
|
||||||
{{ instance.dbCode }}
|
|
||||||
</button>
|
|
||||||
{{else}}
|
|
||||||
<button type="button" data-value="{{ instance.dbCode }}" class="btn btn-primary instance-btn" {{action
|
|
||||||
"updateInstance" instance}}>
|
|
||||||
{{ instance.dbCode }}
|
|
||||||
</button>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if hasversions}}
|
|
||||||
<div class="row">
|
|
||||||
<span class="col-xs-1">Versions:</span>
|
|
||||||
<div class="btn-toolbar col-xs-11" role="toolbar">
|
|
||||||
{{#each versions as |version index|}}
|
|
||||||
<div class="btn-group" role="group">
|
|
||||||
{{#if index}}
|
|
||||||
<button type="button" data-value="{{ version }}" class="btn btn-default version-btn" {{action
|
|
||||||
"updateVersion" version}}>
|
|
||||||
{{ version }}
|
|
||||||
</button>
|
|
||||||
{{else}}
|
|
||||||
<button type="button" data-value="{{ version }}" class="btn btn-primary version-btn" {{action
|
|
||||||
"updateVersion" version}}>
|
|
||||||
{{ version }}
|
|
||||||
</button>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#ivy-tabs selection=tabSelected as |tabs|}}
|
{{#ivy-tabs selection=tabSelected as |tabs|}}
|
||||||
@ -169,8 +69,6 @@
|
|||||||
{{#tablist.tab tabIds.Access on-select=(action "tabSelectionChanged")}}ACL Access{{/tablist.tab}}
|
{{#tablist.tab tabIds.Access on-select=(action "tabSelectionChanged")}}ACL Access{{/tablist.tab}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{{#tablist.tab tabIds.Comments on-select=(action "tabSelectionChanged")}}Comments{{/tablist.tab}}
|
|
||||||
|
|
||||||
{{#tablist.tab tabIds.Schema on-select=(action "tabSelectionChanged")}}Schema{{/tablist.tab}}
|
{{#tablist.tab tabIds.Schema on-select=(action "tabSelectionChanged")}}Schema{{/tablist.tab}}
|
||||||
|
|
||||||
{{#tablist.tab tabIds.Ownership on-select=(action "tabSelectionChanged")}}
|
{{#tablist.tab tabIds.Ownership on-select=(action "tabSelectionChanged")}}
|
||||||
@ -191,26 +89,14 @@
|
|||||||
{{/tablist.tab}}
|
{{/tablist.tab}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#unless isSFDC}}
|
|
||||||
{{#tablist.tab tabIds.SampleData on-select=(action "tabSelectionChanged")}}
|
|
||||||
Sample Data{{/tablist.tab}}
|
|
||||||
{{/unless}}
|
|
||||||
|
|
||||||
{{#tablist.tab tabIds.Relations on-select=(action "tabSelectionChanged")}}
|
|
||||||
Relations{{/tablist.tab}}
|
|
||||||
|
|
||||||
{{/tabs.tablist}}
|
{{/tabs.tablist}}
|
||||||
|
|
||||||
{{#tabs.tabpanel tabIds.Properties}}
|
{{#tabs.tabpanel tabIds.Properties}}
|
||||||
{{#unless isPinot}}
|
{{datasets/containers/dataset-properties
|
||||||
{{dataset-deprecation
|
urn=encodedUrn
|
||||||
deprecated=datasetView.deprecated
|
deprecated=model.deprecated
|
||||||
deprecationNote=datasetView.deprecationNote
|
deprecationNote=model.deprecationNote
|
||||||
onUpdateDeprecation=(action "updateDeprecation")
|
}}
|
||||||
}}
|
|
||||||
|
|
||||||
{{dataset-property properties=properties}}
|
|
||||||
{{/unless}}
|
|
||||||
{{/tabs.tabpanel}}
|
{{/tabs.tabpanel}}
|
||||||
|
|
||||||
{{#tabs.tabpanel tabIds.Comments}}
|
{{#tabs.tabpanel tabIds.Comments}}
|
||||||
@ -223,45 +109,18 @@
|
|||||||
{{/tabs.tabpanel}}
|
{{/tabs.tabpanel}}
|
||||||
|
|
||||||
{{#tabs.tabpanel tabIds.Schema}}
|
{{#tabs.tabpanel tabIds.Schema}}
|
||||||
{{dataset-schema
|
{{datasets/containers/dataset-schema urn=encodedUrn}}
|
||||||
isTable=isTable
|
|
||||||
json=model.schema
|
|
||||||
schemas=schemas
|
|
||||||
}}
|
|
||||||
{{/tabs.tabpanel}}
|
{{/tabs.tabpanel}}
|
||||||
|
|
||||||
{{#tabs.tabpanel tabIds.Ownership}}
|
{{#tabs.tabpanel tabIds.Ownership}}
|
||||||
{{dataset-authors
|
{{datasets/containers/dataset-ownership urn=encodedUrn}}
|
||||||
owners=owners
|
|
||||||
ownerTypes=ownerTypes
|
|
||||||
save=(action "saveOwnerChanges")
|
|
||||||
}}
|
|
||||||
{{/tabs.tabpanel}}
|
|
||||||
|
|
||||||
{{#tabs.tabpanel tabIds.SampleData}}
|
|
||||||
{{#unless isSFDC}}
|
|
||||||
{{dataset-sample hasSamples=hasSamples isPinot=isPinot columns=columns samples=samples}}
|
|
||||||
{{/unless}}
|
|
||||||
{{/tabs.tabpanel}}
|
|
||||||
|
|
||||||
{{#tabs.tabpanel tabIds.Relations}}
|
|
||||||
{{#unless isSFDC}}
|
|
||||||
{{dataset-relations hasDepends=hasDepends depends=depends hasReferences=hasReferences references=references}}
|
|
||||||
{{/unless}}
|
|
||||||
{{/tabs.tabpanel}}
|
{{/tabs.tabpanel}}
|
||||||
|
|
||||||
{{#tabs.tabpanel tabIds.Compliance}}
|
{{#tabs.tabpanel tabIds.Compliance}}
|
||||||
{{dataset-compliance
|
{{datasets/containers/dataset-compliance
|
||||||
datasetName=model.name
|
urn=encodedUrn
|
||||||
schemaless=schemaless
|
platform=model.platform
|
||||||
platform=datasetView.platform
|
datasetName=model.nativeName
|
||||||
complianceInfo=complianceInfo
|
|
||||||
complianceSuggestion=complianceSuggestion
|
|
||||||
isNewComplianceInfo=isNewComplianceInfo
|
|
||||||
schemaFieldNamesMappedToDataTypes=schemaFieldNamesMappedToDataTypes
|
|
||||||
complianceDataTypes=complianceDataTypes
|
|
||||||
onSave=(action "savePrivacyCompliancePolicy")
|
|
||||||
onReset=(action "resetPrivacyCompliancePolicy")
|
|
||||||
}}
|
}}
|
||||||
{{/tabs.tabpanel}}
|
{{/tabs.tabpanel}}
|
||||||
|
|
||||||
|
@ -37,4 +37,14 @@ interface IOwnerPostResponse {
|
|||||||
msg?: string;
|
msg?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { IOwnerPostResponse, IOwnerResponse, IOwner };
|
/**
|
||||||
|
* Describes the properties on a response to a request for owner types
|
||||||
|
* @interface
|
||||||
|
*/
|
||||||
|
interface IOwnerTypeResponse {
|
||||||
|
status: ApiStatus;
|
||||||
|
ownerTypes?: Array<OwnerType>;
|
||||||
|
msg?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { IOwnerPostResponse, IOwnerResponse, IOwner, IOwnerTypeResponse };
|
||||||
|
22
wherehows-web/app/typings/api/datasets/schema.d.ts
vendored
Normal file
22
wherehows-web/app/typings/api/datasets/schema.d.ts
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { IDatasetColumn } from 'wherehows-web/typings/api/datasets/columns';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the properties on a dataset schema object
|
||||||
|
* @interface
|
||||||
|
*/
|
||||||
|
interface IDatasetSchema {
|
||||||
|
schemaless: boolean;
|
||||||
|
rawSchema: null | string;
|
||||||
|
keySchema: null | string;
|
||||||
|
columns: Array<IDatasetColumn>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the properties on a response to a request for dataset schema
|
||||||
|
* @interface
|
||||||
|
*/
|
||||||
|
interface IDatasetSchemaGetResponse {
|
||||||
|
schema: IDatasetSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { IDatasetSchema, IDatasetSchemaGetResponse };
|
@ -25,16 +25,20 @@ const datasetColumnUrlById = (id: number): string => `${datasetUrlById(id)}/colu
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps an object with a column prop to an object containing markdown comments, if the dataset has a comment attribute
|
* Maps an object with a column prop to an object containing markdown comments, if the dataset has a comment attribute
|
||||||
* @template T
|
* @template T
|
||||||
* @param {T} objectWithComment
|
* @param {T} objectWithComment
|
||||||
* @return {T & {commentHtml: string} | {} & T}
|
* @returns {(T | T & {commentHtml: string})}
|
||||||
*/
|
*/
|
||||||
const augmentWithHtmlComment = <T extends { comment: string }>(objectWithComment: T) => {
|
const augmentWithHtmlComment = <T extends { comment: string }>(
|
||||||
|
objectWithComment: T
|
||||||
|
): T | T & { commentHtml: string } => {
|
||||||
const { comment } = objectWithComment;
|
const { comment } = objectWithComment;
|
||||||
// TODO: DSS-6122 Refactor global function reference to marked
|
// TODO: DSS-6122 Refactor global function reference to marked
|
||||||
// not using spread operator here: https://github.com/Microsoft/TypeScript/issues/10727
|
// not using spread operator here: https://github.com/Microsoft/TypeScript/issues/10727
|
||||||
// current ts version: 2.5.3
|
// current ts version: 2.5.3
|
||||||
return Object.assign({}, objectWithComment, comment && { commentHtml: window.marked(comment).htmlSafe() });
|
return comment
|
||||||
|
? Object.assign({}, objectWithComment, { commentHtml: window.marked(comment).htmlSafe() })
|
||||||
|
: objectWithComment;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,7 +59,9 @@ const columnDataTypeAndFieldName = ({
|
|||||||
* Takes a list of objects with comments and returns an array of objects with comments or html comments
|
* Takes a list of objects with comments and returns an array of objects with comments or html comments
|
||||||
* @type {(array: Array<T extends { comment: string } & Object>) => Array<T | T extends { commentHtml: string }>}
|
* @type {(array: Array<T extends { comment: string } & Object>) => Array<T | T extends { commentHtml: string }>}
|
||||||
*/
|
*/
|
||||||
const augmentObjectsWithHtmlComments = arrayMap(augmentWithHtmlComment);
|
const augmentObjectsWithHtmlComments = arrayMap<IDatasetColumn, IDatasetColumnWithHtmlComments | IDatasetColumn>(
|
||||||
|
augmentWithHtmlComment
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a list of IDatasetColumn / IDatasetColumn with html comments and pulls the dataType and and fullFieldPath (as fieldName) attributes
|
* Takes a list of IDatasetColumn / IDatasetColumn with html comments and pulls the dataType and and fullFieldPath (as fieldName) attributes
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import { IDatasetComment, IDatasetCommentsGetResponse } from 'wherehows-web/typings/api/datasets/comments';
|
import { IDatasetComment, IDatasetCommentsGetResponse } from 'wherehows-web/typings/api/datasets/comments';
|
||||||
import { datasetUrlById } from 'wherehows-web/utils/api/datasets/shared';
|
import { datasetUrlById, datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
|
||||||
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
||||||
|
import { getJSON } from 'wherehows-web/utils/api/fetcher';
|
||||||
|
|
||||||
const { $: { getJSON, post, ajax } } = Ember;
|
const { $: { getJSON: $getJSON, post, ajax } } = Ember;
|
||||||
|
|
||||||
// TODO: DSS-6122 Create and move to Error module
|
// TODO: DSS-6122 Create and move to Error module
|
||||||
/**
|
/**
|
||||||
@ -25,6 +26,13 @@ const csrfToken = '_UNUSED_';
|
|||||||
*/
|
*/
|
||||||
const datasetCommentsUrlById = (id: number): string => `${datasetUrlById(id)}/comments`;
|
const datasetCommentsUrlById = (id: number): string => `${datasetUrlById(id)}/comments`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the url for a dataset comment by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const datasetCommentsUrnByUrn = (urn: string): string => `${datasetUrlByUrn(urn)}/comments`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a specific comment on a dataset
|
* Gets a specific comment on a dataset
|
||||||
* @param {number} datasetId the id of the dataset
|
* @param {number} datasetId the id of the dataset
|
||||||
@ -40,7 +48,7 @@ const datasetCommentUrlById = (datasetId: number, commentId: number): string =>
|
|||||||
* @return {Promise<Array<IDatasetComment>>}
|
* @return {Promise<Array<IDatasetComment>>}
|
||||||
*/
|
*/
|
||||||
const readDatasetComments = async (id: number): Promise<Array<IDatasetComment>> => {
|
const readDatasetComments = async (id: number): Promise<Array<IDatasetComment>> => {
|
||||||
const response: IDatasetCommentsGetResponse = await Promise.resolve(getJSON(datasetCommentsUrlById(id)));
|
const response: IDatasetCommentsGetResponse = await Promise.resolve($getJSON(datasetCommentsUrlById(id)));
|
||||||
const { status, data: { comments } } = response;
|
const { status, data: { comments } } = response;
|
||||||
|
|
||||||
if (status === ApiStatus.OK) {
|
if (status === ApiStatus.OK) {
|
||||||
@ -50,6 +58,18 @@ const readDatasetComments = async (id: number): Promise<Array<IDatasetComment>>
|
|||||||
throw new Error(datasetCommentsApiException);
|
throw new Error(datasetCommentsApiException);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the dataset comments related to the urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {Promise<Array<IDatasetComment>>}
|
||||||
|
*/
|
||||||
|
const readDatasetCommentsByUrn = async (urn: string): Promise<Array<IDatasetComment>> => {
|
||||||
|
const { data: { comments } } = await getJSON<Pick<IDatasetCommentsGetResponse, 'data'>>({
|
||||||
|
url: datasetCommentsUrnByUrn(urn)
|
||||||
|
});
|
||||||
|
return comments;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts a new comment on a dataset
|
* Posts a new comment on a dataset
|
||||||
* @param {number} id the id of the dataset
|
* @param {number} id the id of the dataset
|
||||||
@ -138,4 +158,10 @@ const updateDatasetComment = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { readDatasetComments, createDatasetComment, deleteDatasetComment, updateDatasetComment };
|
export {
|
||||||
|
readDatasetComments,
|
||||||
|
createDatasetComment,
|
||||||
|
deleteDatasetComment,
|
||||||
|
updateDatasetComment,
|
||||||
|
readDatasetCommentsByUrn
|
||||||
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { assert } from '@ember/debug';
|
import { assert } from '@ember/debug';
|
||||||
import { createInitialComplianceInfo } from 'wherehows-web/utils/datasets/compliance-policy';
|
import { createInitialComplianceInfo } from 'wherehows-web/utils/datasets/compliance-policy';
|
||||||
import { datasetUrlById } from 'wherehows-web/utils/api/datasets/shared';
|
import { datasetUrlById, datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
|
||||||
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
||||||
import {
|
import {
|
||||||
IComplianceGetResponse,
|
IComplianceGetResponse,
|
||||||
@ -8,7 +8,7 @@ import {
|
|||||||
IComplianceSuggestion,
|
IComplianceSuggestion,
|
||||||
IComplianceSuggestionResponse
|
IComplianceSuggestionResponse
|
||||||
} from 'wherehows-web/typings/api/datasets/compliance';
|
} from 'wherehows-web/typings/api/datasets/compliance';
|
||||||
import { getJSON } from 'wherehows-web/utils/api/fetcher';
|
import { getJSON, postJSON } from 'wherehows-web/utils/api/fetcher';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the dataset compliance url
|
* Constructs the dataset compliance url
|
||||||
@ -17,6 +17,13 @@ import { getJSON } from 'wherehows-web/utils/api/fetcher';
|
|||||||
*/
|
*/
|
||||||
const datasetComplianceUrlById = (id: number): string => `${datasetUrlById(id)}/compliance`;
|
const datasetComplianceUrlById = (id: number): string => `${datasetUrlById(id)}/compliance`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the url for a datasets compliance policy by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const datasetComplianceUrlByUrn = (urn: string): string => `${datasetUrlByUrn(urn)}/compliance`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the compliance suggestions url based of the compliance id
|
* Constructs the compliance suggestions url based of the compliance id
|
||||||
* @param {number} id the id of the dataset
|
* @param {number} id the id of the dataset
|
||||||
@ -24,6 +31,13 @@ const datasetComplianceUrlById = (id: number): string => `${datasetUrlById(id)}/
|
|||||||
*/
|
*/
|
||||||
const datasetComplianceSuggestionsUrlById = (id: number): string => `${datasetComplianceUrlById(id)}/suggestions`;
|
const datasetComplianceSuggestionsUrlById = (id: number): string => `${datasetComplianceUrlById(id)}/suggestions`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the url for a dataset compliance suggestion by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const datasetComplianceSuggestionUrlByUrn = (urn: string): string => `${datasetUrlByUrn(urn)}/complianceSuggestion`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the client app should 'new' a compliance policy
|
* Determines if the client app should 'new' a compliance policy
|
||||||
* If the endpoint responds with a failed status, and the msg contains the indicator that a compliance does not exist
|
* If the endpoint responds with a failed status, and the msg contains the indicator that a compliance does not exist
|
||||||
@ -35,14 +49,21 @@ const requiresCompliancePolicyCreation = ({ status, msg }: IComplianceGetRespons
|
|||||||
return status === ApiStatus.FAILED && String(msg).includes(notFound);
|
return status === ApiStatus.FAILED && String(msg).includes(notFound);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the properties on a map generated by reading the compliance policy for a dataset
|
||||||
|
* @interface
|
||||||
|
*/
|
||||||
|
export interface IReadComplianceResult {
|
||||||
|
isNewComplianceInfo: boolean;
|
||||||
|
complianceInfo: IComplianceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the current compliance policy for a dataset with thi given id
|
* Fetches the current compliance policy for a dataset with thi given id
|
||||||
* @param {number} id the id of the dataset
|
* @param {number} id the id of the dataset
|
||||||
* @returns {(Promise<{ isNewComplianceInfo: boolean; complianceInfo: IComplianceInfo }>)}
|
* @returns {(Promise<IReadComplianceResult>)}
|
||||||
*/
|
*/
|
||||||
const readDatasetCompliance = async (
|
const readDatasetCompliance = async (id: number): Promise<IReadComplianceResult> => {
|
||||||
id: number
|
|
||||||
): Promise<{ isNewComplianceInfo: boolean; complianceInfo: IComplianceInfo }> => {
|
|
||||||
assert(`Expected id to be a number but received ${typeof id}`, typeof id === 'number');
|
assert(`Expected id to be a number but received ${typeof id}`, typeof id === 'number');
|
||||||
|
|
||||||
const response = await getJSON<IComplianceGetResponse>({ url: datasetComplianceUrlById(id) });
|
const response = await getJSON<IComplianceGetResponse>({ url: datasetComplianceUrlById(id) });
|
||||||
@ -60,6 +81,35 @@ const readDatasetCompliance = async (
|
|||||||
throw new Error(msg);
|
throw new Error(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the dataset compliance policy by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {Promise<IReadComplianceResult>}
|
||||||
|
*/
|
||||||
|
const readDatasetComplianceByUrn = async (urn: string): Promise<IReadComplianceResult> => {
|
||||||
|
let { complianceInfo } = await getJSON<Pick<IComplianceGetResponse, 'complianceInfo'>>({
|
||||||
|
url: datasetComplianceUrlByUrn(urn)
|
||||||
|
});
|
||||||
|
const isNewComplianceInfo = !complianceInfo;
|
||||||
|
|
||||||
|
if (isNewComplianceInfo) {
|
||||||
|
complianceInfo = createInitialComplianceInfo(urn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { isNewComplianceInfo, complianceInfo: complianceInfo! };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists the dataset compliance policy
|
||||||
|
* @param {string} urn
|
||||||
|
* @param {IComplianceInfo} complianceInfo
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
const saveDatasetComplianceByUrn = (urn: string, complianceInfo: IComplianceInfo): Promise<void> => {
|
||||||
|
const url = datasetUrlByUrn(urn);
|
||||||
|
return postJSON<void>({ url, data: complianceInfo });
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests the compliance suggestions for a given dataset Id and returns the suggestion list
|
* Requests the compliance suggestions for a given dataset Id and returns the suggestion list
|
||||||
* @param {number} id the id of the dataset
|
* @param {number} id the id of the dataset
|
||||||
@ -73,4 +123,29 @@ const readDatasetComplianceSuggestion = async (id: number): Promise<IComplianceS
|
|||||||
return complianceSuggestion;
|
return complianceSuggestion;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { readDatasetCompliance, readDatasetComplianceSuggestion, datasetComplianceUrlById };
|
/**
|
||||||
|
* Reads the suggestions for a dataset compliance policy by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {Promise<IComplianceSuggestion>}
|
||||||
|
*/
|
||||||
|
const readDatasetComplianceSuggestionByUrn = async (urn: string): Promise<IComplianceSuggestion> => {
|
||||||
|
let complianceSuggestion: IComplianceSuggestion = <IComplianceSuggestion>{};
|
||||||
|
try {
|
||||||
|
({ complianceSuggestion = <IComplianceSuggestion>{} } = await getJSON<
|
||||||
|
Pick<IComplianceSuggestionResponse, 'complianceSuggestion'>
|
||||||
|
>({ url: datasetComplianceSuggestionUrlByUrn(urn) }));
|
||||||
|
} catch {
|
||||||
|
return complianceSuggestion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return complianceSuggestion;
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
readDatasetCompliance,
|
||||||
|
readDatasetComplianceSuggestion,
|
||||||
|
datasetComplianceUrlById,
|
||||||
|
readDatasetComplianceByUrn,
|
||||||
|
saveDatasetComplianceByUrn,
|
||||||
|
readDatasetComplianceSuggestionByUrn
|
||||||
|
};
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
import { IOwner, IOwnerPostResponse, IOwnerResponse } from 'wherehows-web/typings/api/datasets/owners';
|
import {
|
||||||
|
IOwner,
|
||||||
|
IOwnerPostResponse,
|
||||||
|
IOwnerResponse,
|
||||||
|
IOwnerTypeResponse
|
||||||
|
} from 'wherehows-web/typings/api/datasets/owners';
|
||||||
import {
|
import {
|
||||||
IPartyEntity,
|
IPartyEntity,
|
||||||
IPartyEntityResponse,
|
IPartyEntityResponse,
|
||||||
IPartyProps,
|
IPartyProps,
|
||||||
IUserEntityMap
|
IUserEntityMap
|
||||||
} from 'wherehows-web/typings/api/datasets/party-entities';
|
} from 'wherehows-web/typings/api/datasets/party-entities';
|
||||||
import { datasetUrlById } from 'wherehows-web/utils/api/datasets/shared';
|
import { datasetUrlById, datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
|
||||||
import { getJSON, postJSON } from 'wherehows-web/utils/api/fetcher';
|
import { getJSON, postJSON } from 'wherehows-web/utils/api/fetcher';
|
||||||
import { getApiRoot, ApiStatus } from 'wherehows-web/utils/api/shared';
|
import { getApiRoot, ApiStatus } from 'wherehows-web/utils/api/shared';
|
||||||
|
import { arrayFilter, arrayMap } from 'wherehows-web/utils/array';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a string enum for valid owner types
|
* Defines a string enum for valid owner types
|
||||||
@ -57,8 +63,25 @@ enum OwnerSource {
|
|||||||
*/
|
*/
|
||||||
const datasetOwnersUrlById = (id: number): string => `${datasetUrlById(id)}/owners`;
|
const datasetOwnersUrlById = (id: number): string => `${datasetUrlById(id)}/owners`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the dataset owners url by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const datasetOwnersUrlByUrn = (urn: string): string => `${datasetUrlByUrn(urn)}/owners`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the party entities url
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
const partyEntitiesUrl = `${getApiRoot()}/party/entities`;
|
const partyEntitiesUrl = `${getApiRoot()}/party/entities`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the owner types url
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const datasetOwnerTypesUrl = () => `${getApiRoot()}/owner/types`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests the list of dataset owners from the GET endpoint, converts the modifiedTime property
|
* Requests the list of dataset owners from the GET endpoint, converts the modifiedTime property
|
||||||
* to a date object
|
* to a date object
|
||||||
@ -68,15 +91,38 @@ const partyEntitiesUrl = `${getApiRoot()}/party/entities`;
|
|||||||
const readDatasetOwners = async (id: number): Promise<Array<IOwner>> => {
|
const readDatasetOwners = async (id: number): Promise<Array<IOwner>> => {
|
||||||
const { owners = [], status, msg } = await getJSON<IOwnerResponse>({ url: datasetOwnersUrlById(id) });
|
const { owners = [], status, msg } = await getJSON<IOwnerResponse>({ url: datasetOwnersUrlById(id) });
|
||||||
if (status === ApiStatus.OK) {
|
if (status === ApiStatus.OK) {
|
||||||
return owners.map(owner => ({
|
return ownersWithModifiedTimeAsDate(owners);
|
||||||
...owner,
|
|
||||||
modifiedTime: new Date(<number>owner.modifiedTime!) // Api response is always in number format
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(msg);
|
throw new Error(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies an owner object by applying the modified date property as a Date object
|
||||||
|
* @param {IOwner} owner
|
||||||
|
* @return {IOwner}
|
||||||
|
*/
|
||||||
|
const ownerWithModifiedTimeAsDate = (owner: IOwner): IOwner => ({
|
||||||
|
...owner,
|
||||||
|
modifiedTime: new Date(<number>owner.modifiedTime)
|
||||||
|
}); // Api response is always in number format
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies a list of owners with a modified date property as a Date object
|
||||||
|
* @type {(array: Array<IOwner>) => Array<IOwner>}
|
||||||
|
*/
|
||||||
|
const ownersWithModifiedTimeAsDate = arrayMap(ownerWithModifiedTimeAsDate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the owners for dataset by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {Promise<Array<IOwner>>}
|
||||||
|
*/
|
||||||
|
const readDatasetOwnersByUrn = async (urn: string): Promise<Array<IOwner>> => {
|
||||||
|
const { owners = [] } = await getJSON<Pick<IOwnerResponse, 'owners'>>({ url: datasetOwnersUrlByUrn(urn) });
|
||||||
|
return ownersWithModifiedTimeAsDate(owners);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persists the updated list of dataset owners
|
* Persists the updated list of dataset owners
|
||||||
* @param {number} id the id of the dataset
|
* @param {number} id the id of the dataset
|
||||||
@ -105,6 +151,47 @@ const updateDatasetOwners = async (
|
|||||||
throw new Error(msg);
|
throw new Error(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the owners on a dataset by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @param {string} csrfToken
|
||||||
|
* @param {Array<IOwner>} updatedOwners
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
const updateDatasetOwnersByUrn = (urn: string, csrfToken: string = '', updatedOwners: Array<IOwner>): Promise<void> => {
|
||||||
|
return postJSON<void>({
|
||||||
|
url: datasetOwnersUrlByUrn(urn),
|
||||||
|
headers: { 'csrf-token': csrfToken },
|
||||||
|
data: {
|
||||||
|
csrfToken,
|
||||||
|
owners: updatedOwners
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the owner types list on a dataset
|
||||||
|
* @return {Promise<Array<OwnerType>>}
|
||||||
|
*/
|
||||||
|
const readDatasetOwnerTypes = async (): Promise<Array<OwnerType>> => {
|
||||||
|
const url = datasetOwnerTypesUrl();
|
||||||
|
const { ownerTypes = [] } = await getJSON<IOwnerTypeResponse>({ url });
|
||||||
|
return ownerTypes.sort((a: string, b: string) => a.localeCompare(b));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if an owner type supplied is not of type consumer
|
||||||
|
* @param {OwnerType} ownerType
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
const isNotAConsumer = (ownerType: OwnerType): boolean => ownerType !== OwnerType.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the dataset owner types and filters out the OwnerType.Consumer type from the list
|
||||||
|
* @return {Promise<Array<OwnerType>>}
|
||||||
|
*/
|
||||||
|
const readDatasetOwnerTypesWithoutConsumer = async () => arrayFilter(isNotAConsumer)(await readDatasetOwnerTypes());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests party entities and if the response status is OK, resolves with an array of entities
|
* Requests party entities and if the response status is OK, resolves with an array of entities
|
||||||
* @return {Promise<Array<IPartyEntity>>}
|
* @return {Promise<Array<IPartyEntity>>}
|
||||||
@ -179,6 +266,9 @@ const readPartyEntitiesMap = (partyEntities: Array<IPartyEntity>): IUserEntityMa
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
readDatasetOwners,
|
readDatasetOwners,
|
||||||
|
readDatasetOwnersByUrn,
|
||||||
|
updateDatasetOwnersByUrn,
|
||||||
|
readDatasetOwnerTypesWithoutConsumer,
|
||||||
readPartyEntities,
|
readPartyEntities,
|
||||||
readPartyEntitiesMap,
|
readPartyEntitiesMap,
|
||||||
getUserEntities,
|
getUserEntities,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { warn } from '@ember/debug';
|
import { warn } from '@ember/debug';
|
||||||
import { ApiStatus } from 'wherehows-web/utils/api';
|
import { ApiStatus } from 'wherehows-web/utils/api';
|
||||||
import { getJSON, putJSON } from 'wherehows-web/utils/api/fetcher';
|
import { getJSON, putJSON } from 'wherehows-web/utils/api/fetcher';
|
||||||
import { datasetUrlById } from 'wherehows-web/utils/api/datasets/shared';
|
import { datasetUrlById, datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
|
||||||
import {
|
import {
|
||||||
IDatasetProperties,
|
IDatasetProperties,
|
||||||
IDatasetPropertiesGetResponse,
|
IDatasetPropertiesGetResponse,
|
||||||
@ -27,6 +27,13 @@ const datasetPropertiesUrlById = (id: number) => `${datasetUrlById(id)}/properti
|
|||||||
|
|
||||||
const datasetDeprecationUrlById = (id: number) => `${datasetUrlById(id)}/deprecate`;
|
const datasetDeprecationUrlById = (id: number) => `${datasetUrlById(id)}/deprecate`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the url for a dataset deprecation endpoint by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const datasetDeprecationUrlByUrn = (urn: string) => `${datasetUrlByUrn(urn)}/deprecate`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the response from the dataset properties endpoint and returns properties if found
|
* Reads the response from the dataset properties endpoint and returns properties if found
|
||||||
* @param {number} id the dataset id to get properties for
|
* @param {number} id the dataset id to get properties for
|
||||||
@ -197,4 +204,31 @@ const updateDatasetDeprecation = async (id: number, deprecated: boolean, depreca
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { readDatasetProperties, readNonPinotProperties, readPinotProperties, updateDatasetDeprecation };
|
/**
|
||||||
|
* Persists the changes to a datasets deprecation properties by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @param {boolean} deprecated
|
||||||
|
* @param {string} deprecationNote
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
const updateDatasetDeprecationByUrn = (
|
||||||
|
urn: string,
|
||||||
|
deprecated: boolean,
|
||||||
|
deprecationNote: string = ''
|
||||||
|
): Promise<void> => {
|
||||||
|
return putJSON<void>({
|
||||||
|
url: datasetDeprecationUrlByUrn(urn),
|
||||||
|
data: {
|
||||||
|
deprecated,
|
||||||
|
deprecationNote
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
readDatasetProperties,
|
||||||
|
readNonPinotProperties,
|
||||||
|
readPinotProperties,
|
||||||
|
updateDatasetDeprecation,
|
||||||
|
updateDatasetDeprecationByUrn
|
||||||
|
};
|
||||||
|
22
wherehows-web/app/utils/api/datasets/schema.ts
Normal file
22
wherehows-web/app/utils/api/datasets/schema.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { IDatasetSchema, IDatasetSchemaGetResponse } from 'wherehows-web/typings/api/datasets/schema';
|
||||||
|
import { datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
|
||||||
|
import { getJSON } from 'wherehows-web/utils/api/fetcher';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the url for a dataset schema by urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const datasetSchemaUrlByUrn = (urn: string): string => `${datasetUrlByUrn(urn)}/schema`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the schema for a dataset with the related urn
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {Promise<IDatasetSchema>}
|
||||||
|
*/
|
||||||
|
const readDatasetSchemaByUrn = async (urn: string): Promise<IDatasetSchema> => {
|
||||||
|
const { schema } = await getJSON<IDatasetSchemaGetResponse>({ url: datasetSchemaUrlByUrn(urn) });
|
||||||
|
return schema;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { readDatasetSchemaByUrn };
|
@ -19,9 +19,8 @@ export const datasetUrlById = (id: number): string => `${datasetsUrlRoot('v1')}/
|
|||||||
* @param {string} urn
|
* @param {string} urn
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export const datasetUrlByUrn = (urn: string): string => `${getApiRoot('v2')}/dataset/${urn}`;
|
export const datasetUrlByUrn = (urn: string): string => `${datasetsUrlRoot('v2')}/${urn}`;
|
||||||
//FIXME api plurality ^^^^^^^^^^
|
|
||||||
// export const datasetUrlByUrn = (urn: string): string => `${datasetsUrlRoot('v2')}/${urn}`;
|
|
||||||
/**
|
/**
|
||||||
* Composes the datasets count url from a given platform and or prefix if provided
|
* Composes the datasets count url from a given platform and or prefix if provided
|
||||||
* @param {Partial<IReadDatasetsOptionBag>} [{ platform, prefix }={}]
|
* @param {Partial<IReadDatasetsOptionBag>} [{ platform, prefix }={}]
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
import { DatasetClassifiers } from 'wherehows-web/constants/dataset-classification';
|
import { DatasetClassifiers } from 'wherehows-web/constants/dataset-classification';
|
||||||
import { lastSeenSuggestionInterval } from 'wherehows-web/constants/metadata-acquisition';
|
import { lastSeenSuggestionInterval } from 'wherehows-web/constants/metadata-acquisition';
|
||||||
import { assert, warn } from '@ember/debug';
|
import { assert, warn } from '@ember/debug';
|
||||||
|
import { decodeUrn } from 'wherehows-web/utils/validators/urn';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a default shape for securitySpecification & privacyCompliancePolicy with default / unset values
|
* Builds a default shape for securitySpecification & privacyCompliancePolicy with default / unset values
|
||||||
* for non null properties as per Avro schema
|
* for non null properties as per Avro schema
|
||||||
* @param {number} datasetId id for the dataset that this privacy object applies to
|
* @param {number} datasetId identifier for the dataset that this privacy object applies to
|
||||||
*/
|
*/
|
||||||
const createInitialComplianceInfo = datasetId => ({
|
const createInitialComplianceInfo = datasetId => {
|
||||||
datasetId,
|
const identifier = typeof datasetId === 'string' ? { urn: decodeUrn(datasetId) } : { datasetId };
|
||||||
complianceType: '',
|
|
||||||
compliancePurgeNote: '',
|
return {
|
||||||
complianceEntities: [],
|
...identifier,
|
||||||
datasetClassification: {}
|
complianceType: '',
|
||||||
});
|
compliancePurgeNote: '',
|
||||||
|
complianceEntities: [],
|
||||||
|
datasetClassification: {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
import { urnRegex } from 'wherehows-web/utils/validators/urn';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 => {
|
|
||||||
const urnMatch = urnRegex.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 = {
|
|
||||||
crumb,
|
|
||||||
// First item is root
|
|
||||||
urn: !index ? `${crumb}:///` : `${previousCrumb.urn}${crumb}/`
|
|
||||||
};
|
|
||||||
|
|
||||||
return [...breadcrumbs, breadcrumb];
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
41
wherehows-web/app/utils/entities/make-urn-breadcrumbs.ts
Normal file
41
wherehows-web/app/utils/entities/make-urn-breadcrumbs.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
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,17 +1,19 @@
|
|||||||
|
import { assert } from '@ember/debug';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches a url string with a `urn` query. urn query with letters or underscore segment of any length greater
|
* Matches a url string with a `urn` query. urn query with letters or underscore segment of any length greater
|
||||||
* than 1 followed by colon and 3 forward slashes and a segment containing letters, {, }, _ or /, or none
|
* than 1 followed by colon and 3 forward slashes and a segment containing letters, {, }, _ or /, or none
|
||||||
* The value following the urn key is retained
|
* The value following the urn key is retained
|
||||||
* @type {RegExp}
|
* @type {RegExp}
|
||||||
*/
|
*/
|
||||||
const datasetUrnRegexWH = /([a-z_]+):\/{3}([a-z0-9_\-/{}]*)/i;
|
const datasetUrnRegexWH = /([a-z_]+):\/{3}([a-z0-9_\-/{}.]*)/i;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches a urn string that follows the pattern captures, the comma delimited platform, segment and fabric
|
* Matches a urn string that follows the pattern captures, the comma delimited platform, segment and fabric
|
||||||
* e.g urn:li:dataset:(urn:li:dataPlatform:PLATFORM,SEGMENT,FABRIC)
|
* e.g urn:li:dataset:(urn:li:dataPlatform:PLATFORM,SEGMENT,FABRIC)
|
||||||
* @type {RegExp}
|
* @type {RegExp}
|
||||||
*/
|
*/
|
||||||
const datasetUrnRegexLI = /urn:li:dataset:\(urn:li:dataPlatform:(\w+),([\w.\-]+),(\w+)\)/;
|
const datasetUrnRegexLI = /urn:li:dataset:\(urn:li:dataPlatform:(\w+),([\w.\-\/]+),(\w+)\)/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches urn's that occur in flow urls
|
* Matches urn's that occur in flow urls
|
||||||
@ -53,6 +55,61 @@ const getPlatformFromUrn = (candidateUrn: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a WH URN format to a LI URN format
|
||||||
|
* @param {string} whUrn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const convertWhUrnToLiUrn = (whUrn: string): string => {
|
||||||
|
assert(`Expected ${whUrn} to be in the WH urn format`, isWhUrn(whUrn));
|
||||||
|
const [, platform, path] = datasetUrnRegexWH.exec(whUrn)!;
|
||||||
|
|
||||||
|
return `urn:li:dataset:(urn:li:dataPlatform:${platform},${path},PROD)`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached RegExp object for a global search of /
|
||||||
|
* @type {RegExp}
|
||||||
|
*/
|
||||||
|
const encodedSlashRegExp = new RegExp(encodeURIComponent('/'), 'g');
|
||||||
|
/**
|
||||||
|
* Replaces any occurrence of / with the encoded equivalent
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const encodeForwardSlash = (urn: string): string => urn.replace(/\//g, encodeURIComponent('/'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces encoded slashes with /
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const decodeForwardSlash = (urn: string): string => urn.replace(encodedSlashRegExp, decodeURIComponent('/'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces occurrences of / with the encoded counterpart in a urn string
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const encodeUrn = (urn: string): string => encodeForwardSlash(urn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces encoded occurrences of / with the string /
|
||||||
|
* @param {string} urn
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const decodeUrn = (urn: string): string => decodeForwardSlash(urn);
|
||||||
|
|
||||||
export default isUrn;
|
export default isUrn;
|
||||||
|
|
||||||
export { datasetUrnRegexWH, datasetUrnRegexLI, isWhUrn, isLiUrn, specialFlowUrnRegex, getPlatformFromUrn };
|
export {
|
||||||
|
datasetUrnRegexWH,
|
||||||
|
datasetUrnRegexLI,
|
||||||
|
isWhUrn,
|
||||||
|
isLiUrn,
|
||||||
|
specialFlowUrnRegex,
|
||||||
|
getPlatformFromUrn,
|
||||||
|
convertWhUrnToLiUrn,
|
||||||
|
encodeUrn,
|
||||||
|
decodeUrn
|
||||||
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { faker } from 'ember-cli-mirage';
|
import { faker } from 'ember-cli-mirage';
|
||||||
import { IFunctionRouteHandler, IMirageServer } from 'wherehows-web/typings/ember-cli-mirage';
|
import { IFunctionRouteHandler, IMirageServer } from 'wherehows-web/typings/ember-cli-mirage';
|
||||||
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
||||||
import { getDatasetColumns } from 'wherehows-web/mirage/helpers/columns';
|
import { getDatasetColumns, getDatasetSchema } from 'wherehows-web/mirage/helpers/columns';
|
||||||
import { getDatasetCompliance } from 'wherehows-web/mirage/helpers/compliance';
|
import { getDatasetCompliance } from 'wherehows-web/mirage/helpers/compliance';
|
||||||
import { getComplianceDataTypes } from 'wherehows-web/mirage/helpers/compliance-data-types';
|
import { getComplianceDataTypes } from 'wherehows-web/mirage/helpers/compliance-data-types';
|
||||||
import { getDatasetComplianceSuggestion } from 'wherehows-web/mirage/helpers/compliance-suggestions';
|
import { getDatasetComplianceSuggestion } from 'wherehows-web/mirage/helpers/compliance-suggestions';
|
||||||
@ -32,6 +32,16 @@ export default function(this: IMirageServer) {
|
|||||||
|
|
||||||
this.namespace = '/api/v2';
|
this.namespace = '/api/v2';
|
||||||
|
|
||||||
|
this.get('/datasets/:identifier/', getDatasetView);
|
||||||
|
|
||||||
|
this.get('/datasets/:identifier/owners', getDatasetOwners);
|
||||||
|
|
||||||
|
this.get('/datasets/:dataset_id/schema', getDatasetSchema);
|
||||||
|
|
||||||
|
this.get('/datasets/:dataset_id/compliance/suggestions', getDatasetComplianceSuggestion);
|
||||||
|
|
||||||
|
this.get('/datasets/:dataset_id/owners', getDatasetOwners);
|
||||||
|
|
||||||
this.get('/list/complianceDataTypes', getComplianceDataTypes);
|
this.get('/list/complianceDataTypes', getComplianceDataTypes);
|
||||||
|
|
||||||
this.get('/list/platforms', getDatasetPlatforms);
|
this.get('/list/platforms', getDatasetPlatforms);
|
||||||
|
3
wherehows-web/mirage/fixtures/urn.ts
Normal file
3
wherehows-web/mirage/fixtures/urn.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
const urn = 'urn:li:dataset:(urn:li:dataPlatform:hdfs,%2Fjobs%2Faffinity%2FeAffinity%2Fmaster%2Fold-job-seeker,PROD)';
|
||||||
|
|
||||||
|
export { urn };
|
@ -9,4 +9,15 @@ const getDatasetColumns = function(this: IFunctionRouteHandler, { columns }: { c
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getDatasetColumns };
|
const getDatasetSchema = function(this: IFunctionRouteHandler, { columns }: { columns: any }) {
|
||||||
|
return {
|
||||||
|
schema: {
|
||||||
|
columns: this.serialize(columns.all()),
|
||||||
|
schemaless: false,
|
||||||
|
keySchema: null,
|
||||||
|
rawSchema: '{}'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getDatasetColumns, getDatasetSchema };
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { IFunctionRouteHandler } from 'wherehows-web/typings/ember-cli-mirage';
|
import { IFunctionRouteHandler } from 'wherehows-web/typings/ember-cli-mirage';
|
||||||
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
|
||||||
|
|
||||||
const getDatasetOwners = function(this: IFunctionRouteHandler, { owners }: { owners: any }) {
|
const getDatasetOwners = function(this: IFunctionRouteHandler, { owners }: { owners: any }) {
|
||||||
return {
|
return {
|
||||||
owners: this.serialize(owners.all()),
|
owners: this.serialize(owners.all())
|
||||||
status: ApiStatus.OK
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { IFunctionRouteHandler } from 'wherehows-web/typings/ember-cli-mirage';
|
import { IFunctionRouteHandler } from 'wherehows-web/typings/ember-cli-mirage';
|
||||||
import { ApiStatus } from 'wherehows-web/utils/api/shared';
|
|
||||||
|
|
||||||
const getDatasetView = function(this: IFunctionRouteHandler, { datasetViews }: { datasetViews: any }) {
|
const getDatasetView = function(this: IFunctionRouteHandler, { datasetViews }: { datasetViews: any }) {
|
||||||
return {
|
return {
|
||||||
dataset: this.serialize(datasetViews.first()),
|
dataset: this.serialize(datasetViews.first())
|
||||||
status: ApiStatus.OK
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test } from 'qunit';
|
import { skip } from 'qunit';
|
||||||
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
||||||
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
||||||
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
||||||
@ -10,7 +10,8 @@ moduleForAcceptance('Acceptance | datasets/dataset/comments', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('visiting /datasets/dataset/comments', async function(assert) {
|
// feature not yet supported in v2
|
||||||
|
skip('visiting /datasets/dataset/comments', async function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
defaultScenario(server);
|
defaultScenario(server);
|
||||||
const url = '/datasets/12345/comments';
|
const url = '/datasets/12345/comments';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test } from 'qunit';
|
import { skip } from 'qunit';
|
||||||
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
||||||
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
||||||
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
||||||
@ -10,7 +10,7 @@ moduleForAcceptance('Acceptance | datasets/dataset/ownership', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('visiting /datasets/dataset/ownership', async function(assert) {
|
skip('visiting /datasets/dataset/ownership', async function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
defaultScenario(server);
|
defaultScenario(server);
|
||||||
const url = '/datasets/12345/ownership';
|
const url = '/datasets/12345/ownership';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test } from 'qunit';
|
import { skip } from 'qunit';
|
||||||
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
||||||
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
||||||
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
||||||
@ -10,7 +10,7 @@ moduleForAcceptance('Acceptance | datasets/dataset/properties', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('visiting /datasets/dataset/properties', async function(assert) {
|
skip('visiting /datasets/dataset/properties', async function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
defaultScenario(server);
|
defaultScenario(server);
|
||||||
const url = '/datasets/12345/properties';
|
const url = '/datasets/12345/properties';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test } from 'qunit';
|
import { skip } from 'qunit';
|
||||||
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
||||||
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
||||||
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
||||||
@ -10,7 +10,7 @@ moduleForAcceptance('Acceptance | datasets/dataset/relations', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('visiting /datasets/dataset/relations', async function(assert) {
|
skip('visiting /datasets/dataset/relations', async function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
defaultScenario(server);
|
defaultScenario(server);
|
||||||
const url = '/datasets/12345/relations';
|
const url = '/datasets/12345/relations';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test } from 'qunit';
|
import { skip } from 'qunit';
|
||||||
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
||||||
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
||||||
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
||||||
@ -10,7 +10,7 @@ moduleForAcceptance('Acceptance | datasets/dataset/sample', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('visiting /datasets/dataset/sample', async function(assert) {
|
skip('visiting /datasets/dataset/sample', async function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
defaultScenario(server);
|
defaultScenario(server);
|
||||||
const url = '/datasets/12345/sample';
|
const url = '/datasets/12345/sample';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test } from 'qunit';
|
import { skip } from 'qunit';
|
||||||
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
import moduleForAcceptance from 'wherehows-web/tests/helpers/module-for-acceptance';
|
||||||
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
import { visit, find, currentURL, waitUntil } from 'ember-native-dom-helpers';
|
||||||
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
import defaultScenario from 'wherehows-web/mirage/scenarios/default';
|
||||||
@ -10,7 +10,7 @@ moduleForAcceptance('Acceptance | datasets/dataset/schema', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('visiting /datasets/dataset/schema', async function(assert) {
|
skip('visiting /datasets/dataset/schema', async function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
defaultScenario(server);
|
defaultScenario(server);
|
||||||
const url = '/datasets/12345/schema';
|
const url = '/datasets/12345/schema';
|
||||||
|
@ -23,7 +23,7 @@ test('it renders', function(assert) {
|
|||||||
this.$()
|
this.$()
|
||||||
.text()
|
.text()
|
||||||
.trim(),
|
.trim(),
|
||||||
'Dataset is deprecated?',
|
'Is this dataset deprecated?',
|
||||||
'shows the question asking if the dataset is deprecated'
|
'shows the question asking if the dataset is deprecated'
|
||||||
);
|
);
|
||||||
assert.equal(this.$('#dataset-is-deprecated').length, 1, 'has one input checkbox with known selector');
|
assert.equal(this.$('#dataset-is-deprecated').length, 1, 'has one input checkbox with known selector');
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
import { moduleForComponent, test } from 'ember-qunit';
|
||||||
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
import { waitUntil, find } from 'ember-native-dom-helpers';
|
||||||
|
import { urn } from 'wherehows-web/mirage/fixtures/urn';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
|
||||||
|
moduleForComponent(
|
||||||
|
'datasets/containers/dataset-compliance',
|
||||||
|
'Integration | Component | datasets/containers/dataset compliance',
|
||||||
|
{
|
||||||
|
integration: true,
|
||||||
|
|
||||||
|
beforeEach() {
|
||||||
|
this.server = sinon.createFakeServer();
|
||||||
|
},
|
||||||
|
|
||||||
|
afterEach() {
|
||||||
|
this.server.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
test('it renders', async function(assert) {
|
||||||
|
this.set('urn', urn);
|
||||||
|
this.server.respondWith('GET', /\/api\/v2\/datasets\/.*/, [
|
||||||
|
200,
|
||||||
|
{ 'Content-Type': 'application/json' },
|
||||||
|
JSON.stringify({})
|
||||||
|
]);
|
||||||
|
this.server.respondWith(/.*\/complianceDataTypes/, [200, { 'Content-Type': 'application/json' }, JSON.stringify([])]);
|
||||||
|
this.server.respondWith(/.*\/complianceSuggestion/, [
|
||||||
|
200,
|
||||||
|
{ 'Content-Type': 'application/json' },
|
||||||
|
JSON.stringify({})
|
||||||
|
]);
|
||||||
|
this.server.respondWith(/.*\/schema/, [
|
||||||
|
200,
|
||||||
|
{ 'Content-Type': 'application/json' },
|
||||||
|
JSON.stringify({
|
||||||
|
schema: {
|
||||||
|
schemaless: false,
|
||||||
|
columns: [],
|
||||||
|
rawSchema: null,
|
||||||
|
keySchema: null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.render(hbs`{{datasets/containers/dataset-compliance urn=urn}}`);
|
||||||
|
this.server.respond();
|
||||||
|
|
||||||
|
await waitUntil(() => find('.compliance-container'));
|
||||||
|
assert.ok(document.querySelector('empty-state'), 'renders the empty state component');
|
||||||
|
});
|
@ -0,0 +1,46 @@
|
|||||||
|
import { moduleForComponent, test } from 'ember-qunit';
|
||||||
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
import { waitUntil, find } from 'ember-native-dom-helpers';
|
||||||
|
import { urn } from 'wherehows-web/mirage/fixtures/urn';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
|
||||||
|
moduleForComponent(
|
||||||
|
'datasets/containers/dataset-ownership',
|
||||||
|
'Integration | Component | datasets/containers/dataset ownership',
|
||||||
|
{
|
||||||
|
integration: true,
|
||||||
|
|
||||||
|
beforeEach() {
|
||||||
|
this.server = sinon.createFakeServer();
|
||||||
|
this.server.respondImmediately = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
afterEach() {
|
||||||
|
this.server.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
test('it renders', async function(assert) {
|
||||||
|
const lookupClass = '.dataset-author-user-lookup';
|
||||||
|
this.set('urn', urn);
|
||||||
|
this.server.respondWith('GET', /\/api\/v2\/datasets.*/, [
|
||||||
|
200,
|
||||||
|
{ 'Content-Type': 'application/json' },
|
||||||
|
JSON.stringify({})
|
||||||
|
]);
|
||||||
|
this.server.respondWith('GET', '/api/v1/owner/types', [
|
||||||
|
200,
|
||||||
|
{ 'Content-Type': 'application/json' },
|
||||||
|
JSON.stringify([])
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.render(hbs`{{datasets/containers/dataset-ownership urn=urn}}`);
|
||||||
|
|
||||||
|
await waitUntil(() => find(lookupClass));
|
||||||
|
assert.equal(
|
||||||
|
document.querySelector(lookupClass).textContent.trim(),
|
||||||
|
'Add an Owner',
|
||||||
|
'shows dataset authors component'
|
||||||
|
);
|
||||||
|
});
|
@ -0,0 +1,35 @@
|
|||||||
|
import { moduleForComponent, test } from 'ember-qunit';
|
||||||
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
import { waitUntil, find } from 'ember-native-dom-helpers';
|
||||||
|
import { urn } from 'wherehows-web/mirage/fixtures/urn';
|
||||||
|
|
||||||
|
moduleForComponent(
|
||||||
|
'datasets/containers/dataset-properties',
|
||||||
|
'Integration | Component | datasets/containers/dataset properties',
|
||||||
|
{
|
||||||
|
integration: true,
|
||||||
|
|
||||||
|
beforeEach() {
|
||||||
|
this.server = sinon.createFakeServer();
|
||||||
|
this.server.respondImmediately = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
afterEach() {
|
||||||
|
this.server.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
test('it renders', function(assert) {
|
||||||
|
const labelClass = '.dataset-deprecation-toggle__toggle-header__label';
|
||||||
|
this.set('urn', urn);
|
||||||
|
this.server.respondWith('GET', /\/api\/v2\/datasets.*/, [
|
||||||
|
200,
|
||||||
|
{ 'Content-Type': 'application/json' },
|
||||||
|
JSON.stringify({})
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.render(hbs`{{datasets/containers/dataset-properties urn=urn}}`);
|
||||||
|
|
||||||
|
assert.equal(find(labelClass).textContent.trim(), 'Is this dataset deprecated?', 'renders presentation component');
|
||||||
|
});
|
@ -0,0 +1,28 @@
|
|||||||
|
import { moduleForComponent, test } from 'ember-qunit';
|
||||||
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
import { find } from 'ember-native-dom-helpers';
|
||||||
|
import { urn } from 'wherehows-web/mirage/fixtures/urn';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
|
||||||
|
moduleForComponent(
|
||||||
|
'datasets/containers/dataset-schema',
|
||||||
|
'Integration | Component | datasets/containers/dataset schema',
|
||||||
|
{
|
||||||
|
integration: true,
|
||||||
|
|
||||||
|
beforeEach() {
|
||||||
|
this.server = sinon.createFakeServer();
|
||||||
|
},
|
||||||
|
|
||||||
|
afterEach() {
|
||||||
|
this.server.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
test('it renders', function(assert) {
|
||||||
|
this.set('urn', urn);
|
||||||
|
this.render(hbs`{{datasets/containers/dataset-schema urn=urn}}`);
|
||||||
|
|
||||||
|
assert.ok(find('#json-viewer'), 'renders the dataset schema component');
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user