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;
|
meta: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ShareWithOption {
|
||||||
|
label: string;
|
||||||
|
value: {
|
||||||
|
shareType: ShareType;
|
||||||
|
shareWith: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface ShareWith {
|
export interface ShareWith {
|
||||||
users: {
|
users: ShareWithOption[];
|
||||||
label: string;
|
groups: ShareWithOption[];
|
||||||
value: {
|
|
||||||
shareType: ShareType;
|
|
||||||
shareWith: string;
|
|
||||||
};
|
|
||||||
}[];
|
|
||||||
groups: {
|
|
||||||
label: string;
|
|
||||||
value: {
|
|
||||||
shareType: ShareType;
|
|
||||||
shareWith: string;
|
|
||||||
};
|
|
||||||
}[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
|
|
|
@ -49,14 +49,19 @@
|
||||||
box-shadow: 0 5px 10px -5px var(--color-box-shadow);
|
box-shadow: 0 5px 10px -5px var(--color-box-shadow);
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
color: var(--color-text-lighter);
|
||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
cursor: pointer;
|
|
||||||
line-height: 44px;
|
line-height: 44px;
|
||||||
|
|
||||||
|
&.suggestion {
|
||||||
|
color: var(--color-main-text);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--color-background-hover);
|
background-color: var(--color-background-hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bbb-form-shareWith {
|
.bbb-form-shareWith {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
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';
|
import './ShareWith.scss';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -12,6 +12,7 @@ type Props = {
|
||||||
const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setShares }) => {
|
const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setShares }) => {
|
||||||
const [search, setSearch] = useState<string>('');
|
const [search, setSearch] = useState<string>('');
|
||||||
const [hasFocus, setFocus] = useState<boolean>(false);
|
const [hasFocus, setFocus] = useState<boolean>(false);
|
||||||
|
const [showSearchResults, setShowSearchResults] = useState<boolean>(false);
|
||||||
const [recommendations, setRecommendations] = useState<ShareWith>();
|
const [recommendations, setRecommendations] = useState<ShareWith>();
|
||||||
const [searchResults, setSearchResults] = 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) : [];
|
const sharedGroupIds = shares ? shares.filter(share => share.shareType === ShareType.Group).map(share => share.shareWith) : [];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.searchShareWith(search).then(result => {
|
setSearchResults(undefined);
|
||||||
|
const searchQuery = search;
|
||||||
|
|
||||||
|
api.searchShareWith(searchQuery).then(result => {
|
||||||
|
if (searchQuery === search) {
|
||||||
setSearchResults(result);
|
setSearchResults(result);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, [search]);
|
}, [search]);
|
||||||
|
|
||||||
|
@ -33,6 +39,10 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
api.getRecommendedShareWith().then(result => setRecommendations(result));
|
api.getRecommendedShareWith().then(result => setRecommendations(result));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTimeout(() => setShowSearchResults(hasFocus), 100);
|
||||||
|
}, [hasFocus]);
|
||||||
|
|
||||||
async function addRoomShare(shareWith: string, shareType: number, displayName: string, permission: Permission) {
|
async function addRoomShare(shareWith: string, shareType: number, displayName: string, permission: Permission) {
|
||||||
const roomShare = await api.createRoomShare(room.id, shareType, shareWith, 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);
|
return addRoomShare(share.shareWith, share.shareType, share.shareWithDisplayName || share.shareWith, newPermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSearchResults(options: ShareWith) {
|
function renderSearchResults(options: ShareWith|undefined) {
|
||||||
return (
|
const results = options ? [
|
||||||
<ul className="bbb-selection">
|
|
||||||
{[
|
|
||||||
...options.users.filter(user => !sharedUserIds.includes(user.value.shareWith)),
|
...options.users.filter(user => !sharedUserIds.includes(user.value.shareWith)),
|
||||||
...options.groups.filter(group => !sharedGroupIds.includes(group.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')})` : ''}
|
{option.label}{option.value.shareType === ShareType.Group ? ` (${t('bbb', 'Group')})` : ''}
|
||||||
</li>);
|
</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>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -144,10 +162,10 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
value={search}
|
value={search}
|
||||||
onChange={ev => setSearch(ev.currentTarget.value)}
|
onChange={ev => setSearch(ev.currentTarget.value)}
|
||||||
onFocus={() => setFocus(true)}
|
onFocus={() => setFocus(true)}
|
||||||
onBlur={() => setTimeout(() => setFocus(false), 100)}
|
onBlur={() => setFocus(false)}
|
||||||
placeholder={t('bbb', 'Name, group, ...')} /> :
|
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>}
|
<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>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue