Compare commits

..

14 Commits

Author SHA1 Message Date
Klaus c1e42a836e
Merge pull request #200 from sualko/feat-filelist-dialog
feat: use modal to send file
2022-03-16 15:21:55 +01:00
sualko 525d3fa525 feat: use modal to send file
fix #5
2022-03-16 15:11:31 +01:00
Klaus 9a974fcd47
Merge pull request #195 from SpechtD/feat-send-all-users-to-lobby-issue192
feat: send all users to lobby
2022-03-16 13:42:16 +01:00
Klaus dade62576e
Merge pull request #198 from sualko/dependabot/npm_and_yarn/node-fetch-2.6.7
chore(deps): bump node-fetch from 2.6.6 to 2.6.7
2022-03-16 12:03:22 +01:00
sualko 4cbb88cb64 Merge pull request #197 from arawa/cloud_bbb/arawa-master 2022-03-16 11:59:54 +01:00
Thierry Kauffmann 0f4c1682f5 feat: add support for analytics callback url
fix #194
2022-03-16 11:58:38 +01:00
Klaus 96a3a4527d
Merge pull request #199 from sualko/chore-upgrade-dependencies
upgrade required Node version and dependencies
2022-03-16 11:44:08 +01:00
sualko 02168650a4 chore: upgrade required Node version and deps 2022-03-16 11:27:11 +01:00
dependabot[bot] a3b01dbc64
chore(deps): bump node-fetch from 2.6.6 to 2.6.7
Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.6 to 2.6.7.
- [Release notes](https://github.com/node-fetch/node-fetch/releases)
- [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.6...v2.6.7)

---
updated-dependencies:
- dependency-name: node-fetch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-16 09:36:34 +00:00
Klaus a28ab208ef
Merge pull request #190 from sualko/dependabot/npm_and_yarn/follow-redirects-1.14.8
chore(deps): bump follow-redirects from 1.14.7 to 1.14.8
2022-03-16 10:36:00 +01:00
Klaus c926cc63d7
Merge pull request #189 from sualko/dependabot/npm_and_yarn/node-sass-7.0.0
chore(deps-dev): bump node-sass from 4.14.1 to 7.0.0
2022-03-16 10:35:51 +01:00
Specht, David b7aee468b2 feat: send all users to lobby
closes #192
2022-03-08 15:09:18 +01:00
dependabot[bot] 48f0995b21
chore(deps): bump follow-redirects from 1.14.7 to 1.14.8
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-13 11:48:06 +00:00
dependabot[bot] 07611b2a7b
chore(deps-dev): bump node-sass from 4.14.1 to 7.0.0
Bumps [node-sass](https://github.com/sass/node-sass) from 4.14.1 to 7.0.0.
- [Release notes](https://github.com/sass/node-sass/releases)
- [Changelog](https://github.com/sass/node-sass/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sass/node-sass/compare/v4.14.1...v7.0.0)

---
updated-dependencies:
- dependency-name: node-sass
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-10 22:13:00 +00:00
12 changed files with 2685 additions and 4206 deletions

View File

@ -28,7 +28,8 @@ module.exports = {
'comma-dangle': ['error', 'always-multiline'],
'array-bracket-newline': ['error', 'consistent'],
'quote-props': ['error', 'as-needed'],
'indent': ['warn', 'tab'],
semi: ["error", "always"],
indent: ['warn', 'tab'],
semi: ['error', 'always'],
'@typescript-eslint/ban-types': 'off',
},
}

View File

@ -70,11 +70,12 @@ check if those values are correct. Therefore this is not the recommended way.
The syntax to set all settings is `occ config:app:set bbb KEY --value "VALUE"`.
Key | Description
--------------------- | ------------------------------------------------------------------------------------
--------------------------------- | ------------------------------------------------------------------------------------
`app.navigation` | Set to `true` to show navigation entry
`app.navigation.name` | Defines the navigation label. Default "BigBlueButton".
`api.url` | URL to your BBB server. Should start with `https://`
`api.secret` | Secret of your BBB server
`api.meta_analytics-callback-url` | URL which gets called after meetings ends to generate statistics. See [bbb-analytics](https://github.com/betagouv/bbb-analytics).
`app.shortener` | Value of your shortener service. Should start with `https://` and contain `{token}`.
`avatar.path` | Absolute path to an optional avatar cache directory.
`avatar.url` | URL which serves `avatar.path` to be used as avatar cache.

View File

@ -106,7 +106,9 @@ class API {
$joinMeetingParams->setCreateTime(sprintf("%.0f", $creationTime));
$joinMeetingParams->setJoinViaHtml5(true);
$joinMeetingParams->setRedirect(true);
$joinMeetingParams->setGuest($uid === null);
// set the guest parameter for everyone but moderators to send all users to the waiting room if setting is selected
$joinMeetingParams->setGuest((($room->access === Room::ACCESS_WAITING_ROOM_ALL) && !$isModerator) || $uid === null);
$joinMeetingParams->addUserData('bbb_listen_only_mode', $room->getListenOnly());
@ -175,6 +177,13 @@ class API {
$createMeetingParams->addMeta('bbb-origin', \method_exists($this->defaults, 'getProductName') ? $this->defaults->getProductName() : 'Nextcloud');
$createMeetingParams->addMeta('bbb-origin-server-name', $this->request->getServerHost());
$analyticsCallbackUrl = $this->config->getAppValue('bbb', 'api.meta_analytics-callback-url');
if (!empty($analyticsCallbackUrl)) {
// For more details: https://github.com/bigbluebutton/bigbluebutton/blob/develop/record-and-playback/core/scripts/post_events/post_events_analytics_callback.rb
$createMeetingParams->addMeta('analytics-callback-url', $analyticsCallbackUrl);
$createMeetingParams->setMeetingKeepEvents(true);
}
$mac = $this->crypto->calculateHMAC($room->uid);
$endMeetingUrl = $this->urlGenerator->linkToRouteAbsolute('bbb.hook.meetingEnded', ['token' => $room->uid, 'mac' => $mac]);
@ -199,7 +208,7 @@ class API {
$createMeetingParams->addPresentation($presentation->getUrl(), null, $presentation->getFilename());
}
if ($room->access === Room::ACCESS_WAITING_ROOM) {
if ($room->access === Room::ACCESS_WAITING_ROOM || $room->access === Room::ACCESS_WAITING_ROOM_ALL) {
$createMeetingParams->setGuestPolicyAskModerator();
}

View File

@ -47,10 +47,11 @@ class Room extends Entity implements JsonSerializable {
public const ACCESS_PUBLIC = 'public';
public const ACCESS_PASSWORD = 'password';
public const ACCESS_WAITING_ROOM = 'waiting_room';
public const ACCESS_WAITING_ROOM_ALL = 'waiting_room_all';
public const ACCESS_INTERNAL = 'internal';
public const ACCESS_INTERNAL_RESTRICTED = 'internal_restricted';
public const ACCESS = [self::ACCESS_PUBLIC, self::ACCESS_PASSWORD, self::ACCESS_WAITING_ROOM, self::ACCESS_INTERNAL, self::ACCESS_INTERNAL_RESTRICTED];
public const ACCESS = [self::ACCESS_PUBLIC, self::ACCESS_PASSWORD, self::ACCESS_WAITING_ROOM, self::ACCESS_WAITING_ROOM_ALL, self::ACCESS_INTERNAL, self::ACCESS_INTERNAL_RESTRICTED];
public $uid;
public $name;

View File

@ -14,7 +14,7 @@
"license": "agpl",
"private": true,
"scripts": {
"build": "NODE_ENV=production webpack --progress --hide-modules --config webpack.prod.js",
"build": "NODE_ENV=production webpack --progress --config webpack.prod.js",
"dev": "NODE_ENV=development webpack --progress --config webpack.dev.js",
"watch": "NODE_ENV=development webpack --progress --watch --config webpack.dev.js",
"test": "run-s --continue-on-error --print-label test:**",
@ -34,20 +34,20 @@
"release:publish": "node scripts/publish-release.js"
},
"dependencies": {
"@commitlint/cli": "^9.1.2",
"@commitlint/config-conventional": "^9.1.2",
"@commitlint/travis-cli": "^9.1.2",
"@commitlint/cli": "^16.2.3",
"@commitlint/config-conventional": "^16.2.1",
"@commitlint/travis-cli": "^16.2.3",
"@nextcloud/axios": "^1.3.2",
"@nextcloud/router": "^1.0.2",
"@nextcloud/router": "^2.0.0",
"@octokit/rest": "^18.0.4",
"archiver": "^5.0.0",
"colors": "^1.4.0",
"dotenv": "^8.2.0",
"execa": "^4.0.0",
"dotenv": "^16.0.0",
"execa": "^6.1.0",
"libxmljs": "^0.19.7",
"qrcode.react": "^1.0.1",
"qrcode.react": "^2.0.0",
"react-copy-to-clipboard": "^5.0.2",
"simple-git": "^2.20.1"
"simple-git": "^3.3.0"
},
"husky": {
"hooks": {
@ -60,58 +60,59 @@
"extends @nextcloud/browserslist-config"
],
"engines": {
"node": ">=10.0.0"
"node": ">=14.0.0"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.9.0",
"@nextcloud/browserslist-config": "^1.0.0",
"@nextcloud/browserslist-config": "^2.2.0",
"@nextcloud/eslint-plugin": "^2.0.0",
"@nextcloud/files": "^1.0.1",
"@types/bootstrap": "^4.3.2",
"@types/inquirer": "^7.3.1",
"@nextcloud/files": "^2.1.0",
"@types/bootstrap": "^5.1.9",
"@types/inquirer": "^8.2.0",
"@types/jquery": "^3.3.35",
"@types/node": "^14.6.2",
"@types/react": "^16.9.34",
"@types/webpack": "^4.41.12",
"@types/node": "^17.0.21",
"@types/react": "^17.0.40",
"@types/webpack": "^5.28.0",
"@types/webpack-env": "^1.15.2",
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"@typescript-eslint/eslint-plugin": "^5.15.0",
"@typescript-eslint/parser": "^5.15.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
"css-loader": "^4.2.2",
"dotenv-cli": "^3.1.0",
"eslint": "^7.8.0",
"eslint-config-standard": "^14.1.1",
"eslint-import-resolver-webpack": "^0.12.1",
"eslint-loader": "^4.0.2",
"css-loader": "^6.7.1",
"dotenv-cli": "^5.0.0",
"eslint": "^8.11.0",
"eslint-config-standard": "^16.0.3",
"eslint-import-resolver-webpack": "^0.13.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.19.0",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-standard": "^5.0.0",
"eslint-webpack-plugin": "^3.1.1",
"file-loader": "^6.0.0",
"husky": "^4.2.5",
"inquirer": "^7.1.0",
"node-sass": "^4.13.1",
"inquirer": "^8.2.1",
"install": "^0.13.0",
"node-sass": "^7.0.0",
"npm-run-all": "^4.1.5",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-flip-move": "^3.0.4",
"react-hot-loader": "^4.12.20",
"react-select": "^3.1.0",
"sass-loader": "^10.0.1",
"style-loader": "^1.2.0",
"stylelint": "^13.7.0",
"stylelint-config-recommended-scss": "^4.2.0",
"stylelint-scss": "^3.16.0",
"ts-loader": "^8.0.3",
"react-select": "^5.2.2",
"sass-loader": "^12.6.0",
"style-loader": "^3.3.1",
"stylelint": "^14.5.3",
"stylelint-config-recommended-scss": "^5.0.2",
"stylelint-scss": "^4.2.0",
"ts-loader": "^9.2.8",
"typescript": "^4.0.2",
"url-loader": "^4.0.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2",
"webpack-merge": "^5.1.3",
"webpack-node-externals": "^2.5.2"
"webpack-node-externals": "^3.0.0"
}
}

View File

@ -12,6 +12,7 @@ export enum Access {
Public = 'public',
Password = 'password',
WaitingRoom = 'waiting_room',
WaitingRoomAll = 'waiting_room_all',
Internal = 'internal',
InternalRestricted = 'internal_restricted',
}

View File

@ -4,6 +4,7 @@ export const AccessOptions = {
[Access.Public]: t('bbb', 'Public'),
[Access.Password]: t('bbb', 'Internal + Password protection for guests'),
[Access.WaitingRoom]: t('bbb', 'Internal + Waiting room for guests'),
[Access.WaitingRoomAll]: t('bbb', 'Waiting room for all users'),
[Access.Internal]: t('bbb', 'Internal'),
[Access.InternalRestricted]: t('bbb', 'Internal restricted'),
};

View File

@ -2,6 +2,9 @@ import axios from '@nextcloud/axios';
import { generateOcsUrl, generateUrl } from '@nextcloud/router';
import { api } from './Common/Api';
type OC_Dialogs_Message = (content: string, title: string, dialogType: 'notice' | 'alert' | 'warn' | 'none', buttons?: number, callback?: () => void, modal?: boolean, allowHtml?: boolean) => Promise<void>;
type ExtendedDialogs = typeof OC.dialogs & { message: OC_Dialogs_Message };
const mimeTypes = [
'application/pdf',
'application/vnd.oasis.opendocument.presentation',
@ -18,10 +21,16 @@ const mimeTypes = [
'image/png',
'text/plain',
'text/rtf',
];
] as const;
type MimeTypes = typeof mimeTypes[number];
async function createDirectShare(fileId: number): Promise<string> {
const url = generateOcsUrl('apps/dav/api/v1', 1) + 'direct';
const url = generateOcsUrl('apps/dav/api/v1/', undefined, {
ocsVersion: 1,
escape: true,
noRewrite: true,
}) + 'direct';
const createResponse = await axios.post(url, {
fileId,
});
@ -29,7 +38,7 @@ async function createDirectShare(fileId: number): Promise<string> {
return createResponse.data?.ocs?.data?.url;
}
async function share(fileId: number, filename: string, roomUid) {
async function share(fileId: number, filename: string, roomUid: string) {
const shareUrl = await createDirectShare(fileId);
const joinUrl = generateUrl('/apps/bbb/b/{uid}?u={url}&filename={filename}', {
uid: roomUid,
@ -40,15 +49,59 @@ async function share(fileId: number, filename: string, roomUid) {
window.open(joinUrl, '_blank', 'noopener,noreferrer');
}
function registerFileAction(fileActions, mime, id, uid, name) {
async function openDialog(fileId: number, filename: string) {
const initContent = '<div id="bbb-file-action"><span className="icon icon-loading-small icon-visible"></span></div>';
const title = t('bbb', 'Send file to BBB');
await (OC.dialogs as ExtendedDialogs).message(initContent, title, 'none', -1, undefined, true, true);
const rooms = await api.getRooms();
const container = $('#bbb-file-action').empty();
const table = $('<table>').appendTo(container);
table.attr('style', 'margin-top: 1em; width: 100%;');
for (const room of rooms) {
const row = $('<tr>');
const button = $('<button>');
button.text(t('bbb', 'Start'));
button.addClass('primary');
button.attr('type', 'button');
button.on('click', (ev) => {
ev.preventDefault();
share(fileId, filename, room.uid);
container.parents('.oc-dialog').find('.oc-dialog-close').trigger('click');
});
row.append($('<td>').append(button));
row.append($('<td>').attr('style', 'width: 100%;').text(room.name));
row.appendTo(table);
}
if (rooms.length > 0) {
const description = t('bbb', 'Please select the room in which you like to use the file "{filename}".', { filename });
container.append(description);
container.append(table);
} else {
container.append($('p').text(t('bbb', 'No rooms available!')));
}
}
function registerFileAction(fileActions: any, mime: MimeTypes) {
fileActions.registerAction({
name: 'bbb-' + id,
displayName: name,
name: 'bbb',
displayName: t('bbb', 'Send to BBB'),
mime,
permissions: OC.PERMISSION_SHARE,
icon: OC.imagePath('bbb', 'app-dark.svg'),
actionHandler: (fileName, context) => {
share(context.fileInfoModel.id, fileName, uid);
console.log('Action handler');
openDialog(context.fileInfoModel.id, fileName);
},
});
}
@ -63,11 +116,7 @@ const BBBFileListPlugin = {
return;
}
api.getRooms().then(rooms => {
rooms.forEach(room => {
mimeTypes.forEach(mime => registerFileAction(fileList.fileActions, mime, room.id, room.uid, room.name));
});
});
mimeTypes.forEach(mime => registerFileAction(fileList.fileActions, mime));
},
};

View File

@ -1,4 +1,6 @@
const path = require('path')
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
entry: {
@ -19,7 +21,7 @@ module.exports = {
],
waiting: [
path.join(__dirname, 'ts', 'waiting.ts'),
]
],
},
output: {
path: path.resolve(__dirname, './js'),
@ -50,11 +52,6 @@ module.exports = {
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.(js)$/,
use: 'eslint-loader',
enforce: 'pre',
},
{
test: /\.js$/,
loader: 'babel-loader',
@ -71,9 +68,10 @@ module.exports = {
],
},
plugins: [
new ESLintPlugin(),
],
resolve: {
extensions: ['*', '.tsx', '.ts', '.js', '.scss'],
symlinks: false,
},
}
};

View File

@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devtool: '#cheap-source-map',
})
devtool: 'cheap-source-map',
});

View File

@ -1,7 +1,8 @@
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
/* eslint-disable @typescript-eslint/no-var-requires */
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
devtool: '#source-map'
})
devtool: 'source-map',
});

6663
yarn.lock

File diff suppressed because it is too large Load Diff