mirror of https://github.com/sualko/cloud_bbb
parent
971df674ec
commit
f13f28afde
|
@ -0,0 +1,33 @@
|
||||||
|
.bbb-selection-container {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bbb-selection {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: 1px solid var(--color-border-dark);
|
||||||
|
max-height: 88px;
|
||||||
|
overflow: auto;
|
||||||
|
box-shadow: 0 5px 10px -5px var(--color-box-shadow);
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
li {
|
||||||
|
color: var(--color-text-lighter);
|
||||||
|
padding: 0 1em;
|
||||||
|
line-height: 44px;
|
||||||
|
|
||||||
|
&.suggestion {
|
||||||
|
color: var(--color-main-text);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-background-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { api, ShareWith, ShareType, ShareWithOption } from '../Common/Api';
|
import { api, ShareWith, ShareType, ShareWithOption } from '../Common/Api';
|
||||||
import './ShareWith.scss';
|
import './ShareSelection.scss';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
selectShare: (selection: ShareWithOption) => void;
|
selectShare: (selection: ShareWithOption) => void;
|
|
@ -35,43 +35,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bbb-selection-container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bbb-selection {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border: 1px solid var(--color-border-dark);
|
|
||||||
max-height: 88px;
|
|
||||||
overflow: auto;
|
|
||||||
box-shadow: 0 5px 10px -5px var(--color-box-shadow);
|
|
||||||
|
|
||||||
li {
|
|
||||||
color: var(--color-text-lighter);
|
|
||||||
padding: 0 1em;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bbb-icon-unselected {
|
.bbb-icon-unselected {
|
||||||
opacity: 0.2 !important;
|
opacity: 0.2 !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 0.5 !important;
|
opacity: 0.5 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React from 'react';
|
||||||
import { api, ShareWith, ShareType, RoomShare, Room, Permission, ShareWithOption } from '../Common/Api';
|
import { api, ShareWith, ShareType, RoomShare, Room, Permission } from '../Common/Api';
|
||||||
import './ShareWith.scss';
|
import './ShareWith.scss';
|
||||||
|
import ShareSelection from '../Common/ShareSelection';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -10,12 +11,6 @@ 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 [hasFocus, setFocus] = useState<boolean>(false);
|
|
||||||
const [showSearchResults, setShowSearchResults] = useState<boolean>(false);
|
|
||||||
const [recommendations, setRecommendations] = useState<ShareWith>();
|
|
||||||
const [searchResults, setSearchResults] = useState<ShareWith>();
|
|
||||||
|
|
||||||
const isOwner = room.userId === OC.currentUser;
|
const isOwner = room.userId === OC.currentUser;
|
||||||
|
|
||||||
const shares = (allShares && permission === Permission.Moderator) ?
|
const shares = (allShares && permission === Permission.Moderator) ?
|
||||||
|
@ -24,32 +19,11 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
const sharedUserIds = shares ? shares.filter(share => share.shareType === ShareType.User).map(share => share.shareWith) : [];
|
const sharedUserIds = shares ? shares.filter(share => share.shareType === ShareType.User).map(share => share.shareWith) : [];
|
||||||
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(() => {
|
|
||||||
setSearchResults(undefined);
|
|
||||||
const searchQuery = search;
|
|
||||||
|
|
||||||
api.searchShareWith(searchQuery).then(result => {
|
|
||||||
if (searchQuery === search) {
|
|
||||||
setSearchResults(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [search]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
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);
|
||||||
|
|
||||||
roomShare.shareWithDisplayName = displayName;
|
roomShare.shareWithDisplayName = displayName;
|
||||||
|
|
||||||
console.log('addRoomShare', allShares, roomShare);
|
|
||||||
|
|
||||||
const newShares = allShares ? [...allShares] : [];
|
const newShares = allShares ? [...allShares] : [];
|
||||||
const index = newShares.findIndex(share => share.id === roomShare.id);
|
const index = newShares.findIndex(share => share.id === roomShare.id);
|
||||||
|
|
||||||
|
@ -59,10 +33,7 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
newShares.push(roomShare);
|
newShares.push(roomShare);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('newroomshares', newShares);
|
|
||||||
|
|
||||||
setShares(newShares);
|
setShares(newShares);
|
||||||
setSearch('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteRoomShare(id: number) {
|
async function deleteRoomShare(id: number) {
|
||||||
|
@ -79,27 +50,12 @@ 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|undefined) {
|
function getAvatarUrl(userId: string) {
|
||||||
const results = options ? [
|
return OC.generateUrl('/avatar/' + encodeURIComponent(userId) + '/' + 32, {
|
||||||
...options.users.filter(user => !sharedUserIds.includes(user.value.shareWith)),
|
user: userId,
|
||||||
...options.groups.filter(group => !sharedGroupIds.includes(group.value.shareWith)),
|
size: 32,
|
||||||
] : [];
|
requesttoken: OC.requestToken,
|
||||||
|
});
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderShares(shares: RoomShare[]) {
|
function renderShares(shares: RoomShare[]) {
|
||||||
|
@ -116,11 +72,7 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
return (
|
return (
|
||||||
<ul className="bbb-shareWith">
|
<ul className="bbb-shareWith">
|
||||||
{[ownShare, ...shares].map(share => {
|
{[ownShare, ...shares].map(share => {
|
||||||
const avatarUrl = share.shareType === ShareType.User ? OC.generateUrl('/avatar/' + encodeURIComponent(share.shareWith) + '/' + 32, {
|
const avatarUrl = share.shareType === ShareType.User ? getAvatarUrl(share.shareWith) : undefined;
|
||||||
user: share.shareWith,
|
|
||||||
size: 32,
|
|
||||||
requesttoken: OC.requestToken,
|
|
||||||
}) : undefined;
|
|
||||||
const displayName = share.shareWithDisplayName || share.shareWith;
|
const displayName = share.shareWithDisplayName || share.shareWith;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -136,7 +88,10 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
</div>
|
</div>
|
||||||
{(share.id > -1 && permission === Permission.Moderator && isOwner) && <div className="bbb-shareWith__item__action">
|
{(share.id > -1 && permission === Permission.Moderator && isOwner) && <div className="bbb-shareWith__item__action">
|
||||||
<a className={`icon icon-shared icon-visible ${share.permission === Permission.Admin ? 'bbb-icon-selected' : 'bbb-icon-unselected'}`}
|
<a className={`icon icon-shared icon-visible ${share.permission === Permission.Admin ? 'bbb-icon-selected' : 'bbb-icon-unselected'}`}
|
||||||
onClick={ev => {ev.preventDefault(); toggleAdminShare(share);}}
|
onClick={ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
toggleAdminShare(share);
|
||||||
|
}}
|
||||||
title={t('bbb', 'Share')} />
|
title={t('bbb', 'Share')} />
|
||||||
</div>}
|
</div>}
|
||||||
{(share.id > -1 && isOwner) && <div className="bbb-shareWith__item__action">
|
{(share.id > -1 && isOwner) && <div className="bbb-shareWith__item__action">
|
||||||
|
@ -157,17 +112,14 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
<>
|
<>
|
||||||
{shares ? renderShares(shares) : loading}
|
{shares ? renderShares(shares) : loading}
|
||||||
|
|
||||||
<div className="bbb-selection-container">
|
{isOwner ?
|
||||||
{isOwner ? <input
|
<ShareSelection
|
||||||
type="text"
|
selectShare={(shareOption) => addRoomShare(shareOption.value.shareWith, shareOption.value.shareType, shareOption.label, permission)}
|
||||||
value={search}
|
excluded={{userIds: sharedUserIds, groupIds: sharedGroupIds}}/> :
|
||||||
onChange={ev => setSearch(ev.currentTarget.value)}
|
<em>
|
||||||
onFocus={() => setFocus(true)}
|
<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.')}
|
||||||
onBlur={() => setFocus(false)}
|
</em>
|
||||||
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>}
|
|
||||||
{showSearchResults && renderSearchResults((search && searchResults) ? searchResults : ((recommendations && !search) ? recommendations : undefined))}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||||
import '../Manager/App.scss';
|
import '../Manager/App.scss';
|
||||||
import { api, Restriction, ShareType } from '../Common/Api';
|
import { api, Restriction, ShareType } from '../Common/Api';
|
||||||
import RestrictionRow from './RestrictionRow';
|
import RestrictionRow from './RestrictionRow';
|
||||||
import ShareSelection from './ShareSelection';
|
import ShareSelection from '../Common/ShareSelection';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
||||||
|
@ -52,8 +52,7 @@ const App: React.FC<Props> = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="bbb-react-root"
|
<div id="bbb-react-root">
|
||||||
onClick={() => { /* @TODO hide edit inputs */ }}>
|
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
.bbb-shareWith {
|
|
||||||
margin: 1em 0;
|
|
||||||
|
|
||||||
&__item {
|
|
||||||
height: 44px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--color-background-dark);
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatardiv {
|
|
||||||
height: 32px;
|
|
||||||
width: 32px;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.icon-group-white {
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
background-color: #a9a9a9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
height: 44px;
|
|
||||||
width: 44px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
padding: 0 1em;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bbb-selection-container {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bbb-selection {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border: 1px solid var(--color-border-dark);
|
|
||||||
max-height: 88px;
|
|
||||||
overflow: auto;
|
|
||||||
box-shadow: 0 5px 10px -5px var(--color-box-shadow);
|
|
||||||
z-index: 100;
|
|
||||||
|
|
||||||
li {
|
|
||||||
color: var(--color-text-lighter);
|
|
||||||
padding: 0 1em;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bbb-icon-unselected {
|
|
||||||
opacity: 0.2 !important;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.5 !important;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue