>) => void))) {
+ dispatch(tx3);
+ }
+ })) {
+ return false;
}
- })) {
- return false;
}
}
return true;
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index 33ef67ff5..1a292d9af 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -67,8 +67,8 @@ export const nodes: { [index: string]: NodeSpec } = {
// nodes by default. Represented as a `` element with a
// `` element inside of it.
code_block: {
- content: "text*",
- marks: "",
+ content: "inline*",
+ marks: "_",
group: "block",
code: true,
defining: true,
--
cgit v1.2.3-70-g09d2
From 9e37056e3b1e5412e2eca9020841a56503f70d32 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 01:46:42 -0400
Subject: changed richTextMenu to dock at top of window. fixed ColorBox to set
foreground color of selected text.
---
deploy/index.html | 2 +-
src/client/views/AntimodeMenu.tsx | 6 ++++-
src/client/views/MainView.tsx | 2 +-
src/client/views/MetadataEntryMenu.tsx | 26 +++++++++++++---------
.../views/collections/CollectionDockingView.tsx | 17 +++++++-------
src/client/views/nodes/ColorBox.tsx | 6 ++---
.../views/nodes/formattedText/RichTextMenu.tsx | 6 ++---
7 files changed, 37 insertions(+), 28 deletions(-)
(limited to 'src')
diff --git a/deploy/index.html b/deploy/index.html
index fdfd77cc2..e441e3610 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -10,7 +10,7 @@
-
+
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index 2d26afcf6..3e4d20fea 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -147,7 +147,11 @@ export default abstract class AntimodeMenu extends React.Component {
protected getElementWithRows(rows: JSX.Element[], numRows: number, hasDragger: boolean = true) {
return (
+ style={{
+ left: this._left, top: this._top, opacity: this._opacity, transitionProperty: this._transitionProperty,
+ transitionDuration: this._transitionDuration, transitionDelay: this._transitionDelay, height: "auto",
+ flexDirection: this.Pinned ? "row" : undefined, position: this.Pinned ? "unset" : undefined
+ }}>
{hasDragger ?
: (null)}
{rows}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index d6c46e3b0..0686e797e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -570,6 +570,7 @@ export class MainView extends React.Component {
+
{this.mainContent}
@@ -578,7 +579,6 @@ export class MainView extends React.Component {
-
{this.snapLines}
diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx
index e100d3f52..b0752ffb2 100644
--- a/src/client/views/MetadataEntryMenu.tsx
+++ b/src/client/views/MetadataEntryMenu.tsx
@@ -197,19 +197,23 @@ export class MetadataEntryMenu extends React.Component{
render() {
return ( e.stopPropagation()}>
- Key:
-
this.autosuggestRef.current!.input?.focus()} >
-
+
+
Key:
+
this.autosuggestRef.current!.input?.focus()} >
+
+
- Value:
+
+ Value:
this._ref.current!.focus()} onChange={this.onValueChange} onKeyDown={this.onValueKeyDown} />
+
{this.considerChildOptions}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index a969e302d..ee987abdb 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -11,7 +11,7 @@ import { Id } from '../../../fields/FieldSymbols';
import { FieldId } from "../../../fields/RefField";
import { Cast, NumCast, StrCast } from "../../../fields/Types";
import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnOne, returnTrue, Utils, returnZero, returnEmptyFilter } from "../../../Utils";
+import { emptyFunction, returnOne, returnTrue, Utils, returnZero, returnEmptyFilter, setupMoveUpEvents, returnFalse } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { Docs } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
@@ -521,13 +521,14 @@ export class CollectionDockingView extends React.Component
{
- if (!(e.nativeEvent as any).defaultPrevented) {
- e.preventDefault();
- e.stopPropagation();
- const dragData = new DragManager.DocumentDragData([doc]);
- dragData.dropAction = doc.dropAction as dropActionType;
- DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY);
- }
+ setupMoveUpEvents(this, e, (e) => {
+ if (!(e as any).defaultPrevented) {
+ const dragData = new DragManager.DocumentDragData([doc]);
+ dragData.dropAction = doc.dropAction as dropActionType;
+ DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY);
+ return true;
+ } return false
+ }, returnFalse, emptyFunction);
};
tab.buttonDisposer = reaction(() => ((view: Opt) => view ? [view] : [])(DocumentManager.Instance.getDocumentView(doc)),
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index 7b7c4d266..d6d9a8cfd 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -36,11 +36,11 @@ export class ColorBox extends ViewBoxBaseComponent
-
*/}
@@ -788,7 +788,7 @@ export default class RichTextMenu extends AntimodeMenu {
;
return (
-
+
{this.getElementWithRows([row1, row2], 2, false)}
);
--
cgit v1.2.3-70-g09d2
From 71ba25ed627be46d02878e58bd791bf817d552ad Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 01:53:31 -0400
Subject: changed titles to just look at first node of text box.
---
src/client/views/nodes/formattedText/FormattedTextBox.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 3ee5603e5..e01144f82 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -230,7 +230,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
updateTitle = () => {
if ((this.props.Document.isTemplateForField === "text" || !this.props.Document.isTemplateForField) && // only update the title if the data document's data field is changing
StrCast(this.dataDoc.title).startsWith("-") && this._editorView && !this.rootDoc.customTitle) {
- const str = this._editorView.state.doc.textContent;
+ let node = this._editorView.state.doc;
+ while (node.firstChild) node = node.firstChild;
+ const str = node.textContent;
const titlestr = str.substr(0, Math.min(40, str.length));
this.dataDoc.title = "-" + titlestr + (str.length > 40 ? "..." : "");
}
--
cgit v1.2.3-70-g09d2
From 7e02ca22f9667d0bdb89b29da3c412ba52976fbf Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 09:52:05 -0400
Subject: fixed placement of settings panel icon & panel. fixed layout of
docked text bar. added blockquote icon
---
deploy/index.html | 2 +-
src/client/views/AntimodeMenu.scss | 5 +-
src/client/views/MainView.tsx | 54 ++++++++++++----------
src/client/views/globalCssVariables.scss | 2 +
src/client/views/globalCssVariables.scss.d.ts | 1 +
.../views/nodes/formattedText/RichTextMenu.tsx | 39 +++++++++-------
6 files changed, 60 insertions(+), 43 deletions(-)
(limited to 'src')
diff --git a/deploy/index.html b/deploy/index.html
index e441e3610..29a3f15cd 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -10,7 +10,7 @@
-
+
diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss
index d4a76ee17..e56574bb7 100644
--- a/src/client/views/AntimodeMenu.scss
+++ b/src/client/views/AntimodeMenu.scss
@@ -1,7 +1,10 @@
+@import "./globalCssVariables";
+
+
.antimodeMenu-cont {
position: absolute;
z-index: 10000;
- height: 35px;
+ height: $antimodemenu-height;
background: #323232;
box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25);
border-radius: 0px 6px 6px 6px;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 0686e797e..97953452d 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -5,8 +5,9 @@ import {
faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt,
faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote,
- faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye
+ faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft
} from '@fortawesome/free-solid-svg-icons';
+import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, configure, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -134,7 +135,7 @@ export class MainView extends React.Component {
faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt,
faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
- faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye);
+ faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft);
this.initEventListeners();
this.initAuthenticationRouters();
}
@@ -326,9 +327,7 @@ export class MainView extends React.Component {
const width = this.flyoutWidth;
return
{({ measureRef }) =>
- {
- console.log("ENTERING");
- }} onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)` }}>
+
{!mainContainer ? (null) : this.mainDocView}
}
@@ -459,28 +458,33 @@ export class MainView extends React.Component {
@computed get mainContent() {
const sidebar = this.userDoc?.["tabs-panelContainer"];
return !this.userDoc || !(sidebar instanceof Doc) ? (null) : (
-
-
-
-
-
-
- {this.flyout}
- {this.expandButton}
+
+
+
+
+
+
+
+ {this.flyout}
+ {this.expandButton}
+
+ {this.dockingContent}
- {this.dockingContent}
);
}
diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss
index 9d3d2e592..4e85fe0ca 100644
--- a/src/client/views/globalCssVariables.scss
+++ b/src/client/views/globalCssVariables.scss
@@ -12,6 +12,7 @@ $lighter-alt-accent: rgb(207, 220, 240);
$darker-alt-accent: rgb(178, 206, 248);
$intermediate-color: #9c9396;
$dark-color: #121721;
+$antimodemenu-height: 35px;
// fonts
$sans-serif: "Noto Sans",
sans-serif;
@@ -40,4 +41,5 @@ $MAX_ROW_HEIGHT: 44px;
MINIMIZED_ICON_SIZE: $MINIMIZED_ICON_SIZE;
MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT;
SEARCH_THUMBNAIL_SIZE: $search-thumnail-size;
+ ANTIMODEMENU_HEIGHT: $antimodemenu-height;
}
\ No newline at end of file
diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts
index d95cec9d8..a7ca4b300 100644
--- a/src/client/views/globalCssVariables.scss.d.ts
+++ b/src/client/views/globalCssVariables.scss.d.ts
@@ -5,6 +5,7 @@ interface IGlobalScss {
MINIMIZED_ICON_SIZE: string;
MAX_ROW_HEIGHT: string;
SEARCH_THUMBNAIL_SIZE: string;
+ ANTIMODEMENU_HEIGHT: string;
}
declare const globalCssVariables: IGlobalScss;
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index e80951918..68101fbde 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -161,11 +161,10 @@ export default class RichTextMenu extends AntimodeMenu {
return;
}
this.view = view;
- const state = view.state;
props && (this.editorProps = props);
// 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 (lastState?.doc.eq(view.state.doc) && lastState.selection.eq(view.state.selection)) return;
// update active marks
const activeMarks = this.getActiveMarksOnSelection();
@@ -173,18 +172,18 @@ export default class RichTextMenu extends AntimodeMenu {
// update active font family and size
const active = this.getActiveFontStylesOnSelection();
- const activeFamilies = active && active.get("families");
- const activeSizes = active && active.get("sizes");
+ const activeFamilies = active?.get("families");
+ const activeSizes = active?.get("sizes");
- this.activeFontFamily = !activeFamilies || activeFamilies.length === 0 ? "Arial" : activeFamilies.length === 1 ? String(activeFamilies[0]) : "various";
- this.activeFontSize = !activeSizes || activeSizes.length === 0 ? "13pt" : activeSizes.length === 1 ? String(activeSizes[0]) + "pt" : "various";
+ this.activeFontFamily = !activeFamilies?.length ? "Arial" : activeFamilies.length === 1 ? String(activeFamilies[0]) : "various";
+ this.activeFontSize = !activeSizes?.length ? "13pt" : activeSizes.length === 1 ? String(activeSizes[0]) : "various";
// update link in current selection
const targetTitle = await this.getTextLinkTargetTitle();
this.setCurrentLink(targetTitle);
}
- setMark = (mark: Mark, state: EditorState
, dispatch: any) => {
+ setMark = (mark: Mark, state: EditorState, dispatch: any, dontToggle: boolean = false) => {
if (mark) {
const node = (state.selection as NodeSelection).node;
if (node?.type === schema.nodes.ordered_list) {
@@ -194,14 +193,15 @@ export default class RichTextMenu extends AntimodeMenu {
if (mark.type === schema.marks.pFontColor) attrs = { ...attrs, fontColor: mark.attrs.color };
const tr = updateBullets(state.tr.setNodeMarkup(state.selection.from, node.type, attrs), state.schema);
dispatch(tr.setSelection(new NodeSelection(tr.doc.resolve(state.selection.from))));
- } else {
+ } else if (dontToggle) {
toggleMark(mark.type, mark.attrs)(state, (tx: any) => {
const { from, $from, to, empty } = tx.selection;
- // if (!tx.doc.rangeHasMark(from, to, mark.type)) {
- // toggleMark(mark.type, mark.attrs)({ tr: tx, doc: tx.doc, selection: tx.selection, storedMarks: tx.storedMarks }, dispatch);
- // } else
- dispatch(tx);
+ if (!tx.doc.rangeHasMark(from, to, mark.type)) { // hack -- should have just set the mark in the first place
+ toggleMark(mark.type, mark.attrs)({ tr: tx, doc: tx.doc, selection: tx.selection, storedMarks: tx.storedMarks }, dispatch);
+ } else dispatch(tx);
});
+ } else {
+ toggleMark(mark.type, mark.attrs)(state, (tx: any) => dispatch(tx));
}
}
}
@@ -368,11 +368,11 @@ export default class RichTextMenu extends AntimodeMenu {
}
changeFontSize = (mark: Mark, view: EditorView) => {
- this.setMark(view.state.schema.marks.pFontSize.create({ fontSize: mark.attrs.fontSize }), view.state, view.dispatch);
+ this.setMark(view.state.schema.marks.pFontSize.create({ fontSize: mark.attrs.fontSize }), view.state, view.dispatch, true);
}
changeFontFamily = (mark: Mark, view: EditorView) => {
- this.setMark(view.state.schema.marks.pFontFamily.create({ family: mark.attrs.family }), view.state, view.dispatch);
+ this.setMark(view.state.schema.marks.pFontFamily.create({ family: mark.attrs.family }), view.state, view.dispatch, true);
}
// TODO: remove doesn't work
@@ -406,7 +406,13 @@ export default class RichTextMenu extends AntimodeMenu {
tr.addMark(state.selection.from, state.selection.to, mark);
const content = tr.selection.content();
const newNode = state.schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() });
- dispatch && dispatch(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark));
+ dispatch?.(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark));
+ return true;
+ }
+
+ insertBlockquote(state: EditorState, dispatch: any) {
+ if (state.selection.empty) return false;
+ setBlockType(state.schema.nodes.blockquote)(state, (tx: any) => dispatch(tx));
return true;
}
@@ -539,7 +545,7 @@ export default class RichTextMenu extends AntimodeMenu {
dispatch(state.tr.addStoredMark(colorMark));
return false;
}
- this.setMark(colorMark, state, dispatch);
+ this.setMark(colorMark, state, dispatch, true);
}
@action toggleHighlightDropdown() { this.showHighlightDropdown = !this.showHighlightDropdown; }
@@ -766,6 +772,7 @@ export default class RichTextMenu extends AntimodeMenu {
this.createLinkButton(),
this.createBrushButton(),
this.createButton("indent", "Summarize", undefined, this.insertSummarizer),
+ this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote),
]};
const row2 =
--
cgit v1.2.3-70-g09d2
From ae6315813d718f8e4913ed98f5aec33464eb8164 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 11:45:22 -0400
Subject: fixed warnings. fixed blockquote menu function.
---
src/client/util/DragManager.ts | 2 +-
.../views/collections/CollectionDockingView.tsx | 3 +-
.../views/nodes/formattedText/FormattedTextBox.tsx | 5 +--
.../views/nodes/formattedText/ParagraphNodeSpec.ts | 2 +-
.../views/nodes/formattedText/RichTextMenu.tsx | 50 +++++++++++++---------
src/client/views/nodes/formattedText/nodes_rts.ts | 20 ++++++++-
.../nodes/formattedText/prosemirrorPatches.js | 4 +-
7 files changed, 56 insertions(+), 30 deletions(-)
(limited to 'src')
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 533bc8485..91bc51101 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -218,7 +218,7 @@ export namespace DragManager {
docDragData.dropAction !== "same" && docDragData.droppedDocuments.forEach((drop: Doc, i: number) => {
const dragProps = Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []);
const remProps = (dragData?.removeDropProperties || []).concat(Array.from(dragProps));
- remProps.map(prop => drop[prop] = undefined)
+ remProps.map(prop => drop[prop] = undefined);
});
batch.end();
}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index ee987abdb..79c577b6d 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -527,7 +527,8 @@ export class CollectionDockingView extends React.Component dispatch(tx));
+ toggleMark(mark.type, mark.attrs)(state, dispatch);
}
}
}
@@ -411,8 +415,12 @@ export default class RichTextMenu extends AntimodeMenu {
}
insertBlockquote(state: EditorState, dispatch: any) {
- if (state.selection.empty) return false;
- setBlockType(state.schema.nodes.blockquote)(state, (tx: any) => dispatch(tx));
+ const path = (state.selection.$from as any).path;
+ if (path.length > 6 && path[path.length - 6].type === schema.nodes.blockquote) {
+ lift(state, dispatch);
+ } else {
+ wrapIn(schema.nodes.blockquote)(state, dispatch);
+ }
return true;
}
@@ -758,7 +766,7 @@ export default class RichTextMenu extends AntimodeMenu {
}
render() {
-
+ TraceMobx();
const row1 = {[
!this.collapsed ? this.getDragger() : (null),
this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)),
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index 1a292d9af..0a867912f 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -1,7 +1,7 @@
import React = require("react");
import { DOMOutputSpecArray, Fragment, MarkSpec, Node, NodeSpec, Schema, Slice } from "prosemirror-model";
import { bulletList, listItem, orderedList } from 'prosemirror-schema-list';
-import ParagraphNodeSpec from "./ParagraphNodeSpec";
+import { ParagraphNodeSpec, toParagraphDOM, getParagraphNodeAttrs } from "./ParagraphNodeSpec";
const blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"],
preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0];
@@ -32,13 +32,29 @@ export const nodes: { [index: string]: NodeSpec } = {
// :: NodeSpec A blockquote (`
`) wrapping one or more blocks.
blockquote: {
- content: "block+",
+ content: "block*",
group: "block",
defining: true,
parseDOM: [{ tag: "blockquote" }],
toDOM() { return blockquoteDOM; }
},
+
+ // blockquote: {
+ // ...ParagraphNodeSpec,
+ // defining: true,
+ // parseDOM: [{
+ // tag: "blockquote", getAttrs(dom: any) {
+ // return getParagraphNodeAttrs(dom);
+ // }
+ // }],
+ // toDOM(node: any) {
+ // const dom = toParagraphDOM(node);
+ // (dom as any)[0] = 'blockquote';
+ // return dom;
+ // },
+ // },
+
// :: NodeSpec A horizontal rule (`
`).
horizontal_rule: {
group: "block",
diff --git a/src/client/views/nodes/formattedText/prosemirrorPatches.js b/src/client/views/nodes/formattedText/prosemirrorPatches.js
index 269423482..763961958 100644
--- a/src/client/views/nodes/formattedText/prosemirrorPatches.js
+++ b/src/client/views/nodes/formattedText/prosemirrorPatches.js
@@ -136,4 +136,6 @@ function wrappingInputRule(regexp, nodeType, getAttrs, joinPredicate, customWith
(!joinPredicate || joinPredicate(match, before))) { tr.join(start - 1); }
return tr
})
-}
\ No newline at end of file
+}
+
+
--
cgit v1.2.3-70-g09d2
From ab55a59f47efdd8f134a619ca0fa59203efe2fa9 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 13:43:23 -0400
Subject: fixed summary icon
---
src/client/views/MainView.tsx | 4 ++--
src/client/views/nodes/formattedText/RichTextMenu.tsx | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
(limited to 'src')
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 97953452d..415f8b364 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -5,7 +5,7 @@ import {
faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt,
faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote,
- faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft
+ faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft, faSortAmountDown
} from '@fortawesome/free-solid-svg-icons';
import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -135,7 +135,7 @@ export class MainView extends React.Component {
faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt,
faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
- faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft);
+ faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft, faSortAmountDown);
this.initEventListeners();
this.initAuthenticationRouters();
}
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 5e32b3ef8..3a4363587 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -779,7 +779,7 @@ export default class RichTextMenu extends AntimodeMenu {
this.createHighlighterButton(),
this.createLinkButton(),
this.createBrushButton(),
- this.createButton("indent", "Summarize", undefined, this.insertSummarizer),
+ this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer),
this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote),
]}
;
--
cgit v1.2.3-70-g09d2
From 8e9f77d93ec4393c52a215e75bcd9a362173e06a Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 16:24:37 -0400
Subject: made persistent link Icon in bottom left of document
---
src/client/views/DocumentButtonBar.tsx | 18 +++---
src/client/views/DocumentDecorations.tsx | 2 +-
src/client/views/MainView.tsx | 3 +
src/client/views/globalCssVariables.scss | 1 +
src/client/views/linking/LinkMenu.scss | 4 ++
src/client/views/linking/LinkMenu.tsx | 37 ++++++-----
src/client/views/nodes/DocumentLinksButton.scss | 39 +++++++++++
src/client/views/nodes/DocumentLinksButton.tsx | 75 ++++++++++++++++++++++
src/client/views/nodes/DocumentView.tsx | 10 +--
.../views/nodes/formattedText/RichTextMenu.tsx | 7 +-
10 files changed, 160 insertions(+), 36 deletions(-)
create mode 100644 src/client/views/nodes/DocumentLinksButton.scss
create mode 100644 src/client/views/nodes/DocumentLinksButton.tsx
(limited to 'src')
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 62a95116f..208b4d57a 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -239,14 +239,14 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
get linkButton() {
const view0 = this.view0;
const linkCount = view0 && DocListCast(view0.props.Document.links).length;
- return !view0 ? (null) :
-
}>
-
- {linkCount ? linkCount :
}
+ return !view0 || linkCount ? (null) :
+
+
+
+ {linkCount ? linkCount : }
+
-
-
;
+
;
}
@computed
@@ -317,9 +317,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
const considerPull = isText && this.considerGoogleDocsPull;
const considerPush = isText && this.considerGoogleDocsPush;
return
-
- {this.linkButton}
-
+ {this.linkButton}
{this.templateButton}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index beb6155ca..d7b0ab7a9 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -552,7 +552,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}>
-
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 415f8b364..374fd7421 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -55,6 +55,8 @@ import { TimelineMenu } from './animationtimeline/TimelineMenu';
import { SnappingManager } from '../util/SnappingManager';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
import { DocumentManager } from '../util/DocumentManager';
+import { DocumentLinksButton } from './nodes/DocumentLinksButton';
+import { LinkMenu } from './linking/LinkMenu';
@observer
export class MainView extends React.Component {
@@ -578,6 +580,7 @@ export class MainView extends React.Component {
{this.mainContent}
+ {DocumentLinksButton.EditLink ? : (null)}
diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss
index 4e85fe0ca..3e54d001b 100644
--- a/src/client/views/globalCssVariables.scss
+++ b/src/client/views/globalCssVariables.scss
@@ -12,6 +12,7 @@ $lighter-alt-accent: rgb(207, 220, 240);
$darker-alt-accent: rgb(178, 206, 248);
$intermediate-color: #9c9396;
$dark-color: #121721;
+$link-color: lightBlue;
$antimodemenu-height: 35px;
// fonts
$sans-serif: "Noto Sans",
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index 7dee22f66..c372e7098 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -8,6 +8,10 @@
.linkMenu-list {
max-height: 200px;
overflow-y: scroll;
+ position: absolute;
+ z-index: 10;
+ background: $link-color;
+ min-width: 150px
}
.linkMenu-group {
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 56f40ad69..0fcc0f0b9 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -4,11 +4,12 @@ import { DocumentView } from "../nodes/DocumentView";
import { LinkEditor } from "./LinkEditor";
import './LinkMenu.scss';
import React = require("react");
-import { Doc } from "../../../fields/Doc";
+import { Doc, Opt } from "../../../fields/Doc";
import { LinkManager } from "../../util/LinkManager";
import { LinkMenuGroup } from "./LinkMenuGroup";
import { faTrash } from '@fortawesome/free-solid-svg-icons';
import { library } from "@fortawesome/fontawesome-svg-core";
+import { DocumentLinksButton } from "../nodes/DocumentLinksButton";
library.add(faTrash);
@@ -16,16 +17,29 @@ interface Props {
docView: DocumentView;
changeFlyout: () => void;
addDocTab: (document: Doc, where: string) => boolean;
+ location: number[];
}
@observer
export class LinkMenu extends React.Component {
@observable private _editingLink?: Doc;
+ @observable private _linkMenuRef: Opt;
+ @action
+ onClick = (e: PointerEvent) => {
+ if (!Array.from(this._linkMenuRef?.getElementsByTagName((e.target as HTMLElement).tagName) || []).includes(e.target as any)) {
+ DocumentLinksButton.EditLink = undefined;
+ }
+ }
@action
componentDidMount() {
this._editingLink = undefined;
+ document.addEventListener("pointerdown", this.onClick);
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener("pointerdown", this.onClick);
}
clearAllLinks = () => {
@@ -56,20 +70,11 @@ export class LinkMenu extends React.Component {
render() {
const sourceDoc = this.props.docView.props.Document;
const groups: Map = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc);
- if (this._editingLink === undefined) {
- return (
-
- {/*
*/}
- {/* */}
-
- {this.renderAllGroups(groups)}
-
-
- );
- } else {
- return (
- this._editingLink = undefined)}>
- );
- }
+ return this._linkMenuRef = r} style={{ left: this.props.location[0], top: this.props.location[1] }}>
+ {!this._editingLink ?
+ this.renderAllGroups(groups) :
+ this._editingLink = undefined)} />
+ }
+
;
}
}
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
new file mode 100644
index 000000000..b9d5d437b
--- /dev/null
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -0,0 +1,39 @@
+@import "../globalCssVariables.scss";
+
+
+.documentLinksButton-button-empty:hover {
+ background: $main-accent;
+ transform: scale(1.05);
+ cursor: pointer;
+}
+
+.documentLinksButton-button-nonempty:hover {
+ background: $main-accent;
+ transform: scale(1.05);
+ cursor: pointer;
+}
+
+.documentLinksButton-button-empty,
+.documentLinksButton-button-nonempty {
+ height: 20px;
+ width: 20px;
+ border-radius: 50%;
+ opacity: 0.9;
+ pointer-events: auto;
+ background-color: $link-color;
+ color: black;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ font-size: 75%;
+ transition: transform 0.2s;
+ text-align: center;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &:hover {
+ background: $main-accent;
+ transform: scale(1.05);
+ cursor: pointer;
+ }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
new file mode 100644
index 000000000..4f94b06cb
--- /dev/null
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -0,0 +1,75 @@
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { computed, action, runInAction, observable } from "mobx";
+import { observer } from "mobx-react";
+import './DocumentLinksButton.scss';
+import React = require("react");
+import { emptyFunction, setupMoveUpEvents } from "../../../Utils";
+import { DocListCast, Doc } from "../../../fields/Doc";
+import { DocumentView } from "./DocumentView";
+import { LinkMenu } from "../linking/LinkMenu";
+import { UndoManager } from "../../util/UndoManager";
+import { DragManager } from "../../util/DragManager";
+const higflyout = require("@hig/flyout");
+export const { anchorPoints } = higflyout;
+export const Flyout = higflyout.default;
+
+interface DocumentLinksButtonProps {
+ View: DocumentView;
+}
+@observer
+export class DocumentLinksButton extends React.Component {
+ private _linkButton = React.createRef();
+
+ @action
+ onLinkButtonMoved = (e: PointerEvent) => {
+ if (this._linkButton.current !== null) {
+ const linkDrag = UndoManager.StartBatch("Drag Link");
+ this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View.props.Document, e.pageX, e.pageY, {
+ dragComplete: dropEv => {
+ const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
+ if (this.props.View && linkDoc) {
+ !linkDoc.linkRelationship && (Doc.GetProto(linkDoc).linkRelationship = "hyperlink");
+
+ // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks)
+ // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures
+ // however, the dropped document isn't so accessible. What we do is set the newly created link document on the documentView
+ // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it.
+ dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData);
+ runInAction(() => this.props.View._link = linkDoc);
+ setTimeout(action(() => this.props.View._link = undefined), 0);
+ }
+ linkDrag?.end();
+ },
+ hideSource: false
+ });
+ return true;
+ }
+ return false;
+ }
+
+ onLinkButtonDown = (e: React.PointerEvent): void => {
+ setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e) => {
+ DocumentLinksButton.EditLink = this.props.View;
+ DocumentLinksButton.EditLinkLoc = [e.clientX, e.clientY];
+ }));
+ }
+
+ @observable
+ public static EditLink: DocumentView | undefined;
+ public static EditLinkLoc: number[] = [0, 0];
+
+ @computed
+ get linkButton() {
+ const view0 = this.props.View;
+ const linkCount = view0 && DocListCast(view0.props.Document.links).length;
+ return !view0 || !linkCount ? (null) :
+
+
+ {linkCount ? linkCount : }
+
+
;
+ }
+ render() {
+ return this.linkButton;
+ }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7e20b40a3..d9a211e7a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -41,6 +41,7 @@ import "./DocumentView.scss";
import { LinkAnchorBox } from './LinkAnchorBox';
import { RadialMenu } from './RadialMenu';
import React = require("react");
+import { DocumentLinksButton } from './DocumentLinksButton';
library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight,
fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale,
@@ -735,10 +736,8 @@ export class DocumentView extends DocComponent(Docu
const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
templateDoc && optionItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" });
- if (!options) {
- options = { description: "Options...", subitems: optionItems, icon: "compass" };
- cm.addItem(options);
- }
+ optionItems.push({ description: "Toggle Show Each Link Dot", event: () => this.layoutDoc.showLinks = !this.layoutDoc.showLinks, icon: "eye" });
+ !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
const existingOnClick = cm.findByDescription("OnClick...");
const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
@@ -1037,7 +1036,8 @@ export class DocumentView extends DocComponent(Docu
select={this.select}
onClick={this.onClickHandler}
layoutKey={this.finalLayoutKey} />
- {this.anchors}
+ {this.layoutDoc.showLinks ? this.anchors : (null)}
+ {this.props.forcedBackgroundColor?.(this.Document) === "transparent" ? (null) : }
);
}
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 3a4363587..839943aac 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -11,7 +11,7 @@ import { EditorState, NodeSelection, TextSelection } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { Doc } from "../../../../fields/Doc";
import { DarkPastelSchemaPalette, PastelSchemaPalette } from '../../../../fields/SchemaHeaderField';
-import { Cast, StrCast } from "../../../../fields/Types";
+import { Cast, StrCast, BoolCast } from "../../../../fields/Types";
import { unimplementedFunction, Utils } from "../../../../Utils";
import { DocServer } from "../../../DocServer";
import { LinkManager } from "../../../util/LinkManager";
@@ -72,7 +72,7 @@ export default class RichTextMenu extends AntimodeMenu {
super(props);
RichTextMenu.Instance = this;
this._canFade = false;
- this.Pinned = true;
+ this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]);
this.fontSizeOptions = [
{ mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize },
@@ -147,7 +147,6 @@ export default class RichTextMenu extends AntimodeMenu {
this.updateFromDash(view, lastState, this.editorProps);
}
-
public MakeLinkToSelection = (linkDocId: string, title: string, location: string, targetDocId: string): string => {
if (this.view) {
const link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, linkId: linkDocId, targetId: targetDocId });
@@ -750,7 +749,7 @@ export default class RichTextMenu extends AntimodeMenu {
@action
toggleMenuPin = (e: React.MouseEvent) => {
- this.Pinned = !this.Pinned;
+ Doc.UserDoc()["menuRichText-pinned"] = this.Pinned = !this.Pinned;
if (!this.Pinned) {
this.fadeOut(true);
}
--
cgit v1.2.3-70-g09d2
From fe6da65c9ac7ff797a2e0b6047bef2656463c008 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 16:58:07 -0400
Subject: added halo for link buttons
---
src/client/views/nodes/DocumentLinksButton.tsx | 23 ++++++++++-------------
src/client/views/nodes/DocumentView.tsx | 12 +++++++++++-
2 files changed, 21 insertions(+), 14 deletions(-)
(limited to 'src')
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 4f94b06cb..8ab3aed00 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -1,14 +1,12 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { computed, action, runInAction, observable } from "mobx";
+import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import './DocumentLinksButton.scss';
-import React = require("react");
+import { Doc, DocListCast } from "../../../fields/Doc";
import { emptyFunction, setupMoveUpEvents } from "../../../Utils";
-import { DocListCast, Doc } from "../../../fields/Doc";
-import { DocumentView } from "./DocumentView";
-import { LinkMenu } from "../linking/LinkMenu";
-import { UndoManager } from "../../util/UndoManager";
import { DragManager } from "../../util/DragManager";
+import { UndoManager } from "../../util/UndoManager";
+import './DocumentLinksButton.scss';
+import { DocumentView } from "./DocumentView";
+import React = require("react");
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -60,12 +58,11 @@ export class DocumentLinksButton extends React.Component
-
- {linkCount ? linkCount :
}
+
+ {links.length}
;
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d9a211e7a..20a606937 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -584,10 +584,14 @@ export class DocumentView extends DocComponent(Docu
toggleLinkButtonBehavior = (): void => {
if (this.Document.isLinkButton || this.layoutDoc.onClick || this.Document.ignoreClick) {
this.Document.isLinkButton = false;
+ const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
+ first && (first.hidden = false);
this.Document.ignoreClick = false;
this.layoutDoc.onClick = undefined;
} else {
this.Document.isLinkButton = true;
+ const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
+ first && (first.hidden = true);
this.Document.followLinkZoom = false;
this.Document.followLinkLocation = undefined;
}
@@ -597,8 +601,12 @@ export class DocumentView extends DocComponent(Docu
toggleFollowInPlace = (): void => {
if (this.Document.isLinkButton) {
this.Document.isLinkButton = false;
+ const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
+ first && (first.hidden = false);
} else {
this.Document.isLinkButton = true;
+ const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
+ first && (first.hidden = true);
this.Document.followLinkZoom = true;
this.Document.followLinkLocation = "inPlace";
}
@@ -608,6 +616,8 @@ export class DocumentView extends DocComponent(Docu
toggleFollowOnRight = (): void => {
if (this.Document.isLinkButton) {
this.Document.isLinkButton = false;
+ const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
+ first && (first.hidden = false);
} else {
this.Document.isLinkButton = true;
this.Document.followLinkZoom = false;
@@ -1192,7 +1202,7 @@ export class DocumentView extends DocComponent(Docu
color: StrCast(this.layoutDoc.color, "inherit"),
outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px",
border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined,
- boxShadow: this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined,
+ boxShadow: this.Document.isLinkButton ? StrCast(this.props.Document._linkButtonShadow, "lightblue 0em 0em 1em") : this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined,
background: finalColor,
opacity: finalOpacity,
fontFamily: StrCast(this.Document._fontFamily, "inherit"),
--
cgit v1.2.3-70-g09d2
From 4ee4b611c6d6732377f2f9160237118847fca92b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 18:49:25 -0400
Subject: added ability to start a link & finish a link with double click
---
src/client/views/DocumentButtonBar.tsx | 29 ++++++++++++------
src/client/views/GlobalKeyHandler.ts | 2 ++
.../collectionFreeForm/CollectionFreeFormView.tsx | 2 +-
src/client/views/nodes/DocumentLinksButton.scss | 14 ++++++++-
src/client/views/nodes/DocumentLinksButton.tsx | 35 +++++++++++++++++-----
5 files changed, 64 insertions(+), 18 deletions(-)
(limited to 'src')
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 208b4d57a..8cd1b650e 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -1,28 +1,28 @@
import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
-import { faArrowAltCircleDown, faPhotoVideo, faArrowAltCircleUp, faArrowAltCircleRight, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faPhotoVideo, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCast } from "../../fields/Doc";
import { RichTextField } from '../../fields/RichTextField';
-import { NumCast, StrCast, Cast } from "../../fields/Types";
+import { Cast, NumCast } from "../../fields/Types";
import { emptyFunction, setupMoveUpEvents } from "../../Utils";
+import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
+import { Docs, DocUtils } from '../documents/Documents';
+import { DragManager } from '../util/DragManager';
import { UndoManager } from "../util/UndoManager";
import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView';
import { ParentDocSelector } from './collections/ParentDocumentSelector';
import './collections/ParentDocumentSelector.scss';
import './DocumentButtonBar.scss';
-import { LinkMenu } from "./linking/LinkMenu";
+import { MetadataEntryMenu } from './MetadataEntryMenu';
import { DocumentView } from './nodes/DocumentView';
import { GoogleRef } from "./nodes/formattedText/FormattedTextBox";
import { TemplateMenu } from "./TemplateMenu";
import { Template, Templates } from "./Templates";
import React = require("react");
-import { DragManager } from '../util/DragManager';
-import { MetadataEntryMenu } from './MetadataEntryMenu';
-import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
-import { Docs } from '../documents/Documents';
+import { DocumentLinksButton } from './nodes/DocumentLinksButton';
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -142,7 +142,16 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
onLinkButtonDown = (e: React.PointerEvent): void => {
- setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, emptyFunction);
+ setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, (e, doubleTap) => {
+ if (doubleTap) {
+ if (!DocumentLinksButton.StartLink) {
+ runInAction(() => DocumentLinksButton.StartLink = this.view0);
+ } else {
+ DocumentLinksButton.StartLink !== this.view0 && this.view0 &&
+ DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.view0.props.Document }, "long drag");
+ }
+ }
+ });
}
@@ -242,7 +251,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
return !view0 || linkCount ? (null) :
-
+
{linkCount ? linkCount : }
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 27755737e..7bc8cf6a7 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -19,6 +19,7 @@ import { MarqueeView } from "./collections/collectionFreeForm/MarqueeView";
import { DocumentDecorations } from "./DocumentDecorations";
import { MainView } from "./MainView";
import { DocumentView } from "./nodes/DocumentView";
+import { DocumentLinksButton } from "./nodes/DocumentLinksButton";
const modifiers = ["control", "meta", "shift", "alt"];
type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise
;
@@ -77,6 +78,7 @@ export default class KeyManager {
// MarqueeView.DragMarquee = !MarqueeView.DragMarquee; // bcz: this needs a better disclosure UI
break;
case "escape":
+ DocumentLinksButton.StartLink = undefined;
const main = MainView.Instance;
Doc.SetSelectedTool(InkTool.None);
if (main.isPointerDown) {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3a8778c14..eddc225b1 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -245,7 +245,7 @@ export class CollectionFreeFormView extends CollectionSubView {
- setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e) => {
- DocumentLinksButton.EditLink = this.props.View;
- DocumentLinksButton.EditLinkLoc = [e.clientX, e.clientY];
+ setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
+ if (doubleTap) {
+ DocumentLinksButton.StartLink = this.props.View;
+ } else {
+ DocumentLinksButton.EditLink = this.props.View;
+ DocumentLinksButton.EditLinkLoc = [e.clientX + 10, e.clientY];
+ }
+ }));
+ }
+ completeLink = (e: React.PointerEvent): void => {
+ setupMoveUpEvents(this, e, returnFalse, emptyFunction, action((e, doubleTap) => {
+ if (doubleTap) {
+ if (DocumentLinksButton.StartLink === this.props.View) {
+ DocumentLinksButton.StartLink = undefined;
+ } else {
+ DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View &&
+ DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
+ }
+ }
}));
}
@@ -59,11 +78,13 @@ export class DocumentLinksButton extends React.Component
+ return !links.length || links[0].hidden ? (null) :
+
- {links.length}
+ {links.length ? links.length : }
+ {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
: (null)}
+ {DocumentLinksButton.StartLink === this.props.View ?
: (null)}
;
}
render() {
--
cgit v1.2.3-70-g09d2
From fb69ecbbb00ae9f784ee8519729651299049cd86 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 24 Jun 2020 18:50:56 -0400
Subject: from last
---
.../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 ++
1 file changed, 2 insertions(+)
(limited to 'src')
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index eddc225b1..936174b52 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -47,6 +47,7 @@ import { Timeline } from "../../animationtimeline/Timeline";
import { SnappingManager } from "../../../util/SnappingManager";
import { ActiveInkColor, ActiveInkWidth, ActiveInkBezierApprox } from "../../InkingStroke";
import { DocumentType } from "../../../documents/DocumentTypes";
+import { DocumentLinksButton } from "../../nodes/DocumentLinksButton";
library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload);
@@ -589,6 +590,7 @@ export class CollectionFreeFormView extends CollectionSubView {
if (this.layoutDoc.targetScale && (Math.abs(e.pageX - this._downX) < 3 && Math.abs(e.pageY - this._downY) < 3)) {
if (Date.now() - this._lastTap < 300) {
+ runInAction(() => DocumentLinksButton.StartLink = undefined);
const docpt = this.getTransform().transformPoint(e.clientX, e.clientY);
this.scaleAtPt(docpt, 1);
e.stopPropagation();
--
cgit v1.2.3-70-g09d2
From ba42ca25ae828b6279f618dea87f7cd37a3b3814 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Thu, 25 Jun 2020 00:19:40 -0400
Subject: added link preview for blue buttons.
---
src/client/util/DragManager.ts | 2 +-
src/client/views/DocumentButtonBar.tsx | 2 +-
src/client/views/MainView.tsx | 4 +
src/client/views/nodes/DocumentLinksButton.scss | 28 ++-----
src/client/views/nodes/DocumentLinksButton.tsx | 15 +++-
src/client/views/nodes/DocumentView.tsx | 10 ++-
src/client/views/nodes/LinkAnchorBox.tsx | 8 ++
src/client/views/nodes/LinkDocPreview.tsx | 107 ++++++++++++++++++++++++
8 files changed, 148 insertions(+), 28 deletions(-)
create mode 100644 src/client/views/nodes/LinkDocPreview.tsx
(limited to 'src')
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 91bc51101..417ddf989 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -353,7 +353,7 @@ export namespace DragManager {
const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement;
const rect = ele.getBoundingClientRect();
const scaleX = rect.width / ele.offsetWidth,
- scaleY = rect.height / ele.offsetHeight;
+ scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX;
elesCont.left = Math.min(rect.left, elesCont.left);
elesCont.top = Math.min(rect.top, elesCont.top);
elesCont.right = Math.max(rect.right, elesCont.right);
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 8cd1b650e..106b7163e 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -248,7 +248,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
get linkButton() {
const view0 = this.view0;
const linkCount = view0 && DocListCast(view0.props.Document.links).length;
- return !view0 || linkCount ? (null) :
+ return !view0 ? (null) :
{DocumentLinksButton.EditLink ?
: (null)}
+ {LinkDocPreview.LinkInfo ?
: (null)}
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index b4c59b91c..79364ab8e 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -1,21 +1,9 @@
@import "../globalCssVariables.scss";
-.documentLinksButton-button-empty:hover {
- background: $main-accent;
- transform: scale(1.05);
- cursor: pointer;
-}
-
-.documentLinksButton-button-nonempty:hover {
- background: $main-accent;
- transform: scale(1.05);
- cursor: pointer;
-}
-
-.documentLinksButton-button,
-.documentLinksButton-button-empty,
-.documentLinksButton-button-nonempty {
+.documentLinksButton,
+.documentLinksButton-endLink,
+.documentLinksButton-startLink {
height: 20px;
width: 20px;
left: -15px;
@@ -34,18 +22,18 @@
align-items: center;
&:hover {
- background: $main-accent;
+ background: deepskyblue;
transform: scale(1.05);
- cursor: pointer;
+ cursor: default;
}
}
-.documentLinksButton-button-nonempty {
+.documentLinksButton {
background-color: $link-color;
}
-.documentLinksButton-button-empty {
+.documentLinksButton-endLink {
border: red solid 2px;
}
-.documentLinksButton-button {
+.documentLinksButton-startLink {
border: red solid 2px;
background-color: rgba(255, 192, 203, 0.5);
}
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index c9083a65f..fc314ae8b 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -9,6 +9,7 @@ import { DocumentView } from "./DocumentView";
import React = require("react");
import { DocUtils } from "../../documents/Documents";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { LinkDocPreview } from "./LinkDocPreview";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -80,11 +81,19 @@ export class DocumentLinksButton extends React.Component
-
+
LinkDocPreview.LinkInfo = undefined)}
+ onPointerEnter={action(e => LinkDocPreview.LinkInfo = {
+ addDocTab: this.props.View.props.addDocTab,
+ linkSrc: this.props.View.props.Document,
+ linkDoc: links[0],
+ Location: [e.clientX, e.clientY + 20]
+ })} >
{links.length ? links.length : }
- {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
: (null)}
- {DocumentLinksButton.StartLink === this.props.View ?
: (null)}
+ {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
: (null)}
+ {DocumentLinksButton.StartLink === this.props.View ?
: (null)}
;
}
render() {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 20a606937..4cb08bab3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1047,7 +1047,7 @@ export class DocumentView extends DocComponent(Docu
onClick={this.onClickHandler}
layoutKey={this.finalLayoutKey} />
{this.layoutDoc.showLinks ? this.anchors : (null)}
- {this.props.forcedBackgroundColor?.(this.Document) === "transparent" ? (null) : }
+ {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : }
);
}
@@ -1071,7 +1071,7 @@ export class DocumentView extends DocComponent
(Docu
anchorPanelHeight = () => this.props.PanelHeight() || 1;
@computed get anchors() {
TraceMobx();
- return this.layoutDoc.presBox ? (null) : DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) =>
+ return this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.layoutDoc.presBox || this.props.dontRegisterView ? (null) : DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) =>
(Docu
PanelWidth={this.anchorPanelWidth}
PanelHeight={this.anchorPanelHeight}
ContentScaling={returnOne}
+ dontRegisterView={false}
forcedBackgroundColor={returnTransparent}
removeDocument={this.hideLinkAnchor}
pointerEvents={false}
@@ -1202,7 +1203,10 @@ export class DocumentView extends DocComponent(Docu
color: StrCast(this.layoutDoc.color, "inherit"),
outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px",
border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined,
- boxShadow: this.Document.isLinkButton ? StrCast(this.props.Document._linkButtonShadow, "lightblue 0em 0em 1em") : this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined,
+ boxShadow: this.Document.isLinkButton && !this.props.dontRegisterView && this.props.forcedBackgroundColor?.(this.Document) !== "transparent" ?
+ StrCast(this.props.Document._linkButtonShadow, "lightblue 0em 0em 1em") :
+ this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" :
+ undefined,
background: finalColor,
opacity: finalOpacity,
fontFamily: StrCast(this.Document._fontFamily, "inherit"),
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 2b64cdab6..2bcc6168b 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -18,6 +18,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { SelectionManager } from "../../util/SelectionManager";
import { TraceMobx } from "../../../fields/util";
import { Id } from "../../../fields/FieldSymbols";
+import { LinkDocPreview } from "./LinkDocPreview";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -132,6 +133,13 @@ export class LinkAnchorBox extends ViewBoxBaseComponent LinkDocPreview.LinkInfo = undefined)}
+ onPointerEnter={action(e => LinkDocPreview.LinkInfo = {
+ addDocTab: this.props.addDocTab,
+ linkSrc: this.props.ContainingCollectionDoc!,
+ linkDoc: this.rootDoc,
+ Location: [e.clientX, e.clientY + 20]
+ })}
onPointerDown={this.onPointerDown} onClick={this.onClick} title={targetTitle} onContextMenu={this.specificContextMenu}
ref={this._ref} style={{
background: c,
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
new file mode 100644
index 000000000..126dc240a
--- /dev/null
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -0,0 +1,107 @@
+import { action, computed, observable, runInAction } from 'mobx';
+import { observer } from "mobx-react";
+import wiki from "wikijs";
+import { Doc, DocCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { Cast, FieldValue, NumCast } from "../../../fields/Types";
+import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../Utils";
+import { Docs } from "../../documents/Documents";
+import { DocumentManager } from "../../util/DocumentManager";
+import { Transform } from "../../util/Transform";
+import { ContentFittingDocumentView } from "./ContentFittingDocumentView";
+import React = require("react");
+import { DocumentView } from './DocumentView';
+
+interface Props {
+ linkDoc?: Doc;
+ linkSrc?: Doc;
+ href?: string;
+ backgroundColor: (doc: Doc) => string;
+ addDocTab: (document: Doc, where: string) => boolean;
+ location: number[];
+}
+@observer
+export class LinkDocPreview extends React.Component {
+ @observable public static LinkInfo: Opt<{ linkDoc?: Doc; addDocTab: (document: Doc, where: string) => boolean, linkSrc: Doc; href?: string; Location: number[] }>;
+ @observable _targetDoc: Opt;
+ @observable _toolTipText = "";
+
+ componentDidUpdate() { this.updatePreview() }
+ componentDidMount() { this.updatePreview() }
+ async updatePreview() {
+ const linkDoc = this.props.linkDoc;
+ const linkSrc = this.props.linkSrc;
+ if (this.props.href) {
+ if (this.props.href.startsWith("https://en.wikipedia.org/wiki/")) {
+ wiki().page(this.props.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500))));
+ } else {
+ runInAction(() => this._toolTipText = "external => " + this.props.href);
+ }
+ } else if (linkDoc && linkSrc) {
+ const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), linkSrc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc);
+ const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor;
+ runInAction(() => {
+ this._toolTipText = "";
+ this._targetDoc = target;
+ if (anchor !== this._targetDoc && anchor && this._targetDoc) {
+ this._targetDoc._scrollY = NumCast(anchor?.y);
+ }
+ });
+ }
+ }
+ pointerDown = (e: React.PointerEvent) => {
+ if (this.props.linkDoc && this.props.linkSrc) {
+ DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.linkSrc,
+ (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation));
+ } else if (this.props.href) {
+ this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, UseCors: true }), "onRight");
+ }
+ }
+ width = () => Math.min(350, NumCast(this._targetDoc?.[WidthSym](), 350));
+ height = () => Math.min(350, NumCast(this._targetDoc?.[HeightSym](), 350));
+ @computed get targetDocView() {
+ return !this._targetDoc ?
+
+
+ {this._toolTipText}
+
+
:
+ ;
+ }
+
+ render() {
+ return
+ {this.targetDocView}
+
;
+ }
+}
\ No newline at end of file
--
cgit v1.2.3-70-g09d2
From c692276b6c6909d6cf32b620eb69b114057662ca Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Thu, 25 Jun 2020 00:57:56 -0400
Subject: cleaned up DoucmentButtonBar to use DocumentLinksButton
---
src/client/views/DocumentButtonBar.tsx | 62 ++-----------------------
src/client/views/nodes/DocumentLinksButton.scss | 1 -
src/client/views/nodes/DocumentLinksButton.tsx | 3 +-
src/client/views/nodes/DocumentView.tsx | 2 +-
4 files changed, 6 insertions(+), 62 deletions(-)
(limited to 'src')
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 106b7163e..49c15f764 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -113,48 +113,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
get view0() { return this.props.views()?.[0]; }
- @action
- onLinkButtonMoved = (e: PointerEvent) => {
- if (this._linkButton.current !== null) {
- const linkDrag = UndoManager.StartBatch("Drag Link");
- this.view0 && DragManager.StartLinkDrag(this._linkButton.current, this.view0.props.Document, e.pageX, e.pageY, {
- dragComplete: dropEv => {
- const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
- if (this.view0 && linkDoc) {
- !linkDoc.linkRelationship && (Doc.GetProto(linkDoc).linkRelationship = "hyperlink");
-
- // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks)
- // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures
- // however, the dropped document isn't so accessible. What we do is set the newly created link document on the documentView
- // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it.
- dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData);
- runInAction(() => this.view0!._link = linkDoc);
- setTimeout(action(() => this.view0!._link = undefined), 0);
- }
- linkDrag?.end();
- },
- hideSource: false
- });
- return true;
- }
- return false;
- }
-
-
- onLinkButtonDown = (e: React.PointerEvent): void => {
- setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, (e, doubleTap) => {
- if (doubleTap) {
- if (!DocumentLinksButton.StartLink) {
- runInAction(() => DocumentLinksButton.StartLink = this.view0);
- } else {
- DocumentLinksButton.StartLink !== this.view0 && this.view0 &&
- DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.view0.props.Document }, "long drag");
- }
- }
- });
- }
-
-
@computed
get considerGoogleDocsPush() {
const targetDoc = this.view0?.props.Document;
@@ -244,22 +202,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
;
}
- @computed
- get linkButton() {
- const view0 = this.view0;
- const linkCount = view0 && DocListCast(view0.props.Document.links).length;
- return !view0 ? (null) :
-
-
-
- {linkCount ? linkCount : }
-
-
-
;
- }
-
@computed
get metadataButton() {
const view0 = this.view0;
@@ -328,7 +270,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
const considerPull = isText && this.considerGoogleDocsPull;
const considerPush = isText && this.considerGoogleDocsPush;
return
- {this.linkButton}
+
+
+
{this.templateButton}
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index 79364ab8e..484f8c469 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -6,7 +6,6 @@
.documentLinksButton-startLink {
height: 20px;
width: 20px;
- left: -15px;
position: absolute;
border-radius: 50%;
opacity: 0.9;
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index fc314ae8b..ef900fff6 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -16,6 +16,7 @@ export const Flyout = higflyout.default;
interface DocumentLinksButtonProps {
View: DocumentView;
+ Offset?: number[];
}
@observer
export class DocumentLinksButton extends React.Component
{
@@ -80,7 +81,7 @@ export class DocumentLinksButton extends React.Component
+
LinkDocPreview.LinkInfo = undefined)}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4cb08bab3..8f139e39e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1047,7 +1047,7 @@ export class DocumentView extends DocComponent(Docu
onClick={this.onClickHandler}
layoutKey={this.finalLayoutKey} />
{this.layoutDoc.showLinks ? this.anchors : (null)}
- {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : }
+ {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : }
);
}
--
cgit v1.2.3-70-g09d2
From e10165da06f042bc6ee2318439d8d75103f82647 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Thu, 25 Jun 2020 11:33:11 -0400
Subject: fixed selection of filled ink regions. moved ink halo to mainView
---
src/client/util/InteractionUtils.tsx | 3 +--
src/client/views/InkingStroke.tsx | 18 +---------------
src/client/views/MainView.tsx | 24 ++++++++++++++++++++++
src/client/views/nodes/KeyValueBox.tsx | 2 +-
.../views/nodes/formattedText/FormattedTextBox.tsx | 2 +-
5 files changed, 28 insertions(+), 21 deletions(-)
(limited to 'src')
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 64facaca4..c38c9b9c2 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -1,7 +1,6 @@
import React = require("react");
import * as beziercurve from 'bezier-curve';
import * as fitCurve from 'fit-curve';
-import InkOptionsMenu from "../views/collections/collectionFreeForm/InkOptionsMenu";
import "./InteractionUtils.scss";
import { Utils } from "../../Utils";
@@ -136,7 +135,7 @@ export namespace InteractionUtils {
5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15),
StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), StrCast(this.layoutDoc.fillColor, ActiveFillColor()),
- "none", "none", "0", scaleX, scaleY, "", this.props.active() ? "visiblestroke" : "none", false, true);
+ "none", "none", "0", scaleX, scaleY, "", this.props.active() ? "visiblepainted" : "none", false, true);
return (
;
}
+ @computed get inkResources() {
+ return ;
+ }
+
render() {
return (
+ {this.inkResources}
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 4442ee2eb..d375466c9 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -147,7 +147,7 @@ export class KeyValueBox extends React.Component
{
{ this._valInput.current!.select(); e.stopPropagation(); }} style={{ width: `${this.splitPercentage}%` }}>
|
-
+ ;
}
@action
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c23ecb8ac..91168b41c 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1232,7 +1232,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
setTimeout(() => FormattedTextBoxComment.Hide(), 0);
}
const selPad = this.props.isSelected() ? -10 : 0;
- const selclass = this.props.isSelected() ? "-selected" : ""
+ const selclass = this.props.isSelected() ? "-selected" : "";
return (
Date: Thu, 25 Jun 2020 12:23:42 -0400
Subject: fixed blue button visibility for document decoration button bar
---
src/client/views/DocumentButtonBar.tsx | 2 +-
src/client/views/nodes/DocumentLinksButton.tsx | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 49c15f764..fcaea0f0b 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -271,7 +271,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
const considerPush = isText && this.considerGoogleDocsPush;
return
-
+
{this.templateButton}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index ef900fff6..f35b48ce4 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -17,6 +17,7 @@ export const Flyout = higflyout.default;
interface DocumentLinksButtonProps {
View: DocumentView;
Offset?: number[];
+ AlwaysOn?: boolean;
}
@observer
export class DocumentLinksButton extends React.Component
{
@@ -80,7 +81,7 @@ export class DocumentLinksButton extends React.Component
Date: Thu, 25 Jun 2020 14:29:27 -0400
Subject: fixed linkicon dragging feedback
---
src/client/views/nodes/DocumentLinksButton.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
(limited to 'src')
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index f35b48ce4..4f4f12521 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -82,16 +82,16 @@ export class DocumentLinksButton extends React.Component
+
LinkDocPreview.LinkInfo = undefined)}
- onPointerEnter={action(e => LinkDocPreview.LinkInfo = {
+ onPointerEnter={action(e => links.length && (LinkDocPreview.LinkInfo = {
addDocTab: this.props.View.props.addDocTab,
linkSrc: this.props.View.props.Document,
linkDoc: links[0],
Location: [e.clientX, e.clientY + 20]
- })} >
+ }))} >
{links.length ? links.length : }
{DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
: (null)}
--
cgit v1.2.3-70-g09d2
From 29dc4667206b58bca76f28d39fa8c4b0db040d66 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Thu, 25 Jun 2020 14:52:26 -0400
Subject: fixed drag and drop of text onto a text box from creating new
documents
---
src/client/views/nodes/formattedText/FormattedTextBox.tsx | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index cdf231985..9eaf27b42 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1193,6 +1193,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
+ ondrop = (eve: React.DragEvent) => {
+ eve.stopPropagation(); // drag n drop of text within text note will generate a new note if not caughst, as will dragging in from outside of Dash.
+ }
onscrolled = (ev: React.UIEvent) => {
this.layoutDoc._scrollTop = this._scrollRef.current!.scrollTop;
}
@@ -1281,7 +1284,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
})}
>
-
+
Date: Thu, 25 Jun 2020 19:19:50 -0400
Subject: fixed copying/ pasting of PDF quotes to generate blockquotes.
---
src/client/views/GlobalKeyHandler.ts | 4 ++--
.../views/nodes/formattedText/FormattedTextBox.tsx | 18 ++++++++++--------
.../nodes/formattedText/FormattedTextBoxComment.tsx | 7 ++++---
src/client/views/nodes/formattedText/marks_rts.ts | 2 +-
src/client/views/pdf/PDFMenu.tsx | 1 +
5 files changed, 18 insertions(+), 14 deletions(-)
(limited to 'src')
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 7bc8cf6a7..e3546dece 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -15,11 +15,11 @@ import { SelectionManager } from "../util/SelectionManager";
import SharingManager from "../util/SharingManager";
import { undoBatch, UndoManager } from "../util/UndoManager";
import { CollectionDockingView } from "./collections/CollectionDockingView";
-import { MarqueeView } from "./collections/collectionFreeForm/MarqueeView";
import { DocumentDecorations } from "./DocumentDecorations";
import { MainView } from "./MainView";
import { DocumentView } from "./nodes/DocumentView";
import { DocumentLinksButton } from "./nodes/DocumentLinksButton";
+import PDFMenu from "./pdf/PDFMenu";
const modifiers = ["control", "meta", "shift", "alt"];
type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise
;
@@ -264,7 +264,7 @@ export default class KeyManager {
}
break;
case "c":
- if (DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
+ if (!PDFMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
const bds = DocumentDecorations.Instance.Bounds;
const pt = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":");
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 9eaf27b42..61668f84a 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -857,8 +857,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => {
const cbe = event as ClipboardEvent;
- const pdfDocId = cbe.clipboardData && cbe.clipboardData.getData("dash/pdfOrigin");
- const pdfRegionId = cbe.clipboardData && cbe.clipboardData.getData("dash/pdfRegion");
+ const pdfDocId = cbe.clipboardData?.getData("dash/pdfOrigin");
+ const pdfRegionId = cbe.clipboardData?.getData("dash/pdfRegion");
if (pdfDocId && pdfRegionId) {
DocServer.GetRefField(pdfDocId).then(pdfDoc => {
DocServer.GetRefField(pdfRegionId).then(pdfRegion => {
@@ -873,9 +873,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if (link) {
cbe.clipboardData!.setData("dash/linkDoc", link[Id]);
const linkId = link[Id];
- const frag = addMarkToFrag(slice.content, (node: Node) => addLinkMark(node, StrCast(pdfDoc.title), linkId));
- slice = new Slice(frag, slice.openStart, slice.openEnd);
- const tr = view.state.tr.replaceSelection(slice);
+ const quote = view.state.schema.nodes.blockquote.create();
+ quote.content = addMarkToFrag(slice.content, (node: Node) => addLinkMark(node, StrCast(pdfDoc.title), linkId));
+ slice = new Slice(Fragment.from(quote), slice.openStart, slice.openEnd);
+ const tr = view.state.tr.replaceSelection(slice)
view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste"));
}
}
@@ -898,7 +899,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
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: Utils.prepend(`/doc/${linkId}`), location: "onRight", title: title, docref: true });
+ const allHrefs = [{ href: Utils.prepend(`/doc/${linkId}`), title, linkId }];
+ const link = view.state.schema.mark(view.state.schema.marks.link, { allHrefs, location: "onRight", title, docref: true });
marks.splice(linkIndex === -1 ? 0 : linkIndex, 1, link);
return node.mark(marks);
}
@@ -933,7 +935,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
clipboardTextSerializer: this.clipboardTextSerializer,
handlePaste: this.handlePaste,
});
- //applyDevTools.applyDevTools(this._editorView);
+ applyDevTools.applyDevTools(this._editorView);
const startupText = !rtfField && this._editorView && Field.toString(this.dataDoc[fieldKey] as Field);
if (startupText) {
const { state: { tr }, dispatch } = this._editorView;
@@ -1013,7 +1015,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const editor = this._editorView!;
FormattedTextBoxComment.textBox = this;
const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
- const node = pcords && editor.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text)
+ const node = pcords && editor.state.doc.resolve(pcords.pos).node();// editor.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text)
!this.props.isSelected(true) && editor.dispatch(editor.state.tr.setSelection(node && pcords ?
new NodeSelection(editor.state.doc.resolve(pcords.pos)) : new TextSelection(editor.state.doc.resolve(pcords?.pos || 0))));
FormattedTextBoxComment.update(editor, undefined, (e.target as any)?.className === "prosemirror-dropdownlink" ? (e.target as any).href : "");
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 0d8e22251..90f2c0aa6 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -177,11 +177,12 @@ export class FormattedTextBoxComment {
// this checks if the selection is a hyperlink. If so, it displays the target doc's text for internal links, and the url of the target for external links.
if (set === "none" && state.selection.$from) {
nbef = findStartOfMark(state.selection.$from, view, findLinkMark);
- const naft = findEndOfMark(state.selection.$from, view, findLinkMark);
+ const naft = findEndOfMark(state.selection.$from, view, findLinkMark) || nbef;
let child: any = null;
state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node));
- const mark = child && findLinkMark(child.marks);
- const href = mark?.attrs.allHrefs.find((item: { href: string }) => item.href)?.href || forceUrl;
+ child = child || (nbef && state.selection.$from.nodeBefore);
+ const mark = child ? findLinkMark(child.marks) : undefined;
+ const href = (!mark?.attrs.docref || naft === nbef) && mark?.attrs.allHrefs.find((item: { href: string }) => item.href)?.href || forceUrl;
if (forceUrl || (href && child && nbef && naft && mark?.attrs.showPreview)) {
FormattedTextBoxComment.tooltipText.textContent = "external => " + href;
(FormattedTextBoxComment.tooltipText as any).href = href;
diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts
index 1de211f28..b09ac0678 100644
--- a/src/client/views/nodes/formattedText/marks_rts.ts
+++ b/src/client/views/nodes/formattedText/marks_rts.ts
@@ -38,7 +38,7 @@ export const marks: { [index: string]: MarkSpec } = {
const targetids = node.attrs.allHrefs.reduce((p: string, item: { href: string, title: string, targetId: string, linkId: string }) => p + " " + item.targetId, "");
const linkids = node.attrs.allHrefs.reduce((p: string, item: { href: string, title: string, targetId: string, linkId: string }) => p + " " + item.linkId, "");
return node.attrs.docref && node.attrs.title ?
- ["div", ["span", `"`], ["span", 0], ["span", `"`], ["br"], ["a", { ...node.attrs, class: "prosemirror-attribution", title: `${node.attrs.title}` }, node.attrs.title], ["br"]] :
+ ["div", ["span", `"`], ["span", 0], ["span", `"`], ["br"], ["a", { ...node.attrs, href: node.attrs.allHrefs[0].href, class: "prosemirror-attribution" }, node.attrs.title], ["br"]] :
node.attrs.allHrefs.length === 1 ?
["a", { ...node.attrs, class: linkids, targetids, title: `${node.attrs.title}`, href: node.attrs.allHrefs[0].href }, 0] :
["div", { class: "prosemirror-anchor" },
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index a641bce67..6dcf5cce6 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -26,6 +26,7 @@ export default class PDFMenu extends AntimodeMenu {
public AddTag: (key: string, value: string) => boolean = returnFalse;
public PinToPres: () => void = unimplementedFunction;
public Marquee: { left: number; top: number; width: number; height: number; } | undefined;
+ public get Active() { return this._opacity ? true : false; }
constructor(props: Readonly<{}>) {
super(props);
--
cgit v1.2.3-70-g09d2
From 1a129f670e9086fc6fa5926b60671430f4813c3a Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Thu, 25 Jun 2020 19:23:48 -0400
Subject: from last
---
src/client/views/nodes/formattedText/FormattedTextBox.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 61668f84a..25878bda2 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1015,7 +1015,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const editor = this._editorView!;
FormattedTextBoxComment.textBox = this;
const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
- const node = pcords && editor.state.doc.resolve(pcords.pos).node();// editor.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text)
+ const node = pcords && editor.state.doc.resolve(pcords.pos).node();// bcz: changed so that clicking on the attribution of a PDF pasted link will trigger. editor.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text)
!this.props.isSelected(true) && editor.dispatch(editor.state.tr.setSelection(node && pcords ?
new NodeSelection(editor.state.doc.resolve(pcords.pos)) : new TextSelection(editor.state.doc.resolve(pcords?.pos || 0))));
FormattedTextBoxComment.update(editor, undefined, (e.target as any)?.className === "prosemirror-dropdownlink" ? (e.target as any).href : "");
--
cgit v1.2.3-70-g09d2
From 9d92f68750c943d82baa99dc26c29cdd58417e56 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Thu, 25 Jun 2020 21:35:10 -0400
Subject: fixed loading of pdf annotations. fixed copy pasting of pdf excerpts
---
.../collectionFreeForm/CollectionFreeFormView.tsx | 4 +--
src/client/views/pdf/Annotation.tsx | 5 ++--
src/client/views/pdf/PDFViewer.tsx | 35 ++++++++--------------
3 files changed, 17 insertions(+), 27 deletions(-)
(limited to 'src')
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 936174b52..6632291c2 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1383,9 +1383,7 @@ export class CollectionFreeFormView extends CollectionSubView {
- e.preventDefault();
- }}
+ onDragOver={e => e.preventDefault()}
onContextMenu={this.onContextMenu}
style={{
pointerEvents: this.backgroundEvents ? "all" : undefined,
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index cb6a15f36..d29b638e6 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -8,7 +8,6 @@ import { Cast, FieldValue, NumCast, StrCast } from "../../../fields/Types";
import { DocumentManager } from "../../util/DocumentManager";
import PDFMenu from "./PDFMenu";
import "./Annotation.scss";
-import { DocumentView } from "../nodes/DocumentView";
interface IAnnotationProps {
anno: Doc;
@@ -19,7 +18,9 @@ interface IAnnotationProps {
fieldKey: string;
}
-export default class Annotation extends React.Component {
+@observer
+export default
+ class Annotation extends React.Component {
render() {
return DocListCast(this.props.anno.annotations).map(a => (
));
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 50ffd57fe..91d0feafe 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -80,7 +80,6 @@ interface IViewerProps {
export class PDFViewer extends ViewBoxAnnotatableComponent(PdfDocument) {
static _annotationStyle: any = addStyleSheet();
@observable private _pageSizes: { width: number, height: number }[] = [];
- @observable private _annotations: Doc[] = [];
@observable private _savedAnnotations: Dictionary = new Dictionary();
@observable private _script: CompiledScript = CompileScript("return true") as CompiledScript;
@observable private Index: number = -1;
@@ -112,17 +111,14 @@ export class PDFViewer extends ViewBoxAnnotatableComponent this._script.run({ this: anno }, console.log, true).result);
+ return DocListCast(this.dataDoc[this.props.fieldKey + "-annotations"]).
+ filter(anno => this._script.run({ this: anno }, console.log, true).result);
}
+ @computed get nonDocAnnotations() { return this.allAnnotations.filter(a => a.annotations); }
- @computed get nonDocAnnotations() {
- return this._annotations.filter(anno => this._script.run({ this: anno }, console.log, true).result);
- }
-
- _lastSearch: string = "";
componentDidMount = async () => {
// change the address to be the file address of the PNG version of each page
// file address of the pdf
@@ -148,7 +144,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent this._showWaiting = this._showCover = true);
this.props.startupLive && this.setupPdfJsViewer();
- this._mainCont.current!.scrollTop = this.layoutDoc._scrollTop || 0;
+ this._mainCont.current && (this._mainCont.current.scrollTop = this.layoutDoc._scrollTop || 0);
this._searchReactionDisposer = reaction(() => this.Document.searchMatch, search => {
if (search) {
this.search(Doc.SearchQuery(), true);
@@ -231,25 +227,19 @@ export class PDFViewer extends ViewBoxAnnotatableComponent Cast(this.layoutDoc._scrollTop, "number", null),
- (stop) => (stop !== undefined && this.layoutDoc._scrollY === undefined) && (this._mainCont.current!.scrollTop = stop), { fireImmediately: true });
-
- this._annotationReactionDisposer = reaction(
- () => DocListCast(this.dataDoc[this.props.fieldKey + "-annotations"]),
- annotations => annotations?.length && (this._annotations = annotations),
+ (stop) => (stop !== undefined && this.layoutDoc._scrollY === undefined && this._mainCont.current) && (this._mainCont.current.scrollTop = stop),
{ fireImmediately: true });
this._filterReactionDisposer = reaction(
- () => ({ scriptField: Cast(this.Document.filterScript, ScriptField), annos: this._annotations.slice() }),
- action(({ scriptField, annos }: { scriptField: FieldResult, annos: Doc[] }) => {
+ () => Cast(this.Document.filterScript, ScriptField),
+ action(scriptField => {
const oldScript = this._script.originalScript;
- this._script = scriptField && scriptField.script.compiled ? scriptField.script : CompileScript("return true") as CompiledScript;
+ this._script = scriptField?.script.compiled ? scriptField.script : CompileScript("return true") as CompiledScript;
if (this._script.originalScript !== oldScript) {
this.Index = -1;
}
- annos.forEach(d => d.opacity = this._script.run({ this: d }, console.log, 1).result ? 1 : 0);
}),
- { fireImmediately: true }
- );
+ { fireImmediately: true });
this.createPdfViewer();
}
@@ -656,8 +646,9 @@ export class PDFViewer extends ViewBoxAnnotatableComponent
- {this.nonDocAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map((anno, index) =>
- )}
+ {this.nonDocAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno =>
+ )
+ }
;
}
overlayTransform = () => this.scrollXf().scale(1 / this._zoomed);
--
cgit v1.2.3-70-g09d2
From 8d774b6dd81d77294c438bb2951e04cf778dc38e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Fri, 26 Jun 2020 00:40:49 -0400
Subject: fixed highlighting text anchors in text notes. fixed pasting
fragements of PDFs to create back links inside blockquotes.
---
src/client/util/DocumentManager.ts | 8 +++---
src/client/views/PreviewCursor.tsx | 2 ++
.../views/nodes/formattedText/FormattedTextBox.tsx | 31 ++++++++++++++++------
3 files changed, 29 insertions(+), 12 deletions(-)
(limited to 'src')
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 78c05f572..40d6b039a 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -130,7 +130,7 @@ export class DocumentManager {
willZoom: boolean, // whether to zoom doc to take up most of screen
createViewFunc = DocumentManager.addRightSplit, // how to create a view of the doc if it doesn't exist
docContext?: Doc, // context to load that should contain the target
- linkId?: string, // link that's being followed
+ linkDoc?: Doc, // link that's being followed
closeContextIfNotFound: boolean = false, // after opening a context where the document should be, this determines whether the context should be closed if the Doc isn't actually there
originatingDoc: Opt = undefined, // doc that initiated the display of the target odoc
finished?: () => void
@@ -140,7 +140,7 @@ export class DocumentManager {
const highlight = () => {
const finalDocView = getFirstDocView(targetDoc);
if (finalDocView) {
- finalDocView.layoutDoc.scrollToLinkID = linkId;
+ finalDocView.layoutDoc.scrollToLinkID = linkDoc?.[Id];
Doc.linkFollowHighlight(finalDocView.props.Document);
}
};
@@ -195,7 +195,7 @@ export class DocumentManager {
const finalDocView = getFirstDocView(targetDoc);
const finalDocContextView = getFirstDocView(targetDocContext);
setTimeout(() => // if not, wait a bit to see if the context can be loaded (e.g., a PDF). wait interval heurisitic tries to guess how we're animating based on what's just become visible
- this.jumpToDocument(targetDoc, willZoom, createViewFunc, undefined, linkId, true, undefined, finished), // pass true this time for closeContextIfNotFound
+ this.jumpToDocument(targetDoc, willZoom, createViewFunc, undefined, linkDoc, true, undefined, finished), // pass true this time for closeContextIfNotFound
finalDocView ? 0 : finalDocContextView ? 250 : 2000); // so call jump to doc again and if the doc isn't found, it will be created.
}, 0);
}
@@ -224,7 +224,7 @@ export class DocumentManager {
containerDoc.currentTimecode = targetTimecode;
const targetContext = await target?.context as Doc;
const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
- DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "onRight"), finished), targetNavContext, linkDoc[Id], undefined, doc, finished);
+ DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "onRight"), finished), targetNavContext, linkDoc, undefined, doc, finished);
} else {
finished?.();
}
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index e27f6b95a..1ab99881d 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -9,6 +9,7 @@ import { Transform } from "../util/Transform";
import { DocServer } from '../DocServer';
import { undoBatch } from '../util/UndoManager';
import { NumCast } from '../../fields/Types';
+import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
@observer
export class PreviewCursor extends React.Component<{}> {
@@ -81,6 +82,7 @@ export class PreviewCursor extends React.Component<{}> {
e.stopPropagation();
} else {
// creates text document
+ FormattedTextBox.PasteOnLoad = e;
undoBatch(() => PreviewCursor._addLiveTextDoc(Docs.Create.TextDocument("", {
_width: 500,
limitHeight: 400,
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 25878bda2..f96b165fa 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { isEqual } from "lodash";
import { action, computed, IReactionDisposer, Lambda, observable, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { baseKeymap } from "prosemirror-commands";
+import { baseKeymap, selectAll } from "prosemirror-commands";
import { history } from "prosemirror-history";
import { inputRules } from 'prosemirror-inputrules';
import { keymap } from "prosemirror-keymap";
@@ -102,6 +102,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
public static FocusedBox: FormattedTextBox | undefined;
public static SelectOnLoad = "";
+ public static PasteOnLoad: ClipboardEvent | undefined;
public static SelectOnLoadChar = "";
public static IsFragment(html: string) {
return html.indexOf("data-pm-slice") !== -1;
@@ -275,6 +276,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const end = this._editorView.state.doc.nodeSize - 2;
this._editorView.dispatch(this._editorView.state.tr.removeMark(0, end, mark).removeMark(0, end, activeMark));
}
+ if (FormattedTextBox.PasteOnLoad) {
+ const pdfDocId = FormattedTextBox.PasteOnLoad.clipboardData?.getData("dash/pdfOrigin");
+ const pdfRegionId = FormattedTextBox.PasteOnLoad.clipboardData?.getData("dash/pdfRegion");
+ FormattedTextBox.PasteOnLoad = undefined;
+ setTimeout(() => pdfDocId && pdfRegionId && this.addPdfReference(pdfDocId, pdfRegionId, undefined), 10);
+ }
}
adoptAnnotation = (start: number, end: number, mark: Mark) => {
const view = this._editorView!;
@@ -726,7 +733,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
const marks = [...node.marks];
const linkIndex = marks.findIndex(mark => mark.type === editor.state.schema.marks.link);
- return linkIndex !== -1 && marks[linkIndex].attrs.allRefs.find((item: { href: string }) => scrollToLinkID === item.href.replace(/.*\/doc\//, "")) ? node : undefined;
+ return linkIndex !== -1 && marks[linkIndex].attrs.allHrefs.find((item: { href: string }) => scrollToLinkID === item.href.replace(/.*\/doc\//, "")) ? node : undefined;
};
let start = 0;
@@ -859,6 +866,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const cbe = event as ClipboardEvent;
const pdfDocId = cbe.clipboardData?.getData("dash/pdfOrigin");
const pdfRegionId = cbe.clipboardData?.getData("dash/pdfRegion");
+ return pdfDocId && pdfRegionId && this.addPdfReference(pdfDocId, pdfRegionId, slice) ? true : false;
+ }
+
+ addPdfReference = (pdfDocId: string, pdfRegionId: string, slice?: Slice) => {
+ const view = this._editorView!;
if (pdfDocId && pdfRegionId) {
DocServer.GetRefField(pdfDocId).then(pdfDoc => {
DocServer.GetRefField(pdfRegionId).then(pdfRegion => {
@@ -871,13 +883,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const link = DocUtils.MakeLink({ doc: this.rootDoc }, { doc: pdfRegion }, "PDF pasted");
if (link) {
- cbe.clipboardData!.setData("dash/linkDoc", link[Id]);
const linkId = link[Id];
const quote = view.state.schema.nodes.blockquote.create();
- quote.content = addMarkToFrag(slice.content, (node: Node) => addLinkMark(node, StrCast(pdfDoc.title), linkId));
- slice = new Slice(Fragment.from(quote), slice.openStart, slice.openEnd);
- const tr = view.state.tr.replaceSelection(slice)
- view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste"));
+ quote.content = addMarkToFrag(slice?.content || view.state.doc.content, (node: Node) => addLinkMark(node, StrCast(pdfDoc.title), linkId));
+ const newSlice = new Slice(Fragment.from(quote), slice?.openStart || 0, slice?.openEnd || 0);
+ if (slice) {
+ view.dispatch(view.state.tr.replaceSelection(newSlice).scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste"));
+ } else {
+ selectAll(view.state, (tx: Transaction) => view.dispatch(tx.replaceSelection(newSlice).scrollIntoView()));
+
+ }
}
}
});
@@ -1015,7 +1030,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const editor = this._editorView!;
FormattedTextBoxComment.textBox = this;
const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
- const node = pcords && editor.state.doc.resolve(pcords.pos).node();// bcz: changed so that clicking on the attribution of a PDF pasted link will trigger. editor.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text)
+ const node = pcords && editor.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text)
!this.props.isSelected(true) && editor.dispatch(editor.state.tr.setSelection(node && pcords ?
new NodeSelection(editor.state.doc.resolve(pcords.pos)) : new TextSelection(editor.state.doc.resolve(pcords?.pos || 0))));
FormattedTextBoxComment.update(editor, undefined, (e.target as any)?.className === "prosemirror-dropdownlink" ? (e.target as any).href : "");
--
cgit v1.2.3-70-g09d2
From 058ab55074b5b3e1d8278d83af39e185acdcde73 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Fri, 26 Jun 2020 00:58:04 -0400
Subject: made dev tools a development mode feature
---
src/client/views/nodes/formattedText/FormattedTextBox.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f96b165fa..0fc8258fc 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -950,7 +950,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
clipboardTextSerializer: this.clipboardTextSerializer,
handlePaste: this.handlePaste,
});
- applyDevTools.applyDevTools(this._editorView);
+ !Doc.UserDoc().noviceMode && applyDevTools.applyDevTools(this._editorView);
const startupText = !rtfField && this._editorView && Field.toString(this.dataDoc[fieldKey] as Field);
if (startupText) {
const { state: { tr }, dispatch } = this._editorView;
--
cgit v1.2.3-70-g09d2
From eaee04b09b9b91587733f2d8554d6176ae2e678d Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Fri, 26 Jun 2020 01:10:12 -0400
Subject: fix to setting text color
---
src/client/views/nodes/ColorBox.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index d6d9a8cfd..137b387c0 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -39,7 +39,7 @@ export class ColorBox extends ViewBoxBaseComponent
Date: Sat, 27 Jun 2020 01:40:00 +0900
Subject: fixed arrow/dot?
---
src/client/util/InteractionUtils.tsx | 11 ++++++-----
.../views/collections/collectionFreeForm/InkOptionsMenu.tsx | 6 +++---
2 files changed, 9 insertions(+), 8 deletions(-)
(limited to 'src')
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index c38c9b9c2..3634fb704 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -121,12 +121,12 @@ export namespace InteractionUtils {
return (