mirror of https://github.com/sualko/cloud_bbb
refactor: use consistent indentation for ts
parent
4b901f205a
commit
938e8ee68c
|
@ -28,5 +28,6 @@ module.exports = {
|
||||||
'comma-dangle': ['error', 'always-multiline'],
|
'comma-dangle': ['error', 'always-multiline'],
|
||||||
'array-bracket-newline': ['error', 'consistent'],
|
'array-bracket-newline': ['error', 'consistent'],
|
||||||
'quote-props': ['error', 'as-needed'],
|
'quote-props': ['error', 'as-needed'],
|
||||||
|
'indent': ['warn', 'tab'],
|
||||||
},
|
},
|
||||||
}
|
}
|
|
@ -12,20 +12,20 @@ enum SortOrder { DESC = -1, ASC = 1 };
|
||||||
function sortRooms(key: SortKey, orderBy: SortOrder) {
|
function sortRooms(key: SortKey, orderBy: SortOrder) {
|
||||||
return (a: Room, b: Room) => {
|
return (a: Room, b: Room) => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'name':
|
case 'name':
|
||||||
case 'welcome':
|
case 'welcome':
|
||||||
return a[key].localeCompare(b[key]) * orderBy;
|
return a[key].localeCompare(b[key]) * orderBy;
|
||||||
case 'maxParticipants':
|
case 'maxParticipants':
|
||||||
return (a.maxParticipants - b.maxParticipants) * orderBy;
|
return (a.maxParticipants - b.maxParticipants) * orderBy;
|
||||||
case 'record':
|
case 'record':
|
||||||
if (a.record && !b.record) {
|
if (a.record && !b.record) {
|
||||||
return 1 * orderBy;
|
return 1 * orderBy;
|
||||||
}
|
}
|
||||||
if (!a.record && b.record) {
|
if (!a.record && b.record) {
|
||||||
return -1 * orderBy;
|
return -1 * orderBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,27 +5,27 @@ type Props = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const NewRoomForm: React.FC<Props> = (props) => {
|
const NewRoomForm: React.FC<Props> = (props) => {
|
||||||
const [name, setName] = useState('');
|
const [name, setName] = useState('');
|
||||||
|
|
||||||
function addRoom(ev: React.FormEvent) {
|
function addRoom(ev: React.FormEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
props.addRoom(name);
|
props.addRoom(name);
|
||||||
|
|
||||||
setName('');
|
setName('');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form action="#" onSubmit={addRoom}>
|
<form action="#" onSubmit={addRoom}>
|
||||||
<input
|
<input
|
||||||
className="newgroup-name"
|
className="newgroup-name"
|
||||||
value={name}
|
value={name}
|
||||||
placeholder="Room name"
|
placeholder="Room name"
|
||||||
onChange={(event) => {setName(event.target.value)}} />
|
onChange={(event) => {setName(event.target.value)}} />
|
||||||
|
|
||||||
<input type="submit" value="Create" />
|
<input type="submit" value="Create" />
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NewRoomForm;
|
export default NewRoomForm;
|
|
@ -19,87 +19,87 @@ type EditableValueProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditableValue: React.FC<EditableValueProps> = ({ setValue, setActive, active, field, value, type }) => {
|
const EditableValue: React.FC<EditableValueProps> = ({ setValue, setActive, active, field, value, type }) => {
|
||||||
if (active === field) {
|
if (active === field) {
|
||||||
return <SubmitInput
|
return <SubmitInput
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
onSubmitValue={(value) => setValue(field, type === 'number' ? parseInt(value):value)}
|
onSubmitValue={(value) => setValue(field, type === 'number' ? parseInt(value):value)}
|
||||||
onClick={event => event.stopPropagation()}
|
onClick={event => event.stopPropagation()}
|
||||||
initialValue={value}
|
initialValue={value}
|
||||||
type={type}
|
type={type}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClick(ev) {
|
function onClick(ev) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
||||||
setActive(field);
|
setActive(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <a className="action-rename" onClick={onClick}>{value}</a>;
|
return <a className="action-rename" onClick={onClick}>{value}</a>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RoomRow: React.FC<Props> = (props) => {
|
const RoomRow: React.FC<Props> = (props) => {
|
||||||
const [activeEdit, setActiveEdit] = useState('');
|
const [activeEdit, setActiveEdit] = useState('');
|
||||||
const room = props.room;
|
const room = props.room;
|
||||||
|
|
||||||
function updateRoom(key: string, value: string|boolean|number) {
|
function updateRoom(key: string, value: string|boolean|number) {
|
||||||
props.updateRoom({
|
props.updateRoom({
|
||||||
...props.room,
|
...props.room,
|
||||||
[key]: value,
|
[key]: value,
|
||||||
});
|
});
|
||||||
|
|
||||||
setActiveEdit('');
|
setActiveEdit('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteRow(ev: MouseEvent) {
|
function deleteRow(ev: MouseEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
OC.dialogs.confirm(
|
OC.dialogs.confirm(
|
||||||
t('bbb', 'Are you sure you want to delete "{name}"? This operation can not be undone', { name: room.name }),
|
t('bbb', 'Are you sure you want to delete "{name}"? This operation can not be undone', { name: room.name }),
|
||||||
t('bbb', 'Delete "{name}"?', { name: room.name }),
|
t('bbb', 'Delete "{name}"?', { name: room.name }),
|
||||||
confirmed => {
|
confirmed => {
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
props.deleteRoom(room.id);
|
props.deleteRoom(room.id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function edit(field: string, type: 'text' | 'number' = 'text'){
|
function edit(field: string, type: 'text' | 'number' = 'text'){
|
||||||
return <EditableValue field={field} value={room[field]} active={activeEdit} setActive={setActiveEdit} setValue={updateRoom} type={type} />
|
return <EditableValue field={field} value={room[field]} active={activeEdit} setActive={setActiveEdit} setValue={updateRoom} type={type} />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={room.id}>
|
<tr key={room.id}>
|
||||||
<td className="share icon-col">
|
<td className="share icon-col">
|
||||||
<CopyToClipboard text={window.location.origin + api.getUrl(`b/${room.uid}`)}>
|
<CopyToClipboard text={window.location.origin + api.getUrl(`b/${room.uid}`)}>
|
||||||
<span className="icon icon-clippy icon-visible copy-to-clipboard" ></span>
|
<span className="icon icon-clippy icon-visible copy-to-clipboard" ></span>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
</td>
|
</td>
|
||||||
<td className="start icon-col">
|
<td className="start icon-col">
|
||||||
<a href={api.getUrl(`b/${room.uid}`)} className="icon icon-play icon-visible" target="_blank" rel="noopener noreferrer"></a>
|
<a href={api.getUrl(`b/${room.uid}`)} className="icon icon-play icon-visible" target="_blank" rel="noopener noreferrer"></a>
|
||||||
</td>
|
</td>
|
||||||
<td className="name">
|
<td className="name">
|
||||||
{edit('name')}
|
{edit('name')}
|
||||||
</td>
|
</td>
|
||||||
<td className="welcome">
|
<td className="welcome">
|
||||||
{edit('welcome')}
|
{edit('welcome')}
|
||||||
</td>
|
</td>
|
||||||
<td className="max-participants">
|
<td className="max-participants">
|
||||||
{edit('maxParticipants', 'number')}
|
{edit('maxParticipants', 'number')}
|
||||||
</td>
|
</td>
|
||||||
<td className="record">
|
<td className="record">
|
||||||
<input id={`bbb-record-${room.id}`} type="checkbox" className="checkbox" checked={room.record} onChange={(event) => updateRoom('record', event.target.checked)} />
|
<input id={`bbb-record-${room.id}`} type="checkbox" className="checkbox" checked={room.record} onChange={(event) => updateRoom('record', event.target.checked)} />
|
||||||
<label htmlFor={`bbb-record-${room.id}`}></label>
|
<label htmlFor={`bbb-record-${room.id}`}></label>
|
||||||
</td>
|
</td>
|
||||||
<td className="remove icon-col">
|
<td className="remove icon-col">
|
||||||
<a className="icon icon-delete icon-visible"
|
<a className="icon icon-delete icon-visible"
|
||||||
onClick={deleteRow as any}
|
onClick={deleteRow as any}
|
||||||
title="Delete" />
|
title="Delete" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RoomRow;
|
export default RoomRow;
|
|
@ -7,11 +7,11 @@ export interface SortArrowProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SortArrow({name, value, direction}: SortArrowProps) {
|
export function SortArrow({name, value, direction}: SortArrowProps) {
|
||||||
if (name === value) {
|
if (name === value) {
|
||||||
return (<span className='sort_arrow'>
|
return (<span className='sort_arrow'>
|
||||||
{direction < 0 ? '▼' : '▲'}
|
{direction < 0 ? '▼' : '▲'}
|
||||||
</span>);
|
</span>);
|
||||||
} else {
|
} else {
|
||||||
return <span/>;
|
return <span/>;
|
||||||
}
|
}
|
||||||
}
|
}
|
10
ts/admin.ts
10
ts/admin.ts
|
@ -1,10 +1,10 @@
|
||||||
declare const OCP: any;
|
declare const OCP: any;
|
||||||
|
|
||||||
$(() => {
|
$(() => {
|
||||||
$('#bbb-settings form').submit(function (ev) {
|
$('#bbb-settings form').submit(function (ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
OCP.AppConfig.setValue('bbb', 'api.url', this['api.url'].value);
|
OCP.AppConfig.setValue('bbb', 'api.url', this['api.url'].value);
|
||||||
OCP.AppConfig.setValue('bbb', 'api.secret', this['api.secret'].value);
|
OCP.AppConfig.setValue('bbb', 'api.secret', this['api.secret'].value);
|
||||||
})
|
})
|
||||||
});
|
});
|
144
ts/filelist.ts
144
ts/filelist.ts
|
@ -5,97 +5,97 @@ import { Room } from './Manager/Api';
|
||||||
declare const OCA: any;
|
declare const OCA: any;
|
||||||
|
|
||||||
class BigBlueButton {
|
class BigBlueButton {
|
||||||
public async getRooms(): Promise<Room[]> {
|
public async getRooms(): Promise<Room[]> {
|
||||||
const response = await axios.get(OC.generateUrl('/apps/bbb/rooms'))
|
const response = await axios.get(OC.generateUrl('/apps/bbb/rooms'))
|
||||||
|
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(() => {
|
$(() => {
|
||||||
|
|
||||||
if (!OCA?.Files?.fileActions) {
|
if (!OCA?.Files?.fileActions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mimeTypes = [
|
const mimeTypes = [
|
||||||
'application/pdf',
|
'application/pdf',
|
||||||
'application/vnd.oasis.opendocument.presentation',
|
'application/vnd.oasis.opendocument.presentation',
|
||||||
'application/vnd.oasis.opendocument.text',
|
'application/vnd.oasis.opendocument.text',
|
||||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
'application/msword',
|
'application/msword',
|
||||||
'application/vnd.ms-powerpoint',
|
'application/vnd.ms-powerpoint',
|
||||||
];
|
];
|
||||||
const bbb = new BigBlueButton();
|
const bbb = new BigBlueButton()
|
||||||
|
|
||||||
bbb.getRooms().then(rooms => {
|
bbb.getRooms().then(rooms => {
|
||||||
rooms.forEach(room => {
|
rooms.forEach(room => {
|
||||||
mimeTypes.forEach(mime => registerFileAction(mime, room.id, room.uid, room.name));
|
mimeTypes.forEach(mime => registerFileAction(mime, room.id, room.uid, room.name));
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
function registerFileAction(mime, id, uid, name) {
|
function registerFileAction(mime, id, uid, name) {
|
||||||
OCA.Files.fileActions.registerAction({
|
OCA.Files.fileActions.registerAction({
|
||||||
name: 'bbb-' + id,
|
name: 'bbb-' + id,
|
||||||
displayName: name,
|
displayName: name,
|
||||||
mime,
|
mime,
|
||||||
permissions: OC.PERMISSION_SHARE,
|
permissions: OC.PERMISSION_SHARE,
|
||||||
icon: OC.imagePath('bbb', 'app-dark.svg'),
|
icon: OC.imagePath('bbb', 'app-dark.svg'),
|
||||||
actionHandler: (fileName, context) => {
|
actionHandler: (fileName, context) => {
|
||||||
share(context.fileInfoModel.getFullPath(), fileName, uid);
|
share(context.fileInfoModel.getFullPath(), fileName, uid);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function share(path: string, filename: string, roomUid) {
|
async function share(path: string, filename: string, roomUid) {
|
||||||
const id = await createShare(path);
|
const id = await createShare(path);
|
||||||
const shareUrl = await configureShare(id);
|
const shareUrl = await configureShare(id);
|
||||||
const joinUrl = generateUrl('/apps/bbb/b/{uid}?u={url}&filename={filename}', {
|
const joinUrl = generateUrl('/apps/bbb/b/{uid}?u={url}&filename={filename}', {
|
||||||
uid: roomUid,
|
uid: roomUid,
|
||||||
url: shareUrl + '/download',
|
url: shareUrl + '/download',
|
||||||
filename,
|
filename,
|
||||||
});
|
});
|
||||||
|
|
||||||
window.open(joinUrl, '_blank', 'noopener,noreferrer');
|
window.open(joinUrl, '_blank', 'noopener,noreferrer');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createShare(path: string): Promise<number> {
|
async function createShare(path: string): Promise<number> {
|
||||||
const url = generateOcsUrl('apps/files_sharing/api/v1', 2) + 'shares';
|
const url = generateOcsUrl('apps/files_sharing/api/v1', 2) + 'shares';
|
||||||
|
|
||||||
const createResponse = await axios.post(url, {
|
const createResponse = await axios.post(url, {
|
||||||
path,
|
path,
|
||||||
shareType: OC.Share.SHARE_TYPE_LINK,
|
shareType: OC.Share.SHARE_TYPE_LINK,
|
||||||
note: 'foobar foobar foobar',
|
note: 'foobar foobar foobar',
|
||||||
expireDate: '2020-07-01',
|
expireDate: '2020-07-01',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { meta, data } = createResponse.data.ocs;
|
const { meta, data } = createResponse.data.ocs;
|
||||||
|
|
||||||
if (meta.statuscode !== 200) {
|
if (meta.statuscode !== 200) {
|
||||||
throw new Error('Failed to create share');
|
throw new Error('Failed to create share');
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.id;
|
return data.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function configureShare(id: number): Promise<string> {
|
async function configureShare(id: number): Promise<string> {
|
||||||
const url = generateOcsUrl('apps/files_sharing/api/v1', 2) + 'shares/' + id;
|
const url = generateOcsUrl('apps/files_sharing/api/v1', 2) + 'shares/' + id;
|
||||||
|
|
||||||
const tomorrow = new Date();
|
const tomorrow = new Date();
|
||||||
tomorrow.setDate(new Date().getDate() + 1);
|
tomorrow.setDate(new Date().getDate() + 1);
|
||||||
|
|
||||||
const updateResponse = await axios.put(url, {
|
const updateResponse = await axios.put(url, {
|
||||||
expireDate: tomorrow.toISOString().split('T')[0],
|
expireDate: tomorrow.toISOString().split('T')[0],
|
||||||
note: 'BigBlueButton',
|
note: 'BigBlueButton',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { meta, data } = updateResponse.data.ocs;
|
const { meta, data } = updateResponse.data.ocs;
|
||||||
|
|
||||||
if (meta.statuscode !== 200) {
|
if (meta.statuscode !== 200) {
|
||||||
throw new Error('Failed to configure share');
|
throw new Error('Failed to configure share');
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.url;
|
return data.url;
|
||||||
}
|
}
|
||||||
});
|
});
|
Loading…
Reference in New Issue