aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusodhi <61431818+usodhi@users.noreply.github.com>2020-09-22 13:51:49 +0530
committerusodhi <61431818+usodhi@users.noreply.github.com>2020-09-22 13:51:49 +0530
commita9dad1837ffa66b0da304dd2f6f5e35b3ab4a7b8 (patch)
tree69853de7a2a8faa597e12dd4e05a211b3c24b618
parent8fad5a8e842aaed6540d37f6a3a4ba3a3c2abe9b (diff)
parent02029b5cad1c27e65630a63cd4d2b632ed6973cd (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into acls_uv
-rw-r--r--deploy/assets/pinWithView.pngbin0 -> 89557 bytes
-rw-r--r--src/client/documents/Documents.ts3
-rw-r--r--src/client/views/DocumentDecorations.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx18
-rw-r--r--src/client/views/collections/CollectionTreeView.scss1
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx46
-rw-r--r--src/client/views/collections/CollectionView.tsx3
-rw-r--r--src/client/views/collections/TreeView.tsx21
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx19
-rw-r--r--src/client/views/nodes/FilterBox.tsx48
-rw-r--r--src/client/views/nodes/PresBox.tsx16
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx82
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx13
-rw-r--r--src/client/views/search/SearchBox.tsx6
-rw-r--r--src/fields/util.ts2
15 files changed, 149 insertions, 131 deletions
diff --git a/deploy/assets/pinWithView.png b/deploy/assets/pinWithView.png
new file mode 100644
index 000000000..eb0d09689
--- /dev/null
+++ b/deploy/assets/pinWithView.png
Binary files differ
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index f7ab955f3..2d02742c5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -52,6 +52,7 @@ import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
import { DocumentType } from "./DocumentTypes";
import { FilterBox } from "../views/nodes/FilterBox";
import { SharingPermissions } from "../../fields/util";
+import { SharingManager } from "../util/SharingManager";
const path = require('path');
const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
@@ -601,7 +602,7 @@ export namespace Docs {
viewDoc.author = Doc.CurrentUserEmail;
viewDoc.type !== DocumentType.LINK && DocUtils.MakeLinkToActiveAudio(viewDoc);
- if (Doc.UserDoc()?.defaultAclPrivate) viewDoc["acl-Public"] = dataDoc["acl-Public"] = "Not Shared";
+ viewDoc["acl-Public"] = dataDoc["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Add;
return Doc.assign(viewDoc, delegateProps, true);
}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 795208c91..9432d1ffb 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -139,7 +139,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
dragData.offset = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).transformDirection(e.x - left, e.y - top);
dragData.moveDocument = dragDocView.props.moveDocument;
dragData.isSelectionMove = true;
- dragData.dropAction = dragDocView.props.dropAction as dropActionType;
+ dragData.dropAction = dragDocView.props.dropAction;
this.Interacting = true;
this._hidden = true;
DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(dv => dv.ContentDiv!), dragData, e.x, e.y, {
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 18ae260e8..2443bd34e 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -71,6 +71,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
@observable protected _isEditing: boolean = false;
protected _focusRef = React.createRef<HTMLDivElement>();
protected _rowDoc = this.props.rowProps.original;
+ protected _rowDataDoc = Doc.GetProto(this.props.rowProps.original);
protected _dropDisposer?: DragManager.DragDropDisposer;
@observable contents: string = "";
@@ -126,11 +127,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
private drop = (e: Event, de: DragManager.DropEvent) => {
if (de.complete.docDragData) {
if (de.complete.docDragData.draggedDocuments.length === 1) {
- this._rowDoc[this.renderFieldKey] = de.complete.docDragData.draggedDocuments[0];
+ this._rowDataDoc[this.renderFieldKey] = de.complete.docDragData.draggedDocuments[0];
}
else {
const coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], de.complete.docDragData.draggedDocuments, {});
- this._rowDoc[this.renderFieldKey] = coll;
+ this._rowDataDoc[this.renderFieldKey] = coll;
}
e.stopPropagation();
}
@@ -164,8 +165,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
@computed get renderFieldKey() { return CollectionSchemaCell.resolvedFieldKey(this.props.rowProps.column.id!, this.props.rowProps.original); }
onItemDown = async (e: React.PointerEvent) => {
if (this.props.Document._searchDoc) {
- const doc = Doc.GetProto(this._rowDoc);
- const aliasdoc = await SearchUtil.GetAliasesOfDocument(doc);
+ const aliasdoc = await SearchUtil.GetAliasesOfDocument(this._rowDataDoc);
const targetContext = aliasdoc.length <= 0 ? undefined : Cast(aliasdoc[0].context, Doc, null);
DocumentManager.Instance.jumpToDocument(this._rowDoc, false, () => undefined, targetContext);
}
@@ -238,10 +238,10 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
let retVal = false;
if (value.startsWith(":=") || value.startsWith("=:=")) {
const script = value.substring(value.startsWith("=:=") ? 3 : 2);
- retVal = this.props.setComputed(script, value.startsWith(":=") ? Doc.GetProto(this.props.Document) : this.props.Document, this.renderFieldKey, this.props.row, this.props.col);
+ retVal = this.props.setComputed(script, value.startsWith(":=") ? this._rowDataDoc : this._rowDoc, this.renderFieldKey, this.props.row, this.props.col);
} else {
const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
- script.compiled && (retVal = this.applyToDoc(this._rowDoc, this.props.row, this.props.col, script.run));
+ script.compiled && (retVal = this.applyToDoc(this._rowDataDoc, this.props.row, this.props.col, script.run));
}
if (retVal) {
this._isEditing = false; // need to set this here. otherwise, the assignment of the field will invalidate & cause render() to be called with the wrong value for 'editing'
@@ -251,10 +251,10 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
})}
OnFillDown={async (value: string) => {
const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
- script.compiled && DocListCast(field).
+ script.compiled && DocListCast(this.props.Document[this.props.fieldKey]).
forEach((doc, i) => value.startsWith(":=") ?
- this.props.setComputed(value.substring(2), doc, this.renderFieldKey, i, this.props.col) :
- this.applyToDoc(doc, i, this.props.col, script.run));
+ this.props.setComputed(value.substring(2), Doc.GetProto(doc), this.renderFieldKey, i, this.props.col) :
+ this.applyToDoc(Doc.GetProto(doc), i, this.props.col, script.run));
}}
/>
:
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 20bfc0e9d..c5add7cfb 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -28,6 +28,7 @@
.no-indent {
padding-left: 0;
+ width: max-content;
}
.editableView-container {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index efbe5581b..257eaf7f0 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -41,7 +41,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
private _mainEle?: HTMLDivElement;
public _uniqueId = Utils.GenerateGuid();
- @computed get doc() { return this.props.Document; }
+ @computed get doc() { TraceMobx(); return this.props.Document; }
@computed get dataDoc() { return this.props.DataDoc || this.doc; }
protected createTreeDropTarget = (ele: HTMLDivElement) => {
@@ -82,7 +82,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
return true;
}
return false;
- })
+ });
@action
addDoc = (doc: Doc | Doc[], relativeTo: Opt<Doc>, before?: boolean): boolean => {
const doAddDoc = (doc: Doc | Doc[]) =>
@@ -117,7 +117,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
onTreeDrop = (e: React.DragEvent) => this.onExternalDrop(e, {});
@computed get renderClearButton() {
- return <div key="toolbar">
+ return !this.doc.allowClear ? (null) : <div key="toolbar">
<button className="toolbar-button round-button" title="Empty" onClick={undoBatch(action(() => Doc.GetProto(this.doc)[this.props.fieldKey] = undefined))}>
<FontAwesomeIcon icon={"trash"} size="sm" />
</button>
@@ -192,37 +192,45 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
whenActiveChanged = (isActive: boolean) => { this.props.whenActiveChanged(this._isChildActive = isActive); };
active = (outsideReaction: boolean | undefined) => this.props.active(outsideReaction) || this._isChildActive;
- render() {
+ @computed get treeChildren() {
+ TraceMobx();
+ return this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs;
+ }
+ @computed get treeViewElements() {
TraceMobx();
- if (!(this.doc instanceof Doc)) return (null);
const dropAction = StrCast(this.doc.childDropAction) as dropActionType;
const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(d, target, addDoc);
- const childDocs = this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs;
- const childElements = childDocs && TreeView.GetChildElements(childDocs, this, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove,
+ return TreeView.GetChildElements(this.treeChildren, this, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove,
moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform,
this.outerXf, this.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
BoolCast(this.doc.treeViewPreventOpen), [], this.props.onCheckedClick,
this.onChildClick, this.props.ignoreFields, true, this.whenActiveChanged);
+ }
+ @computed get titleBar() {
const hideTitle = this.props.treeViewHideTitle || this.doc.treeViewHideTitle;
- const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.doc.backgroundColor) || this.props.backgroundColor?.(this.doc, this.props.renderDepth);
+ return hideTitle ? (null) : (this.doc.treeViewOutlineMode ? this.documentTitle : this.editableTitle)(this.treeChildren);
+ }
+ render() {
+ TraceMobx();
+ if (!(this.doc instanceof Doc)) return (null);
+ const background = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.doc.backgroundColor) || this.props.backgroundColor?.(this.doc, this.props.renderDepth);
+ const paddingX = `${NumCast(this.doc._xPadding, 10)}px`;
+ const paddingTop = `${NumCast(this.doc._yPadding, 20)}px`;
+ const pointerEvents = !this.props.active() && !SnappingManager.GetIsDragging() && !this._isChildActive ? "none" : undefined;
- return !childDocs ? (null) : (
+ return !this.treeChildren ? (null) : (
<div className="collectionTreeView-container" onContextMenu={this.onContextMenu}>
<div className="collectionTreeView-dropTarget"
- style={{
- background: backgroundColor,
- paddingLeft: `${NumCast(this.doc._xPadding, 10)}px`,
- paddingRight: `${NumCast(this.doc._xPadding, 10)}px`,
- paddingTop: `${NumCast(this.doc._yPadding, 20)}px`,
- pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() && !this._isChildActive ? "none" : undefined,
- }}
+ style={{ background, paddingLeft: paddingX, paddingRight: paddingX, paddingTop, pointerEvents }}
onWheel={(e) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()}
onDrop={this.onTreeDrop}
ref={this.createTreeDropTarget}>
- {hideTitle ? (null) : (this.doc.treeViewOutlineMode ? this.documentTitle : this.editableTitle)(childDocs)}
- {this.doc.allowClear ? this.renderClearButton : (null)}
- <ul className="no-indent" style={{ width: "max-content" }} > {childElements} </ul>
+ {this.titleBar}
+ {this.renderClearButton}
+ <ul className="no-indent">
+ {this.treeViewElements}
+ </ul>
</div >
</div>
);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c9496d374..e35474b81 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -144,7 +144,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
added.forEach(d => {
for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
if (d.author === key.substring(4).replace("_", ".") && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d, true);
- else distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true);
+ else if (this.props.Document[key] === SharingPermissions.Admin) distributeAcls(key, SharingPermissions.Add, d, true);
+ //else distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true);
}
});
}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index edb703135..486e44f6b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -83,9 +83,9 @@ export class TreeView extends React.Component<TreeViewProps> {
private _uniqueId = Utils.GenerateGuid();
private _editMaxWidth: number | string = 0;
- get doc() { return this.props.document; }
+ @computed get doc() { TraceMobx(); return this.props.document; }
get noviceMode() { return BoolCast(Doc.UserDoc().noviceMode, false); }
- get displayName() { return "TreeView(" + this.doc.title + ")"; } // this makes mobx trace() statements more descriptive
+ get displayName() { return "TreeView(" + this.props.document.title + ")"; } // this makes mobx trace() statements more descriptive
get treeViewLockExpandedView() { return this.doc.treeViewLockExpandedView; }
get defaultExpandedView() { return StrCast(this.doc.treeViewDefaultExpandedView, this.noviceMode || this.outlineMode ? "layout" : "fields"); }
get treeViewDefaultExpandedView() { return this.treeViewLockExpandedView ? this.defaultExpandedView : (this.childDocs ? this.fieldKey : this.defaultExpandedView); }
@@ -100,14 +100,14 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); }
@computed get dataDoc() { return this.doc[DataSym]; }
@computed get layoutDoc() { return Doc.Layout(this.doc); }
- @computed get fieldKey() { const splits = StrCast(Doc.LayoutField(this.doc)).split("fieldKey={\'"); return splits.length > 1 ? splits[1].split("\'")[0] : "data"; }
+ @computed get fieldKey() { TraceMobx(); const splits = StrCast(Doc.LayoutField(this.doc)).split("fieldKey={\'"); return splits.length > 1 ? splits[1].split("\'")[0] : "data"; }
childDocList(field: string) {
const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined;
return ((this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
(layout ? DocListCastOrNull(layout[field]) : undefined) || // else if there's a layout doc, display it's fields
DocListCastOrNull(this.doc[field])); // otherwise use the document's data field
}
- @computed get childDocs() { return this.childDocList(this.fieldKey); }
+ @computed get childDocs() { TraceMobx(); return this.childDocList(this.fieldKey); }
@computed get childLinks() { return this.childDocList("links"); }
@computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); }
@computed get boundsOfCollectionDocument() {
@@ -130,13 +130,12 @@ export class TreeView extends React.Component<TreeViewProps> {
constructor(props: any) {
super(props);
- console.log("Ttile = " + this.props.document.title);
const titleScript = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); documentView.select();} `, { documentView: "any" });
const openScript = ScriptField.MakeScript(`openOnRight(self)`);
const treeOpenScript = ScriptField.MakeScript(`self.treeViewOpen = !self.treeViewOpen`);
this._editTitleScript = !Doc.IsSystem(this.props.document) ? titleScript && (() => titleScript) : treeOpenScript && (() => treeOpenScript);
this._openScript = !Doc.IsSystem(this.props.document) ? openScript && (() => openScript) : undefined;
- if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false);
+ if (Doc.GetT(this.props.document, "editTitle", "string", true) === "*") Doc.SetInPlace(this.props.document, "editTitle", this._uniqueId, false);
}
protected createTreeDropTarget = (ele: HTMLDivElement) => {
@@ -185,7 +184,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}
public static makeTextBullet() {
- const bullet = Docs.Create.TextDocument("-text-", { title: "-title-", _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewOutlineMode: true, x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _backgroundColor: "transparent", _width: 1000, _height: 10 });
+ const bullet = Docs.Create.TextDocument("-text-", { title: "-title-", forceActive: true, _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewOutlineMode: true, x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _backgroundColor: "transparent", _width: 1000, _height: 10 });
Doc.GetProto(bullet).layout = CollectionView.LayoutString("data");
Doc.GetProto(bullet).title = ComputedField.MakeFunction('self.text?.Text');
Doc.GetProto(bullet).data = new List<Doc>([]);
@@ -659,8 +658,7 @@ export class TreeView extends React.Component<TreeViewProps> {
onChildClick: undefined | (() => ScriptField),
ignoreFields: string[] | undefined,
firstLevel: boolean,
- whenActiveChanged: (isActive: boolean) => void
- ) {
+ whenActiveChanged: (isActive: boolean) => void) {
const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField);
if (viewSpecScript) {
childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result);
@@ -691,7 +689,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}
const rowWidth = () => panelWidth() - 20;
- return docs.map((child, i) => {
+ return docs.filter(child => child instanceof Doc).map((child, i) => {
const pair = Doc.GetLayoutDataDocPair(containingCollection, dataDoc, child);
if (!pair.layout || pair.data instanceof Promise) {
return (null);
@@ -727,13 +725,12 @@ export class TreeView extends React.Component<TreeViewProps> {
const aspect = NumCast(childLayout._nativeWidth, 0) / NumCast(childLayout._nativeHeight, 0);
return aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]();
};
- return !(child instanceof Doc) ? (null) : <TreeView
+ return <TreeView key={child[Id]}
document={pair.layout}
dataDoc={pair.data}
containingCollection={containingCollection}
prevSibling={docs[i]}
treeView={treeView}
- key={child[Id]}
indentDocument={indent}
outdentDocument={!parentCollectionDoc ? undefined : outdent}
onCheckedClick={onCheckedClick}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 67e7c1986..e8c3662aa 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -114,22 +114,13 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & Fo
}> {
@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"); // bcz: replaced this with below... is it right?
if (this.props.LayoutTemplateString) return this.props.LayoutTemplateString;
+ if (!this.layoutDoc) return "<p>awaiting layout</p>";
+ if (this.props.layoutKey === "layout_keyValue") return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString("data"));
const layout = Cast(this.layoutDoc[this.layoutDoc === this.props.Document && this.props.layoutKey ? this.props.layoutKey : StrCast(this.layoutDoc.layoutKey, "layout")], "string");
- 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>";
- }
+ if (layout === undefined) return this.props.Document.data ? "<FieldView {...props} fieldKey='data' />" : KeyValueBox.LayoutString(this.layoutDoc.proto ? "proto" : "");
+ if (typeof layout === "string") return layout;
+ return "<p>Loading layout</p>";
}
get dataDoc() {
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 748af89ef..067477dcf 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -19,6 +19,7 @@ import { SearchBox } from "../search/SearchBox";
import { FieldView, FieldViewProps } from './FieldView';
import './FilterBox.scss';
import { Scripting } from "../../util/Scripting";
+import { values } from "lodash";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -49,6 +50,39 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
this.allDocs.forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key)));
return Array.from(keys.keys()).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("_") && !key.startsWith("acl")) || noviceFields.includes(key)).sort();
}
+
+ gatherFieldValues(dashboard: Doc, facetKey: string) {
+ const childDocs = DocListCast((dashboard.data as any)[0].data);
+ const valueSet = new Set<string>();
+ let rtFields = 0;
+ childDocs.forEach((d) => {
+ const facetVal = d[facetKey];
+ if (facetVal instanceof RichTextField) rtFields++;
+ valueSet.add(Field.toString(facetVal as Field));
+ const fieldKey = Doc.LayoutFieldKey(d);
+ const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView");
+ const data = d[annos ? fieldKey + "-annotations" : fieldKey];
+ if (data !== undefined) {
+ let subDocs = DocListCast(data);
+ if (subDocs.length > 0) {
+ let newarray: Doc[] = [];
+ while (subDocs.length > 0) {
+ newarray = [];
+ subDocs.forEach((t) => {
+ const facetVal = t[facetKey];
+ if (facetVal instanceof RichTextField) rtFields++;
+ valueSet.add(Field.toString(facetVal as Field));
+ const fieldKey = Doc.LayoutFieldKey(t);
+ const annos = !Field.toString(Doc.LayoutField(t) as Field).includes("CollectionView");
+ DocListCast(t[annos ? fieldKey + "-annotations" : fieldKey]).forEach((newdoc) => newarray.push(newdoc));
+ });
+ subDocs = newarray;
+ }
+ }
+ }
+ });
+ return { strings: Array.from(valueSet.keys()), rtFields };
+ }
/**
* Responds to clicking the check box in the flyout menu
*/
@@ -73,17 +107,11 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
}
} else {
const allCollectionDocs = DocListCast((targetDoc.data as any)[0].data);
- var rtfields = 0;
- const facetValues = Array.from(allCollectionDocs.reduce((set, child) => {
- const field = child[facetHeader] as Field;
- const fieldStr = Field.toString(field);
- if (field instanceof RichTextField || (typeof (field) === "string" && fieldStr.split(" ").length > 2)) rtfields++;
- return set.add(fieldStr);
- }, new Set<string>()));
+ const facetValues = this.gatherFieldValues(targetDoc, facetHeader);
let nonNumbers = 0;
let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE;
- facetValues.map(val => {
+ facetValues.strings.map(val => {
const num = Number(val);
if (Number.isNaN(num)) {
nonNumbers++;
@@ -93,13 +121,13 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
}
});
let newFacet: Opt<Doc>;
- if (facetHeader === "text" || rtfields / allCollectionDocs.length > 0.1) {
+ if (facetHeader === "text" || facetValues.rtFields / allCollectionDocs.length > 0.1) {
newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, _stayInCollection: true, _hideContextMenu: true, treeViewExpandedView: "layout", title: facetHeader, treeViewOpen: true, forceActive: true, ignoreClick: true });
Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
newFacet._textBoxPadding = 4;
const scriptText = `setDocFilter(this?.target, "${facetHeader}", text, "match")`;
newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" });
- } else if (facetHeader !== "tags" && nonNumbers / facetValues.length < .1) {
+ } else if (facetHeader !== "tags" && nonNumbers / facetValues.strings.length < .1) {
newFacet = Docs.Create.SliderDocument({ title: facetHeader, _stayInCollection: true, _hideContextMenu: true, treeViewExpandedView: "layout", treeViewOpen: true });
const newFacetField = Doc.LayoutFieldKey(newFacet);
const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader);
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index c5a64af3e..7eca09f8c 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -265,19 +265,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.layoutDoc.presCollection = srcContext;
} else if (targetDoc) this.layoutDoc.presCollection = targetDoc;
}
- if (collectionDocView) {
- if (srcContext && srcContext !== presCollection) {
- // Case 1: new srcContext inside of current collection so add a new tab to the current pres collection
- collectionDocView.props.addDocTab(srcContext, "inPlace");
- }
- }
+ // if (collectionDocView) {
+ // if (srcContext && srcContext !== presCollection) {
+ // // Case 1: new srcContext inside of current collection so add a new tab to the current pres collection
+ // collectionDocView.props.addDocTab(srcContext, "inPlace");
+ // }
+ // }
this.updateCurrentPresentation();
const docToJump = curDoc;
const willZoom = false;
// If openDocument is selected then it should open the document for the user
if (activeItem.openDocument) {
- this.props.addDocTab(activeItem, "replace:right");
+ collectionDocView ? collectionDocView.props.addDocTab(activeItem, "inPlace") : this.props.addDocTab(activeItem, "replace:right");
} else
//docToJump stayed same meaning, it was not in the group or was the last element in the group
if (activeItem.zoomProgressivize && this.rootDoc.presStatus !== 'edit') {
@@ -1047,7 +1047,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
activeItem.presPinViewX = x;
activeItem.presPinViewY = y;
activeItem.presPinViewScale = scale;
- }}>Update</div> : (null)};
+ }}>Update</div> : (null)}
</div>
<div style={{ display: activeItem.presPinView ? "block" : "none" }}>
<div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ff2ce90b7..e92efd708 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1189,7 +1189,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
this.endUndoTypingBatch();
Object.values(this._disposers).forEach(disposer => disposer?.());
this._editorView?.destroy();
- FormattedTextBoxComment.Hide();
+ FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none");
}
_downEvent: any;
@@ -1522,16 +1522,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
@computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); }
render() {
TraceMobx();
+ const selected = this.props.isSelected();
+ const active = this.active();
const scale = this.props.hideOnLeave ? 1 : this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc._isBackground;
- this.props.isSelected() && setTimeout(() => this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props), 0); // need to make sure that we update a text box that is selected after updating the one that was deselected
- if (!this.props.isSelected() && FormattedTextBoxComment.textBox === this) {
- setTimeout(() => FormattedTextBoxComment.Hide(), 0);
- }
+ selected && setTimeout(() => this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props)); // need to make sure that we update a text box that is selected after updating the one that was deselected
+ if (!selected && FormattedTextBoxComment.textBox === this) { FormattedTextBoxComment.Hide(); }
const minimal = this.props.ignoreAutoHeight;
- const selPad = (this.props.isSelected() && !this.layoutDoc._singleLine) || minimal ? -10 : 0;
- const selclass = this.props.isSelected() && !this.layoutDoc._singleLine ? "-selected" : "";
+ const selPad = (selected && !this.layoutDoc._singleLine) || minimal ? -10 : 0;
+ const selclass = selected && !this.layoutDoc._singleLine ? "-selected" : "";
return (
<div className={"formattedTextBox-cont"} ref={this._boxRef}
style={{
@@ -1564,65 +1564,53 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
onMouseUp={this.onMouseUp}
onWheel={this.onPointerWheel}
onPointerEnter={action(() => this._entered = true)}
- onPointerLeave={action((e: React.PointerEvent<HTMLDivElement>) => {
+ onPointerLeave={action(e => {
this._entered = false;
const target = document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y);
for (let child: any = target; child; child = child?.parentElement) {
- if (child === this._ref.current!) {
- this._entered = true;
- }
+ child === this._ref.current! && (this._entered = true);
}
})}
onDoubleClick={this.onDoubleClick}
>
<div className={`formattedTextBox-outer`} ref={this._scrollRef}
- style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: !this.props.active() ? "none" : undefined }}
+ style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: !active ? "none" : undefined }}
onScroll={this.onscrolled} onDrop={this.ondrop} >
<div className={minimal ? "formattedTextBox-minimal" : `formattedTextBox-inner${rounded}${selclass}`} ref={this.createDropTarget}
style={{
overflow: this.layoutDoc._singleLine ? "hidden" : undefined,
padding: this.layoutDoc._textBoxPadding ? StrCast(this.layoutDoc._textBoxPadding) :
`${Math.max(0, NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0) + selPad)}px ${NumCast(this.layoutDoc._xMargin, this.props.xMargin || 0) + selPad}px`,
- pointerEvents: !this.props.active() ? ((this.layoutDoc.isLinkButton || this.props.onClick) ? "none" : undefined) : undefined
+ pointerEvents: !active ? ((this.layoutDoc.isLinkButton || this.props.onClick) ? "none" : undefined) : undefined
}}
/>
</div>
- {!this.layoutDoc._showSidebar ? (null) : <>
- <div className={"formattedTextBox-sidebar" + (Doc.GetSelectedTool() !== InkTool.None ? "-inking" : "")}
- style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
- {this.sidebarWidthPercent === "0%" ? (null) :
- <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
- PanelHeight={this.active() ? () => 1000 : this.props.PanelHeight}
- PanelWidth={this.sidebarWidth}
- scaleField={this.annotationKey + "-scale"}
- annotationsKey={this.annotationKey}
- isAnnotationOverlay={true}
- focus={this.props.focus}
- isSelected={this.props.isSelected}
- select={emptyFunction}
- active={this.annotationsActive}
- ContentScaling={returnOne}
- whenActiveChanged={this.whenActiveChanged}
- removeDocument={this.removeDocument}
- moveDocument={this.moveDocument}
- addDocument={this.addDocument}
- CollectionView={undefined}
- ScreenToLocalTransform={this.sidebarScreenToLocal}
- renderDepth={this.props.renderDepth + 1}
- ContainingCollectionDoc={this.props.ContainingCollectionDoc} />
- }
- </div>
- {this.props.isSelected() ? <div className="formattedTextBox-sidebar-handle" style={{ left: `max(0px, calc(100% - ${this.sidebarWidthPercent} - 5px))` }} onPointerDown={this.sidebarDown} /> : (null)}
- </>}
+ {!this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
+ <div className={"formattedTextBox-sidebar" + (Doc.GetSelectedTool() !== InkTool.None ? "-inking" : "")} style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
+ <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
+ PanelHeight={active ? () => 1000 : this.props.PanelHeight}
+ PanelWidth={this.sidebarWidth}
+ scaleField={this.annotationKey + "-scale"}
+ annotationsKey={this.annotationKey}
+ isAnnotationOverlay={true}
+ focus={this.props.focus}
+ isSelected={this.props.isSelected}
+ select={emptyFunction}
+ active={this.annotationsActive}
+ ContentScaling={returnOne}
+ whenActiveChanged={this.whenActiveChanged}
+ removeDocument={this.removeDocument}
+ moveDocument={this.moveDocument}
+ addDocument={this.addDocument}
+ CollectionView={undefined}
+ ScreenToLocalTransform={this.sidebarScreenToLocal}
+ renderDepth={this.props.renderDepth + 1}
+ ContainingCollectionDoc={this.props.ContainingCollectionDoc} />
+ </div>}
+ {selected ? <div className="formattedTextBox-sidebar-handle" style={{ left: `max(0px, calc(100% - ${this.sidebarWidthPercent} - 5px))` }} onPointerDown={this.sidebarDown} /> : (null)}
{!this.layoutDoc._showAudio ? (null) :
<div className="formattedTextBox-dictation" onClick={action(e => this._recording = !this._recording)} >
- <FontAwesomeIcon className="formattedTextBox-audioFont"
- style={{
- color: this._recording ? "red" : "blue",
- transitionDelay: "0.6s",
- opacity: this._recording ? 1 : 0.25,
- }}
- icon={"microphone"} size="sm" />
+ <FontAwesomeIcon className="formattedTextBox-audioFont" style={{ color: this._recording ? "red" : "blue", transitionDelay: "0.6s", opacity: this._recording ? 1 : 0.25, }} icon={"microphone"} size="sm" />
</div>}
</div>
</div>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index a37210de6..14bbee1ac 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -143,9 +143,12 @@ export class FormattedTextBoxComment {
public static Hide() {
FormattedTextBoxComment.textBox = undefined;
- FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none");
- ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText);
FormattedTextBoxComment.linkDoc = undefined;
+ FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none");
+ try {
+ ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText);
+ FormattedTextBoxComment.tooltip.removeChild(FormattedTextBoxComment.tooltipText);
+ } catch (e) { }
}
public static SetState(textBox: any, start: number, end: number, mark: Mark) {
FormattedTextBoxComment.textBox = textBox;
@@ -228,17 +231,17 @@ export class FormattedTextBoxComment {
if (forceUrl || (href && child && nbef && naft && mark?.attrs.showPreview)) {
try {
ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText);
+ FormattedTextBoxComment.tooltip.removeChild(FormattedTextBoxComment.tooltipText);
} catch (e) { }
- FormattedTextBoxComment.tooltip.removeChild(FormattedTextBoxComment.tooltipText);
FormattedTextBoxComment.tooltipText = document.createElement("div");
FormattedTextBoxComment.tooltipText.style.width = "100%";
FormattedTextBoxComment.tooltipText.style.height = "100%";
FormattedTextBoxComment.tooltipText.style.textOverflow = "ellipsis";
FormattedTextBoxComment.tooltipText.style.cursor = "pointer";
- FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText);
-
FormattedTextBoxComment.tooltipText.textContent = "URL: " + href;
(FormattedTextBoxComment.tooltipText as any).href = href;
+ FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText);
+
if (href.startsWith("https://en.wikipedia.org/wiki/")) {
wiki().page(href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(summary => FormattedTextBoxComment.tooltipText.textContent = summary.substring(0, 500)));
} else {
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 3238e4dc6..a6ac62ee4 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -530,10 +530,10 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
style={{ cursor: "hand", color: "black", padding: 1, position: "relative" }} /></div>
</Tooltip>
</div>
- <div style={{ position: "absolute", left: 220, width: 30, zIndex: 9000, color: "grey", background: "white", }}>
+ <div style={{ position: "absolute", left: Doc.UserDoc().noviceMode ? 220 : 200, width: 30, zIndex: 9000, color: "grey", background: "white", }}>
{`${this._results.length}` + " of " + `${this.realTotalResults}`}
</div>
- {/* <div style={{ cursor: "default", left: 235, position: "absolute", }}>
+ {Doc.UserDoc().noviceMode ? (null) : <div style={{ cursor: "default", left: 235, position: "absolute", }}>
<Tooltip title={<div className="dash-tooltip" >only display documents matching search</div>} >
<div>
<FontAwesomeIcon icon={"filter"} size="lg"
@@ -542,7 +542,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
onClick={action(() => this.setSearchFilter(this.currentSelectedCollection, this.filter ? undefined : this.docsforfilter))} />
</div>
</Tooltip>
- </div> */}
+ </div>}
{this.scopeButtons}
</div>
</div >
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 31d5cc5f2..a3849661d 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -361,7 +361,7 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any
const oldValue = current;
const newValue = ObjectField.MakeCopy(value);
current = newValue;
- if (!(value instanceof CursorField) && !(value?.some((v: any) => v instanceof CursorField))) {
+ if (!(value instanceof CursorField) && !(value?.some?.((v: any) => v instanceof CursorField))) {
UndoManager.AddEvent({
redo() { receiver[prop] = newValue; },
undo() { receiver[prop] = oldValue; }