Merge branch 'master' of https://github.com/bigbluebutton/bigbluebutton into 2.2-panel-manager

This commit is contained in:
KDSBrowne 2018-12-14 17:28:30 +00:00
commit 899c613c3c
49 changed files with 4280 additions and 6484 deletions

View File

@ -76,4 +76,6 @@ daemonUser in Linux := user
// group which will execute the application
daemonGroup in Linux := group
javaOptions in Universal ++= Seq("-J-Xms130m", "-J-Xmx256m", "-Dconfig.file=conf/application.conf", "-Dlogback.configurationFile=conf/logback.xml")
debianPackageDependencies in Debian ++= Seq("java8-runtime-headless", "bash")

View File

@ -1 +1,6 @@
sbt clean run
#!/usr/bin/env bash
sbt clean stage
sudo service bbb-apps-akka stop
cd target/universal/stage
./bin/bbb-apps-akka

View File

@ -1,93 +0,0 @@
akka {
actor {
debug {
# enable DEBUG logging of all AutoReceiveMessages (Kill, PoisonPill et.c.)
autoreceive = on
# enable DEBUG logging of actor lifecycle changes
lifecycle = on
}
}
loggers = ["akka.event.slf4j.Slf4jLogger"]
loglevel = "DEBUG"
redis-publish-worker-dispatcher {
mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
# Throughput defines the maximum number of messages to be
# processed per actor before the thread jumps to the next actor.
# Set to 1 for as fair as possible.
throughput = 512
}
redis-subscriber-worker-dispatcher {
mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
# Throughput defines the maximum number of messages to be
# processed per actor before the thread jumps to the next actor.
# Set to 1 for as fair as possible.
throughput = 512
}
}
redis {
host="127.0.0.1"
port=6379
password=""
# recording keys should expire in 14 days
keyExpiry=1209600
}
expire {
# time in seconds
lastUserLeft = 60
neverJoined = 300
}
services {
bbbWebAPI = "http://192.168.23.33/bigbluebutton/api"
sharedSecret = "changeme"
}
red5 {
deskshareip="10.130.218.89"
deskshareapp="video-broadcast"
}
eventBus {
meetingManagerChannel = "MeetingManagerChannel"
outMessageChannel = "OutgoingMessageChannel"
incomingJsonMsgChannel = "IncomingJsonMsgChannel"
outBbbMsgMsgChannel = "OutBbbMsgChannel"
}
sharedNotes {
maxNumberOfNotes = 3
maxNumberOfUndos = 30
}
http {
interface = "0.0.0.0"
port = 9999
}
services {
telizeHost = "www.telize.com"
telizePort = 80
}
apps {
checkPermissions = true
endMeetingWhenNoMoreAuthedUsers = false
endMeetingWhenNoMoreAuthedUsersAfterMinutes = 2
}
voiceConf {
recordPath = "/var/freeswitch/meetings"
}
recording {
chapterBreakLengthInMinutes = 180
}
whiteboard {
multiUserDefault = false
}

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"} %-5level %logger{35} - %msg%n</Pattern>
</layout>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/bbb-apps-akka.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>logs/bbb-apps-akka.%d{yyyy-MM-dd}.log</FileNamePattern>
<!-- keep 14 days worth of history -->
<MaxHistory>14</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"} %-5level %logger{35} - %msg%n</Pattern>
</layout>
</appender>
<logger name="akka" level="INFO" />
<logger name="org.bigbluebutton" level="DEBUG" />
<logger name="io.lettuce" level="INFO" />
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE" />
</root>
</configuration>

View File

@ -1,42 +0,0 @@
# #################################
# ##### Default configuration #####
# #################################
# Available replacements
# ------------------------------------------------
# ${{author}} debian author
# ${{descr}} debian package description
# ${{exec}} startup script name
# ${{chdir}} app directory
# ${{retries}} retries for startup
# ${{retryTimeout}} retry timeout
# ${{app_name}} normalized app name
# ${{daemon_user}} daemon user
# -------------------------------------------------
# DEPRECATED, use -J-Xmx1024m instead
# -mem 1024
# Setting -X directly (-J is stripped)
# -J-X
# -J-Xmx1024
# Add additional jvm parameters
# -Dkey=val
# For play applications you may set
# -Dpidfile.path=/var/run/${{app_name}}/play.pid
# Turn on JVM debugging, open at the given port
# -jvm-debug <port>
# Don't run the java version check
# -no-version-check
-J-Xms130m
-J-Xmx256m
# With universal:packageBin:
# - setup with a configuration tool after unzip
# - use the path to the application.ini file
# -Dconfig.file=${{path_to}}/conf/application.conf
-Dconfig.file=/usr/share/bbb-apps-akka/conf/application.conf

View File

@ -15,3 +15,4 @@ notices-for-facebook-graph-api-2
1.4.1-add-shell-server-package
1.4.3-split-account-service-packages
1.5-add-dynamic-import-package
1.7-split-underscore-from-meteor-base

View File

@ -3,24 +3,28 @@
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
standard-app-packages@1.0.9
arunoda:npm@0.2.6
amplify
blaze@2.1.8
francocatena:status
mizzao:timesync
clinical:nightwatch
cfs:power-queue
cfs:reactive-list
cfs:micro-queue
reactive-var@1.0.11
ecmascript@0.9.0
meteor-base
mobile-experience
mongo
reactive-var
standard-minifier-css
standard-minifier-js
es5-shim
ecmascript
shell-server
static-html
react-meteor-data
standard-minifier-css@1.3.5
standard-minifier-js@2.2.0
nathantreid:css-modules
shell-server@0.3.0
http@1.3.0
dynamic-import@0.2.0
rocketchat:streamer
http
session
tracker
check
jquery
nathantreid:css-modules@=3.1.4
rocketchat:streamer
cfs:power-queue
cfs:micro-queue
cfs:reactive-list
stevezhu:lodash

View File

@ -1 +1 @@
METEOR@1.6.0.1
METEOR@1.8.0.1

View File

@ -1,94 +1,82 @@
aldeed:simple-schema@1.5.3
allow-deny@1.1.0
amplify@1.0.0
arunoda:npm@0.2.6
autoupdate@1.3.12
babel-compiler@6.24.7
babel-runtime@1.1.1
base64@1.0.10
binary-heap@1.0.10
blaze@2.3.2
autoupdate@1.5.0
babel-compiler@7.2.3
babel-runtime@1.3.0
base64@1.0.11
binary-heap@1.0.11
blaze-tools@1.0.10
boilerplate-generator@1.3.1
caching-compiler@1.1.9
caching-html-compiler@1.1.2
callback-hook@1.0.10
cfs:http-methods@0.0.32
boilerplate-generator@1.6.0
caching-compiler@1.2.1
caching-html-compiler@1.1.3
callback-hook@1.1.0
cfs:micro-queue@0.0.6
cfs:power-queue@0.9.11
cfs:reactive-list@0.0.9
cfs:reactive-property@0.0.4
check@1.2.5
clinical:nightwatch@2.0.1
coffeescript@1.12.7_3
coffeescript-compiler@1.12.7_3
check@1.3.1
ddp@1.4.0
ddp-client@2.2.0
ddp-common@1.3.0
ddp-server@2.1.1
ddp-client@2.3.3
ddp-common@1.4.0
ddp-server@2.2.0
deps@1.0.12
diff-sequence@1.0.7
dynamic-import@0.2.1
ecmascript@0.9.0
ecmascript-runtime@0.5.0
ecmascript-runtime-client@0.5.0
ecmascript-runtime-server@0.5.0
diff-sequence@1.1.1
dynamic-import@0.5.0
ecmascript@0.12.3
ecmascript-runtime@0.7.0
ecmascript-runtime-client@0.8.0
ecmascript-runtime-server@0.7.1
ejson@1.1.0
fastclick@1.0.13
francocatena:status@1.5.3
es5-shim@4.8.0
fetch@0.1.0
geojson-utils@1.0.10
hot-code-push@1.0.4
html-tools@1.0.11
htmljs@1.0.11
http@1.3.0
id-map@1.0.9
jquery@1.11.10
http@1.4.2
id-map@1.1.0
inter-process-messaging@0.1.0
jquery@1.11.11
launch-screen@1.1.1
livedata@1.0.18
logging@1.1.19
mdg:validation-error@0.5.1
meteor@1.8.2
meteor-platform@1.2.6
meteorspark:util@0.2.0
minifier-css@1.2.16
minifier-js@2.2.2
minimongo@1.4.3
mizzao:timesync@0.5.0
logging@1.1.20
meteor@1.9.2
meteor-base@1.4.0
minifier-css@1.4.1
minifier-js@2.4.0
minimongo@1.4.5
mobile-experience@1.0.5
mobile-status-bar@1.0.14
modules@0.11.2
modules-runtime@0.9.1
mongo@1.3.1
modern-browsers@0.1.3
modules@0.13.0
modules-runtime@0.10.3
mongo@1.6.0
mongo-decimal@0.1.0
mongo-dev-server@1.1.0
mongo-id@1.0.6
nathantreid:css-modules@2.8.0
npm-mongo@2.2.33
observe-sequence@1.0.16
ordered-dict@1.0.9
promise@0.10.0
raix:eventemitter@0.1.3
random@1.0.10
react-meteor-data@0.2.15
reactive-dict@1.2.0
mongo-id@1.0.7
nathantreid:css-modules@3.1.4
npm-mongo@3.1.1
ordered-dict@1.1.0
promise@0.11.1
random@1.1.0
react-meteor-data@0.2.16
reactive-dict@1.2.1
reactive-var@1.0.11
reload@1.1.11
retry@1.0.9
rocketchat:streamer@0.6.2
routepolicy@1.0.12
session@1.1.7
shell-server@0.3.1
spacebars@1.0.15
reload@1.2.0
retry@1.1.0
rocketchat:streamer@1.0.1
routepolicy@1.1.0
session@1.2.0
shell-server@0.4.0
socket-stream-client@0.2.2
spacebars-compiler@1.1.3
standard-app-packages@1.0.9
standard-minifier-css@1.3.5
standard-minifier-js@2.2.3
tap:i18n@1.8.2
templating@1.3.2
templating-compiler@1.3.3
templating-runtime@1.3.2
standard-minifier-css@1.5.2
standard-minifier-js@2.4.0
static-html@1.2.2
stevezhu:lodash@4.17.2
templating-tools@1.1.2
tmeasday:check-npm-versions@0.3.1
tracker@1.1.3
ui@1.0.13
tmeasday:check-npm-versions@0.3.2
tracker@1.2.0
underscore@1.0.10
url@1.1.0
webapp@1.4.0
url@1.2.0
webapp@1.7.1
webapp-hashing@1.0.9

View File

@ -131,8 +131,7 @@ const BaseContainer = withTracker(() => {
},
};
const subscriptionsHandlers = SUBSCRIPTIONS_NAME.map(name =>
Meteor.subscribe(name, credentials, subscriptionErrorHandler));
const subscriptionsHandlers = SUBSCRIPTIONS_NAME.map(name => Meteor.subscribe(name, credentials, subscriptionErrorHandler));
const chats = GroupChat.find({
$or: [

View File

@ -27,6 +27,7 @@ class IntlStartup extends Component {
this.fetchLocalizedMessages = this.fetchLocalizedMessages.bind(this);
}
componentWillMount() {
this.fetchLocalizedMessages(this.props.locale);
}
@ -69,7 +70,7 @@ class IntlStartup extends Component {
render() {
return this.state.fetching ? <LoadingScreen /> : (
<IntlProvider locale={this.state.normalizedLocale} messages={this.state.messages}>
<IntlProvider locale={DEFAULT_LANGUAGE} messages={this.state.messages}>
{this.props.children}
</IntlProvider>
);

View File

@ -1,19 +1,12 @@
import { Meteor } from 'meteor/meteor';
import Winston from 'winston';
import { createLogger, format, transports } from 'winston';
const Logger = new Winston.Logger();
Logger.configure({
levels: {
error: 0, warn: 1, info: 2, verbose: 3, debug: 4,
},
colors: {
error: 'red',
warn: 'yellow',
info: 'green',
verbose: 'cyan',
debug: 'magenta',
},
const Logger = createLogger({
format: format.combine(
format.colorize({ level: true }),
format.splat(),
format.simple(),
),
});
Meteor.startup(() => {
@ -21,7 +14,7 @@ Meteor.startup(() => {
const { level } = LOG_CONFIG;
// console logging
Logger.add(Winston.transports.Console, {
Logger.add(new transports.Console(), {
prettyPrint: false,
humanReadableUnhandledException: true,
colorize: true,

View File

@ -1,3 +1,4 @@
import _ from 'lodash';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, intlShape } from 'react-intl';
@ -91,8 +92,8 @@ class ActionsDropdown extends Component {
}
componentDidMount() {
if (Meteor.settings.public.allowOutsideCommands.toggleRecording ||
getFromUserSettings('outsideToggleRecording', false)) {
if (Meteor.settings.public.allowOutsideCommands.toggleRecording
|| getFromUserSettings('outsideToggleRecording', false)) {
ActionBarService.connectRecordingObserver();
window.addEventListener('message', ActionBarService.processOutsideToggleRecording);
}
@ -132,7 +133,8 @@ class ActionsDropdown extends Component {
}}
/>
: null),
(isUserPresenter ?
(isUserPresenter
? (
<DropdownListItem
data-test="uploadPresentation"
icon="presentation"
@ -141,19 +143,23 @@ class ActionsDropdown extends Component {
key={this.presentationItemId}
onClick={this.handlePresentationClick}
/>
)
: null),
(record && isUserModerator && allowStartStopRecording ?
(record && isUserModerator && allowStartStopRecording
? (
<DropdownListItem
icon="record"
label={intl.formatMessage(isRecording ?
intlMessages.stopRecording : intlMessages.startRecording)}
description={intl.formatMessage(isRecording ?
intlMessages.stopRecording : intlMessages.startRecording)}
label={intl.formatMessage(isRecording
? intlMessages.stopRecording : intlMessages.startRecording)}
description={intl.formatMessage(isRecording
? intlMessages.stopRecording : intlMessages.startRecording)}
key={this.recordId}
onClick={toggleRecording}
/>
)
: null),
(isUserModerator && !meetingIsBreakout && !hasBreakoutRoom ?
(isUserModerator && !meetingIsBreakout && !hasBreakoutRoom
? (
<DropdownListItem
icon="rooms"
label={intl.formatMessage(intlMessages.createBreakoutRoom)}
@ -161,6 +167,7 @@ class ActionsDropdown extends Component {
key={this.createBreakoutRoomId}
onClick={this.handleCreateBreakoutRoomClick}
/>
)
: null),
]);
}
@ -168,6 +175,7 @@ class ActionsDropdown extends Component {
handlePresentationClick() {
this.props.mountModal(<PresentationUploaderContainer />);
}
handleCreateBreakoutRoomClick() {
const {
createBreakoutRoom,

View File

@ -35,8 +35,7 @@ const processToggleMuteFromOutside = (e) => {
}
};
export default withModalMounter(withTracker(({ mountModal }) =>
({
export default withModalMounter(withTracker(({ mountModal }) => ({
processToggleMuteFromOutside: arg => processToggleMuteFromOutside(arg),
mute: Service.isConnected() && !Service.isListenOnly() && !Service.isEchoTest(),
unmute: Service.isConnected() && !Service.isListenOnly() && Service.isMuted(),

View File

@ -11,6 +11,7 @@ class AuthenticatedHandler extends Component {
Session.set('hasError', true);
if (codeError) Session.set('codeError', codeError);
}
static shouldAuthenticate(status, lastStatus) {
return lastStatus != null && lastStatus === STATUS_CONNECTING && status.connected;
}
@ -31,6 +32,7 @@ class AuthenticatedHandler extends Component {
}
});
}
static async authenticatedRouteHandler(callback) {
if (Auth.loggedIn) {
callback();
@ -51,6 +53,7 @@ class AuthenticatedHandler extends Component {
setReason(error);
}
}
constructor(props) {
super(props);
this.changeState = this.changeState.bind(this);

View File

@ -91,11 +91,9 @@ export default class Button extends BaseButton {
const {
size,
color,
disabled,
ghost,
circle,
block,
iconRight,
} = this.props;
const propClassNames = {};
@ -106,8 +104,6 @@ export default class Button extends BaseButton {
propClassNames[styles.ghost] = ghost;
propClassNames[styles.circle] = circle;
propClassNames[styles.block] = block;
propClassNames[styles.iconRight] = iconRight;
propClassNames[styles.disabled] = disabled;
return propClassNames;
}
@ -207,7 +203,7 @@ export default class Button extends BaseButton {
if (iconName) {
return (<Icon className={styles.icon} iconName={iconName} />);
} else if (customIcon) {
} if (customIcon) {
return customIcon;
}

View File

@ -11,7 +11,7 @@ import DropdownListItem from '/imports/ui/components/dropdown/list/item/componen
import Auth from '/imports/ui/services/auth';
import Button from '/imports/ui/components/button/component';
import ChatService from './../service';
import ChatService from '../service';
import { styles } from './styles';
const intlMessages = defineMessages({

View File

@ -89,9 +89,9 @@ class MessageList extends Component {
// Compare with <1 to account for the chance scrollArea.scrollTop is a float
// value in some browsers.
this.shouldScrollBottom = position === scrollArea.scrollHeight ||
(scrollArea.scrollHeight - position < 1) ||
nextProps.scrollPosition === null;
this.shouldScrollBottom = position === scrollArea.scrollHeight
|| (scrollArea.scrollHeight - position < 1)
|| nextProps.scrollPosition === null;
}
componentDidUpdate(prevProps) {
@ -183,7 +183,6 @@ class MessageList extends Component {
{messages.map(message => (
<MessageListItem
handleReadMessage={handleReadMessage}
className={styles.messageListItem}
key={message.id}
messages={message.content}
user={message.sender}

View File

@ -47,7 +47,7 @@ export default class Checkbox extends Component {
return (
<div className={cx({
[styles.disabled]: !!disabled,
}, styles.container, className)}
}, className)}
>
<input
type="checkbox"
@ -59,9 +59,9 @@ export default class Checkbox extends Component {
disabled={disabled}
/>
<div role="presentation" onClick={this.handleChange}>
{ checked ?
<Icon iconName="check" className={cx(styles.icon, styles.checked)} /> :
<Icon iconName="circle" className={styles.icon} />
{ checked
? <Icon iconName="check" className={cx(styles.icon, styles.checked)} />
: <Icon iconName="circle" className={styles.icon} />
}
</div>
<div id={ariaLabelledBy} hidden>{ariaLabel}</div>

View File

@ -1,6 +1,7 @@
import Captions from '/imports/api/captions';
import Auth from '/imports/ui/services/auth';
import Settings from '/imports/ui/services/settings';
import _ from 'lodash';
const getCCData = () => {
const meetingID = Auth.meetingID;

View File

@ -55,16 +55,16 @@ class ErrorScreen extends React.PureComponent {
return (
<div className={styles.background}>
<h1 className={styles.code}>
<h1>
{code}
</h1>
<h1 className={styles.message}>
{formatedMessage}
</h1>
<div className={styles.content}>
<div>
{children}
</div>
<div className={styles.content}>
<div>
<Button
size="sm"
onClick={logoutRouteHandler}

View File

@ -13,6 +13,7 @@ class JoinHandler extends Component {
Session.set('hasError', true);
if (codeError) Session.set('codeError', codeError);
}
constructor(props) {
super(props);
this.fetchToken = this.fetchToken.bind(this);
@ -120,9 +121,9 @@ class JoinHandler extends Component {
render() {
const { children } = this.props;
const { joined } = this.state;
return joined ?
children :
(<LoadingScreen />);
return joined
? children
: (<LoadingScreen />);
}
}

View File

@ -6,7 +6,7 @@ const LoadingScreen = ({ children }) => (
<div className={styles.spinner}>
<div className={styles.bounce1} />
<div className={styles.bounce2} />
<div className={styles.bounce3} />
<div />
</div>
<div className={styles.message}>
{children}

View File

@ -29,7 +29,6 @@ export default class Media extends Component {
const contentClassName = cx({
[styles.content]: true,
[styles.hasOverlay]: !hideOverlay,
});
const overlayClassName = cx({

View File

@ -60,14 +60,12 @@ const defaultProps = {
shortcuts: '',
};
const openBreakoutJoinConfirmation = (breakout, breakoutName, mountModal) =>
mountModal(<BreakoutJoinConfirmation
const openBreakoutJoinConfirmation = (breakout, breakoutName, mountModal) => mountModal(<BreakoutJoinConfirmation
breakout={breakout}
breakoutName={breakoutName}
/>);
const closeBreakoutJoinConfirmation = mountModal =>
mountModal(null);
const closeBreakoutJoinConfirmation = mountModal => mountModal(null);
class NavBar extends PureComponent {
constructor(props) {
@ -151,7 +149,9 @@ class NavBar extends PureComponent {
<Dropdown isOpen={this.state.isActionsOpen}>
<DropdownTrigger>
<h1 className={cx(styles.presentationTitle, styles.dropdownBreakout)}>
{presentationTitle} <Icon iconName="down-arrow" />
{presentationTitle}
{' '}
<Icon iconName="down-arrow" />
</h1>
</DropdownTrigger>
<DropdownContent
@ -174,7 +174,6 @@ class NavBar extends PureComponent {
return (
<DropdownListItem
className={styles.actionsHeader}
key={_.uniqueId('action-header')}
label={breakoutName}
onClick={openBreakoutJoinConfirmation.bind(this, breakout, breakoutName, mountModal)}
@ -219,8 +218,8 @@ class NavBar extends PureComponent {
</div>
<div className={styles.center}>
{this.renderPresentationTitle()}
{beingRecorded.record ?
<span className={styles.presentationTitleSeparator}>|</span>
{beingRecorded.record
? <span className={styles.presentationTitleSeparator}>|</span>
: null}
<RecordingIndicator
{...beingRecorded}

View File

@ -1,6 +1,5 @@
import React, { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import cx from 'classnames';
import _ from 'lodash';
import { withModalMounter } from '/imports/ui/components/modal/service';
import LogoutConfirmationContainer from '/imports/ui/components/logout-confirmation/container';
@ -191,13 +190,15 @@ class SettingsDropdown extends PureComponent {
alterMenu(props) {
const { fullscreenLabel, fullscreenDesc, fullscreenIcon } = this.checkFullscreen(props);
const newFullScreenButton = (<DropdownListItem
const newFullScreenButton = (
<DropdownListItem
key={_.uniqueId('list-item-')}
icon={fullscreenIcon}
label={fullscreenLabel}
description={fullscreenDesc}
onClick={this.props.handleToggleFullscreen}
/>);
/>
);
this.menuItems = this.menuItems.slice(1);
this.menuItems.unshift(newFullScreenButton);
}
@ -222,7 +223,7 @@ class SettingsDropdown extends PureComponent {
ghost
circle
hideLabel
className={cx(styles.btn, styles.btnSettings)}
className={styles.btn}
// FIXME: Without onClick react proptypes keep warning
// even after the DropdownTrigger inject an onClick handler

View File

@ -135,6 +135,7 @@ export default class PresentationArea extends Component {
height: adjustedHeight,
};
}
zoomChanger(zoom) {
let newZoom = zoom;
const isDifferent = newZoom !== this.state.zoom;
@ -146,6 +147,7 @@ export default class PresentationArea extends Component {
}
if (isDifferent) this.setState({ zoom: newZoom });
}
pointUpdate(pointX, pointY) {
this.setState({
delta: {
@ -154,11 +156,13 @@ export default class PresentationArea extends Component {
},
});
}
touchUpdate(bool) {
this.setState({
touchZoom: bool,
});
}
fitToWidthHandler() {
this.setState({
fitToWidth: !this.state.fitToWidth,
@ -168,8 +172,8 @@ export default class PresentationArea extends Component {
// renders the whole presentation area
renderPresentationArea() {
// sometimes tomcat publishes the slide url, but the actual file is not accessible (why?)
if (!this.props.currentSlide ||
!this.props.currentSlide.calculatedData) {
if (!this.props.currentSlide
|| !this.props.currentSlide.calculatedData) {
return null;
}
// to control the size of the svg wrapper manually
@ -328,8 +332,8 @@ export default class PresentationArea extends Component {
}
renderWhiteboardToolbar() {
if (!this.props.currentSlide ||
!this.props.currentSlide.calculatedData) {
if (!this.props.currentSlide
|| !this.props.currentSlide.calculatedData) {
return null;
}
@ -353,11 +357,11 @@ export default class PresentationArea extends Component {
ref={(ref) => { this.refWhiteboardArea = ref; }}
className={styles.whiteboardSizeAvailable}
/>
{this.state.showSlide ?
this.renderPresentationArea()
{this.state.showSlide
? this.renderPresentationArea()
: null }
{this.props.userIsPresenter || this.props.multiUser ?
this.renderWhiteboardToolbar()
{this.props.userIsPresenter || this.props.multiUser
? this.renderWhiteboardToolbar()
: null }
</div>
{this.renderPresentationToolbar()}

View File

@ -80,7 +80,7 @@ class HoldDownButton extends Component {
render() {
const {
key,
uniqueKey,
className,
children,
} = this.props;
@ -88,7 +88,7 @@ class HoldDownButton extends Component {
return (
<span
role="button"
key={key}
key={uniqueKey}
onClick={this.onClick}
onMouseDown={this.mouseDownHandler}
onMouseUp={this.mouseUpHandler}
@ -107,12 +107,12 @@ const defaultProps = {
exec: () => {},
minBound: null,
maxBound: Infinity,
key: _.uniqueId('holdButton-'),
uniqueKey: _.uniqueId('holdButton-'),
value: 0,
};
const propTypes = {
key: PropTypes.string,
uniqueKey: PropTypes.string,
exec: PropTypes.func.isRequired,
minBound: PropTypes.number,
maxBound: PropTypes.number,

View File

@ -145,8 +145,7 @@ class PresentationUploader extends Component {
return fileIndex === -1 ? false : {
presentations: update(presentations, {
[fileIndex]: {
$apply: file =>
update(file, {
$apply: file => update(file, {
[key]: {
[operation]: value,
},
@ -383,8 +382,7 @@ class PresentationUploader extends Component {
});
}
const conversionStatusMessage =
intlMessages[item.conversion.status] || intlMessages.genericConversionStatus;
const conversionStatusMessage = intlMessages[item.conversion.status] || intlMessages.genericConversionStatus;
return intl.formatMessage(conversionStatusMessage);
}
@ -419,12 +417,14 @@ class PresentationUploader extends Component {
<Icon iconName="file" />
</td>
{
isActualCurrent ?
isActualCurrent
? (
<th className={styles.tableItemCurrent}>
<span className={styles.currentLabel}>
{this.props.intl.formatMessage(intlMessages.current)}
</span>
</th>
)
: null
}
<th className={styles.tableItemName} colSpan={!isActualCurrent ? 2 : 0}>
@ -479,12 +479,13 @@ class PresentationUploader extends Component {
accept={fileValidMimeTypes.join()}
minSize={fileSizeMin}
maxSize={fileSizeMax}
disablePreview
disablepreview="true"
onDrop={this.handleFiledrop}
>
<Icon className={styles.dropzoneIcon} iconName="upload" />
<p className={styles.dropzoneMessage}>
{intl.formatMessage(intlMessages.dropzoneLabel)}&nbsp;
{intl.formatMessage(intlMessages.dropzoneLabel)}
&nbsp;
<span className={styles.dropzoneLink}>
{intl.formatMessage(intlMessages.browseFilesLabel)}
</span>

View File

@ -122,8 +122,8 @@ class ApplicationMenu extends BaseMenu {
const { isLargestFontSize, isSmallestFontSize } = this.state;
return (
<div className={styles.tabContent}>
<div className={styles.header}>
<div>
<div>
<h3 className={styles.title}>
{intl.formatMessage(intlMessages.applicationSectionTitle)}
</h3>
@ -221,17 +221,6 @@ class ApplicationMenu extends BaseMenu {
<div className={styles.col}>
<div className={cx(styles.formElement, styles.pullContentRight)}>
<div className={styles.pullContentRight}>
<div className={styles.col}>
<Button
onClick={() => this.handleIncreaseFontSize()}
color="primary"
icon="add"
circle
hideLabel
label={intl.formatMessage(intlMessages.increaseFontBtnLabel)}
disabled={isLargestFontSize}
/>
</div>
<div className={styles.col}>
<Button
onClick={() => this.handleDecreaseFontSize()}
@ -243,6 +232,17 @@ class ApplicationMenu extends BaseMenu {
disabled={isSmallestFontSize}
/>
</div>
<div className={styles.col}>
<Button
onClick={() => this.handleIncreaseFontSize()}
color="primary"
icon="add"
circle
hideLabel
label={intl.formatMessage(intlMessages.increaseFontBtnLabel)}
disabled={isLargestFontSize}
/>
</div>
</div>
</div>
</div>

View File

@ -1,11 +1,11 @@
import React from 'react';
import { styles } from '../styles';
import cx from 'classnames';
import BaseMenu from '../base/component';
import Toggle from '/imports/ui/components/switch/component';
import Checkbox from '/imports/ui/components/checkbox/component';
import { GithubPicker } from 'react-color';
import { defineMessages, injectIntl } from 'react-intl';
import BaseMenu from '../base/component';
import { styles } from '../styles';
// an array of font-families
const FONT_FAMILIES = ['Arial', 'Calibri', 'Time New Roman', 'Sans-serif'];
@ -131,8 +131,8 @@ class ClosedCaptionsMenu extends BaseMenu {
} = this.props;
return (
<div className={styles.tabContent}>
<div className={styles.header}>
<div>
<div>
<h3 className={styles.title}>{intl.formatMessage(intlMessages.closedCaptionsLabel)}</h3>
</div>
<div className={styles.form}>
@ -156,9 +156,11 @@ class ClosedCaptionsMenu extends BaseMenu {
</div>
</div>
</div>
{ this.state.settings.enabled ?
{ this.state.settings.enabled
? (
<div>
{ isModerator ?
{ isModerator
? (
<div className={cx(styles.row, styles.spacedLeft)}>
<div className={styles.col}>
<div className={styles.formElement}>
@ -178,6 +180,7 @@ class ClosedCaptionsMenu extends BaseMenu {
</div>
</div>
</div>
)
: null }
<div className={cx(styles.row, styles.spacedLeft)}>
<div className={styles.col}>
@ -198,15 +201,16 @@ class ClosedCaptionsMenu extends BaseMenu {
onChange={this.handleSelectChange.bind(this, 'locale', this.props.locales)}
>
<option>
{ this.props.locales &&
this.props.locales.length ?
intl.formatMessage(intlMessages.localeOptionLabel) :
intl.formatMessage(intlMessages.noLocaleOptionLabel) }
{ this.props.locales
&& this.props.locales.length
? intl.formatMessage(intlMessages.localeOptionLabel)
: intl.formatMessage(intlMessages.noLocaleOptionLabel) }
</option>
{this.props.locales ? this.props.locales.map((locale, index) =>
(<option key={index} value={index}>
{this.props.locales ? this.props.locales.map((locale, index) => (
<option key={index} value={index}>
{locale}
</option>)) : null }
</option>
)) : null }
</select>
</label>
</div>
@ -234,10 +238,11 @@ class ClosedCaptionsMenu extends BaseMenu {
{intl.formatMessage(intlMessages.fontFamilyOptionLabel)}
</option>
{
FONT_FAMILIES.map((family, index) =>
(<option key={index} value={index}>
FONT_FAMILIES.map((family, index) => (
<option key={index} value={index}>
{family}
</option>))
</option>
))
}
</select>
</label>
@ -266,10 +271,11 @@ class ClosedCaptionsMenu extends BaseMenu {
{intl.formatMessage(intlMessages.fontSizeOptionLabel)}
</option>
{
FONT_SIZES.map((size, index) =>
(<option key={index} value={index}>
FONT_SIZES.map((size, index) => (
<option key={index} value={index}>
{size}
</option>))
</option>
))
}
</select>
</label>
@ -301,7 +307,8 @@ class ClosedCaptionsMenu extends BaseMenu {
style={{ background: this.state.settings.backgroundColor }}
/>
</div>
{ this.state.displayBackgroundColorPicker ?
{ this.state.displayBackgroundColorPicker
? (
<div className={styles.colorPickerPopover}>
<div
className={styles.colorPickerOverlay}
@ -315,6 +322,7 @@ class ClosedCaptionsMenu extends BaseMenu {
triangle="top-right"
/>
</div>
)
: null }
</div>
</div>
@ -343,7 +351,8 @@ class ClosedCaptionsMenu extends BaseMenu {
style={{ background: this.state.settings.fontColor }}
/>
</div>
{ this.state.displayFontColorPicker ?
{ this.state.displayFontColorPicker
? (
<div className={styles.colorPickerPopover}>
<div
className={styles.colorPickerOverlay}
@ -357,6 +366,7 @@ class ClosedCaptionsMenu extends BaseMenu {
triangle="top-right"
/>
</div>
)
: null }
</div>
</div>
@ -372,6 +382,7 @@ class ClosedCaptionsMenu extends BaseMenu {
</span>
</div>
</div>
)
: null }
</div>
</div>

View File

@ -33,14 +33,15 @@ class DataSaving extends BaseMenu {
settings: props.settings,
};
}
render() {
const { intl } = this.props;
const { viewParticipantsWebcams, viewScreenshare } = this.state.settings;
return (
<div className={styles.tabContent}>
<div className={styles.header}>
<div>
<div>
<h3 className={styles.title}>{intl.formatMessage(intlMessages.dataSavingLabel)}</h3>
<p className={styles.subtitle}>{intl.formatMessage(intlMessages.dataSavingDesc)}</p>
</div>

View File

@ -18,12 +18,12 @@ const defaultProps = {
};
class Tooltip extends Component {
static wait(show, event) {
static wait(tip, event) {
const tooltipTarget = event.target;
const expandedEl = tooltipTarget.parentElement.querySelector('[aria-expanded="true"]');
const isTarget = expandedEl === tooltipTarget;
if (expandedEl && !isTarget) return;
show();
tip.show();
}
constructor(props) {
@ -34,17 +34,18 @@ class Tooltip extends Component {
this.onHide = this.onHide.bind(this);
this.handleEscapeHide = this.handleEscapeHide.bind(this);
this.delay = [150, 50];
this.dynamicTitle = true;
}
componentDidMount() {
const {
position,
title,
} = this.props;
const options = {
position,
dynamicTitle: this.dynamicTitle,
placement: position,
performance: true,
content: title,
delay: this.delay,
onShow: this.onShow,
onHide: this.onHide,
@ -53,6 +54,7 @@ class Tooltip extends Component {
};
this.tooltip = Tippy(`#${this.tippySelectorId}`, options);
}
onShow() {
document.addEventListener('keyup', this.handleEscapeHide);
}

View File

@ -12,7 +12,7 @@ const defaultProps = {
const ChatIcon = props => (
<div className={styles.chatThumbnail}>
<Icon iconName={props.icon} className={styles.actionIcon} />
<Icon iconName={props.icon} />
</div>
);

View File

@ -84,26 +84,31 @@ const ChatListItem = (props) => {
<div className={styles.chatListItemLink}>
<div className={styles.chatIcon}>
{chat.icon ?
<ChatIcon icon={chat.icon} />
:
{chat.icon
? <ChatIcon icon={chat.icon} />
: (
<ChatAvatar
isModerator={chat.isModerator}
color={chat.color}
name={chat.name.toLowerCase().slice(0, 2)}
/>}
/>
)}
</div>
<div className={styles.chatName}>
{!compact ?
{!compact
? (
<span className={styles.chatNameMain}>
{isPublicChat(chat) ?
intl.formatMessage(intlMessages.titlePublic) : chat.name}
</span> : null}
{isPublicChat(chat)
? intl.formatMessage(intlMessages.titlePublic) : chat.name}
</span>
) : null}
</div>
{(chat.unreadCounter > 0) ?
{(chat.unreadCounter > 0)
? (
<ChatUnreadCounter
counter={chat.unreadCounter}
/>
)
: null}
</div>
</div>

View File

@ -13,8 +13,8 @@ import DropdownListSeparator from '/imports/ui/components/dropdown/list/separato
import _ from 'lodash';
import { Session } from 'meteor/session';
import { styles } from './styles';
import UserName from './../user-name/component';
import UserIcons from './../user-icons/component';
import UserName from '../user-name/component';
import UserIcons from '../user-icons/component';
const messages = defineMessages({
presenter: {
@ -367,15 +367,13 @@ class UserDropdown extends PureComponent {
dropdownVisible: true,
};
const isDropdownVisible =
UserDropdown.checkIfDropdownIsVisible(
const isDropdownVisible = UserDropdown.checkIfDropdownIsVisible(
dropdownContent.offsetTop,
dropdownContent.offsetHeight,
);
if (!isDropdownVisible) {
const offsetPageTop =
((dropdownTrigger.offsetTop + dropdownTrigger.offsetHeight) - scrollContainer.scrollTop);
const offsetPageTop = ((dropdownTrigger.offsetTop + dropdownTrigger.offsetHeight) - scrollContainer.scrollTop);
nextState.dropdownOffset = window.innerHeight - offsetPageTop;
nextState.dropdownDirection = 'bottom';
@ -405,9 +403,9 @@ class UserDropdown extends PureComponent {
const { clientType } = user;
const isVoiceOnly = clientType === 'dial-in-user';
const iconUser = user.emoji.status !== 'none' ?
(<Icon iconName={normalizeEmojiName(user.emoji.status)} />) :
user.name.toLowerCase().slice(0, 2);
const iconUser = user.emoji.status !== 'none'
? (<Icon iconName={normalizeEmojiName(user.emoji.status)} />)
: user.name.toLowerCase().slice(0, 2);
const iconVoiceOnlyUser = (<Icon iconName="speak_louder" />);
@ -446,7 +444,6 @@ class UserDropdown extends PureComponent {
const userItemContentsStyle = {};
userItemContentsStyle[styles.userItemContentsCompact] = compact;
userItemContentsStyle[styles.dropdown] = true;
userItemContentsStyle[styles.userListItem] = !this.state.isActionsOpen;
userItemContentsStyle[styles.usertListItemWithMenu] = this.state.isActionsOpen;
@ -469,7 +466,7 @@ class UserDropdown extends PureComponent {
const contents = (
<div
data-test={user.isCurrent ? "userListItemCurrent" : null}
data-test={user.isCurrent ? 'userListItemCurrent' : null}
className={!actions.length ? styles.userListItem : null}
>
<div className={styles.userItemContents}>

View File

@ -68,10 +68,11 @@ export default class AnnotationFactory extends Component {
render() {
const { annotationsInfo } = this.props;
return (
<g>
{annotationsInfo ?
annotationsInfo.map(annotationInfo => this.renderAnnotation(annotationInfo))
{annotationsInfo
? annotationsInfo.map(annotationInfo => this.renderAnnotation(annotationInfo))
: null }
</g>
);

View File

@ -213,8 +213,8 @@ class WhiteboardToolbar extends Component {
} else if (this.state.thicknessSelected.value !== prevState.thicknessSelected.value) {
this.thicknessListIconRadius.beginElement();
// 3rd case
} else if (this.state.annotationSelected.value !== 'text' &&
prevState.annotationSelected.value === 'text') {
} else if (this.state.annotationSelected.value !== 'text'
&& prevState.annotationSelected.value === 'text') {
this.thicknessListIconRadius.beginElement();
this.thicknessListIconColor.beginElement();
}
@ -339,7 +339,8 @@ class WhiteboardToolbar extends Component {
onBlur={this.closeSubMenu}
className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'annotationList' ? styles.toolbarActive : null)}
>
{this.state.currentSubmenuOpen === 'annotationList' && annotations.length > 1 ?
{this.state.currentSubmenuOpen === 'annotationList' && annotations.length > 1
? (
<ToolbarSubmenu
type="annotations"
customIcon={false}
@ -350,6 +351,7 @@ class WhiteboardToolbar extends Component {
handleMouseEnter={this.handleMouseEnter}
handleMouseLeave={this.handleMouseLeave}
/>
)
: null}
</ToolbarMenuItem>
);
@ -367,7 +369,8 @@ class WhiteboardToolbar extends Component {
onBlur={this.closeSubMenu}
className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'fontSizeList' ? styles.toolbarActive : null)}
>
{this.state.currentSubmenuOpen === 'fontSizeList' ?
{this.state.currentSubmenuOpen === 'fontSizeList'
? (
<ToolbarSubmenu
type="font-size"
customIcon
@ -378,6 +381,7 @@ class WhiteboardToolbar extends Component {
handleMouseEnter={this.handleMouseEnter}
handleMouseLeave={this.handleMouseLeave}
/>
)
: null}
</ToolbarMenuItem>
);
@ -405,8 +409,8 @@ class WhiteboardToolbar extends Component {
return (
<ToolbarMenuItem
disabled={isDisabled}
label={isDisabled ?
intl.formatMessage(intlMessages.toolbarLineThicknessDisabled)
label={isDisabled
? intl.formatMessage(intlMessages.toolbarLineThicknessDisabled)
: intl.formatMessage(intlMessages.toolbarLineThickness)}
onItemClick={this.displaySubMenu}
objectToReturn="thicknessList"
@ -414,7 +418,8 @@ class WhiteboardToolbar extends Component {
className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'thicknessList' ? styles.toolbarActive : null)}
customIcon={this.renderThicknessItemIcon()}
>
{this.state.currentSubmenuOpen === 'thicknessList' ?
{this.state.currentSubmenuOpen === 'thicknessList'
? (
<ToolbarSubmenu
type="thickness"
customIcon
@ -425,6 +430,7 @@ class WhiteboardToolbar extends Component {
handleMouseEnter={this.handleMouseEnter}
handleMouseLeave={this.handleMouseLeave}
/>
)
: null}
</ToolbarMenuItem>
);
@ -485,8 +491,8 @@ class WhiteboardToolbar extends Component {
return (
<ToolbarMenuItem
disabled={isDisabled}
label={isDisabled ?
intl.formatMessage(intlMessages.toolbarLineColorDisabled)
label={isDisabled
? intl.formatMessage(intlMessages.toolbarLineColorDisabled)
: intl.formatMessage(intlMessages.toolbarLineColor)}
onItemClick={this.displaySubMenu}
objectToReturn="colorList"
@ -494,7 +500,8 @@ class WhiteboardToolbar extends Component {
className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'colorList' ? styles.toolbarActive : null)}
customIcon={this.renderColorItemIcon()}
>
{this.state.currentSubmenuOpen === 'colorList' ?
{this.state.currentSubmenuOpen === 'colorList'
? (
<ToolbarSubmenu
type="color"
customIcon
@ -505,6 +512,7 @@ class WhiteboardToolbar extends Component {
handleMouseEnter={this.handleMouseEnter}
handleMouseLeave={this.handleMouseLeave}
/>
)
: null}
</ToolbarMenuItem>
);
@ -551,7 +559,7 @@ class WhiteboardToolbar extends Component {
label={intl.formatMessage(intlMessages.toolbarUndoAnnotation)}
icon="undo"
onItemClick={this.handleUndo}
className={cx(styles.toolbarButton, styles.notActive)}
className={styles.toolbarButton}
/>
);
}
@ -564,7 +572,7 @@ class WhiteboardToolbar extends Component {
label={intl.formatMessage(intlMessages.toolbarClearAnnotations)}
icon="delete"
onItemClick={this.handleClearAll}
className={cx(styles.toolbarButton, styles.notActive)}
className={styles.toolbarButton}
/>
);
}
@ -574,13 +582,13 @@ class WhiteboardToolbar extends Component {
return (
<ToolbarMenuItem
label={multiUser ?
intl.formatMessage(intlMessages.toolbarMultiUserOff)
label={multiUser
? intl.formatMessage(intlMessages.toolbarMultiUserOff)
: intl.formatMessage(intlMessages.toolbarMultiUserOn)
}
icon={multiUser ? 'multi_whiteboard' : 'whiteboard'}
onItemClick={this.handleSwitchWhiteboardMode}
className={cx(styles.toolbarButton, styles.notActive)}
className={styles.toolbarButton}
/>
);
}

View File

@ -93,13 +93,13 @@ class ToolbarSubmenu extends Component {
<rect x="20%" y="20%" width="60%" height="60%" fill={obj.value} />
</svg>
);
} else if (type === 'thickness') {
} if (type === 'thickness') {
return (
<svg className={styles.customSvgIcon}>
<circle cx="50%" cy="50%" r={obj.value} />
</svg>
);
} else if (type === 'font-size') {
} if (type === 'font-size') {
return (
<p className={styles.textThickness} style={{ fontSize: obj.value }}>
Aa
@ -111,18 +111,19 @@ class ToolbarSubmenu extends Component {
}
static getWrapperClassNames(type) {
if (type === 'color') {
return cx(styles.colorList, styles.toolbarList);
} else if (type === 'thickness') {
return cx(styles.thicknessList, styles.toolbarList);
} else if (type === 'font-size') {
if (type === 'font-size') {
return cx(styles.fontSizeList, styles.toolbarList);
} else if (type === 'annotations') {
return cx(styles.annotationList, styles.toolbarList);
} if (
type === 'annotations'
|| type === 'thickness'
|| type === 'color'
) {
return styles.toolbarList;
}
return null;
}
constructor() {
super();
@ -183,8 +184,7 @@ class ToolbarSubmenu extends Component {
onMouseLeave={this.handleMouseLeave}
className={ToolbarSubmenu.getWrapperClassNames(type)}
>
{objectsToRender ? objectsToRender.map(obj =>
(
{objectsToRender ? objectsToRender.map(obj => (
<ToolbarSubmenuItem
label={this.formatSubmenuLabel(type, obj)}
icon={!customIcon ? obj.icon : null}

9293
bigbluebutton-html5/package-lock.json generated Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -10,11 +10,9 @@
"start:prod": "meteor reset && ROOT_URL=http://127.0.0.1/html5client NODE_ENV=production meteor --production",
"start:dev": "ROOT_URL=http://127.0.0.1/html5client NODE_ENV=development meteor",
"test": "jest",
"lint": "eslint . --ext .jsx,.js",
"precommit": "lint-staged"
"lint": "eslint . --ext .jsx,.js"
},
"lint-staged": {
"gitDir": "../",
"linters": {
"*.{js,jsx}": [
"eslint --fix",
@ -28,65 +26,68 @@
"but Meteor 1.6.0.1 doesn't see it there for some reason",
"need to investigate"
],
"@browser-bunyan/server-stream": "^1.3.0",
"autoprefixer": "~7.1.6",
"@babel/runtime": "^7.2.0",
"@browser-bunyan/server-stream": "^1.5.0",
"autoprefixer": "~9.3.1",
"babel-plugin-react-remove-properties": "~0.2.5",
"babel-runtime": "~6.26.0",
"browser-bunyan": "^1.4.0",
"browser-bunyan": "^1.5.0",
"browser-detect": "^0.2.28",
"classnames": "^2.2.6",
"clipboard": "~1.7.1",
"core-js": "^2.5.7",
"eventemitter2": "~4.1.2",
"flat": "~4.0.0",
"history": "~3.3.0",
"immutability-helper": "~2.4.0",
"clipboard": "^2.0.4",
"core-js": "^2.6.0",
"eventemitter2": "~5.0.1",
"fibers": "^3.1.1",
"flat": "~4.1.0",
"history": "~4.7.2",
"immutability-helper": "~2.8.1",
"langmap": "0.0.16",
"lodash": "~4.17.10",
"lodash": "^4.17.11",
"makeup-screenreader-trap": "0.0.5",
"meteor-node-stubs": "^0.3.3",
"node-sass": "^4.9.3",
"postcss-nested": "2.1.2",
"probe-image-size": "~3.1.0",
"meteor-node-stubs": "^0.4.1",
"node-sass": "^4.10.0",
"postcss-nested": "4.1.0",
"probe-image-size": "~4.0.0",
"prop-types": "^15.6.2",
"re-resizable": "^4.8.1",
"react": "~16.0.0",
"react-autosize-textarea": "~0.4.9",
"re-resizable": "^4.10.0",
"react": "^16.6.3",
"react-autosize-textarea": "^5.0.1",
"react-color": "~2.14.1",
"react-dom": "^16.0.1",
"react-dropzone": "^4.2.13",
"react-intl": "~2.4.0",
"react-modal": "~3.0.4",
"react-dom": "^16.6.3",
"react-dropzone": "^7.0.1",
"react-intl": "~2.7.2",
"react-modal": "~3.6.1",
"react-render-in-browser": "^1.0.0",
"react-tabs": "~2.1.0",
"react-toastify": "~2.1.2",
"react-tabs": "~2.3.0",
"react-toastify": "^4.4.3",
"react-toggle": "~4.0.2",
"react-transition-group": "~2.2.1",
"reconnecting-websocket": "~v3.2.2",
"react-transition-group": "~2.5.0",
"reconnecting-websocket": "~v4.1.10",
"redis": "~2.8.0",
"string-hash": "~1.1.3",
"tippy.js": "~2.0.2",
"winston": "^2.4.4",
"yaml": "^1.0.0"
"tippy.js": "^3.1.3",
"winston": "^3.1.0",
"yaml": "^1.0.3"
},
"devDependencies": {
"axios": "^0.18.0",
"dotenv": "^6.1.0",
"eslint": "~4.9.0",
"eslint-config-airbnb": "~16.1.0",
"eslint-config-airbnb-base": "~12.1.0",
"eslint-plugin-import": "~2.8.0",
"eslint-plugin-jsx-a11y": "~6.0.2",
"eslint-plugin-react": "~7.4.0",
"husky": "~0.14.3",
"jest": "^23.6.0",
"lint-staged": "~4.3.0",
"postcss-modules-extract-imports": "1.1.0",
"chai": "~4.2.0",
"eslint": "~5.8.0",
"eslint-config-airbnb": "~17.1.0",
"eslint-config-airbnb-base": "~13.1.0",
"eslint-plugin-import": "~2.14.0",
"eslint-plugin-jsx-a11y": "~6.1.2",
"eslint-plugin-react": "~7.11.1",
"husky": "^1.1.4",
"lint-staged": "^8.0.5",
"postcss-modules-extract-imports": "2.0.0",
"postcss-modules-local-by-default": "1.2.0",
"postcss-modules-scope": "1.1.0",
"postcss-modules-values": "1.3.0",
"puppeteer": "^1.10.0",
"sha1": "^1.1.1"
"wdio-junit-reporter": "~0.4.4",
"wdio-spec-reporter": "^0.1.5",
"wdio-visual-regression-service": "~0.9.0",
"webdriver-manager": "~12.1.0",
"webdriverio": "^4.14.1"
},
"cssModules": {
"cssClassNamingConvention": {
@ -103,13 +104,13 @@
"autoprefixer": {}
}
},
"jest": {
"modulePathIgnorePatterns": [
"/tests/webdriverio"
]
},
"repository": {
"type": "git",
"url": "https://github.com/bigbluebutton/bigbluebutton.git"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
}

View File

@ -28,9 +28,8 @@ class Clear extends Page {
// []
const after = await util.getTestElements(this);
const response =
before[0].message == e.message &&
after.length == 0;
const response = before[0].message == e.message
&& after.length == 0;
return response;
}

View File

@ -24,9 +24,8 @@ class Send extends Page {
// [{ "name": "User1\nXX:XX XM", "message": "Hello world!" }]
const chat1 = await util.getTestElements(this);
const response =
chat0.length == 0 &&
chat1[0].message == e.message;
const response = chat0.length == 0
&& chat1[0].message == e.message;
return response;
}

View File

@ -19,8 +19,8 @@ async function createMeeting(params) {
const meetingID = `random-${getRandomInt(1000000, 10000000).toString()}`;
const mp = params.moderatorPW;
const ap = params.attendeePW;
const query = `name=${meetingID}&meetingID=${meetingID}&attendeePW=${ap}&moderatorPW=${mp}&joinViaHtml5=true` +
`&record=false&allowStartStopRecording=true&autoStartRecording=false&welcome=${params.welcome}`;
const query = `name=${meetingID}&meetingID=${meetingID}&attendeePW=${ap}&moderatorPW=${mp}&joinViaHtml5=true`
+ `&record=false&allowStartStopRecording=true&autoStartRecording=false&welcome=${params.welcome}`;
const apicall = `create${query}${params.secret}`;
const checksum = sha1(apicall);
const url = `${params.server}/create?${query}&checksum=${checksum}`;

View File

@ -12,7 +12,7 @@ class Page {
}
getParentDir(dir) {
let tmp = dir.split('/');
const tmp = dir.split('/');
tmp.pop();
return tmp.join('/');
}
@ -22,7 +22,7 @@ class Page {
this.browser = await puppeteer.launch(args);
this.page = await this.browser.newPage();
await this.setDownloadBehavior(this.parentDir + '/downloads');
await this.setDownloadBehavior(`${this.parentDir}/downloads`);
this.meetingId = await helper.createMeeting(params);
const joinURL = helper.getJoinURL(this.meetingId, params, true);
@ -33,7 +33,7 @@ class Page {
}
async setDownloadBehavior(downloadPath) {
const downloadBehavior = { behavior: 'allow', downloadPath: downloadPath };
const downloadBehavior = { behavior: 'allow', downloadPath };
await this.page._client.send('Page.setDownloadBehavior', downloadBehavior);
}
@ -113,9 +113,9 @@ class Page {
async screenshot(relief = false) {
if (relief) await helper.sleep(1000);
const filename = this.name + '-' + this.screenshotIndex + '.png';
const path = this.parentDir + '/screenshots/' + filename;
await this.page.screenshot({ path: path });
const filename = `${this.name}-${this.screenshotIndex}.png`;
const path = `${this.parentDir}/screenshots/${filename}`;
await this.page.screenshot({ path });
this.screenshotIndex++;
}

View File

@ -32,7 +32,7 @@ class Slide extends Page {
console.log(svg2);
// TODO: Check test
return true
return true;
}
async getTestElements() {

View File

@ -38,7 +38,7 @@ class Upload extends Page {
console.log(slides1.svg);
// TODO: Check test
return true
return true;
}
async getTestElements() {

View File

@ -29,7 +29,7 @@ class Draw extends Page {
console.log(shapes1);
// TODO: Check test
return true
return true;
}
async getTestElements() {