mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-11 08:52:58 +00:00
Merge pull request #1427 from theseyi/obfuscation-feedback-ui
obfuscation feedback ui: accepting none should replace multi tagged field with single none tag
This commit is contained in:
commit
fc6cbcff5f
@ -1,5 +1,5 @@
|
||||
import Component from '@ember/component';
|
||||
import { IAvatar, IAvatarDropDownAction } from 'wherehows-web/typings/app/avatars';
|
||||
import { IAvatar } from 'wherehows-web/typings/app/avatars';
|
||||
import { action, computed } from '@ember-decorators/object';
|
||||
import { IDropDownOption } from 'wherehows-web/typings/app/dataset-compliance';
|
||||
import { classNames } from '@ember-decorators/component';
|
||||
@ -18,6 +18,12 @@ export default class StackedAvatarsList extends Component {
|
||||
*/
|
||||
avatars: Array<IAvatar>;
|
||||
|
||||
/**
|
||||
* External action to selection of an avatar's menu option
|
||||
* @type {(avatar: IAvatar, option?: IDropDownOption<any>) => any}
|
||||
*/
|
||||
handleAvatarOptionSelection: (avatar: IAvatar, option?: IDropDownOption<any>) => any;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
@ -64,13 +70,11 @@ export default class StackedAvatarsList extends Component {
|
||||
/**
|
||||
* Handler to invoke IAvatarDropDownAction instance when the drop down option is selected
|
||||
* @param {IAvatar} avatar the avatar item selected from the list
|
||||
* @param {(IDropDownOption<IAvatarDropDownAction> | void)} selectedOption drop down option selected
|
||||
* @param {(IDropDownOption<any>)} [selectedOption] drop down option selected
|
||||
* @memberof StackedAvatarsList
|
||||
*/
|
||||
@action
|
||||
onAvatarOptionSelected(avatar: IAvatar, selectedOption: IDropDownOption<IAvatarDropDownAction> | void): void {
|
||||
const { value } = selectedOption || { value: (a: IAvatar) => a };
|
||||
|
||||
value(avatar);
|
||||
onAvatarOptionSelected(avatar: IAvatar, selectedOption?: IDropDownOption<any>): void {
|
||||
this.handleAvatarOptionSelection(avatar, selectedOption);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import { get, set } from '@ember/object';
|
||||
import ComputedProperty, { gte } from '@ember/object/computed';
|
||||
import { TaskInstance, TaskProperty } from 'ember-concurrency';
|
||||
import { action, computed } from '@ember-decorators/object';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
IAccessControlAccessTypeOption,
|
||||
IAccessControlEntry,
|
||||
@ -12,8 +13,7 @@ import { getDefaultRequestAccessControlEntry } from 'wherehows-web/utils/dataset
|
||||
import { IAvatar } from 'wherehows-web/typings/app/avatars';
|
||||
import { arrayMap } from 'wherehows-web/utils/array';
|
||||
import { IAppConfig } from 'wherehows-web/typings/api/configurator/configurator';
|
||||
import { getAvatarProps } from 'wherehows-web/constants/avatars/avatars';
|
||||
import moment from 'moment';
|
||||
import { makeAvatar } from 'wherehows-web/constants/avatars/avatars';
|
||||
|
||||
/**
|
||||
* Date object with the minimum selectable date for acl request expiration,
|
||||
@ -141,7 +141,7 @@ export default class DatasetAclAccess extends Component {
|
||||
const { acls, avatarProperties } = this;
|
||||
const aclWithAvatar = (acl: IAccessControlEntry): IAccessControlEntry & Record<'avatar', IAvatar> => ({
|
||||
...acl,
|
||||
avatar: getAvatarProps(avatarProperties!)({ userName: acl.principal })
|
||||
avatar: makeAvatar(avatarProperties!)({ userName: acl.principal })
|
||||
});
|
||||
|
||||
return avatarProperties ? arrayMap(aclWithAvatar)(acls) : [];
|
||||
|
||||
@ -22,7 +22,7 @@ import { OwnerSource, OwnerType } from 'wherehows-web/utils/api/datasets/owners'
|
||||
import Notifications, { NotificationEvent } from 'wherehows-web/services/notifications';
|
||||
import { noop } from 'wherehows-web/utils/helpers/functions';
|
||||
import { IAppConfig } from 'wherehows-web/typings/api/configurator/configurator';
|
||||
import { getAvatarProps } from 'wherehows-web/constants/avatars/avatars';
|
||||
import { makeAvatar } from 'wherehows-web/constants/avatars/avatars';
|
||||
import { OwnerWithAvatarRecord } from 'wherehows-web/typings/app/datasets/owners';
|
||||
|
||||
type Comparator = -1 | 0 | 1;
|
||||
@ -177,7 +177,7 @@ export default class DatasetAuthors extends Component {
|
||||
return {
|
||||
owner,
|
||||
avatar: avatarProperties
|
||||
? getAvatarProps(avatarProperties)({ userName: owner.userName })
|
||||
? makeAvatar(avatarProperties)({ userName: owner.userName })
|
||||
: { imageUrl: '', imageUrlFallback: '/assets/assets/images/default_avatar.png' }
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Component from '@ember/component';
|
||||
import ComputedProperty, { alias, equal, bool, mapBy } from '@ember/object/computed';
|
||||
import ComputedProperty, { equal, bool, mapBy } from '@ember/object/computed';
|
||||
import { get, getWithDefault, getProperties, computed } from '@ember/object';
|
||||
import { action } from '@ember-decorators/object';
|
||||
import {
|
||||
@ -21,8 +21,9 @@ import { getTagSuggestions } from 'wherehows-web/utils/datasets/compliance-sugge
|
||||
import { IColumnFieldProps } from 'wherehows-web/typings/app/dataset-columns';
|
||||
import { fieldTagsHaveIdentifierType } from 'wherehows-web/constants/dataset-compliance';
|
||||
import { IComplianceDataType } from 'wherehows-web/typings/api/list/compliance-datatypes';
|
||||
import { arrayReduce } from 'wherehows-web/utils/array';
|
||||
import { arrayEach, arrayReduce } from 'wherehows-web/utils/array';
|
||||
import { IComplianceEntity } from 'wherehows-web/typings/api/datasets/compliance';
|
||||
import { alias } from '@ember-decorators/object/computed';
|
||||
|
||||
export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
tagName: ''
|
||||
@ -118,7 +119,8 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
* @type {ComputedProperty<string>}
|
||||
* @memberof DatasetComplianceRollupRow
|
||||
*/
|
||||
identifierField: ComputedProperty<string> = alias('field.firstObject');
|
||||
@alias('field.firstObject')
|
||||
identifierField: string;
|
||||
|
||||
/**
|
||||
* References the second item in the IdentifierFieldWithFieldChangeSetTuple type, this is the list of tags
|
||||
@ -126,7 +128,8 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
* @type {ComputedProperty<Array<IComplianceChangeSet>>}
|
||||
* @memberof DatasetComplianceRollupRow
|
||||
*/
|
||||
fieldChangeSet: ComputedProperty<Array<IComplianceChangeSet>> = alias('field.1');
|
||||
@alias('field.1')
|
||||
fieldChangeSet: Array<IComplianceChangeSet>;
|
||||
|
||||
/**
|
||||
* References the first tag in the change set, this is the primary tag for the field and should not be deleted
|
||||
@ -134,7 +137,8 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
* @type {ComputedProperty<IComplianceChangeSet>}
|
||||
* @memberof DatasetComplianceRollupRow
|
||||
*/
|
||||
fieldProps: ComputedProperty<IComplianceChangeSet> = alias('fieldChangeSet.firstObject');
|
||||
@alias('fieldChangeSet.firstObject')
|
||||
fieldProps: IComplianceChangeSet;
|
||||
|
||||
/**
|
||||
* Aliases the dataType property on the first item in the field change set, this should available
|
||||
@ -142,7 +146,8 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
* @type {ComputedProperty<string>}
|
||||
* @memberof DatasetComplianceRollupRow
|
||||
*/
|
||||
dataType: ComputedProperty<string> = alias('fieldProps.dataType');
|
||||
@alias('fieldProps.dataType')
|
||||
dataType: string;
|
||||
|
||||
/**
|
||||
* Checks if the field has only one tag
|
||||
@ -178,9 +183,8 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
* @type {(ComputedProperty<SuggestionIntent | void>)}
|
||||
* @memberof DatasetComplianceRollupRow
|
||||
*/
|
||||
suggestionAuthority: ComputedProperty<IComplianceChangeSet['suggestionAuthority']> = alias(
|
||||
'fieldProps.suggestionAuthority'
|
||||
);
|
||||
@alias('fieldProps.suggestionAuthority')
|
||||
suggestionAuthority: IComplianceChangeSet['suggestionAuthority'];
|
||||
|
||||
/**
|
||||
* Extracts the field suggestions into a cached computed property, if a suggestion exists
|
||||
@ -352,17 +356,19 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
// Field has only one tag, that tag has an identifierType
|
||||
const updateDefault = hasSingleTag && fieldTagsHaveIdentifierType(get(this, 'fieldChangeSet'));
|
||||
|
||||
// Identifier type and changeSet does not already have suggested type
|
||||
// Suggested identifierType exists but changeSet does not already have the suggested type
|
||||
if (identifierType && !suggestedValuesInChangeSet.includes(identifierType)) {
|
||||
if (updateDefault) {
|
||||
get(this, 'onTagIdentifierTypeChange')(get(this, 'fieldProps'), {
|
||||
value: <ComplianceFieldIdValue>identifierType
|
||||
});
|
||||
} else {
|
||||
// If suggested value is ComplianceFieldIdValue.None then do not add
|
||||
if (identifierType !== ComplianceFieldIdValue.None) {
|
||||
this.actions.onAddFieldTag.call(this, { identifierType, logicalType });
|
||||
// If suggested value is ComplianceFieldIdValue.None, remove all other annotations first before tagging field as none
|
||||
if (identifierType === ComplianceFieldIdValue.None) {
|
||||
arrayEach(this.actions.onRemoveFieldTag.bind(this))(this.fieldChangeSet);
|
||||
}
|
||||
|
||||
this.actions.onAddFieldTag.call(this, { identifierType, logicalType });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,20 @@
|
||||
import Component from '@ember/component';
|
||||
import { set } from '@ember/object';
|
||||
import { classNames } from '@ember-decorators/component';
|
||||
import { computed } from '@ember-decorators/object';
|
||||
import { computed, action } from '@ember-decorators/object';
|
||||
import { assert } from '@ember/debug';
|
||||
import { task } from 'ember-concurrency';
|
||||
import { readDatasetOwnersByUrn } from 'wherehows-web/utils/api/datasets/owners';
|
||||
import { arrayMap, arrayPipe } from 'wherehows-web/utils/array';
|
||||
import { IAvatar } from 'wherehows-web/typings/app/avatars';
|
||||
import { IOwner, IOwnerResponse } from 'wherehows-web/typings/api/datasets/owners';
|
||||
import { getAvatarProps } from 'wherehows-web/constants/avatars/avatars';
|
||||
import { makeAvatar } from 'wherehows-web/constants/avatars/avatars';
|
||||
import { confirmedOwners, avatarWithDropDownOption } from 'wherehows-web/constants/datasets/owner';
|
||||
import { containerDataSource } from 'wherehows-web/utils/components/containers/data-source';
|
||||
import { decodeUrn, isLiUrn } from 'wherehows-web/utils/validators/urn';
|
||||
import { IAppConfig } from 'wherehows-web/typings/api/configurator/configurator';
|
||||
import { buildMailToUrl } from 'wherehows-web/utils/helpers/email';
|
||||
import { IDropDownOption } from 'wherehows-web/typings/app/dataset-compliance';
|
||||
|
||||
@classNames('dataset-owner-list')
|
||||
@containerDataSource('getOwnersTask')
|
||||
@ -59,12 +61,28 @@ export default class DatasetOwnerListContainer extends Component {
|
||||
@computed('owners')
|
||||
get avatars(): Array<IAvatar> {
|
||||
const { avatarEntityProps, owners } = this;
|
||||
const [getAvatarProperties, augmentAvatarsWithDropDownOption] = [
|
||||
arrayMap(getAvatarProps(avatarEntityProps)),
|
||||
const [makeAvatars, augmentAvatarsWithDropDownOption] = [
|
||||
arrayMap(makeAvatar(avatarEntityProps)),
|
||||
arrayMap(avatarWithDropDownOption)
|
||||
];
|
||||
|
||||
return arrayPipe(getAvatarProperties, augmentAvatarsWithDropDownOption)(owners);
|
||||
return arrayPipe(makeAvatars, augmentAvatarsWithDropDownOption)(owners);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles user selection of an option for each owner avatar
|
||||
* @param {IAvatar} avatar owner's avatar instance
|
||||
* @param {IDropDownOption<any>} [_option] unused optional parameter indicating selected option
|
||||
* @returns {(Window | null)}
|
||||
* @memberof DatasetOwnerListContainer
|
||||
*/
|
||||
@action
|
||||
onOwnerOptionSelected(avatar: IAvatar, _option?: IDropDownOption<any>): Window | null {
|
||||
// if the owner avatar does not have an email then a null value is returned with no action performed
|
||||
const emailOwner = ({ email }: IAvatar): Window | null =>
|
||||
email ? window.open(buildMailToUrl({ to: email || '' }), '_blank') : null;
|
||||
|
||||
return emailOwner(avatar);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -9,7 +9,7 @@ import { IAppConfig } from 'wherehows-web/typings/api/configurator/configurator'
|
||||
* @param {IAppConfig.userEntityProps.aviUrlFallback} aviUrlFallback
|
||||
* @return {IAvatar}
|
||||
*/
|
||||
const getAvatarProps = ({ aviUrlPrimary, aviUrlFallback = '' }: IAppConfig['userEntityProps']) => (
|
||||
const makeAvatar = ({ aviUrlPrimary, aviUrlFallback = '' }: IAppConfig['userEntityProps']) => (
|
||||
object: Partial<IAvatar>
|
||||
): IAvatar => {
|
||||
const props = pick(object, ['email', 'userName', 'name']);
|
||||
@ -22,4 +22,4 @@ const getAvatarProps = ({ aviUrlPrimary, aviUrlFallback = '' }: IAppConfig['user
|
||||
};
|
||||
};
|
||||
|
||||
export { getAvatarProps };
|
||||
export { makeAvatar };
|
||||
|
||||
@ -3,7 +3,6 @@ import { IOwner } from 'wherehows-web/typings/api/datasets/owners';
|
||||
import { OwnerIdType, OwnerSource, OwnerType, OwnerUrnNamespace } from 'wherehows-web/utils/api/datasets/owners';
|
||||
import { arrayFilter, isListUnique } from 'wherehows-web/utils/array';
|
||||
import { IAvatar } from 'wherehows-web/typings/app/avatars';
|
||||
import { buildMailToUrl } from 'wherehows-web/utils/helpers/email';
|
||||
|
||||
/**
|
||||
* Initial user name for candidate owners
|
||||
@ -164,9 +163,7 @@ const avatarWithDropDownOption = (avatar: IAvatar): IAvatar & Required<Pick<IAva
|
||||
...avatar,
|
||||
avatarOptions: [
|
||||
{
|
||||
// if the owner avatar does not have an email then a null value is returned with no action performed
|
||||
value: ({ email }: IAvatar): Window | null =>
|
||||
email ? window.open(buildMailToUrl({ to: email || '' }), '_blank') : null,
|
||||
value: email,
|
||||
label: email
|
||||
}
|
||||
]
|
||||
|
||||
@ -5,7 +5,7 @@ import { get } from '@ember/object';
|
||||
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
|
||||
import { feedback, avatar } from 'wherehows-web/constants';
|
||||
import Configurator from 'wherehows-web/services/configurator';
|
||||
import { getAvatarProps } from 'wherehows-web/constants/avatars/avatars';
|
||||
import { makeAvatar } from 'wherehows-web/constants/avatars/avatars';
|
||||
|
||||
const { mail, subject, title } = feedback;
|
||||
|
||||
@ -48,7 +48,7 @@ export default Route.extend(ApplicationRouteMixin, {
|
||||
getConfig('userEntityProps')
|
||||
];
|
||||
const { userName, email, name } = get(this, 'sessionUser.currentUser') || {};
|
||||
const avatar = getAvatarProps(avatarEntityProps)({ userName, email, name });
|
||||
const avatar = makeAvatar(avatarEntityProps)({ userName, email, name });
|
||||
|
||||
/**
|
||||
* properties for the navigation link to allow a user to provide feedback
|
||||
|
||||
@ -1 +1,5 @@
|
||||
{{avatars/stacked-avatars-list avatars=avatars avatarType="owner"}}
|
||||
{{avatars/stacked-avatars-list
|
||||
avatars=avatars
|
||||
handleAvatarOptionSelection=onOwnerOptionSelected
|
||||
avatarType="owner"
|
||||
}}
|
||||
12
wherehows-web/app/typings/app/avatars.d.ts
vendored
12
wherehows-web/app/typings/app/avatars.d.ts
vendored
@ -1,13 +1,5 @@
|
||||
import { IDropDownOption } from 'wherehows-web/typings/app/dataset-compliance';
|
||||
|
||||
/**
|
||||
* Defines the interface for functions that are supplied as options to IAvatar.avatarOptions
|
||||
* @interface IAvatarDropDownAction
|
||||
*/
|
||||
interface IAvatarDropDownAction {
|
||||
(avatar: IAvatar): any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the interface for an avatar object
|
||||
* @interface IAvatar
|
||||
@ -22,7 +14,7 @@ interface IAvatar {
|
||||
userName?: string;
|
||||
name?: string;
|
||||
// Selection options for an avatar with dropdown
|
||||
avatarOptions?: Array<IDropDownOption<IAvatarDropDownAction>>;
|
||||
avatarOptions?: Array<IDropDownOption<any>>;
|
||||
}
|
||||
|
||||
export { IAvatar, IAvatarDropDownAction };
|
||||
export { IAvatar };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user