Skip to content

Commit

Permalink
Merge branch 'develop' into feature/511-basic-export
Browse files Browse the repository at this point in the history
  • Loading branch information
blms committed Oct 28, 2024
2 parents 9a96ee4 + e9eec0b commit 2bd0e20
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 28 deletions.
112 changes: 108 additions & 4 deletions client/src/DocumentViewer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import {
DragSource,
DropTarget
Expand All @@ -12,15 +13,16 @@ import Close from 'material-ui/svg-icons/navigation/close';
import Visibility from 'material-ui/svg-icons/action/visibility';
import VisibilityOff from 'material-ui/svg-icons/action/visibility-off';
import Description from 'material-ui/svg-icons/action/description';
import { grey100, grey800, grey900 } from 'material-ui/styles/colors';
import { grey100, grey200, grey300, grey800, grey900, white } from 'material-ui/styles/colors';
import { updateDocument, closeDocument, moveDocumentWindow, layoutOptions } from './modules/documentGrid';
import { toggleCanvasHighlights } from './modules/canvasEditor';
import { toggleTextHighlights } from './modules/textEditor';
import { closeDocumentTargets } from './modules/annotationViewer';
import TextResource from './TextResource';
import CanvasResource from './CanvasResource';
import DocumentStatusBar from './DocumentStatusBar';
import { Popover } from 'material-ui';
import { Popover, RaisedButton } from 'material-ui';
import { BoxArrowUp, Check2 } from 'react-bootstrap-icons';

const DocumentInner = function(props) {
switch (props.document_kind) {
Expand Down Expand Up @@ -90,6 +92,10 @@ class DocumentViewer extends Component {
doneSaving: true,
cornerIconTooltipOpen: false,
cornerIconTooltipAnchor: null,
sharePanelOpen: false,
sharePanelAnchor: null,
documentURL: '',
hasCopiedURL: false,
}
}

Expand All @@ -103,6 +109,7 @@ class DocumentViewer extends Component {

componentDidMount() {
this.props.connectDragPreview(new Image());
this.getDocumentURL(this.props.document_id);
}

isEditable = () => {
Expand Down Expand Up @@ -174,6 +181,50 @@ class DocumentViewer extends Component {
});
}

onShareOpen (e) {
e.persist();
const sharePanelAnchor = e.currentTarget;
e.preventDefault();
this.setState((prevState) => {
return {
...prevState,
sharePanelOpen: true,
sharePanelAnchor,
}
});
}

onShareClose () {
this.setState((prevState) => {
return {
...prevState,
sharePanelOpen: false,
hasCopiedURL: false,
}
});
}

getDocumentURL(docId) {
const loc = window.location.href.replace(window.location.search, "");
this.setState((prevState) => ({
...prevState,
documentURL: `${loc}?document=${docId}`
}));
}

copyDocumentURL(e) {
if (e.currentTarget.nodeName === "INPUT") {
e.currentTarget.select();
} else {
e.currentTarget.parentNode.parentNode.querySelector("#document-link").select();
}
navigator.clipboard.writeText(this.state.documentURL);
this.setState((prevState) => ({
...prevState,
hasCopiedURL: true,
}));
}

renderTitleBar() {
const iconStyle = {
padding: '0',
Expand Down Expand Up @@ -218,8 +269,60 @@ class DocumentViewer extends Component {
onChange={this.onChangeTitle}
disabled={!this.isEditable()}
/>
<IconButton
tooltip="Share document"
onClick={this.onShareOpen.bind(this)}
style={buttonStyle}
iconStyle={{ width: '16px', height: '16px' }}
>
<BoxArrowUp color={this.props.document_kind === 'canvas' ? '#FFF' : '#000'} />
</IconButton>
<Popover
open={this.state.sharePanelOpen}
anchorEl={this.state.sharePanelAnchor}
zDepth={5}
className="share-panel"
anchorOrigin={{horizontal: 'right', vertical: 'bottom'}}
targetOrigin={{horizontal: 'right', vertical: 'top'}}
useLayerForClickAway={true}
autoCloseWhenOffScreen={true}
onRequestClose={this.onShareClose.bind(this)}
style={{ padding: '5px 0 5px 10px', backgroundColor: grey200 }}
>
<div style={{
display: 'flex',
gap: '10px',
flexFlow: 'row nowrap',
alignItems: 'center',
}}>
<TextField
id="document-link"
value={this.state.documentURL}
onFocus={this.copyDocumentURL.bind(this)}
onClick={this.copyDocumentURL.bind(this)}
inputStyle={{
backgroundColor: white,
height: '40px',
marginTop: '5px',
padding: '0 5px',
}}
underlineStyle={{
marginBottom: '-5px',
padding: '0 5px',
}}
style={{ margin: '0 10px 0 0' }}
/>
<RaisedButton
icon={this.state.hasCopiedURL ? <Check2 /> : null}
label={this.state.hasCopiedURL ? "Copied" : "Copy link"}
style={{marginRight: '10px'}}
onClick={this.copyDocumentURL.bind(this)}
backgroundColor={this.state.hasCopiedURL ? grey300 : white}
/>
</div>
</Popover>
{ !this.isEditable() &&
<IconButton tooltip='Toggle highlights' onClick={this.onToggleHighlights.bind(this)} style={buttonStyle} iconStyle={iconStyle}>
<IconButton tooltip='Toggle highlights' tooltipStyles={{ marginLeft: '-10px' }} onClick={this.onToggleHighlights.bind(this)} style={buttonStyle} iconStyle={iconStyle}>
{ highlightsHidden
? <VisibilityOff
color={this.props.document_kind === 'canvas' ? '#FFF' : '#000'}
Expand Down Expand Up @@ -349,4 +452,5 @@ const mapDispatchToProps = (dispatch, props) => bindActionCreators({
export default connect(
mapStateToProps,
mapDispatchToProps
)(DocumentViewer);
)(withRouter((props) => <DocumentViewer {...props} />));

39 changes: 29 additions & 10 deletions client/src/Project.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import HTML5Backend from 'react-dnd-html5-backend';
import { DragDropContext } from 'react-dnd';
import { loadProject, updateProject, showSettings, hideSettings, checkInAll } from './modules/project';
import { selectTarget, closeTarget, closeTargetRollover, promoteTarget } from './modules/annotationViewer';
import { closeDeleteDialog, confirmDeleteDialog, layoutOptions, updateSnackBar, fetchLock } from './modules/documentGrid';
import { closeDeleteDialog, confirmDeleteDialog, layoutOptions, openDocument, openInitialDocs, updateSnackBar, fetchLock } from './modules/documentGrid';
import { selectHighlight } from './modules/textEditor';
import Dialog from 'material-ui/Dialog';
import Snackbar from 'material-ui/Snackbar';
Expand Down Expand Up @@ -118,6 +118,11 @@ class Project extends Component {
window.hideRollover = this.hideRollover.bind(this);
if (this.props.match.params.slug !== 'new') {
this.props.loadProject(this.props.match.params.slug, this.props.projectTitle)
// open documents included in query params
const queryParams = new URLSearchParams(this.props.location.search);
if (queryParams) {
this.props.openInitialDocs(queryParams.getAll("document"));
}
}
}

Expand All @@ -128,6 +133,17 @@ class Project extends Component {
this.props.fetchLock(id);
});
}
if (prevProps.openDocuments !== this.props.openDocuments && !this.props.loadingInitialDocs) {
// update query params when opening or closing a document
const queryParams = new URLSearchParams();
this.props.openDocuments.forEach((doc) => {
queryParams.append("document", doc.id.toString());
});
this.props.history.replace({
pathname: this.props.location.pathname,
search: `?${queryParams.toString()}`,
});
}
}

renderDeleteDialog() {
Expand Down Expand Up @@ -325,6 +341,7 @@ const mapStateToProps = state => ({
deleteDialogTitle: state.documentGrid.deleteDialogTitle,
deleteDialogBody: state.documentGrid.deleteDialogBody,
deleteDialogSubmit: state.documentGrid.deleteDialogSubmit,
loadingInitialDocs: state.documentGrid.loadingInitialDocs,
snackBarOpen: state.documentGrid.snackBarOpen,
snackBarMessage: state.documentGrid.snackBarMessage,
currentLayout: layoutOptions[state.documentGrid.currentLayout],
Expand All @@ -336,20 +353,22 @@ const mapStateToProps = state => ({
});

const mapDispatchToProps = dispatch => bindActionCreators({
loadProject,
updateProject,
selectTarget,
checkInAll,
closeDeleteDialog,
closeTarget,
closeTargetRollover,
promoteTarget,
closeDeleteDialog,
confirmDeleteDialog,
showSettings,
checkInAll,
updateSnackBar,
fetchLock,
hideSettings,
loadProject,
openDocument,
openInitialDocs,
promoteTarget,
selectHighlight,
fetchLock,
selectTarget,
showSettings,
updateProject,
updateSnackBar,
}, dispatch);

export default connect(
Expand Down
11 changes: 6 additions & 5 deletions client/src/TextResource.js
Original file line number Diff line number Diff line change
Expand Up @@ -1285,13 +1285,14 @@ class TextResource extends Component {
let alteredHighlights = [];
let effectedMarks = [];
const editorState = this.getEditorState();
if (steps.length > 0 && steps.every((step) => step instanceof AddMarkStep && step.mark.type.name === this.state.documentSchema.marks.highlight.name)) {
// on highlight, will create 1 AddMarkStep per line break / element crossing
// save one new highlight for the entire range
this.createHighlight(steps[0].mark, tx.curSelection.content(), serializer);
}
steps.forEach(step => {
// save new highlight
if (step instanceof AddMarkStep && step.mark.type.name === this.state.documentSchema.marks.highlight.name) {
this.createHighlight(step.mark, tx.curSelection.content(), serializer);
}
// process highlights that have been removed or altered by a text content change or a mark toggle
else if (step instanceof ReplaceStep || (step instanceof RemoveMarkStep && step.mark.type.name === this.state.documentSchema.marks.highlight.name)) {
if (step instanceof ReplaceStep || (step instanceof RemoveMarkStep && step.mark.type.name === this.state.documentSchema.marks.highlight.name)) {
// TODO: handle case where the space between two highlights is eliminated
// pad the range where we look for effected highlights in order to accommodate edge cases with cursor at beginning or end of highlight
let from = Math.max(step.from - 1, 0), to = step.to;
Expand Down
Loading

0 comments on commit 2bd0e20

Please sign in to comment.