PR review fixes

This commit is contained in:
Oleksandr Zhurbenko 2017-09-05 18:36:15 -07:00
parent b12e0b84a9
commit 3014b26439
25 changed files with 214 additions and 203 deletions

View File

@ -16,21 +16,22 @@ export default function clearWhiteboard(credentials, whiteboardId) {
check(requesterToken, String);
check(whiteboardId, String);
if (Acl.can('methods.clearWhiteboard', credentials) || getMultiUserStatus(meetingId)) {
const header = {
name: EVENT_NAME,
meetingId,
userId: requesterUserId,
};
const payload = {
whiteboardId,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
const allowed = Acl.can('methods.clearWhiteboard', credentials) || getMultiUserStatus(meetingId);
if (!allowed) {
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to clear the whiteboard`,
);
}
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to clear the whiteboard`,
);
const header = {
name: EVENT_NAME,
meetingId,
userId: requesterUserId,
};
const payload = {
whiteboardId,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
}

View File

@ -13,10 +13,7 @@ function isLastMessage(annotation, userId) {
};
const _annotation = Annotations.findOne(selector);
if (_annotation != null) {
return true;
}
return false;
return _annotation !== null;
}
return false;
@ -41,23 +38,25 @@ export default function sendAnnotation(credentials, annotation) {
// and then slide/presentation changes, the user lost presenter rights,
// or multi-user whiteboard gets turned off
// So we allow the last "DRAW_END" message to pass through, to finish the shape.
if (Acl.can('methods.sendAnnotation', credentials) ||
const allowed = Acl.can('methods.sendAnnotation', credentials) ||
getMultiUserStatus(meetingId) ||
isLastMessage(annotation, requesterUserId)) {
const header = {
name: EVENT_NAME,
meetingId,
userId: requesterUserId,
};
isLastMessage(annotation, requesterUserId);
const payload = {
annotation,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
if (!allowed) {
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to send an annotation`,
);
}
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to send an annotation`,
);
const header = {
name: EVENT_NAME,
meetingId,
userId: requesterUserId,
};
const payload = {
annotation,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
}

View File

@ -16,21 +16,22 @@ export default function undoAnnotation(credentials, whiteboardId) {
check(requesterToken, String);
check(whiteboardId, String);
if (Acl.can('methods.undoAnnotation', credentials) || getMultiUserStatus(meetingId)) {
const header = {
name: EVENT_NAME,
meetingId,
userId: requesterUserId,
};
const payload = {
whiteboardId,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
const allowed = Acl.can('methods.undoAnnotation', credentials) || getMultiUserStatus(meetingId);
if (!allowed) {
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to undo the annotation`,
);
}
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to undo the annotation`,
);
const header = {
name: EVENT_NAME,
meetingId,
userId: requesterUserId,
};
const payload = {
whiteboardId,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
}

View File

@ -20,21 +20,23 @@ export default function publishCursorUpdate(credentials, coordinates) {
yPercent: Number,
});
if (Acl.can('methods.moveCursor', credentials) || getMultiUserStatus(meetingId)) {
const header = {
name: EVENT_NAME,
userId: requesterUserId,
meetingId,
};
const payload = {
xPercent: coordinates.xPercent,
yPercent: coordinates.yPercent,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
}
throw new Meteor.Error(
const allowed = Acl.can('methods.moveCursor', credentials) || getMultiUserStatus(meetingId);
if (!allowed) {
throw new Meteor.Error(
'not-allowed', `User ${requesterUserId} is not allowed to move the cursor`,
);
}
const header = {
name: EVENT_NAME,
userId: requesterUserId,
meetingId,
};
const payload = {
xPercent: coordinates.xPercent,
yPercent: coordinates.yPercent,
};
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
}

View File

@ -31,12 +31,13 @@ export default class PresentationArea extends React.Component {
setTimeout(this.handleResize.bind(this), 0);
});
const { presentationPaper, whiteboardSizeAvailable } = this;
this.getInitialPaperSizes(presentationPaper, whiteboardSizeAvailable);
this.getInitialPaperSizes();
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
window.removeEventListener('resize', () => {
setTimeout(this.handleResize.bind(this), 0);
});
}
// returns a ref to the svg element, which is required by a WhiteboardOverlay
@ -45,29 +46,9 @@ export default class PresentationArea extends React.Component {
return this.svggroup;
}
getInitialPaperSizes(presentationPaper, whiteboardSizeAvailable) {
// determining the paperWidth and paperHeight (available space for the svg) on the initial load
let clientHeight;
let clientWidth;
if (this.props.userIsPresenter) {
clientHeight = whiteboardSizeAvailable.clientHeight;
clientWidth = whiteboardSizeAvailable.clientWidth;
} else {
clientHeight = presentationPaper.clientHeight;
clientWidth = presentationPaper.clientWidth;
}
// setting the state of the paperWidth and paperheight (available space for the svg)
// and set the showSlide to true to start rendering the slide
this.setState({
paperHeight: clientHeight,
paperWidth: clientWidth,
showSlide: true,
});
}
handleResize() {
getPaperSizes() {
const { presentationPaper, whiteboardSizeAvailable } = this;
const paperSizes = {};
if (presentationPaper) {
// if a user is a presenter - this means there is a whiteboardToolBar on the right
@ -85,11 +66,28 @@ export default class PresentationArea extends React.Component {
clientWidth = presentationPaper.clientWidth;
}
paperSizes.paperHeight = clientHeight;
paperSizes.paperWidth = clientWidth;
}
return paperSizes;
}
getInitialPaperSizes() {
// determining the paperWidth and paperHeight (available space for the svg) on the initial load
const paperSizes = this.getPaperSizes();
if (Object.keys(paperSizes).length > 0) {
// setting the state of the paperWidth and paperHeight (available space for the svg)
// and set the showSlide to true to start rendering the slide
paperSizes.showSlide = true;
this.setState(paperSizes);
}
}
handleResize() {
const paperSizes = this.getPaperSizes();
if (Object.keys(paperSizes).length > 0) {
// updating the size of the space available for the slide
this.setState({
paperHeight: clientHeight,
paperWidth: clientWidth,
});
this.setState(paperSizes);
}
}

View File

@ -71,13 +71,13 @@ export default class Cursor extends Component {
componentWillMount() {
const cursorCoordinate = Cursor.getCursorCoordinates(this.props);
const { fill, displayLabel } = Cursor.getFillAndLabel(this.props);
const scaledSizes = Cursor.getScaledSizes(this.props);
const _scaledSizes = Cursor.getScaledSizes(this.props);
// setting the initial cursor info
this.cursorCoordinate = cursorCoordinate;
this.fill = fill;
this.displayLabel = displayLabel;
this.scaledSizes = scaledSizes;
this.scaledSizes = _scaledSizes;
}
componentDidMount() {
@ -108,8 +108,8 @@ export default class Cursor extends Component {
||
(labelBoxWidth !== nextProps.labelBoxWidth ||
labelBoxHeight !== nextProps.labelBoxHeight)) {
const scaledSizes = Cursor.getScaledSizes(nextProps);
this.scaledSizes = scaledSizes;
const _scaledSizes = Cursor.getScaledSizes(nextProps);
this.scaledSizes = _scaledSizes;
}
if (cursorX !== nextProps.cursorX || cursorY !== nextProps.cursorY) {

View File

@ -24,14 +24,15 @@ class CursorContainer extends Component {
render() {
const { cursorX, cursorY } = this.props;
const { labelBoxWidth, labelBoxHeight } = this.state;
if (cursorX > 0 && cursorY > 0) {
return (
<Cursor
cursorX={cursorX}
cursorY={cursorY}
labelBoxWidth={this.state.labelBoxWidth}
labelBoxHeight={this.state.labelBoxHeight}
labelBoxWidth={labelBoxWidth}
labelBoxHeight={labelBoxHeight}
setLabelBoxDimensions={this.setLabelBoxDimensions}
{...this.props}
/>

View File

@ -20,7 +20,7 @@ import CursorContainer from '../container';
const CursorWrapperContainer = ({ presenterCursorId, multiUserCursorIds, ...rest }) => (
<g>
{ presenterCursorId ?
{Object.keys(presenterCursorId).length > 0 ?
<CursorContainer
key={presenterCursorId._id}
presenter
@ -29,7 +29,7 @@ const CursorWrapperContainer = ({ presenterCursorId, multiUserCursorIds, ...rest
/>
: null }
{multiUserCursorIds && multiUserCursorIds.length > 0 ?
{multiUserCursorIds.length > 0 ?
multiUserCursorIds.map(cursorId =>
(<CursorContainer
key={cursorId._id}
@ -64,6 +64,6 @@ CursorWrapperContainer.propTypes = {
};
CursorWrapperContainer.defaultProps = {
presenterCursorId: undefined,
multiUserCursorIds: undefined,
presenterCursorId: {},
multiUserCursorIds: [],
};

View File

@ -80,7 +80,7 @@ AnnotationFactory.propTypes = {
// array of annotations, optional
annotationsInfo: PropTypes.arrayOf(PropTypes.object).isRequired,
annotationSelector: PropTypes.objectOf(PropTypes.instanceOf(Function)).isRequired,
annotationSelector: PropTypes.objectOf(PropTypes.func).isRequired,
};
AnnotationFactory.defaultProps = {

View File

@ -20,7 +20,7 @@ ReactiveAnnotation.propTypes = {
PropTypes.number,
PropTypes.object,
])).isRequired,
drawObject: PropTypes.instanceOf(Function).isRequired,
drawObject: PropTypes.func.isRequired,
slideWidth: PropTypes.number.isRequired,
slideHeight: PropTypes.number.isRequired,
};

View File

@ -34,7 +34,7 @@ ReactiveAnnotationContainer.propTypes = {
PropTypes.number,
PropTypes.object,
])),
drawObject: PropTypes.instanceOf(Function).isRequired,
drawObject: PropTypes.func.isRequired,
slideWidth: PropTypes.number.isRequired,
slideHeight: PropTypes.number.isRequired,
};

View File

@ -26,7 +26,7 @@ export default class StaticAnnotation extends React.Component {
StaticAnnotation.propTypes = {
shapeId: PropTypes.string.isRequired,
drawObject: PropTypes.instanceOf(Function).isRequired,
drawObject: PropTypes.func.isRequired,
slideWidth: PropTypes.number.isRequired,
slideHeight: PropTypes.number.isRequired,
};

View File

@ -40,15 +40,16 @@ export default class EllipseDrawComponent extends Component {
render() {
const results = this.getCoordinates();
const { annotation, slideWidth } = this.props;
const { cx, cy, rx, ry } = results;
return (
<ellipse
cx={results.cx}
cy={results.cy}
rx={results.rx}
ry={results.ry}
cx={cx}
cy={cy}
rx={rx}
ry={ry}
fill="none"
stroke={AnnotationHelpers.formatColor(annotation.color)}
stroke={AnnotationHelpers.getFormattedColor(annotation.color)}
strokeWidth={AnnotationHelpers.getStrokeWidth(annotation.thickness, slideWidth)}
style={{ WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)' }}
/>

View File

@ -8,7 +8,7 @@ const colourToHex = (value) => {
return `#${hex}`;
};
const formatColor = (color) => {
const getFormattedColor = (color) => {
let _color;
if (!color) {
@ -27,6 +27,6 @@ const formatColor = (color) => {
const getStrokeWidth = (thickness, slideWidth) => (thickness * slideWidth) / 100;
export default {
formatColor,
getFormattedColor,
getStrokeWidth,
};

View File

@ -28,14 +28,15 @@ export default class LineDrawComponent extends Component {
render() {
const results = this.getCoordinates();
const { annotation, slideWidth } = this.props;
const { x1, y1, x2, y2 } = results;
return (
<line
x1={results.x1}
y1={results.y1}
x2={results.x2}
y2={results.y2}
stroke={AnnotationHelpers.formatColor(annotation.color)}
x1={x1}
y1={y1}
x2={x2}
y2={y2}
stroke={AnnotationHelpers.getFormattedColor(annotation.color)}
strokeLinejoin="round"
strokeWidth={AnnotationHelpers.getStrokeWidth(annotation.thickness, slideWidth)}
style={{ WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)' }}

View File

@ -97,21 +97,18 @@ export default class PencilDrawComponent extends Component {
}
getCoordinates(annotation, slideWidth, slideHeight) {
let data;
// Final message, display smoothes coordinates
if (annotation.status === 'DRAW_END') {
const data = PencilDrawComponent.getFinalCoordinates(annotation, slideWidth, slideHeight);
this.points = data.points;
return data.path;
data = PencilDrawComponent.getFinalCoordinates(annotation, slideWidth, slideHeight);
// Not a final message, but rendering it for the first time, creating a new path
} else if (!this.path) {
const data = PencilDrawComponent.getInitialCoordinates(annotation, slideWidth, slideHeight);
this.points = data.points;
return data.path;
data = PencilDrawComponent.getInitialCoordinates(annotation, slideWidth, slideHeight);
// If it's not the first 2 cases - means we just got an update, updating the coordinates
} else {
data = this.updateCoordinates(annotation, slideWidth, slideHeight);
}
// If it's not the first 2 cases - means we just got an update, updating the coordinates
const data = this.updateCoordinates(annotation, slideWidth, slideHeight);
this.points = data.points;
return data.path;
}
@ -140,7 +137,7 @@ export default class PencilDrawComponent extends Component {
return (
<path
fill="none"
stroke={AnnotationHelpers.formatColor(annotation.color)}
stroke={AnnotationHelpers.getFormattedColor(annotation.color)}
d={this.getCurrentPath()}
strokeWidth={AnnotationHelpers.getStrokeWidth(annotation.thickness, slideWidth)}
strokeLinejoin="round"

View File

@ -54,7 +54,7 @@ export default class RectangleDrawComponent extends Component {
width={results.width}
height={results.height}
fill="none"
stroke={AnnotationHelpers.formatColor(annotation.color)}
stroke={AnnotationHelpers.getFormattedColor(annotation.color)}
strokeWidth={AnnotationHelpers.getStrokeWidth(annotation.thickness, slideWidth)}
style={{ WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)' }}
/>

View File

@ -30,6 +30,7 @@ export default class TextDrawComponent extends Component {
static getPresenterStyles(results) {
const styles = {
fontFamily: 'Arial',
lineHeight: 'normal',
border: '1px solid black',
width: '100%',
height: '100%',
@ -76,25 +77,35 @@ export default class TextDrawComponent extends Component {
getCoordinates() {
const { annotation, slideWidth, slideHeight } = this.props;
const x = (annotation.x / 100) * slideWidth;
const y = (annotation.y / 100) * slideHeight;
const width = (annotation.textBoxWidth / 100) * slideWidth;
const height = (annotation.textBoxHeight / 100) * slideHeight;
const fontColor = AnnotationHelpers.formatColor(annotation.fontColor);
const fontSize = annotation.fontSize;
const calcedFontSize = (annotation.calcedFontSize / 100) * slideHeight;
const text = annotation.text;
return {
const {
x,
y,
text,
width,
height,
fontSize,
textBoxWidth,
textBoxHeight,
fontColor,
fontSize,
calcedFontSize,
text,
} = annotation;
const _x = (x / 100) * slideWidth;
const _y = (y / 100) * slideHeight;
const _width = (textBoxWidth / 100) * slideWidth;
const _height = (textBoxHeight / 100) * slideHeight;
const _fontColor = AnnotationHelpers.getFormattedColor(fontColor);
const _fontSize = fontSize;
const _calcedFontSize = (calcedFontSize / 100) * slideHeight;
const _text = text;
return {
x: _x,
y: _y,
text: _text,
width: _width,
height: _height,
fontSize: _fontSize,
fontColor: _fontColor,
calcedFontSize: _calcedFontSize,
};
}

View File

@ -46,7 +46,7 @@ const activeTextShapeId = () => {
return drawSettings.textShape.textShapeActiveId;
}
return undefined;
return '';
};
export default {

View File

@ -39,7 +39,7 @@ export default class TriangleDrawComponent extends Component {
<path
style={{ WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)' }}
fill="none"
stroke={AnnotationHelpers.formatColor(annotation.color)}
stroke={AnnotationHelpers.getFormattedColor(annotation.color)}
d={path}
strokeWidth={AnnotationHelpers.getStrokeWidth(annotation.thickness, slideWidth)}
strokeLinejoin="miter"

View File

@ -90,26 +90,26 @@ export default class WhiteboardOverlay extends Component {
let y = point.y;
// set this flag to true if either x or y are out of bounds
let shouldUnSelect = false;
let shouldUnselect = false;
if (x < viewBoxX) {
x = viewBoxX;
shouldUnSelect = true;
shouldUnselect = true;
} else if (x > viewBoxX + viewBoxWidth) {
x = viewBoxX + viewBoxWidth;
shouldUnSelect = true;
shouldUnselect = true;
}
if (y < viewBoxY) {
y = viewBoxY;
shouldUnSelect = true;
shouldUnselect = true;
} else if (y > viewBoxY + viewBoxHeight) {
y = viewBoxY + viewBoxHeight;
shouldUnSelect = true;
shouldUnselect = true;
}
// if either x or y are out of bounds - remove selection from potentially selected elements
if (shouldUnSelect) {
if (shouldUnselect) {
WhiteboardOverlay.unSelect();
}

View File

@ -5,7 +5,7 @@ import WhiteboardOverlayService from './service';
import WhiteboardOverlay from './component';
const WhiteboardOverlayContainer = ({ ...props }) => {
if (props.drawSettings) {
if (Object.keys(props.drawSettings).length > 0) {
return (
<WhiteboardOverlay {...props} />
);
@ -40,5 +40,5 @@ WhiteboardOverlayContainer.propTypes = {
};
WhiteboardOverlayContainer.defaultProps = {
drawSettings: undefined,
drawSettings: {},
};

View File

@ -26,7 +26,7 @@ const getWhiteboardToolbarValues = () => {
textShapeActiveId: textShape.textShapeActiveId ? textShape.textShapeActiveId : '',
};
}
return undefined;
return {};
};
const resetTextShapeSession = () => {

View File

@ -51,48 +51,49 @@ export default class ShapeDrawListener extends Component {
// main mouse down handler
mouseDownHandler(event) {
if (!this.isDrawing) {
window.addEventListener('mouseup', this.mouseUpHandler);
window.addEventListener('mousemove', this.mouseMoveHandler, true);
this.isDrawing = true;
const {
getTransformedSvgPoint,
generateNewShapeId,
svgCoordinateToPercentages,
} = this.props.actions;
// sending the first message
let transformedSvgPoint = getTransformedSvgPoint(event);
// transforming svg coordinate to percentages relative to the slide width/height
transformedSvgPoint = svgCoordinateToPercentages(transformedSvgPoint);
// generating new shape id
generateNewShapeId();
// setting the initial current status
this.currentStatus = 'DRAW_START';
// saving the coordinates for future references
this.initialCoordinate = {
x: transformedSvgPoint.x,
y: transformedSvgPoint.y,
};
this.currentCoordinate = {
x: transformedSvgPoint.x,
y: transformedSvgPoint.y,
};
// All the messages will be send on timer by sendCoordinates func
this.intervalId = setInterval(this.sendCoordinates, MESSAGE_INTERVAL);
// Sometimes when you Alt+Tab while drawing it can happen that your mouse is up,
// but the browser didn't catch it. So check it here.
} else {
this.sendLastMessage();
// Sometimes when you Alt+Tab while drawing it can happen that your mouse is up,
// but the browser didn't catch it. So check it here.
if (this.isDrawing) {
return this.sendLastMessage();
}
window.addEventListener('mouseup', this.mouseUpHandler);
window.addEventListener('mousemove', this.mouseMoveHandler, true);
this.isDrawing = true;
const {
getTransformedSvgPoint,
generateNewShapeId,
svgCoordinateToPercentages,
} = this.props.actions;
// sending the first message
let transformedSvgPoint = getTransformedSvgPoint(event);
// transforming svg coordinate to percentages relative to the slide width/height
transformedSvgPoint = svgCoordinateToPercentages(transformedSvgPoint);
// generating new shape id
generateNewShapeId();
// setting the initial current status
this.currentStatus = 'DRAW_START';
// saving the coordinates for future references
this.initialCoordinate = {
x: transformedSvgPoint.x,
y: transformedSvgPoint.y,
};
this.currentCoordinate = {
x: transformedSvgPoint.x,
y: transformedSvgPoint.y,
};
// All the messages will be send on timer by sendCoordinates func
this.intervalId = setInterval(this.sendCoordinates, MESSAGE_INTERVAL);
return true;
}
// main mouse move handler

View File

@ -141,7 +141,7 @@ export default class WhiteboardToolbar extends Component {
* we have 4 main cases:
* 1. Color change -
a) Text tool is selected, Font-Size icon substitutes the thickness icon,
thus we need to trigger just color change for the color icon
thus we need to trigger the color change just for the color icon
b) Any other tool than Text tool is selected - trigger color change for both icons
* 2. Thickness change - trigger radius for the thickness icon
* 3. Switch from the Text tool to any other - trigger color and radius for thickness
@ -150,14 +150,12 @@ export default class WhiteboardToolbar extends Component {
// 1st case
if (this.state.colorSelected !== prevState.colorSelected) {
// 1st case a)
if (this.state.annotationSelected.sessionValue === 'text') {
this.colorListIconColor.beginElement();
// 1st case b)
} else {
this.colorListIconColor.beginElement();
if (this.state.annotationSelected.sessionValue !== 'text') {
this.thicknessListIconColor.beginElement();
}
// 1st case a)
this.colorListIconColor.beginElement();
// 2nd case
} else if (this.state.thicknessSelected !== prevState.thicknessSelected) {
this.thicknessListIconRadius.beginElement();