From 7f5688d6d02a5b48bfc28971f59b7b275a4f05aa Mon Sep 17 00:00:00 2001
From: Seyi Adebajo
Date: Mon, 13 Nov 2017 17:54:43 -0800
Subject: [PATCH] adds local type defs for ember concurrency. contraints the
return type for confirmOwner to the interface property. updates the remaining
owners required count on datasetauthors component. adds fixed height for
required count component
---
.../app/components/dataset-authors.ts | 23 ++++-
wherehows-web/app/constants/datasets/owner.ts | 4 +-
.../dataset-author/_dataset-author.scss | 4 +
.../templates/components/dataset-authors.hbs | 12 +--
.../app/typings/ember-concurrency.d.ts | 91 +++++++++++++++++++
.../app/typings/untyped-js-module.d.ts | 18 ----
.../app/utils/api/datasets/owners.ts | 48 +++++++---
7 files changed, 159 insertions(+), 41 deletions(-)
create mode 100644 wherehows-web/app/typings/ember-concurrency.d.ts
diff --git a/wherehows-web/app/components/dataset-authors.ts b/wherehows-web/app/components/dataset-authors.ts
index db9549f76e..dd3997a4b0 100644
--- a/wherehows-web/app/components/dataset-authors.ts
+++ b/wherehows-web/app/components/dataset-authors.ts
@@ -7,8 +7,18 @@ import { assert } from '@ember/debug';
import UserLookup from 'wherehows-web/services/user-lookup';
import CurrentUser from 'wherehows-web/services/current-user';
import { IOwner } from 'wherehows-web/typings/api/datasets/owners';
-import { ownerAlreadyExists, confirmOwner, updateOwner } from 'wherehows-web/constants/datasets/owner';
-import { isRequiredMinOwnersNotConfirmed, OwnerSource, OwnerType } from 'wherehows-web/utils/api/datasets/owners';
+import {
+ ownerAlreadyExists,
+ confirmOwner,
+ updateOwner,
+ minRequiredConfirmedOwners
+} from 'wherehows-web/constants/datasets/owner';
+import {
+ isRequiredMinOwnersNotConfirmed,
+ OwnerSource,
+ OwnerType,
+ validConfirmedOwners
+} from 'wherehows-web/utils/api/datasets/owners';
import Notifications, { NotificationEvent } from 'wherehows-web/services/notifications';
/**
@@ -79,6 +89,15 @@ export default class DatasetAuthors extends Component {
return isRequiredMinOwnersNotConfirmed(get(this, 'confirmedOwners'));
});
+ /**
+ * Counts the number of valid confirmed owners needed to make changes to the dataset
+ * @type {ComputedProperty}
+ * @memberof DatasetAuthors
+ */
+ ownersRequiredCount: ComputedProperty = computed('confirmedOwners.[]', function(this: DatasetAuthors) {
+ return minRequiredConfirmedOwners - validConfirmedOwners(get(this, 'confirmedOwners')).length;
+ });
+
/**
* Lists the owners that have be confirmed view the client ui
* @type {ComputedProperty>}
diff --git a/wherehows-web/app/constants/datasets/owner.ts b/wherehows-web/app/constants/datasets/owner.ts
index a97b746af1..114e8bf2fd 100644
--- a/wherehows-web/app/constants/datasets/owner.ts
+++ b/wherehows-web/app/constants/datasets/owner.ts
@@ -86,9 +86,9 @@ function updateOwner(
* Sets the `confirmedBy` attribute to the currently logged in user
* @param {IOwner} owner the owner to be updated
* @param {string} confirmedBy the userName of the confirming user
- * @returns {(Array | void)}
+ * @returns {IOwner.confirmedBy}
*/
-const confirmOwner = (owner: IOwner, confirmedBy: string): null | string =>
+const confirmOwner = (owner: IOwner, confirmedBy: string): IOwner['confirmedBy'] =>
set(owner, 'confirmedBy', confirmedBy || null);
/**
* Defines the default properties for a newly created IOwner instance
diff --git a/wherehows-web/app/styles/components/dataset-author/_dataset-author.scss b/wherehows-web/app/styles/components/dataset-author/_dataset-author.scss
index 7e4ecabb19..23aa697ac2 100644
--- a/wherehows-web/app/styles/components/dataset-author/_dataset-author.scss
+++ b/wherehows-web/app/styles/components/dataset-author/_dataset-author.scss
@@ -8,6 +8,10 @@ $owner-list-issue-color: set-color(red, maroonflush);
font-size: 20px;
font-weight: fw(normal, 4);
}
+
+ &__required-count {
+ height: item-spacing(4);
+ }
}
.dataset-author-record {
diff --git a/wherehows-web/app/templates/components/dataset-authors.hbs b/wherehows-web/app/templates/components/dataset-authors.hbs
index 71a9030041..8cc725ad5c 100644
--- a/wherehows-web/app/templates/components/dataset-authors.hbs
+++ b/wherehows-web/app/templates/components/dataset-authors.hbs
@@ -10,14 +10,14 @@
-{{#if requiredMinNotConfirmed}}
+
+ {{#if requiredMinNotConfirmed}}
-
- Add at least {{sub 2 confirmedOwners.length}} confirmed owner(s) with ID Type - USER
+ Add at least {{ownersRequiredCount}} owner(s) with ID Type - USER
and Owner Type - Owner
-
-{{/if}}
+ {{/if}}
+
@@ -92,7 +92,7 @@
- These are dataset ownership records, suggested based information derived from the source metadata.
+ These are dataset ownership records, suggested based on information derived from the source metadata.
diff --git a/wherehows-web/app/typings/ember-concurrency.d.ts b/wherehows-web/app/typings/ember-concurrency.d.ts
new file mode 100644
index 0000000000..de0d70dfd5
--- /dev/null
+++ b/wherehows-web/app/typings/ember-concurrency.d.ts
@@ -0,0 +1,91 @@
+declare module 'ember-concurrency' {
+ export function timeout(delay: number): Promise;
+ import ComputedProperty from '@ember/object/computed';
+ import RSVP from 'rsvp';
+
+ export enum TaskInstanceState {
+ Dropped = 'dropped',
+ Canceled = 'canceled',
+ Finished = 'finished',
+ Running = 'running',
+ Waiting = 'waiting'
+ }
+
+ export interface TaskProperty extends ComputedProperty {
+ cancelOn(eventNames: string[]): this;
+ debug(): this;
+ drop(): this;
+ enqueue(): this;
+ group(groupPath: string): this;
+ keepLatest(): this;
+ maxConcurrency(n: number): this;
+ on(eventNames: string[]): this;
+ restartable(): this;
+ }
+
+ export interface TaskInstance extends PromiseLike {
+ readonly error?: any;
+ readonly hasStarted: ComputedProperty;
+ readonly isCanceled: ComputedProperty;
+ readonly isDropped: ComputedProperty;
+ readonly isError: ComputedProperty;
+ readonly isFinished: ComputedProperty;
+ readonly isRunning: ComputedProperty;
+ readonly isSuccessful: ComputedProperty;
+ readonly state: ComputedProperty;
+ readonly value?: T;
+ cancel(): void;
+ catch: () => RSVP.Promise;
+ finally: () => RSVP.Promise;
+ then(
+ onfulfilled?: ((value: T) => TResult1 | RSVP.Promise) | undefined | null,
+ onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null
+ ): RSVP.Promise;
+ }
+
+ export enum TaskState {
+ Running = 'running',
+ Queued = 'queued',
+ Idle = 'idle'
+ }
+
+ type Task = TaskProperty &
+ ComputedProperty<{ perform: P }> & {
+ readonly isIdle: boolean;
+ readonly isQueued: boolean;
+ readonly isRunning: boolean;
+ readonly last?: TaskInstance;
+ readonly lastCanceled?: TaskInstance;
+ readonly lastComplete?: TaskInstance;
+ readonly lastErrored?: TaskInstance;
+ readonly lastIncomplete?: TaskInstance;
+ readonly lastPerformed?: TaskInstance;
+ readonly lastRunning?: TaskInstance;
+ readonly lastSuccessful?: TaskInstance;
+ readonly performCount: number;
+ readonly state: TaskState;
+ cancelAll(): void;
+ };
+
+ export function task(generatorFn: (a: A) => Iterator): Task TaskInstance>;
+
+ export function task(
+ generatorFn: (a1: A1, a2: A2) => Iterator
+ ): Task TaskInstance>;
+
+ export function task(
+ generatorFn: (a1: A1, a2: A2, a3: A3) => Iterator
+ ): Task TaskInstance>;
+
+ export function task(
+ generatorFn: (a1: A1, a2: A2, a3: A3, a4: A4) => Iterator
+ ): Task TaskInstance>;
+
+ export function task(
+ generatorFn: (a1: A1, a2: A2, a3: A3, a4: A4, a5: A5) => Iterator
+ ): Task TaskInstance>;
+
+ export function task(
+ generatorFn: (a1: A1, a2: A2, a3: A3, a4: A4, a6: A6) => Iterator
+ ): Task TaskInstance>;
+}
diff --git a/wherehows-web/app/typings/untyped-js-module.d.ts b/wherehows-web/app/typings/untyped-js-module.d.ts
index d7b9ef5257..8ef543215b 100644
--- a/wherehows-web/app/typings/untyped-js-module.d.ts
+++ b/wherehows-web/app/typings/untyped-js-module.d.ts
@@ -23,24 +23,6 @@ declare module 'wherehows-web/utils/datasets/compliance-policy';
declare module 'ember-cli-mirage';
-declare module 'ember-concurrency' {
- class TaskInstance {}
- class TaskProperty {
- perform(...args: Array): TaskInstance;
- on(): this;
- cancelOn(eventNames: string): this;
- debug(): this;
- drop(): this;
- restartable(): this;
- enqueue(): this;
- keepLatest(): this;
- performs(): this;
- maxConcurrency(n: number): this;
- }
- export function task(...args: Array): TaskProperty;
- export function timeout(delay: number): Promise;
-}
-
// https://github.com/ember-cli/ember-fetch/issues/72
// TS assumes the mapping btw ES modules and CJS modules is 1:1
// However, `ember-fetch` is the module name, but it's imported with `fetch`
diff --git a/wherehows-web/app/utils/api/datasets/owners.ts b/wherehows-web/app/utils/api/datasets/owners.ts
index 9f43f4a7ec..1a053086c9 100644
--- a/wherehows-web/app/utils/api/datasets/owners.ts
+++ b/wherehows-web/app/utils/api/datasets/owners.ts
@@ -12,7 +12,7 @@ import { getJSON, postJSON } from 'wherehows-web/utils/api/fetcher';
/**
* Defines a string enum for valid owner types
*/
-export enum OwnerIdType {
+enum OwnerIdType {
User = 'USER',
Group = 'GROUP'
}
@@ -21,7 +21,7 @@ export enum OwnerIdType {
* Defines the string enum for the OwnerType attribute
* @type {string}
*/
-export enum OwnerType {
+enum OwnerType {
Owner = 'Owner',
Consumer = 'Consumer',
Delegate = 'Delegate',
@@ -32,12 +32,12 @@ export enum OwnerType {
/**
* Accepted string values for the namespace of a user
*/
-export enum OwnerUrnNamespace {
+enum OwnerUrnNamespace {
corpUser = 'urn:li:corpuser',
groupUser = 'urn:li:corpGroup'
}
-export enum OwnerSource {
+enum OwnerSource {
Scm = 'SCM',
Nuage = 'NUAGE',
Sos = 'SOS',
@@ -71,7 +71,7 @@ const partyEntitiesUrl = `${ApiRoot}/party/entities`;
* @param {number} id the dataset Id
* @return {Promise>} the current list of dataset owners
*/
-export const readDatasetOwners = async (id: number): Promise> => {
+const readDatasetOwners = async (id: number): Promise> => {
const { owners = [], status, msg } = await getJSON({ url: datasetOwnersUrlById(id) });
if (status === ApiStatus.OK) {
return owners.map(owner => ({
@@ -90,7 +90,7 @@ export const readDatasetOwners = async (id: number): Promise> => {
* @param {Array} updatedOwners the updated list of owners for this dataset
* @return {Promise}
*/
-export const updateDatasetOwners = async (
+const updateDatasetOwners = async (
id: number,
csrfToken: string,
updatedOwners: Array
@@ -115,7 +115,7 @@ export const updateDatasetOwners = async (
* Requests party entities and if the response status is OK, resolves with an array of entities
* @return {Promise>}
*/
-export const readPartyEntities = async (): Promise> => {
+const readPartyEntities = async (): Promise> => {
const { status, userEntities = [], msg } = await getJSON({ url: partyEntitiesUrl });
return status === ApiStatus.OK ? userEntities : Promise.reject(msg);
};
@@ -127,7 +127,7 @@ export const readPartyEntities = async (): Promise> => {
* userEntitiesSource property is also lazy evaluated and cached for app lifetime.
* @type {() => Promise}
*/
-export const getUserEntities: () => Promise = (() => {
+const getUserEntities: () => Promise = (() => {
/**
* Memoized reference to the resolved value of a previous invocation to curried function in getUserEntities
* @type {{result: IPartyProps | null}}
@@ -177,18 +177,40 @@ export const getUserEntities: () => Promise = (() => {
* @param {Array} partyEntities
* @return {IUserEntityMap}
*/
-export const readPartyEntitiesMap = (partyEntities: Array): IUserEntityMap =>
+const readPartyEntitiesMap = (partyEntities: Array): IUserEntityMap =>
partyEntities.reduce(
(map: { [label: string]: string }, { label, displayName }: IPartyEntity) => ((map[label] = displayName), map),
{}
);
+/**
+ * Filters out a list of valid confirmed owners in a list of owners
+ * @param {Array} [owners=[]] the owners to filter
+ * @returns {Array}
+ */
+const validConfirmedOwners = (owners: Array = []): Array =>
+ owners.filter(
+ ({ confirmedBy, type, idType }) => confirmedBy && type === OwnerType.Owner && idType === OwnerIdType.User
+ );
+
/**
* Checks that the required minimum number of confirmed users is met with the type Owner and idType User
* @param {Array} owners the list of owners to check
* @return {boolean}
*/
-export const isRequiredMinOwnersNotConfirmed = (owners: Array = []): boolean =>
- owners.filter(
- ({ confirmedBy, type, idType }) => confirmedBy && type === OwnerType.Owner && idType === OwnerIdType.User
- ).length < minRequiredConfirmed;
+const isRequiredMinOwnersNotConfirmed = (owners: Array = []): boolean =>
+ validConfirmedOwners(owners).length < minRequiredConfirmed;
+
+export {
+ validConfirmedOwners,
+ isRequiredMinOwnersNotConfirmed,
+ readDatasetOwners,
+ readPartyEntities,
+ readPartyEntitiesMap,
+ getUserEntities,
+ updateDatasetOwners,
+ OwnerIdType,
+ OwnerType,
+ OwnerUrnNamespace,
+ OwnerSource
+};