aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-08-23 11:22:31 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-08-23 11:22:31 -0400
commit56753f8d87f7647d7012fd1c4c35daffc116ec11 (patch)
tree4ff3aeb8c50d6006c0d5b5c9748cdf9fd49d558c /src/client/views/collections
parentf0f0cc36654183921076db5a341fe7cac2bfdd3c (diff)
parentac23ac310985ac9042694473df3defb2adbd09f2 (diff)
merged with master
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx5
-rw-r--r--src/client/views/collections/CollectionViewChromes.scss73
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx87
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx47
4 files changed, 183 insertions, 29 deletions
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b61894b29..7e1aacd5d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -28,6 +28,7 @@ import "./CollectionTreeView.scss";
import React = require("react");
import { ComputedField, ScriptField } from '../../../new_fields/ScriptField';
import { KeyValueBox } from '../nodes/KeyValueBox';
+import { ContextMenuProps } from '../ContextMenuItem';
export interface TreeViewProps {
@@ -541,6 +542,10 @@ export class CollectionTreeView extends CollectionSubView(Document) {
e.stopPropagation();
e.preventDefault();
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
+ } else {
+ let layoutItems: ContextMenuProps[] = [];
+ layoutItems.push({ description: this.props.Document.preventTreeViewOpen ? "Persist Treeview State" : "Abandon Treeview State", event: () => this.props.Document.preventTreeViewOpen = !this.props.Document.preventTreeViewOpen, icon: "paint-brush" });
+ ContextMenu.Instance.addItem({ description: "Treeview Options ...", subitems: layoutItems, icon: "eye" });
}
}
outerXf = () => Utils.GetScreenTransform(this._mainEle!);
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index f39bd877a..64411b5fe 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -64,7 +64,7 @@
font-size: 75%;
background: rgb(238, 238, 238);
height: 100%;
- width: 150px;
+ width: 75px;
}
.collectionViewBaseChrome-viewSpecsMenu {
@@ -234,4 +234,75 @@
margin-left: 50px;
}
}
+}
+
+
+.commandEntry-outerDiv {
+ display: flex;
+ flex-direction: column;
+ width: 165px;
+ height: 40px;
+}
+.commandEntry-inputArea {
+ display:flex;
+ flex-direction: row;
+ width: 150px;
+ margin: auto 0 auto auto;
+}
+
+.react-autosuggest__container {
+ position: relative;
+ width: 100%;
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
+.react-autosuggest__input {
+ border: 1px solid #aaa;
+ border-radius: 4px;
+ width: 100%;
+}
+
+.react-autosuggest__input--focused {
+ outline: none;
+}
+
+.react-autosuggest__input--open {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+}
+
+.react-autosuggest__suggestions-container {
+ display: none;
+}
+
+.react-autosuggest__suggestions-container--open {
+ display: block;
+ position: fixed;
+ overflow-y: auto;
+ max-height: 400px;
+ width: 180px;
+ border: 1px solid #aaa;
+ background-color: #fff;
+ font-family: Helvetica, sans-serif;
+ font-weight: 300;
+ font-size: 16px;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ z-index: 2;
+}
+
+.react-autosuggest__suggestions-list {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+}
+
+.react-autosuggest__suggestion {
+ cursor: pointer;
+ padding: 10px 20px;
+}
+
+.react-autosuggest__suggestion--highlighted {
+ background-color: #ddd;
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 74e57611d..352bcd4a6 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -8,7 +8,7 @@ import { List } from "../../../new_fields/List";
import { listSpec } from "../../../new_fields/Schema";
import { ScriptField } from "../../../new_fields/ScriptField";
import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
-import { Utils } from "../../../Utils";
+import { Utils, emptyFunction } from "../../../Utils";
import { DragManager } from "../../util/DragManager";
import { CompileScript } from "../../util/Scripting";
import { undoBatch } from "../../util/UndoManager";
@@ -18,7 +18,9 @@ import { DocLike } from "../MetadataEntryMenu";
import { CollectionViewType } from "./CollectionBaseView";
import { CollectionView } from "./CollectionView";
import "./CollectionViewChromes.scss";
+import * as Autosuggest from 'react-autosuggest';
import KeyRestrictionRow from "./KeyRestrictionRow";
+import { Docs } from "../../documents/Documents";
const datepicker = require('js-datepicker');
interface CollectionViewChromeProps {
@@ -43,6 +45,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
@observable private _dateWithinValue: string = "";
@observable private _dateValue: Date | string = "";
@observable private _keyRestrictions: [JSX.Element, string][] = [];
+ @observable private suggestions: string[] = [];
+ _commandRef = React.createRef<HTMLInputElement>();
@computed private get filterValue() { return Cast(this.props.CollectionView.props.Document.viewSpecScript, ScriptField); }
private _picker: any;
@@ -287,7 +291,12 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
protected drop(e: Event, de: DragManager.DropEvent): boolean {
if (de.data instanceof DragManager.DocumentDragData) {
if (de.data.draggedDocuments.length) {
- this.props.CollectionView.props.Document.childLayout = de.data.draggedDocuments[0];
+ if (this._currentKey === "Set Template") {
+ this.props.CollectionView.props.Document.childLayout = de.data.draggedDocuments[0];
+ }
+ if (this._currentKey === "Set Content") {
+ Doc.GetProto(this.props.CollectionView.props.Document).data = new List<Doc>(de.data.draggedDocuments);
+ }
e.stopPropagation();
return true;
}
@@ -308,6 +317,63 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
}
}
}
+
+ @observable private _currentKey: string = "";
+ @observable _allCommands: string[] = ["Set Template", "Set Content"];
+ private autosuggestRef = React.createRef<Autosuggest>();
+
+ renderSuggestion = (suggestion: string) => {
+ return <p>{suggestion}</p>;
+ }
+ getSuggestionValue = (suggestion: string) => suggestion;
+
+ @action
+ onKeyChange = (e: React.ChangeEvent, { newValue }: { newValue: string }) => {
+ this._currentKey = newValue;
+ }
+ onSuggestionFetch = async ({ value }: { value: string }) => {
+ const sugg = await this.getKeySuggestions(value);
+ runInAction(() => this.suggestions = sugg);
+ }
+ @action
+ onSuggestionClear = () => {
+ this.suggestions = [];
+ }
+ getKeySuggestions = async (value: string): Promise<string[]> => {
+ return this._allCommands.filter(c => c.indexOf(value) !== -1);
+ }
+
+ autoSuggestDown = (e: React.PointerEvent) => {
+ e.stopPropagation();
+ }
+ dragCommandDown = (e: React.PointerEvent) => {
+ let de = new DragManager.DocumentDragData([this.props.CollectionView.props.Document], [undefined]);
+ DragManager.StartDocumentDrag([this._commandRef.current!], de, e.clientX, e.clientY, {
+ finishDrag: (dropData: { [id: string]: any }) => {
+ let bd = Docs.Create.ButtonDocument({ width: 150, height: 50, title: this._currentKey });
+ let script = `getProto(target).data = copyField(this.source);`;
+ let compiled = CompileScript(script, {
+ params: { doc: Doc.name },
+ capturedVariables: { target: this.props.CollectionView.props.Document },
+ typecheck: false,
+ editable: true
+ });
+ if (compiled.compiled) {
+ let scriptField = new ScriptField(compiled);
+ bd.onClick = scriptField;
+ }
+ dropData.droppedDocuments = [bd];
+ },
+ handlers: {
+ dragComplete: action(() => {
+ }),
+ },
+ hideSource: false
+ });
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
render() {
let collapsed = this.props.CollectionView.props.Document.chromeStatus !== "enabled";
return (
@@ -337,7 +403,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
</select>
<div className="collectionViewBaseChrome-viewSpecs" style={{ display: collapsed ? "none" : "grid" }}>
<input className="collectionViewBaseChrome-viewSpecsInput"
- placeholder="FILTER DOCUMENTS"
+ placeholder="FILTER"
value={this.filterValue ? this.filterValue.script.originalScript === "return true" ? "" : this.filterValue.script.originalScript : ""}
onChange={(e) => { }}
onPointerDown={this.openViewSpecs}
@@ -388,8 +454,19 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
</div>
</div>
</div>
- <div className="collectionViewBaseChrome-template" ref={this.createDropTarget} style={{}}>
- TEMPLATE
+ <div className="collectionViewBaseChrome-template" ref={this.createDropTarget} >
+ <div className="commandEntry-outerDiv" ref={this._commandRef} onPointerDown={this.dragCommandDown}>
+ <div className="commandEntry-inputArea" onPointerDown={this.autoSuggestDown} >
+ <Autosuggest inputProps={{ value: this._currentKey, onChange: this.onKeyChange }}
+ getSuggestionValue={this.getSuggestionValue}
+ suggestions={this.suggestions}
+ alwaysRenderSuggestions={true}
+ renderSuggestion={this.renderSuggestion}
+ onSuggestionsFetchRequested={this.onSuggestionFetch}
+ onSuggestionsClearRequested={this.onSuggestionClear}
+ ref={this.autosuggestRef} />
+ </div>
+ </div>
</div>
</div>
{this.subChrome()}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index cbc123c61..224e8047d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -345,9 +345,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}, -1);
if (cluster !== -1) {
let eles = this.childDocs.filter(cd => NumCast(cd.cluster) === cluster);
+
+ // hacky way to get a list of DocumentViews in the current view given a list of Documents in the current view
+ let prevSelected = SelectionManager.SelectedDocuments();
this.selectDocuments(eles);
let clusterDocs = SelectionManager.SelectedDocuments();
SelectionManager.DeselectAll();
+ prevSelected.map(dv => SelectionManager.SelectDoc(dv, true));
+
let de = new DragManager.DocumentDragData(eles, eles.map(d => undefined));
de.moveDocument = this.props.moveDocument;
const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0);
@@ -818,30 +823,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
onContextMenu = (e: React.MouseEvent) => {
let layoutItems: ContextMenuProps[] = [];
- layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: this.fitToContainer, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" });
- layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
- layoutItems.push({
- description: `${this.props.Document.useClusters ? "Uncluster" : "Use Clusters"}`,
- event: async () => {
- Docs.Prototypes.get(DocumentType.TEXT).defaultBackgroundColor = "#f1efeb"; // backward compatibility with databases that didn't have a default background color on prototypes
- Docs.Prototypes.get(DocumentType.COL).defaultBackgroundColor = "white";
- this.props.Document.useClusters = !this.props.Document.useClusters;
- },
- icon: !this.props.Document.useClusters ? "braille" : "braille"
- });
layoutItems.push({
- description: `${this.props.Document.clusterOverridesDefaultBackground ? "Use Default Backgrounds" : "Clusters Override Defaults"}`,
- event: async () => this.props.Document.clusterOverridesDefaultBackground = !this.props.Document.clusterOverridesDefaultBackground,
- icon: !this.props.Document.useClusters ? "chalkboard" : "chalkboard"
- });
- layoutItems.push({ description: "Arrange contents in grid", event: this.arrangeContents, icon: "table" });
- ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" });
-
- let existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers...");
- let analyzers: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : [];
- analyzers.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" });
- !existingAnalyze && ContextMenu.Instance.addItem({ description: "Analyzers...", subitems: analyzers, icon: "hand-point-right" });
- ContextMenu.Instance.addItem({
description: "Import document", icon: "upload", event: () => {
const input = document.createElement("input");
input.type = "file";
@@ -871,6 +853,25 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
input.click();
}
});
+ layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: this.fitToContainer, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" });
+ layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
+ layoutItems.push({
+ description: `${this.props.Document.useClusters ? "Uncluster" : "Use Clusters"}`,
+ event: async () => {
+ Docs.Prototypes.get(DocumentType.TEXT).defaultBackgroundColor = "#f1efeb"; // backward compatibility with databases that didn't have a default background color on prototypes
+ Docs.Prototypes.get(DocumentType.COL).defaultBackgroundColor = "white";
+ this.props.Document.useClusters = !this.props.Document.useClusters;
+ },
+ icon: !this.props.Document.useClusters ? "braille" : "braille"
+ });
+ layoutItems.push({
+ description: `${this.props.Document.clusterOverridesDefaultBackground ? "Use Default Backgrounds" : "Clusters Override Defaults"}`,
+ event: async () => this.props.Document.clusterOverridesDefaultBackground = !this.props.Document.clusterOverridesDefaultBackground,
+ icon: !this.props.Document.useClusters ? "chalkboard" : "chalkboard"
+ });
+ layoutItems.push({ description: "Arrange contents in grid", event: this.arrangeContents, icon: "table" });
+ layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" });
+ ContextMenu.Instance.addItem({ description: "Freeform Options ...", subitems: layoutItems, icon: "eye" });
}