aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts3
-rw-r--r--src/client/util/CurrentUserUtils.ts12
-rw-r--r--src/client/util/DocumentManager.ts1
-rw-r--r--src/client/util/SelectionManager.ts9
-rw-r--r--src/client/views/DocComponent.tsx2
-rw-r--r--src/client/views/GlobalKeyHandler.ts2
-rw-r--r--src/client/views/MainView.tsx4
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx4
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx206
-rw-r--r--src/client/views/collections/CollectionSchemaHeaders.tsx299
-rw-r--r--src/client/views/collections/CollectionSchemaView.scss93
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx28
-rw-r--r--src/client/views/collections/CollectionSubView.tsx45
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx19
-rw-r--r--src/client/views/collections/CollectionView.tsx103
-rw-r--r--src/client/views/collections/SchemaTable.tsx39
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/PropertiesView.tsx6
-rw-r--r--src/client/views/nodes/DocumentView.tsx3
-rw-r--r--src/client/views/nodes/PresBox.scss2
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx42
-rw-r--r--src/client/views/pdf/PDFViewer.tsx3
-rw-r--r--src/client/views/search/SearchBox.tsx131
-rw-r--r--src/server/websocket.ts1
24 files changed, 751 insertions, 311 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 956a5645c..5e83645ec 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1212,5 +1212,4 @@ export namespace DocUtils {
}
Scripting.addGlobal("Docs", Docs);
-Scripting.addGlobal(function makeDelegate(proto: any) { const d = Docs.Create.DelegateDocument(proto, { title: "child of " + proto.title }); return d; });
-
+Scripting.addGlobal(function makeDelegate(proto: any) { const d = Docs.Create.DelegateDocument(proto, { title: "child of " + proto.title }); return d; }); \ No newline at end of file
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 4fbc27cd3..11c2395ff 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -391,7 +391,7 @@ export class CurrentUserUtils {
}[] {
if (doc.emptyPresentation === undefined) {
doc.emptyPresentation = Docs.Create.PresDocument(new List<Doc>(),
- { title: "Presentation", _viewType: CollectionViewType.Stacking, targetDropAction: "alias", _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0", system: true });
+ { title: "Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true });
}
if (doc.emptyCollection === undefined) {
doc.emptyCollection = Docs.Create.FreeformDocument([],
@@ -834,10 +834,7 @@ export class CurrentUserUtils {
}));
}
if (doc.activePresentation === undefined) {
- doc.activePresentation = Docs.Create.PresDocument(new List<Doc>(), {
- title: "Presentation", _viewType: CollectionViewType.Stacking, targetDropAction: "alias",
- _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0", system: true
- });
+ doc.activePresentation = Doc.MakeCopy(doc.emptyPresentation as Doc, true);
}
}
@@ -926,12 +923,13 @@ export class CurrentUserUtils {
this.setupSearchPanel(doc);
this.setupOverlays(doc); // documents in overlay layer
this.setupDockedButtons(doc); // the bottom bar of font icons
- this.setupDefaultPresentation(doc); // presentation that's initially triggered
await this.setupSidebarButtons(doc); // the pop-out left sidebar of tools/panels
doc.globalLinkDatabase = Docs.Prototypes.MainLinkDocument();
doc.globalScriptDatabase = Docs.Prototypes.MainScriptDocument();
doc.globalGroupDatabase = Docs.Prototypes.MainGroupDocument();
+ setTimeout(() => this.setupDefaultPresentation(doc), 0); // presentation that's initially triggered
+
// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet
doc["dockedBtn-undo"] && reaction(() => UndoManager.undoStack.slice(), () => Doc.GetProto(doc["dockedBtn-undo"] as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true });
doc["dockedBtn-redo"] && reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(doc["dockedBtn-redo"] as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true });
@@ -969,4 +967,4 @@ Scripting.addGlobal(function createNewWorkspace() { return MainView.Instance.cre
Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); },
"returns all the links to the document or its annotations", "(doc: any)");
Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); },
- "returns all the links directly to the document", "(doc: any)");
+ "returns all the links directly to the document", "(doc: any)"); \ No newline at end of file
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index bd57e7f48..962294933 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -231,6 +231,7 @@ export class DocumentManager {
containerDoc.currentTimecode = targetTimecode;
const targetContext = await target?.context as Doc;
const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
+ console.log(targetNavContext);
DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "onRight"), finished), targetNavContext, linkDoc, undefined, doc, finished);
} else {
finished?.();
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 05ba00331..113278593 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -84,11 +84,4 @@ export namespace SelectionManager {
export function SelectedDocuments(): Array<DocumentView> {
return Array.from(manager.SelectedDocuments.keys());
}
-}
-
-
-Scripting.addGlobal(function selectDoc(doc: any) {
- const view = DocumentManager.Instance.getDocumentView(doc);
- view && SelectionManager.SelectDoc(view, false);
- //Doc.UserDoc().activeSelection = new List([doc]);
-}); \ No newline at end of file
+} \ No newline at end of file
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index a05bfc302..4a92ed262 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -176,6 +176,8 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
added.map(doc => doc.context = this.props.Document);
(targetDataDoc[this.annotationKey] as List<Doc>).push(...added);
targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now()));
+ const lastModified = "lastModified";
+ targetDataDoc[lastModified] = new DateField(new Date(Date.now()));
}
}
}
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index c97882f06..1fc0ed034 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -324,6 +324,8 @@ export default class KeyManager {
undoBatch(() => {
targetDataDoc[fieldKey] = new List<Doc>([...docList, ...added]);
targetDataDoc[fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
+ const lastModified = "lastModified";
+ targetDataDoc[lastModified] = new DateField(new Date(Date.now()));
})();
}
}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index dbce1502f..5ee10f7a6 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -199,7 +199,7 @@ export class MainView extends React.Component {
let check = false;
const icon = "icon";
targets.forEach((thing) => {
- if (thing.className.toString() === "collectionSchemaView-table" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "beta" || thing.className.toString() === "collectionSchemaView-menuOptions-wrapper") {
+ if (thing.className.toString() === "collectionSchemaView-searchContainer" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "collectionSchema-header-menuOptions" || thing.className.toString() === "altcollectionTimeView-treeView") {
check = true;
}
});
@@ -904,4 +904,4 @@ Scripting.addGlobal(function copyWorkspace() {
Doc.AddDocToList(workspaces, "data", copiedWorkspace);
// bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
setTimeout(() => MainView.Instance.openWorkspace(copiedWorkspace), 0);
-});
+}); \ No newline at end of file
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 7db846f72..22bb6e59a 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -758,7 +758,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged);
this.props.glContainer.on("tab", this.onActiveContentItemChanged);
this.onActiveContentItemChanged();
- this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: StrCast(this._document?._backgroundColor, this._document && CollectionDockingView.Instance.props.backgroundColor?.(this._document, 0) || "white") }),
+ this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: StrCast(this._document?._backgroundColor, this._document && CollectionDockingView.Instance?.props.backgroundColor?.(this._document, 0) || "white") }),
(data) => {
const selected = data.views.some(v => Doc.AreProtosEqual(v.props.Document, this._document));
this._tab && (this._tab.style.backgroundColor = selected ? data.color : "");
@@ -821,7 +821,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
if (this._mainCont && this._mainCont.children) {
const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont.children[0].firstChild as HTMLElement);
const scale = Utils.GetScreenTransform(this._mainCont).scale;
- return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale);
+ return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale);
}
return Transform.Identity();
}
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 8a1dd8472..20ae74b44 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -33,6 +33,8 @@ import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { DateField } from "../../../fields/DateField";
import { RichTextField } from "../../../fields/RichTextField";
+import { DocumentManager } from "../../util/DocumentManager";
+import { SearchUtil } from "../../util/SearchUtil";
const path = require('path');
library.add(faExpand);
@@ -159,6 +161,29 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
// e.stopPropagation();
// }
+ returnHighlights(bing: (() => string), positions?: number[]) {
+ const results = [];
+ const contents = bing();
+
+ if (positions !== undefined) {
+ StrCast(this.props.Document._searchString)
+ const length = StrCast(this.props.Document._searchString).length;
+
+ results.push(<span style={{ color: contents ? "black" : "grey" }}>{contents ? contents.slice(0, positions[0]) : "undefined"}</span>);
+ positions.forEach((num, cur) => {
+ results.push(<span style={{ backgroundColor: "#FFFF00", color: contents ? "black" : "grey" }}>{contents ? contents.slice(num, num + length) : "undefined"}</span>);
+ let end = 0;
+ cur === positions.length - 1 ? end = contents.length : end = positions[cur + 1];
+ results.push(<span style={{ color: contents ? "black" : "grey" }}>{contents ? contents.slice(num + length, end) : "undefined"}</span>);
+ }
+ );
+ return results;
+ }
+ else {
+ return <span style={{ color: contents ? "black" : "grey" }}>{contents ? contents?.valueOf() : "undefined"}</span>;
+ }
+ }
+
renderCellWithType(type: string | undefined) {
const dragRef: React.RefObject<HTMLDivElement> = React.createRef();
@@ -200,12 +225,24 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
const doc = FieldValue(Cast(field, Doc));
const fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc);
- const onItemDown = (e: React.PointerEvent) => {
- //fieldIsDoc &&
- SetupDrag(this._focusRef,
- () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
- this._document[props.fieldKey] instanceof Doc ? (doc: Doc | Doc[], target: Doc | undefined, addDoc: (newDoc: Doc | Doc[]) => any) => addDoc(doc) : this.props.moveDocument,
- this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
+ const onItemDown = async (e: React.PointerEvent) => {
+ if (this.props.Document._searchDoc !== undefined) {
+ let doc = Doc.GetProto(this.props.rowProps.original);
+ const aliasdoc = await SearchUtil.GetAliasesOfDocument(doc);
+ let targetContext = undefined;
+ if (aliasdoc.length > 0) {
+ targetContext = Cast(aliasdoc[0].context, Doc) as Doc;
+ }
+ console.log(targetContext);
+ DocumentManager.Instance.jumpToDocument(this.props.rowProps.original, false, undefined, targetContext);
+ }
+ else {
+ fieldIsDoc &&
+ SetupDrag(this._focusRef,
+ () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
+ this._document[props.fieldKey] instanceof Doc ? (doc: Doc | Doc[], target: Doc | undefined, addDoc: (newDoc: Doc | Doc[]) => any) => addDoc(doc) : this.props.moveDocument,
+ this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
+ }
};
const onPointerEnter = (e: React.PointerEvent): void => {
if (e.buttons === 1 && SnappingManager.GetIsDragging() && (type === "document" || type === undefined)) {
@@ -281,27 +318,98 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
positions.pop();
}
}
+ let search = false;
+ if (this.props.Document._searchDoc !== undefined) {
+ search = true;
+ }
+
+
return (
<div className="collectionSchemaView-cellContainer" style={{ cursor: fieldIsDoc ? "grab" : "auto" }}
ref={dragRef} onPointerDown={this.onPointerDown} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
<div className={className} ref={this._focusRef} onPointerDown={onItemDown} tabIndex={-1}>
- <div className="collectionSchemaView-cellContents" ref={type === undefined || type === "document" ? this.dropRef : null} key={props.Document[Id]}>
- <EditableView
- positions={positions.length > 0 ? positions : undefined}
- search={StrCast(this.props.Document._searchString) ? StrCast(this.props.Document._searchString) : undefined}
- editing={this._isEditing}
- isEditingCallback={this.isEditingCallback}
- display={"inline"}
- contents={contents ? contents : type === "number" ? "0" : "undefined"}
- highlight={positions.length > 0 ? true : undefined}
- //contents={StrCast(contents)}
- height={"auto"}
- maxHeight={Number(MAX_ROW_HEIGHT)}
- placeholder={"enter value"}
- bing={() => {
+ <div className="collectionSchemaView-cellContents"
+ ref={type === undefined || type === "document" ? this.dropRef : null} key={props.Document[Id]}>
+ {!search ?
+ <EditableView
+ positions={positions.length > 0 ? positions : undefined}
+ search={StrCast(this.props.Document._searchString) ? StrCast(this.props.Document._searchString) : undefined}
+ editing={this._isEditing}
+ isEditingCallback={this.isEditingCallback}
+ display={"inline"}
+ contents={contents ? contents : type === "number" ? "0" : "undefined"}
+ highlight={positions.length > 0 ? true : undefined}
+ //contents={StrCast(contents)}
+ height={"auto"}
+ maxHeight={Number(MAX_ROW_HEIGHT)}
+ placeholder={"undefined"}
+ bing={() => {
+ const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
+ if (cfield !== undefined) {
+ // if (typeof(cfield)===RichTextField)
+ const a = cfield as RichTextField;
+ if (a.Text !== undefined) {
+ return (a.Text);
+ }
+ else if (StrCast(cfield)) {
+ return StrCast(cfield);
+ }
+ else {
+ return String(NumCast(cfield));
+ }
+ }
+ }}
+ GetValue={() => {
+ if (type === "number" && (contents === 0 || contents === "0")) {
+ return "0";
+ } else {
+ const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
+ if (type === "number") {
+ return StrCast(cfield);
+ }
+ const cscript = cfield instanceof ComputedField ? cfield.script.originalScript : undefined;
+ const cfinalScript = cscript?.split("return")[cscript.split("return").length - 1];
+ const val = cscript !== undefined ? (cfinalScript?.endsWith(";") ? `:=${cfinalScript?.substring(0, cfinalScript.length - 2)}` : cfinalScript) :
+ Field.IsField(cfield) ? Field.toScriptString(cfield) : "";
+ return val;
+
+ }
+
+ }}
+ SetValue={action((value: string) => {
+ let retVal = false;
+
+ if (value.startsWith(":=")) {
+ retVal = this.props.setComputed(value.substring(2), props.Document, this.props.rowProps.column.id!, 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" } });
+ if (script.compiled) {
+ retVal = this.applyToDoc(props.Document, 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'
+ this.props.setIsEditing(false);
+ }
+ return retVal;
+
+ //return true;
+ })}
+ 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" } });
+ if (script.compiled) {
+ DocListCast(this.props.Document[this.props.fieldKey]).
+ forEach((doc, i) => value.startsWith(":=") ?
+ this.props.setComputed(value.substring(2), doc, this.props.rowProps.column.id!, i, this.props.col) :
+ this.applyToDoc(doc, i, this.props.col, script.run));
+ }
+ }}
+ />
+ :
+ this.returnHighlights(() => {
const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
if (cfield !== undefined) {
- console.log(typeof (cfield));
// if (typeof(cfield)===RichTextField)
const a = cfield as RichTextField;
if (a.Text !== undefined) {
@@ -314,56 +422,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
return String(NumCast(cfield));
}
}
- }}
- GetValue={() => {
- if (type === "number" && (contents === 0 || contents === "0")) {
- return "0";
- } else {
- const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
- if (type === "number") {
- return StrCast(cfield);
- }
- const cscript = cfield instanceof ComputedField ? cfield.script.originalScript : undefined;
- const cfinalScript = cscript?.split("return")[cscript.split("return").length - 1];
- const val = cscript !== undefined ? (cfinalScript?.endsWith(";") ? `:=${cfinalScript?.substring(0, cfinalScript.length - 2)}` : cfinalScript) :
- Field.IsField(cfield) ? Field.toScriptString(cfield) : "";
- return val;
-
+ else {
+ return "";
}
-
- }}
- SetValue={action((value: string) => {
- let retVal = false;
-
- if (value.startsWith(":=")) {
- retVal = this.props.setComputed(value.substring(2), props.Document, this.props.rowProps.column.id!, 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" } });
- if (script.compiled) {
- retVal = this.applyToDoc(props.Document, 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'
- this.props.setIsEditing(false);
- }
- return retVal;
-
- //return true;
- })}
- 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" } });
- if (script.compiled) {
- DocListCast(this.props.Document[this.props.fieldKey]).
- forEach((doc, i) => value.startsWith(":=") ?
- this.props.setComputed(value.substring(2), doc, this.props.rowProps.column.id!, i, this.props.col) :
- this.applyToDoc(doc, i, this.props.col, script.run));
- }
- }}
- />
-
-
+ }, positions)
+ }
</div >
{/* {fieldIsDoc ? docExpander : null} */}
</div>
@@ -903,7 +966,6 @@ export class CollectionSchemaButtons extends CollectionSchemaCell {
}}><button onClick={() => {
doc.searchMatch = false;
setTimeout(() => doc.searchMatch = true, 0);
- doc.searchIndex = NumCast(doc.searchIndex);
}} style={{ padding: 2, left: 77 }}>
<FontAwesomeIcon icon="arrow-up" size="sm" />
</button>
@@ -911,7 +973,6 @@ export class CollectionSchemaButtons extends CollectionSchemaCell {
{
doc.searchMatchAlt = false;
setTimeout(() => doc.searchMatchAlt = true, 0);
- doc.searchIndex = NumCast(doc.searchIndex);
}
}} style={{ padding: 2 }}>
<FontAwesomeIcon icon="arrow-down" size="sm" />
@@ -929,7 +990,6 @@ export class CollectionSchemaButtons extends CollectionSchemaCell {
onClick={() => {
doc.searchMatch = false;
setTimeout(() => doc.searchMatch = true, 0);
- doc.searchIndex = NumCast(doc.searchIndex);
}}>
<FontAwesomeIcon icon="arrow-down" size="sm" />
</button></div >;
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index e65adcf76..8cc91b3da 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -1,5 +1,5 @@
import React = require("react");
-import { action, observable } from "mobx";
+import { action, observable, computed } from "mobx";
import { observer } from "mobx-react";
import "./CollectionSchemaView.scss";
import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faSortAmountDown, faSortAmountUp, faTimes, faImage, faListUl, faCalendar } from '@fortawesome/free-solid-svg-icons';
@@ -9,8 +9,23 @@ import { ColumnType } from "./CollectionSchemaView";
import { faFile } from "@fortawesome/free-regular-svg-icons";
import { SchemaHeaderField, PastelSchemaPalette } from "../../../fields/SchemaHeaderField";
import { undoBatch } from "../../util/UndoManager";
-import { Doc } from "../../../fields/Doc";
-import { StrCast } from "../../../fields/Types";
+import { Transform } from '../../util/Transform';
+import { Doc, DocListCast, Field, Opt } from "../../../fields/Doc";
+import { StrCast, Cast } from "../../../fields/Types";
+import { optionFocusAriaMessage } from "react-select/src/accessibility";
+import { TraceMobx } from "../../../fields/util";
+import { CollectionTreeView } from "./CollectionTreeView";
+import { returnEmptyFilter, returnFalse, emptyPath, returnZero, emptyFunction, returnOne } from "../../../Utils";
+import { RichTextField } from "../../../fields/RichTextField";
+import { Docs } from "../../documents/Documents";
+import { List } from "../../../fields/List";
+import { listSpec } from "../../../fields/Schema";
+import { ScriptField, ComputedField } from "../../../fields/ScriptField";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { CollectionView } from "./CollectionView";
+import { SearchBox } from "../search/SearchBox";
+import { createParameter } from "typescript";
+
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -286,6 +301,12 @@ export interface KeysDropdownProps {
setIsEditing: (isEditing: boolean) => void;
width?: string;
docs?: Doc[];
+ Document?: Doc;
+ dataDoc?: Doc;
+ fieldKey?: string;
+ ContainingCollectionDoc?: Doc;
+ ContainingCollectionView?: CollectionView;
+ active?: (outsideReaction?: boolean) => boolean;
}
@observer
export class KeysDropdown extends React.Component<KeysDropdownProps> {
@@ -301,8 +322,10 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
@action
onSelect = (key: string): void => {
- if (key.slice(0, this._key.length) === this._key && this._key !== key) {
- const filter = key.slice(this._key.length - key.length);
+ if (this._searchTerm.includes(":")) {
+ const colpos = this._searchTerm.indexOf(":");
+ const filter = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
+ //const filter = key.slice(this._key.length - key.length);
this.props.onSelect(this._key, this._key, this.props.addNew, filter);
}
else {
@@ -314,16 +337,21 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
}
@action
- onSelect2 = (key: string): void => {
- this._searchTerm = this._searchTerm.slice(0, this._key.length) + key;
+ onSelectValue = (key: string): void => {
+ const colpos = this._searchTerm.indexOf(":");
+ this.onSelect(key);
+ this._searchTerm = this._searchTerm.slice(0, colpos + 1) + key;
this._isOpen = false;
+ this.props.onSelect(this._key, this._key, this.props.addNew, key);
}
@undoBatch
onKeyDown = (e: React.KeyboardEvent): void => {
if (e.key === "Enter") {
- const keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+ let keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+ let blockedkeys = ["_scrollTop", "customTitle", "limitHeight", "proto", "x", "y", "_width", "_height", "_autoHeight", "_fontSize", "_fontFamily", "context", "zIndex", "_timeStampOnEnter", "lines", "highlighting", "searchMatch", "creationDate", "isPrototype", "text-annotations", "aliases", "text-lastModified", "text-noTemplate", "layoutKey", "baseProto", "_xMargin", "_yMargin", "layout", "layout_keyValue", "links"];
+ keyOptions = keyOptions.filter(n => !blockedkeys.includes(n));
if (keyOptions.length) {
this.onSelect(keyOptions[0]);
} else if (this._searchTerm !== "" && this.props.canAddNew) {
@@ -360,20 +388,25 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
onPointerOut = (e: React.PointerEvent): void => {
this._canClose = true;
}
-
+ @action
renderOptions = (): JSX.Element[] | JSX.Element => {
- if (!this._isOpen) return <></>;
-
+ if (!this._isOpen) {
+ this.defaultMenuHeight = 0;
+ return <></>;
+ }
const searchTerm = this._searchTerm.trim() === "New field" ? "" : this._searchTerm;
- const keyOptions = searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+ let keyOptions = searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
const exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 ||
this.props.existingKeys.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1;
+ let blockedkeys = ["proto", "x", "y", "_width", "_height", "_autoHeight", "_fontSize", "_fontFamily", "context", "zIndex", "_timeStampOnEnter", "lines", "highlighting", "searchMatch", "creationDate", "isPrototype", "text-annotations", "aliases", "text-lastModified", "text-noTemplate", "layoutKey", "baseProto", "_xMargin", "_yMargin", "layout", "layout_keyValue", "links"];
+ keyOptions = keyOptions.filter(n => !blockedkeys.includes(n));
+
const options = keyOptions.map(key => {
return <div key={key} className="key-option" style={{
border: "1px solid lightgray",
- width: this.props.width, maxWidth: this.props.width, overflowX: "hidden"
+ width: this.props.width, maxWidth: this.props.width, overflowX: "hidden", background: "white",
}}
onPointerDown={e => e.stopPropagation()} onClick={() => { this.onSelect(key); this.setSearchTerm(""); }}>{key}</div>;
});
@@ -382,49 +415,252 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
if (this._key !== this._searchTerm.slice(0, this._key.length)) {
if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) {
options.push(<div key={""} className="key-option" style={{
- border: "1px solid lightgray",
- width: this.props.width, maxWidth: this.props.width, overflowX: "hidden"
+ border: "1px solid lightgray", width: this.props.width, maxWidth: this.props.width, overflowX: "hidden", background: "white",
}}
onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}>
Create "{this._searchTerm}" key</div>);
}
}
+ if (options.length === 0) {
+ this.defaultMenuHeight = 0;
+ }
+ else {
+ if (this.props.docs) {
+ let panesize = this.props.docs.length * 30;
+ options.length * 20 + 8 - 10 > panesize ? this.defaultMenuHeight = panesize : this.defaultMenuHeight = options.length * 20 + 8;
+ }
+ else {
+ options.length > 5 ? this.defaultMenuHeight = 108 : this.defaultMenuHeight = options.length * 20 + 8;
+ }
+ }
return options;
}
-
+ @action
renderFilterOptions = (): JSX.Element[] | JSX.Element => {
- if (!this._isOpen) return <></>;
- const keyOptions: string[] = [];
- const temp = this._searchTerm.slice(this._key.length);
- this.props.docs?.forEach((doc) => {
+ if (!this._isOpen) {
+ this.defaultMenuHeight = 0;
+ return <></>;
+ }
+ let keyOptions: string[] = [];
+ const colpos = this._searchTerm.indexOf(":");
+ const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
+ let docs = DocListCast(this.props.dataDoc![this.props.fieldKey!]);
+ docs.forEach((doc) => {
const key = StrCast(doc[this._key]);
if (keyOptions.includes(key) === false && key.includes(temp)) {
keyOptions.push(key);
}
});
-
const options = keyOptions.map(key => {
+ //Doc.setDocFilter(this.props.Document!, this._key, key, undefined);
+ let bool = false;
+ let filters = Cast(this.props.Document!._docFilters, listSpec("string"));
+ console.log(filters);
+ if (filters !== undefined) {
+ bool = filters.includes(key) && filters[filters.indexOf(key) + 1] === "check";
+ console.log(filters.includes(key));
+ }
return <div key={key} className="key-option" style={{
- border: "1px solid lightgray",
- width: this.props.width, maxWidth: this.props.width, overflowX: "hidden"
+ border: "1px solid lightgray", paddingLeft: 5, textAlign: "left",
+ width: this.props.width, maxWidth: this.props.width, overflowX: "hidden", background: "white", backgroundColor: "white",
}}
- onPointerDown={e => e.stopPropagation()} onClick={() => { this.onSelect2(key); }}>{key}</div>;
+ >
+ <input type="checkbox" onChange={(e) => { e.target.checked === true ? Doc.setDocFilter(this.props.Document!, this._key, key, "check") : Doc.setDocFilter(this.props.Document!, this._key, key, undefined); e.target.checked === true && SearchBox.Instance.filter === true ? Doc.setDocFilter(docs![0], this._key, key, "check") : Doc.setDocFilter(docs![0], this._key, key, undefined); }}
+ checked={bool} ></input>
+ <span style={{ paddingLeft: 4 }}>
+ {key}
+ </span>
+
+ </div>;
});
+ if (options.length === 0) {
+ this.defaultMenuHeight = 0;
+ }
+ else {
+ if (this.props.docs) {
+ let panesize = this.props.docs.length * 30;
+ options.length * 20 + 8 - 10 > panesize ? this.defaultMenuHeight = panesize : this.defaultMenuHeight = options.length * 20 + 8;
+ }
+ else {
+ options.length > 5 ? this.defaultMenuHeight = 108 : this.defaultMenuHeight = options.length * 20 + 8;
+ }
+
+ }
return options;
}
+ // @action
+ // renderFilterOptions = (): JSX.Element[] | JSX.Element => {
+ // this.facetClick(this._key);
+ // return <div>
+ // {this.filterView}
+ // </div>
+ // }
+ @observable defaultMenuHeight = 0;
+
+
+ facetClick = (facetHeader: string) => {
+ facetHeader = this._key;
+ let newFacet: Opt<Doc>;
+ if (this.props.Document !== undefined) {
+ const facetCollection = this.props.Document;
+ // const found = DocListCast(facetCollection[this.props.fieldKey + "-filter"]).findIndex(doc => doc.title === facetHeader);
+ // if (found !== -1) {
+ // console.log("found not n-1");
+ // (facetCollection[this.props.fieldKey + "-filter"] as List<Doc>).splice(found, 1);
+ // const docFilter = Cast(this.props.Document._docFilters, listSpec("string"));
+ // if (docFilter) {
+ // let index: number;
+ // while ((index = docFilter.findIndex(item => item === facetHeader)) !== -1) {
+ // docFilter.splice(index, 3);
+ // }
+ // }
+ // const docRangeFilters = Cast(this.props.Document._docRangeFilters, listSpec("string"));
+ // if (docRangeFilters) {
+ // let index: number;
+ // while ((index = docRangeFilters.findIndex(item => item === facetHeader)) !== -1) {
+ // docRangeFilters.splice(index, 3);
+ // }
+ // }
+ // }
+
+
+
+ console.log("found is n-1");
+ const allCollectionDocs = DocListCast(this.props.dataDoc![this.props.fieldKey!]);
+ 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>()));
+
+ let nonNumbers = 0;
+ let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE;
+ facetValues.map(val => {
+ const num = Number(val);
+ if (Number.isNaN(num)) {
+ nonNumbers++;
+ } else {
+ minVal = Math.min(num, minVal);
+ maxVal = Math.max(num, maxVal);
+ }
+ });
+ if (facetHeader === "text" || rtfields / allCollectionDocs.length > 0.1) {
+ console.log("Case1");
+ newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, 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.target = this.props.Document;
+ newFacet._textBoxPadding = 4;
+ const scriptText = `setDocFilter(this.target, "${facetHeader}", text, "match")`;
+ newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" });
+ } else if (nonNumbers / facetValues.length < .1) {
+ console.log("Case2");
+ newFacet = Docs.Create.SliderDocument({ title: facetHeader, treeViewExpandedView: "layout", treeViewOpen: true });
+ const newFacetField = Doc.LayoutFieldKey(newFacet);
+ const ranged = Doc.readDocRangeFilter(this.props.Document, facetHeader);
+ Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
+ const extendedMinVal = minVal - Math.min(1, Math.abs(maxVal - minVal) * .05);
+ const extendedMaxVal = maxVal + Math.min(1, Math.abs(maxVal - minVal) * .05);
+ newFacet[newFacetField + "-min"] = ranged === undefined ? extendedMinVal : ranged[0];
+ newFacet[newFacetField + "-max"] = ranged === undefined ? extendedMaxVal : ranged[1];
+ Doc.GetProto(newFacet)[newFacetField + "-minThumb"] = extendedMinVal;
+ Doc.GetProto(newFacet)[newFacetField + "-maxThumb"] = extendedMaxVal;
+ newFacet.target = this.props.Document;
+ const scriptText = `setDocFilterRange(this.target, "${facetHeader}", range)`;
+ newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: "number" });
+ Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet);
+ } else {
+ console.log("Case3");
+ newFacet = new Doc();
+ newFacet.title = facetHeader;
+ newFacet.treeViewOpen = true;
+ newFacet.type = DocumentType.COL;
+ const capturedVariables = { layoutDoc: this.props.Document, dataDoc: this.props.dataDoc! };
+ this.props.Document.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, {}, capturedVariables);
+ // this.props.Document.data
+ }
+ //newFacet && Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet);
+ }
+ }
+
+
+ get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; }
+
+ @computed get scriptField() {
+ console.log("we kinda made it");
+ const scriptText = "setDocFilter(containingTreeView, heading, this.title, checked)";
+ const script = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name });
+ return script ? () => script : undefined;
+ }
+ filterBackground = () => "rgba(105, 105, 105, 0.432)";
+
+
+ // @computed get filterView() {
+ // TraceMobx();
+ // if (this.props.Document !== undefined) {
+ // //const facetCollection = this.props.Document;
+ // // const flyout = (
+ // // <div className="collectionTimeView-flyout" style={{ width: `${this.facetWidth()}`, height: this.props.PanelHeight() - 30 }} onWheel={e => e.stopPropagation()}>
+ // // {this._allFacets.map(facet => <label className="collectionTimeView-flyout-item" key={`${facet}`} onClick={e => this.facetClick(facet)}>
+ // // <input type="checkbox" onChange={e => { }} checked={DocListCast(this.props.Document[this.props.fieldKey + "-filter"]).some(d => d.title === facet)} />
+ // // <span className="checkmark" />
+ // // {facet}
+ // // </label>)}
+ // // </div>
+ // // );
+ // return <div className="altcollectionTimeView-treeView">
+ // <div className="altcollectionTimeView-tree" key="tree">
+ // <CollectionTreeView
+ // PanelPosition={""}
+ // Document={this.props.Document}
+ // DataDoc={this.props.Document}
+ // fieldKey={this.props.fieldKey!}
+ // CollectionView={undefined}
+ // docFilters={returnEmptyFilter}
+ // ContainingCollectionDoc={this.props.ContainingCollectionDoc!}
+ // ContainingCollectionView={this.props.ContainingCollectionView!}
+ // PanelWidth={() => 200}
+ // PanelHeight={() => 200}
+ // NativeHeight={returnZero}
+ // NativeWidth={returnZero}
+ // LibraryPath={emptyPath}
+ // rootSelected={returnFalse}
+ // renderDepth={1}
+ // dropAction={undefined}
+ // ScreenToLocalTransform={Transform.Identity}
+ // addDocTab={returnFalse}
+ // pinToPres={returnFalse}
+ // isSelected={returnFalse}
+ // select={returnFalse}
+ // bringToFront={emptyFunction}
+ // active={this.props.active!}
+ // whenActiveChanged={returnFalse}
+ // treeViewHideTitle={true}
+ // ContentScaling={returnOne}
+ // focus={returnFalse}
+ // treeViewHideHeaderFields={true}
+ // onCheckedClick={this.scriptField}
+ // ignoreFields={this.ignoreFields}
+ // annotationsKey={""}
+ // dontRegisterView={true}
+ // backgroundColor={this.filterBackground}
+ // moveDocument={returnFalse}
+ // removeDocument={returnFalse}
+ // addDocument={returnFalse} />
+ // </div>
+ // </div>;
+ // }
+ // }
+
render() {
return (
<div className="keys-dropdown" style={{ zIndex: 10, width: this.props.width, maxWidth: this.props.width }}>
- {this._key === this._searchTerm.slice(0, this._key.length) ?
- <div style={{ position: "absolute", marginLeft: "4px", marginTop: "3", color: "grey", pointerEvents: "none", lineHeight: 1.15 }}>
- {this._key}
- </div>
- : undefined}
<input className="keys-search" style={{ width: "100%" }}
ref={this._inputRef} type="text" value={this._searchTerm} placeholder="Column key" onKeyDown={this.onKeyDown}
onChange={e => this.onChange(e.target.value)}
@@ -433,11 +669,10 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
e.stopPropagation();
}} onFocus={this.onFocus} onBlur={this.onBlur}></input>
<div className="keys-options-wrapper" style={{
- backgroundColor: "white",
- width: this.props.width, maxWidth: this.props.width,
+ width: this.props.width, maxWidth: this.props.width, height: "auto",
}}
onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerOut}>
- {this._key === this._searchTerm.slice(0, this._key.length) ?
+ {this._searchTerm.includes(":") ?
this.renderFilterOptions() : this.renderOptions()}
</div>
</div >
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index ba0a259c5..5c2931a8b 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -43,6 +43,49 @@
// }
}
+.collectionSchemaView-searchContainer {
+ border-width: $COLLECTION_BORDER_WIDTH;
+ border-color: $intermediate-color;
+ border-style: solid;
+ border-radius: $border-radius;
+ box-sizing: border-box;
+ position: relative;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ margin-top: 0;
+ transition: top 0.5s;
+ display: flex;
+ justify-content: space-between;
+ flex-wrap: nowrap;
+ touch-action: none;
+
+ div {
+ touch-action: none;
+ }
+
+
+ .collectionSchemaView-tableContainer {
+ width: 100%;
+ height: 100%;
+ }
+
+ .collectionSchemaView-dividerDragger {
+ position: relative;
+ height: 100%;
+ width: 20px;
+ z-index: 20;
+ right: 0;
+ top: 0;
+ background: gray;
+ cursor: col-resize;
+ }
+
+ // .documentView-node:first-child {
+ // background: $light-color;
+ // }
+}
+
.ReactTable {
width: 100%;
background: white;
@@ -165,7 +208,7 @@
.collectionSchema-header-menu {
- height: 100%;
+ height: auto;
z-index: 100;
position: absolute;
background:white;
@@ -280,11 +323,9 @@ button.add-column {
background-color: white;
.key-option {
- //background-color: $light-color;
background-color: white;
border: 1px solid lightgray;
padding: 2px 3px;
-
&:not(:first-child) {
border-top: 0;
}
@@ -315,12 +356,53 @@ button.add-column {
}
}
+.altcollectionTimeView-treeView {
+ display: flex;
+ flex-direction: column;
+ width: 175px;
+ height: auto;
+ position: fixed;
+ border-left: solid 1px;
+ z-index: 1;
+
+ .collectionTimeView-addfacet {
+ display: inline-block;
+ width: 200px;
+ height: 30px;
+ background: darkGray;
+ text-align: left;
+
+ .collectionTimeView-button {
+ align-items: center;
+ display: flex;
+ width: 100%;
+ height: 100%;
+
+ .collectionTimeView-span {
+ margin: auto;
+ }
+ }
+
+ >div,
+ >div>div {
+ width: 100%;
+ height: 100%;
+ }
+ }
+
+ .altcollectionTimeView-tree {
+ display: inline-block;
+ width: 100%;
+ height: calc(100% - 30px);
+ }
+}
+
.collectionSchema-row {
height: 100%;
background-color: white;
&.row-focused .rt-td {
- background-color: rgb(255, 246, 246); //$light-color-secondary;
+ background-color: #bfffc0; //$light-color-secondary;
}
&.row-wrapped {
@@ -383,6 +465,9 @@ button.add-column {
.collectionSchemaView-cellWrapper {
height: 100%;
padding: 4px;
+ text-align:left;
+ padding-left:19px;
+
position: relative;
&:focus {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a003de0d3..3f879b489 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -11,7 +11,7 @@ import { Doc } from "../../../fields/Doc";
import { List } from "../../../fields/List";
import { listSpec } from "../../../fields/Schema";
import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField";
-import { Cast, NumCast } from "../../../fields/Types";
+import { Cast, NumCast, BoolCast } from "../../../fields/Types";
import { TraceMobx } from "../../../fields/util";
import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents } from "../../../Utils";
import { SnappingManager } from "../../util/SnappingManager";
@@ -71,8 +71,18 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
@observable _pointerY = 0;
@observable _openTypes: boolean = false;
@computed get menuCoordinates() {
- const x = Math.max(0, Math.min(document.body.clientWidth - this._menuWidth, this._pointerX));
- const y = Math.max(0, Math.min(document.body.clientHeight - this._menuHeight, this._pointerY));
+ let searchx = 0;
+ let searchy = 0;
+ if (this.props.Document._searchDoc !== undefined) {
+ let el = document.getElementsByClassName("collectionSchemaView-searchContainer")[0];
+ if (el !== undefined) {
+ let rect = el.getBoundingClientRect();
+ searchx = rect.x;
+ searchy = rect.y
+ }
+ }
+ const x = Math.max(0, Math.min(document.body.clientWidth - this._menuWidth, this._pointerX)) - searchx;
+ const y = Math.max(0, Math.min(document.body.clientHeight - this._menuHeight, this._pointerY)) - searchy;
return this.props.ScreenToLocalTransform().transformPoint(x, y);
}
@@ -611,14 +621,18 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
onKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
}
render() {
+ let name = "collectionSchemaView-container";
+ if (this.props.Document._searchDoc !== undefined) {
+ name = "collectionSchemaView-searchContainer";
+ }
TraceMobx();
const menuContent = this.renderMenuContent;
const menu = <div className="collectionSchema-header-menu" ref={this.setNode}
onWheel={e => this.onZoomMenu(e)}
onPointerDown={e => this.onHeaderClick(e)}
style={{
- position: "fixed", background: "white",
- transform: `translate(${this.menuCoordinates[0] / this.scale}px, ${this.menuCoordinates[1] / this.scale}px)`
+ position: "fixed", background: "white", border: "black 1px solid",
+ transform: `translate(${(this.menuCoordinates[0] / this.scale)}px, ${(this.menuCoordinates[1] / this.scale)}px)`
}}>
<Measure offset onResize={action((r: any) => {
const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height);
@@ -627,9 +641,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
{({ measureRef }) => <div ref={measureRef}> {menuContent} </div>}
</Measure>
</div>;
- return <div className="collectionSchemaView-container"
+ return <div className={name}
style={{
- overflow: this.props.overflow === true ? "auto" : undefined,
+ overflow: this.props.overflow === true ? "scroll" : undefined,
pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined,
width: this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative",
}} >
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index c88eabdcc..7957ded1c 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -112,10 +112,8 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
[...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])];
}
@computed get childDocs() {
- let rawdocs: (Doc | Promise<Doc>)[] = DocListCast(this.props.Document._searchDocs);
-
- if (rawdocs.length !== 0) {
- } else if (this.dataField instanceof Doc) { // if collection data is just a document, then promote it to a singleton list;
+ 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);
@@ -130,28 +128,23 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField);
let childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
- const searchDocs = DocListCast(this.props.Document._searchDocs);
- // if (searchDocs !== undefined && searchDocs.length > 0) {
- // let newdocs: Doc[] = [];
- // childDocs.forEach((el) => {
- // searchDocs.includes(el) ? newdocs.push(el) : undefined;
- // });
- // childDocs = newdocs;
- // }
+ let searchDocs = DocListCast(this.props.Document._searchDocs);
+
let docsforFilter: Doc[] = childDocs;
+
if (searchDocs !== undefined && searchDocs.length > 0) {
docsforFilter = [];
- // let newdocs: Doc[] = [];
- // let newarray: Doc[] = [];
- //while (childDocs.length > 0) {
- //newarray = [];
+ const docRangeFilters = this.props.ignoreFields?.includes("_docRangeFilters") ? [] : Cast(this.props.Document._docRangeFilters, listSpec("string"), []);
+ console.log(searchDocs);
+ searchDocs = DocUtils.FilterDocs(searchDocs, this.docFilters(), docRangeFilters, viewSpecScript)
+ console.log(this.docFilters());
+ console.log(searchDocs);
childDocs.forEach((d) => {
if (d.data !== undefined) {
- console.log(d);
let newdocs = DocListCast(d.data);
if (newdocs.length > 0) {
- let vibecheck: boolean | undefined = undefined;
+ let displaycheck: boolean | undefined = undefined;
let newarray: Doc[] = [];
while (newdocs.length > 0) {
newarray = [];
@@ -163,12 +156,12 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
});
}
if (searchDocs.includes(t)) {
- vibecheck = true;
+ displaycheck = true;
}
});
newdocs = newarray;
}
- if (vibecheck === true) {
+ if (displaycheck === true) {
docsforFilter.push(d);
}
}
@@ -177,14 +170,12 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
docsforFilter.push(d);
}
});
- //childDocs = newarray;
- //}
+ return docsforFilter;
}
- childDocs = docsforFilter;
-
+ console.log("you fool");
+ console.log(childDocs);
const docRangeFilters = this.props.ignoreFields?.includes("_docRangeFilters") ? [] : Cast(this.props.Document._docRangeFilters, listSpec("string"), []);
-
- return this.props.Document.dontRegisterView ? docs : DocUtils.FilterDocs(docs, this.docFilters(), docRangeFilters, viewSpecScript);
+ return this.props.Document.dontRegisterView ? childDocs : DocUtils.FilterDocs(childDocs, this.docFilters(), docRangeFilters, viewSpecScript);
}
@action
@@ -481,7 +472,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
completed?.();
} else {
if (text && !text.includes("https://")) {
- this.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 }));
+ UndoManager.RunInBatch(() => this.addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 })), "drop");
}
}
disposer();
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index dc88917cc..6768c6df9 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -53,7 +53,7 @@ export interface TreeViewProps {
indentDocument?: () => void;
outdentDocument?: () => void;
ScreenToLocalTransform: () => Transform;
- backgroundColor?: (doc: Doc) => string | undefined;
+ backgroundColor?: (doc: Doc, renderDepth: number) => string | undefined;
outerXf: () => { translateX: number, translateY: number };
treeViewDoc: Doc;
parentKey: string;
@@ -88,7 +88,7 @@ class TreeView extends React.Component<TreeViewProps> {
get doc() { 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 defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.doc.defaultExpandedView, this.noviceMode ? "layout" : "fields"); }
+ get defaultExpandedView() { return this.childDocs.length ? this.fieldKey : StrCast(this.doc.defaultExpandedView, this.noviceMode ? "layout" : "fields"); }
@observable _overrideTreeViewOpen = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state
set treeViewOpen(c: boolean) {
if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c;
@@ -108,6 +108,7 @@ class TreeView extends React.Component<TreeViewProps> {
}
@computed get childDocs() { return this.childDocList(this.fieldKey); }
@computed get childLinks() { return this.childDocList("links"); }
+ @computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); }
@computed get boundsOfCollectionDocument() {
return StrCast(this.props.document.type).indexOf(DocumentType.COL) === -1 || !DocListCast(this.props.document[this.fieldKey]).length ? undefined :
Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey]));
@@ -127,7 +128,7 @@ class TreeView extends React.Component<TreeViewProps> {
constructor(props: any) {
super(props);
- const script = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); selectDoc(self);} `);
+ const script = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); documentView.select();} `, { documentView: "any" });
this._editTitleScript = script && (() => script);
if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false);
}
@@ -313,11 +314,11 @@ class TreeView extends React.Component<TreeViewProps> {
@computed get renderContent() {
TraceMobx();
const expandKey = this.treeViewExpandedView;
- if (["links", this.fieldKey].includes(expandKey)) {
+ if (["links", "annotations", this.fieldKey].includes(expandKey)) {
const remDoc = (doc: Doc | Doc[]) => this.remove(doc, expandKey);
const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) =>
(doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true), true);
- const docs = expandKey === "links" ? this.childLinks : this.childDocs;
+ const docs = expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
const sortKey = `${this.fieldKey}-sortAscending`;
return <ul key={expandKey + "more"} onClick={(e) => {
this.doc[sortKey] = (this.doc[sortKey] ? false : (this.doc[sortKey] === false ? undefined : true));
@@ -397,7 +398,7 @@ class TreeView extends React.Component<TreeViewProps> {
title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
onClick={this.bulletClick}
style={{ color: StrCast(this.doc.color, checked === "unchecked" ? "white" : "inherit"), opacity: checked === "unchecked" ? undefined : 0.4 }}>
- {<FontAwesomeIcon icon={checked === "check" ? "check" : (checked === "x" ? "times" : checked === "unchecked" ? "square" : !this.treeViewOpen ? (this.childDocs ? "caret-square-right" : "caret-right") : (this.childDocs ? "caret-square-down" : "caret-down"))} />}
+ {<FontAwesomeIcon icon={checked === "check" ? "check" : (checked === "x" ? "times" : checked === "unchecked" ? "square" : !this.treeViewOpen ? (this.childDocs?.length ? "caret-square-right" : "caret-right") : (this.childDocs?.length ? "caret-square-down" : "caret-down"))} />}
</div>;
}
@@ -424,7 +425,8 @@ class TreeView extends React.Component<TreeViewProps> {
this.doc.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode ? "layout" : "fields") :
this.treeViewExpandedView === "fields" && this.layoutDoc ? "layout" :
this.treeViewExpandedView === "layout" && DocListCast(this.doc.links).length ? "links" :
- this.childDocs ? this.fieldKey : (Doc.UserDoc().noviceMode ? "layout" : "fields");
+ (this.treeViewExpandedView === "links" || this.treeViewExpandedView === "layout") && DocListCast(this.doc[this.fieldKey + "-annotations"]).length ? "annotations" :
+ this.childDocs.length ? this.fieldKey : (Doc.UserDoc().noviceMode ? "layout" : "fields");
}
this.treeViewOpen = true;
})}>
@@ -453,6 +455,7 @@ class TreeView extends React.Component<TreeViewProps> {
NativeHeight={returnZero}
NativeWidth={returnZero}
contextMenuItems={this.contextMenuItems}
+ opacity={returnOne}
renderDepth={1}
focus={returnTrue}
parentActive={returnTrue}
@@ -533,7 +536,7 @@ class TreeView extends React.Component<TreeViewProps> {
dropAction: dropActionType,
addDocTab: (doc: Doc, where: string) => boolean,
pinToPres: (document: Doc) => void,
- backgroundColor: undefined | ((document: Doc) => string | undefined),
+ backgroundColor: undefined | ((document: Doc, renderDepth: number) => string | undefined),
screenToLocalXf: () => Transform,
outerXf: () => { translateX: number, translateY: number },
active: (outsideReaction?: boolean) => boolean,
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 555db7e1a..a048d4ebd 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -46,6 +46,7 @@ import { CollectionTimeView } from './CollectionTimeView';
import { CollectionTreeView } from "./CollectionTreeView";
import './CollectionView.scss';
import { ContextMenuProps } from '../ContextMenuItem';
+import { table } from 'console';
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -182,6 +183,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
// targetDataDoc[this.props.fieldKey] = new List<Doc>([...docList, ...added]);
(targetDataDoc[this.props.fieldKey] as List<Doc>).push(...added);
targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
+ const lastModified = "lastModified";
+ targetDataDoc[lastModified] = new DateField(new Date(Date.now()));
}
}
}
@@ -515,56 +518,56 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
</label>)}
</div>
);
- return !this._facetWidth || this.props.dontRegisterView ? (null) :
- <div className="collectionTimeView-treeView" style={{ width: `${this.facetWidth()}px`, overflow: this.facetWidth() < 15 ? "hidden" : undefined }}>
- <div className="collectionTimeView-addFacet" style={{ width: `${this.facetWidth()}px` }} onPointerDown={e => e.stopPropagation()}>
- <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout}>
- <div className="collectionTimeView-button">
- <FontAwesomeIcon icon={faEdit} size={"lg"} />
- <span className="collectionTimeView-span">Facet Filters</span>
- </div>
- </Flyout>
- </div>
- <div className="collectionTimeView-tree" key="tree">
- <CollectionTreeView
- PanelPosition={""}
- Document={facetCollection}
- DataDoc={facetCollection}
- fieldKey={`${this.props.fieldKey}-filter`}
- CollectionView={this}
- docFilters={returnEmptyFilter}
- ContainingCollectionDoc={this.props.ContainingCollectionDoc}
- ContainingCollectionView={this.props.ContainingCollectionView}
- PanelWidth={this.facetWidth}
- PanelHeight={this.props.PanelHeight}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
- LibraryPath={emptyPath}
- rootSelected={this.props.rootSelected}
- renderDepth={1}
- dropAction={this.props.dropAction}
- ScreenToLocalTransform={this.props.ScreenToLocalTransform}
- addDocTab={returnFalse}
- pinToPres={returnFalse}
- isSelected={returnFalse}
- select={returnFalse}
- bringToFront={emptyFunction}
- active={this.props.active}
- whenActiveChanged={returnFalse}
- treeViewHideTitle={true}
- ContentScaling={returnOne}
- focus={returnFalse}
- treeViewHideHeaderFields={true}
- onCheckedClick={this.scriptField}
- ignoreFields={this.ignoreFields}
- annotationsKey={""}
- dontRegisterView={true}
- backgroundColor={this.filterBackground}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- addDocument={returnFalse} />
- </div>
- </div>;
+
+ return !this._facetWidth || this.props.dontRegisterView ? (null) : <div className="collectionTimeView-treeView" style={{ width: `${this.facetWidth()}px`, overflow: this.facetWidth() < 15 ? "hidden" : undefined }}>
+ <div className="collectionTimeView-addFacet" style={{ width: `${this.facetWidth()}px` }} onPointerDown={e => e.stopPropagation()}>
+ <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout}>
+ <div className="collectionTimeView-button">
+ <FontAwesomeIcon icon={faEdit} size={"lg"} />
+ <span className="collectionTimeView-span">Facet Filters</span>
+ </div>
+ </Flyout>
+ </div>
+ <div className="collectionTimeView-tree" key="tree">
+ <CollectionTreeView
+ PanelPosition={""}
+ Document={facetCollection}
+ DataDoc={facetCollection}
+ fieldKey={`${this.props.fieldKey}-filter`}
+ CollectionView={this}
+ docFilters={returnEmptyFilter}
+ ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+ ContainingCollectionView={this.props.ContainingCollectionView}
+ PanelWidth={this.facetWidth}
+ PanelHeight={this.props.PanelHeight}
+ NativeHeight={returnZero}
+ NativeWidth={returnZero}
+ LibraryPath={emptyPath}
+ rootSelected={this.props.rootSelected}
+ renderDepth={1}
+ dropAction={this.props.dropAction}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+ addDocTab={returnFalse}
+ pinToPres={returnFalse}
+ isSelected={returnFalse}
+ select={returnFalse}
+ bringToFront={emptyFunction}
+ active={this.props.active}
+ whenActiveChanged={returnFalse}
+ treeViewHideTitle={true}
+ ContentScaling={returnOne}
+ focus={returnFalse}
+ treeViewHideHeaderFields={true}
+ onCheckedClick={this.scriptField}
+ ignoreFields={this.ignoreFields}
+ annotationsKey={""}
+ dontRegisterView={true}
+ backgroundColor={this.filterBackground}
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ addDocument={returnFalse} />
+ </div>
+ </div>;
}
childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null);
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index a974c5496..d8756aae3 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -177,9 +177,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
}
);
}
+ this.props.active
const cols = this.props.columns.map(col => {
-
const keysDropdown = <KeysDropdown
keyValue={col.heading}
possibleKeys={possibleKeys}
@@ -189,6 +189,14 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
onSelect={this.props.changeColumns}
setIsEditing={this.props.setHeaderIsEditing}
docs={this.props.childDocs}
+ Document={this.props.Document}
+ dataDoc={this.props.dataDoc}
+ fieldKey={this.props.fieldKey}
+ ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+ ContainingCollectionView={this.props.ContainingCollectionView}
+ active={this.props.active}
+
+
// try commenting this out
width={"100%"}
/>;
@@ -218,19 +226,15 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
background: col.color, padding: "2px",
display: "flex", cursor: "default", height: "100%",
}}>
- <FontAwesomeIcon icon={icon} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px" }} />
+ <FontAwesomeIcon onClick={e => this.props.openHeader(col, e.clientX, e.clientY)} icon={icon} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px", cursor: "hand" }} />
{/* <div className="keys-dropdown"
style={{ display: "inline", zIndex: 1000 }}> */}
{keysDropdown}
{/* </div> */}
<div onClick={e => this.changeSorting(col)}
- style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit" }}>
+ style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit", cursor: "hand" }}>
<FontAwesomeIcon icon={sortIcon} size="lg" />
</div>
- {/* <div onClick={e => this.props.openHeader(col, e.clientX, e.clientY)}
- style={{ float: "right", paddingRight: "6px", zIndex: 1, background: "inherit" }}>
- <FontAwesomeIcon icon={"compass"} size="sm" />
- </div> */}
</div>;
return {
@@ -318,27 +322,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
}
-
- @action
- nextHighlight = (e: React.MouseEvent, doc: Doc) => {
- e.preventDefault();
- e.stopPropagation();
- doc.searchMatch = false;
- console.log(doc.searchMatch);
- setTimeout(() => doc.searchMatch = true, 0);
- console.log(doc.searchMatch);
-
- doc.searchIndex = NumCast(doc.searchIndex);
- }
-
- @action
- nextHighlight2 = (doc: Doc) => {
-
- doc.searchMatchAlt = false;
- setTimeout(() => doc.searchMatchAlt = true, 0);
- doc.searchIndex = NumCast(doc.searchIndex);
- }
-
constructor(props: SchemaTableProps) {
super(props);
// convert old schema columns (list of strings) into new schema columns (list of schema header fields)
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 7de14c7d6..a396dc6c8 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -105,11 +105,12 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
if (br) break;
}
}
+ let ypos = y;
ns.map(line => {
const indent = line.search(/\S|$/);
- const newBox = Docs.Create.TextDocument(line, { _width: 200, _height: 35, x: x + indent / 3 * 10, y: y, title: line });
+ const newBox = Docs.Create.TextDocument(line, { _width: 200, _height: 35, x: x + indent / 3 * 10, y: ypos, title: line });
this.props.addDocument(newBox);
- y += 40 * this.props.getTransform().Scale;
+ ypos += 40 * this.props.getTransform().Scale;
});
})();
e.stopPropagation();
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index e0f3eca44..c7edd67b3 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -970,15 +970,15 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<div className="propertiesView-name">
{this.editableTitle}
<div className="propertiesView-presSelected">
- {PresBox.Instance._selectedArray.length} selected
+ {PresBox.Instance?._selectedArray.length} selected
<div className="propertiesView-selectedList">
- {PresBox.Instance.listOfSelected}
+ {PresBox.Instance?.listOfSelected}
</div>
</div>
</div>
{!selectedItem ? (null) : <div className="propertiesView-presTrails">
<div className="propertiesView-presTrails-title"
- onPointerDown={() => runInAction(() => { this.openPresTransitions = !this.openPresTransitions; })}
+ onPointerDown={action(() => { this.openPresTransitions = !this.openPresTransitions; })}
style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}>
&nbsp; <FontAwesomeIcon icon={"rocket"} /> &nbsp; Transitions
<div className="propertiesView-presTrails-title-icon">
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7d2c34b2b..58f8bdaac 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -324,6 +324,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
self: this.rootDoc,
scriptContext: this.props.scriptContext,
thisContainer: this.props.ContainingCollectionDoc,
+ documentView: this,
shiftKey: e.shiftKey
}, console.log);
if (!Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-undo"] as Doc) && !Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-redo"] as Doc)) {
@@ -924,7 +925,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const showTitle = StrCast(this.layoutDoc._showTitle);
const showTitleHover = StrCast(this.layoutDoc._showTitleHover);
const showCaption = StrCast(this.layoutDoc._showCaption);
- const showTextTitle = showTitle && (StrCast(this.layoutDoc.layout).indexOf("PresBox") !== -1 || StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1) ? showTitle : undefined;
+ const showTextTitle = showTitle && (StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1) ? showTitle : undefined;
const captionView = (!showCaption ? (null) :
<div className="documentView-captionWrapper" style={{ backgroundColor: StrCast(this.layoutDoc["caption-backgroundColor"]), color: StrCast(this.layoutDoc["caption-color"]) }}>
<DocumentContentsView {...OmitKeys(this.props, ['children']).omit}
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index a87b0e466..8ee7f1e0e 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -19,7 +19,7 @@ $light-background: #ececec;
.presBox-listCont {
position: relative;
- height: calc(100% - 25px);
+ height: calc(100% - 67px);
width: 100%;
margin-top: 3px;
}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 7d4bd5dd3..f1eb5ef09 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -23,7 +23,7 @@ import { PrefetchProxy } from '../../../../fields/Proxy';
import { RichTextField } from "../../../../fields/RichTextField";
import { RichTextUtils } from '../../../../fields/RichTextUtils';
import { createSchema, makeInterface } from "../../../../fields/Schema";
-import { Cast, DateCast, NumCast, StrCast, ScriptCast } from "../../../../fields/Types";
+import { Cast, DateCast, NumCast, StrCast, ScriptCast, BoolCast } from "../../../../fields/Types";
import { TraceMobx, OVERRIDE_ACL, GetEffectiveAcl } from '../../../../fields/util';
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, returnZero, Utils, setupMoveUpEvents } from '../../../../Utils';
import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
@@ -376,6 +376,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
public highlightSearchTerms = (terms: string[], alt: boolean) => {
if (this._editorView && (this._editorView as any).docView && terms.some(t => t)) {
+
const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight);
const activeMark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight, { selected: true });
const res = terms.filter(t => t).map(term => this.findInNode(this._editorView!, this._editorView!.state.doc, term));
@@ -383,30 +384,31 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
let tr = this._editorView.state.tr;
const flattened: TextSelection[] = [];
res.map(r => r.map(h => flattened.push(h)));
-
-
- const lastSel = Math.min(flattened.length - 1, this._searchIndex);
- flattened.forEach((h: TextSelection, ind: number) => tr = tr.addMark(h.from, h.to, ind === lastSel ? activeMark : mark));
- this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex;
- this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(flattened[lastSel].from), tr.doc.resolve(flattened[lastSel].to))).scrollIntoView());
- if (alt === true) {
- if (this._searchIndex > 1) {
- this._searchIndex += -2;
- }
- else if (this._searchIndex === 1) {
- this._searchIndex = length - 1;
- }
- else if (this._searchIndex === 0 && length !== 1) {
- this._searchIndex = length - 2;
- }
-
+ if (BoolCast(Doc.GetProto(this.dataDoc).resetSearch) === true) {
+ this._searchIndex = 0;
+ Doc.GetProto(this.dataDoc).resetSearch = undefined;
}
else {
+ this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex;
+ if (alt === true) {
+ if (this._searchIndex > 1) {
+ this._searchIndex += -2;
+ }
+ else if (this._searchIndex === 1) {
+ this._searchIndex = length - 1;
+ }
+ else if (this._searchIndex === 0 && length !== 1) {
+ this._searchIndex = length - 2;
+ }
+ }
}
- const index = this._searchIndex;
- Doc.GetProto(this.dataDoc).searchIndex = index;
+ const lastSel = Math.min(flattened.length - 1, this._searchIndex);
+ flattened.forEach((h: TextSelection, ind: number) => tr = tr.addMark(h.from, h.to, ind === lastSel ? activeMark : mark));
+ flattened[lastSel] && this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(flattened[lastSel].from), tr.doc.resolve(flattened[lastSel].to))).scrollIntoView());
+
+ console.log(this._searchIndex);
}
}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index cfa9a1844..7c1b2f621 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -337,7 +337,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
nextAnnotation = () => {
this.Index = Math.min(this.Index + 1, this.allAnnotations.length - 1);
this.scrollToAnnotation(this.allAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y))[this.Index]);
- this.Document.searchIndex = this.Index;
}
@@ -411,7 +410,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
phraseSearch: true,
query: searchString
});
- this.Document.searchIndex = this.Index;
}
else if (this._mainCont.current) {
const executeFind = () => {
@@ -425,7 +423,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
};
this._mainCont.current.addEventListener("pagesloaded", executeFind);
this._mainCont.current.addEventListener("pagerendered", executeFind);
- this.Document.searchIndex = this.Index;
}
}
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index f7b817aa1..4a14b222c 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -126,6 +126,29 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
if (e.target.value === "") {
+ if (this.currentSelectedCollection !== undefined) {
+ let newarray: Doc[] = [];
+ let docs: Doc[] = [];
+ docs = DocListCast(this.currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(this.currentSelectedCollection.dataDoc)]);
+ while (docs.length > 0) {
+ newarray = [];
+ docs.forEach((d) => {
+ if (d.data !== undefined) {
+ d._searchDocs = new List<Doc>();
+ d._docFilters = new List();
+ const newdocs = DocListCast(d.data);
+ newdocs.forEach((newdoc) => {
+ newarray.push(newdoc);
+ });
+ }
+ });
+ docs = newarray;
+ }
+
+ this.currentSelectedCollection.props.Document._searchDocs = new List<Doc>([]);
+ this.currentSelectedCollection.props.Document._docFilters = new List();
+ this.props.Document.selectedDoc = undefined;
+ }
this._results.forEach(result => {
Doc.UnBrushDoc(result[0]);
result[0].searchMatch = undefined;
@@ -235,7 +258,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
@action
filterDocsByType(docs: Doc[]) {
const finalDocs: Doc[] = [];
- const blockedTypes: string[] = ["preselement", "docholder", "collection", "search", "searchitem", "script", "fonticonbox", "button", "label"];
+ const blockedTypes: string[] = ["preselement", "docholder", "search", "searchitem", "script", "fonticonbox", "button", "label"];
docs.forEach(doc => {
const layoutresult = Cast(doc.type, "string");
if (layoutresult && !blockedTypes.includes(layoutresult)) {
@@ -299,6 +322,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
searchCollection(query: string) {
const selectedCollection: DocumentView = SelectionManager.SelectedDocuments()[0];
query = query.toLowerCase();
+
if (selectedCollection !== undefined) {
this.currentSelectedCollection = selectedCollection;
if (this.filter === true) {
@@ -312,6 +336,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
while (docs.length > 0) {
newarray = [];
docs.forEach((d) => {
+ d ? console.log(Cast(d.context, Doc)) : null;
if (d.data !== undefined) {
newarray.push(...DocListCast(d.data));
}
@@ -412,10 +437,33 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
@action
submitSearch = async (reset?: boolean) => {
+ if (this.currentSelectedCollection !== undefined) {
+ let newarray: Doc[] = [];
+ let docs: Doc[] = [];
+ docs = DocListCast(this.currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(this.currentSelectedCollection.dataDoc)]);
+ while (docs.length > 0) {
+ newarray = [];
+ docs.forEach((d) => {
+ if (d.data !== undefined) {
+ d._searchDocs = new List<Doc>();
+ d._docFilters = new List();
+ const newdocs = DocListCast(d.data);
+ newdocs.forEach((newdoc) => {
+ newarray.push(newdoc);
+ });
+ }
+ });
+ docs = newarray;
+ }
+
+ this.currentSelectedCollection.props.Document._searchDocs = new List<Doc>([]);
+ this.currentSelectedCollection.props.Document._docFilters = new List();
+ this.props.Document.selectedDoc = undefined;
+ }
if (reset) {
this.layoutDoc._searchString = "";
}
- this.props.Document._docFilters = undefined;
+ this.props.Document._docFilters = new List();
this.noresults = "";
this.dataDoc[this.fieldKey] = new List<Doc>([]);
@@ -586,7 +634,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
y += 300;
}
}
- return Docs.Create.SearchDocument({ _autoHeight: true, _viewType: CollectionViewType.Schema, title: StrCast(this.layoutDoc._searchString), searchQuery: StrCast(this.layoutDoc._searchString) });
+ return Docs.Create.SchemaDocument(Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []), DocListCast(this.dataDoc[this.fieldKey]), { _autoHeight: true, _viewType: CollectionViewType.Schema, title: StrCast(this.layoutDoc._searchString) });
}
@action.bound
@@ -628,7 +676,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
const endIndex = 30;
//this._endIndex = endIndex === -1 ? 12 : endIndex;
this._endIndex = 30;
- const headers = new Set<string>(["title", "author", "*lastModified", "text"]);
+ const headers = new Set<string>(["title", "author", "*lastModified"]);
if ((this._numTotalResults === 0 || this._results.length === 0) && this._openNoResults) {
if (this.noresults === "") {
this.noresults = "No search results :(";
@@ -733,6 +781,8 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
@computed get searchItemTemplate() { return Cast(Doc.UserDoc().searchItemTemplate, Doc, null); }
+ @computed get viewspec() { return Cast(this.props.Document._docFilters, listSpec("string"), []) }
+
getTransform = () => {
return this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
}
@@ -749,7 +799,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
@observable filter = false;
- //Make id layour document
render() {
this.props.Document._chromeStatus === "disabled";
this.props.Document._searchDoc = true;
@@ -758,47 +807,67 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
cols > 5 ? length = 1076 : length = cols * 205 + 51;
let height = 0;
const rows = this.children;
- rows > 8 ? height = 31 + 31 * 8 : height = 31 * rows + 31;
+ rows > 6 ? height = 31 + 31 * 6 : height = 31 * rows + 31;
return (
<div style={{ pointerEvents: "all" }} className="searchBox-container">
<div className="searchBox-bar">
<div style={{ position: "absolute", left: 15 }}>{Doc.CurrentUserEmail}</div>
<div style={{ display: "flex", alignItems: "center" }}>
- <FontAwesomeIcon onPointerDown={SetupDrag(this.collectionRef, () => StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined)} icon={"search"} size="lg"
- style={{ color: "black", padding: 1, left: 35, position: "relative" }} />
-
+ <Tooltip title={<div className="dash-tooltip" >drag search results as collection</div>} ><div>
+ <FontAwesomeIcon onPointerDown={SetupDrag(this.collectionRef, () => StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined)} icon={"search"} size="lg"
+ style={{ cursor: "hand", color: "black", padding: 1, left: 35, position: "relative" }} />
+ </div></Tooltip>
<div style={{ cursor: "default", left: 250, position: "relative", }}>
<Tooltip title={<div className="dash-tooltip" >only display documents matching search</div>} ><div>
<FontAwesomeIcon icon={"filter"} size="lg"
- style={{ padding: 1, backgroundColor: this.filter ? "white" : "lightgray", color: this.filter ? "black" : "white" }}
+ style={{ cursor: "hand", padding: 1, backgroundColor: this.filter ? "white" : "lightgray", color: this.filter ? "black" : "white" }}
onPointerDown={e => { e.stopPropagation(); SetupDrag(this.collectionRef, () => StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined); }}
onClick={action(() => {
- const dofilter = (currentSelectedCollection: DocumentView) => {
- let docs = DocListCast(currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(currentSelectedCollection.dataDoc)]);
+ ///DONT Change without emailing andy r first.
+ this.filter = !this.filter && !this.searchFullDB;
+ if (this.filter === true && this.currentSelectedCollection !== undefined) {
+ this.currentSelectedCollection.props.Document._searchDocs = new List<Doc>(this.docsforfilter);
+ let newarray: Doc[] = [];
+ let docs: Doc[] = [];
+ docs = DocListCast(this.currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(this.currentSelectedCollection.dataDoc)]);
while (docs.length > 0) {
- const newarray: Doc[] = [];
- docs.filter(d => d.data !== undefined).forEach((d) => {
- d._searchDocs = new List<Doc>(this.docsforfilter);
- newarray.push(...DocListCast(d.data));
+ newarray = [];
+ docs.forEach((d) => {
+ if (d.data !== undefined) {
+ d._searchDocs = new List<Doc>(this.docsforfilter);
+ const newdocs = DocListCast(d.data);
+ newdocs.forEach((newdoc) => {
+ newarray.push(newdoc);
+ });
+ }
});
docs = newarray;
}
- };
- this.filter = !this.filter && !this.searchFullDB;
- if (this.filter === true && this.currentSelectedCollection !== undefined) {
- this.currentSelectedCollection.props.Document._searchDocs = new List<Doc>(this.docsforfilter);
- dofilter(this.currentSelectedCollection);
-
- this.currentSelectedCollection.props.Document._docFilters = new List<string>(Cast(this.props.Document._docFilters, listSpec("string"), []));
+ this.currentSelectedCollection.props.Document._docFilters = new List<string>(this.viewspec);
this.props.Document.selectedDoc = this.currentSelectedCollection.props.Document;
}
else if (this.filter === false && this.currentSelectedCollection !== undefined) {
-
- dofilter(this.currentSelectedCollection);
+ let newarray: Doc[] = [];
+ let docs: Doc[] = [];
+ docs = DocListCast(this.currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(this.currentSelectedCollection.dataDoc)]);
+ while (docs.length > 0) {
+ newarray = [];
+ docs.forEach((d) => {
+ if (d.data !== undefined) {
+ d._searchDocs = new List<Doc>();
+ d._docFilters = new List();
+ const newdocs = DocListCast(d.data);
+ newdocs.forEach((newdoc) => {
+ newarray.push(newdoc);
+ });
+ }
+ });
+ docs = newarray;
+ }
this.currentSelectedCollection.props.Document._searchDocs = new List<Doc>([]);
- this.currentSelectedCollection.props.Document._docFilters = undefined;
+ this.currentSelectedCollection.props.Document._docFilters = new List();
this.props.Document.selectedDoc = undefined;
}
}
@@ -832,6 +901,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
docs.forEach((d) => {
if (d.data !== undefined) {
d._searchDocs = new List<Doc>();
+ d._docFilters = new List();
const newdocs = DocListCast(d.data);
newdocs.forEach((newdoc) => {
newarray.push(newdoc);
@@ -840,7 +910,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
});
docs = newarray;
}
- this.currentSelectedCollection.props.Document._docFilters = undefined;
+ this.currentSelectedCollection.props.Document._docFilters = new List();
this.currentSelectedCollection.props.Document._searchDocs = undefined;
this.currentSelectedCollection = undefined;
}
@@ -866,6 +936,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
docs.forEach((d) => {
if (d.data !== undefined) {
d._searchDocs = new List<Doc>();
+ d._docFilters = new List()
const newdocs = DocListCast(d.data);
newdocs.forEach((newdoc) => {
newarray.push(newdoc);
@@ -874,7 +945,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
});
docs = newarray;
}
- this.currentSelectedCollection.props.Document._docFilters = undefined;
+ this.currentSelectedCollection.props.Document._docFilters = new List();
this.currentSelectedCollection.props.Document._searchDocs = undefined;
this.currentSelectedCollection = undefined;
}
@@ -900,7 +971,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
removeDocument={returnFalse}
PanelHeight={this.open === true ? () => height : () => 0}
PanelWidth={this.open === true ? () => length : () => 0}
- overflow={cols > 5 || rows > 8 ? true : false}
+ overflow={cols > 5 || rows > 6 ? true : false}
focus={this.selectElement}
ScreenToLocalTransform={Transform.Identity}
/>
@@ -920,4 +991,4 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
</div >
);
}
-}
+} \ No newline at end of file
diff --git a/src/server/websocket.ts b/src/server/websocket.ts
index f9351ba05..18c5ece98 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -230,7 +230,6 @@ export namespace WebSocket {
"RichTextField": ["_t", value => value.Text],
"date": ["_d", value => new Date(value.date).toISOString()],
"proxy": ["_i", "fieldId"],
- // "proxy": ["", "fieldId"],
"list": ["_l", list => {
const results = [];
for (const value of list.fields) {