Merge pull request #1029 from theseyi/resolved-ownership

resolved ownership
This commit is contained in:
Seyi Adebajo 2018-03-13 11:14:57 -07:00 committed by GitHub
commit 701824cc2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 234 additions and 21 deletions

View File

@ -1,12 +1,12 @@
import Component from '@ember/component';
import { get, set, getProperties } from '@ember/object';
import { get, set, getProperties, setProperties } from '@ember/object';
import ComputedProperty from '@ember/object/computed';
import { inject } from '@ember/service';
import { task, TaskInstance } from 'ember-concurrency';
import { action } from 'ember-decorators/object';
import Notifications from 'wherehows-web/services/notifications';
import { NotificationEvent } from 'wherehows-web/services/notifications';
import { IOwner } from 'wherehows-web/typings/api/datasets/owners';
import { IOwner, IOwnerResponse } from 'wherehows-web/typings/api/datasets/owners';
import {
OwnerType,
readDatasetOwnersByUrn,
@ -39,6 +39,18 @@ export default class DatasetOwnershipContainer extends Component {
*/
notifications: ComputedProperty<Notifications> = inject();
/**
* Flag indicates that a ownership metadata is inherited from an upstream dataset
* @type {boolean}
*/
fromUpstream = false;
/**
* Reference to the upstream dataset
* @type {string}
*/
upstreamUrn: string;
didInsertElement() {
get(this, 'getContainerDataTask').perform();
}
@ -59,12 +71,12 @@ export default class DatasetOwnershipContainer extends Component {
/**
* Reads the owners for this dataset
* @type {Task<Promise<Array<IOwner>>, (a?: any) => TaskInstance<Promise<Array<IOwner>>>>}
* @type {Task<Promise<Array<IOwner>>, (a?: any) => TaskInstance<Promise<IOwnerResponse>>>}
*/
getDatasetOwnersTask = task(function*(this: DatasetOwnershipContainer): IterableIterator<Promise<Array<IOwner>>> {
const owners = yield readDatasetOwnersByUrn(get(this, 'urn'));
getDatasetOwnersTask = task(function*(this: DatasetOwnershipContainer): IterableIterator<Promise<IOwnerResponse>> {
const { owners, fromUpstream, datasetUrn } = yield readDatasetOwnersByUrn(get(this, 'urn'));
set(this, 'owners', owners);
setProperties(this, { owners, fromUpstream, upstreamUrn: datasetUrn });
});
/**

View File

@ -0,0 +1,48 @@
import Component from '@ember/component';
import { task } from 'ember-concurrency';
import { get, set } from '@ember/object';
import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset';
import { assert } from '@ember/debug';
import { readDatasetByUrn } from 'wherehows-web/utils/api/datasets/dataset';
export default class UpstreamOwners extends Component {
/**
* urn for the parent dataset
* @type {string}
* @memberof UpstreamOwners
*/
upstreamUrn: string;
/**
* The name of the upstream dataset
* @type {IDatasetView.nativeName}
* @memberof UpstreamOwners
*/
nativeName: IDatasetView['nativeName'];
constructor() {
super(...arguments);
assert('A valid upstreamUrn must be provided on instantiation', typeof this.upstreamUrn === 'string');
}
didUpdateAttrs() {
this._super(...arguments);
get(this, 'getUpstreamPropertiesTask').perform();
}
didInsertElement() {
this._super(...arguments);
get(this, 'getUpstreamPropertiesTask').perform();
}
/**
* Task to get properties for the upstream dataset
* @type {Task<Promise<IDatasetView>>, (a?: {} | undefined) => TaskInstance<Promise<IDatasetView>>>}
* @memberof UpstreamOwners
*/
getUpstreamPropertiesTask = task(function*(this: UpstreamOwners): IterableIterator<Promise<IDatasetView>> {
const { nativeName }: IDatasetView = yield readDatasetByUrn(get(this, 'upstreamUrn'));
set(this, 'nativeName', nativeName);
});
}

View File

@ -0,0 +1,7 @@
import Component from '@ember/component';
export default class extends Component {
tagName = 'section';
classNames = ['upstream-owners-banner'];
}

View File

@ -4,7 +4,7 @@ import { inject } from '@ember/service';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
import { featureEntryPoints } from 'wherehows-web/constants/application';
const { browse, scriptFinder, schemaHistory, idpc } = featureEntryPoints;
const { browse, scriptFinder, schemaHistory } = featureEntryPoints;
export default Route.extend(AuthenticatedRouteMixin, {
/**
@ -26,7 +26,7 @@ export default Route.extend(AuthenticatedRouteMixin, {
model() {
// Static list of content for the index route featureCard links
return [browse, scriptFinder, schemaHistory, idpc];
return [browse, scriptFinder, schemaHistory];
},
/**
* Perform post model operations

View File

@ -20,6 +20,7 @@
@import 'dataset-acl-access/all';
@import 'ivy-tabs/all';
@import 'upstream-dataset/all';
@import 'upstream-owners/all';
@import 'nacho/nacho-button';
@import 'nacho/nacho-global-search';

View File

@ -30,5 +30,5 @@ $feature-card-image-size: 50px !default;
/// Wrap cards in containers with 1:1 ar
.feature-container {
@include aspect-ratio(1, 1);
@include aspect-ratio(1, 0.5);
}

View File

@ -0,0 +1 @@
@import 'upstream-owners';

View File

@ -0,0 +1,17 @@
.upstream-owners-banner {
@include nacho-container;
display: flex;
flex-direction: row;
align-items: center;
&__informational {
display: flex;
flex-direction: row;
align-items: center;
&__text {
margin: 0;
padding: item-spacing(2);
}
}
}

View File

@ -24,11 +24,19 @@
{{else}}
{{dataset-authors
owners=owners
ownerTypes=ownerTypes
save=(action "saveOwnerChanges")
}}
{{#if fromUpstream}}
{{datasets/containers/upstream-owners upstreamUrn=upstreamUrn}}
{{else}}
{{dataset-authors
owners=owners
ownerTypes=ownerTypes
save=(action "saveOwnerChanges")
}}
{{/if}}
{{/if}}

View File

@ -0,0 +1,12 @@
{{#if getUpstreamPropertiesTask.isRunning}}
{{pendulum-ellipsis-animation}}
{{else}}
{{datasets/upstream-owners
nativeName=nativeName
upstreamUrn=upstreamUrn
}}
{{/if}}

View File

@ -0,0 +1,22 @@
<section class="upstream-owners-banner__content">
<div class="upstream-owners-banner__informational">
<i class="fa fa-info-circle fa-2x"></i>
<p class="upstream-owners-banner__informational__text">
Ownership metadata for this dataset is inherited from a parent dataset.
<br>
To make modifications, please update the Ownership on the parent dataset.
<br>
</p>
</div>
<header class="upstream-owners-banner__title">
Parent Dataset Name:
{{#link-to
"datasets.dataset"
upstreamUrn
}}
<strong>{{nativeName}}</strong>
{{/link-to}}
</header>
</section>

View File

@ -2,7 +2,7 @@
<div class="container">
<div class="row">
{{#each model as |featureCard|}}
<div class="col-md-3">
<div class="col-md-4">
<div class="feature-container">
<article class="feature-card">
{{#link-to featureCard.route}}

View File

@ -34,7 +34,6 @@
<ul class="dropdown-menu" role="menu">
{{#nav-link 'scripts' tagName="li"}}Script Finder{{/nav-link}}
{{#nav-link 'schemahistory' tagName="li"}}Schema History{{/nav-link}}
{{#nav-link 'idpc' tagName="li"}}IDPC{{/nav-link}}
</ul>
</li>

View File

@ -94,15 +94,17 @@ const ownersWithModifiedTimeAsDate = arrayMap(ownerWithModifiedTimeAsDate);
* @param {string} urn
* @return {Promise<Array<IOwner>>}
*/
const readDatasetOwnersByUrn = async (urn: string): Promise<Array<IOwner>> => {
let owners: Array<IOwner> = [];
const readDatasetOwnersByUrn = async (urn: string): Promise<IOwnerResponse> => {
let owners: Array<IOwner> = [],
fromUpstream = false,
datasetUrn = '';
try {
({ owners = [] } = await getJSON<Pick<IOwnerResponse, 'owners'>>({ url: datasetOwnersUrlByUrn(urn) }));
return ownersWithModifiedTimeAsDate(owners);
({ owners = [], fromUpstream, datasetUrn } = await getJSON<IOwnerResponse>({ url: datasetOwnersUrlByUrn(urn) }));
return { owners: ownersWithModifiedTimeAsDate(owners), fromUpstream, datasetUrn };
} catch (e) {
if (notFoundApiError(e)) {
return owners;
return { owners, fromUpstream, datasetUrn };
} else {
throw e;
}

View File

@ -0,0 +1,46 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { hdfsUrn } from 'wherehows-web/mirage/fixtures/urn';
import sinon from 'sinon';
import { waitUntil, find } from 'ember-native-dom-helpers';
moduleForComponent(
'datasets/containers/upstream-owners',
'Integration | Component | datasets/containers/upstream owners',
{
integration: true,
beforeEach() {
this.server = sinon.createFakeServer();
this.server.respondImmediately = true;
},
afterEach() {
this.server.restore();
}
}
);
test('it renders', async function(assert) {
const titleElementQuery = '.upstream-owners-banner__title strong';
const nativeName = 'A nativeName';
this.set('upstreamUrn', hdfsUrn);
this.server.respondWith(/\/api\/v2\/datasets.*/, async function(xhr) {
xhr.respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify({
dataset: {
nativeName
}
})
);
});
this.render(hbs`{{datasets/containers/upstream-owners upstreamUrn=upstreamUrn}}`);
await waitUntil(() => find(titleElementQuery));
assert.equal(find(titleElementQuery).textContent.trim(), nativeName);
});

View File

@ -0,0 +1,38 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { hdfsUrn, nonHdfsUrn } from 'wherehows-web/mirage/fixtures/urn';
moduleForComponent('datasets/upstream-owners', 'Integration | Component | datasets/upstream owners', {
integration: true
});
test('it renders', function(assert) {
this.render(hbs`{{datasets/upstream-owners}}`);
assert.ok(document.querySelector('.upstream-owners-banner'), 'renders upstream-dataset as expected');
});
test('rendering nativeName', function(assert) {
const titleElementQuery = '.upstream-owners-banner__title strong';
const nativeName = 'Upstream Dataset';
this.set('nativeName', nativeName);
this.render(hbs`{{datasets/upstream-owners nativeName=nativeName}}`);
assert.ok(
document
.querySelector(titleElementQuery)
.textContent.trim()
.includes(nativeName),
'it renders upstream ownership properties'
);
});
test('link to upstream dataset', function(assert) {
this.set('upstreamUrn', hdfsUrn);
this.render(hbs`{{datasets/upstream-owners upstreamUrn=upstreamUrn}}`);
assert.ok(document.querySelector('.upstream-owners-banner a'), 'it creates a link to the upstream dataset');
});