aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/ClientRecommender.tsx54
-rw-r--r--src/client/apis/google_docs/GooglePhotosClientUtils.ts2
-rw-r--r--src/client/cognitive_services/CognitiveServices.ts36
-rw-r--r--src/client/documents/Documents.ts3
-rw-r--r--src/client/util/DragManager.ts4
-rw-r--r--src/client/util/RichTextSchema.tsx20
-rw-r--r--src/client/views/DocumentButtonBar.tsx13
-rw-r--r--src/client/views/DocumentDecorations.tsx2
-rw-r--r--src/client/views/EditableView.tsx22
-rw-r--r--src/client/views/GestureOverlay.tsx8
-rw-r--r--src/client/views/GlobalKeyHandler.ts4
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/RecommendationsBox.tsx16
-rw-r--r--src/client/views/TemplateMenu.tsx8
-rw-r--r--src/client/views/TouchScrollableMenu.tsx4
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx8
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx4
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx3
-rw-r--r--src/client/views/collections/CollectionStaffView.tsx12
-rw-r--r--src/client/views/collections/CollectionSubView.tsx16
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx4
-rw-r--r--src/client/views/collections/CollectionView.tsx8
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx12
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx124
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx54
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx4
-rw-r--r--src/client/views/nodes/ButtonBox.tsx16
-rw-r--r--src/client/views/nodes/ContentFittingDocumentView.tsx2
-rw-r--r--src/client/views/nodes/DocumentBox.scss7
-rw-r--r--src/client/views/nodes/DocumentBox.tsx89
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx28
-rw-r--r--src/client/views/nodes/DocumentView.tsx148
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx29
-rw-r--r--src/client/views/nodes/ImageBox.tsx5
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx2
-rw-r--r--src/client/views/nodes/RadialMenuItem.tsx30
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx2
-rw-r--r--src/client/views/nodes/WebBox.tsx2
-rw-r--r--src/client/views/pdf/PDFMenu.tsx5
-rw-r--r--src/client/views/pdf/PDFViewer.tsx4
-rw-r--r--src/client/views/search/SearchBox.tsx2
-rw-r--r--src/client/views/webcam/DashWebRTCVideo.tsx8
-rw-r--r--src/mobile/MobileInterface.tsx2
-rw-r--r--src/new_fields/Doc.ts27
-rw-r--r--src/new_fields/RichTextUtils.ts4
-rw-r--r--src/new_fields/documentSchemas.ts3
-rw-r--r--src/new_fields/util.ts3
-rw-r--r--src/server/DashSession/Session/agents/applied_session_agent.ts2
-rw-r--r--src/server/DashSession/Session/agents/monitor.ts2
-rw-r--r--src/server/DashSession/Session/agents/promisified_ipc_manager.ts6
-rw-r--r--src/server/Websocket/Websocket.ts8
-rw-r--r--src/server/authentication/models/current_user_utils.ts21
-rw-r--r--src/server/database.ts2
-rw-r--r--src/server/server_Initialization.ts2
56 files changed, 496 insertions, 416 deletions
diff --git a/src/client/ClientRecommender.tsx b/src/client/ClientRecommender.tsx
index 0e67a6e57..537e331ab 100644
--- a/src/client/ClientRecommender.tsx
+++ b/src/client/ClientRecommender.tsx
@@ -69,7 +69,7 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
*/
private distance(vector1: number[], vector2: number[], metric: string = "cosine") {
- assert(vector1.length === vector2.length, "Vectors are not the same length");
+ // assert(vector1.length === vector2.length, "Vectors are not the same length");
let similarity: number;
switch (metric) {
case "cosine":
@@ -113,7 +113,7 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
}
}
);
- let doclist = Array.from(ClientRecommender.Instance.docVectors);
+ const doclist = Array.from(ClientRecommender.Instance.docVectors);
if (distance_metric === "euclidian") {
doclist.sort((a: RecommenderDocument, b: RecommenderDocument) => a.score - b.score);
}
@@ -169,12 +169,12 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
*/
generateMetadata = async (dataDoc: Doc, extDoc: Doc, threshold: Confidence = Confidence.Excellent) => {
- let converter = (results: any) => {
- let tagDoc = new Doc;
- let tagsList = new List();
+ const converter = (results: any) => {
+ const tagDoc = new Doc;
+ const tagsList = new List();
results.tags.map((tag: Tag) => {
tagsList.push(tag.name);
- let sanitized = tag.name.replace(" ", "_");
+ const sanitized = tag.name.replace(" ", "_");
tagDoc[sanitized] = ComputedField.MakeFunction(`(${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`);
});
extDoc.generatedTags = tagsList;
@@ -193,7 +193,7 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
*/
private url(dataDoc: Doc) {
- let data = Cast(Doc.GetProto(dataDoc)[fieldkey], ImageField);
+ const data = Cast(Doc.GetProto(dataDoc)[fieldkey], ImageField);
return data ? data.url.href : undefined;
}
@@ -215,14 +215,14 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
}
}
else {
- let fielddata = Cast(dataDoc.data, RichTextField);
- fielddata ? data = fielddata[ToPlainText]() : data = "";
+ const fielddata = Cast(dataDoc.data, RichTextField, null);
+ data = fielddata?.Text || "";
}
// STEP 2. Upon receiving response from Text Cognitive Services, do additional processing on keywords.
// Currently we are still using Cognitive Services for internal recommendations, but in the future this might not be necessary.
- let converter = async (results: any, data: string, isImage: boolean = false) => {
+ const converter = async (results: any, data: string, isImage: boolean = false) => {
let keyterms = new List<string>(); // raw keywords
let kp_string: string = ""; // keywords*frequency concatenated into a string. input into TF
let highKP: string[] = [""]; // most frequent keyphrase
@@ -237,7 +237,7 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
}
else { // text processing
results.documents.forEach((doc: any) => {
- let keyPhrases = doc.keyPhrases; // returned by Cognitive Services
+ const keyPhrases = doc.keyPhrases; // returned by Cognitive Services
keyPhrases.map((kp: string) => {
keyterms.push(kp);
const frequency = this.countFrequencies(kp, data); // frequency of keyphrase in paragraph
@@ -308,10 +308,10 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
*/
private countFrequencies(keyphrase: string, paragraph: string) {
- let data = paragraph.split(/ |\n/); // splits by new lines and spaces
- let kp_array = keyphrase.split(" ");
- let num_keywords = kp_array.length;
- let par_length = data.length;
+ const data = paragraph.split(/ |\n/); // splits by new lines and spaces
+ const kp_array = keyphrase.split(" ");
+ const num_keywords = kp_array.length;
+ const par_length = data.length;
let frequency = 0;
// slides keyphrase windows across paragraph and checks if it matches with corresponding paragraph slice
for (let i = 0; i <= par_length - num_keywords; i++) {
@@ -353,8 +353,8 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
bingWebSearch = async (query: string) => {
const converter = async (results: any) => {
- let title_vals: string[] = [];
- let url_vals: string[] = [];
+ const title_vals: string[] = [];
+ const url_vals: string[] = [];
results.webPages.value.forEach((doc: any) => {
title_vals.push(doc.name);
url_vals.push(doc.url);
@@ -369,23 +369,23 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
*/
arxivrequest = async (query: string) => {
- let xhttp = new XMLHttpRequest();
- let serveraddress = "http://export.arxiv.org/api";
+ const xhttp = new XMLHttpRequest();
+ const serveraddress = "http://export.arxiv.org/api";
const maxresults = 5;
- let endpoint = serveraddress + "/query?search_query=all:" + query + "&start=0&max_results=" + maxresults.toString();
- let promisified = (resolve: any, reject: any) => {
+ const endpoint = serveraddress + "/query?search_query=all:" + query + "&start=0&max_results=" + maxresults.toString();
+ const promisified = (resolve: any, reject: any) => {
xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
- let result = xhttp.response;
- let xml = xhttp.responseXML;
+ const result = xhttp.response;
+ const xml = xhttp.responseXML;
console.log("arXiv Result: ", xml);
switch (this.status) {
case 200:
- let title_vals: string[] = [];
- let url_vals: string[] = [];
+ const title_vals: string[] = [];
+ const url_vals: string[] = [];
//console.log(result);
if (xml) {
- let titles = xml.getElementsByTagName("title");
+ const titles = xml.getElementsByTagName("title");
let counter = 1;
if (titles && titles.length > 1) {
while (counter <= maxresults) {
@@ -394,7 +394,7 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
counter++;
}
}
- let ids = xml.getElementsByTagName("id");
+ const ids = xml.getElementsByTagName("id");
counter = 1;
if (ids && ids.length > 1) {
while (counter <= maxresults) {
diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
index f8723f02d..7c4137f59 100644
--- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts
+++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
@@ -340,7 +340,7 @@ export namespace GooglePhotos {
const url = data.url.href;
const target = Doc.MakeAlias(source);
const description = parseDescription(target, descriptionKey);
- await DocumentView.makeCustomViewClicked(target, undefined, Docs.Create.FreeformDocument);
+ await DocumentView.makeCustomViewClicked(target, Docs.Create.FreeformDocument);
media.push({ url, description });
}
if (media.length) {
diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts
index 542ccf04d..3f3726621 100644
--- a/src/client/cognitive_services/CognitiveServices.ts
+++ b/src/client/cognitive_services/CognitiveServices.ts
@@ -208,7 +208,7 @@ export namespace CognitiveServices {
results.recognitionUnits && (results = results.recognitionUnits);
}
return results;
- }
+ };
}
export interface AzureStrokeData {
@@ -232,13 +232,13 @@ export namespace CognitiveServices {
return data;
},
requester: async (apiKey: string, query: string) => {
- let xhttp = new XMLHttpRequest();
- let serverAddress = "https://api.cognitive.microsoft.com";
- let endpoint = serverAddress + '/bing/v5.0/search?q=' + encodeURIComponent(query);
- let promisified = (resolve: any, reject: any) => {
+ const xhttp = new XMLHttpRequest();
+ const serverAddress = "https://api.cognitive.microsoft.com";
+ const endpoint = serverAddress + '/bing/v5.0/search?q=' + encodeURIComponent(query);
+ const promisified = (resolve: any, reject: any) => {
xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
- let result = xhttp.responseText;
+ const result = xhttp.responseText;
switch (this.status) {
case 200:
return resolve(result);
@@ -266,7 +266,7 @@ export namespace CognitiveServices {
export namespace Appliers {
export const analyzer = async (query: string, converter: BingConverter) => {
- let results = await ExecuteQuery(Service.Bing, Manager, query);
+ const results = await ExecuteQuery(Service.Bing, Manager, query);
console.log("Bing results: ", results);
const { title_vals, url_vals } = await converter(results);
return { title_vals, url_vals };
@@ -281,13 +281,13 @@ export namespace CognitiveServices {
return data;
},
requester: async (apiKey: string, query: string) => {
- let xhttp = new XMLHttpRequest();
- let serverAddress = "https://babel.hathitrust.org/cgi/htd/​";
- let endpoint = serverAddress + '/bing/v5.0/search?q=' + encodeURIComponent(query);
- let promisified = (resolve: any, reject: any) => {
+ const xhttp = new XMLHttpRequest();
+ const serverAddress = "https://babel.hathitrust.org/cgi/htd/​";
+ const endpoint = serverAddress + '/bing/v5.0/search?q=' + encodeURIComponent(query);
+ const promisified = (resolve: any, reject: any) => {
xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
- let result = xhttp.responseText;
+ const result = xhttp.responseText;
switch (this.status) {
case 200:
return resolve(result);
@@ -315,7 +315,7 @@ export namespace CognitiveServices {
export namespace Appliers {
export const analyzer = async (query: string, converter: BingConverter) => {
- let results = await ExecuteQuery(Service.Bing, Manager, query);
+ const results = await ExecuteQuery(Service.Bing, Manager, query);
console.log("Bing results: ", results);
const { title_vals, url_vals } = await converter(results);
return { title_vals, url_vals };
@@ -337,9 +337,9 @@ export namespace CognitiveServices {
});
},
requester: async (apiKey: string, body: string, service: Service) => {
- let serverAddress = "https://eastus.api.cognitive.microsoft.com";
- let endpoint = serverAddress + "/text/analytics/v2.1/keyPhrases";
- let sampleBody = {
+ const serverAddress = "https://eastus.api.cognitive.microsoft.com";
+ const endpoint = serverAddress + "/text/analytics/v2.1/keyPhrases";
+ const sampleBody = {
"documents": [
{
"language": "en",
@@ -348,7 +348,7 @@ export namespace CognitiveServices {
}
]
};
- let actualBody = body;
+ const actualBody = body;
const options = {
uri: endpoint,
body: actualBody,
@@ -368,7 +368,7 @@ export namespace CognitiveServices {
console.log("vectorizing...");
//keyterms = ["father", "king"];
- let args = { method: 'POST', uri: Utils.prepend("/recommender"), body: { keyphrases: keyterms }, json: true };
+ const args = { method: 'POST', uri: Utils.prepend("/recommender"), body: { keyphrases: keyterms }, json: true };
await requestPromise.post(args).then(async (wordvecs) => {
if (wordvecs) {
const indices = Object.keys(wordvecs);
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index dbea8062e..96425ba30 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -266,7 +266,7 @@ export namespace Docs {
options: { _width: 40, _height: 40, borderRounding: "100%" },
}],
[DocumentType.RECOMMENDATION, {
- layout: { view: RecommendationsBox },
+ layout: { view: RecommendationsBox, dataField: data },
options: { width: 200, height: 200 },
}],
[DocumentType.WEBCAM, {
@@ -365,6 +365,7 @@ export namespace Docs {
const options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) };
options.layout = layout.view.LayoutString(layout.dataField);
const doc = Doc.assign(new Doc(prototypeId, true), { layoutKey: "layout", ...options });
+ doc.layout_keyValue = KeyValueBox.LayoutString("");
return doc;
}
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 63a11c85a..1f2312032 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -137,7 +137,6 @@ export namespace DragManager {
userDropAction: dropActionType;
embedDoc?: boolean;
moveDocument?: MoveFunction;
- applyAsTemplate?: boolean;
isSelectionMove?: boolean; // indicates that an explicitly selected Document is being dragged. this will suppress onDragStart scripts
}
export class LinkDragData {
@@ -148,6 +147,7 @@ export namespace DragManager {
linkSourceDocument: Doc;
dontClearTextBox?: boolean;
linkDocument?: Doc;
+ linkDropCallback?: (data: LinkDragData) => void;
}
export class ColumnDragData {
constructor(colKey: SchemaHeaderField) {
@@ -351,7 +351,7 @@ export namespace DragManager {
const moveHandler = (e: PointerEvent) => {
e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop
if (dragData instanceof DocumentDragData) {
- dragData.userDropAction = e.ctrlKey ? "alias" : undefined;
+ dragData.userDropAction = e.ctrlKey && e.altKey ? "copy" : e.ctrlKey ? "alias" : undefined;
}
if (e.shiftKey && CollectionDockingView.Instance && dragData.droppedDocuments.length === 1) {
AbortDrag();
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index a2fb7c11b..094cd58f3 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -776,7 +776,7 @@ export class DashDocView {
if (dashDocBase instanceof Doc) {
const aliasedDoc = Doc.MakeAlias(dashDocBase, docid + alias);
aliasedDoc.layoutKey = "layout";
- node.attrs.fieldKey && DocumentView.makeCustomViewClicked(aliasedDoc, undefined, Docs.Create.StackingDocument, node.attrs.fieldKey, undefined);
+ node.attrs.fieldKey && DocumentView.makeCustomViewClicked(aliasedDoc, Docs.Create.StackingDocument, node.attrs.fieldKey, undefined);
self.doRender(aliasedDoc, removeDoc, node, view, getPos);
}
});
@@ -810,7 +810,7 @@ export class DashDocView {
this._dashSpan.style.height = this._outer.style.height = Math.max(20, dim[1]) + "px";
this._outer.style.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeWorkspace, Doc, null).darkScheme ? "dimGray" : "lightGray"));
}, { fireImmediately: true });
- let doReactRender = (finalLayout: Doc, resolvedDataDoc: Doc) => {
+ const doReactRender = (finalLayout: Doc, resolvedDataDoc: Doc) => {
ReactDOM.unmountComponentAtNode(this._dashSpan);
ReactDOM.render(<DocumentView
Document={finalLayout}
@@ -844,7 +844,7 @@ export class DashDocView {
console.log(e);
}
}
- }
+ };
this._renderDisposer?.();
this._renderDisposer = reaction(() => {
if (!Doc.AreProtosEqual(finalLayout, dashDoc)) {
@@ -939,7 +939,7 @@ export class DashFieldView {
this._fieldCheck.style.backgroundColor = "rgba(155, 155, 155, 0.24)";
this._fieldCheck.onchange = function (e: any) {
self._dashDoc![self._fieldKey] = e.target.checked;
- }
+ };
this._fieldSpan = document.createElement("div");
this._fieldSpan.id = Utils.GenerateGuid();
@@ -1095,12 +1095,12 @@ export class FootnoteView {
"Mod-y": () => redo(this.outerView.state, this.outerView.dispatch),
"Mod-b": toggleMark(schema.marks.strong)
}),
- new Plugin({
- view(newView) {
- // TODO -- make this work with RichTextMenu
- // return FormattedTextBox.getToolTip(newView);
- }
- })
+ // new Plugin({
+ // view(newView) {
+ // // TODO -- make this work with RichTextMenu
+ // // return FormattedTextBox.getToolTip(newView);
+ // }
+ // })
],
}),
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index e673189f9..b95cc6627 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -4,12 +4,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCast } from "../../new_fields/Doc";
-import { Id } from '../../new_fields/FieldSymbols';
import { RichTextField } from '../../new_fields/RichTextField';
import { NumCast, StrCast } from "../../new_fields/Types";
import { emptyFunction } from "../../Utils";
import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
-import RichTextMenu from '../util/RichTextMenu';
import { UndoManager } from "../util/UndoManager";
import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView';
import { ParentDocSelector } from './collections/ParentDocumentSelector';
@@ -39,7 +37,7 @@ library.add(faCheckCircle);
library.add(faCloudUploadAlt);
library.add(faSyncAlt);
library.add(faShare);
-library.add(faPhotoVideo)
+library.add(faPhotoVideo);
const cloud: IconProp = "cloud-upload-alt";
const fetch: IconProp = "sync-alt";
@@ -121,10 +119,9 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView |
const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
if (this.view0 && linkDoc) {
Doc.GetProto(linkDoc).linkRelationship = "hyperlink";
-
- const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-";
- const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : "";
- const text = RichTextMenu.Instance.MakeLinkToSelection(linkDoc[Id], anchor2Title, e.ctrlKey ? "onRight" : "inTab", anchor2Id);
+ dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData);
+ runInAction(() => this.view0!._link = linkDoc);
+ setTimeout(action(() => this.view0!._link = undefined), 0);
}
linkDrag?.end();
},
@@ -312,7 +309,7 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView |
render() {
if (!this.view0) return (null);
- const isText = this.view0.props.Document.data instanceof RichTextField; // bcz: Todo - can't assume layout is using the 'data' field. need to add fieldKey to DocumentView
+ const isText = this.view0.props.Document[Doc.LayoutFieldKey(this.view0.props.Document)] instanceof RichTextField;
const considerPull = isText && this.considerGoogleDocsPull;
const considerPush = isText && this.considerGoogleDocsPush;
return <div className="documentButtonBar">
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 3e07fd109..79600b7c1 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -266,7 +266,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
let dist = Math.sqrt((e.clientX - down[0]) * (e.clientX - down[0]) + (e.clientY - down[1]) * (e.clientY - down[1]));
dist = dist < 3 ? 0 : dist;
SelectionManager.SelectedDocuments().map(dv => dv.props.Document).map(doc => doc.layout instanceof Doc ? doc.layout : doc.isTemplateForField ? doc : Doc.GetProto(doc)).
- map(d => d.borderRounding = `${Math.max(0, dist)}%`);
+ map(d => d.borderRounding = `${Math.max(0, dist)}px`);
return false;
}
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 4a27425e8..2219966e5 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -4,10 +4,7 @@ import { observer } from 'mobx-react';
import * as Autosuggest from 'react-autosuggest';
import { ObjectField } from '../../new_fields/ObjectField';
import { SchemaHeaderField } from '../../new_fields/SchemaHeaderField';
-import { ContextMenu } from './ContextMenu';
-import { ContextMenuProps } from './ContextMenuItem';
import "./EditableView.scss";
-import { CollectionTreeView } from './collections/CollectionTreeView';
export interface EditableProps {
/**
@@ -88,12 +85,12 @@ export class EditableView extends React.Component<EditableProps> {
onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Tab") {
e.stopPropagation();
- this.finalizeEdit(e.currentTarget.value, e.shiftKey);
+ this.finalizeEdit(e.currentTarget.value, e.shiftKey, false);
this.props.OnTab && this.props.OnTab(e.shiftKey);
} else if (e.key === "Enter") {
e.stopPropagation();
if (!e.ctrlKey) {
- this.finalizeEdit(e.currentTarget.value, e.shiftKey);
+ this.finalizeEdit(e.currentTarget.value, e.shiftKey, false);
} else if (this.props.OnFillDown) {
this.props.OnFillDown(e.currentTarget.value);
this._editing = false;
@@ -123,10 +120,17 @@ export class EditableView extends React.Component<EditableProps> {
}
@action
- private finalizeEdit(value: string, shiftDown: boolean) {
- this._editing = false;
+ private finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean) {
if (this.props.SetValue(value, shiftDown)) {
+ this._editing = false;
+ this.props.isEditingCallback?.(false);
+ } else {
+ this._editing = false;
this.props.isEditingCallback?.(false);
+ !lostFocus && setTimeout(action(() => {
+ this._editing = true;
+ this.props.isEditingCallback?.(true);
+ }), 0);
}
}
@@ -151,7 +155,7 @@ export class EditableView extends React.Component<EditableProps> {
className: "editableView-input",
onKeyDown: this.onKeyDown,
autoFocus: true,
- onBlur: e => this.finalizeEdit(e.currentTarget.value, false),
+ onBlur: e => this.finalizeEdit(e.currentTarget.value, false, true),
onPointerDown: this.stopPropagation,
onClick: this.stopPropagation,
onPointerUp: this.stopPropagation,
@@ -163,7 +167,7 @@ export class EditableView extends React.Component<EditableProps> {
defaultValue={this.props.GetValue()}
onKeyDown={this.onKeyDown}
autoFocus={true}
- onBlur={e => this.finalizeEdit(e.currentTarget.value, false)}
+ onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true)}
onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation}
style={{ display: this.props.display, fontSize: this.props.fontSize }}
/>;
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 1eff58948..ea60907f6 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -165,7 +165,7 @@ export default class GestureOverlay extends Touchable {
this._holdTimer = setTimeout(() => {
console.log("hold");
const target = document.elementFromPoint(te.changedTouches.item(0).clientX, te.changedTouches.item(0).clientY);
- let pt: any = te.touches[te.touches.length - 1];
+ const pt: any = te.touches[te.touches.length - 1];
if (nts.nt.length === 1 && pt.radiusX > 1 && pt.radiusY > 1) {
target?.dispatchEvent(
new CustomEvent<InteractionUtils.MultiTouchEvent<React.TouchEvent>>("dashOnTouchHoldStart",
@@ -589,7 +589,7 @@ export default class GestureOverlay extends Touchable {
for (const wR of wordResults) {
console.log(wR);
if (wR?.recognizedText) {
- possibilities.push(wR?.recognizedText)
+ possibilities.push(wR?.recognizedText);
}
possibilities.push(...wR?.alternates?.map((a: any) => a.recognizedString));
}
@@ -743,16 +743,16 @@ export default class GestureOverlay extends Touchable {
{this.elements}
<div className="clipboardDoc-cont" style={{
- transform: `translate(${this._thumbX}px, ${(this._thumbY ?? 0) - this.height}px)`,
height: this.height,
width: this.height,
pointerEvents: this._clipboardDoc ? "unset" : "none",
touchAction: this._clipboardDoc ? "unset" : "none",
+ transform: `translate(${this._thumbX}px, ${(this._thumbY || 0) - this.height} px)`,
}}>
{this._clipboardDoc}
</div>
<div className="filter-cont" style={{
- transform: `translate(${this._thumbX}px, ${(this._thumbY ?? 0) - this.height}px)`,
+ transform: `translate(${this._thumbX}px, ${(this._thumbY || 0) - this.height}px)`,
height: this.height,
width: this.height,
pointerEvents: "none",
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index b59ee7a87..52801b570 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -106,8 +106,8 @@ export default class KeyManager {
});
private shift = async (keyname: string) => {
- let stopPropagation = false;
- let preventDefault = false;
+ const stopPropagation = false;
+ const preventDefault = false;
switch (keyname) {
// case "~":
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index a81e0cc2c..8d9be5980 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -521,7 +521,9 @@ export class MainView extends React.Component {
DataDoc={undefined}
LibraryPath={emptyPath}
fieldKey={"data"}
+ dropAction={"alias"}
annotationsKey={""}
+ bringToFront={emptyFunction}
select={emptyFunction}
active={returnFalse}
isSelected={returnFalse}
diff --git a/src/client/views/RecommendationsBox.tsx b/src/client/views/RecommendationsBox.tsx
index 262226bac..5ebba0abb 100644
--- a/src/client/views/RecommendationsBox.tsx
+++ b/src/client/views/RecommendationsBox.tsx
@@ -6,7 +6,7 @@ import "./RecommendationsBox.scss";
import { Doc, DocListCast, WidthSym, HeightSym } from "../../new_fields/Doc";
import { DocumentIcon } from "./nodes/DocumentIcon";
import { StrCast, NumCast } from "../../new_fields/Types";
-import { returnFalse, emptyFunction, returnEmptyString, returnOne } from "../../Utils";
+import { returnFalse, emptyFunction, returnEmptyString, returnOne, emptyPath } from "../../Utils";
import { Transform } from "../util/Transform";
import { ObjectField } from "../../new_fields/ObjectField";
import { DocumentView } from "./nodes/DocumentView";
@@ -31,7 +31,7 @@ library.add(faBullseye, faLink);
@observer
export class RecommendationsBox extends React.Component<FieldViewProps> {
- public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(RecommendationsBox, fieldKey); }
+ public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecommendationsBox, fieldKey); }
// @observable private _display: boolean = false;
@observable private _pageX: number = 0;
@@ -48,17 +48,17 @@ export class RecommendationsBox extends React.Component<FieldViewProps> {
@action
private DocumentIcon(doc: Doc) {
- let layoutresult = StrCast(doc.type);
+ const layoutresult = StrCast(doc.type);
let renderDoc = doc;
//let box: number[] = [];
if (layoutresult.indexOf(DocumentType.COL) !== -1) {
renderDoc = Doc.MakeDelegate(renderDoc);
}
- let returnXDimension = () => 150;
- let returnYDimension = () => 150;
- let scale = () => returnXDimension() / NumCast(renderDoc.nativeWidth, returnXDimension());
+ const returnXDimension = () => 150;
+ const returnYDimension = () => 150;
+ const scale = () => returnXDimension() / NumCast(renderDoc.nativeWidth, returnXDimension());
//let scale = () => 1;
- let newRenderDoc = Doc.MakeAlias(renderDoc); /// newRenderDoc -> renderDoc -> render"data"Doc -> TextProt
+ const newRenderDoc = Doc.MakeAlias(renderDoc); /// newRenderDoc -> renderDoc -> render"data"Doc -> TextProt
newRenderDoc.height = NumCast(this.props.Document.documentIconHeight);
newRenderDoc.autoHeight = false;
const docview = <div>
@@ -66,8 +66,8 @@ export class RecommendationsBox extends React.Component<FieldViewProps> {
fitToBox={StrCast(doc.type).indexOf(DocumentType.COL) !== -1}
Document={newRenderDoc}
addDocument={returnFalse}
+ LibraryPath={emptyPath}
removeDocument={returnFalse}
- ruleProvider={undefined}
ScreenToLocalTransform={Transform.Identity}
addDocTab={returnFalse}
pinToPres={returnFalse}
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 83dbd3db3..8eb5c5050 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -114,7 +114,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
const templateName = StrCast(firstDoc.layoutKey, "layout").replace("layout_", "");
const noteTypesDoc = Cast(Doc.UserDoc().noteTypes, Doc, null);
const noteTypes = DocListCast(noteTypesDoc?.data);
- const addedTypes = DocListCast(Cast(Doc.UserDoc().templateButtons, Doc, null)?.data)
+ const addedTypes = DocListCast(Cast(Doc.UserDoc().templateButtons, Doc, null)?.data);
const layout = Doc.Layout(firstDoc);
const templateMenu: Array<JSX.Element> = [];
this.props.templates.forEach((checked, template) =>
@@ -170,8 +170,8 @@ Scripting.addGlobal(function switchView(doc: Doc, template: Doc) {
if (template.dragFactory) {
template = Cast(template.dragFactory, Doc, null);
}
- let templateTitle = StrCast(template?.title);
- return templateTitle && DocumentView.makeCustomViewClicked(doc, undefined, Docs.Create.FreeformDocument, templateTitle, template)
+ const templateTitle = StrCast(template?.title);
+ return templateTitle && DocumentView.makeCustomViewClicked(doc, Docs.Create.FreeformDocument, templateTitle, template);
});
Scripting.addGlobal(function templateIsUsed(templateDoc: Doc, firstDocTitlte: string) {
@@ -180,4 +180,4 @@ Scripting.addGlobal(function templateIsUsed(templateDoc: Doc, firstDocTitlte: st
const template = StrCast(templateDoc.dragFactory ? Cast(templateDoc.dragFactory, Doc, null)?.title : templateDoc.title);
return StrCast(firstDoc.layoutKey) === "layout_" + template ? 'check' : 'unchecked';
// return SelectionManager.SelectedDocuments().some(view => StrCast(view.props.Document.layoutKey) === "layout_" + template) ? 'check' : 'unchecked'
-}) \ No newline at end of file
+}); \ No newline at end of file
diff --git a/src/client/views/TouchScrollableMenu.tsx b/src/client/views/TouchScrollableMenu.tsx
index 4bda0818e..969605be9 100644
--- a/src/client/views/TouchScrollableMenu.tsx
+++ b/src/client/views/TouchScrollableMenu.tsx
@@ -44,7 +44,7 @@ export default class TouchScrollableMenu extends React.Component<TouchScrollable
<div className="shadow" style={{ height: `calc(100% - 25px - ${this.selectedIndex * 25}px)` }}>
</div>
</div>
- )
+ );
}
}
@@ -54,6 +54,6 @@ export class TouchScrollableMenuItem extends React.Component<TouchScrollableMenu
<div className="menuItem-cont" onClick={this.props.onClick}>
{this.props.text}
</div>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 2ee39bc0d..4e1e76f39 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -513,7 +513,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
dragData.dropAction = doc.dropAction as dropActionType;
DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY);
}
- }
+ };
let rendered = false;
tab.buttonDisposer = reaction(() => ((view: Opt<DocumentView>) => view ? [view] : [])(DocumentManager.Instance.getDocumentView(doc)),
(views) => {
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 79b5d7bb7..f124fe21b 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -157,6 +157,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
Document: this.props.rowProps.original,
DataDoc: this.props.rowProps.original,
LibraryPath: [],
+ dropAction: "alias",
+ bringToFront: emptyFunction,
fieldKey: this.props.rowProps.column.id as string,
ContainingCollectionView: this.props.CollectionView,
ContainingCollectionDoc: this.props.CollectionView && this.props.CollectionView.props.Document,
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a4502cced..981438513 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -51,8 +51,7 @@ const columnTypes: Map<string, ColumnType> = new Map([
@observer
export class CollectionSchemaView extends CollectionSubView(doc => doc) {
- private _mainCont?: HTMLDivElement;
- private _startPreviewWidth = 0;
+ private _previewCont?: HTMLDivElement;
private DIVIDER_WIDTH = 4;
@observable previewDoc: Doc | undefined = undefined;
@@ -64,7 +63,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
@computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
private createTarget = (ele: HTMLDivElement) => {
- this._mainCont = ele;
+ this._previewCont = ele;
super.CreateDropTarget(ele);
}
@@ -81,12 +80,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
}
onDividerDown = (e: React.PointerEvent) => {
- this._startPreviewWidth = this.previewWidth();
setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, action(() => this.toggleExpander()));
}
@action
onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => {
- const nativeWidth = this._mainCont!.getBoundingClientRect();
+ const nativeWidth = this._previewCont!.getBoundingClientRect();
const minWidth = 40;
const maxWidth = 1000;
const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 9d5500e1a..076dd3629 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -63,7 +63,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap);
const style = this.isStackingView ? { width: width(), marginTop: this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` };
return <div className={`collectionStackingView-${this.isStackingView ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} >
- {this.getDisplayDoc(d, this.props.DataDoc, dxf, width)}
+ {this.getDisplayDoc(d, (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc, dxf, width)}
</div>;
});
}
@@ -106,7 +106,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
fields.delete(header);
sectionHeaders.splice(sectionHeaders.indexOf(header), 1);
changed = true;
- })
+ });
}
changed && setTimeout(action(() => { if (this.sectionHeaders) { this.sectionHeaders.length = 0; this.sectionHeaders.push(...sectionHeaders); } }), 0);
return fields;
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 646b433bf..0a48c95e4 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -131,7 +131,8 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
const maxHeading = this.props.docList.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0);
const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3;
newDoc.heading = heading;
- return this.props.parent.props.addDocument(newDoc);
+ this.props.parent.props.addDocument(newDoc);
+ return false;
}
@action
diff --git a/src/client/views/collections/CollectionStaffView.tsx b/src/client/views/collections/CollectionStaffView.tsx
index 8c7e113b2..5b9a69bf7 100644
--- a/src/client/views/collections/CollectionStaffView.tsx
+++ b/src/client/views/collections/CollectionStaffView.tsx
@@ -1,22 +1,20 @@
import { CollectionSubView } from "./CollectionSubView";
-import { Transform } from "../../util/Transform";
import React = require("react");
import { computed, action, IReactionDisposer, reaction, runInAction, observable } from "mobx";
-import { Doc } from "../../../new_fields/Doc";
import { NumCast } from "../../../new_fields/Types";
import "./CollectionStaffView.scss";
import { observer } from "mobx-react";
@observer
export class CollectionStaffView extends CollectionSubView(doc => doc) {
- private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(0, -this._mainCont.current!.scrollTop);
- private _mainCont = React.createRef<HTMLDivElement>();
private _reactionDisposer: IReactionDisposer | undefined;
@observable private _staves = NumCast(this.props.Document.staves);
+ componentWillUnmount() {
+ this._reactionDisposer?.();
+ }
componentDidMount = () => {
- this._reactionDisposer = reaction(
- () => NumCast(this.props.Document.staves),
+ this._reactionDisposer = reaction(() => NumCast(this.props.Document.staves),
(staves) => runInAction(() => this._staves = staves)
);
@@ -47,7 +45,7 @@ export class CollectionStaffView extends CollectionSubView(doc => doc) {
}
render() {
- return <div className="collectionStaffView" ref={this._mainCont}>
+ return <div className="collectionStaffView">
{this.staves}
{this.addStaffButton}
</div>;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 39621b75c..70927cf22 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,5 +1,4 @@
import { action, computed, IReactionDisposer, reaction } from "mobx";
-import * as rp from 'request-promise';
import CursorField from "../../../new_fields/CursorField";
import { Doc, DocListCast, Opt, WidthSym, HeightSym } from "../../../new_fields/Doc";
import { Id } from "../../../new_fields/FieldSymbols";
@@ -107,7 +106,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
const { Document, DataDoc } = this.props;
const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.annotationsKey ? DataDoc : undefined, doc)).filter(pair => pair.layout);
- return validPairs.map(({ data, layout }) => ({ data, layout: layout! })); // this mapping is a bit of a hack to coerce types
+ return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
}
get childDocList() {
return Cast(this.dataField, listSpec(Doc));
@@ -124,8 +123,17 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
filterFacets[key][value] = modifiers;
}
- const dfield = this.dataField;
- const rawdocs = (dfield instanceof Doc) ? [dfield] : Cast(dfield, listSpec(Doc), this.props.Document.rootDocument && !this.props.annotationsKey ? [Cast(this.props.Document.rootDocument, Doc, null)] : []);
+ let rawdocs: (Doc | Promise<Doc>)[] = [];
+ if (this.dataField instanceof Doc) { // if collection data is just a document, then promote it to a singleton list;
+ rawdocs = [this.dataField];
+ } else if (Cast(this.dataField, listSpec(Doc), null)) { // otherwise, if the collection data is a list, then use it.
+ rawdocs = Cast(this.dataField, listSpec(Doc), null);
+ } else { // Finally, if it's not a doc or a list and the document is a template, we try to render the root doc.
+ // For example, if an image doc is rendered with a slide template, the template will try to render the data field as a collection.
+ // Since the data field is actually an image, we set the list of documents to the singleton of root document's proto which will be an image.
+ const rootDoc = Cast(this.props.Document.rootDocument, Doc, null);
+ rawdocs = rootDoc && !this.props.annotationsKey ? [Doc.GetProto(rootDoc)] : [];
+ }
const docs = rawdocs.filter(d => !(d instanceof Promise)).map(d => d as Doc);
const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField);
const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 64832506b..4f77e8b0e 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -31,7 +31,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
componentDidMount() {
this.props.Document._freezeOnDrop = true;
const childDetailed = this.props.Document.childDetailed; // bcz: needs to be here to make sure the childDetailed layout template has been loaded when the first item is clicked;
- const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(containingCollection.childDetailed, alias, 'layout_detailView'); alias.dropAction='alias'; alias.removeDropProperties=new List<string>(['dropAction']); useRightSplit(alias, shiftKey); ";
+ const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(containingCollection.childDetailed, alias, 'layout_detailView'); alias.layoutKey='layout_detailedView'; alias.dropAction='alias'; alias.removeDropProperties=new List<string>(['dropAction']); useRightSplit(alias, shiftKey); ";
this.props.Document.onChildClick = ScriptField.MakeScript(childText, { this: Doc.name, heading: "string", containingCollection: Doc.name, shiftKey: "boolean" });
this.props.Document._fitToBox = true;
if (!this.props.Document.onViewDefClick) {
@@ -146,7 +146,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
back
</button>
<EditableView {...newEditableViewProps} display={"inline"} menuCallback={this.menuCallback} />
- </div>
+ </div>;
}
render() {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index edb9fd930..df1770ffe 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -299,7 +299,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
const { Document, DataDoc } = this.props;
const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, DataDoc, doc)).filter(pair => pair.layout);
- return validPairs.map(({ data, layout }) => ({ data, layout: layout! })); // this mapping is a bit of a hack to coerce types
+ return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
}
get childDocList() {
return Cast(this.dataField, listSpec(Doc));
@@ -429,9 +429,9 @@ export class CollectionView extends Touchable<FieldViewProps> {
Document={facetCollection}
backgroundColor={this.filterBackground}
fieldKey={`${this.props.fieldKey}-filter`}
- moveDocument={(doc: Doc) => false}
- removeDocument={(doc: Doc) => false}
- addDocument={(doc: Doc) => false} />
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ addDocument={returnFalse} />
</div>
</div>;
}
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 53ee4c547..2d565d9db 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -267,10 +267,10 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled";
if (collapsed) return null;
switch (this.props.type) {
- case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
- case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
- case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
- case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
default: return null;
}
}
@@ -355,7 +355,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
immediate: (source: Doc[]) => Doc.setChildLayout(this.target, source?.[0]),
initialize: emptyFunction,
};
- DragManager.StartButtonDrag([this._viewRef.current!], c.script, c.title,
+ DragManager.StartButtonDrag([this._viewRef.current!], c.script, StrCast(c.title),
{ target: this.props.CollectionView.props.Document }, c.params, c.initialize, e.clientX, e.clientY);
return true;
}, emptyFunction, emptyFunction);
@@ -600,7 +600,7 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh
togglePreview = () => {
const dividerWidth = 4;
const borderWidth = Number(COLLECTION_BORDER_WIDTH);
- const panelWidth = this.props.PanelWidth();
+ const panelWidth = this.props.CollectionView.props.PanelWidth();
const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
const tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth;
this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 85b75f5cb..49ca024a2 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,4 +1,4 @@
-import { computed, IReactionDisposer } from "mobx";
+import { computed } from "mobx";
import { observer } from "mobx-react";
import { Doc } from "../../../../new_fields/Doc";
import { Id } from "../../../../new_fields/FieldSymbols";
@@ -7,70 +7,12 @@ import { DocumentView } from "../../nodes/DocumentView";
import "./CollectionFreeFormLinksView.scss";
import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView";
import React = require("react");
-import { Utils } from "../../../../Utils";
+import { Utils, emptyFunction } from "../../../../Utils";
import { SelectionManager } from "../../../util/SelectionManager";
import { DocumentType } from "../../../documents/DocumentTypes";
-import { StrCast } from "../../../../new_fields/Types";
@observer
export class CollectionFreeFormLinksView extends React.Component {
-
- _brushReactionDisposer?: IReactionDisposer;
- componentDidMount() {
- // this._brushReactionDisposer = reaction(
- // () => {
- // let doclist = DocListCast(this.props.Document[this.props.fieldKey]);
- // return { doclist: doclist ? doclist : [], xs: doclist.map(d => d.x) };
- // },
- // () => {
- // let doclist = DocListCast(this.props.Document[this.props.fieldKey]);
- // let views = doclist ? doclist.filter(doc => StrCast(doc.backgroundLayout).indexOf("istogram") !== -1) : [];
- // views.forEach((dstDoc, i) => {
- // views.forEach((srcDoc, j) => {
- // let dstTarg = dstDoc;
- // let srcTarg = srcDoc;
- // let x1 = NumCast(srcDoc.x);
- // let x2 = NumCast(dstDoc.x);
- // let x1w = NumCast(srcDoc.width, -1);
- // let x2w = NumCast(dstDoc.width, -1);
- // if (x1w < 0 || x2w < 0 || i === j) { }
- // else {
- // let findBrush = (field: (Doc | Promise<Doc>)[]) => field.findIndex(brush => {
- // let bdocs = brush instanceof Doc ? Cast(brush.brushingDocs, listSpec(Doc), []) : undefined;
- // return bdocs && bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false;
- // });
- // let brushAction = (field: (Doc | Promise<Doc>)[]) => {
- // let found = findBrush(field);
- // if (found !== -1) {
- // field.splice(found, 1);
- // }
- // };
- // if (Math.abs(x1 + x1w - x2) < 20) {
- // let linkDoc: Doc = new Doc();
- // linkDoc.title = "Histogram Brush";
- // linkDoc.linkDescription = "Brush between " + StrCast(srcTarg.title) + " and " + StrCast(dstTarg.Title);
- // linkDoc.brushingDocs = new List([dstTarg, srcTarg]);
-
- // brushAction = (field: (Doc | Promise<Doc>)[]) => {
- // if (findBrush(field) === -1) {
- // field.push(linkDoc);
- // }
- // };
- // }
- // if (dstTarg.brushingDocs === undefined) dstTarg.brushingDocs = new List<Doc>();
- // if (srcTarg.brushingDocs === undefined) srcTarg.brushingDocs = new List<Doc>();
- // let dstBrushDocs = Cast(dstTarg.brushingDocs, listSpec(Doc), []);
- // let srcBrushDocs = Cast(srcTarg.brushingDocs, listSpec(Doc), []);
- // brushAction(dstBrushDocs);
- // brushAction(srcBrushDocs);
- // }
- // });
- // });
- // });
- }
- componentWillUnmount() {
- this._brushReactionDisposer && this._brushReactionDisposer();
- }
@computed
get uniqueConnections() {
const connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => {
@@ -87,8 +29,10 @@ export class CollectionFreeFormLinksView extends React.Component {
}
return drawnPairs;
}, [] as { a: DocumentView, b: DocumentView, l: Doc[] }[]);
- return connections.filter(c => c.a.props.Document.type === DocumentType.LINK && StrCast(c.a.props.Document.layout).includes("DocuLinkBox")) // get rid of the filter to show links to documents in addition to document anchors
- .map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
+ return connections.filter(c =>
+ c.a.props.layoutKey && c.b.props.layoutKey && c.a.props.Document.type === DocumentType.LINK &&
+ c.a.props.bringToFront !== emptyFunction && c.b.props.bringToFront !== emptyFunction // this prevents links to be drawn to anchors in CollectionTree views -- this is a hack that should be fixed
+ ).map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
}
render() {
@@ -99,4 +43,60 @@ export class CollectionFreeFormLinksView extends React.Component {
{this.props.children}
</div>;
}
+ // _brushReactionDisposer?: IReactionDisposer;
+ // componentDidMount() {
+ // this._brushReactionDisposer = reaction(
+ // () => {
+ // let doclist = DocListCast(this.props.Document[this.props.fieldKey]);
+ // return { doclist: doclist ? doclist : [], xs: doclist.map(d => d.x) };
+ // },
+ // () => {
+ // let doclist = DocListCast(this.props.Document[this.props.fieldKey]);
+ // let views = doclist ? doclist.filter(doc => StrCast(doc.backgroundLayout).indexOf("istogram") !== -1) : [];
+ // views.forEach((dstDoc, i) => {
+ // views.forEach((srcDoc, j) => {
+ // let dstTarg = dstDoc;
+ // let srcTarg = srcDoc;
+ // let x1 = NumCast(srcDoc.x);
+ // let x2 = NumCast(dstDoc.x);
+ // let x1w = NumCast(srcDoc.width, -1);
+ // let x2w = NumCast(dstDoc.width, -1);
+ // if (x1w < 0 || x2w < 0 || i === j) { }
+ // else {
+ // let findBrush = (field: (Doc | Promise<Doc>)[]) => field.findIndex(brush => {
+ // let bdocs = brush instanceof Doc ? Cast(brush.brushingDocs, listSpec(Doc), []) : undefined;
+ // return bdocs && bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false;
+ // });
+ // let brushAction = (field: (Doc | Promise<Doc>)[]) => {
+ // let found = findBrush(field);
+ // if (found !== -1) {
+ // field.splice(found, 1);
+ // }
+ // };
+ // if (Math.abs(x1 + x1w - x2) < 20) {
+ // let linkDoc: Doc = new Doc();
+ // linkDoc.title = "Histogram Brush";
+ // linkDoc.linkDescription = "Brush between " + StrCast(srcTarg.title) + " and " + StrCast(dstTarg.Title);
+ // linkDoc.brushingDocs = new List([dstTarg, srcTarg]);
+
+ // brushAction = (field: (Doc | Promise<Doc>)[]) => {
+ // if (findBrush(field) === -1) {
+ // field.push(linkDoc);
+ // }
+ // };
+ // }
+ // if (dstTarg.brushingDocs === undefined) dstTarg.brushingDocs = new List<Doc>();
+ // if (srcTarg.brushingDocs === undefined) srcTarg.brushingDocs = new List<Doc>();
+ // let dstBrushDocs = Cast(dstTarg.brushingDocs, listSpec(Doc), []);
+ // let srcBrushDocs = Cast(srcTarg.brushingDocs, listSpec(Doc), []);
+ // brushAction(dstBrushDocs);
+ // brushAction(srcBrushDocs);
+ // }
+ // });
+ // });
+ // });
+ // }
+ // componentWillUnmount() {
+ // this._brushReactionDisposer?.();
+ // }
} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a0dd4f2de..2871fe192 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -500,36 +500,36 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@action
pan = (e: PointerEvent | React.Touch | { clientX: number, clientY: number }): void => {
- // I think it makes sense for the marquee menu to go away when panned. -syip2
- MarqueeOptionsMenu.Instance && MarqueeOptionsMenu.Instance.fadeOut(true);
+ // bcz: theres should be a better way of doing these than referencing these static instances directly
+ MarqueeOptionsMenu.Instance?.fadeOut(true);// I think it makes sense for the marquee menu to go away when panned. -syip2
+ PDFMenu.Instance.fadeOut(true);
- let x = this.Document._panX || 0;
- let y = this.Document._panY || 0;
- const docs = this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout);
const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
- if (!this.isAnnotationOverlay && docs.length && this.childDataProvider(docs[0])) {
- PDFMenu.Instance.fadeOut(true);
- const minx = this.childDataProvider(docs[0]).x;
- const miny = this.childDataProvider(docs[0]).y;
- const maxx = this.childDataProvider(docs[0]).width + minx;
- const maxy = this.childDataProvider(docs[0]).height + miny;
- const ranges = docs.filter(doc => doc && this.childDataProvider(doc)).reduce((range, doc) => {
- const x = this.childDataProvider(doc).x;
- const y = this.childDataProvider(doc).y;
- const xe = this.childDataProvider(doc).width + x;
- const ye = this.childDataProvider(doc).height + y;
- return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]],
- [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]];
- }, [[minx, maxx], [miny, maxy]]);
-
- const cscale = this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.scale) : 1;
- const panelDim = [this.props.PanelWidth() * cscale / this.zoomScaling(), this.props.PanelHeight() * cscale / this.zoomScaling()];
- if (ranges[0][0] - dx > (this.panX() + panelDim[0] / 2)) x = ranges[0][1] + panelDim[0] / 2;
- if (ranges[0][1] - dx < (this.panX() - panelDim[0] / 2)) x = ranges[0][0] - panelDim[0] / 2;
- if (ranges[1][0] - dy > (this.panY() + panelDim[1] / 2)) y = ranges[1][1] + panelDim[1] / 2;
- if (ranges[1][1] - dy < (this.panY() - panelDim[1] / 2)) y = ranges[1][0] - panelDim[1] / 2;
+ let x = (this.Document._panX || 0) - dx;
+ let y = (this.Document._panY || 0) - dy;
+ if (!this.isAnnotationOverlay) {
+ // this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds
+ const docs = this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout);
+ const measuredDocs = docs.filter(doc => doc && this.childDataProvider(doc)).map(doc => this.childDataProvider(doc));
+ if (measuredDocs.length) {
+ const ranges = measuredDocs.reduce(({ xrange, yrange }, { x, y, width, height }) => // computes range of content
+ ({
+ xrange: { min: Math.min(xrange.min, x), max: Math.max(xrange.max, x + width) },
+ yrange: { min: Math.min(yrange.min, y), max: Math.max(yrange.max, y + height) }
+ })
+ , {
+ xrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE },
+ yrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE }
+ });
+
+ const panelDim = [this.props.PanelWidth() / this.zoomScaling(), this.props.PanelHeight() / this.zoomScaling()];
+ if (ranges.xrange.min > (this.panX() + panelDim[0] / 2)) x = ranges.xrange.max + panelDim[0] / 2; // snaps pan position of range of content goes out of bounds
+ if (ranges.xrange.max < (this.panX() - panelDim[0] / 2)) x = ranges.xrange.min - panelDim[0] / 2;
+ if (ranges.yrange.min > (this.panY() + panelDim[1] / 2)) y = ranges.yrange.max + panelDim[1] / 2;
+ if (ranges.yrange.max < (this.panY() - panelDim[1] / 2)) y = ranges.yrange.min - panelDim[1] / 2;
+ }
}
- this.setPan(x - dx, y - dy);
+ this.setPan(x, y);
this._lastX = e.clientX;
this._lastY = e.clientY;
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 0f94bffd6..276a49570 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -4,7 +4,7 @@ import { Doc, DocListCast, DataSym, WidthSym, HeightSym } from "../../../../new_
import { InkField, InkData } from "../../../../new_fields/InkField";
import { List } from "../../../../new_fields/List";
import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField";
-import { Cast, NumCast, FieldValue } from "../../../../new_fields/Types";
+import { Cast, NumCast, FieldValue, StrCast } from "../../../../new_fields/Types";
import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
import { Utils } from "../../../../Utils";
import { Docs, DocUtils } from "../../../documents/Documents";
@@ -107,7 +107,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
});
} else if (!e.ctrlKey) {
FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout ? e.key : "";
- let tbox = Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" });
+ const tbox = Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" });
const template = FormattedTextBox.DefaultLayout;
if (template instanceof Doc) {
tbox._width = NumCast(template._width);
diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx
index de0b509eb..1b70ff824 100644
--- a/src/client/views/nodes/ButtonBox.tsx
+++ b/src/client/views/nodes/ButtonBox.tsx
@@ -42,9 +42,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
protected createDropTarget = (ele: HTMLDivElement) => {
- if (this.dropDisposer) {
- this.dropDisposer();
- }
+ this.dropDisposer?.();
if (ele) {
this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this));
}
@@ -55,7 +53,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
funcs.push({
description: "Clear Script Params", event: () => {
const params = FieldValue(this.Document.buttonParams);
- params && params.map(p => this.props.Document[p] = undefined);
+ params?.map(p => this.props.Document[p] = undefined);
}, icon: "trash"
});
@@ -66,7 +64,9 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
@action
drop = (e: Event, de: DragManager.DropEvent) => {
const docDragData = de.complete.docDragData;
- if (docDragData && e.target) {
+ const params = this.Document.buttonParams;
+ const missingParams = params?.filter(p => this.props.Document[p] === undefined);
+ if (docDragData && missingParams?.includes((e.target as any).textContent)) {
this.props.Document[(e.target as any).textContent] = new List<Doc>(docDragData.droppedDocuments.map((d, i) =>
d.onDragStart ? docDragData.draggedDocuments[i] : d));
e.stopPropagation();
@@ -75,14 +75,14 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
// (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")")
render() {
const params = this.Document.buttonParams;
- const missingParams = params && params.filter(p => this.props.Document[p] === undefined);
- params && params.map(p => DocListCast(this.props.Document[p])); // bcz: really hacky form of prefetching ...
+ const missingParams = params?.filter(p => this.props.Document[p] === undefined);
+ params?.map(p => DocListCast(this.props.Document[p])); // bcz: really hacky form of prefetching ...
return (
<div className="buttonBox-outerDiv" ref={this.createDropTarget} onContextMenu={this.specificContextMenu}
style={{ boxShadow: this.Document.opacity === 0 ? undefined : StrCast(this.Document.boxShadow, "") }}>
<div className="buttonBox-mainButton" style={{
background: this.Document.backgroundColor, color: this.Document.color || "inherit",
- fontSize: this.Document.fontSize, letterSpacing: this.Document.letterSpacing || "", textTransform: this.Document.textTransform || ""
+ fontSize: this.Document.fontSize, letterSpacing: this.Document.letterSpacing || "", textTransform: (this.Document.textTransform as any) || ""
}} >
<div className="buttonBox-mainButtonCenter">
{(this.Document.text || this.Document.title)}
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index 8632f9c9a..9494a4bc4 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -22,6 +22,7 @@ interface ContentFittingDocumentViewProps {
childDocs?: Doc[];
renderDepth: number;
fitToBox?: boolean;
+ layoutKey?: string;
dropAction?: dropActionType;
PanelWidth: () => number;
PanelHeight: () => number;
@@ -88,6 +89,7 @@ export class ContentFittingDocumentView extends React.Component<ContentFittingDo
LayoutDoc={this.props.LayoutDoc}
LibraryPath={this.props.LibraryPath}
fitToBox={this.props.fitToBox}
+ layoutKey={this.props.layoutKey}
dropAction={this.props.dropAction}
onClick={this.props.onClick}
backgroundColor={this.props.backgroundColor}
diff --git a/src/client/views/nodes/DocumentBox.scss b/src/client/views/nodes/DocumentBox.scss
index b7d06b364..ce21391ce 100644
--- a/src/client/views/nodes/DocumentBox.scss
+++ b/src/client/views/nodes/DocumentBox.scss
@@ -3,13 +3,12 @@
height: 100%;
pointer-events: all;
background: gray;
- border: #00000021 solid 15px;
- border-top: #0000005e inset 15px;
- border-bottom: #0000005e outset 15px;
.documentBox-lock {
margin: auto;
color: white;
- margin-top: -15px;
+ position: absolute;
+ }
+ .contentFittingDocumentView {
position: absolute;
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx
index 978480142..debe104d7 100644
--- a/src/client/views/nodes/DocumentBox.tsx
+++ b/src/client/views/nodes/DocumentBox.tsx
@@ -5,7 +5,7 @@ import { Doc, Field } from "../../../new_fields/Doc";
import { documentSchema } from "../../../new_fields/documentSchemas";
import { makeInterface } from "../../../new_fields/Schema";
import { ComputedField } from "../../../new_fields/ScriptField";
-import { Cast, StrCast } from "../../../new_fields/Types";
+import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
import { emptyPath } from "../../../Utils";
import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from "../ContextMenuItem";
@@ -15,6 +15,8 @@ import "./DocumentBox.scss";
import { FieldView, FieldViewProps } from "./FieldView";
import React = require("react");
import { TraceMobx } from "../../../new_fields/util";
+import { DocumentView } from "./DocumentView";
+import { Docs } from "../../documents/Documents";
type DocBoxSchema = makeInterface<[typeof documentSchema]>;
const DocBoxDocument = makeInterface(documentSchema);
@@ -35,12 +37,12 @@ export class DocumentBox extends DocAnnotatableComponent<FieldViewProps, DocBoxS
});
}
componentWillUnmount() {
- this._prevSelectionDisposer && this._prevSelectionDisposer();
+ this._prevSelectionDisposer?.();
}
specificContextMenu = (e: React.MouseEvent): void => {
const funcs: ContextMenuProps[] = [];
funcs.push({ description: (this.isSelectionLocked() ? "Show" : "Lock") + " Selection", event: () => this.toggleLockSelection, icon: "expand-arrows-alt" });
- funcs.push({ description: (this.props.Document.excludeCollections ? "Include" : "Exclude") + " Collections", event: () => this.props.Document.excludeCollections = !this.props.Document.excludeCollections, icon: "expand-arrows-alt" });
+ funcs.push({ description: (this.props.Document.excludeCollections ? "Include" : "Exclude") + " Collections", event: () => Doc.GetProto(this.props.Document).excludeCollections = !this.props.Document.excludeCollections, icon: "expand-arrows-alt" });
funcs.push({ description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" });
ContextMenu.Instance.addItem({ description: "DocumentBox Funcs...", subitems: funcs, icon: "asterisk" });
@@ -85,13 +87,15 @@ export class DocumentBox extends DocAnnotatableComponent<FieldViewProps, DocBoxS
(e.nativeEvent as any).formattedHandled = true;
e.stopPropagation();
}
+ get xPad() { return NumCast(this.props.Document._xPadding); }
+ get yPad() { return NumCast(this.props.Document._yPadding); }
onClick = (e: React.MouseEvent) => {
let hitWidget: boolean | undefined = false;
- if (this._contRef.current!.getBoundingClientRect().top + 15 > e.clientY) hitWidget = (() => { this.props.select(false); return true; })();
- else if (this._contRef.current!.getBoundingClientRect().bottom - 15 < e.clientY) hitWidget = (() => { this.props.select(false); return true; })();
+ if (this._contRef.current!.getBoundingClientRect().top + this.yPad > e.clientY) hitWidget = (() => { this.props.select(false); return true; })();
+ else if (this._contRef.current!.getBoundingClientRect().bottom - this.yPad < e.clientY) hitWidget = (() => { this.props.select(false); return true; })();
else {
- if (this._contRef.current!.getBoundingClientRect().left + 15 > e.clientX) hitWidget = this.prevSelection();
- if (this._contRef.current!.getBoundingClientRect().right - 15 < e.clientX) hitWidget = this.nextSelection();
+ if (this._contRef.current!.getBoundingClientRect().left + this.xPad > e.clientX) hitWidget = this.prevSelection();
+ if (this._contRef.current!.getBoundingClientRect().right - this.xPad < e.clientX) hitWidget = this.nextSelection();
}
if (hitWidget) {
(e.nativeEvent as any).formattedHandled = true;
@@ -99,38 +103,57 @@ export class DocumentBox extends DocAnnotatableComponent<FieldViewProps, DocBoxS
}
}
_contRef = React.createRef<HTMLDivElement>();
- pwidth = () => this.props.PanelWidth() - 30;
- pheight = () => this.props.PanelHeight() - 30;
- getTransform = () => this.props.ScreenToLocalTransform().translate(-15, -15);
+ pwidth = () => this.props.PanelWidth() - 2 * this.xPad;
+ pheight = () => this.props.PanelHeight() - 2 * this.yPad;
+ getTransform = () => this.props.ScreenToLocalTransform().translate(-this.xPad, -this.yPad);
+ get renderContents() {
+ const containedDoc = Cast(this.contentDoc[this.props.fieldKey], Doc, null);
+ const childTemplateName = StrCast(this.props.Document.childTemplateName);
+ if (containedDoc && childTemplateName && !containedDoc["layout_" + childTemplateName]) {
+ setTimeout(() => {
+ DocumentView.createCustomView(containedDoc, Docs.Create.StackingDocument, childTemplateName);
+ Doc.expandTemplateLayout(Cast(containedDoc["layout_" + childTemplateName], Doc, null)!, containedDoc, undefined);
+ }, 0);
+ }
+ const contents = !(containedDoc instanceof Doc) ? (null) : <ContentFittingDocumentView
+ Document={containedDoc}
+ DataDocument={undefined}
+ LibraryPath={emptyPath}
+ CollectionView={this as any} // bcz: hack! need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked. currently, the up selector allows only a containing collection to be selected
+ fitToBox={this.props.fitToBox}
+ layoutKey={"layout_" + childTemplateName}
+ addDocument={this.props.addDocument}
+ moveDocument={this.props.moveDocument}
+ removeDocument={this.props.removeDocument}
+ addDocTab={this.props.addDocTab}
+ pinToPres={this.props.pinToPres}
+ getTransform={this.getTransform}
+ renderDepth={this.props.renderDepth + 1}
+ PanelWidth={this.pwidth}
+ PanelHeight={this.pheight}
+ focus={this.props.focus}
+ active={this.props.active}
+ dontRegisterView={!this.isSelectionLocked()}
+ whenActiveChanged={this.props.whenActiveChanged}
+ />;
+ return contents;
+ }
render() {
TraceMobx();
- const containedDoc = this.contentDoc[this.props.fieldKey];
return <div className="documentBox-container" ref={this._contRef}
onContextMenu={this.specificContextMenu}
onPointerDown={this.onPointerDown} onClick={this.onClick}
- style={{ background: StrCast(this.props.Document.backgroundColor) }}>
- <div className="documentBox-lock" onClick={this.onLockClick}>
+ style={{
+ background: StrCast(this.props.Document.backgroundColor),
+ border: `#00000021 solid ${this.xPad}px`,
+ borderTop: `#0000005e solid ${this.yPad}px`,
+ borderBottom: `#0000005e solid ${this.yPad}px`,
+ }}>
+ {this.renderContents}
+ <div className="documentBox-lock" onClick={this.onLockClick}
+ style={{ marginTop: - this.yPad }}>
<FontAwesomeIcon icon={this.isSelectionLocked() ? "lock" : "unlock"} size="sm" />
</div>
- {!(containedDoc instanceof Doc) ? (null) : <ContentFittingDocumentView
- Document={containedDoc}
- DataDocument={undefined}
- LibraryPath={emptyPath}
- fitToBox={this.props.fitToBox}
- addDocument={this.props.addDocument}
- moveDocument={this.props.moveDocument}
- removeDocument={this.props.removeDocument}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- getTransform={this.getTransform}
- renderDepth={this.props.renderDepth + 1} // bcz: need a forceActive prop here ... not the same as renderDepth = 0
- PanelWidth={this.pwidth}
- PanelHeight={this.pheight}
- focus={this.props.focus}
- active={this.props.active}
- dontRegisterView={!this.isSelectionLocked()}
- whenActiveChanged={this.props.whenActiveChanged}
- />}
- </div>;
+ </div >;
}
}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 8be6ab151..68501fca2 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -58,21 +58,26 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
select: (ctrl: boolean) => void,
layoutKey: string,
forceLayout?: string,
- forceFieldKey?: string
+ forceFieldKey?: string,
+ hideOnLeave?: boolean,
+ makeLink?: () => Opt<Doc>;
}> {
@computed get layout(): string {
TraceMobx();
if (!this.layoutDoc) return "<p>awaiting layout</p>";
const layout = Cast(this.layoutDoc[StrCast(this.layoutDoc.layoutKey, this.layoutDoc === this.props.Document ? this.props.layoutKey : "layout")], "string");
- if (layout === undefined) {
- return this.props.Document.data ?
- "<FieldView {...props} fieldKey='data' />" :
- KeyValueBox.LayoutString(this.layoutDoc.proto ? "proto" : "");
- } else if (typeof layout === "string") {
- return layout;
- } else {
- return "<p>Loading layout</p>";
- }
+ if (this.props.layoutKey === "layout_keyValue") {
+ return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString("data"));
+ } else
+ if (layout === undefined) {
+ return this.props.Document.data ?
+ "<FieldView {...props} fieldKey='data' />" :
+ KeyValueBox.LayoutString(this.layoutDoc.proto ? "proto" : "");
+ } else if (typeof layout === "string") {
+ return layout;
+ } else {
+ return "<p>Loading layout</p>";
+ }
}
get dataDoc() {
@@ -81,7 +86,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
}
get layoutDoc() {
const params = StrCast(this.props.Document.PARAMS);
- return Doc.expandTemplateLayout(this.props.LayoutDoc?.() || Doc.Layout(this.props.Document), this.props.Document, params ? "(" + params + ")" : this.props.layoutKey);
+ const template: Doc = this.props.LayoutDoc?.() || Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined);
+ return Doc.expandTemplateLayout(template, this.props.Document, params ? "(" + params + ")" : this.props.layoutKey);
}
CreateBindings(): JsxBindings {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 1dee25c51..02a1ac527 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -40,7 +40,6 @@ import { ScriptBox } from '../ScriptBox';
import { ScriptingRepl } from '../ScriptingRepl';
import { DocumentContentsView } from "./DocumentContentsView";
import "./DocumentView.scss";
-import { FormattedTextBox } from './FormattedTextBox';
import React = require("react");
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { SchemaHeaderField } from '../../../new_fields/SchemaHeaderField';
@@ -509,58 +508,49 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@undoBatch
deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument?.(this.props.Document); }
- static makeNativeViewClicked = (doc: Doc) => {
- undoBatch(() => Doc.setNativeView(doc))();
- }
-
- static makeCustomViewClicked = (doc: Doc, dataDoc: Opt<Doc>, creator: (documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc, templateSignature: string = "custom", docLayoutTemplate?: Doc) => {
- const userDoc = Doc.UserDoc();
- const imgView = Cast(userDoc.iconView, Doc, null);
- const iconImgView = Cast(userDoc.iconImageView, Doc, null);
- const iconColView = Cast(userDoc.iconColView, Doc, null);
- const iconViews = [imgView, iconImgView, iconColView];
- const templateButtons = DocListCast(Cast(userDoc.templateButtons, Doc, null)?.data);
- const noteTypes = DocListCast(Cast(userDoc.noteTypes, Doc, null)?.data);
- const allTemplates = iconViews.concat(templateButtons).concat(noteTypes);
- const templateName = templateSignature.replace(/\(.*\)/, "");
- !docLayoutTemplate && allTemplates.map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc).filter(doc => doc.isTemplateDoc).forEach(tempDoc => {
- if (StrCast(tempDoc.title) === doc.type + "_" + templateName) {
- docLayoutTemplate = tempDoc;
- }
- });
- !docLayoutTemplate && allTemplates.map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc).filter(doc => doc.isTemplateDoc).forEach(tempDoc => {
- if (StrCast(tempDoc.title) === templateName) {
- docLayoutTemplate = tempDoc;
+ // applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView)
+ static makeCustomViewClicked = (doc: Doc, creator: (documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc, templateSignature: string = "custom", docLayoutTemplate?: Doc) => {
+ const batch = UndoManager.StartBatch("makeCustomViewClicked");
+ runInAction(() => {
+ doc.layoutKey = "layout_" + templateSignature;
+ if (doc[doc.layoutKey] === undefined) {
+ DocumentView.createCustomView(doc, creator, templateSignature, docLayoutTemplate);
}
});
+ batch.end();
+ }
+ static createCustomView = (doc: Doc, creator: (documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc, templateSignature: string = "custom", docLayoutTemplate?: Doc) => {
+ const iconViews = DocListCast(Cast(Doc.UserDoc().iconViews, Doc, null)?.data);
+ const templBtns = DocListCast(Cast(Doc.UserDoc().templateButtons, Doc, null)?.data);
+ const noteTypes = DocListCast(Cast(Doc.UserDoc().noteTypes, Doc, null)?.data);
+ const allTemplates = iconViews.concat(templBtns).concat(noteTypes).map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc).filter(doc => doc.isTemplateDoc);
+ const templateName = templateSignature.replace(/\(.*\)/, "");
+ // bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document. but type is not reliable and there could be other types of template searches so this should be generalized
+ // first try to find a template that matches the specific document type (<typeName>_<templateName>). otherwise, fallback to a general match on <templateName>
+ !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === doc.type + "_" + templateName && (docLayoutTemplate = tempDoc));
+ !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName && (docLayoutTemplate = tempDoc));
- const batch = UndoManager.StartBatch("CustomViewClicked");
const customName = "layout_" + templateSignature;
- if (doc[customName] === undefined) {
- const _width = NumCast(doc._width);
- const _height = NumCast(doc._height);
- const options = { title: "data", backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: - _height / 2, _showSidebar: false };
-
- let fieldTemplate: Opt<Doc>;
- if (doc.data instanceof RichTextField || typeof (doc.data) === "string") {
- fieldTemplate = Docs.Create.TextDocument("", options);
- } else if (doc.data instanceof PdfField) {
- fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options);
- } else if (doc.data instanceof VideoField) {
- fieldTemplate = Docs.Create.VideoDocument("http://www.cs.brown.edu", options);
- } else if (doc.data instanceof AudioField) {
- fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options);
- } else if (doc.data instanceof ImageField) {
- fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
- }
- const docTemplate = docLayoutTemplate || creator(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
-
- fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate));
- Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
- } else {
- doc.layoutKey = customName;
+ const _width = NumCast(doc._width);
+ const _height = NumCast(doc._height);
+ const options = { title: "data", backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: - _height / 2, _showSidebar: false };
+
+ let fieldTemplate: Opt<Doc>;
+ if (doc.data instanceof RichTextField || typeof (doc.data) === "string") {
+ fieldTemplate = Docs.Create.TextDocument("", options);
+ } else if (doc.data instanceof PdfField) {
+ fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options);
+ } else if (doc.data instanceof VideoField) {
+ fieldTemplate = Docs.Create.VideoDocument("http://www.cs.brown.edu", options);
+ } else if (doc.data instanceof AudioField) {
+ fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options);
+ } else if (doc.data instanceof ImageField) {
+ fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
}
- batch.end();
+ const docTemplate = docLayoutTemplate || creator(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
+
+ fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate));
+ Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
}
@undoBatch
@@ -584,29 +574,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
DocUtils.MakeLink({ doc: de.complete.annoDragData.annotationDocument }, { doc: this.props.Document }, "link");
}
- if (de.complete.docDragData) {
- if (de.complete.docDragData.applyAsTemplate) {
- Doc.ApplyTemplateTo(de.complete.docDragData.draggedDocuments[0], this.props.Document, "layout_custom", undefined);
- e.stopPropagation();
- }
- else if (de.complete.docDragData.draggedDocuments[0].type === "text") {
- const text = Cast(de.complete.docDragData.draggedDocuments[0].data, RichTextField)?.Text;
- if (text && text[0] === "{" && text[text.length - 1] === "}" && text.includes(":")) {
- const loc = text.indexOf(":");
- const key = text.slice(1, loc);
- const value = text.slice(loc + 1, text.length - 1);
- console.log(key);
- console.log(value);
- console.log(this.props.Document);
- this.props.Document[key] = value;
- console.log(de.complete.docDragData.draggedDocuments[0].x);
- console.log(de.complete.docDragData.draggedDocuments[0].x);
- e.preventDefault();
- e.stopPropagation();
- de.complete.aborted = true;
- }
- }
- }
if (de.complete.linkDragData) {
e.stopPropagation();
// const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true);
@@ -647,9 +614,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@undoBatch
@action
setCustomView = (custom: boolean, layout: string): void => {
- DocumentView.makeNativeViewClicked(this.props.Document);
+ Doc.setNativeView(this.props.Document);
if (custom) {
- DocumentView.makeCustomViewClicked(this.props.Document, this.props.DataDoc, Docs.Create.StackingDocument, layout, undefined);
+ DocumentView.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
}
}
@@ -962,7 +929,30 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling());
@computed get contents() {
TraceMobx();
- return (<DocumentContentsView {...OmitKeys(this.props, ['children']).omit}
+ return (<DocumentContentsView ContainingCollectionView={this.props.ContainingCollectionView}
+ ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+ Document={this.props.Document}
+ DataDoc={this.props.DataDoc}
+ LayoutDoc={this.props.LayoutDoc}
+ makeLink={this.makeLink}
+ fitToBox={this.props.fitToBox}
+ LibraryPath={this.props.LibraryPath}
+ addDocument={this.props.addDocument}
+ removeDocument={this.props.removeDocument}
+ moveDocument={this.props.moveDocument}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+ renderDepth={this.props.renderDepth}
+ PanelWidth={this.props.PanelWidth}
+ PanelHeight={this.props.PanelHeight}
+ focus={this.props.focus}
+ parentActive={this.props.parentActive}
+ whenActiveChanged={this.props.whenActiveChanged}
+ bringToFront={this.props.bringToFront}
+ addDocTab={this.props.addDocTab}
+ pinToPres={this.props.pinToPres}
+ zoomToScale={this.props.zoomToScale}
+ backgroundColor={this.props.backgroundColor}
+ getScale={this.props.getScale}
ContentScaling={this.childScaling}
ChromeHeight={this.chromeHeight}
isSelected={this.isSelected}
@@ -981,6 +971,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
return anchor.type === DocumentType.AUDIO && NumCast(ept) ? false : true;
}
+ @observable _link: Opt<Doc>;
+ makeLink = () => {
+ return this._link;
+ }
+
@computed get innards() {
TraceMobx();
if (!this.props.PanelWidth()) {
@@ -988,8 +983,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
{StrCast(this.props.Document.title)}
{this.Document.links && DocListCast(this.Document.links).filter(d => !d.hidden).filter(this.isNonTemporalLink).map((d, i) =>
<div className="documentView-docuLinkWrapper" style={{ position: "absolute", top: 0, left: 0 }} key={`${d[Id]}`}>
- <DocumentView {...this.props} ContentScaling={returnOne} ContainingCollectionDoc={this.props.Document}
- PanelWidth={returnOne} PanelHeight={returnOne} Document={d} layoutKey={this.linkEndpoint(d)} backgroundColor={returnTransparent} removeDocument={undoBatch(doc => doc.hidden = true)} />
+ <DocumentView {...this.props} Document={d} ContainingCollectionDoc={this.props.Document}
+ PanelWidth={returnOne} PanelHeight={returnOne} layoutKey={this.linkEndpoint(d)} ContentScaling={returnOne}
+ backgroundColor={returnTransparent} removeDocument={undoBatch(doc => doc.hidden = true)} />
</div>)}
</div>;
}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index bc43beab9..241345f3e 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -54,6 +54,7 @@ library.add(faSmile, faTextHeight, faUpload);
export interface FormattedTextBoxProps {
hideOnLeave?: boolean;
+ makeLink?: () => Opt<Doc>;
}
const richTextSchema = createSchema({
@@ -91,6 +92,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
private _pullReactionDisposer: Opt<IReactionDisposer>;
private _pushReactionDisposer: Opt<IReactionDisposer>;
private _buttonBarReactionDisposer: Opt<IReactionDisposer>;
+ private _linkMakerDisposer: Opt<IReactionDisposer>;
private _scrollDisposer: Opt<IReactionDisposer>;
private dropDisposer?: DragManager.DragDropDisposer;
@@ -282,8 +284,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
e.stopPropagation();
// }
} // otherwise, fall through to outer collection to handle drop
+ } else if (de.complete.linkDragData) {
+ de.complete.linkDragData.linkDropCallback = this.linkDrop;
}
}
+ linkDrop = (data: DragManager.LinkDragData) => {
+ const linkDoc = data.linkDocument!;
+ const anchor1Title = linkDoc.anchor1 instanceof Doc ? StrCast(linkDoc.anchor1.title) : "-untitled-";
+ const anchor1Id = linkDoc.anchor1 instanceof Doc ? linkDoc.anchor1[Id] : "";
+ this.makeLinkToSelection(linkDoc[Id], anchor1Title, "onRight", anchor1Id)
+ }
getNodeEndpoints(context: Node, node: Node): { from: number, to: number } | null {
let offset = 0;
@@ -513,6 +523,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
};
}
+ makeLinkToSelection(linkDocId: string, title: string, location: string, targetDocId: string) {
+ if (this._editorView) {
+ const link = this._editorView.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, linkId: linkDocId, targetId: targetDocId });
+ this._editorView.dispatch(this._editorView.state.tr.removeMark(this._editorView.state.selection.from, this._editorView.state.selection.to, this._editorView.state.schema.marks.link).
+ addMark(this._editorView.state.selection.from, this._editorView.state.selection.to, link));
+ }
+ }
componentDidMount() {
this._buttonBarReactionDisposer = reaction(
() => DocumentButtonBar.Instance,
@@ -523,6 +540,17 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
}
}
);
+ this._linkMakerDisposer = reaction(
+ () => this.props.makeLink?.(),
+ (linkDoc: Opt<Doc>) => {
+ if (linkDoc) {
+ const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-";
+ const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : "";
+ this.makeLinkToSelection(linkDoc[Id], anchor2Title, "onRight", anchor2Id);
+ }
+ },
+ { fireImmediately: true }
+ );
this._reactionDisposer = reaction(
() => {
@@ -858,6 +886,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
this._searchReactionDisposer?.();
this._recordReactionDisposer?.();
this._buttonBarReactionDisposer?.();
+ this._linkMakerDisposer?.();
this._editorView?.destroy();
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 68eb4493a..00057055f 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -225,7 +225,7 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
return url.href;
} else if (url.href.indexOf(window.location.origin) === -1) {
return Utils.CorsProxy(url.href);
- } else if (!/\.(png|jpg|jpeg|gif)$/.test(lower)) {
+ } else if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) {
return url.href;//Why is this here
}
const ext = path.extname(url.href);
@@ -439,7 +439,8 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
transform: `scale(${this.props.ContentScaling()})`,
width: `${100 / this.props.ContentScaling()}%`,
height: `${100 / this.props.ContentScaling()}%`,
- pointerEvents: this.props.Document.isBackground ? "none" : undefined
+ pointerEvents: this.props.Document.isBackground ? "none" : undefined,
+ borderRadius: `${Number(StrCast(this.layoutDoc.borderRounding).replace("px", "")) / this.props.ContentScaling()}px`
}} >
<CollectionFreeFormView {...this.props}
PanelHeight={this.props.PanelHeight}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 93bda6d02..3d59ea61a 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -61,6 +61,8 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
fieldKey: this.props.keyName,
isSelected: returnFalse,
select: emptyFunction,
+ dropAction:"alias",
+ bringToFront:emptyFunction,
renderDepth: 1,
active: returnFalse,
whenActiveChanged: emptyFunction,
diff --git a/src/client/views/nodes/RadialMenuItem.tsx b/src/client/views/nodes/RadialMenuItem.tsx
index fdc732d3f..bd5b3bff4 100644
--- a/src/client/views/nodes/RadialMenuItem.tsx
+++ b/src/client/views/nodes/RadialMenuItem.tsx
@@ -44,12 +44,12 @@ export class RadialMenuItem extends React.Component<RadialMenuProps> {
setcircle() {
let circlemin = 0;
- let circlemax = 1
+ let circlemax = 1;
this.props.min ? circlemin = this.props.min : null;
this.props.max ? circlemax = this.props.max : null;
if (document.getElementById("myCanvas") !== null) {
- var c: any = document.getElementById("myCanvas");
- let color = "white"
+ const c: any = document.getElementById("myCanvas");
+ let color = "white";
switch (circlemin % 3) {
case 1:
color = "#c2c2c5";
@@ -70,38 +70,38 @@ export class RadialMenuItem extends React.Component<RadialMenuProps> {
}
if (c.getContext) {
- var ctx = c.getContext("2d");
+ const ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(150, 150, 150, (circlemin / circlemax) * 2 * Math.PI, ((circlemin + 1) / circlemax) * 2 * Math.PI);
ctx.arc(150, 150, 50, ((circlemin + 1) / circlemax) * 2 * Math.PI, (circlemin / circlemax) * 2 * Math.PI, true);
ctx.fillStyle = color;
- ctx.fill()
+ ctx.fill();
}
}
}
calculatorx() {
let circlemin = 0;
- let circlemax = 1
+ let circlemax = 1;
this.props.min ? circlemin = this.props.min : null;
this.props.max ? circlemax = this.props.max : null;
- let avg = ((circlemin / circlemax) + ((circlemin + 1) / circlemax)) / 2;
- let degrees = 360 * avg;
- let x = 100 * Math.cos(degrees * Math.PI / 180);
- let y = -125 * Math.sin(degrees * Math.PI / 180);
+ const avg = ((circlemin / circlemax) + ((circlemin + 1) / circlemax)) / 2;
+ const degrees = 360 * avg;
+ const x = 100 * Math.cos(degrees * Math.PI / 180);
+ const y = -125 * Math.sin(degrees * Math.PI / 180);
return x;
}
calculatory() {
let circlemin = 0;
- let circlemax = 1
+ let circlemax = 1;
this.props.min ? circlemin = this.props.min : null;
this.props.max ? circlemax = this.props.max : null;
- let avg = ((circlemin / circlemax) + ((circlemin + 1) / circlemax)) / 2;
- let degrees = 360 * avg;
- let x = 125 * Math.cos(degrees * Math.PI / 180);
- let y = -100 * Math.sin(degrees * Math.PI / 180);
+ const avg = ((circlemin / circlemax) + ((circlemin + 1) / circlemax)) / 2;
+ const degrees = 360 * avg;
+ const x = 125 * Math.cos(degrees * Math.PI / 180);
+ const y = -100 * Math.sin(degrees * Math.PI / 180);
return y;
}
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 548066f1c..7c58a5148 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -142,7 +142,7 @@ export class ScreenshotBox extends DocAnnotatableComponent<FieldViewProps, Scree
toggleRecording = action(async () => {
this._screenCapture = !this._screenCapture;
this._videoRef!.srcObject = !this._screenCapture ? undefined : await (navigator.mediaDevices as any).getDisplayMedia({ video: true });
- })
+ });
private get uIButtons() {
return (<div className="screenshotBox-uiButtons">
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 591864f2c..838fbefb1 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -63,7 +63,7 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument>
this.layoutDoc._height = NumCast(this.layoutDoc._width) / youtubeaspect;
}
} else if (field?.url) {
- var result = await WebRequest.get(Utils.CorsProxy(field.url.href));
+ const result = await WebRequest.get(Utils.CorsProxy(field.url.href));
this.dataDoc.text = htmlToText.fromString(result.content);
}
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index 05c70b74a..5913c5a82 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -61,11 +61,10 @@ export default class PDFMenu extends AntimodeMenu {
e.preventDefault();
}
- @action
- togglePin = (e: React.MouseEvent) => {
+ togglePin = action((e: React.MouseEvent) => {
this.Pinned = !this.Pinned;
!this.Pinned && (this.Highlighting = false);
- }
+ })
@action
highlightClicked = (e: React.MouseEvent) => {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index a1e7d5c2a..71495d95f 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -238,7 +238,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument
this._pdfViewer.currentScaleValue = this._zoomed = 1;
this.gotoPage(this.Document.curPage || 1);
document.removeEventListener("pagesinit", this.pagesinit);
- })
+ });
createPdfViewer() {
if (!this._mainCont.current) { // bcz: I don't think this is ever triggered or needed
@@ -575,7 +575,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument
clipDoc._scrollTop = this.marqueeY();
const targetDoc = Docs.Create.TextDocument("", { _width: 200, _height: 200, title: "Note linked to " + this.props.Document.title });
Doc.GetProto(targetDoc).data = new List<Doc>([clipDoc]);
- DocumentView.makeCustomViewClicked(targetDoc, undefined, Docs.Create.StackingDocument, "slideView", undefined);
+ DocumentView.makeCustomViewClicked(targetDoc, Docs.Create.StackingDocument, "slideView", undefined);
// const targetDoc = Docs.Create.TextDocument("", { _width: 200, _height: 200, title: "Note linked to " + this.props.Document.title });
// Doc.GetProto(targetDoc).snipped = this.dataDoc[this.props.fieldKey][Copy]();
// const snipLayout = Docs.Create.PdfDocument("http://www.msn.com", { title: "snippetView", isTemplateDoc: true, isTemplateForField: "snipped", _fitWidth: true, _width: this.marqueeWidth(), _height: this.marqueeHeight(), _scrollTop: this.marqueeY() });
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 9bd42b516..586365f6e 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -347,7 +347,7 @@ export class SearchBox extends React.Component {
<input value={this._searchString} onChange={this.onChange} type="text" placeholder="Search..." id="search-input" ref={this.inputRef}
className="searchBox-barChild searchBox-input" onPointerDown={this.openSearch} onKeyPress={this.enter} onFocus={this.openSearch}
style={{ width: this._searchbarOpen ? "500px" : "100px" }} />
- <button className="searchBox-barChild searchBox-filter" title="Advanced Filtering Options" onClick={FilterBox.Instance.openFilter} onPointerDown={FilterBox.Instance.stopProp}><FontAwesomeIcon icon="ellipsis-v" color="white" /></button>
+ <button className="searchBox-barChild searchBox-filter" title="Advanced Filtering Options" onClick={() => { }} onPointerDown={FilterBox.Instance.stopProp}><FontAwesomeIcon icon="ellipsis-v" color="white" /></button>
</div>
<div className="searchBox-quickFilter" onPointerDown={this.openSearch}>
<div className="filter-panel"><IconBar /></div>
diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx
index 9c339e986..1d52ba38f 100644
--- a/src/client/views/webcam/DashWebRTCVideo.tsx
+++ b/src/client/views/webcam/DashWebRTCVideo.tsx
@@ -36,7 +36,7 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV
*/
private onEnterKeyDown = (e: React.KeyboardEvent) => {
if (e.keyCode === 13) {
- let submittedTitle = this.roomText!.value;
+ const submittedTitle = this.roomText!.value;
this.roomText!.value = "";
this.roomText!.blur();
initialize(submittedTitle, this.changeUILook);
@@ -56,7 +56,7 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV
}
render() {
- let content =
+ const content =
<div className="webcam-cont" style={{ width: "100%", height: "100%" }}>
<div className="webcam-header">DashWebRTC</div>
<input id="roomName" type="text" placeholder="Enter room name" ref={(e) => this.roomText = e!} onKeyDown={this.onEnterKeyDown} />
@@ -72,8 +72,8 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV
</div>
</div >;
- let frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting;
- let classname = "webBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !DocumentDecorations.Instance.Interacting ? "-interactive" : "");
+ const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting;
+ const classname = "webBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !DocumentDecorations.Instance.Interacting ? "-interactive" : "");
return (
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 5d3a517ae..1d2d57b96 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -199,6 +199,8 @@ export default class MobileInterface extends React.Component {
DataDoc={undefined}
LibraryPath={emptyPath}
fieldKey={""}
+ dropAction={"alias"}
+ bringToFront={emptyFunction }
addDocTab={returnFalse}
pinToPres={emptyFunction}
PanelHeight={() => window.innerHeight}
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 8110130b0..85926e393 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -353,7 +353,7 @@ export namespace Doc {
// and returns the document who's proto is undefined or whose proto is marked as a base prototype ('isPrototype').
export function GetProto(doc: Doc): Doc {
if (doc instanceof Promise) {
- console.log("GetProto: error: got Promise insead of Doc")
+ console.log("GetProto: error: got Promise insead of Doc");
}
const proto = doc && (Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc));
return proto === doc ? proto : Doc.GetProto(proto);
@@ -521,8 +521,7 @@ export namespace Doc {
console.log("No, no, no!");
return { layout: childDoc, data: childDoc };
}
- const existingResolvedDataDoc = childDoc[DataSym] !== Doc.GetProto(childDoc)[DataSym] && childDoc[DataSym];
- const resolvedDataDoc = existingResolvedDataDoc || (Doc.AreProtosEqual(containerDataDoc, containerDoc) || !containerDataDoc || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField && !childDoc.PARAMS) ? undefined : containerDataDoc);
+ const resolvedDataDoc = (Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField && !childDoc.PARAMS) ? undefined : containerDataDoc);
return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc, "(" + StrCast(containerDoc.PARAMS) + ")"), data: resolvedDataDoc };
}
@@ -566,7 +565,8 @@ export namespace Doc {
} else if (cfield instanceof ComputedField) {
copy[key] = ComputedField.MakeFunction(cfield.script.originalScript);
} else if (field instanceof ObjectField) {
- copy[key] = key.includes("layout[") && doc[key] instanceof Doc ? Doc.MakeCopy(doc[key] as Doc, false) : ObjectField.MakeCopy(field);
+ copy[key] = key.includes("layout[") && doc[key] instanceof Doc ? Doc.MakeCopy(doc[key] as Doc, false) :
+ doc[key] instanceof Doc ? doc[key] : ObjectField.MakeCopy(field);
} else if (field instanceof Promise) {
debugger; //This shouldn't happend...
} else {
@@ -593,7 +593,10 @@ export namespace Doc {
let _applyCount: number = 0;
export function ApplyTemplate(templateDoc: Doc) {
if (templateDoc) {
- const applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), StrCast(templateDoc.layoutKey, "layout"), templateDoc.title + "(..." + _applyCount++ + ")");
+ const target = Doc.MakeDelegate(new Doc());
+ const targetKey = StrCast(templateDoc.layoutKey, "layout");
+ const applied = ApplyTemplateTo(templateDoc, target, targetKey, templateDoc.title + "(..." + _applyCount++ + ")");
+ target.layoutKey = targetKey;
applied && (Doc.GetProto(applied).type = templateDoc.type);
return applied;
}
@@ -616,7 +619,6 @@ export namespace Doc {
Doc.GetProto(target)[targetKey] = new PrefetchProxy(templateDoc);
}
}
- target.layoutKey = targetKey;
return target;
}
@@ -698,7 +700,7 @@ export namespace Doc {
// the document containing the view layout information - will be the Document itself unless the Document has
// a layout field or 'layout' is given.
export function Layout(doc: Doc, layout?: Doc): Doc {
- const overrideLayout = layout && Cast(doc["data-layout[" + layout[Id] + "]"], Doc, null);
+ const overrideLayout = layout && Cast(doc[`${StrCast(layout.isTemplateForField, "data")}-layout[` + layout[Id] + "]"], Doc, null);
return overrideLayout || doc[LayoutSym] || doc;
}
export function SetLayout(doc: Doc, layout: Doc | string) { doc[StrCast(doc.layoutKey, "layout")] = layout; }
@@ -883,9 +885,10 @@ export namespace Doc {
}
const options = optionsCollection as Doc;
const targetDoc = doc && Doc.GetProto(Cast(doc.rootDocument, Doc, null) || doc);
- targetDoc && (targetDoc.backgroundColor = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.rootDocument||this)["${enumeratedFieldKey}"])?._backgroundColor || "white"`, undefined, { options }));
- targetDoc && (targetDoc.color = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.rootDocument||this)["${enumeratedFieldKey}"]).color || "black"`, undefined, { options }));
- targetDoc && (targetDoc.borderRounding = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.rootDocument||this)["${enumeratedFieldKey}"]).borderRounding`, undefined, { options }));
+ const docFind = `options.data.find(doc => doc.title === (this.rootDocument||this)["${enumeratedFieldKey}"])?`;
+ targetDoc && (targetDoc.backgroundColor = ComputedField.MakeFunction(docFind + `._backgroundColor || "white"`, undefined, { options }));
+ targetDoc && (targetDoc.color = ComputedField.MakeFunction(docFind + `.color || "black"`, undefined, { options }));
+ targetDoc && (targetDoc.borderRounding = ComputedField.MakeFunction(docFind + `.borderRounding`, undefined, { options }));
enumerations.map(enumeration => {
const found = DocListCast(options.data).find(d => d.title === enumeration.title);
if (found) {
@@ -920,7 +923,9 @@ Scripting.addGlobal(function curPresentationItem() {
});
Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); });
Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
- const docs = DocListCast(Doc.UserDoc().SelectedDocs).filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCUMENT && d.type !== DocumentType.KVP && (!excludeCollections || !Cast(d.data, listSpec(Doc), null)));
+ const docs = DocListCast(Doc.UserDoc().SelectedDocs).
+ filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCUMENT && d.type !== DocumentType.KVP &&
+ (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
return docs.length ? new List(docs) : prevValue;
});
Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: "check" | "x" | undefined) { Doc.setDocFilter(container, key, value, modifiers); });
diff --git a/src/new_fields/RichTextUtils.ts b/src/new_fields/RichTextUtils.ts
index 1d90c984d..c211b3d3c 100644
--- a/src/new_fields/RichTextUtils.ts
+++ b/src/new_fields/RichTextUtils.ts
@@ -274,7 +274,7 @@ export namespace RichTextUtils {
const backingDocId = StrCast(textNote[guid]);
if (!backingDocId) {
const backingDoc = Docs.Create.ImageDocument(agnostic, { _width: 300, _height: 300 });
- DocumentView.makeCustomViewClicked(backingDoc, undefined, Docs.Create.FreeformDocument);
+ DocumentView.makeCustomViewClicked(backingDoc, Docs.Create.FreeformDocument);
docid = backingDoc[Id];
textNote[guid] = docid;
} else {
@@ -403,7 +403,7 @@ export namespace RichTextUtils {
let exported = (await Cast(linkDoc.anchor2, Doc))!;
if (!exported.customLayout) {
exported = Doc.MakeAlias(exported);
- DocumentView.makeCustomViewClicked(exported, undefined, Docs.Create.FreeformDocument);
+ DocumentView.makeCustomViewClicked(exported, Docs.Create.FreeformDocument);
linkDoc.anchor2 = exported;
}
url = Utils.shareUrl(exported[Id]);
diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts
index e06452a4e..91ea32bee 100644
--- a/src/new_fields/documentSchemas.ts
+++ b/src/new_fields/documentSchemas.ts
@@ -61,7 +61,8 @@ export const documentSchema = createSchema({
fontSize: "string",
fitToBox: "boolean", // whether freeform view contents should be zoomed/panned to fill the area of the document view
letterSpacing: "string",
- textTransform: "string"
+ textTransform: "string",
+ childTemplateName: "string" // the name of a template to use to override the layoutKey when rendering a document in DocumentBox
});
export const positionSchema = createSchema({
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index 3ab1b299b..8c719ccd8 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -12,8 +12,9 @@ function _readOnlySetter(): never {
throw new Error("Documents can't be modified in read-only mode");
}
+const tracing = false;
export function TraceMobx() {
- // trace();
+ tracing && trace();
}
export interface GetterResult {
diff --git a/src/server/DashSession/Session/agents/applied_session_agent.ts b/src/server/DashSession/Session/agents/applied_session_agent.ts
index 46c9e22ed..12064668b 100644
--- a/src/server/DashSession/Session/agents/applied_session_agent.ts
+++ b/src/server/DashSession/Session/agents/applied_session_agent.ts
@@ -44,7 +44,7 @@ export abstract class AppliedSessionAgent {
if (!this.launched) {
this.launched = true;
if (isMaster) {
- this.sessionMonitorRef = Monitor.Create()
+ this.sessionMonitorRef = Monitor.Create();
const sessionKey = await this.initializeMonitor(this.sessionMonitorRef);
this.sessionMonitorRef.finalize(sessionKey);
} else {
diff --git a/src/server/DashSession/Session/agents/monitor.ts b/src/server/DashSession/Session/agents/monitor.ts
index 6f8d25614..ee8afee65 100644
--- a/src/server/DashSession/Session/agents/monitor.ts
+++ b/src/server/DashSession/Session/agents/monitor.ts
@@ -167,7 +167,7 @@ export class Monitor extends IPCMessageReceiver {
* and pass down any variables the pertinent to the child processes as environment variables.
*/
private loadAndValidateConfiguration = (): Configuration => {
- let config: Configuration;
+ let config: Configuration | undefined;
try {
console.log(this.timestamp(), cyan("validating configuration..."));
config = JSON.parse(readFileSync('./session.config.json', 'utf8'));
diff --git a/src/server/DashSession/Session/agents/promisified_ipc_manager.ts b/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
index 9f0db8330..feff568e1 100644
--- a/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
+++ b/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
@@ -35,8 +35,8 @@ export type MessageHandler<T = any> = (args: T) => (any | Promise<any>);
* When a message is emitted, it is embedded with private metadata
* to facilitate the resolution of promises, etc.
*/
-interface InternalMessage extends Message { metadata: Metadata }
-interface Metadata { isResponse: boolean; id: string }
+interface InternalMessage extends Message { metadata: Metadata; }
+interface Metadata { isResponse: boolean; id: string; }
type InternalMessageHandler = (message: InternalMessage) => (any | Promise<any>);
/**
@@ -133,7 +133,7 @@ export class PromisifiedIPCManager {
Object.keys(pendingMessages).forEach(id => {
const error: ErrorLike = { name: "ManagerDestroyed", message: "The IPC manager was destroyed before the response could be returned." };
const message: InternalMessage = { name: pendingMessages[id], args: { error }, metadata: { id, isResponse: true } };
- this.target.send?.(message)
+ this.target.send?.(message);
});
this.pendingMessages = {};
}
diff --git a/src/server/Websocket/Websocket.ts b/src/server/Websocket/Websocket.ts
index c5dc22912..9f9fc9619 100644
--- a/src/server/Websocket/Websocket.ts
+++ b/src/server/Websocket/Websocket.ts
@@ -55,8 +55,8 @@ export namespace WebSocket {
socket.on('create or join', function (room) {
console.log('Received request to create or join room ' + room);
- var clientsInRoom = socket.adapter.rooms[room];
- var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;
+ const clientsInRoom = socket.adapter.rooms[room];
+ const numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;
console.log('Room ' + room + ' now has ' + numClients + ' client(s)');
if (numClients === 0) {
@@ -76,8 +76,8 @@ export namespace WebSocket {
});
socket.on('ipaddr', function () {
- var ifaces = networkInterfaces();
- for (var dev in ifaces) {
+ const ifaces = networkInterfaces();
+ for (const dev in ifaces) {
ifaces[dev].forEach(function (details) {
if (details.family === 'IPv4' && details.address !== '127.0.0.1') {
socket.emit('ipaddr', details.address);
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index d9f354cf2..4f82da44d 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -55,6 +55,16 @@ export class CurrentUserUtils {
Doc.addFieldEnumerations(Doc.GetProto(noteTemplates[4]), "taskStatus", taskStatusValues);
doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(noteTemplates.map(nt => makeTemplate(nt, true, StrCast(nt.style)) ? nt : nt), { title: "Note Layouts", _height: 75 }));
}
+ static setupDefaultIconTypes(doc: Doc, buttons?: string[]) {
+ doc.iconView = new PrefetchProxy(Docs.Create.TextDocument("", { title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
+ Doc.GetProto(doc.iconView as any as Doc).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
+ doc.isTemplateDoc = makeTemplate(doc.iconView as any as Doc);
+ doc.iconImageView = new PrefetchProxy(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
+ doc.isTemplateDoc = makeTemplate(doc.iconImageView as any as Doc, true, "image_icon");
+ doc.iconColView = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
+ doc.isTemplateDoc = makeTemplate(doc.iconColView as any as Doc, true, "collection_icon");
+ doc.iconViews = Docs.Create.TreeDocument([doc.iconView as any as Doc, doc.iconImageView as any as Doc, doc.iconColView as any as Doc], { title: "icon types", _height: 75 });
+ }
// setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools
static setupCreatorButtons(doc: Doc, alreadyCreatedButtons?: string[]) {
@@ -63,7 +73,7 @@ export class CurrentUserUtils {
doc.activePen = doc;
const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [
{ title: "collection", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: emptyCollection },
- { title: "preview", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(ComputedField.MakeFunction("selectedDocs(this,true,[_last_])?.[0]"), { _width: 250, _height: 250, title: "container" })' },
+ { title: "preview", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]"), { _width: 250, _height: 250, title: "container" })' },
{ title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", {_width: 300, _height: 300, title: "New Webpage" })' },
{ title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' },
{ title: "buxton", icon: "cloud-upload-alt", ignoreClick: true, drag: "Docs.Create.Buxton()" },
@@ -278,14 +288,6 @@ export class CurrentUserUtils {
Doc.GetProto(descriptionTemplate).layout = FormattedTextBox.LayoutString("description");
descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView");
- doc.iconView = new PrefetchProxy(Docs.Create.TextDocument("", { title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
- Doc.GetProto(doc.iconView as any as Doc).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
- doc.isTemplateDoc = makeTemplate(doc.iconView as any as Doc);
- doc.iconImageView = new PrefetchProxy(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
- doc.isTemplateDoc = makeTemplate(doc.iconImageView as any as Doc, true, "image_icon");
- doc.iconColView = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
- doc.isTemplateDoc = makeTemplate(doc.iconColView as any as Doc, true, "collection_icon");
-
const ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ ...opts, dontSelect: true, dropAction: "alias", removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100 })) as any as Doc;
const blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
...opts,
@@ -324,6 +326,7 @@ export class CurrentUserUtils {
static updateUserDocument(doc: Doc) {
doc.title = Doc.CurrentUserEmail;
new InkingControl();
+ (doc.iconTypes === undefined) && CurrentUserUtils.setupDefaultIconTypes(doc);
(doc.noteTypes === undefined) && CurrentUserUtils.setupDefaultDocTemplates(doc);
(doc.optionalRightCollection === undefined) && CurrentUserUtils.setupMobileUploads(doc);
(doc.overlays === undefined) && CurrentUserUtils.setupOverlays(doc);
diff --git a/src/server/database.ts b/src/server/database.ts
index 055f04c49..fc91ff3a2 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -328,7 +328,7 @@ export namespace Database {
export const LogUpload = async (information: Upload.ImageInformation) => {
const bundle = {
- _id: Utils.GenerateDeterministicGuid(String(information.contentSize!)),
+ _id: Utils.GenerateDeterministicGuid(String(information.contentSize)),
...information
};
return Instance.insert(bundle, AuxiliaryCollections.GooglePhotosUploadHistory);
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index 7b2228831..1150118f7 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -123,7 +123,7 @@ function registerCorsProxy(server: express.Express) {
const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
server.use("/corsProxy", (req, res) => {
- let requrl = decodeURIComponent(req.url.substring(1));
+ const requrl = decodeURIComponent(req.url.substring(1));
const referer = req.headers.referer ? decodeURIComponent(req.headers.referer) : "";
// cors weirdness here...
// if the referer is a cors page and the cors() route (I think) redirected to /corsProxy/<path> and the requested url path was relative,