mirror of https://github.com/sualko/cloud_bbb
fix: improve share with input
- show loading indicator (fix #58) - fix drop down behaviour (fix #49)pull/67/head
parent
ab60034086
commit
bfbf130e3f
|
@ -47,21 +47,17 @@ export type Recording = {
|
|||
meta: any;
|
||||
}
|
||||
|
||||
export interface ShareWithOption {
|
||||
label: string;
|
||||
value: {
|
||||
shareType: ShareType;
|
||||
shareWith: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ShareWith {
|
||||
users: {
|
||||
label: string;
|
||||
value: {
|
||||
shareType: ShareType;
|
||||
shareWith: string;
|
||||
};
|
||||
}[];
|
||||
groups: {
|
||||
label: string;
|
||||
value: {
|
||||
shareType: ShareType;
|
||||
shareWith: string;
|
||||
};
|
||||
}[];
|
||||
users: ShareWithOption[];
|
||||
groups: ShareWithOption[];
|
||||
}
|
||||
|
||||
class Api {
|
||||
|
|
|
@ -49,15 +49,20 @@
|
|||
box-shadow: 0 5px 10px -5px var(--color-box-shadow);
|
||||
|
||||
li {
|
||||
color: var(--color-text-lighter);
|
||||
padding: 0 1em;
|
||||
cursor: pointer;
|
||||
line-height: 44px;
|
||||
|
||||
&.suggestion {
|
||||
color: var(--color-main-text);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-background-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bbb-form-shareWith {
|
||||
margin-top: -1.5em;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { api, ShareWith, ShareType, RoomShare, Room, Permission } from './Api';
|
||||
import { api, ShareWith, ShareType, RoomShare, Room, Permission, ShareWithOption } from './Api';
|
||||
import './ShareWith.scss';
|
||||
|
||||
type Props = {
|
||||
|
@ -12,6 +12,7 @@ type Props = {
|
|||
const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setShares }) => {
|
||||
const [search, setSearch] = useState<string>('');
|
||||
const [hasFocus, setFocus] = useState<boolean>(false);
|
||||
const [showSearchResults, setShowSearchResults] = useState<boolean>(false);
|
||||
const [recommendations, setRecommendations] = useState<ShareWith>();
|
||||
const [searchResults, setSearchResults] = useState<ShareWith>();
|
||||
|
||||
|
@ -24,8 +25,13 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
|||
const sharedGroupIds = shares ? shares.filter(share => share.shareType === ShareType.Group).map(share => share.shareWith) : [];
|
||||
|
||||
useEffect(() => {
|
||||
api.searchShareWith(search).then(result => {
|
||||
setSearchResults(undefined);
|
||||
const searchQuery = search;
|
||||
|
||||
api.searchShareWith(searchQuery).then(result => {
|
||||
if (searchQuery === search) {
|
||||
setSearchResults(result);
|
||||
}
|
||||
});
|
||||
}, [search]);
|
||||
|
||||
|
@ -33,6 +39,10 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
|||
api.getRecommendedShareWith().then(result => setRecommendations(result));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => setShowSearchResults(hasFocus), 100);
|
||||
}, [hasFocus]);
|
||||
|
||||
async function addRoomShare(shareWith: string, shareType: number, displayName: string, permission: Permission) {
|
||||
const roomShare = await api.createRoomShare(room.id, shareType, shareWith, permission);
|
||||
|
||||
|
@ -68,17 +78,25 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
|||
return addRoomShare(share.shareWith, share.shareType, share.shareWithDisplayName || share.shareWith, newPermission);
|
||||
}
|
||||
|
||||
function renderSearchResults(options: ShareWith) {
|
||||
return (
|
||||
<ul className="bbb-selection">
|
||||
{[
|
||||
function renderSearchResults(options: ShareWith|undefined) {
|
||||
const results = options ? [
|
||||
...options.users.filter(user => !sharedUserIds.includes(user.value.shareWith)),
|
||||
...options.groups.filter(group => !sharedGroupIds.includes(group.value.shareWith)),
|
||||
].map(option => {
|
||||
return (<li key={option.value.shareWith} onClick={() => addRoomShare(option.value.shareWith, option.value.shareType, option.label, permission)}>
|
||||
] : [];
|
||||
|
||||
const renderOption = (option: ShareWithOption) => {
|
||||
return (<li key={option.value.shareWith} className="suggestion" onClick={() => addRoomShare(option.value.shareWith, option.value.shareType, option.label, permission)}>
|
||||
{option.label}{option.value.shareType === ShareType.Group ? ` (${t('bbb', 'Group')})` : ''}
|
||||
</li>);
|
||||
})}
|
||||
};
|
||||
|
||||
return (
|
||||
<ul className="bbb-selection">
|
||||
{!options ?
|
||||
<li><span className="icon icon-loading-small icon-visible"></span> {t('bbb', 'Searching')}</li> :
|
||||
(
|
||||
(results.length === 0 && search) ? <li>{t('bbb', 'No matches')}</li> : results.map(renderOption)
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
@ -144,10 +162,10 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
|||
value={search}
|
||||
onChange={ev => setSearch(ev.currentTarget.value)}
|
||||
onFocus={() => setFocus(true)}
|
||||
onBlur={() => setTimeout(() => setFocus(false), 100)}
|
||||
onBlur={() => setFocus(false)}
|
||||
placeholder={t('bbb', 'Name, group, ...')} /> :
|
||||
<em><span className="icon icon-details icon-visible"></span> {t('bbb', 'You are not allowed to change this option, because this room is shared with you.')}</em>}
|
||||
{hasFocus && (searchResults ? renderSearchResults(searchResults) : (recommendations ? renderSearchResults(recommendations) : loading))}
|
||||
{showSearchResults && renderSearchResults((search && searchResults) ? searchResults : ((recommendations && !search) ? recommendations : undefined))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue