mirror of
https://github.com/datahub-project/datahub.git
synced 2025-08-30 03:56:04 +00:00
Merge pull request #860 from theseyi/ownership-deux
adds local type defs for ember concurrency. contraints the return typ…
This commit is contained in:
commit
e3a87e02d3
@ -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<number>}
|
||||
* @memberof DatasetAuthors
|
||||
*/
|
||||
ownersRequiredCount: ComputedProperty<number> = 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<Array<IOwner>>}
|
||||
|
@ -86,9 +86,9 @@ function updateOwner<K extends keyof IOwner>(
|
||||
* 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<IOwner> | 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
|
||||
|
@ -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 {
|
||||
|
@ -10,14 +10,14 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{#if requiredMinNotConfirmed}}
|
||||
<p class="dataset-author__required-count">
|
||||
{{#if requiredMinNotConfirmed}}
|
||||
|
||||
<p>
|
||||
Add <strong>at least {{sub 2 confirmedOwners.length}}</strong> confirmed owner(s) with ID Type - <code>USER</code>
|
||||
Add <strong>at least {{ownersRequiredCount}}</strong> owner(s) with ID Type - <code>USER</code>
|
||||
and Owner Type - <code>Owner</code>
|
||||
</p>
|
||||
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</p>
|
||||
|
||||
<section class="dataset-author">
|
||||
<header>
|
||||
@ -92,7 +92,7 @@
|
||||
</h2>
|
||||
|
||||
<p class="dataset-author__byline">
|
||||
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.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
|
91
wherehows-web/app/typings/ember-concurrency.d.ts
vendored
Normal file
91
wherehows-web/app/typings/ember-concurrency.d.ts
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
declare module 'ember-concurrency' {
|
||||
export function timeout(delay: number): Promise<void>;
|
||||
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<T> extends ComputedProperty<T> {
|
||||
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<T> extends PromiseLike<T> {
|
||||
readonly error?: any;
|
||||
readonly hasStarted: ComputedProperty<boolean>;
|
||||
readonly isCanceled: ComputedProperty<boolean>;
|
||||
readonly isDropped: ComputedProperty<boolean>;
|
||||
readonly isError: ComputedProperty<boolean>;
|
||||
readonly isFinished: ComputedProperty<boolean>;
|
||||
readonly isRunning: ComputedProperty<boolean>;
|
||||
readonly isSuccessful: ComputedProperty<boolean>;
|
||||
readonly state: ComputedProperty<TaskInstanceState>;
|
||||
readonly value?: T;
|
||||
cancel(): void;
|
||||
catch: () => RSVP.Promise<any>;
|
||||
finally: () => RSVP.Promise<any>;
|
||||
then<TResult1 = T, TResult2 = never>(
|
||||
onfulfilled?: ((value: T) => TResult1 | RSVP.Promise<TResult1>) | undefined | null,
|
||||
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
|
||||
): RSVP.Promise<TResult1 | TResult2>;
|
||||
}
|
||||
|
||||
export enum TaskState {
|
||||
Running = 'running',
|
||||
Queued = 'queued',
|
||||
Idle = 'idle'
|
||||
}
|
||||
|
||||
type Task<T, P> = TaskProperty<T> &
|
||||
ComputedProperty<{ perform: P }> & {
|
||||
readonly isIdle: boolean;
|
||||
readonly isQueued: boolean;
|
||||
readonly isRunning: boolean;
|
||||
readonly last?: TaskInstance<T>;
|
||||
readonly lastCanceled?: TaskInstance<T>;
|
||||
readonly lastComplete?: TaskInstance<T>;
|
||||
readonly lastErrored?: TaskInstance<T>;
|
||||
readonly lastIncomplete?: TaskInstance<T>;
|
||||
readonly lastPerformed?: TaskInstance<T>;
|
||||
readonly lastRunning?: TaskInstance<T>;
|
||||
readonly lastSuccessful?: TaskInstance<T>;
|
||||
readonly performCount: number;
|
||||
readonly state: TaskState;
|
||||
cancelAll(): void;
|
||||
};
|
||||
|
||||
export function task<T, A>(generatorFn: (a: A) => Iterator<T>): Task<T, (a: A) => TaskInstance<T>>;
|
||||
|
||||
export function task<T, A1, A2>(
|
||||
generatorFn: (a1: A1, a2: A2) => Iterator<T>
|
||||
): Task<T, (a1: A1, a2: A2) => TaskInstance<T>>;
|
||||
|
||||
export function task<T, A1, A2, A3>(
|
||||
generatorFn: (a1: A1, a2: A2, a3: A3) => Iterator<T>
|
||||
): Task<T, (a1: A1, a2: A2, a3: A3) => TaskInstance<T>>;
|
||||
|
||||
export function task<T, A1, A2, A3, A4>(
|
||||
generatorFn: (a1: A1, a2: A2, a3: A3, a4: A4) => Iterator<T>
|
||||
): Task<T, (a1: A1, a2: A2, a3: A3, a4: A4) => TaskInstance<T>>;
|
||||
|
||||
export function task<T, A1, A2, A3, A4, A5>(
|
||||
generatorFn: (a1: A1, a2: A2, a3: A3, a4: A4, a5: A5) => Iterator<T>
|
||||
): Task<T, (a1: A1, a2: A2, a3: A3, a4: A4, a5: A5) => TaskInstance<T>>;
|
||||
|
||||
export function task<T, A1, A2, A3, A4, A5, A6>(
|
||||
generatorFn: (a1: A1, a2: A2, a3: A3, a4: A4, a6: A6) => Iterator<T>
|
||||
): Task<T, (a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6) => TaskInstance<T>>;
|
||||
}
|
18
wherehows-web/app/typings/untyped-js-module.d.ts
vendored
18
wherehows-web/app/typings/untyped-js-module.d.ts
vendored
@ -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<any>): 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<any>): TaskProperty;
|
||||
export function timeout(delay: number): Promise<void>;
|
||||
}
|
||||
|
||||
// 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`
|
||||
|
@ -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<Array<IOwner>>} the current list of dataset owners
|
||||
*/
|
||||
export const readDatasetOwners = async (id: number): Promise<Array<IOwner>> => {
|
||||
const readDatasetOwners = async (id: number): Promise<Array<IOwner>> => {
|
||||
const { owners = [], status, msg } = await getJSON<IOwnerResponse>({ url: datasetOwnersUrlById(id) });
|
||||
if (status === ApiStatus.OK) {
|
||||
return owners.map(owner => ({
|
||||
@ -90,7 +90,7 @@ export const readDatasetOwners = async (id: number): Promise<Array<IOwner>> => {
|
||||
* @param {Array<IOwner>} updatedOwners the updated list of owners for this dataset
|
||||
* @return {Promise<IOwnerPostResponse>}
|
||||
*/
|
||||
export const updateDatasetOwners = async (
|
||||
const updateDatasetOwners = async (
|
||||
id: number,
|
||||
csrfToken: string,
|
||||
updatedOwners: Array<IOwner>
|
||||
@ -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<Array<IPartyEntity>>}
|
||||
*/
|
||||
export const readPartyEntities = async (): Promise<Array<IPartyEntity>> => {
|
||||
const readPartyEntities = async (): Promise<Array<IPartyEntity>> => {
|
||||
const { status, userEntities = [], msg } = await getJSON<IPartyEntityResponse>({ url: partyEntitiesUrl });
|
||||
return status === ApiStatus.OK ? userEntities : Promise.reject(msg);
|
||||
};
|
||||
@ -127,7 +127,7 @@ export const readPartyEntities = async (): Promise<Array<IPartyEntity>> => {
|
||||
* userEntitiesSource property is also lazy evaluated and cached for app lifetime.
|
||||
* @type {() => Promise<IPartyProps>}
|
||||
*/
|
||||
export const getUserEntities: () => Promise<IPartyProps> = (() => {
|
||||
const getUserEntities: () => Promise<IPartyProps> = (() => {
|
||||
/**
|
||||
* 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<IPartyProps> = (() => {
|
||||
* @param {Array<IPartyEntity>} partyEntities
|
||||
* @return {IUserEntityMap}
|
||||
*/
|
||||
export const readPartyEntitiesMap = (partyEntities: Array<IPartyEntity>): IUserEntityMap =>
|
||||
const readPartyEntitiesMap = (partyEntities: Array<IPartyEntity>): 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<IOwner>} [owners=[]] the owners to filter
|
||||
* @returns {Array<IOwner>}
|
||||
*/
|
||||
const validConfirmedOwners = (owners: Array<IOwner> = []): Array<IOwner> =>
|
||||
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<IOwner>} owners the list of owners to check
|
||||
* @return {boolean}
|
||||
*/
|
||||
export const isRequiredMinOwnersNotConfirmed = (owners: Array<IOwner> = []): boolean =>
|
||||
owners.filter(
|
||||
({ confirmedBy, type, idType }) => confirmedBy && type === OwnerType.Owner && idType === OwnerIdType.User
|
||||
).length < minRequiredConfirmed;
|
||||
const isRequiredMinOwnersNotConfirmed = (owners: Array<IOwner> = []): boolean =>
|
||||
validConfirmedOwners(owners).length < minRequiredConfirmed;
|
||||
|
||||
export {
|
||||
validConfirmedOwners,
|
||||
isRequiredMinOwnersNotConfirmed,
|
||||
readDatasetOwners,
|
||||
readPartyEntities,
|
||||
readPartyEntitiesMap,
|
||||
getUserEntities,
|
||||
updateDatasetOwners,
|
||||
OwnerIdType,
|
||||
OwnerType,
|
||||
OwnerUrnNamespace,
|
||||
OwnerSource
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user