mirror of https://github.com/sualko/cloud_bbb
parent
bec1b4dce7
commit
8b2dc9cb71
|
@ -11,6 +11,7 @@ use BigBlueButton\Parameters\DeleteRecordingsParameters;
|
|||
use BigBlueButton\Parameters\IsMeetingRunningParameters;
|
||||
use OCA\BigBlueButton\Db\Room;
|
||||
use OCA\BigBlueButton\Db\RoomShare;
|
||||
use OCA\BigBlueButton\Permission;
|
||||
use OCA\BigBlueButton\Service\RoomShareService;
|
||||
use OCP\IConfig;
|
||||
use OCP\IURLGenerator;
|
||||
|
@ -24,11 +25,8 @@ class API
|
|||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
/** @var IGroupManager */
|
||||
private $groupManager;
|
||||
|
||||
/** @var RoomShareService */
|
||||
private $roomShareService;
|
||||
/** @var Permission */
|
||||
private $permission;
|
||||
|
||||
/** @var BigBlueButton */
|
||||
private $server;
|
||||
|
@ -36,13 +34,11 @@ class API
|
|||
public function __construct(
|
||||
IConfig $config,
|
||||
IURLGenerator $urlGenerator,
|
||||
IGroupManager $groupManager,
|
||||
RoomShareService $roomShareService
|
||||
Permission $permission
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->roomShareService = $roomShareService;
|
||||
$this->permission = $permission;
|
||||
}
|
||||
|
||||
private function getServer()
|
||||
|
@ -64,7 +60,7 @@ class API
|
|||
*/
|
||||
public function createJoinUrl(Room $room, int $creationTime, string $displayname, string $uid = null)
|
||||
{
|
||||
$password = $this->isModerator($room, $uid) ? $room->moderatorPassword : $room->attendeePassword;
|
||||
$password = $this->permission->isModerator($room, $uid) ? $room->moderatorPassword : $room->attendeePassword;
|
||||
|
||||
$joinMeetingParams = new JoinMeetingParameters($room->uid, $displayname, $password);
|
||||
|
||||
|
@ -81,38 +77,6 @@ class API
|
|||
return $this->getServer()->getJoinMeetingURL($joinMeetingParams);
|
||||
}
|
||||
|
||||
private function isModerator(Room $room, string $uid): bool
|
||||
{
|
||||
if ($uid === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($uid === $room->userId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$shares = $this->roomShareService->findAll($room->id);
|
||||
|
||||
/** @var RoomShare $share */
|
||||
foreach ($shares as $share) {
|
||||
if (!$share->hasModeratorPermission()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($share->getShareType() === RoomShare::SHARE_TYPE_USER) {
|
||||
if ($share->getShareWith() === $uid) {
|
||||
return true;
|
||||
}
|
||||
} elseif ($share->getShareType() === RoomShare::SHARE_TYPE_GROUP) {
|
||||
if ($this->groupManager->isInGroup($uid, $share->getShareWith())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create meeting room.
|
||||
*
|
||||
|
|
|
@ -4,7 +4,9 @@ namespace OCA\BigBlueButton\Controller;
|
|||
use OCA\BigBlueButton\BigBlueButton\API;
|
||||
use OCA\BigBlueButton\BigBlueButton\Presentation;
|
||||
use OCA\BigBlueButton\Db\Room;
|
||||
use OCA\BigBlueButton\NoPermissionException;
|
||||
use OCA\BigBlueButton\NotFoundException;
|
||||
use OCA\BigBlueButton\Permission;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\IRequest;
|
||||
use OCP\ISession;
|
||||
|
@ -38,6 +40,9 @@ class JoinController extends Controller
|
|||
/** @var API */
|
||||
private $api;
|
||||
|
||||
/** @var Permission */
|
||||
private $permission;
|
||||
|
||||
public function __construct(
|
||||
string $appName,
|
||||
IRequest $request,
|
||||
|
@ -46,7 +51,8 @@ class JoinController extends Controller
|
|||
IURLGenerator $urlGenerator,
|
||||
IUserSession $userSession,
|
||||
IConfig $config,
|
||||
API $api
|
||||
API $api,
|
||||
Permission $permission
|
||||
) {
|
||||
parent::__construct($appName, $request, $session);
|
||||
|
||||
|
@ -55,6 +61,7 @@ class JoinController extends Controller
|
|||
$this->userSession = $userSession;
|
||||
$this->config = $config;
|
||||
$this->api = $api;
|
||||
$this->permission = $permission;
|
||||
}
|
||||
|
||||
public function setToken(string $token)
|
||||
|
@ -90,10 +97,14 @@ class JoinController extends Controller
|
|||
$displayname = $user->getDisplayName();
|
||||
$userId = $user->getUID();
|
||||
|
||||
if ($room->access == Room::ACCESS_INTERNAL_RESTRICTED && !$this->permission->isUser($room, $userId)) {
|
||||
throw new NoPermissionException();
|
||||
}
|
||||
|
||||
if ($userId === $room->userId) {
|
||||
$presentation = new Presentation($u, $filename);
|
||||
}
|
||||
} elseif ($room->access === Room::ACCESS_INTERNAL) {
|
||||
} elseif ($room->access === Room::ACCESS_INTERNAL || $room->access == Room::ACCESS_INTERNAL_RESTRICTED) {
|
||||
return new RedirectResponse(
|
||||
$this->urlGenerator->linkToRoute('core.login.showLoginForm', [
|
||||
'redirect_url' => $this->urlGenerator->linkToRoute(
|
||||
|
|
|
@ -30,6 +30,19 @@ class RoomShareMapper extends QBMapper
|
|||
return $this->findEntity($qb);
|
||||
}
|
||||
|
||||
public function findByRoomAndEntity(int $roomId, string $shareWith, int $shareType): RoomShare
|
||||
{
|
||||
/* @var $qb IQueryBuilder */
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('bbb_room_shares')
|
||||
->where($qb->expr()->eq('room_id', $qb->createNamedParameter($roomId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($shareWith)))
|
||||
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
return $this->findEntity($qb);
|
||||
}
|
||||
|
||||
public function findAll(int $roomId): array
|
||||
{
|
||||
/* @var $qb IQueryBuilder */
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
namespace OCA\BigBlueButton\Middleware;
|
||||
|
||||
use OCA\BigBlueButton\Controller\JoinController;
|
||||
use OCA\BigBlueButton\NoPermissionException;
|
||||
use OCA\BigBlueButton\NoPermissionResponse;
|
||||
use OCA\BigBlueButton\NotFoundException;
|
||||
use OCP\AppFramework\Middleware;
|
||||
use OCP\AppFramework\Http\NotFoundResponse;
|
||||
|
@ -47,6 +49,10 @@ class JoinMiddleware extends Middleware
|
|||
return new NotFoundResponse();
|
||||
}
|
||||
|
||||
if ($exception instanceof NoPermissionException) {
|
||||
return new NoPermissionResponse();
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\BigBlueButton;
|
||||
|
||||
class NoPermissionException extends \Exception
|
||||
{
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
namespace OCA\BigBlueButton;
|
||||
|
||||
use OCP\Template;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
|
||||
class NoPermissionResponse extends Response
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->setContentSecurityPolicy(new ContentSecurityPolicy());
|
||||
$this->setStatus(404);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$template = new Template('core', '403', 'guest');
|
||||
return $template->fetchPage();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\BigBlueButton;
|
||||
|
||||
use Closure;
|
||||
use OCA\BigBlueButton\Service\RoomShareService;
|
||||
use OCA\BigBlueButton\Db\Room;
|
||||
use OCA\BigBlueButton\Db\RoomShare;
|
||||
use OCP\IGroupManager;
|
||||
|
||||
class Permission
|
||||
{
|
||||
|
||||
/** @var IGroupManager */
|
||||
private $groupManager;
|
||||
|
||||
/** @var RoomShareService */
|
||||
private $roomShareService;
|
||||
|
||||
public function __construct(
|
||||
IGroupManager $groupManager,
|
||||
RoomShareService $roomShareService
|
||||
) {
|
||||
$this->groupManager = $groupManager;
|
||||
$this->roomShareService = $roomShareService;
|
||||
}
|
||||
|
||||
public function isUser(Room $room, string $uid)
|
||||
{
|
||||
return $this->hasPermission($room, $uid, function (RoomShare $share) {
|
||||
return $share->hasUserPermission();
|
||||
});
|
||||
}
|
||||
|
||||
public function isModerator(Room $room, string $uid)
|
||||
{
|
||||
return $this->hasPermission($room, $uid, function (RoomShare $share) {
|
||||
return $share->hasModeratorPermission();
|
||||
});
|
||||
}
|
||||
|
||||
public function isAdmin(Room $room, string $uid)
|
||||
{
|
||||
return $this->hasPermission($room, $uid, function (RoomShare $share) {
|
||||
return $share->hasAdminPermission();
|
||||
});
|
||||
}
|
||||
|
||||
private function hasPermission(Room $room, string $uid, Closure $hasPermission): bool
|
||||
{
|
||||
if ($uid === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($uid === $room->userId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$shares = $this->roomShareService->findAll($room->id);
|
||||
|
||||
/** @var RoomShare $share */
|
||||
foreach ($shares as $share) {
|
||||
if (!$hasPermission($share)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($share->getShareType() === RoomShare::SHARE_TYPE_USER) {
|
||||
if ($share->getShareWith() === $uid) {
|
||||
return true;
|
||||
}
|
||||
} elseif ($share->getShareType() === RoomShare::SHARE_TYPE_GROUP) {
|
||||
if ($this->groupManager->isInGroup($uid, $share->getShareWith())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -46,14 +46,20 @@ class RoomShareService
|
|||
|
||||
public function create(int $roomId, int $shareType, string $shareWith, int $permission): RoomShare
|
||||
{
|
||||
$roomShare = new RoomShare();
|
||||
try {
|
||||
$roomShare = $this->mapper->findByRoomAndEntity($roomId, $shareWith, $shareType);
|
||||
|
||||
$roomShare->setRoomId($roomId);
|
||||
$roomShare->setShareType($shareType);
|
||||
$roomShare->setShareWith($shareWith);
|
||||
$roomShare->setPermission($permission);
|
||||
return $this->update($roomShare->getId(), $roomId, $shareType, $shareWith, $permission);
|
||||
} catch (DoesNotExistException $e) {
|
||||
$roomShare = new RoomShare();
|
||||
|
||||
return $this->mapper->insert($roomShare);
|
||||
$roomShare->setRoomId($roomId);
|
||||
$roomShare->setShareType($shareType);
|
||||
$roomShare->setShareWith($shareWith);
|
||||
$roomShare->setPermission($permission);
|
||||
|
||||
return $this->mapper->insert($roomShare);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(int $id, int $roomId, int $shareType, string $shareWith, int $permission): RoomShare
|
||||
|
|
|
@ -15,6 +15,7 @@ use OCA\BigBlueButton\Controller\JoinController;
|
|||
use OCA\BigBlueButton\BigBlueButton\API;
|
||||
use OCA\BigBlueButton\NotFoundException;
|
||||
use OCA\BigBlueButton\Db\Room;
|
||||
use OCA\BigBlueButton\Permission;
|
||||
|
||||
class JoinControllerTest extends TestCase
|
||||
{
|
||||
|
@ -25,6 +26,7 @@ class JoinControllerTest extends TestCase
|
|||
private $urlGenerator;
|
||||
private $controller;
|
||||
private $api;
|
||||
private $permission;
|
||||
private $room;
|
||||
|
||||
public function setUp(): void
|
||||
|
@ -38,6 +40,7 @@ class JoinControllerTest extends TestCase
|
|||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->urlGenerator = $this->createMock(IURLGenerator::class);
|
||||
$this->api = $this->createMock(API::class);
|
||||
$this->permission = $this->createMock(Permission::class);
|
||||
|
||||
$this->controller = new JoinController(
|
||||
'bbb',
|
||||
|
@ -47,7 +50,8 @@ class JoinControllerTest extends TestCase
|
|||
$this->urlGenerator,
|
||||
$this->userSession,
|
||||
$this->config,
|
||||
$this->api
|
||||
$this->api,
|
||||
$this->permission
|
||||
);
|
||||
|
||||
$this->room = new Room();
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Room } from './Api';
|
||||
import EditRoomDialog from './EditRoomDialog';
|
||||
|
||||
type Props = {
|
||||
room: Room;
|
||||
updateProperty: (key: string, value: string | boolean | number) => Promise<void>;
|
||||
}
|
||||
|
||||
const EditRoom: React.FC<Props> = ({ room, updateProperty }) => {
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<a className="icon icon-edit icon-visible"
|
||||
onClick={ev => { ev.preventDefault(), setOpen(true); }}
|
||||
title={t('bbb', 'Edit')} />
|
||||
|
||||
<EditRoomDialog room={room} updateProperty={updateProperty} open={open} setOpen={setOpen} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditRoom;
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Access, Room } from './Api';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Access, Room, Permission, RoomShare, api } from './Api';
|
||||
import Dialog from './Dialog';
|
||||
import ShareWith from './ShareWith';
|
||||
import { SubmitInput } from './SubmitInput';
|
||||
|
@ -13,12 +13,29 @@ const descriptions: { [key: string]: string } = {
|
|||
};
|
||||
|
||||
type Props = {
|
||||
room: Room;
|
||||
updateProperty: (key: string, value: string | boolean | number) => Promise<void>;
|
||||
room: Room;
|
||||
updateProperty: (key: string, value: string | boolean | number) => Promise<void>;
|
||||
open: boolean;
|
||||
setOpen: (open: boolean) => void;
|
||||
}
|
||||
|
||||
const EditRoomDialog: React.FC<Props> = ({ room, updateProperty }) => {
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const EditRoomDialog: React.FC<Props> = ({ room, updateProperty, open, setOpen }) => {
|
||||
const [shares, setShares] = useState<RoomShare[]>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
return;
|
||||
}
|
||||
|
||||
api.getRoomShares(room.id).then(roomShares => {
|
||||
console.log(room.name, roomShares);
|
||||
setShares(roomShares);
|
||||
}).catch(err => {
|
||||
console.warn('Could not load room shares.', err);
|
||||
|
||||
setShares([]);
|
||||
});
|
||||
}, [room.id, open]);
|
||||
|
||||
function inputElement(label: string, field: string, type: 'text' | 'number' = 'text') {
|
||||
return (
|
||||
|
@ -33,7 +50,7 @@ const EditRoomDialog: React.FC<Props> = ({ room, updateProperty }) => {
|
|||
);
|
||||
}
|
||||
|
||||
function selectElement(label: string, field: string, value: string, options: {[key: string]: string}, onChange: (value: string) => void) {
|
||||
function selectElement(label: string, field: string, value: string, options: { [key: string]: string }, onChange: (value: string) => void) {
|
||||
return (
|
||||
<div className="bbb-form-element">
|
||||
<label htmlFor={`bbb-${field}`}>
|
||||
|
@ -54,49 +71,47 @@ const EditRoomDialog: React.FC<Props> = ({ room, updateProperty }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<a className="icon icon-edit icon-visible"
|
||||
onClick={ev => { ev.preventDefault(), setOpen(true); }}
|
||||
title={t('bbb', 'Edit')} />
|
||||
<Dialog open={open} onClose={() => setOpen(false)} title={t('bbb', 'Edit "{room}"', { room: room.name })}>
|
||||
{inputElement(t('bbb', 'Name'), 'name')}
|
||||
{inputElement(t('bbb', 'Welcome'), 'welcome')}
|
||||
{inputElement(t('bbb', 'Participant limit'), 'maxParticipants', 'number')}
|
||||
|
||||
<Dialog open={open} onClose={() => setOpen(false)} title={t('bbb', 'Edit "{room}"', { room: room.name })}>
|
||||
{inputElement(t('bbb', 'Name'), 'name')}
|
||||
{inputElement(t('bbb', 'Welcome'), 'welcome')}
|
||||
{inputElement(t('bbb', 'Participant limit'), 'maxParticipants', 'number')}
|
||||
{selectElement(t('bbb', 'Access'), 'access', room.access, {
|
||||
[Access.Public]: t('bbb', 'Public'),
|
||||
[Access.Password]: t('bbb', 'Internal + Password protection for guests'),
|
||||
[Access.WaitingRoom]: t('bbb', 'Internal + Waiting room for guests'),
|
||||
[Access.Internal]: t('bbb', 'Internal'),
|
||||
[Access.InternalRestricted]: t('bbb', 'Internal restricted'),
|
||||
}, (value) => {
|
||||
console.log('access', value);
|
||||
updateProperty('access', value);
|
||||
})}
|
||||
|
||||
{selectElement(t('bbb', 'Access'), 'access', room.access, {
|
||||
[Access.Public]: t('bbb', 'Public'),
|
||||
[Access.Password]: t('bbb', 'Internal + Password protection for guests'),
|
||||
[Access.WaitingRoom]: t('bbb', 'Internal + Waiting room for guests'),
|
||||
[Access.Internal]: t('bbb', 'Internal'),
|
||||
// [Access.InternalRestricted]: t('bbb', 'Restricted'),
|
||||
}, (value) => {
|
||||
console.log('access', value);
|
||||
updateProperty('access', value);
|
||||
})}
|
||||
{room.access === Access.InternalRestricted && <div className="bbb-form-element bbb-form-shareWith">
|
||||
<ShareWith permission={Permission.User} room={room} shares={shares} setShares={setShares} />
|
||||
</div>}
|
||||
|
||||
<div className="bbb-form-element">
|
||||
<label htmlFor={'bbb-moderator'}>
|
||||
<h3>Moderator</h3>
|
||||
</label>
|
||||
<div className="bbb-form-element">
|
||||
<label htmlFor={'bbb-moderator'}>
|
||||
<h3>Moderator</h3>
|
||||
</label>
|
||||
|
||||
<ShareWith room={room} />
|
||||
</div>
|
||||
<ShareWith permission={Permission.Moderator} room={room} shares={shares} setShares={setShares} />
|
||||
</div>
|
||||
|
||||
<h3>{t('bbb', 'Miscellaneous')}</h3>
|
||||
<h3>{t('bbb', 'Miscellaneous')}</h3>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<input id={`bbb-record-${room.id}`}
|
||||
type="checkbox"
|
||||
className="checkbox"
|
||||
checked={room.record}
|
||||
onChange={(event) => updateProperty('record', event.target.checked)} />
|
||||
<label htmlFor={`bbb-record-${room.id}`}>{t('bbb', 'Recording')}</label>
|
||||
</div>
|
||||
<em>{descriptions.recording}</em>
|
||||
<input id={`bbb-record-${room.id}`}
|
||||
type="checkbox"
|
||||
className="checkbox"
|
||||
checked={room.record}
|
||||
onChange={(event) => updateProperty('record', event.target.checked)} />
|
||||
<label htmlFor={`bbb-record-${room.id}`}>{t('bbb', 'Recording')}</label>
|
||||
</div>
|
||||
</Dialog>
|
||||
</>
|
||||
<em>{descriptions.recording}</em>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import { api, Recording, Room } from './Api';
|
||||
import EditRoomDialog from './EditRoomDialog';
|
||||
import EditRoom from './EditRoom';
|
||||
import RecordingRow from './RecordingRow';
|
||||
import EditableValue from './EditableValue';
|
||||
|
||||
|
@ -184,7 +184,7 @@ const RoomRow: React.FC<Props> = (props) => {
|
|||
</td>
|
||||
<td><RecordingsNumber recordings={recordings} showRecordings={showRecordings} setShowRecordings={setShowRecordings} /></td>
|
||||
<td className="edit icon-col">
|
||||
<EditRoomDialog room={props.room} updateProperty={updateRoom} />
|
||||
<EditRoom room={props.room} updateProperty={updateRoom} />
|
||||
</td>
|
||||
<td className="remove icon-col">
|
||||
<a className="icon icon-delete icon-visible"
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
height: 32px;
|
||||
width: 32px;
|
||||
overflow: hidden;
|
||||
|
||||
.icon-group-white {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #a9a9a9;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
|
@ -51,3 +58,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bbb-form-shareWith {
|
||||
margin-top: -1.5em;
|
||||
}
|
|
@ -3,28 +3,23 @@ import { api, ShareWith, ShareType, RoomShare, Room, Permission } from './Api';
|
|||
import './ShareWith.scss';
|
||||
|
||||
type Props = {
|
||||
room: Room;
|
||||
room: Room;
|
||||
permission: Permission.User | Permission.Moderator;
|
||||
shares: RoomShare[] | undefined;
|
||||
setShares: (shares: RoomShare[]) => void;
|
||||
}
|
||||
|
||||
const SearchInput: React.FC<Props> = ({ room }) => {
|
||||
const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setShares }) => {
|
||||
const [search, setSearch] = useState<string>('');
|
||||
const [hasFocus, setFocus] = useState<boolean>(false);
|
||||
const [recommendations, setRecommendations] = useState<ShareWith>();
|
||||
const [searchResults, setSearchResults] = useState<ShareWith>();
|
||||
const [shares, setShares] = useState<RoomShare[]>();
|
||||
|
||||
const userShares = shares ? shares.filter(share => share.shareType === ShareType.User).map(share => share.shareWith) : [];
|
||||
const groupShares = shares ? shares.filter(share => share.shareType === ShareType.Group).map(share => share.shareWith) : [];
|
||||
const shares = (allShares && permission === Permission.Moderator) ?
|
||||
allShares.filter(share => share.permission !== Permission.User) : allShares;
|
||||
|
||||
useEffect(() => {
|
||||
api.getRoomShares(room.id).then(roomShares => {
|
||||
setShares(roomShares);
|
||||
}).catch(err => {
|
||||
console.warn('Could not load room shares.', err);
|
||||
|
||||
setShares([]);
|
||||
});
|
||||
}, [room.id]);
|
||||
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) : [];
|
||||
|
||||
useEffect(() => {
|
||||
api.searchShareWith(search).then(result => {
|
||||
|
@ -37,25 +32,40 @@ const SearchInput: React.FC<Props> = ({ room }) => {
|
|||
}, []);
|
||||
|
||||
async function addRoomShare(shareWith: string, shareType: number, displayName: string) {
|
||||
const roomShare = await api.createRoomShare(room.id, shareType, shareWith, Permission.Moderator);
|
||||
const roomShare = await api.createRoomShare(room.id, shareType, shareWith, permission);
|
||||
|
||||
roomShare.shareWithDisplayName = displayName;
|
||||
|
||||
setShares([...(shares || []), roomShare]);
|
||||
console.log('addRoomShare', allShares, roomShare);
|
||||
|
||||
const newShares = allShares ? [...allShares] : [];
|
||||
const index = newShares.findIndex(share => share.id === roomShare.id);
|
||||
|
||||
if (index > -1) {
|
||||
newShares[index] = roomShare;
|
||||
} else {
|
||||
newShares.push(roomShare);
|
||||
}
|
||||
|
||||
console.log('newroomshares', newShares);
|
||||
|
||||
setShares(newShares);
|
||||
}
|
||||
|
||||
async function deleteRoomShare(id: number) {
|
||||
console.log('deleteRoomShare', id);
|
||||
|
||||
await api.deleteRoomShare(id);
|
||||
|
||||
setShares(shares?.filter(share => share.id !== id));
|
||||
setShares((allShares ? [...allShares] : []).filter(share => share.id !== id));
|
||||
}
|
||||
|
||||
function renderSearchResults(options: ShareWith) {
|
||||
return (
|
||||
<ul className="bbb-selection">
|
||||
{[
|
||||
...options.users.filter(user => !userShares.includes(user.value.shareWith)),
|
||||
...options.groups.filter(group => !groupShares.includes(group.value.shareWith)),
|
||||
...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)}>
|
||||
{option.label}{option.value.shareType === ShareType.Group ? ` (${t('bbb', 'Group')})` : ''}
|
||||
|
@ -90,9 +100,10 @@ const SearchInput: React.FC<Props> = ({ room }) => {
|
|||
<li key={share.id} className="bbb-shareWith__item">
|
||||
<div className="avatardiv">
|
||||
{avatarUrl && <img src={avatarUrl} alt={`Avatar from ${displayName}`} />}
|
||||
{share.shareType === ShareType.Group && <span className="icon-group-white"></span>}
|
||||
</div>
|
||||
<div className="bbb-shareWith__item__label">
|
||||
<h5>{displayName}{share.shareType === ShareType.Group ? ` (${t('bbb', 'Group')})` : ''}</h5>
|
||||
<h5>{displayName}{(share.permission === Permission.Moderator && permission === Permission.User) ? ` (${t('bbb', 'moderator')})` : ''}</h5>
|
||||
</div>
|
||||
{share.id > -1 && <div className="bbb-shareWith__item__action">
|
||||
<a className="icon icon-delete icon-visible"
|
||||
|
@ -126,4 +137,4 @@ const SearchInput: React.FC<Props> = ({ room }) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default SearchInput;
|
||||
export default ShareWith;
|
Loading…
Reference in New Issue