200085: Fix for sharing dialog, clear on blur
[arvados-workbench2.git] / src / views-components / sharing-dialog / participant-select.tsx
index ea3775e93ad652a8463b95b3e28656e74a8f03de..b43940f045e9f69b87b2dbb515826506e23c0a84 100644 (file)
@@ -2,31 +2,35 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import * as React from 'react';
-import { Autocomplete } from '~/components/autocomplete/autocomplete';
+import React from 'react';
+import { Autocomplete } from 'components/autocomplete/autocomplete';
 import { connect, DispatchProp } from 'react-redux';
-import { ServiceRepository } from '~/services/services';
+import { ServiceRepository } from 'services/services';
 import { FilterBuilder } from '../../services/api/filter-builder';
 import { debounce } from 'debounce';
 import { ListItemText, Typography } from '@material-ui/core';
 import { noop } from 'lodash/fp';
-import { GroupClass, GroupResource } from '~/models/group';
-import { getUserDisplayName, UserResource } from '~/models/user';
-import { ResourceKind } from '~/models/resource';
-import { ListResults } from '~/services/common-service/common-service';
+import { GroupClass, GroupResource } from 'models/group';
+import { getUserDetailsString, getUserDisplayName, UserResource } from 'models/user';
+import { Resource, ResourceKind } from 'models/resource';
+import { ListResults } from 'services/common-service/common-service';
 
 export interface Participant {
     name: string;
+    tooltip: string;
     uuid: string;
 }
 
-type ParticipantResource = GroupResource & UserResource;
+type ParticipantResource = GroupResource | UserResource;
 
 interface ParticipantSelectProps {
     items: Participant[];
+    excludedParticipants?: string[];
     label?: string;
     autofocus?: boolean;
     onlyPeople?: boolean;
+    onlyActive?: boolean;
+    disabled?: boolean;
 
     onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
     onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
@@ -40,14 +44,25 @@ interface ParticipantSelectState {
     suggestions: ParticipantResource[];
 }
 
-const getDisplayName = (item: GroupResource & UserResource) => {
+const getDisplayName = (item: GroupResource | UserResource, detailed: boolean) => {
     switch (item.kind) {
         case ResourceKind.USER:
-            return getUserDisplayName(item, true);
+            return getUserDisplayName(item, detailed, detailed);
         case ResourceKind.GROUP:
-            return item.name;
+            return item.name + `(${`(${(item as Resource).uuid})`})`;
         default:
-            return item.uuid;
+            return (item as Resource).uuid;
+    }
+};
+
+const getDisplayTooltip = (item: GroupResource | UserResource) => {
+    switch (item.kind) {
+        case ResourceKind.USER:
+            return getUserDetailsString(item);
+        case ResourceKind.GROUP:
+            return item.name + `(${`(${(item as Resource).uuid})`})`;
+        default:
+            return (item as Resource).uuid;
     }
 };
 
@@ -71,23 +86,36 @@ export const ParticipantSelect = connect()(
                     onChange={this.handleChange}
                     onCreate={this.handleCreate}
                     onSelect={this.handleSelect}
-                    onDelete={this.handleDelete}
+                    onDelete={this.props.onDelete && !this.props.disabled ? this.handleDelete : undefined}
                     onFocus={this.props.onFocus}
-                    onBlur={this.props.onBlur}
+                    onBlur={this.onBlur}
                     renderChipValue={this.renderChipValue}
-                    renderSuggestion={this.renderSuggestion} />
+                    renderChipTooltip={this.renderChipTooltip}
+                    renderSuggestion={this.renderSuggestion}
+                    disabled={this.props.disabled}/>
             );
         }
 
+        onBlur = (e) => {
+            if (this.props.onBlur) {
+                this.props.onBlur(e);
+            }
+            setTimeout(() => this.setState({ value: '', suggestions: [] }), 200);
+        }
+
         renderChipValue(chipValue: Participant) {
             const { name, uuid } = chipValue;
             return name || uuid;
         }
 
+        renderChipTooltip(item: Participant) {
+            return item.tooltip;
+        }
+
         renderSuggestion(item: ParticipantResource) {
             return (
                 <ListItemText>
-                    <Typography noWrap>{getDisplayName(item)}</Typography>
+                    <Typography noWrap>{getDisplayName(item, true)}</Typography>
                 </ListItemText>
             );
         }
@@ -103,6 +131,7 @@ export const ParticipantSelect = connect()(
                 this.setState({ value: '', suggestions: [] });
                 onCreate({
                     name: '',
+                    tooltip: '',
                     uuid: this.state.value,
                 });
             }
@@ -113,7 +142,8 @@ export const ParticipantSelect = connect()(
             const { onSelect = noop } = this.props;
             this.setState({ value: '', suggestions: [] });
             onSelect({
-                name: getDisplayName(selection),
+                name: getDisplayName(selection, false),
+                tooltip: getDisplayTooltip(selection),
                 uuid,
             });
         }
@@ -130,11 +160,14 @@ export const ParticipantSelect = connect()(
 
             const filterUsers = new FilterBuilder()
                 .addILike('any', value)
+                .addEqual('is_active', this.props.onlyActive || undefined)
+                .addNotIn('uuid', this.props.excludedParticipants)
                 .getFilters();
             const userItems: ListResults<any> = await userService.list({ filters: filterUsers, limit, count: "none" });
 
             const filterGroups = new FilterBuilder()
-                .addNotIn('group_class', [GroupClass.PROJECT])
+                .addNotIn('group_class', [GroupClass.PROJECT, GroupClass.FILTER])
+                .addNotIn('uuid', this.props.excludedParticipants)
                 .addILike('name', value)
                 .getFilters();