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.ts2
-rw-r--r--src/client/util/DocumentManager.ts1
-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/CollectionSchemaCells.tsx206
-rw-r--r--src/client/views/collections/CollectionSchemaHeaders.tsx287
-rw-r--r--src/client/views/collections/CollectionSchemaView.scss87
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx28
-rw-r--r--src/client/views/collections/CollectionSubView.tsx31
-rw-r--r--src/client/views/collections/CollectionView.tsx103
-rw-r--r--src/client/views/collections/SchemaTable.tsx39
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx41
-rw-r--r--src/client/views/pdf/PDFViewer.tsx3
-rw-r--r--src/client/views/search/SearchBox.tsx70
-rw-r--r--src/server/websocket.ts3
17 files changed, 644 insertions, 268 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e54c89d9f..6a9701cfa 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1211,5 +1211,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 7eed4d2b1..ee17c694f 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -964,4 +964,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/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index eea133ed9..ea854c2a3 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -171,6 +171,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 182f6397c..fd9b04128 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -331,6 +331,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 4d5dfc99e..5f7abdcb1 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/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..b7d6f212f 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,21 @@ 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";
+
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -286,6 +299,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 +320,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 +335,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 +386,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 +413,242 @@ 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);
}
});
-
+ //checked={() =>{Cast(this.props.Document!._docRangeFilters, listSpec("string"))!.includes(key)}}
const options = keyOptions.map(key => {
+ //Doc.setDocFilter(this.props.Document!, this._key, key, undefined);
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", 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) }} ></input>
+ {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 => {
+ // 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 +657,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..ee643b86b 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,7 +323,6 @@ button.add-column {
background-color: white;
.key-option {
- //background-color: $light-color;
background-color: white;
border: 1px solid lightgray;
padding: 2px 3px;
@@ -315,6 +357,47 @@ 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;
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 d1aeb1b65..9be5a5d99 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);
@@ -131,27 +129,17 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
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 docsforFilter: Doc[] = childDocs;
if (searchDocs !== undefined && searchDocs.length > 0) {
docsforFilter = [];
- // let newdocs: Doc[] = [];
- // let newarray: Doc[] = [];
- //while (childDocs.length > 0) {
- //newarray = [];
+
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 +151,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 +165,13 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
docsforFilter.push(d);
}
});
- //childDocs = newarray;
- //}
+
}
childDocs = docsforFilter;
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
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 0feec3fbd..fe30cb05a 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()));
}
}
}
@@ -510,56 +513,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/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 7d4bd5dd3..31d69327b 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,32 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
let tr = this._editorView.state.tr;
const flattened: TextSelection[] = [];
res.map(r => r.map(h => flattened.push(h)));
+ 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 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;
- }
-
- }
- else {
-
- }
- const index = this._searchIndex;
- Doc.GetProto(this.dataDoc).searchIndex = index;
+ 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..6d6f32da7 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -235,7 +235,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 +299,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 +313,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));
}
@@ -586,7 +588,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 +630,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 :(";
@@ -749,7 +751,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,44 +759,63 @@ 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.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>();
+ 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;
@@ -900,7 +920,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 +940,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 63cfa41f0..798c79164 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -230,8 +230,7 @@ export namespace WebSocket {
"script": ["_t", value => value.script.originalScript],
"RichTextField": ["_t", value => value.Text],
"date": ["_d", value => new Date(value.date).toISOString()],
- // "proxy": ["_i", "fieldId"],
- // "proxy": ["", "fieldId"],
+ "proxy": ["_i", "fieldId"],
"list": ["_l", list => {
const results = [];
for (const value of list.fields) {