aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DocumentManager.ts2
-rw-r--r--src/client/util/ProsemirrorExampleTransfer.ts82
-rw-r--r--src/client/util/RichTextSchema.tsx102
-rw-r--r--src/client/util/TooltipTextMenu.tsx34
-rw-r--r--src/client/views/DocumentDecorations.tsx17
-rw-r--r--src/client/views/MainOverlayTextBox.tsx10
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/OverlayView.tsx1
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx1
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx1
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx1
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx3
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx2
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx42
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx35
-rw-r--r--src/client/views/nodes/DocumentView.tsx6
-rw-r--r--src/client/views/nodes/FieldView.tsx2
-rw-r--r--src/client/views/nodes/FormattedTextBox.scss35
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx180
-rw-r--r--src/client/views/nodes/FormattedTextBoxComment.scss34
-rw-r--r--src/client/views/nodes/FormattedTextBoxComment.tsx110
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx1
-rw-r--r--src/client/views/pdf/PDFViewer.tsx6
-rw-r--r--src/client/views/pdf/Page.tsx7
-rw-r--r--src/client/views/presentationview/PresentationElement.tsx1
-rw-r--r--src/client/views/search/SearchItem.tsx1
-rw-r--r--src/server/authentication/config/passport.ts10
-rw-r--r--src/server/index.ts8
29 files changed, 498 insertions, 242 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 124faf266..ec731da84 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -204,4 +204,4 @@ export class DocumentManager {
}
}
}
-Scripting.addGlobal(function focus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, true)) }) \ No newline at end of file
+Scripting.addGlobal(function focus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, true)); }); \ No newline at end of file
diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index 3cdfba59a..3979d8a49 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -79,66 +79,71 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
bind("Mod-s", TooltipTextMenu.insertStar);
+ let nodeTypeMark = (depth: number) => depth === 2 ? "indent2" : depth === 4 ? "indent3" : depth === 6 ? "indent4" : "indent1";
- let levelMark = (depth: number) => {
- let p10 = schema.marks.pFontSize.create({ fontSize: 10 });
- let p14 = schema.marks.pFontSize.create({ fontSize: 14 });
- let p18 = schema.marks.pFontSize.create({ fontSize: 18 });
- let p24 = schema.marks.pFontSize.create({ fontSize: 24 });
- return depth == 0 ? p24 : depth == 2 ? p18 : depth == 4 ? p14 : p10;
- }
let bulletFunc = (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
var ref = state.selection;
var range = ref.$from.blockRange(ref.$to);
var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
let depth = range && range.depth ? range.depth : 0;
- let nodeType = depth == 2 ? schema.nodes.cap_alphabet_list : depth == 4 ? schema.nodes.roman_list : depth == 6 ? schema.nodes.alphabet_list : schema.nodes.ordered_list;
- let nodeTypeMark = depth == 2 ? schema.marks.mcap_alphabet_list : depth == 4 ? schema.marks.mroman_list : depth == 6 ? schema.marks.malphabet_list : schema.marks.mordered_list;
- let created = levelMark(depth);
- if (!sinkListItem(nodeType /*schema.nodes.list_item */)(state, (tx2: Transaction) => {
+ if (!sinkListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
const resolvedPos = tx2.doc.resolve(range!.start);
- let ns = new NodeSelection(resolvedPos);
- let tx3 = tx2.addMark(ns.from - 1, ns.to, created).addMark(ns.from - 1, ns.to, nodeTypeMark as any).setSelection(TextSelection.create(tx2.doc, ns.to - (depth == 0 ? 3 : 1)));
- marks && tx3.ensureMarks([...marks, created]);
- marks && tx3.setStoredMarks([...marks, created]);
-
- dispatch(tx3);
+ let path = (resolvedPos as any).path;
+ for (let i = path.length - 1; i > 0; i--) {
+ if (path[i].type === schema.nodes.ordered_list) {
+ path[i].attrs.bulletStyle = nodeTypeMark(depth);
+ break;
+ }
+ }
+ marks && tx2.ensureMarks([...marks]);
+ marks && tx2.setStoredMarks([...marks]);
+ dispatch(tx2);
})) {
let sxf = state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end));
let newstate = state.applyTransaction(sxf);
- if (!wrapInList(nodeType)(newstate.state, (tx2: Transaction) => {
- const resolvedPos = tx2.doc.resolve(range!.start);
- let ns = new TextSelection(resolvedPos, tx2.doc.resolve(range!.end + 1)); // new NodeSelection(resolvedPos);
- let tx3 = tx2.setSelection(ns).removeMark(ns.from, ns.to, created).addMark(ns.from, ns.to, created).setSelection(TextSelection.create(tx2.doc, ns.to));
- let tx4 = depth > 0 ? tx3.insertText(" ").setSelection(TextSelection.create(tx2.doc, ns.to - 2, ns.to + 2)).deleteSelection() : tx3;
- marks && tx4.ensureMarks([...marks, created]);
- marks && tx4.setStoredMarks([...marks, created]);
-
- dispatch(tx4);
+ if (!wrapInList(schema.nodes.ordered_list)(newstate.state, (tx2: Transaction) => {
+ const resolvedPos = tx2.doc.resolve(Math.round((range!.start + range!.end) / 2));
+ let path = (resolvedPos as any).path;
+ for (let i = path.length - 1; i > 0; i--) {
+ if (path[i].type === schema.nodes.ordered_list) {
+ path[i].attrs.bulletStyle = nodeTypeMark(depth);
+ break;
+ }
+ }
+ // when promoting to a list, assume list will format things so don't copy the stored marks.
+ // marks && tx2.ensureMarks([...marks]);
+ // marks && tx2.setStoredMarks([...marks]);
+
+ dispatch(tx2);
})) {
console.log("bullet fail");
}
}
- }
- bind("Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => bulletFunc(state, dispatch));
+ };
+
+ bind("Tab", bulletFunc);
bind("Shift-Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
var ref = state.selection;
var range = ref.$from.blockRange(ref.$to);
var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
- let created = levelMark(range && range.depth ? range.depth - 4 : 0);
+ let depth = range && range.depth > 3 ? range.depth - 4 : 0;
liftListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
try {
const resolvedPos = tx2.doc.resolve(Math.round((range!.start + range!.end) / 2));
- let nodeIndex = resolvedPos.pos - (resolvedPos.nodeBefore && resolvedPos.nodeBefore.type.name === "text" ? resolvedPos.nodeBefore!.nodeSize : 0);
- let ns = new NodeSelection(tx2.doc.resolve(nodeIndex));
- if (resolvedPos.nodeAfter && resolvedPos.nodeAfter.type.name === "list_item")
- ns = new NodeSelection(tx2.doc.resolve(nodeIndex + 1));
- let tx3 = tx2.setSelection(ns).removeMark(ns.from, ns.to, created).addMark(ns.from, ns.to, created).setSelection(TextSelection.create(tx2.doc, ns.to));
- marks && tx3.ensureMarks([...marks, created]);
- marks && tx3.setStoredMarks([...marks, created]);
- dispatch(tx3);
+
+ let path = (resolvedPos as any).path;
+ for (let i = path.length - 1; i > 0; i--) {
+ if (path[i].type === schema.nodes.ordered_list) {
+ path[i].attrs.bulletStyle = nodeTypeMark(depth);
+ break;
+ }
+ }
+
+ marks && tx2.ensureMarks([...marks]);
+ marks && tx2.setStoredMarks([...marks]);
+ dispatch(tx2);
} catch (e) {
dispatch(tx2);
}
@@ -155,7 +160,8 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
if (!splitBlockKeepMarks(state, (tx3: Transaction) => {
marks && tx3.ensureMarks(marks);
marks && tx3.setStoredMarks(marks);
- if (!liftListItem(schema.nodes.list_item)(state, (tx4: Transaction) => dispatch(tx4))) {
+ if (!liftListItem(schema.nodes.list_item)(state, dispatch as ((tx: Transaction<Schema<any, any>>) => void))
+ ) {
dispatch(tx3);
}
})) {
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index f128162c2..a642ee46c 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -1,6 +1,7 @@
import { DOMOutputSpecArray, MarkSpec, Node, NodeSpec, Schema, Slice } from "prosemirror-model";
import { bulletList, listItem, orderedList } from 'prosemirror-schema-list';
import { TextSelection } from "prosemirror-state";
+import { Doc } from "../../new_fields/Doc";
const pDOM: DOMOutputSpecArray = ["p", 0], blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"],
preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0];
@@ -175,43 +176,17 @@ export const nodes: { [index: string]: NodeSpec } = {
content: 'list_item+',
group: 'block',
attrs: {
- bulletStyle: { default: "decimal" },
+ bulletStyle: { default: "" },
+ mapStyle: { default: "decimal" }
},
toDOM(node: Node<any>) {
- return ['ol', { style: `list-style: ${node.attrs.bulletStyle}` }, 0]
- }
- },
- alphabet_list: {
- ...orderedList,
- content: 'list_item+',
- group: 'block',
- attrs: {
- bulletStyle: { default: "lower-alpha" },
- },
- toDOM(node: Node<any>) {
- return ['ol', { style: `list-style: ${node.attrs.bulletStyle}` }, 0]
- }
- },
- cap_alphabet_list: {
- ...orderedList,
- content: 'list_item+',
- group: 'block',
- attrs: {
- bulletStyle: { default: "upper-alpha" },
- },
- toDOM(node: Node<any>) {
- return ['ol', { style: `list-style: ${node.attrs.bulletStyle}` }, 0]
- }
- },
- roman_list: {
- ...orderedList,
- content: 'list_item+',
- group: 'block',
- attrs: {
- bulletStyle: { default: "lower-roman" },
- },
- toDOM(node: Node<any>) {
- return ['ol', { style: `list-style: ${node.attrs.bulletStyle}` }, 0]
+ const bs = node.attrs.bulletStyle;
+ const decMap = bs === "indent1" ? "decimal" : bs === "indent2" ? "decimal2" : bs === "indent3" ? "decimal3" : bs === "indent4" ? "decimal4" : "";
+ const multiMap = bs === "indent1" ? "decimal" : bs === "indent2" ? "upper-alpha" : bs === "indent3" ? "lower-roman" : bs === "indent4" ? "lower-alpha" : "";
+ let map = node.attrs.mapStyle === "decimal" ? decMap : multiMap;
+ for (let i = 0; i < node.childCount; i++) node.child(i).attrs.className = map;
+ return ['ol', { class: `${map}-ol`, style: `list-style: none;` }, 0];
+ //return ['ol', { class: `${node.attrs.bulletStyle}`, style: `list-style: ${node.attrs.bulletStyle};`, 0]
}
},
//this doesn't currently work for some reason
@@ -220,9 +195,10 @@ export const nodes: { [index: string]: NodeSpec } = {
content: 'list_item+',
group: 'block',
// parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }],
- // toDOM() { return ['ol', {
- // style: 'list-type: hebrew'
- // }] }
+ toDOM(node: Node<any>) {
+ for (let i = 0; i < node.childCount; i++) node.child(i).attrs.className = "";
+ return ['ul', 0];
+ }
},
//bullet_list: {
@@ -234,8 +210,14 @@ export const nodes: { [index: string]: NodeSpec } = {
//select: state => true,
// },
list_item: {
+ attrs: {
+ className: { default: "" }
+ },
...listItem,
- content: 'paragraph block*'
+ content: 'paragraph block*',
+ toDOM(node: any) {
+ return ["li", { class: node.attrs.className }, 0];
+ }
},
};
@@ -267,7 +249,7 @@ export const marks: { [index: string]: MarkSpec } = {
// :: MarkSpec An emphasis mark. Rendered as an `<em>` element.
// Has parse rules that also match `<i>` and `font-style: italic`.
em: {
- parseDOM: [{ tag: "i" }, { tag: "em" }, { style: "font-style=italic" }],
+ parseDOM: [{ tag: "i" }, { tag: "em" }, { style: "font-style: italic" }],
toDOM() { return emDOM; }
},
@@ -319,13 +301,15 @@ export const marks: { [index: string]: MarkSpec } = {
toDOM: () => ['sup']
},
- malphabet_list: {
- },
- mcap_alphabet_list: {
- },
- mroman_list: {
- },
- mo_list: {
+ mbulletType: {
+ attrs: {
+ bulletType: { default: "decimal" }
+ },
+ toDOM(node: any) {
+ return ['span', {
+ style: `background: ${node.attrs.bulletType === "decimal" ? "yellow" : node.attrs.bulletType === "upper-alpha" ? "blue" : "green"}`
+ }];
+ }
},
highlight: {
@@ -346,6 +330,28 @@ export const marks: { [index: string]: MarkSpec } = {
}
},
+ // the id of the user who entered the text
+ user_mark: {
+ attrs: {
+ userid: { default: "" },
+ hide_users: { default: [] },
+ opened: { default: true },
+ modified: { default: "when?" }
+ },
+ group: "inline",
+ inclusive: false,
+ toDOM(node: any) {
+ let hideUsers = node.attrs.hide_users;
+ let hidden = hideUsers.indexOf(node.attrs.userid) !== -1 || (hideUsers.length === 0 && node.attrs.userid !== Doc.CurrentUserEmail);
+ return hidden ?
+ (node.attrs.opened ?
+ ['span', { class: "userMarkOpen" }, 0] :
+ ['span', { class: "userMark" }, ['span', { style: "font-size:2" }, 0]]
+ ) :
+ ['span', 0];
+ }
+ },
+
// :: MarkSpec Code font mark. Represented as a `<code>` element.
code: {
@@ -599,6 +605,8 @@ export class SummarizedView {
attrs.textslice = newSelection.content().toJSON();
view.dispatch(view.state.tr.setNodeMarkup(y, undefined, attrs));
view.dispatch(view.state.tr.setSelection(newSelection).deleteSelection(view.state, () => { }));
+ let marks = view.state.storedMarks.filter((m: any) => m.type !== view.state.schema.marks.highlight);
+ view.state.storedMarks = marks;
self._collapsed.textContent = "㊉";
} else {
// node.attrs.visibility = !node.attrs.visibility;
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 77396c829..e979e6cde 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -28,11 +28,11 @@ export class TooltipTextMenu {
private view: EditorView;
private fontStyles: MarkType[];
private fontSizes: MarkType[];
- private listTypes: NodeType[];
+ private listTypes: (NodeType | any)[];
private editorProps: FieldViewProps & FormattedTextBoxProps;
private fontSizeToNum: Map<MarkType, number>;
private fontStylesToName: Map<MarkType, string>;
- private listTypeToIcon: Map<NodeType, string>;
+ private listTypeToIcon: Map<NodeType | any, string>;
//private link: HTMLAnchorElement;
private wrapper: HTMLDivElement;
private extras: HTMLDivElement;
@@ -179,10 +179,8 @@ export class TooltipTextMenu {
//list types
this.listTypeToIcon = new Map();
this.listTypeToIcon.set(schema.nodes.bullet_list, ":");
- this.listTypeToIcon.set(schema.nodes.ordered_list, "1)");
- this.listTypeToIcon.set(schema.nodes.alphabet_list, "a)");
- this.listTypeToIcon.set(schema.nodes.cap_alphabet_list, "A)");
- this.listTypeToIcon.set(schema.nodes.roman_list, "i.");
+ this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "decimal" }), "1.1");
+ this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "multi" }), "1.A");
// this.listTypeToIcon.set(schema.nodes.bullet_list, "⬜");
this.listTypes = Array.from(this.listTypeToIcon.keys());
@@ -515,10 +513,28 @@ export class TooltipTextMenu {
//remove all node typeand apply the passed-in one to the selected text
changeToNodeType(nodeType: NodeType | undefined, view: EditorView) {
- //remove old
- liftListItem(schema.nodes.list_item)(view.state, view.dispatch);
- if (nodeType) { //add new
+ //remove oldif (nodeType) { //add new
+ if (nodeType === schema.nodes.bullet_list) {
wrapInList(nodeType)(view.state, view.dispatch);
+ } else {
+ var ref = view.state.selection;
+ var range = ref.$from.blockRange(ref.$to);
+ var marks = view.state.storedMarks || (view.state.selection.$to.parentOffset && view.state.selection.$from.marks());
+ wrapInList(schema.nodes.ordered_list)(view.state, (tx2: any) => {
+ const resolvedPos = tx2.doc.resolve(Math.round((range!.start + range!.end) / 2));
+ let path = resolvedPos.path;
+ for (let i = path.length - 1; i > 0; i--) {
+ if (path[i].type === schema.nodes.ordered_list) {
+ path[i].attrs.bulletStyle = "indent1";
+ path[i].attrs.mapStyle = (nodeType as any).attrs.mapStyle;
+ break;
+ }
+ }
+ marks && tx2.ensureMarks([...marks]);
+ marks && tx2.setStoredMarks([...marks]);
+
+ view.dispatch(tx2);
+ });
}
}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 371b76823..700a4b49d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -200,14 +200,22 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
this.onBackgroundUp(e);
}
+ @observable _forceUpdate = 0;
+ _lastBox = { x: 0, y: 0, r: 0, b: 0 };
@computed
get Bounds(): { x: number, y: number, b: number, r: number } {
- return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
+ let x = this._forceUpdate;
+ this._lastBox = SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
if (documentView.props.renderDepth === 0 ||
Doc.AreProtosEqual(documentView.props.Document, CurrentUserUtils.UserDocument)) {
return bounds;
}
let transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse();
+ if (transform.TranslateX === 0 && transform.TranslateY === 0) {
+ setTimeout(action(() => this._forceUpdate++), 0); // bcz: fix CollectionStackingView's getTransform() somehow...
+ return this._lastBox;
+ }
+
var [sptX, sptY] = transform.transformPoint(0, 0);
let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight());
return {
@@ -215,6 +223,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
};
}, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE });
+ return this._lastBox;
}
onBackgroundDown = (e: React.PointerEvent): void => {
@@ -822,11 +831,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
let templates: Map<Template, boolean> = new Map();
Array.from(Object.values(Templates.TemplateList)).map(template => {
- let sorted = SelectionManager.ViewsSortedVertically(); // slice().sort((doc1, doc2) => {
- // if (NumCast(doc1.props.Document.y) > NumCast(doc2.props.Document.x)) return 1;
- // if (NumCast(doc1.props.Document.x) < NumCast(doc2.props.Document.x)) return -1;
- // return 0;
- // });
+ let sorted = SelectionManager.ViewsSortedVertically();
let docTemps = sorted.reduce((res: string[], doc: DocumentView, i) => {
let temps = doc.props.Document.templates;
if (temps instanceof List) {
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index e95e5b777..755e5de14 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -2,7 +2,7 @@ import { action, observable, reaction, trace } from 'mobx';
import { observer } from 'mobx-react';
import "normalize.css";
import * as React from 'react';
-import { Doc } from '../../new_fields/Doc';
+import { Doc, DocListCast } from '../../new_fields/Doc';
import { BoolCast } from '../../new_fields/Types';
import { emptyFunction, returnTrue, returnZero, Utils, returnOne } from '../../Utils';
import { DragManager } from '../util/DragManager';
@@ -42,13 +42,17 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
return this._textBox && this._textBox.setFontColor(color);
}
-
constructor(props: MainOverlayTextBoxProps) {
super(props);
this._textProxyDiv = React.createRef();
MainOverlayTextBox.Instance = this;
reaction(() => FormattedTextBox.InputBoxOverlay,
(box?: FormattedTextBox) => {
+ const tb = this._textBox;
+ const container = tb && tb.props.ContainingCollectionView;
+ if (tb && container) {
+ tb.rebuildEditor();// this forces the edited text box to completely recreate itself to avoid get out of sync -- e.g., bullet labels are only computed when the dom elements are created
+ }
this._textBox = box;
if (box) {
this.ChromeHeight = box.props.ChromeHeight;
@@ -146,7 +150,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
DataDoc={FormattedTextBox.InputBoxOverlay.props.DataDoc}
onClick={undefined}
ChromeHeight={this.ChromeHeight}
- isSelected={returnTrue} select={emptyFunction} renderDepth={0} selectOnLoad={true}
+ isSelected={returnTrue} select={emptyFunction} renderDepth={0}
ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} ContentScaling={returnOne}
ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction}
pinToPres={returnZero} addDocTab={this.addDocTab} outer_div={(tooltip: HTMLElement) => { this._tooltip = tooltip; this.updateTooltip(); }} />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 20fc1dce8..1fc8d1397 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -329,7 +329,6 @@ export class MainView extends React.Component {
PanelHeight={this.getPHeight}
renderDepth={0}
backgroundColor={returnEmptyString}
- selectOnLoad={false}
focus={emptyFunction}
parentActive={returnTrue}
whenActiveChanged={emptyFunction}
@@ -392,7 +391,6 @@ export class MainView extends React.Component {
PanelWidth={this.flyoutWidthFunc}
PanelHeight={this.getPHeight}
renderDepth={0}
- selectOnLoad={false}
focus={emptyFunction}
backgroundColor={returnEmptyString}
parentActive={returnTrue}
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index bc02a49c6..a1afe651c 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -184,7 +184,6 @@ export class OverlayView extends React.Component {
PanelHeight={returnOne}
ScreenToLocalTransform={Transform.Identity}
renderDepth={1}
- selectOnLoad={false}
parentActive={returnTrue}
whenActiveChanged={emptyFunction}
focus={emptyFunction}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index dc0cbda0b..95f94875c 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -636,7 +636,6 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
PanelHeight={this.panelHeight}
ScreenToLocalTransform={this.ScreenToLocalTransform}
renderDepth={0}
- selectOnLoad={false}
parentActive={returnTrue}
whenActiveChanged={emptyFunction}
focus={emptyFunction}
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 551b485e7..9c26a08f0 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -153,7 +153,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
isSelected: returnFalse,
select: emptyFunction,
renderDepth: this.props.renderDepth + 1,
- selectOnLoad: false,
ScreenToLocalTransform: Transform.Identity,
focus: emptyFunction,
active: returnFalse,
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4008dea51..9d83aa6c1 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1006,7 +1006,6 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
parentActive={this.props.active}
ScreenToLocalTransform={this.getTransform}
renderDepth={this.props.renderDepth + 1}
- selectOnLoad={false}
ContentScaling={this.contentScaling}
PanelWidth={this.PanelWidth}
PanelHeight={this.PanelHeight}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 6f22f2d2a..97b31bf2a 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -278,7 +278,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
}
getDocTransform(doc: Doc, dref: HTMLDivElement) {
- let y = this._scroll;
+ if (!dref) return Transform.Identity();
+ let y = this._scroll; // required for document decorations to update when the text box container is scrolled
let { scale, translateX, translateY } = Utils.GetScreenTransform(dref);
let outerXf = Utils.GetScreenTransform(this._masonryGridRef!);
let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index f30e99362..bc4fe7dd7 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -2,7 +2,7 @@ import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
import { faPalette } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, observable } from "mobx";
+import { action, observable, trace } from "mobx";
import { observer } from "mobx-react";
import { Doc, WidthSym } from "../../../new_fields/Doc";
import { Id } from "../../../new_fields/FieldSymbols";
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 04133fb5b..50f03005c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -432,26 +432,28 @@ class TreeView extends React.Component<TreeViewProps> {
}
let ascending = Cast(containingCollection.sortAscending, "boolean", null);
- if (ascending !== undefined) docs.sort(function (a, b): 1 | -1 {
- let descA = ascending ? b : a;
- let descB = ascending ? a : b;
- let first = descA.title;
- let second = descB.title;
- // TODO find better way to sort how to sort..................
- if (typeof first === 'number' && typeof second === 'number') {
- return (first - second) > 0 ? 1 : -1;
- }
- if (typeof first === 'string' && typeof second === 'string') {
- return first > second ? 1 : -1;
- }
- if (typeof first === 'boolean' && typeof second === 'boolean') {
- // if (first === second) { // bugfixing?: otherwise, the list "flickers" because the list is resorted during every load
- // return Number(descA.x) > Number(descB.x) ? 1 : -1;
- // }
- return first > second ? 1 : -1;
- }
- return ascending ? 1 : -1;
- });
+ if (ascending !== undefined) {
+ docs.sort(function (a, b): 1 | -1 {
+ let descA = ascending ? b : a;
+ let descB = ascending ? a : b;
+ let first = descA.title;
+ let second = descB.title;
+ // TODO find better way to sort how to sort..................
+ if (typeof first === 'number' && typeof second === 'number') {
+ return (first - second) > 0 ? 1 : -1;
+ }
+ if (typeof first === 'string' && typeof second === 'string') {
+ return first > second ? 1 : -1;
+ }
+ if (typeof first === 'boolean' && typeof second === 'boolean') {
+ // if (first === second) { // bugfixing?: otherwise, the list "flickers" because the list is resorted during every load
+ // return Number(descA.x) > Number(descB.x) ? 1 : -1;
+ // }
+ return first > second ? 1 : -1;
+ }
+ return ascending ? 1 : -1;
+ });
+ }
let rowWidth = () => panelWidth() - 20;
return docs.map((child, i) => {
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index b2df0e747..c897af17e 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -42,16 +42,18 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
_templateCommand = {
title: "set template", script: "this.target.childLayout = this.source ? this.source[0] : undefined", params: ["target", "source"],
+ initialize: emptyFunction,
immediate: (draggedDocs: Doc[]) => this.props.CollectionView.props.Document.childLayout = draggedDocs.length ? draggedDocs[0] : undefined
};
_contentCommand = {
// title: "set content", script: "getProto(this.target).data = aliasDocs(this.source.map(async p => await p));", params: ["target", "source"], // bcz: doesn't look like we can do async stuff in scripting...
title: "set content", script: "getProto(this.target).data = aliasDocs(this.source);", params: ["target", "source"],
+ initialize: emptyFunction,
immediate: (draggedDocs: Doc[]) => Doc.GetProto(this.props.CollectionView.props.Document).data = new List<Doc>(draggedDocs.map((d: any) => Doc.MakeAlias(d)))
};
_viewCommand = {
title: "restore view", script: "this.target.panX = this.restoredPanX; this.target.panY = this.restoredPanY; this.target.scale = this.restoredScale;", params: ["target"],
- immediate: (draggedDocs: Doc[]) => { this.props.CollectionView.props.Document.panX = 0; this.props.CollectionView.props.Document.panY = 0; this.props.CollectionView.props.Document.scale = 1 },
+ immediate: (draggedDocs: Doc[]) => { this.props.CollectionView.props.Document.panX = 0; this.props.CollectionView.props.Document.panY = 0; this.props.CollectionView.props.Document.scale = 1; },
initialize: (button: Doc) => { button.restoredPanX = this.props.CollectionView.props.Document.panX; button.restoredPanY = this.props.CollectionView.props.Document.panY; button.restoredScale = this.props.CollectionView.props.Document.scale; }
};
_freeform_commands = [this._contentCommand, this._templateCommand, this._viewCommand];
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f185222ce..a7acd9e91 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,7 +1,7 @@
import { library } from "@fortawesome/fontawesome-svg-core";
import { faEye } from "@fortawesome/free-regular-svg-icons";
import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
-import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, trace } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCastAsync, Field, FieldResult, HeightSym, Opt, WidthSym } from "../../../../new_fields/Doc";
import { Id } from "../../../../new_fields/FieldSymbols";
@@ -38,6 +38,7 @@ import "./CollectionFreeFormView.scss";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
import { DocServer } from "../../../DocServer";
+import { FormattedTextBox } from "../../nodes/FormattedTextBox";
library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard);
@@ -165,8 +166,6 @@ export namespace PivotView {
return prev;
}, elements);
- target.resetSelectOnLoaded();
-
return docViews;
};
@@ -177,25 +176,35 @@ const PanZoomDocument = makeInterface(panZoomSchema, positionSchema, pageSchema)
@observer
export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
- private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type)
private _lastX: number = 0;
private _lastY: number = 0;
private get _pwidth() { return this.props.PanelWidth(); }
private get _pheight() { return this.props.PanelHeight(); }
private inkKey = "ink";
private _childLayoutDisposer?: IReactionDisposer;
+ private _childDisposer?: IReactionDisposer;
componentDidMount() {
- this._childLayoutDisposer = reaction(() => [this.childDocs, Cast(this.props.Document.childLayout, Doc)],
- async (args) => {
- this.childDocs.filter(doc => args[1] instanceof Doc || doc.layout instanceof Doc).map(async doc => {
- if (!Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc)) {
- Doc.ApplyTemplateTo(args[1] as Doc, (await doc), undefined);
+ this._childDisposer = reaction(() => this.childDocs,
+ async (childDocs) => {
+ let childLayout = Cast(this.props.Document.childLayout, Doc) as Doc;
+ childLayout && childDocs.map(async doc => {
+ if (!Doc.AreProtosEqual(childLayout, (await doc).layout as Doc)) {
+ Doc.ApplyTemplateTo(childLayout, doc, undefined);
+ }
+ });
+ });
+ this._childLayoutDisposer = reaction(() => Cast(this.props.Document.childLayout, Doc),
+ async (childLayout) => {
+ this.childDocs.map(async doc => {
+ if (!Doc.AreProtosEqual(childLayout as Doc, (await doc).layout as Doc)) {
+ Doc.ApplyTemplateTo(childLayout as Doc, doc, undefined);
}
});
});
}
componentWillUnmount() {
+ this._childDisposer && this._childDisposer();
this._childLayoutDisposer && this._childLayoutDisposer();
}
@@ -241,7 +250,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY());
private addLiveTextBox = (newBox: Doc) => {
- this._selectOnLoaded = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
+ FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
this.addDocument(newBox, false);
}
private addDocument = (newBox: Doc, allowDuplicates: boolean) => {
@@ -642,7 +651,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
onClick: this.props.onClick,
ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform,
renderDepth: this.props.renderDepth + 1,
- selectOnLoad: childLayout[Id] === this._selectOnLoaded,
PanelWidth: childLayout[WidthSym],
PanelHeight: childLayout[HeightSym],
ContentScaling: returnOne,
@@ -668,7 +676,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
onClick: this.props.onClick,
ScreenToLocalTransform: this.getTransform,
renderDepth: this.props.renderDepth,
- selectOnLoad: layoutDoc[Id] === this._selectOnLoaded,
PanelWidth: layoutDoc[WidthSym],
PanelHeight: layoutDoc[HeightSym],
ContentScaling: returnOne,
@@ -768,13 +775,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
return prev;
}, elements);
- this.resetSelectOnLoaded();
-
return docviews;
}
- resetSelectOnLoaded = () => setTimeout(() => this._selectOnLoaded = "", 600);// bcz: surely there must be a better way ....
-
@computed.struct
get views() {
let source = this.elements;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f682c3d22..b60730a6b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -92,7 +92,6 @@ export interface DocumentViewProps {
PanelWidth: () => number;
PanelHeight: () => number;
focus: (doc: Doc, willZoom: boolean, scale?: number) => void;
- selectOnLoad: boolean;
parentActive: () => boolean;
whenActiveChanged: (isActive: boolean) => void;
bringToFront: (doc: Doc, sendToBack?: boolean) => void;
@@ -601,7 +600,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
this.makeBtnClicked();
}, icon: "window-restore"
});
- makes.push({ description: this.props.Document.ignoreClick ? "Selectable" : "Unselectable", event: () => this.props.Document.ignoreClick = !this.props.Document.ignoreClick, icon: this.props.Document.ignoreClick ? "unlock" : "lock" })
+ makes.push({ description: this.props.Document.ignoreClick ? "Selectable" : "Unselectable", event: () => this.props.Document.ignoreClick = !this.props.Document.ignoreClick, icon: this.props.Document.ignoreClick ? "unlock" : "lock" });
!existingMake && cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" });
let existing = ContextMenu.Instance.findByDescription("Layout...");
let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : [];
@@ -717,7 +716,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
isSelected={this.isSelected}
select={this.select}
onClick={this.onClickHandler}
- selectOnLoad={this.props.selectOnLoad}
layoutKey={"layout"}
fitToBox={BoolCast(this.props.Document.fitToBox) ? true : this.props.fitToBox}
DataDoc={this.dataDoc} />);
@@ -810,7 +808,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
{!showCaption ? (null) :
<div style={{ position: "absolute", bottom: 0, transformOrigin: "bottom left", width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})` }}>
- <FormattedTextBox {...this.props} onClick={this.onClickHandler} DataDoc={this.dataDoc} active={returnTrue} isSelected={this.isSelected} focus={emptyFunction} select={this.select} selectOnLoad={this.props.selectOnLoad} fieldExt={""} hideOnLeave={true} fieldKey={showCaption} />
+ <FormattedTextBox {...this.props} onClick={this.onClickHandler} DataDoc={this.dataDoc} active={returnTrue} isSelected={this.isSelected} focus={emptyFunction} select={this.select} fieldExt={""} hideOnLeave={true} fieldKey={showCaption} />
</div>
}
</div>
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index f0f1b3b73..d9774303b 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -36,7 +36,6 @@ export interface FieldViewProps {
isSelected: () => boolean;
select: (isCtrlPressed: boolean) => void;
renderDepth: number;
- selectOnLoad: boolean;
addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean;
addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
pinToPres: (document: Doc) => void;
@@ -108,7 +107,6 @@ export class FieldView extends React.Component<FieldViewProps> {
// PanelWidth={returnHundred}
// PanelHeight={returnHundred}
// renderDepth={0} //TODO Why is renderDepth reset?
- // selectOnLoad={false}
// focus={emptyFunction}
// isSelected={this.props.isSelected}
// select={returnFalse}
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 1b537cc52..03e81bfca 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -65,4 +65,37 @@
.em {
font-style: italic;
-} \ No newline at end of file
+}
+
+.userMarkOpen {
+ background: rgba(255, 255, 0, 0.267);
+ display: inline;
+}
+.userMark {
+ background: rgba(255, 255, 0, 0.267);
+ font-size: 2px;
+ display: inline-grid;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ width:10px;
+ min-height:10px;
+ text-align:center;
+ align-content: center;
+}
+
+ol { counter-reset: deci 0;}
+.decimal-ol { counter-reset: deci 0; p { display: inline }; font-size: 24 }
+.decimal2-ol {counter-reset: deci2; p { display: inline }; font-size: 18 }
+.decimal3-ol {counter-reset: deci3; p { display: inline }; font-size: 14 }
+.decimal4-ol {counter-reset: deci4; p { display: inline }; font-size: 10 }
+.upper-alpha-ol {counter-reset: ualph; p { display: inline }; font-size: 18 }
+.lower-roman-ol {counter-reset: lroman; p { display: inline }; font-size: 14; }
+.lower-alpha-ol {counter-reset: lalpha; p { display: inline }; font-size: 10;}
+.decimal:before { content: counter(deci) " "; counter-increment: deci; display:inline-block; width: 30}
+.decimal2:before { content: counter(deci) "." counter(deci2) " "; counter-increment: deci2; display:inline-block; width: 35}
+.decimal3:before { content: counter(deci) "." counter(deci2) "." counter(deci3) " "; counter-increment: deci3; display:inline-block; width: 35}
+.decimal4:before { content: counter(deci) "." counter(deci2) "." counter(deci3) "." counter(deci4) " "; counter-increment: deci4; display:inline-block; width: 40}
+.upper-alpha:before { content: counter(deci) "." counter(ualph, upper-alpha) " "; counter-increment: ualph; display:inline-block; width: 35 }
+.lower-roman:before { content: counter(deci) "." counter(ualph, upper-alpha) "." counter(lroman, lower-roman) " "; counter-increment: lroman;display:inline-block; width: 50 }
+.lower-alpha:before { content: counter(deci) "." counter(ualph, upper-alpha) "." counter(lroman, lower-roman) "." counter(lalpha, lower-alpha)" "; counter-increment: lalpha; display:inline-block; width: 35}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index acfd2a3b8..0d4376d8d 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -5,8 +5,8 @@ import { observer } from "mobx-react";
import { baseKeymap } from "prosemirror-commands";
import { history } from "prosemirror-history";
import { keymap } from "prosemirror-keymap";
-import { Fragment, Node, Node as ProsNode, NodeType, Slice } from "prosemirror-model";
-import { EditorState, Plugin, Transaction, TextSelection } from "prosemirror-state";
+import { Fragment, Node, Node as ProsNode, NodeType, Slice, Mark, ResolvedPos } from "prosemirror-model";
+import { EditorState, Plugin, Transaction, TextSelection, NodeSelection } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { DateField } from '../../../new_fields/DateField';
import { Doc, DocListCast, Opt, WidthSym } from "../../../new_fields/Doc";
@@ -15,7 +15,7 @@ import { List } from '../../../new_fields/List';
import { RichTextField, ToPlainText, FromPlainText } from "../../../new_fields/RichTextField";
import { BoolCast, Cast, NumCast, StrCast, DateCast } from "../../../new_fields/Types";
import { createSchema, makeInterface } from "../../../new_fields/Schema";
-import { Utils } from '../../../Utils';
+import { Utils, numberRange } from '../../../Utils';
import { DocServer } from "../../DocServer";
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
@@ -37,6 +37,8 @@ import { DocumentDecorations } from '../DocumentDecorations';
import { DictationManager } from '../../util/DictationManager';
import { ReplaceStep } from 'prosemirror-transform';
import { DocumentType } from '../../documents/DocumentTypes';
+import { selectionSizePlugin, findStartOfMark, findUserMark, findEndOfMark, findOtherUserMark, SelectionSizeTooltip } from './FormattedTextBoxComment';
+import { date } from 'serializr';
library.add(faEdit);
library.add(faSmile, faTextHeight, faUpload);
@@ -68,25 +70,25 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
public static LayoutString(fieldStr: string = "data") {
return FieldView.LayoutString(FormattedTextBox, fieldStr);
}
- public static Instance: FormattedTextBox;
- private _ref: React.RefObject<HTMLDivElement>;
+ private static _toolTipTextMenu: TooltipTextMenu | undefined = undefined;
+ private _ref: React.RefObject<HTMLDivElement> = React.createRef();
private _proseRef?: HTMLDivElement;
private _editorView: Opt<EditorView>;
- private static _toolTipTextMenu: TooltipTextMenu | undefined = undefined;
private _applyingChange: boolean = false;
private _linkClicked = "";
+ private _undoTyping?: UndoManager.Batch;
private _reactionDisposer: Opt<IReactionDisposer>;
private _searchReactionDisposer?: Lambda;
private _textReactionDisposer: Opt<IReactionDisposer>;
private _heightReactionDisposer: Opt<IReactionDisposer>;
private _proxyReactionDisposer: Opt<IReactionDisposer>;
- private pullReactionDisposer: Opt<IReactionDisposer>;
- private pushReactionDisposer: Opt<IReactionDisposer>;
+ private _pullReactionDisposer: Opt<IReactionDisposer>;
+ private _pushReactionDisposer: Opt<IReactionDisposer>;
private dropDisposer?: DragManager.DragDropDisposer;
- public get CurrentDiv(): HTMLDivElement { return this._ref.current!; }
- @observable _entered = false;
+ @observable private _entered = false;
@observable public static InputBoxOverlay?: FormattedTextBox = undefined;
+ public static SelectOnLoad = "";
public static InputBoxOverlayScroll: number = 0;
public static IsFragment(html: string) {
return html.indexOf("data-pm-slice") !== -1;
@@ -127,15 +129,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
constructor(props: FieldViewProps) {
super(props);
- FormattedTextBox.Instance = this;
- this._ref = React.createRef();
if (this.props.isOverlay) {
DragManager.StartDragFunctions.push(() => FormattedTextBox.InputBoxOverlay = undefined);
}
-
- document.addEventListener("paste", this.paste);
}
+ public get CurrentDiv(): HTMLDivElement { return this._ref.current!; }
+
@computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.dataDoc, this.props.fieldKey, "dummy"); }
@computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
@@ -235,12 +235,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
protected createDropTarget = (ele: HTMLDivElement) => {
this._proseRef = ele;
- if (this.dropDisposer) {
- this.dropDisposer();
- }
- if (ele) {
- this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
- }
+ this.dropDisposer && this.dropDisposer();
+ ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }));
}
@undoBatch
@@ -264,13 +260,12 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
recordKeyHandler = (e: KeyboardEvent) => {
- if (this.props.Document !== SelectionManager.SelectedDocuments()[0].props.Document) {
- return;
- }
- if (e.key === "R" && e.altKey) {
- e.stopPropagation();
- e.preventDefault();
- this.recordBullet();
+ if (this.props.Document === SelectionManager.SelectedDocuments()[0].props.Document) {
+ if (e.key === "R" && e.altKey) {
+ e.stopPropagation();
+ e.preventDefault();
+ this.recordBullet();
+ }
}
}
@@ -314,15 +309,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
private newListItems = (count: number) => {
- let listItems: any[] = [];
- for (let i = 0; i < count; i++) {
- listItems.push(schema.nodes.list_item.create(undefined, schema.nodes.paragraph.create()));
- }
- return listItems;
+ return numberRange(count).map(x => schema.nodes.list_item.create(undefined, schema.nodes.paragraph.create()));
}
- componentDidMount() {
- const config = {
+ @computed get config() {
+ return {
schema,
inpRules, //these currently don't do anything, but could eventually be helpful
plugins: this.props.isOverlay ? [
@@ -335,13 +326,23 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
props: {
attributes: { class: "ProseMirror-example-setup-style" }
}
- })
+ }),
+ selectionSizePlugin
] : [
history(),
keymap(buildKeymap(schema)),
keymap(baseKeymap),
]
};
+ }
+
+ @action
+ rebuildEditor() {
+ this.setupEditor(this.config, this.dataDoc, this.props.fieldKey);
+ }
+
+ componentDidMount() {
+ document.addEventListener("paste", this.paste);
if (!this.props.isOverlay) {
this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
@@ -364,13 +365,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
incomingValue => {
if (this._editorView && !this._applyingChange) {
let updatedState = JSON.parse(incomingValue);
- this._editorView.updateState(EditorState.fromJSON(config, updatedState));
+ this._editorView.updateState(EditorState.fromJSON(this.config, updatedState));
this.tryUpdateHeight();
}
}
);
- this.pullReactionDisposer = reaction(
+ this._pullReactionDisposer = reaction(
() => this.props.Document[Pulls],
() => {
if (!DocumentDecorations.hasPulledHack) {
@@ -381,7 +382,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
);
- this.pushReactionDisposer = reaction(
+ this._pushReactionDisposer = reaction(
() => this.props.Document[Pushes],
() => {
if (!DocumentDecorations.hasPushedHack) {
@@ -406,7 +407,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
this.dataDoc.lastModified = undefined;
}
}, { fireImmediately: true });
- this.setupEditor(config, this.dataDoc, this.props.fieldKey);
+
+
+ this.setupEditor(this.config, this.dataDoc, this.props.fieldKey);
this._searchReactionDisposer = reaction(() => {
return StrCast(this.props.Document.search_string);
@@ -506,7 +509,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}
-
clipboardTextSerializer = (slice: Slice): string => {
let text = "", separated = true;
const from = 0, to = slice.content.size;
@@ -606,6 +608,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}
if (this._proseRef) {
+ this._editorView && this._editorView.destroy();
this._editorView = new EditorView(this._proseRef, {
state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config),
dispatchTransaction: this.dispatchTransaction,
@@ -622,21 +625,27 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}
- if (this.props.selectOnLoad) {
- if (!this.props.isOverlay) this.props.select(false);
- else this._editorView!.focus();
+ if (this.props.Document[Id] === FormattedTextBox.SelectOnLoad) {
+ FormattedTextBox.SelectOnLoad = "";
+ this.props.select(false);
}
+ else if (this.props.isOverlay) this._editorView!.focus();
+ var markerss = this._editorView!.state.storedMarks || (this._editorView!.state.selection.$to.parentOffset && this._editorView!.state.selection.$from.marks());
+ let newMarks = [...(markerss ? markerss.filter(m => m.type !== schema.marks.user_mark) : []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail })];
+ this._editorView!.state.storedMarks = newMarks;
+
}
componentWillUnmount() {
- this._editorView && this._editorView.destroy();
this._reactionDisposer && this._reactionDisposer();
this._proxyReactionDisposer && this._proxyReactionDisposer();
this._textReactionDisposer && this._textReactionDisposer();
- this.pushReactionDisposer && this.pushReactionDisposer();
- this.pullReactionDisposer && this.pullReactionDisposer();
+ this._pushReactionDisposer && this._pushReactionDisposer();
+ this._pullReactionDisposer && this._pullReactionDisposer();
this._heightReactionDisposer && this._heightReactionDisposer();
this._searchReactionDisposer && this._searchReactionDisposer();
+ document.removeEventListener("paste", this.paste);
+ this._editorView && this._editorView.destroy();
}
onPointerDown = (e: React.PointerEvent): void => {
@@ -700,15 +709,38 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
e.preventDefault();
}
}
+
onPointerUp = (e: React.PointerEvent): void => {
- if (FormattedTextBox._toolTipTextMenu && FormattedTextBox._toolTipTextMenu.tooltip) {
- //this._toolTipTextMenu.tooltip.style.opacity = "1";
+ let view = this._editorView!;
+ const pos = view.posAtCoords({ left: e.clientX, top: e.clientY });
+ const rpos = pos && view.state.doc.resolve(pos.pos);
+ let noselection = view.state.selection.$from === view.state.selection.$to;
+ let set = false;
+ if (pos && rpos) {
+ let nbef = findStartOfMark(rpos, view, findOtherUserMark);
+ let naft = findEndOfMark(rpos, view, findOtherUserMark);
+ const spos = pos.pos - nbef;
+ const epos = pos.pos + naft;
+ let child = rpos.nodeBefore || rpos.nodeAfter;
+ let mark = child && findOtherUserMark(child.marks);
+ if (mark && child && (nbef || naft) && (!mark.attrs.opened || noselection)) {
+ SelectionSizeTooltip.SetState(this, mark.attrs.opened, spos, epos, mark);
+ set = true;
+ }
}
+ !set && SelectionSizeTooltip.Hide();
if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
e.stopPropagation();
}
}
+ setAnnotation = (start: number, end: number, mark: Mark, opened: boolean, keep: boolean = false) => {
+ let view = this._editorView!;
+ let mid = view.state.doc.resolve(Math.round((start + end) / 2));
+ let nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: keep ? Doc.CurrentUserEmail : mark.attrs.userid, opened: opened });
+ view.dispatch(view.state.tr.removeMark(start, end, nmark).addMark(start, end, nmark).setSelection(new TextSelection(mid, mid)));
+ }
+
@action
onFocused = (e: React.FocusEvent): void => {
document.removeEventListener("keypress", this.recordKeyHandler);
@@ -751,7 +783,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
return self._toolTipTextMenu = new TooltipTextMenu(_editorView, myprops);
}
});
- //this.props.Document.tooltip = self._toolTipTextMenu;
}
tooltipLinkingMenuPlugin() {
@@ -769,13 +800,37 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
this._undoTyping = undefined;
}
}
- public _undoTyping?: UndoManager.Batch;
onKeyPress = (e: React.KeyboardEvent) => {
if (e.key === "Escape") {
SelectionManager.DeselectAll();
}
e.stopPropagation();
- if (e.key === "Tab") e.preventDefault();
+ if (e.key === "Tab" || e.key === "Enter") { // bullets typically change "levels" when tab or enter is used. sometimes backspcae, so maybe that should be added.
+ e.preventDefault();
+ setTimeout(() => { // force re-rendering of bullet numbers that may have had their bullet labels change. (Our prosemirrior code re-"marks" the changed bullets, but nothing causes the Dom to be re-rendered which is where the nubering takes place)
+ SelectionManager.DeselectAll();
+ SelectionManager.SelectDoc(DocumentManager.Instance.getDocumentView(this.props.Document, this.props.ContainingCollectionView)!, false);
+ }, 0);
+ }
+ function timenow() {
+ var now = new Date();
+ let ampm = 'am';
+ let h = now.getHours();
+ let m: any = now.getMinutes();
+ let s: any = now.getSeconds();
+ if (h >= 12) {
+ if (h > 12) h -= 12;
+ ampm = 'pm';
+ }
+
+ if (m < 10) m = '0' + m;
+ if (s < 10) s = '0' + s;
+ return now.toLocaleDateString() + ' ' + h + ':' + m + ':' + s + ' ' + ampm;
+ }
+ var markerss = this._editorView!.state.storedMarks || (this._editorView!.state.selection.$to.parentOffset && this._editorView!.state.selection.$from.marks());
+ let newMarks = [...(markerss ? markerss.filter(m => m.type !== schema.marks.user_mark) : []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: timenow() })];
+ this._editorView!.state.storedMarks = newMarks;
+
// stop propagation doesn't seem to stop propagation of native keyboard events.
// so we set a flag on the native event that marks that the event's been handled.
(e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
@@ -802,24 +857,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}
- @action
- onPointerEnter = (e: React.PointerEvent) => {
- this._entered = true;
- }
- @action
- onPointerLeave = (e: React.PointerEvent) => {
- this._entered = false;
- }
-
- specificContextMenu = (e: React.MouseEvent): void => {
- // let subitems: ContextMenuProps[] = [];
- // subitems.push({
- // description: BoolCast(this.props.Document.autoHeight) ? "Manual Height" : "Auto Height",
- // event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight)), icon: "expand-arrows-alt"
- // });
- // ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems, icon: "text-height" });
- }
-
render() {
let self = this;
@@ -842,14 +879,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
onKeyDown={this.onKeyPress}
onFocus={this.onFocused}
onClick={this.onClick}
- onContextMenu={this.specificContextMenu}
onBlur={this.onBlur}
onPointerUp={this.onPointerUp}
onPointerDown={this.onPointerDown}
onMouseDown={this.onMouseDown}
onWheel={this.onPointerWheel}
- onPointerEnter={this.onPointerEnter}
- onPointerLeave={this.onPointerLeave}
+ onPointerEnter={action(() => this._entered = true)}
+ onPointerLeave={action(() => this._entered = false)}
>
<div className={`formattedTextBox-inner${rounded}`} ref={this.createDropTarget} style={{ whiteSpace: "pre-wrap" }} />
</div>
diff --git a/src/client/views/nodes/FormattedTextBoxComment.scss b/src/client/views/nodes/FormattedTextBoxComment.scss
new file mode 100644
index 000000000..792cee182
--- /dev/null
+++ b/src/client/views/nodes/FormattedTextBoxComment.scss
@@ -0,0 +1,34 @@
+.FormattedTextBox-tooltip {
+ position: absolute;
+ pointer-events: none;
+ z-index: 20;
+ background: white;
+ border: 1px solid silver;
+ border-radius: 2px;
+ padding: 2px 10px;
+ margin-bottom: 7px;
+ -webkit-transform: translateX(-50%);
+ transform: translateX(-50%);
+ }
+ .FormattedTextBox-tooltip:before {
+ content: "";
+ height: 0; width: 0;
+ position: absolute;
+ left: 50%;
+ margin-left: -5px;
+ bottom: -6px;
+ border: 5px solid transparent;
+ border-bottom-width: 0;
+ border-top-color: silver;
+ }
+ .FormattedTextBox-tooltip:after {
+ content: "";
+ height: 0; width: 0;
+ position: absolute;
+ left: 50%;
+ margin-left: -5px;
+ bottom: -4.5px;
+ border: 5px solid transparent;
+ border-bottom-width: 0;
+ border-top-color: white;
+ } \ No newline at end of file
diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx
new file mode 100644
index 000000000..9123f8aed
--- /dev/null
+++ b/src/client/views/nodes/FormattedTextBoxComment.tsx
@@ -0,0 +1,110 @@
+import { Plugin, EditorState } from "prosemirror-state"
+import './FormattedTextBoxComment.scss'
+import { ResolvedPos, Mark } from "prosemirror-model";
+import { EditorView } from "prosemirror-view";
+import { Doc } from "../../../new_fields/Doc";
+
+export let selectionSizePlugin = new Plugin({
+ view(editorView) { return new SelectionSizeTooltip(editorView); }
+})
+export function findOtherUserMark(marks: Mark[]): Mark | undefined {
+ return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail);
+}
+export function findUserMark(marks: Mark[]): Mark | undefined {
+ return marks.find(m => m.attrs.userid);
+}
+export function findStartOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: Mark[]) => Mark | undefined) {
+ let before = 0;
+ let nbef = rpos.nodeBefore;
+ while (nbef && finder(nbef.marks)) {
+ before += nbef.nodeSize;
+ rpos = view.state.doc.resolve(rpos.pos - nbef.nodeSize);
+ rpos && (nbef = rpos.nodeBefore);
+ }
+ return before;
+}
+export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: Mark[]) => Mark | undefined) {
+ let after = 0;
+ let naft = rpos.nodeAfter;
+ while (naft && finder(naft.marks)) {
+ after += naft.nodeSize;
+ rpos = view.state.doc.resolve(rpos.pos + naft.nodeSize);
+ rpos && (naft = rpos.nodeAfter);
+ }
+ return after;
+}
+
+
+export class SelectionSizeTooltip {
+ static tooltip: HTMLElement;
+ static tooltipText: HTMLElement;
+ static start: number;
+ static end: number;
+ static mark: Mark;
+ static opened: boolean;
+ static textBox: any;
+ constructor(view: any) {
+ if (!SelectionSizeTooltip.tooltip) {
+ const root = document.getElementById("root");
+ let input = document.createElement("input");
+ input.type = "checkbox";
+ SelectionSizeTooltip.tooltip = document.createElement("div");
+ SelectionSizeTooltip.tooltipText = document.createElement("div");
+ SelectionSizeTooltip.tooltip.appendChild(SelectionSizeTooltip.tooltipText);
+ SelectionSizeTooltip.tooltip.className = "FormattedTextBox-tooltip";
+ SelectionSizeTooltip.tooltip.style.pointerEvents = "all";
+ SelectionSizeTooltip.tooltip.appendChild(input);
+ SelectionSizeTooltip.tooltip.onpointerdown = (e: PointerEvent) => {
+ let keep = e.target && (e.target as any).type === "checkbox";
+ SelectionSizeTooltip.opened = keep || !SelectionSizeTooltip.opened;
+ SelectionSizeTooltip.textBox.setAnnotation(
+ SelectionSizeTooltip.start, SelectionSizeTooltip.end, SelectionSizeTooltip.mark,
+ SelectionSizeTooltip.opened, keep);
+ };
+ root && root.appendChild(SelectionSizeTooltip.tooltip);
+ }
+ this.update(view, undefined);
+ }
+
+ public static Hide() {
+ SelectionSizeTooltip.textBox = undefined;
+ SelectionSizeTooltip.tooltip && (SelectionSizeTooltip.tooltip.style.display = "none");
+ }
+ public static SetState(textBox: any, opened: boolean, start: number, end: number, mark: Mark) {
+ SelectionSizeTooltip.textBox = textBox;
+ SelectionSizeTooltip.start = start;
+ SelectionSizeTooltip.end = end;
+ SelectionSizeTooltip.mark = mark;
+ SelectionSizeTooltip.opened = opened;
+ SelectionSizeTooltip.textBox && SelectionSizeTooltip.tooltip && (SelectionSizeTooltip.tooltip.style.display = "");
+ }
+
+ update(view: EditorView, lastState?: EditorState) {
+ let state = view.state;
+ // Don't do anything if the document/selection didn't change
+ if (lastState && lastState.doc.eq(state.doc) &&
+ lastState.selection.eq(state.selection)) return;
+
+ if (state.selection.$from) {
+ let nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark);
+ let naft = findEndOfMark(state.selection.$from, view, findOtherUserMark);
+ let child = state.selection.$from.nodeBefore;
+ let mark = child && findOtherUserMark(child.marks);
+ if (mark && child && nbef && naft) {
+ SelectionSizeTooltip.tooltipText.textContent = mark.attrs.userid + " " + mark.attrs.modified;
+ // These are in screen coordinates
+ // let start = view.coordsAtPos(state.selection.from), end = view.coordsAtPos(state.selection.to);
+ let start = view.coordsAtPos(state.selection.from - nbef), end = view.coordsAtPos(state.selection.from - nbef);
+ // The box in which the tooltip is positioned, to use as base
+ let box = (document.getElementById("main-div") as any).getBoundingClientRect();
+ // Find a center-ish x position from the selection endpoints (when
+ // crossing lines, end may be more to the left)
+ let left = Math.max((start.left + end.left) / 2, start.left + 3);
+ SelectionSizeTooltip.tooltip.style.left = (left - box.left) + "px";
+ SelectionSizeTooltip.tooltip.style.bottom = (box.bottom - start.top) + "px";
+ }
+ }
+ }
+
+ destroy() { SelectionSizeTooltip.tooltip.style.display = "none" }
+}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 8001b24a7..5afd4d834 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -60,7 +60,6 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
isSelected: returnFalse,
select: emptyFunction,
renderDepth: 1,
- selectOnLoad: false,
active: returnFalse,
whenActiveChanged: emptyFunction,
ScreenToLocalTransform: Transform.Identity,
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 258e218f0..e5917fefc 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -152,12 +152,18 @@ export class PDFViewer extends React.Component<IViewerProps> {
if (this._pageSizes.length === 0) {
this._isPage = Array<string>(this.props.pdf.numPages);
this._pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages);
+ this._visibleElements = Array<JSX.Element>(this.props.pdf.numPages);
await Promise.all(this._pageSizes.map<Pdfjs.PDFPromise<any>>((val, i) =>
this.props.pdf.getPage(i + 1).then(action((page: Pdfjs.PDFPageProxy) => {
this._pageSizes.splice(i, 1, {
width: (page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]) * scale,
height: (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0]) * scale
});
+ this._visibleElements.splice(i, 1,
+ <div key={`${this.props.url}-placeholder-${i + 1}`} className="pdfviewer-placeholder"
+ style={{ width: this._pageSizes[i].width, height: this._pageSizes[i].height }}>
+ "PAGE IS LOADING... "
+ </div>);
this.getPlaceholderPage(i);
}))));
this.props.loaded(Math.max(...this._pageSizes.map(i => i.width)), this._pageSizes[0].height, this.props.pdf.numPages);
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 0de1777e6..8df2dce29 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -64,13 +64,14 @@ export default class Page extends React.Component<IPageProps> {
// lower scale = easier to read at small sizes, higher scale = easier to read at large sizes
if (this._state !== "rendering" && !this._page && this._canvas.current && this._textLayer.current) {
this._state = "rendering";
- let viewport = page.getViewport(scale);
+ let viewport = page.getViewport({ scale: scale });
this._canvas.current.width = this._width = viewport.width;
this._canvas.current.height = this._height = viewport.height;
this.props.pageLoaded(viewport);
let ctx = this._canvas.current.getContext("2d");
if (ctx) {
- page.render({ canvasContext: ctx, viewport: viewport }); // renders the page onto the canvas context
+ //@ts-ignore
+ page.render({ canvasContext: ctx, viewport: viewport, enableWebGL: true }); // renders the page onto the canvas context
page.getTextContent().then(res => // renders text onto the text container
//@ts-ignore
Pdfjs.renderTextLayer({
@@ -258,7 +259,7 @@ export default class Page extends React.Component<IPageProps> {
}
}
}
- let text = selRange.extractContents().textContent;
+ let text = selRange.cloneContents().textContent;
text && this.props.setSelectionText(text);
// clear selection
diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx
index 83413814f..80aa25f48 100644
--- a/src/client/views/presentationview/PresentationElement.tsx
+++ b/src/client/views/presentationview/PresentationElement.tsx
@@ -359,7 +359,6 @@ export default class PresentationElement extends React.Component<PresentationEle
PanelHeight={() => 90}
focus={emptyFunction}
backgroundColor={returnEmptyString}
- selectOnLoad={false}
parentActive={returnFalse}
whenActiveChanged={returnFalse}
bringToFront={emptyFunction}
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index 567bc6c97..386b5fe74 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -210,7 +210,6 @@ export class SearchItem extends React.Component<SearchItemProps> {
PanelHeight={returnYDimension}
focus={emptyFunction}
backgroundColor={returnEmptyString}
- selectOnLoad={false}
parentActive={returnFalse}
whenActiveChanged={returnFalse}
bringToFront={emptyFunction}
diff --git a/src/server/authentication/config/passport.ts b/src/server/authentication/config/passport.ts
index d42741410..10b17de71 100644
--- a/src/server/authentication/config/passport.ts
+++ b/src/server/authentication/config/passport.ts
@@ -42,9 +42,11 @@ export let isAuthenticated = (req: Request, res: Response, next: NextFunction) =
export let isAuthorized = (req: Request, res: Response, next: NextFunction) => {
const provider = req.path.split("/").slice(-1)[0];
- if (_.find(req.user.tokens, { kind: provider })) {
- next();
- } else {
- res.redirect(`/auth/${provider}`);
+ if (req.user) {
+ if (_.find((req.user as any).tokens, { kind: provider })) {
+ next();
+ } else {
+ res.redirect(`/auth/${provider}`);
+ }
}
}; \ No newline at end of file
diff --git a/src/server/index.ts b/src/server/index.ts
index 34a0a19f1..fca90a585 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -116,7 +116,7 @@ function addSecureRoute(method: Method,
) {
let abstracted = (req: express.Request, res: express.Response) => {
if (req.user) {
- handler(req.user, res, req);
+ handler(req.user as any, res, req);
} else {
req.session!.target = req.originalUrl;
onRejection(res, req);
@@ -447,7 +447,7 @@ function LoadPage(file: string, pageNumber: number, res: Response) {
console.log(pageNumber);
pdf.getPage(pageNumber).then((page: Pdfjs.PDFPageProxy) => {
console.log("reading " + page);
- let viewport = page.getViewport(1);
+ let viewport = page.getViewport({ scale: 1 });
let canvasAndContext = factory.create(viewport.width, viewport.height);
let renderContext = {
canvasContext: canvasAndContext.context,
@@ -811,8 +811,8 @@ const EndpointHandlerMap = new Map<GoogleApiServerUtils.Action, GoogleApiServerU
]);
app.post(RouteStore.googleDocs + "/:sector/:action", (req, res) => {
- let sector = req.params.sector;
- let action = req.params.action;
+ let sector: any = req.params.sector;
+ let action: any = req.params.action;
GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], { credentials, token }).then(endpoint => {
let handler = EndpointHandlerMap.get(action);
if (endpoint && handler) {