diff --git a/datahub-web/@datahub/data-models/addon/api/dataset/dataset.ts b/datahub-web/@datahub/data-models/addon/api/dataset/dataset.ts index 77127b8d36bca6..f6480edd4acf3a 100644 --- a/datahub-web/@datahub/data-models/addon/api/dataset/dataset.ts +++ b/datahub-web/@datahub/data-models/addon/api/dataset/dataset.ts @@ -7,7 +7,7 @@ import { encodeUrn } from '@datahub/utils/validators/urn'; * @param {ApiVersion} version the version of the api applicable to retrieve the Dataset * @returns {string} */ -export const datasetUrlRoot = (version: ApiVersion): string => `${getApiRoot(version)}/datasets`; +const datasetUrlRoot = (version: ApiVersion): string => `${getApiRoot(version)}/datasets`; /** * Constructs the url for a dataset identified by the provided string urn @@ -16,6 +16,13 @@ export const datasetUrlRoot = (version: ApiVersion): string => `${getApiRoot(ver */ export const datasetUrlByUrn = (urn: string): string => `${datasetUrlRoot(ApiVersion.v2)}/${encodeUrn(urn)}`; +/** + * Constructs the url for a dataset identified by the provided string urn + * @param {string} urn the urn to use in querying for dataset entity + * @returns {string} + */ +export const datasetV1UrlByUrn = (urn: string): string => `${datasetUrlRoot(ApiVersion.v1)}/${encodeUrn(urn)}`; + /** * Reads a dataset entity from api */ diff --git a/datahub-web/@datahub/data-models/addon/api/dataset/schema.ts b/datahub-web/@datahub/data-models/addon/api/dataset/schema.ts index 93b9d7a741ad98..bbb107bcf684b1 100644 --- a/datahub-web/@datahub/data-models/addon/api/dataset/schema.ts +++ b/datahub-web/@datahub/data-models/addon/api/dataset/schema.ts @@ -1,5 +1,5 @@ import { datasetUrlByUrn } from '@datahub/data-models/api/dataset/dataset'; -import { IDatasetSchema } from '@datahub/metadata-types/types/entity/dataset/scehma'; +import { IDatasetSchema } from '@datahub/metadata-types/types/entity/dataset/schema'; import { getJSON } from '@datahub/utils/api/fetcher'; /** diff --git a/datahub-web/@datahub/data-models/addon/constants/entity/index.ts b/datahub-web/@datahub/data-models/addon/constants/entity/index.ts index 1b6b5851e796c8..65b59f3951411d 100644 --- a/datahub-web/@datahub/data-models/addon/constants/entity/index.ts +++ b/datahub-web/@datahub/data-models/addon/constants/entity/index.ts @@ -4,6 +4,7 @@ import { ListEntity } from '@datahub/data-models/entity/list/list-entity'; import { BaseEntity } from '@datahub/data-models/entity/base-entity'; import { IBaseEntity } from '@datahub/metadata-types/types/entity/index'; import { DataConstructChangeManagementEntity } from '@datahub/data-models/entity/data-construct-change-management/data-construct-change-management-entity'; +import { GroupEntity } from '@datahub/data-models/entity/group/group-entity'; /** * Defines the interface for the DataModelEntity enum below. @@ -13,6 +14,7 @@ export interface IDataModelEntity { [DatasetEntity.displayName]: typeof DatasetEntity; [PersonEntity.displayName]: typeof PersonEntity; [ListEntity.displayName]: typeof ListEntity; + [GroupEntity.displayName]: typeof GroupEntity; [DataConstructChangeManagementEntity.displayName]: typeof DataConstructChangeManagementEntity; } @@ -23,6 +25,7 @@ export interface IDataModelEntity { export const DataModelEntity: IDataModelEntity = { [DatasetEntity.displayName]: DatasetEntity, [PersonEntity.displayName]: PersonEntity, + [GroupEntity.displayName]: GroupEntity, [ListEntity.displayName]: ListEntity, [DataConstructChangeManagementEntity.displayName]: DataConstructChangeManagementEntity }; diff --git a/datahub-web/@datahub/data-models/addon/entity/data-construct-change-management/data-construct-change-management-entity.ts b/datahub-web/@datahub/data-models/addon/entity/data-construct-change-management/data-construct-change-management-entity.ts index 1d9f04180a1c54..385cd1f5dcd69b 100644 --- a/datahub-web/@datahub/data-models/addon/entity/data-construct-change-management/data-construct-change-management-entity.ts +++ b/datahub-web/@datahub/data-models/addon/entity/data-construct-change-management/data-construct-change-management-entity.ts @@ -25,7 +25,8 @@ export class DataConstructChangeManagementEntity extends BaseEntity< search: { placeholder: '', attributes: [], - isEnabled: false + isEnabled: false, + defaultAspects: [] } }; } diff --git a/datahub-web/@datahub/data-models/addon/entity/dataset/helpers/validators/compliance/schema.ts b/datahub-web/@datahub/data-models/addon/entity/dataset/helpers/validators/compliance/schema.ts index 3d2d426b9e9f2b..a581979b0b3d65 100644 --- a/datahub-web/@datahub/data-models/addon/entity/dataset/helpers/validators/compliance/schema.ts +++ b/datahub-web/@datahub/data-models/addon/entity/dataset/helpers/validators/compliance/schema.ts @@ -1,6 +1,6 @@ import DatasetComplianceAnnotation from '@datahub/data-models/entity/dataset/modules/compliance-annotation'; import DatasetSchema from '@datahub/data-models/entity/dataset/modules/schema'; -import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/scehma'; +import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/schema'; /** * Given a list of compliance annotations and a schema to match against, removes annotations for diff --git a/datahub-web/@datahub/data-models/addon/entity/dataset/modules/schema.ts b/datahub-web/@datahub/data-models/addon/entity/dataset/modules/schema.ts index 79316e206e3852..088168a98c86c8 100644 --- a/datahub-web/@datahub/data-models/addon/entity/dataset/modules/schema.ts +++ b/datahub-web/@datahub/data-models/addon/entity/dataset/modules/schema.ts @@ -1,4 +1,4 @@ -import { IDatasetSchema, IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/scehma'; +import { IDatasetSchema, IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/schema'; import { oneWay } from '@ember/object/computed'; /** diff --git a/datahub-web/@datahub/data-models/addon/entity/dataset/render-props.ts b/datahub-web/@datahub/data-models/addon/entity/dataset/render-props.ts index 90b4f8a3721fc1..eec028fe29ef91 100644 --- a/datahub-web/@datahub/data-models/addon/entity/dataset/render-props.ts +++ b/datahub-web/@datahub/data-models/addon/entity/dataset/render-props.ts @@ -2,6 +2,16 @@ import { DatasetTab } from '@datahub/data-models/constants/entity/dataset/tabs'; import { IEntityRenderProps } from '@datahub/data-models/types/entity/rendering/entity-render-props'; import { fields } from '@datahub/data-models/entity/dataset/fields'; +/** + * Aspects for search datasets + */ +const defaultAspects: Array = [ + 'com.linkedin.common.Health', + 'com.linkedin.common.Likes', + 'com.linkedin.common.EntityTopUsage', + 'com.linkedin.common.Status' +]; + /** * Class properties common across instances * Dictates how visual ui components should be rendered @@ -27,10 +37,12 @@ export const getRenderProps = (): IEntityRenderProps => { }, { name: 'social/containers/social-metadata' } ], - isEnabled: true + isEnabled: true, + defaultAspects }, userEntityOwnership: { - attributes: fields + attributes: fields, + defaultAspects }, browse: { showHierarchySearch: false diff --git a/datahub-web/@datahub/data-models/addon/entity/group/group-entity.ts b/datahub-web/@datahub/data-models/addon/entity/group/group-entity.ts new file mode 100644 index 00000000000000..e3a1e441afde01 --- /dev/null +++ b/datahub-web/@datahub/data-models/addon/entity/group/group-entity.ts @@ -0,0 +1,34 @@ +import { BaseEntity, statics, IBaseEntityStatics } from '@datahub/data-models/entity/base-entity'; +import { IEntityRenderProps } from '@datahub/data-models/types/entity/rendering/entity-render-props'; +import { ICorpGroupResponse } from '@datahub/metadata-types/types/entity/group/group-entity'; + +/** + * The GroupEntity represents a group of people entities, most often associated with headless + * accounts or group aliases. + */ +@statics>() +export class GroupEntity extends BaseEntity { + /** + * Identifier for the entity + */ + static displayName: 'corp-groups' = 'corp-groups'; + + /** + * Class properties common across instances + * Dictates how visual ui components should be rendered + * Implemented as a getter to ensure that reads are idempotent + * @readonly + * @static + */ + static get renderProps(): IEntityRenderProps { + return { + apiEntityName: 'corpgroup', + search: { + placeholder: '', + attributes: [], + isEnabled: false, + defaultAspects: [] + } + }; + } +} diff --git a/datahub-web/@datahub/data-models/addon/entity/list/list-entity.ts b/datahub-web/@datahub/data-models/addon/entity/list/list-entity.ts index b8aaa19a9b5f79..92a47424886270 100644 --- a/datahub-web/@datahub/data-models/addon/entity/list/list-entity.ts +++ b/datahub-web/@datahub/data-models/addon/entity/list/list-entity.ts @@ -35,7 +35,8 @@ export class ListEntity extends BaseEntity<{}> { search: { placeholder: '', attributes: [], - isEnabled: false + isEnabled: false, + defaultAspects: [] } }; } diff --git a/datahub-web/@datahub/data-models/addon/entity/mock/mock-entity.ts b/datahub-web/@datahub/data-models/addon/entity/mock/mock-entity.ts index 0b3d71d9451932..ef5ce08d21dddf 100644 --- a/datahub-web/@datahub/data-models/addon/entity/mock/mock-entity.ts +++ b/datahub-web/@datahub/data-models/addon/entity/mock/mock-entity.ts @@ -33,7 +33,8 @@ export class MockEntity extends BaseEntity { desc: 'A mock field', example: 'Evolutionary' } - ] + ], + defaultAspects: [] }, entityPage: { route: 'entity-type.urn', diff --git a/datahub-web/@datahub/data-models/addon/entity/person/render-props.ts b/datahub-web/@datahub/data-models/addon/entity/person/render-props.ts index abb995c4afd20c..9eafa02a59326e 100644 --- a/datahub-web/@datahub/data-models/addon/entity/person/render-props.ts +++ b/datahub-web/@datahub/data-models/addon/entity/person/render-props.ts @@ -27,8 +27,11 @@ export interface IPersonEntitySpecificConfigs { * * Making sure entityPage is not marked optional in the types as we know it is defined */ -export const getRenderProps = (): IEntityRenderProps & { entityPage: IEntityRenderPropsEntityPage } => { +export const getRenderProps = (): IEntityRenderProps & { + entityPage: IEntityRenderPropsEntityPage; +} => { const tabIds = [PersonTab.UserOwnership]; + const aspects: Array = ['com.linkedin.identity.CorpUserInfo']; return { apiEntityName: 'corpuser', @@ -96,7 +99,8 @@ export const getRenderProps = (): IEntityRenderProps & { entityPage: IEntityRend showFacets: false, placeholder: 'Search for People...', autocompleteNameField: 'fullName', - isEnabled: true + isEnabled: true, + defaultAspects: aspects } }; }; diff --git a/datahub-web/@datahub/data-models/addon/mirage-addon/factories/dataset-schema-column.ts b/datahub-web/@datahub/data-models/addon/mirage-addon/factories/dataset-schema-column.ts new file mode 100644 index 00000000000000..2c7eb9e3371fa2 --- /dev/null +++ b/datahub-web/@datahub/data-models/addon/mirage-addon/factories/dataset-schema-column.ts @@ -0,0 +1,42 @@ +import { Factory, faker } from 'ember-cli-mirage'; +import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/schema'; + +export default Factory.extend({ + comment: faker.lorem.sentence, + //faker 3 does not have database + dataType: (faker.database && faker.database.type) || ((i: number): string => `data_type_${i}`), + distributed: faker.random.boolean, + //faker 3 does not have database + fieldName: (faker.database && faker.database.column) || ((i: number): string => `field_name_${i}`), + fullFieldPath: faker.system.filePath, + indexed: faker.random.boolean, + nullable: faker.random.boolean, + partitioned: faker.random.boolean, + treeGridClass: null, + commentCount(): number { + return faker.random.number(1000); + }, + id(): number | null { + return faker.random.arrayElement([faker.random.number(), null]); + }, + parentSortID() { + return faker.random.number(100); + }, + sortID(): number { + return faker.random.number(100); + } +}); + +declare module 'ember-cli-mirage/types/registries/schema' { + interface IMirageSchemaRegistry { + datasetSchemaColumns: IDatasetSchemaColumn; + datasetSchemaColumn?: IDatasetSchemaColumn; + } +} + +declare module 'ember-cli-mirage/types/registries/model' { + interface IMirageModelRegistry { + datasetSchemaColumns: IDatasetSchemaColumn; + datasetSchemaColumn?: IDatasetSchemaColumn; + } +} diff --git a/datahub-web/@datahub/data-models/addon/mirage-addon/mirage-config.ts b/datahub-web/@datahub/data-models/addon/mirage-addon/mirage-config.ts index cbd2bd2821b474..a486b27e455c7e 100644 --- a/datahub-web/@datahub/data-models/addon/mirage-addon/mirage-config.ts +++ b/datahub-web/@datahub/data-models/addon/mirage-addon/mirage-config.ts @@ -3,6 +3,7 @@ import { getApiRoot, ApiVersion } from '@datahub/utils/api/shared'; import { ownershipEndpoint } from '@datahub/data-models/api/dataset/ownership'; import { getDatasetOwnership } from '@datahub/data-models/mirage-addon/test-helpers/datasets/ownership'; import { getEntity } from '@datahub/data-models/mirage-addon/test-helpers/get-entity'; +import { getDatasetSchema } from '@datahub/data-models/mirage-addon/test-helpers/datasets/schema'; /** * Shareable mirage/config for dependent modules * @param {Server} server the passed in Mirage server instance in the calling test @@ -12,4 +13,5 @@ export const setup = (server: Server): void => { server.get('/:entityType/:identifier', getEntity); server.get(`datasets/:urn/${ownershipEndpoint}`, getDatasetOwnership); + server.get('/datasets/:urn/schema', getDatasetSchema); }; diff --git a/datahub-web/@datahub/data-models/addon/mirage-addon/test-helpers/datasets/schema.ts b/datahub-web/@datahub/data-models/addon/mirage-addon/test-helpers/datasets/schema.ts index da8bb3185ac8f5..5b95805fd54f95 100644 --- a/datahub-web/@datahub/data-models/addon/mirage-addon/test-helpers/datasets/schema.ts +++ b/datahub-web/@datahub/data-models/addon/mirage-addon/test-helpers/datasets/schema.ts @@ -1,28 +1,19 @@ import DatasetSchema from '@datahub/data-models/entity/dataset/modules/schema'; -import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/scehma'; +import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/schema'; +import { IDatasetSchema } from '@datahub/metadata-types/types/entity/dataset/schema'; +import { HandlerFunction, Server } from 'ember-cli-mirage'; /** * Allows us to abstract away most of the logic to generate a mock list of schema fields and allows * us to create these fields easily in a customizable way through the tests and mock application * @param {Array} fieldNames - field names to generate for the mocked schema fields */ -export const generateDatasetSchemaFields = (fieldNames: Array = []): Array => { +export const generateDatasetSchemaFields = ( + fieldNames: Array = [], + server: Server +): Array => { return fieldNames.map( - (name): IDatasetSchemaColumn => ({ - comment: '', - commentCount: 0, - dataType: 'pretendType', - distributed: false, - fieldName: name, - fullFieldPath: name, - id: null, - indexed: false, - nullable: false, - parentSortID: 0, - partitioned: false, - sortID: 0, - treeGridClass: null - }) + (name): IDatasetSchemaColumn => server.create('datasetSchemaColumn', { fieldName: name, fullFieldPath: name }) ); }; @@ -40,3 +31,22 @@ export const generateDatasetSchema = (columns: Array = []) keySchema: 'testSchema' }); }; + +// TODO: [META-8403] Needs to be expanded into properly getting schemas for certain dataset test scenarios, +// but this will be sufficient for the current situation of testing basic compliance table flow + +/** + * This handler is used in the mirage route config to handle get requests for a dataset schema. + */ +export const getDatasetSchema: HandlerFunction = function(schema): { schema: IDatasetSchema } { + const columns = this.serialize(schema.db.datasetSchemaColumns); + const dsSchema: IDatasetSchema = { + keySchema: null, + lastModified: 1548806346860, + rawSchema: '', + schemaless: false, + columns: [...columns] + }; + + return { schema: dsSchema }; +}; diff --git a/datahub-web/@datahub/data-models/tests/unit/utils/entity/dataset/helpers/validators/schema-test.ts b/datahub-web/@datahub/data-models/tests/unit/utils/entity/dataset/helpers/validators/schema-test.ts index 08095c22f6c033..3444864d8b2171 100644 --- a/datahub-web/@datahub/data-models/tests/unit/utils/entity/dataset/helpers/validators/schema-test.ts +++ b/datahub-web/@datahub/data-models/tests/unit/utils/entity/dataset/helpers/validators/schema-test.ts @@ -4,21 +4,24 @@ import DatasetSchema from '@datahub/data-models/entity/dataset/modules/schema'; import DatasetComplianceAnnotation from '@datahub/data-models/entity/dataset/modules/compliance-annotation'; import { filterAnnotationsToDatasetSchema } from '@datahub/data-models/entity/dataset/helpers/validators/compliance/schema'; import { - generateDatasetSchemaFields, - generateDatasetSchema + generateDatasetSchema, + generateDatasetSchemaFields } from '@datahub/data-models/mirage-addon/test-helpers/datasets/schema'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { MirageTestContext } from '@datahub/utils/types/vendor/ember-cli-mirage/mirage-tests'; module('Unit | Utility | entity/dataset/helpers/validators/schema', function(hooks): void { setupTest(hooks); + setupMirage(hooks); - test('filterAnnotationsToDatasetSchema', function(assert): void { + test('filterAnnotationsToDatasetSchema', function(this: MirageTestContext, assert): void { const annotations: Array = []; let schema = new DatasetSchema(); const resultA = filterAnnotationsToDatasetSchema(annotations, schema); assert.ok(resultA, 'Blank case works without issues'); - schema = generateDatasetSchema(generateDatasetSchemaFields(['pokemon["name"]', 'type["string"]'])); + schema = generateDatasetSchema(generateDatasetSchemaFields(['pokemon["name"]', 'type["string"]'], this.server)); annotations.push( ...[ @@ -41,7 +44,7 @@ module('Unit | Utility | entity/dataset/helpers/validators/schema', function(hoo const resultC = filterAnnotationsToDatasetSchema(annotations, schema); assert.equal(resultC.length, 4, 'Filters out the annotation that doesnt match schema'); - schema = generateDatasetSchema(generateDatasetSchemaFields(['pokemon["string"]', 'type["string"]'])); + schema = generateDatasetSchema(generateDatasetSchemaFields(['pokemon["string"]', 'type["string"]'], this.server)); const resultD = filterAnnotationsToDatasetSchema(annotations, schema); assert.equal(resultD.length, 3, 'Filters out annotations that do not match schema, after schema change'); diff --git a/datahub-web/@datahub/data-models/types/search/search-entity-render-prop.d.ts b/datahub-web/@datahub/data-models/types/search/search-entity-render-prop.d.ts index 2ec85d623f1e6f..c78483cb6c2423 100644 --- a/datahub-web/@datahub/data-models/types/search/search-entity-render-prop.d.ts +++ b/datahub-web/@datahub/data-models/types/search/search-entity-render-prop.d.ts @@ -26,6 +26,7 @@ export interface IEntityRenderCommonPropsSearch { // Note: Though this parameter is optional, items that rely on listing entities that are searchable // will default this to false isEnabled?: boolean; + defaultAspects: Array; } /** * This interface should live in search addon, but search addon depends on data-models and diff --git a/datahub-web/packages/data-portal/app/components/datasets/containers/dataset-schema.ts b/datahub-web/@datahub/datasets-core/addon/components/datasets/containers/dataset-schema.ts similarity index 66% rename from datahub-web/packages/data-portal/app/components/datasets/containers/dataset-schema.ts rename to datahub-web/@datahub/datasets-core/addon/components/datasets/containers/dataset-schema.ts index f4890baf1760d8..fcd188abd1ac50 100644 --- a/datahub-web/packages/data-portal/app/components/datasets/containers/dataset-schema.ts +++ b/datahub-web/@datahub/datasets-core/addon/components/datasets/containers/dataset-schema.ts @@ -1,26 +1,31 @@ import Component from '@ember/component'; import { setProperties } from '@ember/object'; import { task } from 'ember-concurrency'; -import { IDatasetColumn, IDatasetColumnWithHtmlComments } from 'datahub-web/typings/api/datasets/columns'; -import { IDatasetSchema } from 'datahub-web/typings/api/datasets/schema'; -import { augmentObjectsWithHtmlComments } from 'datahub-web/utils/api/datasets/columns'; -import { readDatasetSchemaByUrn } from 'datahub-web/utils/api/datasets/schema'; +import { IDatasetColumnWithHtmlComments } from '@datahub/datasets-core/types/datasets/columns'; +import { augmentObjectsWithHtmlComments } from '@datahub/datasets-core/utils/api/columns'; +import { readDatasetSchemaByUrn } from '@datahub/datasets-core/utils/api/schema'; import { containerDataSource } from '@datahub/utils/api/data-source'; import { ETaskPromise } from '@datahub/utils/types/concurrency'; +import { IDatasetSchemaColumn, IDatasetSchema } from '@datahub/metadata-types/types/entity/dataset/schema'; +import { layout } from '@ember-decorators/component'; +// @ts-ignore: Ignore import of compiled template +import template from '../../../templates/components/datasets/containers/dataset-schema'; +import { DatasetEntity } from '@datahub/data-models/entity/dataset/dataset-entity'; -@containerDataSource('getDatasetSchemaTask', ['urn']) +@layout(template) +@containerDataSource('getDatasetSchemaTask', ['entity']) export default class DatasetSchemaContainer extends Component { /** * The urn identifier for the dataset * @type {string} */ - urn!: string; + entity!: DatasetEntity; /** * json string for the dataset schema properties * @type {string} */ - json: string; + json?: string; /** * Stores the last modified date on the dataset schema as an utc time string @@ -32,7 +37,7 @@ export default class DatasetSchemaContainer extends Component { * List of schema properties for the dataset * @type {IDatasetColumnWithHtmlComments | IDatasetColumn} */ - schemas: Array; + schemas?: Array; /** * If there is schema or not @@ -44,7 +49,7 @@ export default class DatasetSchemaContainer extends Component { */ @task(function*(this: DatasetSchemaContainer): IterableIterator> { const { columns = [], rawSchema: json, lastModified } = ((yield readDatasetSchemaByUrn( - this.urn + this.entity.urn )) as unknown) as IDatasetSchema; const lastModifiedString = lastModified ? new Date(lastModified).toLocaleString() : ''; diff --git a/datahub-web/packages/data-portal/app/templates/components/dataset-schema.hbs b/datahub-web/@datahub/datasets-core/addon/components/datasets/dataset-schema.hbs similarity index 86% rename from datahub-web/packages/data-portal/app/templates/components/dataset-schema.hbs rename to datahub-web/@datahub/datasets-core/addon/components/datasets/dataset-schema.hbs index 4df7f875aabed8..f2eb2f37f2f1bf 100644 --- a/datahub-web/packages/data-portal/app/templates/components/dataset-schema.hbs +++ b/datahub-web/@datahub/datasets-core/addon/components/datasets/dataset-schema.hbs @@ -1,4 +1,4 @@ -{{#if schemas.length}} +{{#if @schemas.length}}
@@ -9,14 +9,14 @@ @leftOptionText="Table" @rightOptionValue={{false}} @rightOptionText="JSON" - @onChange={{perform this.onToggleSchemaViewTypeTask}} + @onChange={{fn this.onToggleSchemaViewTypeTask}} />
- Last modified: {{lastModified}} + Last modified: {{@lastModified}}
@@ -33,19 +33,13 @@ Default Comments - - - - {{#each this.schemas as |schema|}} + {{#each @schemas as |schema|}}
- {{schema.fieldName}} + {{schema.fieldName}} {{#if schema.nullable}} N @@ -83,9 +77,6 @@

- - {{schema.commentCount}} -
{{/each}}
diff --git a/datahub-web/packages/data-portal/app/components/dataset-schema.ts b/datahub-web/@datahub/datasets-core/addon/components/datasets/dataset-schema.ts similarity index 74% rename from datahub-web/packages/data-portal/app/components/dataset-schema.ts rename to datahub-web/@datahub/datasets-core/addon/components/datasets/dataset-schema.ts index d3bcf1795c9c2e..303710d8a31f0f 100644 --- a/datahub-web/packages/data-portal/app/components/dataset-schema.ts +++ b/datahub-web/@datahub/datasets-core/addon/components/datasets/dataset-schema.ts @@ -1,8 +1,7 @@ -import Component from '@ember/component'; -import { computed, set, setProperties } from '@ember/object'; -import { IDatasetColumn, IDatasetColumnWithHtmlComments } from 'datahub-web/typings/api/datasets/columns'; -import { task } from 'ember-concurrency'; -import { ETask } from '@datahub/utils/types/concurrency'; +import Component from '@glimmer/component'; +import { computed, set, setProperties, action } from '@ember/object'; +import { IDatasetColumnWithHtmlComments } from '@datahub/datasets-core/types/datasets/columns'; +import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/schema'; /** * Presentational component for rendering a JSON Schema, either with a Table or a JSON representation @@ -10,7 +9,21 @@ import { ETask } from '@datahub/utils/types/concurrency'; * @class DatasetSchema * @extends {Component} */ -export default class DatasetSchema extends Component { +export default class DatasetSchema extends Component<{ + /** + * Externally supplied JSON value for the related Dataset's schema. This is defaulted to an empty JSON object + */ + json: string; + /** + * List of columns in the Dataset and additional attributes, used to back the table representation of the Dataset's schema + */ + schemas: Array; + + /** + * Schema last modified + */ + lastModified: Date; +}> { /** * Flag indicating that the schema should be rendered with a tabular representation * This currently is driven by the schemas attribute @@ -22,21 +35,11 @@ export default class DatasetSchema extends Component { */ isValidJson = false; - /** - * Externally supplied JSON value for the related Dataset's schema. This is defaulted to an empty JSON object - */ - json = '{}'; - /** * This will reference the prettified JSON input from this.JSON. * By default, it points to the same value */ - possibleJsonOutput = this.json; - - /** - * List of columns in the Dataset and additional attributes, used to back the table representation of the Dataset's schema - */ - schemas: Array = []; + possibleJsonOutput = this.args.json; /** * Toggle the render mode for ember-ace editor between JSON and text depending on the last task @@ -55,7 +58,7 @@ export default class DatasetSchema extends Component { * Format the JSON string as a human friendly string */ prettifyJson(_r: boolean = this.isShowingTable): string { - return JSON.stringify(JSON.parse(this.json), null, '\t'); + return JSON.stringify(JSON.parse(this.args.json), null, '\t'); } /** @@ -64,13 +67,11 @@ export default class DatasetSchema extends Component { * An error will be thrown by the task if an invalid JSON string is provided * @param {boolean} [shouldShowTable=this.isShowingTable] Flag indicating the user toggled view, * if no value is passed in e.g. when attrs are updated, we retain the currently set flag state - * @type {ETask} */ - @(task(function*( - this: DatasetSchema, - shouldShowTable: DatasetSchema['isShowingTable'] = this.isShowingTable - ): IterableIterator { - let output = this.json; + + @action + onToggleSchemaViewTypeTask(shouldShowTable: DatasetSchema['isShowingTable'] = this.isShowingTable): void { + let output = this.args.json; // Attempt to parse JSON try { @@ -89,8 +90,5 @@ export default class DatasetSchema extends Component { // Always toggle state even if the JSON is invalid , source value (this.json) will be rendered as plain text setProperties(this, { possibleJsonOutput: output, isShowingTable: shouldShowTable }); } - }) - .restartable() - .on('didUpdateAttrs')) - onToggleSchemaViewTypeTask: ETask; + } } diff --git a/datahub-web/@datahub/datasets-core/addon/mirage-addon/datasets-config.ts b/datahub-web/@datahub/datasets-core/addon/mirage-addon/datasets-config.ts index dcd1571d5b34ca..33e82060bb7ee0 100644 --- a/datahub-web/@datahub/datasets-core/addon/mirage-addon/datasets-config.ts +++ b/datahub-web/@datahub/datasets-core/addon/mirage-addon/datasets-config.ts @@ -1,4 +1,3 @@ -import { getDatasetSchema } from '@datahub/datasets-core/mirage-addon/helpers/schema'; import { getDataPlatforms } from '@datahub/datasets-core/mirage-addon/helpers/platforms'; import { getDatasetOwnership } from '@datahub/datasets-core/mirage-addon/helpers/ownership'; import { Server } from 'ember-cli-mirage'; @@ -10,8 +9,6 @@ export function datasetsMirageConfig(server: Server | IMirageServer): void { server = server as IMirageServer; server.namespace = '/api/v2'; - server.get('/datasets/:urn/schema', getDatasetSchema); - // Temporary solution as we don't need real upstreams at the moment, we just don't wnat mirage to throw // any errors server.get('/datasets/:urn/upstreams', () => []); diff --git a/datahub-web/@datahub/datasets-core/addon/mirage-addon/factories/dataset-schema-column.ts b/datahub-web/@datahub/datasets-core/addon/mirage-addon/factories/dataset-schema-column.ts deleted file mode 100644 index 739081d7ecc67e..00000000000000 --- a/datahub-web/@datahub/datasets-core/addon/mirage-addon/factories/dataset-schema-column.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Factory, faker } from 'ember-cli-mirage'; - -/** - * A list of static identifier fields to cycle through for testing purposes. This is to help reduce the variation - * in identifier fields to a list of expected values - */ -const fieldNames = [ - 'CONTACT_ID[type = long]', - 'DATA_XML_VERSION[type = long]', - 'DATA[type = string]', - 'DELETED_TS[type = long]', - 'GG_MODI_TS[type = long]', - 'GG_STATUS[type = string]', - 'IS_NOTE_MANUALLY_MOD[type = string]', - 'lumos_dropdate', - 'MODIFIED_DATE' -]; - -export default Factory.extend({ - comment: 'pocketmon', - commentCount: null, - dataType: 'DATATYPE', - distributed: false, - fieldName: faker.list.cycle(...fieldNames), - fullFieldPath(): string { - return this.fieldName as string; - }, - id(id: number): number { - return id; - }, - indexed: false, - nullable: false, - parentSortID: 7, - partitioned: false, - sortId: 7, - treeGridClass: null -}); diff --git a/datahub-web/@datahub/datasets-core/addon/mirage-addon/helpers/schema.ts b/datahub-web/@datahub/datasets-core/addon/mirage-addon/helpers/schema.ts deleted file mode 100644 index b3ba9acfde94cf..00000000000000 --- a/datahub-web/@datahub/datasets-core/addon/mirage-addon/helpers/schema.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { IFunctionRouteHandler } from '@datahub/utils/types/vendor/ember-cli-mirage-deprecated'; -import { IMirageDatasetCoreSchema } from '@datahub/datasets-core/types/vendor/mirage-for-datasets'; -import { IDatasetSchema } from '@datahub/metadata-types/types/entity/dataset/scehma'; - -// TODO: [META-8403] Needs to be expanded into properly getting schemas for certain dataset test scenarios, -// but this will be sufficient for the current situation of testing basic compliance table flow - -/** - * This handler is used in the mirage route config to handle get requests for a dataset schema. - */ -export const getDatasetSchema = function( - this: IFunctionRouteHandler, - schema: IMirageDatasetCoreSchema -): { schema: IDatasetSchema } { - const dsSchema: IDatasetSchema = { - keySchema: null, - lastModified: 1548806346860, - rawSchema: '', - schemaless: false, - columns: [...schema.db.datasetSchemaColumns] - }; - - return { schema: this.serialize(dsSchema) }; -}; diff --git a/datahub-web/@datahub/datasets-core/addon/mirage-addon/scenarios/default.ts b/datahub-web/@datahub/datasets-core/addon/mirage-addon/scenarios/default.ts index 0578bf05dede08..ed8b8e699070f9 100644 --- a/datahub-web/@datahub/datasets-core/addon/mirage-addon/scenarios/default.ts +++ b/datahub-web/@datahub/datasets-core/addon/mirage-addon/scenarios/default.ts @@ -1,5 +1,18 @@ import { IMirageServer } from '@datahub/utils/types/vendor/ember-cli-mirage-deprecated'; import { Server } from 'ember-cli-mirage'; +import { generateDatasetSchemaFields } from '@datahub/data-models/mirage-addon/test-helpers/datasets/schema'; + +export const fieldNames = [ + 'CONTACT_ID[type = long]', + 'DATA_XML_VERSION[type = long]', + 'DATA[type = string]', + 'DELETED_TS[type = long]', + 'GG_MODI_TS[type = long]', + 'GG_STATUS[type = string]', + 'IS_NOTE_MANUALLY_MOD[type = string]', + 'lumos_dropdate', + 'MODIFIED_DATE' +]; // TODO: [META-11940] Looks like mirage server types are incompatible but is outside the scope of this // migration. Should return to clean up @@ -9,7 +22,9 @@ export default function(server: Server | IMirageServer): void { server.createList('datasetComplianceAnnotationTag', 9); server.createList('datasetComplianceAnnotationTag', 10, 'asSuggestion'); - server.createList('datasetSchemaColumn', 9); + + generateDatasetSchemaFields(fieldNames, (server as unknown) as Server); + server.createList('datasetPurgePolicy', 1); server.createList('datasets', 1); server.createList('datasetComplianceInfo', 1); diff --git a/datahub-web/packages/data-portal/app/templates/components/datasets/containers/dataset-schema.hbs b/datahub-web/@datahub/datasets-core/addon/templates/components/datasets/containers/dataset-schema.hbs similarity index 93% rename from datahub-web/packages/data-portal/app/templates/components/datasets/containers/dataset-schema.hbs rename to datahub-web/@datahub/datasets-core/addon/templates/components/datasets/containers/dataset-schema.hbs index ac0d16d858661e..7a59f5cd45ec17 100644 --- a/datahub-web/packages/data-portal/app/templates/components/datasets/containers/dataset-schema.hbs +++ b/datahub-web/@datahub/datasets-core/addon/templates/components/datasets/containers/dataset-schema.hbs @@ -7,7 +7,7 @@ @heading="We could not find a schema for this dataset" /> {{else}} - ( + objectWithComment: T +): T | (T & { commentHtml: string }) => { + const { comment } = objectWithComment; + // TODO: DSS-6122 Refactor global function reference to marked + // not using spread operator here: https://github.com/Microsoft/TypeScript/issues/10727 + // current ts version: 2.5.3 + return comment + ? Object.assign({}, objectWithComment, { commentHtml: renderLinksAsAnchorTags([comment]) }) + : objectWithComment; +}; +/** + * Takes a list of objects with comments and returns an array of objects with comments or html comments + * @type {(array: Array) => Array} + */ +export const augmentObjectsWithHtmlComments = arrayMap< + IDatasetSchemaColumn, + IDatasetColumnWithHtmlComments | IDatasetSchemaColumn +>(augmentWithHtmlComment); diff --git a/datahub-web/packages/data-portal/app/utils/api/datasets/schema.ts b/datahub-web/@datahub/datasets-core/addon/utils/api/schema.ts similarity index 81% rename from datahub-web/packages/data-portal/app/utils/api/datasets/schema.ts rename to datahub-web/@datahub/datasets-core/addon/utils/api/schema.ts index c24c104f93bd98..8abd6c714d63f4 100644 --- a/datahub-web/packages/data-portal/app/utils/api/datasets/schema.ts +++ b/datahub-web/@datahub/datasets-core/addon/utils/api/schema.ts @@ -1,6 +1,7 @@ -import { IDatasetSchema, IDatasetSchemaGetResponse } from 'datahub-web/typings/api/datasets/schema'; import { getJSON } from '@datahub/utils/api/fetcher'; import { datasetUrlByUrn } from '@datahub/data-models/api/dataset/dataset'; +import { IDatasetSchema } from '@datahub/metadata-types/types/entity/dataset/schema'; +import { IDatasetSchemaGetResponse } from '@datahub/datasets-core/types/datasets/schema'; /** * Returns the url for a dataset schema by urn @@ -19,7 +20,7 @@ const readDatasetSchemaByUrn = async (urn: string): Promise => { try { ({ schema } = await getJSON({ url: datasetSchemaUrlByUrn(urn) })); - } catch { + } catch (e) { return { schemaless: false, rawSchema: null, diff --git a/datahub-web/@datahub/datasets-core/app/components/datasets/containers/dataset-schema.js b/datahub-web/@datahub/datasets-core/app/components/datasets/containers/dataset-schema.js new file mode 100644 index 00000000000000..d16eb7a4a9b7d3 --- /dev/null +++ b/datahub-web/@datahub/datasets-core/app/components/datasets/containers/dataset-schema.js @@ -0,0 +1 @@ +export { default } from '@datahub/datasets-core/components/datasets/containers/dataset-schema'; diff --git a/datahub-web/@datahub/datasets-core/app/components/datasets/dataset-schema.js b/datahub-web/@datahub/datasets-core/app/components/datasets/dataset-schema.js new file mode 100644 index 00000000000000..2bd721b5cee2a1 --- /dev/null +++ b/datahub-web/@datahub/datasets-core/app/components/datasets/dataset-schema.js @@ -0,0 +1 @@ +export { default } from '@datahub/datasets-core/components/datasets/dataset-schema'; diff --git a/datahub-web/@datahub/datasets-core/package.json b/datahub-web/@datahub/datasets-core/package.json index dce3cdaf4aca8e..01823bfd3d60d2 100644 --- a/datahub-web/@datahub/datasets-core/package.json +++ b/datahub-web/@datahub/datasets-core/package.json @@ -21,6 +21,7 @@ "postpublish": "ember ts:clean" }, "dependencies": { + "@datahub/shared": "0.0.0", "@datahub/data-models": "0.0.0", "@datahub/metadata-types": "0.0.0", "@datahub/utils": "0.0.0", diff --git a/datahub-web/@datahub/datasets-core/tests/integration/components/datasets/containers/dataset-schema-test.ts b/datahub-web/@datahub/datasets-core/tests/integration/components/datasets/containers/dataset-schema-test.ts new file mode 100644 index 00000000000000..35667bb3e31542 --- /dev/null +++ b/datahub-web/@datahub/datasets-core/tests/integration/components/datasets/containers/dataset-schema-test.ts @@ -0,0 +1,20 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import hbs from 'htmlbars-inline-precompile'; +import { urn } from '@datahub/shared/mirage-addon/test-helpers/urn'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; + +module('Integration | Component | datasets/containers/dataset-schema', function(hooks): void { + setupRenderingTest(hooks); + setupMirage(hooks); + + test('renders default state as expected', async function(assert): Promise { + this.set('urn', urn); + + await render(hbs``); + assert + .dom('.empty-state__header') + .hasText('We could not find a schema for this dataset', 'renders empty State with an error prompt'); + }); +}); diff --git a/datahub-web/@datahub/datasets-core/tests/integration/components/datasets/dataset-schema-test.ts b/datahub-web/@datahub/datasets-core/tests/integration/components/datasets/dataset-schema-test.ts new file mode 100644 index 00000000000000..3f41cba8f2c810 --- /dev/null +++ b/datahub-web/@datahub/datasets-core/tests/integration/components/datasets/dataset-schema-test.ts @@ -0,0 +1,130 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, click } from '@ember/test-helpers'; +import hbs from 'htmlbars-inline-precompile'; +import DatasetSchema from '@datahub/datasets-core/components/datasets/dataset-schema'; +import { MirageTestContext } from '@datahub/utils/types/vendor/ember-cli-mirage/mirage-tests'; +import { getSerializedMirageModel } from '@datahub/utils/test-helpers/serialize-mirage-model'; +import { getRenderedComponent } from '@datahub/utils/test-helpers/register-component'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; + +module('Integration | Component | datasets/dataset-schema', function(hooks): void { + setupRenderingTest(hooks); + setupMirage(hooks); + + let defaultOnError: OnErrorEventHandler; + // Click helper + const toggleJson = (): Promise => click('.nacho-toggle__button--right'); + + // there is an issue where the worker loading gets cancelled (due to test finished) + // since we have no control on the Ace lib, we are just ignoring this error as this + // only affects to syntax validation (if syntax is wrong) + const ignoreWorkerError = function(this: unknown, _e: unknown, msg: string): void { + if (msg.indexOf('blob:') === 0) { + return; + } + + // eslint-disable-next-line + defaultOnError?.apply(this, arguments); + }; + + hooks.before(() => { + defaultOnError = window.onerror; + window.onerror = ignoreWorkerError; + }); + + hooks.after(() => { + window.onerror = defaultOnError; + }); + + test('empty component render', async function(assert): Promise { + await render(hbs``); + + assert.dom().hasText('There was an error retrieving the Schema for this Dataset'); + const schemas: DatasetSchema['args']['schemas'] = []; + const json = '{}'; + + this.setProperties({ json, schemas }); + + await render(hbs` + + `); + + assert.dom().hasText('There was an error retrieving the Schema for this Dataset'); + }); + + test('component attributes, and interactive JSON rendering', async function(this: MirageTestContext, assert): Promise< + void + > { + const tableSelector = '.dataset-detail-table'; + const json = '{}'; + + this.server.createList('datasetSchemaColumns', 10); + const schemas: DatasetSchema['args']['schemas'] = getSerializedMirageModel('datasetSchemaColumns', this.server); + + this.setProperties({ json, schemas }); + + const component = await getRenderedComponent({ + template: hbs` + + `, + ComponentToRender: DatasetSchema, + componentName: 'datasets/dataset-schema', + testContext: this + }); + + assert.dom(`${tableSelector} thead`).hasText('Column Data Type Default Comments'); + assert.equal( + document.querySelectorAll(`${tableSelector} tbody tr`).length, + schemas.length, + 'Expected a table row to be rendered for each schema column' + ); + + assert + .dom('.dataset-schema__header') + .hasText('Table JSON Last modified:', 'Expected toggle header row to be visible'); + + await toggleJson(); + + assert.notOk(component.isShowingTable, 'Expected the isShowingTable to be false'); + assert.dom(tableSelector).doesNotExist(); + + assert.equal(component.aceMode, 'ace/mode/json'); + assert.dom('.dataset-compliance__editor').exists(); + assert.dom('.dataset-compliance__editor .ace_content').hasText('{}'); + }); + + test('Non JSON rendering', async function(this: MirageTestContext, assert): Promise { + const notJson = + 'struct'; + + this.server.createList('datasetSchemaColumns', 1); + this.setProperties({ notJson, schemas: getSerializedMirageModel('datasetSchemaColumns', this.server) }); + + const component = await getRenderedComponent({ + template: hbs` + + `, + ComponentToRender: DatasetSchema, + componentName: 'datasets/dataset-schema', + testContext: this + }); + + await toggleJson(); + + assert.equal(component.aceMode, 'ace/mode/text', 'Expected the mode to change to text when JSON is invalid'); + assert + .dom('.dataset-compliance__editor .ace_content') + .hasText(notJson, 'Expected none JSON content to be rendered as text'); + + assert.dom('.ace_gutter-cell').hasText('1', 'Expected line numbers to be show in the ace editor'); + }); +}); diff --git a/datahub-web/@datahub/datasets-core/types/datasets/columns.d.ts b/datahub-web/@datahub/datasets-core/types/datasets/columns.d.ts new file mode 100644 index 00000000000000..92a2ca39f69281 --- /dev/null +++ b/datahub-web/@datahub/datasets-core/types/datasets/columns.d.ts @@ -0,0 +1,19 @@ +import { ApiStatus } from '@datahub/utils/api/shared'; +import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/schema'; + +/** + * Describes the interface that extends a DatasetColumn with a string + */ +export interface IDatasetColumnWithHtmlComments extends IDatasetSchemaColumn { + commentHtml: string; +} + +/** + * Describes a dataset column GET request response + */ +export interface IDatasetColumnsGetResponse { + status: ApiStatus; + columns?: Array; + message?: string; + schemaless: boolean; +} diff --git a/datahub-web/@datahub/datasets-core/types/datasets/schema.d.ts b/datahub-web/@datahub/datasets-core/types/datasets/schema.d.ts new file mode 100644 index 00000000000000..f44e5c18bfeb96 --- /dev/null +++ b/datahub-web/@datahub/datasets-core/types/datasets/schema.d.ts @@ -0,0 +1,8 @@ +import { IDatasetSchema } from '@datahub/metadata-types/types/entity/dataset/schema'; +/** + * Describes the properties on a response to a request for dataset schema + * @interface + */ +export interface IDatasetSchemaGetResponse { + schema: IDatasetSchema; +} diff --git a/datahub-web/@datahub/datasets-core/types/vendor/mirage-for-datasets.d.ts b/datahub-web/@datahub/datasets-core/types/vendor/mirage-for-datasets.d.ts index d0097e61ba7218..eab8dda00aad94 100644 --- a/datahub-web/@datahub/datasets-core/types/vendor/mirage-for-datasets.d.ts +++ b/datahub-web/@datahub/datasets-core/types/vendor/mirage-for-datasets.d.ts @@ -1,7 +1,7 @@ import { IMirageDB } from '@datahub/utils/types/vendor/ember-cli-mirage-deprecated'; import { IComplianceFieldAnnotation } from '@datahub/metadata-types/constants/entity/dataset/compliance-field-annotation'; import { IComplianceDataType } from '@datahub/metadata-types/types/entity/dataset/compliance-data-types'; -import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/scehma'; +import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/schema'; import { IDatasetComplianceInfo } from '@datahub/metadata-types/types/entity/dataset/compliance/info'; import { IDatasetExportPolicy } from '@datahub/metadata-types/types/entity/dataset/compliance/export-policy'; import { IDataPlatform } from '@datahub/metadata-types/types/entity/dataset/platform'; diff --git a/datahub-web/@datahub/metadata-types/types/entity/dataset/scehma.d.ts b/datahub-web/@datahub/metadata-types/types/entity/dataset/schema.d.ts similarity index 100% rename from datahub-web/@datahub/metadata-types/types/entity/dataset/scehma.d.ts rename to datahub-web/@datahub/metadata-types/types/entity/dataset/schema.d.ts diff --git a/datahub-web/@datahub/metadata-types/types/entity/group/group-entity.d.ts b/datahub-web/@datahub/metadata-types/types/entity/group/group-entity.d.ts new file mode 100644 index 00000000000000..0d110a1399e589 --- /dev/null +++ b/datahub-web/@datahub/metadata-types/types/entity/group/group-entity.d.ts @@ -0,0 +1,8 @@ +/** + * The expected response for the the Group entity api call from the backend. + */ +export interface ICorpGroupResponse { + name: string; + info: Com.Linkedin.Identity.CorpGroupInfo; + urn: string; +} diff --git a/datahub-web/@datahub/shared/app/templates/components/change-management/add-change-log-modal.hbs b/datahub-web/@datahub/shared/addon/components/change-management/add-change-log-modal.hbs similarity index 87% rename from datahub-web/@datahub/shared/app/templates/components/change-management/add-change-log-modal.hbs rename to datahub-web/@datahub/shared/addon/components/change-management/add-change-log-modal.hbs index bb927f4644a231..614a81130d65e6 100644 --- a/datahub-web/@datahub/shared/app/templates/components/change-management/add-change-log-modal.hbs +++ b/datahub-web/@datahub/shared/addon/components/change-management/add-change-log-modal.hbs @@ -35,10 +35,10 @@ {{#if this.isDisplayingPreviewModal}}
-

+

{{this.titleText}}

-
    +
    • Dataset Followers ({{this.emailRecipientsCount.followers}})
    • All Owners of the dataset ({{this.emailRecipientsCount.owners}})
    • Individual email recipients ({{this.emailRecipientsCount.individualRecipients}})
    • @@ -46,28 +46,19 @@
-

- Add Additional email recipients (optional) +

+ Add additional email recipients (optional)

- Add Group email distribution list + Add group email distribution lists

-
- {{#each this.distributionLists as |distributionList index|}} - - {{/each}} - -
+

- Add Individual email recipients + Add individual email recipients

= []; + /** * A Dummy component that has no significant logic around API calls or data transformation but serves * as a wrapper for providing the required search configs and params. @@ -23,7 +28,8 @@ export default class ChangeLogSearchProvider extends Component>; - // placeholder method that is called upon when user enters a query - onSearch: (query: string) => Promise; - // List of individual recipients to be displayed - individualRecipients: Array; - // placeholder method that is called when user wants to add a new recipient - addRecipient: (recipientType: string, recipientName: string) => void; - // placeholder method that is called when user wants to delete a recipient - removeRecipient: (recipientType: string, recipientName: string, index: number) => void; -} - -/** - * Properties that exist on the options that an user sees in the power select dropdown - */ -interface IRecipientOption { - fullName: string; - email: string; - username: string; -} - -/** - * Styling class for the component - */ -const baseClass = 'recipient-power-select'; - -/** - * - */ -export default class RecipientPowerSelect extends Component { - /** - * Attached to component for easier access from template. - */ - baseClass = baseClass; - - /** - * Types of recipients possible - */ - recipientType: Record = { - individualRecipient: RecipientType.IndividualRecipient, - distributionList: RecipientType.DistributionList - }; - - /** - * Flag that controls if we want to display the power select dropdown or not - */ - @tracked - showOptions = false; - - /** - * A getter that massages the `result` data from the search api into something meaningful and light that can be - * used by power-select as options. - */ - get options(): Array { - const { result } = this.args; - - const dataArray = result?.data || []; - const dataEntities: Array = dataArray.mapBy('data'); - - // Fetch the usernames - const userNames: Array = dataEntities.mapBy('entity').map(resultResponse => resultResponse.username); - // Fetch the name , email and append username to it. - - const options = dataEntities - .mapBy('entity') - .map(resultResponse => resultResponse.info) - .map((person, index) => { - return { fullName: person.fullName, email: person.email, username: userNames[index] }; - }); - return options; - } - - /** - * Triggers a search when user enters 2 letters or more in the input field. - * - * @param keyEvent HTML event from a keypress - */ - @action - onSearchLocal(keyEvent: KeyboardEvent): Promise | void { - const userInputField = keyEvent.target as HTMLInputElement; - if (userInputField && userInputField.value.length >= 2 && typeof this.args.onSearch === 'function') { - const keyword = userInputField.value; - this.showOptions = true; - return this.onSearchDebounced(keyword); - } else { - this.showOptions = false; - } - } - - onSearchDebounced(keyword: string): void { - debounce(this, this.args.onSearch, keyword, 250); - } - - /** - * Incharge of adding a recipient when the user selects an option from the list of user suggestions.a1 - * - * @param selection One of the options in the power-select dropdown - */ - @action - onChangeSelection(selection: IRecipientOption): void { - this.args.addRecipient(this.recipientType.individualRecipient, selection.username); - this.showOptions = false; - } -} diff --git a/datahub-web/@datahub/shared/addon/components/change-management/recipient-search-select.hbs b/datahub-web/@datahub/shared/addon/components/change-management/recipient-search-select.hbs new file mode 100644 index 00000000000000..31da848f93248f --- /dev/null +++ b/datahub-web/@datahub/shared/addon/components/change-management/recipient-search-select.hbs @@ -0,0 +1,54 @@ +
+ {{#if (eq recipientType 'distributionList')}} + {{#each @distributionLists as |distributionList index|}} + + {{/each}} + {{else}} + {{#each @individualRecipients as |individualRecipient index|}} + + {{/each}} + {{/if}} + +
+
+ {{#if (eq recipientType 'distributionList')}} + + {{else}} + + {{/if}} +
+
+
+ + {{if (eq recipientType 'distributionList') result.entity.name result.name}} + +
+ +
+
+
+
\ No newline at end of file diff --git a/datahub-web/@datahub/shared/addon/components/change-management/recipient-search-select.ts b/datahub-web/@datahub/shared/addon/components/change-management/recipient-search-select.ts index 06311782e8c1cc..b95f8412df87f8 100644 --- a/datahub-web/@datahub/shared/addon/components/change-management/recipient-search-select.ts +++ b/datahub-web/@datahub/shared/addon/components/change-management/recipient-search-select.ts @@ -1,20 +1,21 @@ import Component from '@glimmer/component'; -import { IEntityRenderCommonPropsSearch } from '@datahub/data-models/types/search/search-entity-render-prop'; -import { DataModelName, DataModelEntityInstance, DataModelEntity } from '@datahub/data-models/constants/entity'; +import { DataModelEntityInstance, DataModelEntity } from '@datahub/data-models/constants/entity'; import { inject as service } from '@ember/service'; import DataModelsService from '@datahub/data-models/services/data-models'; -import { alias } from '@ember/object/computed'; import { PersonEntity } from '@datahub/data-models/entity/person/person-entity'; import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; +import { RecipientType } from '@datahub/shared/constants/change-management'; +import { getResultsForEntity } from '@datahub/shared/utils/search/search-results'; +import { IDataModelEntitySearchResult } from '@datahub/data-models/types/entity/search'; +import { task, timeout } from 'ember-concurrency'; +import { ETaskPromise } from '@datahub/utils/types/concurrency'; +import { GroupEntity } from '@datahub/data-models/entity/group/group-entity'; /** * Interface for the list of the arguments being fed into the recipient-search-select component */ interface IRecipientSearchSelectArgs { - /** - * The entity which resides as a property on the `data-construct-change-management` entity under `OwningEntity` - */ - entity: DataModelEntityInstance; /** * Placeholder method that passes the action of adding a recipient back to the parent */ @@ -22,26 +23,55 @@ interface IRecipientSearchSelectArgs { /** * Placeholder method that passes the action of removing a recipient back to the parent */ - removeRecipient: (recipientType: string, recipientName: string, index: number) => void; + removeRecipient: (recipientType: string, index: number) => void; + + /** + * Optional Array of ldaps of individual recipients that are fed in from the parent + */ + individualRecipients?: Array; + + /** + * Optional Array of distributed lists / CorpGroups that are fed in from the parent + */ + distributionLists?: Array; } /** - * A Dummy component that has no significant logic around API calls or data transformation but serves - * as a wrapper for providing the required search configs and params. + * Styling class for the component + */ +const baseClass = 'recipient-search-select'; + +/** + * Time delay that the function is being debounced for + */ +const DEBOUNCE_TIME_IN_MS = 250; + +/** + * The minimum amount of characters for the user to type so that we trigger off the search and populate the recipient results + */ +const SEARCH_INPUT_MIN_LENGTH = 2; + +/** + * A component that provides an interface to allow users to search for either Individuals or Groups and add them to a collective list. + * It abstracts the searching aspect of it like providing configs , de-bouncing the input , handing the keyword. + * + * It is currently able to search for either Person entity / Group entity based on how the parent chooses to provide optional arguments. */ export default class RecipientSearchSelect extends Component { /** - * Search config being passed over to leverage existing search container + * Styling class name */ - searchConfig?: IEntityRenderCommonPropsSearch = { - attributes: [], - showFacets: false - }; + baseClass = baseClass; /** - * Number of search results we want to display in a single page. + * Debounce time provided */ - pageSize = 5; + debounceTimeInMs = DEBOUNCE_TIME_IN_MS; + + /** + * Min input length for search to trigger + */ + searchInputMinLength = SEARCH_INPUT_MIN_LENGTH; /** * The search keyword being provided to dictate what aspect of the entity we search by @@ -51,12 +81,29 @@ export default class RecipientSearchSelect extends Component | undefined | void>> { + yield timeout(this.debounceTimeInMs); + // If we are searching for a person, we want to ensure they are active in the directory + keyword = this.searchEntityType === PersonEntity ? `${keyword} AND active:true` : keyword; + const results = ((yield getResultsForEntity( + { + facetsApiParams: {}, + keyword, + page: 1, + pageSize: this.pageSize + }, + this.searchEntityType.displayName, + this.dataModels + )) as unknown) as IDataModelEntitySearchResult | undefined; + return results?.data; + }) + onSearchTask!: ETaskPromise | undefined | void, string>; } diff --git a/datahub-web/@datahub/shared/app/templates/components/change-management/view-change-log-modal.hbs b/datahub-web/@datahub/shared/addon/components/change-management/view-change-log-modal.hbs similarity index 100% rename from datahub-web/@datahub/shared/app/templates/components/change-management/view-change-log-modal.hbs rename to datahub-web/@datahub/shared/addon/components/change-management/view-change-log-modal.hbs diff --git a/datahub-web/@datahub/shared/app/templates/components/tab-content-modal.hbs b/datahub-web/@datahub/shared/addon/components/tab-content-modal.hbs similarity index 100% rename from datahub-web/@datahub/shared/app/templates/components/tab-content-modal.hbs rename to datahub-web/@datahub/shared/addon/components/tab-content-modal.hbs diff --git a/datahub-web/@datahub/shared/addon/components/top-consumers/containers/top-consumers.hbs b/datahub-web/@datahub/shared/addon/components/top-consumers/containers/top-consumers.hbs new file mode 100644 index 00000000000000..324a695981a469 --- /dev/null +++ b/datahub-web/@datahub/shared/addon/components/top-consumers/containers/top-consumers.hbs @@ -0,0 +1,11 @@ +
+ {{yield (hash + containerTask=this.getTopConsumersTask + topUserUrns=this.topUserUrns + topGroupUrns=this.topGroupUrns + topGroupLinkParams=this.topGroupLinkParams + )}} +
diff --git a/datahub-web/@datahub/shared/addon/components/top-consumers/containers/top-consumers.ts b/datahub-web/@datahub/shared/addon/components/top-consumers/containers/top-consumers.ts index 23847483c987ec..973d5afb24e438 100644 --- a/datahub-web/@datahub/shared/addon/components/top-consumers/containers/top-consumers.ts +++ b/datahub-web/@datahub/shared/addon/components/top-consumers/containers/top-consumers.ts @@ -1,41 +1,23 @@ -import Component from '@ember/component'; -// @ts-ignore: Ignore import of compiled template -import template from '../../../templates/components/top-consumers/containers/top-consumers'; -import { layout, classNames, tagName } from '@ember-decorators/component'; -import { alias, map } from '@ember/object/computed'; -import { setProperties } from '@ember/object'; -import { containerDataSource } from '@datahub/utils/api/data-source'; -import { task } from 'ember-concurrency'; +import Component from '@glimmer/component'; +import { alias, map, or } from '@ember/object/computed'; import { IDynamicLinkParams } from 'dynamic-link/components/dynamic-link'; import { DataModelName, DataModelEntityInstance } from '@datahub/data-models/constants/entity'; +import { getGridGroupFromUrn } from '@datahub/data-models/utils/get-group-from-urn'; import { PersonEntity } from '@datahub/data-models/entity/person/person-entity'; -import { ETaskPromise } from '@datahub/utils/types/concurrency'; +import { task } from 'ember-concurrency'; import { readTopConsumersForEntity } from '@datahub/shared/api/top-consumers'; -import { getGridGroupFromUrn } from '@datahub/data-models/utils/get-group-from-urn'; +import { ETaskPromise } from '@datahub/utils/types/concurrency'; +import { tracked } from '@glimmer/tracking'; /** * This container is the data source for the top consumers aspect for an entity */ -@classNames('top-consumers') -@layout(template) -@tagName('') -@containerDataSource('getTopConsumersTask', ['urn', 'entityType']) -export default class TopConsumersContainer extends Component { +export default class TopConsumersContainer extends Component<{ /** * An external entity that gives context to this container for fetching the appropriate top consumers insight */ entity?: DataModelEntityInstance; - - /** - * A list of people urns for the top users that consume the entity - */ - topUserUrns: Array = []; - - /** - * A list of group urns for the top groups that consume the entity - */ - topGroupUrns: Array = []; - +}> { /** * The prefix for grid group primary entity page * TODO META-11471: Refactor top consumers for internal vs external compatibility @@ -45,15 +27,49 @@ export default class TopConsumersContainer extends Component { /** * The urn of the context entity for top consumers */ - @alias('entity.urn') + @alias('args.entity.urn') urn = ''; /** * The entity type of the context entity for top consumers */ - @alias('entity.displayName') + @alias('args.entity.displayName') entityType?: DataModelName; + /** + * The aspect of the entity that it is passed in + */ + @alias('args.entity.entity.entityTopUsage') + aspectEntityTopUsage?: Com.Linkedin.Common.EntityTopUsage; + + /** + * The entityTopUsage fetched from the api (if available) + */ + @tracked + apiEntityTopUsage?: Com.Linkedin.Common.EntityTopUsage; + + /** + * Checks if the aspect is defined, otherwise use the api response + * + */ + @or('aspectEntityTopUsage', 'apiEntityTopUsage') + entityTopUsage?: Com.Linkedin.Common.EntityTopUsage; + + /** + * URNs of top users + */ + @map('entityTopUsage.mostFrequentUsers', (user): string => user.identity.corpUser || '') + topUserUrns?: Array; + + /** + * URNs of top groups + */ + @map( + 'entityTopUsage.mostFrequentGroups', + (group): string => group.identity.gridGroup || group.identity.corpGroup || '' + ) + topGroupUrns?: Array; + /** * A map of link params that opens a new tab to the top group's entity page * The top consumers insight consumes this to render links for users to go to a top group's primary entity page (not on DataHub) @@ -68,36 +84,20 @@ export default class TopConsumersContainer extends Component { topGroupLinkParams!: Array; /** - * The task used to fetch the top consumers aspect and provides context to the container + * The task used to fetch the top consumers aspect and provides context to the container. + * The container will only fetch if the aspect is not defined */ @task(function*( this: TopConsumersContainer ): IterableIterator | Promise>> { const { entityType, urn } = this; + if (entityType && urn && !this.aspectEntityTopUsage) { + const entityTopUsage = ((yield readTopConsumersForEntity( + entityType, + urn + )) as unknown) as Com.Linkedin.Common.EntityTopUsage; - let topUserUrns: Array = []; - let topGroupUrns: Array = []; - - if (entityType && urn) { - try { - const { mostFrequentUsers, mostFrequentGroups } = ((yield readTopConsumersForEntity( - entityType, - urn - )) as unknown) as Com.Linkedin.Common.EntityTopUsage; - - topUserUrns = mostFrequentUsers.map((user): string => (user.identity as { corpUser?: string }).corpUser || ''); - topGroupUrns = mostFrequentGroups.map( - (group): string => - (group.identity as { gridGroup?: string }).gridGroup || - (group.identity as { corpGroup?: string }).corpGroup || - '' - ); - } finally { - setProperties(this, { - topUserUrns, - topGroupUrns - }); - } + this.apiEntityTopUsage = entityTopUsage; } }) getTopConsumersTask!: ETaskPromise; diff --git a/datahub-web/@datahub/shared/app/templates/components/top-consumers/insight/insight-card.hbs b/datahub-web/@datahub/shared/addon/components/top-consumers/insight/insight-card.hbs similarity index 100% rename from datahub-web/@datahub/shared/app/templates/components/top-consumers/insight/insight-card.hbs rename to datahub-web/@datahub/shared/addon/components/top-consumers/insight/insight-card.hbs diff --git a/datahub-web/@datahub/shared/app/templates/components/top-consumers/insight/insight-strip.hbs b/datahub-web/@datahub/shared/addon/components/top-consumers/insight/insight-strip.hbs similarity index 100% rename from datahub-web/@datahub/shared/app/templates/components/top-consumers/insight/insight-strip.hbs rename to datahub-web/@datahub/shared/addon/components/top-consumers/insight/insight-strip.hbs diff --git a/datahub-web/@datahub/shared/app/templates/components/top-consumers/insight/top-consumers-insight.hbs b/datahub-web/@datahub/shared/addon/components/top-consumers/insight/top-consumers-insight.hbs similarity index 100% rename from datahub-web/@datahub/shared/app/templates/components/top-consumers/insight/top-consumers-insight.hbs rename to datahub-web/@datahub/shared/addon/components/top-consumers/insight/top-consumers-insight.hbs diff --git a/datahub-web/@datahub/shared/addon/mirage-addon/test-helpers/urn.ts b/datahub-web/@datahub/shared/addon/mirage-addon/test-helpers/urn.ts new file mode 100644 index 00000000000000..8f45befeaaca8f --- /dev/null +++ b/datahub-web/@datahub/shared/addon/mirage-addon/test-helpers/urn.ts @@ -0,0 +1,28 @@ +import { decodeUrn } from '@datahub/utils/validators/urn'; + +const urn = 'urn:li:dataset:(urn:li:dataPlatform:hdfs,%2Fseg1s%2Fseg2%2Fseg3%2Fseg4%2Fdataset-node,PROD)'; +const nonHdfsUrn = 'urn:li:dataset:(urn:li:dataPlatform:db,ABOOK.ABOOK_DATA,PROD)'; +const hdfsUrn = decodeUrn(urn); + +const whUrnToLiUrnMap = [ + ['espresso:///ETLInfra/AllTables', 'urn:li:dataset:(urn:li:dataPlatform:espresso,ETLInfra.AllTables,PROD)'], + [ + 'hdfs:///seg1/seg2/seg3/data/kebab-db-name', + 'urn:li:dataset:(urn:li:dataPlatform:hdfs,/seg1/seg2/seg3/data/kebab-db-name,PROD)' + ], + [ + 'hdfs:///seg1/seg2/data/UpperCaseDbName', + 'urn:li:dataset:(urn:li:dataPlatform:hdfs,/seg1/seg2/data/UpperCaseDbName,PROD)' + ], + ['oracle:///ABOOK/ABOOK_DATA', 'urn:li:dataset:(urn:li:dataPlatform:oracle,ABOOK.ABOOK_DATA,PROD)'] +]; + +const liUrns = [ + 'urn:li:dataset:(urn:li:dataPlatform:oracle,ABOOK.ABOOK_EMAILS,PROD)', + 'urn:li:dataset:(urn:li:dataPlatform:gibberish,gibberish.gibberish,PROD)', + 'urn:li:dataset:(urn:li:dataPlatform:hdfs,/gibberish/gibberish/gIbberish/gibberish/gibberish-gibberish-gibberish,PROD)', + 'urn:li:dataset:(urn:li:dataPlatform:gibberish,GIBBERISH.GIBBERISH_GIBBERISH,PROD)', + 'urn:li:dataset:(urn:li:dataPlatform:gibberish-gibberish,GIBBERISH.gibberish-gibberish-com.gibberish.gibberish.gibberish.Windows-gibberish,PROD)' +]; + +export { urn, whUrnToLiUrnMap, hdfsUrn, nonHdfsUrn, liUrns }; diff --git a/datahub-web/@datahub/shared/addon/services/current-user.ts b/datahub-web/@datahub/shared/addon/services/current-user.ts index 4a8d2ea9b8ed0f..d0fcf9e097f51a 100644 --- a/datahub-web/@datahub/shared/addon/services/current-user.ts +++ b/datahub-web/@datahub/shared/addon/services/current-user.ts @@ -55,7 +55,7 @@ export default class CurrentUser extends Service { const userV1: IUser = await currentUserDeprecated(); const PersonEntityClass = dataModels.getModel(PersonEntity.displayName); const urn = PersonEntityClass.urnFromUsername(userV1.userName); - const entity = await dataModels.createInstance(PersonEntityClass.displayName, urn); + const entity = dataModels.createPartialInstance(PersonEntityClass.displayName, { ...userV1, urn }); set(this, 'entity', entity); } diff --git a/datahub-web/@datahub/shared/addon/services/unified-tracking.ts b/datahub-web/@datahub/shared/addon/services/unified-tracking.ts index 18907c1a614b9a..0a639f11664194 100644 --- a/datahub-web/@datahub/shared/addon/services/unified-tracking.ts +++ b/datahub-web/@datahub/shared/addon/services/unified-tracking.ts @@ -182,7 +182,9 @@ export default class UnifiedTracking extends Service { this.router.on('routeDidChange', ({ to }: Transition): void => { const { router, metrics } = this; // Fetch the URL from the router and store it as an identifier - const page: string = router.currentURL; + // Note: We need to append the hash '#' here as this isn't included in our tracking adapter but we need this hash + // to provide accurate information about the page since the Ember app uses it + const page: string = '/#' + router.currentURL; // fallback to page value if a resolution cannot be determined, e.g when to / from is null const title: string = resolveDynamicRouteName(mapOfRouteNamesToResolver, to) || page || ''; diff --git a/datahub-web/@datahub/shared/addon/templates/components/top-consumers/containers/top-consumers.hbs b/datahub-web/@datahub/shared/addon/templates/components/top-consumers/containers/top-consumers.hbs deleted file mode 100644 index 828e2b325d783d..00000000000000 --- a/datahub-web/@datahub/shared/addon/templates/components/top-consumers/containers/top-consumers.hbs +++ /dev/null @@ -1,6 +0,0 @@ -{{yield (hash - containerTask=this.getTopConsumersTask - topUserUrns=this.topUserUrns - topGroupUrns=this.topGroupUrns - topGroupLinkParams=this.topGroupLinkParams -)}} diff --git a/datahub-web/@datahub/shared/addon/utils/search/search-results.ts b/datahub-web/@datahub/shared/addon/utils/search/search-results.ts index 0f2ea1802b21e4..019b5345b04763 100644 --- a/datahub-web/@datahub/shared/addon/utils/search/search-results.ts +++ b/datahub-web/@datahub/shared/addon/utils/search/search-results.ts @@ -6,6 +6,10 @@ import { import { IFacetCounts, IFacetsCounts } from '@datahub/data-models/types/entity/facets'; import { IAggregationMetadata } from '@datahub/shared/types/search/entity'; import { DataModelEntity } from '@datahub/data-models/constants/entity'; +import { DataModelEntityInstance, DataModelName } from '@datahub/data-models/constants/entity'; +import { ISearchEntityApiParams, IEntitySearchResult } from '@datahub/shared/types/search/entity'; +import { readSearchV2 } from '@datahub/shared/utils/search/search'; +import DataModelsService from '@datahub/data-models/services/data-models'; /** * Computes the search result item's index within the full list of results @@ -118,3 +122,62 @@ export const searchResultMetasToFacetCounts = ( ); return mergeFacetCountsWithSelections(facetCounts, previousSelections); }; + +/** + * Param type for making the `getResultsForEntity` call. + */ +export interface ISearchParams { + keyword: string; + page: number; + facetsApiParams: Record>; + pageSize: number; + aspects?: Array; +} + +/** + * Will perform a search for any type of entity (except datasets at the moment) + */ +export async function getResultsForEntity( + params: ISearchParams, + entity: DataModelName, + dataModels: DataModelsService +): Promise | undefined> { + const { keyword, page = 1, facetsApiParams, pageSize, aspects } = params; + const searchApiParams: ISearchEntityApiParams = { + facets: facetsApiParams, + input: keyword, + type: dataModels.getModel(entity).renderProps.apiEntityName, + start: (page - 1) * pageSize, + count: pageSize, + aspects + }; + + const searchResultProxy: IEntitySearchResult = await readSearchV2< + DataModelEntityInstance['entity'] + >(searchApiParams); + const { elements } = searchResultProxy; + + if (elements) { + const { start, count, total } = searchResultProxy; + const itemsPerPage = count; + const totalPages = Math.ceil(total / itemsPerPage); + const page = Math.ceil((start + 1) / itemsPerPage); + const data = elements.map( + (entityData): DataModelEntityInstance => dataModels.createPartialInstance(entity, entityData) + ); + + const entitySearchResult = { + data, + count: total, + start, + itemsPerPage, + page, + totalPages, + facets: searchResultMetasToFacetCounts(searchResultProxy.searchResultMetadatas, facetsApiParams) + }; + + return entitySearchResult; + } + + return; +} diff --git a/datahub-web/packages/data-portal/app/utils/api/search/search.ts b/datahub-web/@datahub/shared/addon/utils/search/search.ts similarity index 100% rename from datahub-web/packages/data-portal/app/utils/api/search/search.ts rename to datahub-web/@datahub/shared/addon/utils/search/search.ts diff --git a/datahub-web/packages/data-portal/app/utils/api/search/values-v2.ts b/datahub-web/@datahub/shared/addon/utils/search/values-v2.ts similarity index 86% rename from datahub-web/packages/data-portal/app/utils/api/search/values-v2.ts rename to datahub-web/@datahub/shared/addon/utils/search/values-v2.ts index 35c1788f1c2363..559a8d949430a7 100644 --- a/datahub-web/packages/data-portal/app/utils/api/search/values-v2.ts +++ b/datahub-web/@datahub/shared/addon/utils/search/values-v2.ts @@ -1,5 +1,5 @@ import { getJSON } from '@datahub/utils/api/fetcher'; -import { FieldValuesRequestV2, IFieldValuesResponseV2 } from 'datahub-web/typings/app/search/fields-v2'; +import { FieldValuesRequestV2, IFieldValuesResponseV2 } from '@datahub/shared/types/search/fields-v2'; import { getApiRoot, ApiVersion } from '@datahub/utils/api/shared'; import buildUrl from '@datahub/utils/api/build-url'; diff --git a/datahub-web/@datahub/shared/app/components/change-management/recipient-power-select.js b/datahub-web/@datahub/shared/app/components/change-management/recipient-power-select.js deleted file mode 100644 index 73dab06a4f0463..00000000000000 --- a/datahub-web/@datahub/shared/app/components/change-management/recipient-power-select.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@datahub/shared/components/change-management/recipient-power-select'; diff --git a/datahub-web/@datahub/shared/app/styles/change-management/_add-change-log-modal.scss b/datahub-web/@datahub/shared/app/styles/change-management/_add-change-log-modal.scss index 2804792fde585e..2d11e45eda8276 100644 --- a/datahub-web/@datahub/shared/app/styles/change-management/_add-change-log-modal.scss +++ b/datahub-web/@datahub/shared/app/styles/change-management/_add-change-log-modal.scss @@ -37,6 +37,7 @@ display: flex; overflow-y: auto; overflow-x: hidden; + padding-top: item-spacing(2); } &__content-preview &__subject { @@ -54,33 +55,44 @@ &__preview-markdown-icon { margin-right: item-spacing(2); - width: 16px; + width: item-spacing(4); } &__label { margin-bottom: item-spacing(1); } - &__list, - &__label, + &__list { + font-weight: fw(normal, 4); + } + + &__label { + font-weight: fw(normal, 4); + margin-bottom: item-spacing(1); + } + &__title { font-weight: fw(normal, 6); } - &__label-bold { + &__label--bold { font-weight: fw(normal, 7); font-size: fs(standard); + margin-bottom: item-spacing(2); } &__item { display: flex; flex-direction: column; width: $add-change-log-modal-item-width; + margin-bottom: item-spacing(2); + margin-top: item-spacing(4); } &__list { padding-left: 18px; } + &__text-input { padding: item-spacing(1 2 1 2); border: 1px solid get-color(black, 0.75); @@ -114,16 +126,11 @@ } &__tag-input { - border-radius: 2px; - border: 1px solid get-color(black, 0.6); - padding: item-spacing(2); - display: flex; - flex-wrap: wrap; - margin-bottom: item-spacing(1); + @include change-management-tag-input; } &__pill { - margin: item-spacing(1 1 0 0); + @include change-management-pill; } &__action { diff --git a/datahub-web/@datahub/shared/app/styles/change-management/_all.scss b/datahub-web/@datahub/shared/app/styles/change-management/_all.scss index 0c78aa2a603369..2c5b12a563fe6f 100644 --- a/datahub-web/@datahub/shared/app/styles/change-management/_all.scss +++ b/datahub-web/@datahub/shared/app/styles/change-management/_all.scss @@ -1,6 +1,7 @@ +@import 'common'; @import 'change-log-table'; @import 'add-change-log-modal'; @import 'view-change-log-modal'; @import 'read-only-email-content'; @import 'markdown-cheat-sheet'; -@import 'recipient-power-select'; +@import 'recipient-search-select'; diff --git a/datahub-web/@datahub/shared/app/styles/change-management/_common.scss b/datahub-web/@datahub/shared/app/styles/change-management/_common.scss new file mode 100644 index 00000000000000..7ab90bf3e6d6ef --- /dev/null +++ b/datahub-web/@datahub/shared/app/styles/change-management/_common.scss @@ -0,0 +1,14 @@ +@mixin change-management-tag-input { + border-radius: 2px; + border: 1px solid get-color(gray3); + padding: item-spacing(1); + display: flex; + flex-wrap: wrap; + margin-bottom: item-spacing(4); + line-height: 38px; +} + +@mixin change-management-pill { + margin: item-spacing(1 1 1 0); + min-height: 30px; +} diff --git a/datahub-web/@datahub/shared/app/styles/change-management/_recipient-power-select.scss b/datahub-web/@datahub/shared/app/styles/change-management/_recipient-power-select.scss deleted file mode 100644 index 8dd0e0b403363f..00000000000000 --- a/datahub-web/@datahub/shared/app/styles/change-management/_recipient-power-select.scss +++ /dev/null @@ -1,66 +0,0 @@ -.recipient-power-select { - &__tag-input { - border-radius: 2px; - border: 1px solid get-color(black, 0.6); - padding: item-spacing(2); - display: flex; - flex-wrap: wrap; - margin-bottom: item-spacing(1); - } - - &__pill { - margin: item-spacing(1 1 0 0); - max-height: 30px; - } - - &__trigger { - display: none; - } - - &__suggestions-list { - list-style: none; - padding: 0px; - margin-top: item-spacing(1); - position: absolute; - background-color: get-color(white); - box-shadow: 0px -1px 1px get-color(black, 0.1), 1px 0px 1px get-color(black, 0.1), 0px 1px 1px get-color(black, 0.1), - -1px 0px 1px get-color(black, 0.1), 0px 6px 9px get-color(black, 0.2); - } - - &__suggestions-list-item { - display: flex; - border: none; - background-color: get-color(white); - width: 100%; - align-items: center; - padding: item-spacing(1); - } - - &__suggestions-list-item:hover { - background-color: get-color(slate0); - cursor: pointer; - } - - &__suggestions-list-item > div { - margin: item-spacing(1); - } - &__suggestions-list-item-detail { - display: flex; - text-align: left; - flex-direction: column; - } - - &__suggestions-list &__icon { - height: item-spacing(5); - width: item-spacing(5); - } - - &__suggestions-list-item-detail-email { - color: get-color(black, 0.6); - } - - &__icon-container { - display: flex; - align-items: center; - } -} diff --git a/datahub-web/@datahub/shared/app/styles/change-management/_recipient-search-select.scss b/datahub-web/@datahub/shared/app/styles/change-management/_recipient-search-select.scss new file mode 100644 index 00000000000000..4e05e96671fde7 --- /dev/null +++ b/datahub-web/@datahub/shared/app/styles/change-management/_recipient-search-select.scss @@ -0,0 +1,44 @@ +.recipient-search-select { + &__tag-input { + @include change-management-tag-input; + } + + &__pill { + @include change-management-pill; + } + + &__suggestions-list-item { + display: flex; + border: none; + width: 100%; + align-items: center; + padding: item-spacing(2 0); + } + + &__suggestions-list-item-detail { + display: flex; + text-align: left; + flex-direction: column; + width: 100%; + } + + &__icon { + flex-shrink: 0; + &#{&}#{&} { + height: item-spacing(6); + width: item-spacing(6); + border: none; + } + } + + &__suggestions-list-item-detail-email { + color: get-color(black, 0.6); + } + + &__icon-container { + display: flex; + flex-shrink: 0; + align-items: center; + margin-right: item-spacing(2); + } +} diff --git a/datahub-web/@datahub/shared/app/templates/components/change-management/recipient-power-select.hbs b/datahub-web/@datahub/shared/app/templates/components/change-management/recipient-power-select.hbs deleted file mode 100644 index 8e76445912d186..00000000000000 --- a/datahub-web/@datahub/shared/app/templates/components/change-management/recipient-power-select.hbs +++ /dev/null @@ -1,48 +0,0 @@ -
- {{#each @individualRecipients as |individualRecipient index|}} - - {{/each}} -
- - {{#if (and this.showOptions (gt this.options.length 0))}} -
    - {{#each this.options as |option|}} -
  • - -
  • - {{/each}} -
- {{/if}} -
-
diff --git a/datahub-web/@datahub/shared/app/templates/components/change-management/recipient-search-select.hbs b/datahub-web/@datahub/shared/app/templates/components/change-management/recipient-search-select.hbs deleted file mode 100644 index 9503fb676ce0c8..00000000000000 --- a/datahub-web/@datahub/shared/app/templates/components/change-management/recipient-search-select.hbs +++ /dev/null @@ -1,16 +0,0 @@ - - - \ No newline at end of file diff --git a/datahub-web/@datahub/shared/package.json b/datahub-web/@datahub/shared/package.json index 24d4f59b8c0776..1292e219eaa78b 100644 --- a/datahub-web/@datahub/shared/package.json +++ b/datahub-web/@datahub/shared/package.json @@ -71,6 +71,7 @@ "eyeglass-restyle": "^1.1.0", "ivy-tabs": "^3.3.0", "minimatch": "^3.0.4", + "restliparams": "^1.0.1", "sass": "^1.21.0", "svg-pan-zoom": "^3.6.1", "faker": "^4.1.0" diff --git a/datahub-web/@datahub/shared/tests/integration/components/change-management/add-change-log-modal-test.ts b/datahub-web/@datahub/shared/tests/integration/components/change-management/add-change-log-modal-test.ts index 5cdfb7ad91afe6..4b116d6e466b64 100644 --- a/datahub-web/@datahub/shared/tests/integration/components/change-management/add-change-log-modal-test.ts +++ b/datahub-web/@datahub/shared/tests/integration/components/change-management/add-change-log-modal-test.ts @@ -73,20 +73,25 @@ module('Integration | Component | change-management/add-change-log-modal', funct const actions = findAll(`.${baseModalClass}__action`); assert.dom(actions[1]).hasText('Continue to send email', 'button text is rendered as expected'); await click(actions[1]); - + // Focus pill await click('.nacho-pill-input:nth-child(1)'); - await fillIn('.nacho-pill-input__input:nth-child(1)', 'testGroup1'); - await triggerKeyEvent('.nacho-pill-input__input:nth-child(1)', 'keyup', 13); + const nachoPillInputs = findAll('.nacho-pill-input__input'); + // Fill input with data + await fillIn(findAll('.ember-power-select-search-input')[0], 'testGroup1'); + // Hit tab / enter + await triggerKeyEvent(nachoPillInputs[0], 'keyup', 13); // Add a new individual recipient - await click(findAll('.nacho-pill-input')[2]); - await click(findAll('.nacho-pill-input__input')[0]); - await fillIn('.nacho-pill-input__input:nth-child(1)', 'testIndividualLDAP1'); - await triggerKeyEvent('.nacho-pill-input__input:nth-child(1)', 'keyup', 13); + await click(findAll('.nacho-pill-input')[1]); + await fillIn(findAll('.ember-power-select-search-input')[0], 'testIndividualLDAP1'); + await triggerKeyEvent(findAll('.ember-power-select-search-input')[0], 'keyup', 13); assert .dom(find(`.${baseModalClass}__content`)) - .includesText('Sending Email to 5 individuals and 1 group(s)', 'Title text is displayed correctly'); + .includesText( + 'Sending Email to 4 individuals', + 'User is able to enter input for searching and Title text is displayed correctly' + ); assert .dom(find(`.${baseModalClass}__content`)) @@ -94,13 +99,13 @@ module('Integration | Component | change-management/add-change-log-modal', funct assert .dom(find(`.${baseModalClass}__content`)) .includesText( - 'Group email distribution list (1)', + 'Group email distribution list (0)', 'Distribution lists are included in prompt with the right count' ); assert .dom(find(`.${baseModalClass}__content`)) .includesText( - 'Individual email recipients (1)', + 'Individual email recipients (0)', 'Individual recipients are included in prompt with the right count' ); }); diff --git a/datahub-web/@datahub/shared/tests/integration/components/dynamic-components/entity/field-test.ts b/datahub-web/@datahub/shared/tests/integration/components/dynamic-components/entity/field-test.ts index 5960f5a9069c23..2702b1097e6649 100644 --- a/datahub-web/@datahub/shared/tests/integration/components/dynamic-components/entity/field-test.ts +++ b/datahub-web/@datahub/shared/tests/integration/components/dynamic-components/entity/field-test.ts @@ -8,7 +8,9 @@ module('Integration | Component | dynamic-components/entity/field', function(hoo setupRenderingTest(hooks); test('it renders', async function(assert) { - const fakeSeedInformation = { description: `Pikachu's special dataset` }; + const fakeSeedInformation = { + description: `Pikachu's special dataset` + }; const testUnderlyingDataset = new DatasetEntity( 'pikachu', (fakeSeedInformation as unknown) as Com.Linkedin.Dataset.Dataset diff --git a/datahub-web/@datahub/shared/tests/integration/components/entity-page/entity-page-main-test.ts b/datahub-web/@datahub/shared/tests/integration/components/entity-page/entity-page-main-test.ts index 02a392a942961f..08db678de2a6c4 100644 --- a/datahub-web/@datahub/shared/tests/integration/components/entity-page/entity-page-main-test.ts +++ b/datahub-web/@datahub/shared/tests/integration/components/entity-page/entity-page-main-test.ts @@ -29,7 +29,8 @@ const setupTest = async function( search: { attributes: [], autocompleteNameField: '', - placeholder: '' + placeholder: '', + defaultAspects: [] } }; if (options.withBrowsePage) { diff --git a/datahub-web/@datahub/shared/tests/integration/components/top-consumers/containers/top-consumers-test.ts b/datahub-web/@datahub/shared/tests/integration/components/top-consumers/containers/top-consumers-test.ts index 40541e4a2094c5..1283889ec4b29f 100644 --- a/datahub-web/@datahub/shared/tests/integration/components/top-consumers/containers/top-consumers-test.ts +++ b/datahub-web/@datahub/shared/tests/integration/components/top-consumers/containers/top-consumers-test.ts @@ -27,12 +27,12 @@ module('Integration | Component | top-consumers/containers/top-consumers', funct }); assert.notEqual( - topConsumersContainer.topUserUrns.length, + topConsumersContainer.topUserUrns?.length, 0, 'Expects container to have the correct number of top users urns' ); assert.notEqual( - topConsumersContainer.topGroupUrns.length, + topConsumersContainer.topGroupUrns?.length, 0, 'Expects container to have the correct number of top group urns' ); diff --git a/datahub-web/@datahub/shared/types/search/entity.d.ts b/datahub-web/@datahub/shared/types/search/entity.d.ts index 5ef92f05598746..74cc108d60c92b 100644 --- a/datahub-web/@datahub/shared/types/search/entity.d.ts +++ b/datahub-web/@datahub/shared/types/search/entity.d.ts @@ -26,6 +26,8 @@ export interface ISearchEntityApiParams { count?: number; // Facet params expected facets: Record>; + // Aspects that we need to fetch for the entity type + aspects?: Array; } /** diff --git a/datahub-web/packages/data-portal/app/typings/app/search/fields-v2.d.ts b/datahub-web/@datahub/shared/types/search/fields-v2.d.ts similarity index 100% rename from datahub-web/packages/data-portal/app/typings/app/search/fields-v2.d.ts rename to datahub-web/@datahub/shared/types/search/fields-v2.d.ts diff --git a/datahub-web/@datahub/utils/addon/components/radio-button-composer.ts b/datahub-web/@datahub/utils/addon/components/radio-button-composer.ts index 42cd531d6e5529..358a20c9570cc6 100644 --- a/datahub-web/@datahub/utils/addon/components/radio-button-composer.ts +++ b/datahub-web/@datahub/utils/addon/components/radio-button-composer.ts @@ -38,7 +38,7 @@ export default class RadioButtonComposer extends RadioButton { return this.checked ? this.checkedClass : ''; } - didReceiveAttrs() { + didReceiveAttrs(): void { super.didReceiveAttrs(); // ensures that the values a supplied at the component call site @@ -49,11 +49,24 @@ export default class RadioButtonComposer extends RadioButton { }); } + didInsertElement(): void { + super.didInsertElement(); + this.element.addEventListener('mouseenter', this.handleMouseEnter); + this.element.addEventListener('mouseleave', this.handleMouseLeave); + } + + willDestroyElement(): void { + super.willDestroyElement(); + this.element.removeEventListener('mouseenter', this.handleMouseEnter); + this.element.removeEventListener('mouseleave', this.handleMouseLeave); + } + /** * Handles the mouseenter event on the component element and invokes * the external action if provided as an attribute */ - mouseEnter() { + @action + handleMouseEnter(): void { const { onMouseEnter, value } = this; if (typeof onMouseEnter === 'function') { onMouseEnter({ value }); @@ -64,7 +77,8 @@ export default class RadioButtonComposer extends RadioButton { * Handles the mouseleave event on the component element and invokes * the external action if provided as an attribute */ - mouseLeave() { + @action + handleMouseLeave(): void { const { onMouseLeave, value } = this; if (typeof onMouseLeave === 'function') { onMouseLeave({ value }); @@ -77,7 +91,7 @@ export default class RadioButtonComposer extends RadioButton { * if an onclick handler is provided it will be invoked * @memberof RadioButtonComposer */ - click() { + click(): void { const { onclick, value } = this; typeof onclick === 'function' && onclick({ value }); diff --git a/datahub-web/@datahub/utils/addon/templates/components/concurrency-task-state-handler.hbs b/datahub-web/@datahub/utils/addon/templates/components/concurrency-task-state-handler.hbs index 7a1d53cbf83c74..79546bfe7a2c47 100644 --- a/datahub-web/@datahub/utils/addon/templates/components/concurrency-task-state-handler.hbs +++ b/datahub-web/@datahub/utils/addon/templates/components/concurrency-task-state-handler.hbs @@ -8,7 +8,6 @@ {{/if}} {{else}} {{#if @task.last.isError}} - {{#let (or @errorHeading "An error occurred. Please try again shortly.") as |errorMessage|}} {{! Show entity lockup if toggled on, otherwise yield error. This allows this component to be used in interfaces where rendering the lockup is not suitable, for example in a button diff --git a/datahub-web/@datahub/utils/addon/types/vendor/ember-cli-mirage/index.d.ts b/datahub-web/@datahub/utils/addon/types/vendor/ember-cli-mirage/index.d.ts index a2cbcbeb1f90ac..191e2a9eccd18d 100644 --- a/datahub-web/@datahub/utils/addon/types/vendor/ember-cli-mirage/index.d.ts +++ b/datahub-web/@datahub/utils/addon/types/vendor/ember-cli-mirage/index.d.ts @@ -148,10 +148,11 @@ declare module 'ember-cli-mirage' { export interface HandlerContext { request: Request; - serialize( - modelOrCollection: Collection | ModelInstance | Array | ModelClass, + serialize(modelOrCollection: ModelInstance | ModelClass, serializerName?: string): T; + serialize( + modelOrCollection: DatabaseCollection | Array> | Collection, serializerName?: string - ): unknown; + ): Array; normalizedRequestAttrs(model: M): NormalizedRequestAttrs; } diff --git a/datahub-web/@datahub/utils/tests/integration/components/radio-button-composer-test.ts b/datahub-web/@datahub/utils/tests/integration/components/radio-button-composer-test.ts index c55e77580aea5b..d88ada617125a8 100644 --- a/datahub-web/@datahub/utils/tests/integration/components/radio-button-composer-test.ts +++ b/datahub-web/@datahub/utils/tests/integration/components/radio-button-composer-test.ts @@ -16,30 +16,32 @@ module('Integration | Component | radio-button-composer', function(hooks): void assert.ok(true, 'Function got called on mouseEnter'); } }); - await render(hbs`{{#radio-button-composer - disabledClass=disabledClass - name="testA" - groupValue="groupA" - value=value - onMouseEnter=mouseEnter}} - {{value}} - {{/radio-button-composer}}`); + await render(hbs` + {{value}} + `); // Ensures the function assert was called. - assert.expect(4); + assert.expect(5); assert.equal(this.element.textContent?.trim(), 'electrify', 'renders expected value'); assert.equal(findAll(`.${disabledClass}`).length, 0, 'Does not disable when not supposed to'); - await triggerEvent('span', 'mouseover'); + await triggerEvent('span', 'mouseenter'); - await render(hbs`{{radio-button-composer - disabledClass=disabledClass - name="testB" - groupValue="groupB" - value=value - onMouseEnter=mouseEnter - disabled=true}}`); + await render(hbs``); assert.equal(findAll(`.${disabledClass}`).length, 1, 'Renders the disabled class'); + await triggerEvent('span', 'mouseenter'); }); }); diff --git a/datahub-web/@nacho-ui/nacho-pill/addon/components/nacho-pill-input.ts b/datahub-web/@nacho-ui/nacho-pill/addon/components/nacho-pill-input.ts index 46083d25911a72..0f7168442daa40 100644 --- a/datahub-web/@nacho-ui/nacho-pill/addon/components/nacho-pill-input.ts +++ b/datahub-web/@nacho-ui/nacho-pill/addon/components/nacho-pill-input.ts @@ -18,11 +18,13 @@ export const baseInputPillClass = 'nacho-pill-input'; * - While in editing mode, pressing the tab key will create a new tag and also leave us in * editing mode still to quickly add more tags * - While in editing mode, clicking away will cause the input pill to reset + * - If typeahead is enabled then upon searching a dropdown will surface with the suggestions * * Refer to dummy application component for suggested use of this component * @example * extends BasePillComponent { /** * Inclusion in component for easy access in the template */ @@ -54,12 +56,17 @@ export default class NachoPillInput extends BasePillComponent { */ value?: string; + /** + * Whether or not we want to use nacho-pill-input as an input for a typeahead dropdown + */ + isTypeahead = false; + /** * This is expected to be updated based on the user's input into the pill during editing mode. * We don't connect it directly to the value parameter because we don't necessarily know if * it will connect to any property directly. */ - tagValue = ''; + tagValue?: T; /** * Expected to be passed in, or will get a default value in the constructor, determines the @@ -80,7 +87,7 @@ export default class NachoPillInput extends BasePillComponent { * Ultimately, this confirms their choice to finalize their pill entry and add the typed in value * to somelist */ - onComplete: (value: string) => void = noop; + onComplete: (value: string | T) => void = noop; /** * External action, meant to handle a user action expressing desire to delete the value @@ -107,7 +114,7 @@ export default class NachoPillInput extends BasePillComponent { createPillAndReset(): void { if (this.tagValue) { this.onComplete(this.tagValue); - set(this, 'tagValue', ''); + set(this, 'tagValue', undefined); } } @@ -157,7 +164,22 @@ export default class NachoPillInput extends BasePillComponent { // If focusOut does not stem from a sibling button then reset tagValue , else ignore and let secondaryTargetHandler take over the event propagation if (isTargetValid && !isChildPresent) { - setProperties(this, { tagValue: '', isEditing: false }); + setProperties(this, { tagValue: undefined, isEditing: false }); + } + } + + /** + * Handler method for the PowerSelectTypeahead component, which dictates how we handle NachoPillInput when user focuses out. + */ + @action + onBlur(_dd: unknown | undefined, event: MouseEvent | undefined): void { + // a secondary mouse event if any that happened alongside the focusOut. Eg : "onClick" + const secondaryTarget = event?.relatedTarget as Node | undefined; + + // When clicked in a dropdown option, secondary target is null. We just want to take action when the + // secondary target is defined and it is outside ourselves + if (secondaryTarget && !this.element.contains(secondaryTarget)) { + setProperties(this, { tagValue: undefined, isEditing: false }); } } @@ -166,8 +188,11 @@ export default class NachoPillInput extends BasePillComponent { * tag they've created to whatever list provided the context for this pill and its siblings */ @action - userConfirmedEntry(): void { + userConfirmedEntry(selectedEntry: T): void { set(this, 'isEditing', false); + if (selectedEntry) { + set(this, 'tagValue', selectedEntry); + } this.createPillAndReset(); } diff --git a/datahub-web/@nacho-ui/nacho-pill/addon/templates/components/nacho-pill-input.hbs b/datahub-web/@nacho-ui/nacho-pill/addon/templates/components/nacho-pill-input.hbs index f3ba894cfff39f..ca38b68da7333f 100644 --- a/datahub-web/@nacho-ui/nacho-pill/addon/templates/components/nacho-pill-input.hbs +++ b/datahub-web/@nacho-ui/nacho-pill/addon/templates/components/nacho-pill-input.hbs @@ -1,19 +1,38 @@ {{#if this.isEditing}} - - + + {{#if this.isTypeahead}} + + {{yield option}} + + {{else}} + + + + {{/if}} + {{else}} {{!-- Tag has value and should be a basic display --}} {{#if @value}} @@ -38,4 +57,3 @@ {{/if}} {{/if}} -{{yield}} diff --git a/datahub-web/@nacho-ui/nacho-pill/app/styles/nacho-pill-styles/_pill-input.scss b/datahub-web/@nacho-ui/nacho-pill/app/styles/nacho-pill-styles/_pill-input.scss index 27dfcda51ea297..7f15387bbb86e6 100644 --- a/datahub-web/@nacho-ui/nacho-pill/app/styles/nacho-pill-styles/_pill-input.scss +++ b/datahub-web/@nacho-ui/nacho-pill/app/styles/nacho-pill-styles/_pill-input.scss @@ -1,9 +1,12 @@ .nacho-pill-input { &__input { - border: none; - - &:focus { - outline: none; + &, + .ember-power-select-search-input { + width: 220px; + border: none; + &:focus { + outline: none; + } } } @@ -14,4 +17,25 @@ padding: 0; color: inherit; } + + &__dropdown { + &#{&} { + z-index: z('modal') + z('dropdown'); + margin-top: item-spacing(2); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + border-radius: 2px; + border: 1px solid get-color(gray1); + + .ember-power-select-option[aria-current='true'] { + color: $text-color; + background-color: get-color(slate0); + } + } + + ul.ember-power-select-options[role='listbox'] { + height: 100%; + overflow-y: hidden; + max-height: none; + } + } } diff --git a/datahub-web/CONTRIBUTORS.md b/datahub-web/CONTRIBUTORS.md index 54753d1cfe06bd..8aada5184f0932 100644 --- a/datahub-web/CONTRIBUTORS.md +++ b/datahub-web/CONTRIBUTORS.md @@ -1,10 +1,7 @@ -DataHub Web Contributors -============================================= +# DataHub Web Contributors - Ignacio (Nacho) Bona Piedrabuena (2018) - Charlie (That Pikachu Guy) Tran (2017) -- Ram (Raym) Anbalagan (2019) - ## In loving memory @@ -52,4 +49,27 @@ DataHub Web Contributors | 2019 - 2020 || * | * ** * ** |** ** \))\\(///.,(//,,..,,\||(,,.,\\,.((// -``` \ No newline at end of file +``` + +``` + _ /) + (\ / ) + |/)\) + /\_ + \__|= + ( ) + __)(__ + _____/ \\_____ + | _ ___ _ || + | | \ | | \ || + | | | | | | || + | |_/ | |_/ || + | | \ | | || + | | \ | | || + | | \. _|_. | . || + | || + | Ram Anbalagan || + | 2019 - 2020 || + * | * ** * ** |** ** + \))\\(///.,(//,,..,,\||(,,.,\\,.((// +``` diff --git a/datahub-web/packages/data-portal/app/components/schema-comment.ts b/datahub-web/packages/data-portal/app/components/schema-comment.ts deleted file mode 100644 index c05d941472cc23..00000000000000 --- a/datahub-web/packages/data-portal/app/components/schema-comment.ts +++ /dev/null @@ -1,118 +0,0 @@ -import Component from '@ember/component'; -import { set } from '@ember/object'; -import { - readDatasetSchemaComments, - createDatasetSchemaComment, - updateDatasetSchemaComment, - deleteDatasetSchemaComment -} from 'datahub-web/utils/api/datasets/schema-comments'; -import { augmentObjectsWithHtmlComments } from 'datahub-web/utils/api/datasets/columns'; -import { IDatasetComment } from 'datahub-web/typings/api/datasets/comments'; -import { IDatasetColumn } from 'datahub-web/typings/api/datasets/columns'; -import Notifications from '@datahub/utils/services/notifications'; -import { NotificationEvent } from '@datahub/utils/constants/notifications'; -import { action } from '@ember/object'; -import { inject as service } from '@ember/service'; -import { TaskInstance, task } from 'ember-concurrency'; -import { ETask } from '@datahub/utils/types/concurrency'; - -enum SchemaCommentActions { - modify = 'modify', - destroy = 'destroy', - add = 'add' -} - -interface IGetCommentsTaskArgs { - datasetId: number; - columnId: number; - comments: Array; -} - -export class SchemaComment extends Component { - comments: Array = []; - count = 0; - datasetId = 0; - columnId = 0; - isShowingFieldComment = false; - - /** - * Local reference to the notifications service - * @memberof SchemaComment - */ - @service - notifications: Notifications; - - /** - * Enum of applicable values for schema comment actions - * @type {SchemaCommentActions} - */ - SchemaCommentActions = SchemaCommentActions; - - /** - * Task to get related schema comments - * TODO: refactor move to container component - */ - @task(function*({ - datasetId, - columnId, - comments - }: IGetCommentsTaskArgs): IterableIterator>> { - const schemaComments = ((yield readDatasetSchemaComments(datasetId, columnId)) as unknown) as Array< - IDatasetComment - >; - - if (Array.isArray(schemaComments)) { - const withHtmlComments = augmentObjectsWithHtmlComments( - schemaComments.map( - ({ text }): Partial => ({ - comment: text - }) - ) as Array - ); - comments.setObjects.call(comments, withHtmlComments); - } - }) - getCommentsTask!: ETask>, IGetCommentsTaskArgs>; - - @action - showComments(): TaskInstance>> { - const { datasetId, columnId, comments } = this; - set(this, 'isShowingFieldComment', true); - - return this.getCommentsTask.perform({ datasetId, columnId, comments }); - } - - @action - hideComments(): boolean { - return set(this, 'isShowingFieldComment', false); - } - - /** - * Given a schema comment action, invokes the related action to process the schema comment - * @param {SchemaCommentActions} strategy - * @return {Promise} - */ - @action - async handleSchemaComment(strategy: SchemaCommentActions, options: { text?: string } = {}): Promise { - const { text = '' } = options; - const { datasetId, columnId, notifications, comments, getCommentsTask } = this; - const { notify } = notifications; - - const action = { - add: (): Promise => createDatasetSchemaComment(datasetId, columnId, text), - modify: (): Promise => updateDatasetSchemaComment(datasetId, columnId, text), - destroy: (): Promise => deleteDatasetSchemaComment(datasetId, columnId) - }[strategy]; - - try { - await action(); - notify({ type: NotificationEvent.success, content: 'Success!' }); - // @ts-ignore ts limitation with the ember object model, fixed in ember 3.1 with es5 getters - getCommentsTask.perform({ datasetId, columnId, comments }); - } catch (e) { - notify({ type: NotificationEvent.error, content: e.message }); - } - - return false; - } -} diff --git a/datahub-web/packages/data-portal/app/components/search/containers/entity-task-container.ts b/datahub-web/packages/data-portal/app/components/search/containers/entity-task-container.ts index 81f24c9e9fef3b..77eace612eb303 100644 --- a/datahub-web/packages/data-portal/app/components/search/containers/entity-task-container.ts +++ b/datahub-web/packages/data-portal/app/components/search/containers/entity-task-container.ts @@ -6,14 +6,13 @@ import { import { TrackingEventCategory } from '@datahub/shared/constants/tracking/event-tracking/index'; import Component from '@ember/component'; import { set, computed } from '@ember/object'; -import { facetFromParamUrl, readSearchV2, facetToParamUrl } from 'datahub-web/utils/api/search/search'; +import { facetFromParamUrl, facetToParamUrl } from '@datahub/shared/utils/search/search'; import { IFacetsCounts, IFacetsSelectionsMap } from '@datahub/data-models/types/entity/facets'; import { task } from 'ember-concurrency'; import { debounce } from '@ember/runloop'; import { IDataModelEntitySearchResult, ISearchDataWithMetadata } from '@datahub/data-models/types/entity/search'; import { DataModelEntity, DataModelName, DataModelEntityInstance } from '@datahub/data-models/constants/entity'; import { DatasetEntity } from '@datahub/data-models/entity/dataset/dataset-entity'; -import { ISearchEntityApiParams, IEntitySearchResult } from '@datahub/shared/types/search/entity'; import { alias } from '@ember/object/computed'; import { containerDataSource } from '@datahub/utils/api/data-source'; import { inject as service } from '@ember/service'; @@ -29,8 +28,8 @@ import CurrentUser from '@datahub/shared/services/current-user'; import { PageKey, CustomTrackingEventName } from '@datahub/shared/constants/tracking/event-tracking'; import { ISearchResultImpressionTrackEventParams } from '@datahub/shared/types/tracking/event-tracking'; import { + getResultsForEntity, searchResultItemIndex, - searchResultMetasToFacetCounts, withResultMetadata } from '@datahub/shared/utils/search/search-results'; import { assertComponentPropertyNotUndefined } from '@datahub/utils/decorators/assert'; @@ -215,49 +214,23 @@ export default class SearchEntityTaskContainer extends Component { /** * Will perform a search for any type of entity (except datasets at the moment) */ - async getResultsForEntity( + getResultsForEntity( entity: DataModelName, searchConfig: SearchEntityTaskContainer['searchConfig'] ): Promise | undefined> { - const { keyword = '', page = 1, facetsApiParams, pageSize, dataModels } = this; const forcedFacets = getFacetForcedValueForEntity(searchConfig.attributes); - const mergedFacetsApiParams: Record> = { ...facetsApiParams, ...forcedFacets }; - const searchApiParams: ISearchEntityApiParams = { - facets: mergedFacetsApiParams, - input: keyword, - type: dataModels.getModel(entity).renderProps.apiEntityName, - start: (page - 1) * pageSize, - count: pageSize - }; - - const searchResultProxy: IEntitySearchResult = await readSearchV2< - DataModelEntityInstance['entity'] - >(searchApiParams); - const { elements } = searchResultProxy; - - if (elements) { - const { start, count, total } = searchResultProxy; - const itemsPerPage = count; - const totalPages = Math.ceil(total / itemsPerPage); - const page = Math.ceil((start + 1) / itemsPerPage); - const data = elements.map( - (entityData): DataModelEntityInstance => dataModels.createPartialInstance(entity, entityData) - ); - - const entitySearchResult = { - data, - count: total, - start, - itemsPerPage, - page, - totalPages, - facets: searchResultMetasToFacetCounts(searchResultProxy.searchResultMetadatas, facetsApiParams) - }; - - return entitySearchResult; - } - return; + return getResultsForEntity( + { + facetsApiParams: { ...this.facetsApiParams, ...forcedFacets }, + keyword: this.keyword || '', + page: this.page || 1, + pageSize: this.pageSize, + aspects: searchConfig.defaultAspects + }, + entity, + this.dataModels + ); } /** @@ -276,16 +249,6 @@ export default class SearchEntityTaskContainer extends Component { throw new Error('Could not parse search results'); } - /** - * Performs the action of searching entities (through the getResultsForEntity method) but by providing a way to override the keyword property. - * - * @param keyword User provided string to search against - */ - async searchEntitiesWithKeyword(keyword = ''): Promise { - set(this, 'keyword', keyword); - await this.searchEntities(); - } - /** * Relevant data model entity based on the kind of entity we are using. This helps us understand what * to render in the search results and how the autocomplete should work diff --git a/datahub-web/packages/data-portal/app/components/search/containers/search-box.ts b/datahub-web/packages/data-portal/app/components/search/containers/search-box.ts index 5bf5e341fcf249..25abcfb09265f3 100644 --- a/datahub-web/packages/data-portal/app/components/search/containers/search-box.ts +++ b/datahub-web/packages/data-portal/app/components/search/containers/search-box.ts @@ -12,11 +12,11 @@ import { getFacetDefaultValueForEntity, transformDefaultsIntoSelections } from '@datahub/data-models/entity/utils/facets'; -import { facetToParamUrl } from 'datahub-web/utils/api/search/search'; import RouterService from '@ember/routing/router-service'; import { task } from 'ember-concurrency'; import { ETaskPromise } from '@datahub/utils/types/concurrency'; import DataModelsService from '@datahub/data-models/services/data-models'; +import { facetToParamUrl } from '@datahub/shared/utils/search/search'; /** * Search box container that handle all the data part for diff --git a/datahub-web/packages/data-portal/app/templates/components/datasets/dataset-page.hbs b/datahub-web/packages/data-portal/app/templates/components/datasets/dataset-page.hbs index fc98b908dce8a5..338e57d22c6fbf 100644 --- a/datahub-web/packages/data-portal/app/templates/components/datasets/dataset-page.hbs +++ b/datahub-web/packages/data-portal/app/templates/components/datasets/dataset-page.hbs @@ -102,7 +102,6 @@ snapshot=(readonly container.entity.snapshot) urn=(readonly container.urn) avatarProperties=container.avatarEntityProps - jitAclConfig=container.jitAclConfig currentUsername=@userName wikiLinks=container.wikiLinks datasetName=container.entity.name diff --git a/datahub-web/packages/data-portal/app/templates/components/schema-comment.hbs b/datahub-web/packages/data-portal/app/templates/components/schema-comment.hbs deleted file mode 100644 index 8adab53af2905d..00000000000000 --- a/datahub-web/packages/data-portal/app/templates/components/schema-comment.hbs +++ /dev/null @@ -1,37 +0,0 @@ - - -{{#if isShowingFieldComment}} - {{#if getComments.last.isRunning}} - - - - - - Comments for {{schema.fieldName}} - - - - + Add a comment... - - - {{#each stream.comments as |comment|}} - - {{comment.html}} - - {{/each}} - - - - {{else}} - - {{/if}} -{{/if}} diff --git a/datahub-web/packages/data-portal/app/templates/components/search/containers/entity-task-container.hbs b/datahub-web/packages/data-portal/app/templates/components/search/containers/entity-task-container.hbs index c741e332af9919..eb40520e45e2a9 100644 --- a/datahub-web/packages/data-portal/app/templates/components/search/containers/entity-task-container.hbs +++ b/datahub-web/packages/data-portal/app/templates/components/search/containers/entity-task-container.hbs @@ -5,7 +5,6 @@ facetCounts=this.facetCounts isSearchRunning=this.isSearchRunning facetsSelections=this.facetsSelections - searchEntitiesWithKeyword=(action this.searchEntitiesWithKeyword) route=this.router.currentRouteName dataModelEntity=this.dataModelEntity pageSize=this.pageSize diff --git a/datahub-web/packages/data-portal/app/templates/features/feature/tab.hbs b/datahub-web/packages/data-portal/app/templates/features/feature/tab.hbs index 6505d947d34102..6392edc26064e0 100644 --- a/datahub-web/packages/data-portal/app/templates/features/feature/tab.hbs +++ b/datahub-web/packages/data-portal/app/templates/features/feature/tab.hbs @@ -24,6 +24,9 @@ @feature={{readonly container.entity}} @didUpdateStatus={{action container.onUpdateFeatureStatus}} > + {{#if (and container.entity container.entity.isPublished)}} + + {{/if}}
diff --git a/datahub-web/packages/data-portal/app/typings/api/datasets/columns.d.ts b/datahub-web/packages/data-portal/app/typings/api/datasets/columns.d.ts deleted file mode 100644 index 6a9e73ea3a170d..00000000000000 --- a/datahub-web/packages/data-portal/app/typings/api/datasets/columns.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ApiStatus } from '@datahub/utils/api/shared'; - -/** - * Describes a dataset column - */ -export interface IDatasetColumn { - comment: string; - commentCount: null | number; - dataType: string; - distributed: boolean; - fieldName: string; - fullFieldPath: string; - id: number | null; - indexed: boolean; - nullable: boolean; - parentSortID: number; - partitioned: boolean; - sortID: number; - treeGridClass: null; -} - -/** - * Describes the interface that extends a DatasetColumn with a string - */ -export interface IDatasetColumnWithHtmlComments extends IDatasetColumn { - commentHtml: string; -} - -/** - * Describes a dataset column GET request response - */ -export interface IDatasetColumnsGetResponse { - status: ApiStatus; - columns?: Array; - message?: string; - schemaless: boolean; -} diff --git a/datahub-web/packages/data-portal/app/typings/api/datasets/properties.d.ts b/datahub-web/packages/data-portal/app/typings/api/datasets/properties.d.ts deleted file mode 100644 index 1cc465f74e632f..00000000000000 --- a/datahub-web/packages/data-portal/app/typings/api/datasets/properties.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ApiStatus } from '@datahub/utils/api/shared'; - -/** - * Describes the interface a for dataset properties that are not sourced from pinot - * @interface IDatasetProperties - */ -export interface IDatasetProperties { - [prop: string]: any; -} - -/** - * Describes the interface for properties that are from sources other than pinot - * @interface IDatasetPinotProperties - */ -export interface IDatasetPinotProperties { - elements: Array<{ - columnNames: Array; - results: Array; - }>; -} - -/** - * Describes the interface for a response received from a GET request to the properties endpoint - * when the source is NOT pinot - * @interface IDatasetPropertiesGetResponse - */ -export interface IDatasetPropertiesGetResponse { - status: ApiStatus; - properties?: IDatasetProperties; - message?: string; -} - -/** - * Describes the interface for a response received from a GET request to the properties endpoint - * when the source IS pinot - * @interface IDatasetPinotPropertiesGetResponse - */ -export interface IDatasetPinotPropertiesGetResponse { - status: ApiStatus; - properties?: IDatasetPinotProperties; - message?: string; -} diff --git a/datahub-web/packages/data-portal/app/typings/api/datasets/schema-comments.d.ts b/datahub-web/packages/data-portal/app/typings/api/datasets/schema-comments.d.ts deleted file mode 100644 index 147006fbecf206..00000000000000 --- a/datahub-web/packages/data-portal/app/typings/api/datasets/schema-comments.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ApiStatus } from '@datahub/utils/api/shared'; - -export interface IDatasetSchemaCommentResponse { - status: ApiStatus; -} diff --git a/datahub-web/packages/data-portal/app/typings/api/datasets/schema.d.ts b/datahub-web/packages/data-portal/app/typings/api/datasets/schema.d.ts deleted file mode 100644 index 72221526df0ae0..00000000000000 --- a/datahub-web/packages/data-portal/app/typings/api/datasets/schema.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IDatasetColumn } from 'datahub-web/typings/api/datasets/columns'; - -/** - * Describes the properties on a dataset schema object - * @interface - */ -export interface IDatasetSchema { - schemaless: boolean; - rawSchema: null | string; - keySchema: null | string; - lastModified?: number; - columns: Array; -} - -/** - * Describes the properties on a response to a request for dataset schema - * @interface - */ -export interface IDatasetSchemaGetResponse { - schema: IDatasetSchema; -} diff --git a/datahub-web/packages/data-portal/app/typings/app/dataset-columns.d.ts b/datahub-web/packages/data-portal/app/typings/app/dataset-columns.d.ts index 3a290dc2fe3c26..953905273bb938 100644 --- a/datahub-web/packages/data-portal/app/typings/app/dataset-columns.d.ts +++ b/datahub-web/packages/data-portal/app/typings/app/dataset-columns.d.ts @@ -1,14 +1,14 @@ -import { IDatasetColumn } from 'datahub-web/typings/api/datasets/columns'; import { IComplianceEntity, IComplianceInfo } from 'datahub-web/typings/api/datasets/compliance'; import { IComplianceChangeSet, ISchemaFieldsToPolicy } from 'datahub-web/typings/app/dataset-compliance'; +import { IDatasetSchemaColumn } from '@datahub/metadata-types/types/entity/dataset/schema'; /** * Defines the interface for keys extracted from the columns property on an response of IDatasetSchemaGetResponse * @interface IColumnFieldProps */ export interface IColumnFieldProps { - identifierField: IDatasetColumn['fullFieldPath']; - dataType: IDatasetColumn['dataType']; + identifierField: IDatasetSchemaColumn['fullFieldPath']; + dataType: IDatasetSchemaColumn['dataType']; identifierType?: IComplianceEntity['identifierType']; logicalType?: IComplianceEntity['logicalType']; suggestion?: IComplianceChangeSet['suggestion']; diff --git a/datahub-web/packages/data-portal/app/utils/api/datasets/columns.ts b/datahub-web/packages/data-portal/app/utils/api/datasets/columns.ts deleted file mode 100644 index a9dd8638624339..00000000000000 --- a/datahub-web/packages/data-portal/app/utils/api/datasets/columns.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { datasetUrlById } from 'datahub-web/utils/api/datasets/shared'; -import { - IDatasetColumn, - IDatasetColumnsGetResponse, - IDatasetColumnWithHtmlComments -} from 'datahub-web/typings/api/datasets/columns'; -import { getJSON } from '@datahub/utils/api/fetcher'; -import { ApiStatus } from '@datahub/utils/api/shared'; -import { arrayMap } from '@datahub/utils/array/index'; -import { renderLinksAsAnchorTags } from '@datahub/utils/helpers/render-links-as-anchor-tags'; - -// TODO: DSS-6122 Create and move to Error module - -/** - * default exception string for columns api - * @type {string} - */ -const datasetColumnsException = 'An error occurred with the columns api'; - -/** - * Constructs a dataset column url using a dataset id - * @param {number} id the id of the dataset - * @return {string} - */ -const datasetColumnUrlById = (id: number): string => `${datasetUrlById(id)}/columns`; - -/** - * Maps an object with a column prop to an object containing markdown comments, if the dataset has a comment attribute - * @template T - * @param {T} objectWithComment - * @returns {(T | T & {commentHtml: string})} - */ -const augmentWithHtmlComment = ( - objectWithComment: T -): T | (T & { commentHtml: string }) => { - const { comment } = objectWithComment; - // TODO: DSS-6122 Refactor global function reference to marked - // not using spread operator here: https://github.com/Microsoft/TypeScript/issues/10727 - // current ts version: 2.5.3 - return comment - ? Object.assign({}, objectWithComment, { commentHtml: renderLinksAsAnchorTags([comment]) }) - : objectWithComment; -}; - -/** - * Picks out the dataset dataType and fullFieldPath (as fieldName) properties - * @param {string} dataType string representing the data type of the field - * @param {string} fullFieldPath the path of the field on this dataset - * @return {Pick} - */ -const columnDataTypeAndFieldName = ({ - dataType, - fullFieldPath -}: IDatasetColumn | IDatasetColumnWithHtmlComments): Pick => ({ - dataType, - fieldName: fullFieldPath -}); - -/** - * Takes a list of objects with comments and returns an array of objects with comments or html comments - * @type {(array: Array) => Array} - */ -const augmentObjectsWithHtmlComments = arrayMap( - augmentWithHtmlComment -); - -/** - * Takes a list of IDatasetColumn / IDatasetColumn with html comments and pulls the dataType and and fullFieldPath (as fieldName) attributes - * @type {(array: Array) => Array>} - */ -const columnDataTypesAndFieldNames = arrayMap(columnDataTypeAndFieldName); - -/** - * Gets the dataset columns for a dataset with the id specified and the schemaless flag - * @param {number} id the id of the dataset - * @return {(Promise<{schemaless: boolean; columns: Array}>)} - */ -const readDatasetColumns = async (id: number): Promise<{ schemaless: boolean; columns: Array }> => { - const { status, columns = [], schemaless, message = datasetColumnsException } = await getJSON< - IDatasetColumnsGetResponse - >({ - url: datasetColumnUrlById(id) - }); - - // Returns an empty list if the status is ok but the columns is falsey - if (status === ApiStatus.OK) { - return { schemaless, columns }; - } - - throw new Error(message); -}; - -export { readDatasetColumns, columnDataTypesAndFieldNames, augmentObjectsWithHtmlComments, datasetColumnUrlById }; diff --git a/datahub-web/packages/data-portal/app/utils/api/datasets/properties.ts b/datahub-web/packages/data-portal/app/utils/api/datasets/properties.ts index 2cee0b328f561a..2c4f3f55358aae 100644 --- a/datahub-web/packages/data-portal/app/utils/api/datasets/properties.ts +++ b/datahub-web/packages/data-portal/app/utils/api/datasets/properties.ts @@ -1,30 +1,6 @@ -import { ApiStatus } from '@datahub/utils/api/shared'; -import { getJSON, putJSON } from '@datahub/utils/api/fetcher'; -import { datasetUrlById } from 'datahub-web/utils/api/datasets/shared'; -import { - IDatasetProperties, - IDatasetPropertiesGetResponse, - IDatasetPinotPropertiesGetResponse, - IDatasetPinotProperties -} from 'datahub-web/typings/api/datasets/properties'; +import { putJSON } from '@datahub/utils/api/fetcher'; import { datasetUrlByUrn } from '@datahub/data-models/api/dataset/dataset'; -/** - * Describes the interface for an element in the list generated by the buildPropertiesList function - * @interface IPropertyItem - */ -interface IPropertyItem { - isSelectController: boolean; - key: keyof IDatasetProperties; - value: string | Element; -} - -/** - * Constructs the dataset properties endpoint url based on the id - * @param {number} id dataset id - */ -const datasetPropertiesUrlById = (id: number): string => `${datasetUrlById(id)}/properties`; - /** * Returns the url for a dataset deprecation endpoint by urn * @param {string} urn @@ -32,151 +8,6 @@ const datasetPropertiesUrlById = (id: number): string => `${datasetUrlById(id)}/ */ const datasetDeprecationUrlByUrn = (urn: string): string => `${datasetUrlByUrn(urn)}/deprecate`; -/** - * Reads the response from the dataset properties endpoint and returns properties if found - * @param {number} id the dataset id to get properties for - * @returns {IDatasetPropertiesGetResponse | IDatasetPinotPropertiesGetResponse} - */ -const readDatasetProperties = async ( - id: number -): Promise => { - const { status, properties, message } = await getJSON({ url: datasetPropertiesUrlById(id) }); - - if (status === ApiStatus.OK && properties) { - return properties; - } - - // treat the error status with a record not found msg as empty set - if (status === ApiStatus.ERROR && message === 'record not found') { - return {}; - } - - throw new Error('Exception occurred reading the dataset properties'); -}; - -/** - * Formats the property value as a date string - * @param {keyof IDatasetProperties} property - * @param {*} value - * @returns {*} - */ -//TODO -// eslint-disable-next-line -const formatPropertyDateValue = (property: Extract, value: any): any => { - const isoStringDateProperties = ['modification_time', 'begin_date', 'lumos_process_time', 'end_date', 'oracle_time']; - - if (isoStringDateProperties.includes(property)) { - if (+value < 0) { - return value; - } - - return new Date(value).toISOString(); - } - - if (property === 'dumpdate') { - return [ - ['-', 0, 4], - ['-', 4, 6], - [' ', 6, 8], - [':', 8, 10], - [':', 10, 12], - ['', 12, 14] - ].reduce((dateString, props: [string, number, number]): string => { - const [postfix, start, end] = props; - return value ? dateString + ('' + value).substring(start, end) + postfix : dateString; - }, ''); - } - - return value; -}; - -/** - * Builds a list of IPropertyItem values - * @param {IDatasetProperties} properties - * @returns {Array} - * @link IPropertyItem - */ -const buildPropertiesList = (properties: IDatasetProperties): Array => { - return Object.keys(properties).reduce((propertiesList, property: Extract): Array< - IPropertyItem - > => { - if (['elements', 'view_depends_on'].includes(property)) { - return propertiesList; - } - - const typeofPropertyIsNotObject = typeof properties[property] !== 'object'; - const connectionURL = properties['connectionURL']; - let value: string | Element; - let listItem: IPropertyItem = { - isSelectController: ['view_expanded_text', 'viewSqlText'].includes(property), - key: property, - value: window.JsonHuman ? window.JsonHuman.format(properties[property]) : '' - }; - - if (typeofPropertyIsNotObject) { - if (connectionURL) { - const list = connectionURL.split(',') || []; - value = list.length ? (window.JsonHuman ? window.JsonHuman.format(list) : '') : connectionURL; - } else { - const tempValue = formatPropertyDateValue(property, properties[property]); - value = !tempValue && tempValue !== 0 ? 'NULL' : tempValue; - } - - listItem = { ...listItem, value }; - } - - return [...propertiesList, listItem]; - }, []); -}; - -/** - * Reads the dataset properties returned by the properties endpoint and builds a list of IPropertyItem values - * @param {number} id - * @returns {Promise>} - */ -const readNonPinotProperties = async (id: number): Promise> => { - return buildPropertiesList((await readDatasetProperties(id)) as IDatasetProperties); -}; - -/** - * Describes the interface of object returned from the api request to get pinot properties - * @interface IDatasetSamplesAndColumns - */ -interface IDatasetSamplesAndColumns { - hasSamples: boolean; - samples: Array; - columns: Array; -} -/** - * Extracts samples and columns for a dataset that is sourced from pinot - * @param {IDatasetPinotProperties} [properties={}] - * @returns - */ -const getDatasetSamplesAndColumns = ( - //TODO - // eslint-disable-next-line - properties: IDatasetPinotProperties = {} as IDatasetPinotProperties -): IDatasetSamplesAndColumns | void => { - const { elements = [{ columnNames: [], results: [] }] } = properties; - const [{ columnNames = [], results }] = elements; - if (columnNames.length) { - return { - hasSamples: true, // TODO: remove the, can be derived from samples.length - samples: results, - columns: columnNames - }; - } -}; - -/** - * Reads a subset: samples and columns from a datasets properties that are derived from pinot - * @param {number} id the id of the pinot dataset - * @returns - */ -const readPinotProperties = async (id: number): Promise => { - return getDatasetSamplesAndColumns((await readDatasetProperties(id)) as IDatasetPinotProperties); -}; - /** * Persists the changes to a datasets deprecation properties by urn * @param {string} urn @@ -185,7 +16,7 @@ const readPinotProperties = async (id: number): Promise} */ -const updateDatasetDeprecationByUrn = ( +export const updateDatasetDeprecationByUrn = ( urn: string, deprecated: boolean, deprecationNote = '', @@ -199,5 +30,3 @@ const updateDatasetDeprecationByUrn = ( decommissionTime } }); - -export { readDatasetProperties, readNonPinotProperties, readPinotProperties, updateDatasetDeprecationByUrn }; diff --git a/datahub-web/packages/data-portal/app/utils/api/datasets/schema-comments.ts b/datahub-web/packages/data-portal/app/utils/api/datasets/schema-comments.ts deleted file mode 100644 index fc0d46f377c7b9..00000000000000 --- a/datahub-web/packages/data-portal/app/utils/api/datasets/schema-comments.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { IDatasetComment, IDatasetCommentsGetResponse } from 'datahub-web/typings/api/datasets/comments'; -import { datasetColumnUrlById } from 'datahub-web/utils/api/datasets/columns'; -import { ApiStatus } from '@datahub/utils/api/shared'; -import { getJSON, postJSON, deleteJSON, putJSON } from '@datahub/utils/api/fetcher'; -import { IDatasetSchemaCommentResponse } from 'datahub-web/typings/api/datasets/schema-comments'; - -/** - * - * @param {number} datasetId - * @param {number} columnId - */ -const datasetSchemaCommentUrlById = (datasetId: number, columnId: number): string => - `${datasetColumnUrlById(datasetId)}/${columnId}/comments`; - -/** - * - * @param {number} datasetId - * @param {number} columnId - * @return {Promise>} - */ -const readDatasetSchemaComments = async (datasetId: number, columnId: number): Promise> => { - const defaultData: { comments: Array } = { comments: [] }; - const { status, data: { comments = [] } = defaultData } = await getJSON({ - url: datasetSchemaCommentUrlById(datasetId, columnId) - }); - - if (status === ApiStatus.OK) { - return comments; - } - - throw new Error(''); -}; - -const createDatasetSchemaComment = async (datasetId: number, columnId: number, comment: string): Promise => { - const { status } = await postJSON({ - url: datasetSchemaCommentUrlById(datasetId, columnId), - data: { comment } - }); - - if (status !== ApiStatus.OK) { - throw new Error(); - } -}; - -const deleteDatasetSchemaComment = async (datasetId: number, columnId: number): Promise => { - const { status } = await deleteJSON({ - url: datasetSchemaCommentUrlById(datasetId, columnId) - }); - - if (status !== ApiStatus.OK) { - throw new Error(); - } -}; - -const updateDatasetSchemaComment = async (datasetId: number, columnId: number, comment: string): Promise => { - const { status } = await putJSON({ - url: datasetSchemaCommentUrlById(datasetId, columnId), - data: { comment } - }); - - if (status !== ApiStatus.OK) { - throw new Error(); - } -}; - -export { - readDatasetSchemaComments, - createDatasetSchemaComment, - deleteDatasetSchemaComment, - updateDatasetSchemaComment -}; diff --git a/datahub-web/packages/data-portal/app/utils/api/datasets/shared.ts b/datahub-web/packages/data-portal/app/utils/api/datasets/shared.ts deleted file mode 100644 index e8444d934d717a..00000000000000 --- a/datahub-web/packages/data-portal/app/utils/api/datasets/shared.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { datasetUrlRoot } from '@datahub/data-models/api/dataset/dataset'; -import { ApiVersion } from '@datahub/utils/api/shared'; - -/** - * Constructs a url to get a dataset with a given id - * @param {number} id the id of the dataset - * @return {string} the dataset url - */ -export const datasetUrlById = (id: number): string => `${datasetUrlRoot(ApiVersion.v1)}/${id}`; diff --git a/datahub-web/packages/data-portal/app/utils/parsers/autocomplete/utils.ts b/datahub-web/packages/data-portal/app/utils/parsers/autocomplete/utils.ts index aa0b4337aa80d8..96da2126221f31 100644 --- a/datahub-web/packages/data-portal/app/utils/parsers/autocomplete/utils.ts +++ b/datahub-web/packages/data-portal/app/utils/parsers/autocomplete/utils.ts @@ -1,5 +1,5 @@ -import { readValuesV2 } from 'datahub-web/utils/api/search/values-v2'; -import { IFieldValuesResponseV2 } from 'datahub-web/typings/app/search/fields-v2'; +import { readValuesV2 } from '@datahub/shared/utils/search/values-v2'; +import { IFieldValuesResponseV2 } from '@datahub/shared/types/search/fields-v2'; import { debounceAndMemoizeAsyncQuery } from '@datahub/utils/api/autocomplete'; /** diff --git a/datahub-web/packages/data-portal/app/utils/parsers/helpers.ts b/datahub-web/packages/data-portal/app/utils/parsers/helpers.ts index 138669eddf7924..ff548829cee8ec 100644 --- a/datahub-web/packages/data-portal/app/utils/parsers/helpers.ts +++ b/datahub-web/packages/data-portal/app/utils/parsers/helpers.ts @@ -1,8 +1,8 @@ import { ISuggestionGroup } from 'datahub-web/utils/parsers/autocomplete/types'; import { DataModelEntity } from '@datahub/data-models/constants/entity'; -import { IFieldValuesResponseV2, FieldValuesRequestV2 } from 'datahub-web/typings/app/search/fields-v2'; import { facetValuesApiEntities } from 'datahub-web/utils/parsers/autocomplete/utils'; import { getFacetForcedValueForEntity } from '@datahub/data-models/entity/utils/facets'; +import { FieldValuesRequestV2, IFieldValuesResponseV2 } from '@datahub/shared/types/search/fields-v2'; export const createSuggestionsFromError = (error: string): Array => { return [ diff --git a/datahub-web/yarn.lock b/datahub-web/yarn.lock index dadea9b49e40b7..63796f419f630d 100644 --- a/datahub-web/yarn.lock +++ b/datahub-web/yarn.lock @@ -2757,11 +2757,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8" integrity sha1-XIXWYvdvodNFdXZsXc1mFavNMNg= -"@yarnpkg/lockfile@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha1-53qX+9NFt22DJF7c0X05OxtB+zE= - JSONStream@~1.3.1: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -2939,11 +2934,6 @@ ansi-colors@3.2.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha1-V9NbhoboUeLMBMQD8cACA5dqGBM= -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= - ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -3008,16 +2998,16 @@ ansi-to-html@^0.6.6: dependencies: entities "^1.1.2" -ansicolors@^0.3.2, ansicolors@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" - integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= - ansicolors@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" integrity sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8= +ansicolors@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" + integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= + ansistyles@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" @@ -3073,13 +3063,6 @@ aproba@~1.1.2: resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" integrity sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw== -archive-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" - integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= - dependencies: - file-type "^4.2.0" - archy@^1.0.0, archy@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -4066,11 +4049,6 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg= -bignumber.js@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8" - integrity sha1-g4qZLan51zfg9LLbC+YrsJ3Qxeg= - binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -4255,20 +4233,6 @@ boxen@^1.0.0, boxen@^1.2.1: term-size "^1.2.0" widest-line "^2.0.0" -boxen@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb" - integrity sha1-+9/w3pNjarRFCIa2/0W5LQmPRes= - dependencies: - ansi-align "^3.0.0" - camelcase "^5.3.1" - chalk "^2.4.2" - cli-boxes "^2.2.0" - string-width "^3.0.0" - term-size "^1.2.0" - type-fest "^0.3.0" - widest-line "^2.0.0" - boxen@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" @@ -5122,13 +5086,6 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" - integrity sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0= - dependencies: - pako "~0.2.0" - browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" @@ -5534,16 +5491,6 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -caw@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" - integrity sha1-bDygcfwZRyCIPC3F2psHS/x+npU= - dependencies: - get-proxy "^2.0.0" - isurl "^1.0.0-alpha5" - tunnel-agent "^0.6.0" - url-to-options "^1.0.1" - chai@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" @@ -5571,7 +5518,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ= @@ -5743,13 +5690,6 @@ cli-boxes@^2.2.0: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== -cli-cursor@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= - dependencies: - restore-cursor "^1.0.1" - cli-cursor@^2.0.0, cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -5764,11 +5704,6 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^1.1.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" - integrity sha1-ACwZkJEtDVlYDJO9NsBW3pnkJZo= - cli-spinners@^2.0.0, cli-spinners@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" @@ -5991,7 +5926,7 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -compare-versions@^3.2.1, compare-versions@^3.4.0: +compare-versions@^3.2.1: version "3.5.1" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.5.1.tgz#26e1f5cf0d48a77eced5046b9f67b6b61075a393" integrity sha1-JuH1zw1Ip37O1QRrn2e2thB1o5M= @@ -6051,7 +5986,7 @@ concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.5.2: readable-stream "^2.2.2" typedarray "^0.0.6" -config-chain@^1.1.11, config-chain@~1.1.11: +config-chain@~1.1.11: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== @@ -6071,18 +6006,6 @@ configstore@^3.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" -configstore@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" - integrity sha1-WTMxHpXTaH77WSxSi5ItkmLSJ+c= - dependencies: - dot-prop "^4.1.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - configstore@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.0.tgz#37de662c7a49b5fe8dbcf8f6f5818d2d81ed852b" @@ -6117,18 +6040,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -console-ui@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/console-ui/-/console-ui-2.2.3.tgz#134b92e632f2c0088f78e52b20f1ca22a95b9a91" - integrity sha1-E0uS5jLywAiPeOUrIPHKIqlbmpE= - dependencies: - chalk "^2.1.0" - inquirer "^2" - json-stable-stringify "^1.0.1" - ora "^2.0.0" - through "^2.3.8" - user-info "^1.0.0" - console-ui@^3.0.4, console-ui@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/console-ui/-/console-ui-3.1.1.tgz#681a0414e8b0a23ed679d0a2802e39d920801171" @@ -6157,7 +6068,7 @@ contains-path@^0.1.0: resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= -content-disposition@0.5.3, content-disposition@^0.5.2: +content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" integrity sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70= @@ -6504,11 +6415,6 @@ date-time@^2.1.0: dependencies: time-zone "^1.0.0" -dayjs@^1.8.14: - version "1.8.17" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.17.tgz#53ec413f2a7b02afbea1846d61bb260fa8567cea" - integrity sha1-U+xBPyp7Aq++oYRtYbsmD6hWfOo= - deasync@^0.1.13: version "0.1.19" resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.19.tgz#e7ea89fcc9ad483367e8a48fe78f508ca86286e8" @@ -6656,11 +6562,6 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -deepmerge@^4.0.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha1-RNLqNnm49NT/ujPwPYZfwee/SVU= - default-require-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" @@ -6773,16 +6674,16 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" -detect-indent@^5.0.0, detect-indent@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" - integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= - detect-indent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" integrity sha1-Cr0PVJ9p/GZZolT+lnhhhrb1KP0= +detect-indent@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= + detect-newline@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -7004,24 +6905,6 @@ dotenv@^5.0.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow== -download@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/download/-/download-7.1.0.tgz#9059aa9d70b503ee76a132897be6dec8e5587233" - integrity sha1-kFmqnXC1A+52oTKJe+beyOVYcjM= - dependencies: - archive-type "^4.0.0" - caw "^2.0.1" - content-disposition "^0.5.2" - decompress "^4.2.0" - ext-name "^5.0.0" - file-type "^8.1.0" - filenamify "^2.0.0" - get-stream "^3.0.0" - got "^8.3.1" - make-dir "^1.2.0" - p-event "^2.1.0" - pify "^3.0.0" - duplex@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/duplex/-/duplex-1.0.0.tgz#6abc5c16ec17e4c578578727126700590d3a2dda" @@ -7032,7 +6915,7 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= -duplexify@^3.4.2, duplexify@^3.5.0, duplexify@^3.6.0: +duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" integrity sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk= @@ -8064,7 +7947,7 @@ ember-local-storage@^1.7.0: ember-cli-version-checker "^2.1.0" ember-copy "^1.0.0" -ember-lodash@^4.18.0, ember-lodash@^4.19.4: +ember-lodash@^4.18.0: version "4.19.4" resolved "https://registry.yarnpkg.com/ember-lodash/-/ember-lodash-4.19.4.tgz#3e76e6cb04c9312c2158180bf16d7983aae05774" integrity sha1-PnbmywTJMSwhWBgL8W15g6rgV3Q= @@ -8085,7 +7968,7 @@ ember-macro-helpers@^4.2.2: ember-cli-string-utils "^1.1.0" ember-cli-test-info "^1.0.0" -ember-math-helpers@^2.11.3, ember-math-helpers@^2.7.1: +ember-math-helpers@^2.7.1: version "2.11.3" resolved "https://registry.yarnpkg.com/ember-math-helpers/-/ember-math-helpers-2.11.3.tgz#32a2523c7408787a6029b64c25b6ece88b320142" integrity sha1-MqJSPHQIeHpgKbZMJbbs6IsyAUI= @@ -8334,7 +8217,7 @@ ember-sinon@^3.1.0, ember-sinon@~3.1.0: ember-cli-babel "^7.1.3" sinon "^7.1.1" -ember-sinon@^4.0.0, ember-sinon@^4.1.1: +ember-sinon@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ember-sinon/-/ember-sinon-4.1.1.tgz#ff6db9e3b9548e269386d9efe1c381e165f03ba5" integrity sha1-/22547lUjiaThtnv4cOB4WXwO6U= @@ -8989,33 +8872,11 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -exec-file-sync@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/exec-file-sync/-/exec-file-sync-2.0.2.tgz#58d441db46e40de6d1f30de5be022785bd89e328" - integrity sha1-WNRB20bkDebR8w3lvgInhb2J4yg= - dependencies: - is-obj "^1.0.0" - object-assign "^4.0.1" - spawn-sync "^1.0.11" - exec-sh@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b" integrity sha1-ZzjeLrfI5nHQNmrqCw24xvfXORs= -execa@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - integrity sha1-/0Vqj1P5D47MxxqW0Rvfx/CCy1A= - dependencies: - cross-spawn "^6.0.0" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -9083,11 +8944,6 @@ exists-sync@^0.1.0: resolved "https://registry.yarnpkg.com/exists-sync/-/exists-sync-0.1.0.tgz#318d545213d2b2a31499e92c35f74c94196a22f7" integrity sha512-qEfFekfBVid4b14FNug/RNY1nv+BADnlzKGHulc+t6ZLqGY4kdHGh1iFha8lnE3sJU/1WzMzKRNxS6EvSakJUg== -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" - integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -9149,21 +9005,6 @@ express@^4.10.7, express@^4.16.4: utils-merge "1.0.1" vary "~1.1.2" -ext-list@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" - integrity sha1-C5jmTtgvWs8PKTG6v2khLvUt3Tc= - dependencies: - mime-db "^1.28.0" - -ext-name@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" - integrity sha1-cHgZgdGD7hXROZPIgiBFxQbI8KY= - dependencies: - ext-list "^2.0.0" - sort-keys-length "^1.0.0" - extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -9184,15 +9025,6 @@ extend@^3.0.0, extend@^3.0.2, extend@~3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-1.1.1.tgz#12d7b0db850f7ff7e7081baf4005700060c4600b" - integrity sha1-Etew24UPf/fnCBuvQAVwAGDEYAs= - dependencies: - extend "^3.0.0" - spawn-sync "^1.0.15" - tmp "^0.0.29" - external-editor@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" @@ -9419,11 +9251,6 @@ file-type@^3.8.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= -file-type@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" - integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= - file-type@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" @@ -9434,30 +9261,11 @@ file-type@^6.1.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" integrity sha1-5QzXXTVv/tTjBtxPW89Sp5kDqRk= -file-type@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-8.1.0.tgz#244f3b7ef641bbe0cca196c7276e4b332399f68c" - integrity sha1-JE87fvZBu+DMoZbHJ25LMyOZ9ow= - file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90= -filename-reserved-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" - integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= - -filenamify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9" - integrity sha1-iPr0lfsbR6v9YSMAACoWIoxnfuk= - dependencies: - filename-reserved-regex "^2.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - fileset@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" @@ -9634,14 +9442,6 @@ fixturify-project@^1.10.0: fixturify "^1.2.0" tmp "^0.0.33" -fixturify@^0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/fixturify/-/fixturify-0.3.4.tgz#c676de404a7f8ee8e64d0b76118e62ec95ab7b25" - integrity sha1-xnbeQEp/jujmTQt2EY5i7JWreyU= - dependencies: - fs-extra "^0.30.0" - matcher-collection "^1.0.4" - fixturify@^1.0.0, fixturify@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/fixturify/-/fixturify-1.2.0.tgz#abe8c52dd27dbbfdb874a02893781c93425663ea" @@ -9775,17 +9575,6 @@ fs-extra@^0.24.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - fs-extra@^4.0.2, fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -9804,7 +9593,7 @@ fs-extra@^5.0.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^6.0.0, fs-extra@^6.0.1: +fs-extra@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" integrity sha1-irwSj3lG4xATXdyTuYvdtBDno0s= @@ -9843,13 +9632,6 @@ fs-merger@^3.0.1: rimraf "^2.6.3" walk-sync "^2.0.2" -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha1-zP+FcIQef+QmVpPaiJNsVa7X98c= - dependencies: - minipass "^2.6.0" - fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -10027,13 +9809,6 @@ get-own-enumerable-property-symbols@^3.0.0: resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203" integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg== -get-proxy@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" - integrity sha1-NJ8rTZHUTE1NTpy6KtkBQ/rF75M= - dependencies: - npm-conf "^1.1.0" - get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -10353,7 +10128,7 @@ got@^6.7.1: unzip-response "^2.0.1" url-parse-lax "^1.0.0" -got@^8.0.1, got@^8.3.1: +got@^8.0.1: version "8.3.2" resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== @@ -10393,7 +10168,7 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2: +graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha1-ShL/G2A3bvCYYsIJPt2Qgyi+hCM= @@ -10423,18 +10198,6 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -gunzip-maybe@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/gunzip-maybe/-/gunzip-maybe-1.4.1.tgz#39c72ed89d1b49ba708e18776500488902a52027" - integrity sha1-Occu2J0bSbpwjhh3ZQBIiQKlICc= - dependencies: - browserify-zlib "^0.1.4" - is-deflate "^1.0.0" - is-gzip "^1.0.0" - peek-stream "^1.1.0" - pumpify "^1.3.3" - through2 "^2.0.3" - hammerjs@^2.0.6, hammerjs@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1" @@ -11025,26 +10788,6 @@ inline-source-map-comment@^1.0.5: sum-up "^1.0.1" xtend "^4.0.0" -inquirer@^2: - version "2.0.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-2.0.0.tgz#e1351687b90d150ca403ceaa3cefb1e3065bef4b" - integrity sha1-4TUWh7kNFQykA86qPO+x4wZb70s= - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^2.0.0" - external-editor "^1.1.0" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.6" - pinkie-promise "^2.0.0" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@^6: version "6.3.1" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" @@ -11211,11 +10954,6 @@ is-date-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha1-vac28s2P0G0yhE53Q7+nSUw7/X4= -is-deflate@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-deflate/-/is-deflate-1.0.0.tgz#c862901c3c161fb09dac7cdc7e784f80e98f2f14" - integrity sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ= - is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -11302,11 +11040,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-gzip@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-gzip/-/is-gzip-1.0.0.tgz#6ca8b07b99c77998025900e555ced8ed80879a83" - integrity sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM= - is-installed-globally@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" @@ -11890,13 +11623,6 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0= -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= - optionalDependencies: - graceful-fs "^4.1.9" - latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" @@ -12238,11 +11964,6 @@ lodash.bind@^4.1.4: resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= - lodash.castarray@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115" @@ -12317,11 +12038,6 @@ lodash.foreach@^4.3.0, lodash.foreach@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -12436,7 +12152,7 @@ lodash.without@~4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@~4.17.10: +lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.5.1, lodash@^4.6.1, lodash@~4.17.10: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg= @@ -12552,7 +12268,7 @@ magic-string@^0.24.0: dependencies: sourcemap-codec "^1.4.1" -make-dir@^1.0.0, make-dir@^1.2.0, make-dir@^1.3.0: +make-dir@^1.0.0, make-dir@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== @@ -12680,7 +12396,7 @@ marked@^1.1.1: resolved "https://registry.yarnpkg.com/marked/-/marked-1.1.1.tgz#e5d61b69842210d5df57b05856e0c91572703e6a" integrity sha1-5dYbaYQiENXfV7BYVuDJFXJwPmo= -matcher-collection@^1.0.0, matcher-collection@^1.0.4, matcher-collection@^1.1.1: +matcher-collection@^1.0.0, matcher-collection@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/matcher-collection/-/matcher-collection-1.1.2.tgz#1076f506f10ca85897b53d14ef54f90a5c426838" integrity sha1-EHb1BvEMqFiXtT0U71T5ClxCaDg= @@ -12767,7 +12483,7 @@ memory-streams@^0.1.3: dependencies: readable-stream "~1.0.2" -meow@^3.4.0, meow@^3.7.0: +meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= @@ -12866,7 +12582,7 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.43.0, "mime-db@>= 1.40.0 < 2", mime-db@^1.28.0: +mime-db@1.43.0, "mime-db@>= 1.40.0 < 2": version "1.43.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== @@ -12983,7 +12699,7 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@^2.2.0, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: +minipass@^2.2.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" integrity sha1-5xN2Ln0+Mv7YAxFc+T4EvKn8yaY= @@ -12998,13 +12714,6 @@ minipass@^3.0.0, minipass@^3.0.1, minipass@^3.1.0, minipass@^3.1.1: dependencies: yallist "^4.0.0" -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha1-IpDeloGKNMKVUcio0wEha9Zahh0= - dependencies: - minipass "^2.9.0" - minizlib@^2.0.0, minizlib@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3" @@ -13218,11 +12927,6 @@ mustache@^3.0.0: resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.1.tgz#873855f23aa8a95b150fb96d9836edbc5a1d248a" integrity sha1-hzhV8jqoqVsVD7ltmDbtvFodJIo= -mute-stream@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db" - integrity sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s= - mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -13341,7 +13045,7 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0: +node-fetch@^2.3.0, node-fetch@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha1-5jNFY4bUqlWGP2dqerDaqP3ssP0= @@ -13560,14 +13264,6 @@ npm-cache-filename@~1.0.2: resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11" integrity sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE= -npm-conf@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" - integrity sha1-JWzEe9DiGMJZxOlVC/QTvCGSr/k= - dependencies: - config-chain "^1.1.11" - pify "^3.0.0" - npm-install-checks@~3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.2.tgz#ab2e32ad27baa46720706908e5b14c1852de44d9" @@ -13933,11 +13629,6 @@ once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0, once@~1.4.0: dependencies: wrappy "1" -onetime@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" - integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= - onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -13985,18 +13676,6 @@ optionator@^0.8.1, optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" -ora@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" - integrity sha1-bK8oMOuSSUGGHsU6FzeZ4Ai1Hls= - dependencies: - chalk "^2.3.1" - cli-cursor "^2.1.0" - cli-spinners "^1.1.0" - log-symbols "^2.2.0" - strip-ansi "^4.0.0" - wcwidth "^1.0.1" - ora@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" @@ -14028,7 +13707,7 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0, os-homedir@^1.0.1: +os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= @@ -14096,13 +13775,6 @@ p-defer@^3.0.0: resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83" integrity sha1-0dzrTumytgSx2U/+yDdgF11Ob4M= -p-event@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" - integrity sha1-WWJ57xaassPgyuiMHPuwgHmZPvY= - dependencies: - p-timeout "^2.0.1" - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -14264,11 +13936,6 @@ pacote@~2.7.38: unique-filename "^1.1.0" which "^1.2.12" -pako@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= - pako@~1.0.5: version "1.0.10" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" @@ -14356,13 +14023,6 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -passwd-user@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/passwd-user/-/passwd-user-1.2.1.tgz#a01a5dc639ef007dc56364b8178569080ad3a7b8" - integrity sha1-oBpdxjnvAH3FY2S4F4VpCArTp7g= - dependencies: - exec-file-sync "^2.0.0" - path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" @@ -14483,15 +14143,6 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -peek-stream@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67" - integrity sha1-OzXYS3zLvSYv/zHcENpWhW6tbWc= - dependencies: - buffer-from "^1.0.0" - duplexify "^3.5.0" - through2 "^2.0.3" - pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -15462,7 +15113,7 @@ request-promise-native@^1.0.5: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.74.0, request@^2.81.0, request@^2.85.0, request@^2.87.0, request@^2.88.0: +request@^2.74.0, request@^2.81.0, request@^2.87.0, request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -15622,14 +15273,6 @@ restliparams@^1.0.1: dependencies: lodash "^4.17.5" -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -15800,11 +15443,6 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= - rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.5.3: version "6.5.4" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" @@ -15878,7 +15516,7 @@ sass@^1.21.0: dependencies: chokidar ">=2.0.0 <4.0.0" -sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: +sax@>=0.6.0, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha1-KBYjTiN4vdxOU1T6tcqold9xANk= @@ -16277,20 +15915,6 @@ socks@~2.3.2: ip "1.1.5" smart-buffer "^4.1.0" -sort-keys-length@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" - integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= - dependencies: - sort-keys "^1.0.0" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" - sort-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" @@ -16314,7 +15938,7 @@ sort-package-json@^1.39.1: globby "10.0.1" sort-object-keys "^1.1.3" -sorted-object@^2.0.1, sorted-object@~2.0.1: +sorted-object@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc" integrity sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw= @@ -16412,7 +16036,7 @@ spawn-args@^0.2.0: resolved "https://registry.yarnpkg.com/spawn-args/-/spawn-args-0.2.0.tgz#fb7d0bd1d70fd4316bd9e3dec389e65f9d6361bb" integrity sha1-+30L0dcP1DFr2ePew4nmX51jYbs= -spawn-sync@^1.0.11, spawn-sync@^1.0.15: +spawn-sync@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" integrity sha1-sAeZVX63+wyDdsKdROih6mfldHY= @@ -16779,13 +16403,6 @@ strip-json-comments@^3.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" integrity sha1-hXE5dakfuHvxswXMp3OV5A0qZKc= -strip-outer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" - integrity sha1-sv0qv2YEudHmATBXGV34Nrip1jE= - dependencies: - escape-string-regexp "^1.0.2" - styled_string@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/styled_string/-/styled_string-0.0.1.tgz#d22782bd81295459bc4f1df18c4bad8e94dd124a" @@ -16925,7 +16542,7 @@ tapable@^1.0.0, tapable@^1.1.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" integrity sha1-TSl5I8WnKkI2DeKrUtrfquwAAY4= -tar-fs@^1.15.3, tar-fs@^1.16.2: +tar-fs@^1.15.3: version "1.16.3" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== @@ -16957,19 +16574,6 @@ tar@^2.0.0, tar@~2.2.1: fstream "^1.0.12" inherits "2" -tar@^4.4.12: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha1-Q7NkvFKIjVVSmGN7ENYHkCVKtSU= - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - tar@^5.0.5: version "5.0.5" resolved "https://registry.yarnpkg.com/tar/-/tar-5.0.5.tgz#03fcdb7105bc8ea3ce6c86642b9c942495b04f93" @@ -17096,7 +16700,7 @@ throat@^4.1.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= -through2@^2.0.0, through2@^2.0.3: +through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0= @@ -17171,13 +16775,6 @@ tmp@0.1.0, tmp@^0.1.0: dependencies: rimraf "^2.6.3" -tmp@^0.0.29: - version "0.0.29" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" - integrity sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA= - dependencies: - os-tmpdir "~1.0.1" - tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -17325,13 +16922,6 @@ trim-newlines@^1.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= -trim-repeated@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" - integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= - dependencies: - escape-string-regexp "^1.0.2" - trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -17431,11 +17021,6 @@ type-detect@^1.0.0: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" integrity sha1-diIXzAbbJY7EiQihKY6LlRIejqI= -type-fest@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" - integrity sha1-Y9ANIE4FlHT+Xht8ARESu9HcKeE= - type-fest@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" @@ -17735,27 +17320,11 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8= -user-info@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/user-info/-/user-info-1.0.0.tgz#81c82b7ed63e674c2475667653413b3c76fde239" - integrity sha1-gcgrftY+Z0wkdWZ2U0E7PHb94jk= - dependencies: - os-homedir "^1.0.1" - passwd-user "^1.2.1" - username "^1.0.1" - username-sync@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/username-sync/-/username-sync-1.0.2.tgz#0a3697909fb7b5768d29e2921f573acfdd427592" integrity sha1-CjaXkJ+3tXaNKeKSH1c6z91CdZI= -username@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/username/-/username-1.0.1.tgz#e1f72295e3e58e06f002c6327ce06897a99cd67f" - integrity sha1-4fcilePljgbwAsYyfOBol6mc1n8= - dependencies: - meow "^3.4.0" - username@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/username/-/username-4.1.0.tgz#640f2ae13d17c51e7fb1d3517ad7c17fcd5d1670" @@ -18112,7 +17681,7 @@ worker-farm@~1.3.1: errno ">=0.1.1 <0.2.0-0" xtend ">=4.0.0 <4.1.0-0" -workerpool@^2.3.0, workerpool@^2.3.3: +workerpool@^2.3.0: version "2.3.3" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-2.3.3.tgz#49a70089bd55e890d68cc836a19419451d7c81d7" integrity sha1-SacAib1V6JDWjMg2oZQZRR18gdc= @@ -18245,13 +17814,6 @@ xdg-basedir@^4.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha1-S8jZmEQDaWIl74OhVzy7y0552xM= -xml-js@^1.6.8: - version "1.6.8" - resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.8.tgz#e06419c54235f18f4c2cdda824cbd65a782330de" - integrity sha1-4GQZxUI18Y9MLN2oJMvWWngjMN4= - dependencies: - sax "^1.2.4" - xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" @@ -18306,7 +17868,7 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.0, yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=