aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFawn <fangrui_tong@brown.edu>2019-07-27 23:38:55 -0400
committerFawn <fangrui_tong@brown.edu>2019-07-27 23:38:55 -0400
commit1c7ae29e05e2a7c6ad75d3edb6a9ea17ed36e523 (patch)
tree68d5baa8a501a5b511e21630657c7e15a148a573 /src
parentcf4da743cc82357b4018184d026a07f715f61ad5 (diff)
parent73d30f20e5d38104424c47845a28e860070e4159 (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into schema_view_improvements_2
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DragManager.ts1
-rw-r--r--src/client/views/DocumentDecorations.tsx18
-rw-r--r--src/client/views/Main.tsx5
-rw-r--r--src/client/views/collections/CollectionPDFView.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaMovableTableHOC.tsx2
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx6
-rw-r--r--src/client/views/collections/CollectionVideoView.tsx2
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx6
-rw-r--r--src/client/views/collections/KeyRestrictionRow.tsx2
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx57
-rw-r--r--src/client/views/nodes/LinkMenu.tsx9
-rw-r--r--src/client/views/nodes/LinkMenuGroup.tsx2
-rw-r--r--src/client/views/nodes/LinkMenuItem.tsx28
-rw-r--r--src/server/authentication/models/current_user_utils.ts4
14 files changed, 105 insertions, 39 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 5a4fa3688..9221ef274 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -436,7 +436,6 @@ export namespace DragManager {
if (options) {
options.handlers.dragComplete({});
}
- DocumentDecorations.Instance.endLinkDragBatch();
};
AbortDrag = () => {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index ee16938ff..40f2c3da9 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -378,16 +378,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
}
}
- endLinkDragBatch = () => {
- if (!this._linkDrag) {
- return;
- }
- this._linkDrag.end();
- this._linkDrag = undefined;
- }
-
onLinkerButtonDown = (e: React.PointerEvent): void => {
- this._linkDrag = UndoManager.StartBatch("Drag Link");
e.stopPropagation();
document.removeEventListener("pointermove", this.onLinkerButtonMoved);
document.addEventListener("pointermove", this.onLinkerButtonMoved);
@@ -424,9 +415,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
let container = selDoc.props.ContainingCollectionView ? selDoc.props.ContainingCollectionView.props.Document.proto : undefined;
let dragData = new DragManager.LinkDragData(selDoc.props.Document, container ? [container] : []);
FormattedTextBox.InputBoxOverlay = undefined;
+ this._linkDrag = UndoManager.StartBatch("Drag Link");
DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, {
handlers: {
- dragComplete: action(emptyFunction),
+ dragComplete: () => {
+ if (this._linkDrag) {
+ this._linkDrag.end();
+ this._linkDrag = undefined;
+ }
+ },
},
hideSource: false
});
@@ -679,6 +676,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
linkButton = (<Flyout
anchorPoint={anchorPoints.RIGHT_TOP}
content={<LinkMenu docView={selFirst}
+ addDocTab={selFirst.props.addDocTab}
changeFlyout={this.changeFlyoutContent} />}>
<div className={"linkButton-" + (linkCount ? "nonempty" : "empty")} onPointerDown={this.onLinkButtonDown} >{linkCount}</div>
</Flyout >);
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 86578af3e..1cf13aa74 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -33,6 +33,11 @@ let swapDocs = async () => {
DocServer.init(window.location.protocol, window.location.hostname, 4321, info.email);
await Docs.Prototypes.initialize();
await CurrentUserUtils.loadUserDocument(info);
+ // updates old user documents to prevent chrome on tree view.
+ (await Cast(CurrentUserUtils.UserDocument.workspaces, Doc))!.chromeStatus = "disabled";
+ (await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))!.chromeStatus = "disabled";
+ (await Cast(CurrentUserUtils.UserDocument.sidebar, Doc))!.chromeStatus = "disabled";
+ CurrentUserUtils.UserDocument.chromeStatus = "disabled";
await swapDocs();
ReactDOM.render(<MainView />, document.getElementById('root'));
})(); \ No newline at end of file
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 9074854d6..70010819a 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -78,7 +78,7 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
let props = { ...this.props, ...renderProps };
return (
<>
- <CollectionFreeFormView {...props} setPdfBox={this.setPdfBox} CollectionView={this} />
+ <CollectionFreeFormView {...props} setPdfBox={this.setPdfBox} CollectionView={this} chromeCollapsed={true} />
{renderProps.active() ? this.uIButtons : (null)}
</>
);
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 2349e42ca..7342ede7a 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -180,7 +180,7 @@ export class MovableRow extends React.Component<MovableRowProps> {
onRowContextMenu = (e: React.MouseEvent): void => {
let description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row";
- ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original) });
+ ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: "file-pdf" });
}
@action
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 1a5d203f9..cf6079196 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -74,7 +74,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
let layoutDoc = Doc.expandTemplateLayout(d, parent.props.DataDoc);
let headings = this.props.headings();
let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
- let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d)
+ let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d);
let width = () => (d.nativeWidth && !BoolCast(d.ignoreAspect) ? Math.min(pair.layout[WidthSym](), parent.columnWidth) : parent.columnWidth) / (uniqueHeadings.length + 1);
let height = () => parent.getDocHeight(pair.layout);
if (parent.singleColumn) {
@@ -243,12 +243,12 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
SetValue: this.headingChanged,
contents: evContents,
oneLine: true
- }
+ };
let newEditableViewProps = {
GetValue: () => "",
SetValue: this.addDocument,
contents: "+ NEW"
- }
+ };
let headingView = this.props.headingObject ?
<div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef}
style={{ width: (style.columnWidth) / (uniqueHeadings.length + 1) }}>
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 31a8a93e0..a264cc402 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -89,7 +89,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
private subView = (_type: CollectionViewType, renderProps: CollectionRenderProps) => {
let props = { ...this.props, ...renderProps };
return (<>
- <CollectionFreeFormView {...props} setVideoBox={this.setVideoBox} CollectionView={this} />
+ <CollectionFreeFormView {...props} setVideoBox={this.setVideoBox} CollectionView={this} chromeCollapsed={true} />
{this.props.isSelected() ? this.uIButtons : (null)}
</>);
}
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index de1d01ef0..044d5336a 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -40,11 +40,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
private _datePickerElGuid = Utils.GenerateGuid();
componentDidMount = () => {
- this._picker = datepicker("#" + this._datePickerElGuid, {
+ setTimeout(() => this._picker = datepicker("#" + this._datePickerElGuid, {
disabler: (date: Date) => date > new Date(),
onSelect: (instance: any, date: Date) => runInAction(() => this._dateValue = date),
dateSelected: new Date()
- });
+ }), 1000);
runInAction(() => {
this._keyRestrictions.push([<KeyRestrictionRow key={Utils.GenerateGuid()} contains={true} script={(value: string) => runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]);
@@ -296,7 +296,7 @@ export class CollectionStackingViewChrome extends React.Component<CollectionView
return true;
}
- @action toggleSort = () => { this.props.CollectionView.props.Document.stackingHeadersSortDescending = !this.props.CollectionView.props.Document.stackingHeadersSortDescending; }
+ @action toggleSort = () => { this.props.CollectionView.props.Document.stackingHeadersSortDescending = !this.props.CollectionView.props.Document.stackingHeadersSortDescending; };
@action resetValue = () => { this._currentKey = this.sectionFilter; };
render() {
diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx
index 8051a8359..f292557b5 100644
--- a/src/client/views/collections/KeyRestrictionRow.tsx
+++ b/src/client/views/collections/KeyRestrictionRow.tsx
@@ -40,6 +40,6 @@ export default class KeyRestrictionRow extends React.Component<IKeyRestrictionPr
onChange={(e) => runInAction(() => this._value = e.target.value)}
placeholder="VALUE" />
</div>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 5ac4af0bb..d5f539194 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { baseKeymap } from "prosemirror-commands";
import { history } from "prosemirror-history";
import { keymap } from "prosemirror-keymap";
-import { NodeType } from 'prosemirror-model';
+import { NodeType, Slice, Node, Fragment } from 'prosemirror-model';
import { EditorState, Plugin, Transaction } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { Doc, Opt } from "../../../new_fields/Doc";
@@ -34,7 +34,6 @@ import { FieldView, FieldViewProps } from "./FieldView";
import "./FormattedTextBox.scss";
import React = require("react");
import { DateField } from '../../../new_fields/DateField';
-import { thisExpression } from 'babel-types';
import { Utils } from '../../../Utils';
library.add(faEdit);
@@ -251,6 +250,56 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
this.setupEditor(config, this.dataDoc, this.props.fieldKey);
}
+ clipboardTextSerializer = (slice: Slice): string => {
+ let text = "", separated = true;
+ const from = 0, to = slice.content.size;
+ slice.content.nodesBetween(from, to, (node, pos) => {
+ if (node.isText) {
+ text += node.text!.slice(Math.max(from, pos) - pos, to - pos);
+ separated = false;
+ } else if (!separated && node.isBlock) {
+ text += "\n";
+ separated = true;
+ } else if (node.type.name === "hard_break") {
+ text += "\n";
+ }
+ }, 0);
+ return text;
+ }
+
+ sliceSingleNode(slice: Slice) {
+ return slice.openStart === 0 && slice.openEnd === 0 && slice.content.childCount === 1 ? slice.content.firstChild : null;
+ }
+
+ handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => {
+ return false;
+ function addMarkToFrag(frag: Fragment) {
+ const nodes: Node[] = [];
+ frag.forEach(node => nodes.push(addLinkMark(node)));
+ return Fragment.fromArray(nodes);
+ }
+ function addLinkMark(node: Node) {
+ if (!node.isText) {
+ const content = addMarkToFrag(node.content);
+ return node.copy(content);
+ }
+ const marks = [...node.marks];
+ const linkIndex = marks.findIndex(mark => mark.type.name === "link");
+ const link = view.state.schema.mark(view.state.schema.marks.link, { href: "http://localhost:1050/doc/[link document id]", location: "onRight" });
+ if (linkIndex !== -1) {
+ marks.splice(linkIndex, 1, link);
+ } else {
+ marks.push(link);
+ }
+ return node.mark(marks);
+ }
+ let frag = addMarkToFrag(slice.content);
+ slice = new Slice(frag, slice.openStart, slice.openEnd);
+ var tr = view.state.tr.replaceSelection(slice);
+ view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste"));
+ return true;
+ }
+
private setupEditor(config: any, doc: Doc, fieldKey: string) {
let field = doc ? Cast(doc[fieldKey], RichTextField) : undefined;
let startup = StrCast(doc.documentText);
@@ -270,7 +319,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
nodeViews: {
image(node, view, getPos) { return new ImageResizeView(node, view, getPos); },
star(node, view, getPos) { return new SummarizedView(node, view, getPos); }
- }
+ },
+ clipboardTextSerializer: this.clipboardTextSerializer,
+ handlePaste: this.handlePaste,
});
if (startup) {
Doc.GetProto(doc).documentText = undefined;
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index 1eda7d1fb..1a4af04f8 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -19,6 +19,7 @@ import { DocumentType } from "../../documents/Documents";
interface Props {
docView: DocumentView;
changeFlyout: () => void;
+ addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
}
@observer
@@ -39,7 +40,13 @@ export class LinkMenu extends React.Component<Props> {
let linkItems: Array<JSX.Element> = [];
groups.forEach((group, groupType) => {
linkItems.push(
- <LinkMenuGroup key={groupType} sourceDoc={this.props.docView.props.Document} group={group} groupType={groupType} showEditor={action((linkDoc: Doc) => this._editingLink = linkDoc)} />
+ <LinkMenuGroup
+ key={groupType}
+ sourceDoc={this.props.docView.props.Document}
+ group={group}
+ groupType={groupType}
+ showEditor={action((linkDoc: Doc) => this._editingLink = linkDoc)}
+ addDocTab={this.props.addDocTab} />
);
});
diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx
index 3637807ad..0cb216aa6 100644
--- a/src/client/views/nodes/LinkMenuGroup.tsx
+++ b/src/client/views/nodes/LinkMenuGroup.tsx
@@ -21,6 +21,7 @@ interface LinkMenuGroupProps {
group: Doc[];
groupType: string;
showEditor: (linkDoc: Doc) => void;
+ addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
}
@observer
@@ -83,6 +84,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc);
if (destination && this.props.sourceDoc) {
return <LinkMenuItem key={destination[Id] + this.props.sourceDoc[Id]} groupType={this.props.groupType}
+ addDocTab={this.props.addDocTab}
linkDoc={linkDoc} sourceDoc={this.props.sourceDoc} destinationDoc={destination} showEditor={this.props.showEditor} />;
}
});
diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx
index d4c92c9f2..1d4fcad69 100644
--- a/src/client/views/nodes/LinkMenuItem.tsx
+++ b/src/client/views/nodes/LinkMenuItem.tsx
@@ -12,6 +12,7 @@ import { observable, action } from 'mobx';
import { LinkManager } from '../../util/LinkManager';
import { DragLinkAsDocument } from '../../util/DragManager';
import { CollectionDockingView } from '../collections/CollectionDockingView';
+import { SelectionManager } from '../../util/SelectionManager';
library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp);
@@ -21,6 +22,7 @@ interface LinkMenuItemProps {
sourceDoc: Doc;
destinationDoc: Doc;
showEditor: (linkDoc: Doc) => void;
+ addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
}
@observer
@@ -42,18 +44,24 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
let targetContext = await Cast(proto.targetContext, Doc);
let sourceContext = await Cast(proto.sourceContext, Doc);
let self = this;
- if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
+
+
+ let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
+ if (e.ctrlKey) {
+ dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined);
+ }
+
+ if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) {
+ DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(targetContext!));
+ }
+ else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) {
+ DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!));
+ }
+ else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page)));
}
- else if (!((this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) || (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext))) {
- DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(document, undefined));
- } else {
- if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) {
- DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(targetContext!, undefined));
- }
- else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) {
- DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(sourceContext!, undefined));
- }
+ else {
+ DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, dockingFunc);
}
}
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 41eb1aa0c..1c52a3f11 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -50,7 +50,6 @@ export class CurrentUserUtils {
if (doc.workspaces === undefined) {
const workspaces = Docs.Create.TreeDocument([], { title: "Workspaces", height: 100 });
workspaces.excludeFromLibrary = true;
- workspaces.chromeStatus = "disabled";
workspaces.workspaceLibrary = true;
workspaces.boxShadow = "0 0";
doc.workspaces = workspaces;
@@ -58,7 +57,6 @@ export class CurrentUserUtils {
if (doc.recentlyClosed === undefined) {
const recentlyClosed = Docs.Create.TreeDocument([], { title: "Recently Closed", height: 75 });
recentlyClosed.excludeFromLibrary = true;
- recentlyClosed.chromeStatus = "disabled";
recentlyClosed.boxShadow = "0 0";
doc.recentlyClosed = recentlyClosed;
}
@@ -67,13 +65,11 @@ export class CurrentUserUtils {
sidebar.excludeFromLibrary = true;
sidebar.gridGap = 5;
sidebar.xMargin = 5;
- sidebar.chromeStatus = "disabled";
sidebar.yMargin = 5;
Doc.GetProto(sidebar).backgroundColor = "#aca3a6";
sidebar.boxShadow = "1 1 3";
doc.sidebar = sidebar;
}
- doc.chromeStatus = "disabled";
StrCast(doc.title).indexOf("@") !== -1 && (doc.title = StrCast(doc.title).split("@")[0] + "'s Library");
}