aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorSam Wilkins <abdullah_ahmed@brown.edu>2019-04-22 20:37:25 -0400
committerSam Wilkins <abdullah_ahmed@brown.edu>2019-04-22 20:37:25 -0400
commitff5e275d4d9bb17866a432459884274cd870a640 (patch)
treee00d6d90c20feefc51023c084b15388626e3035c /src/client/views/collections
parentece19e7f0fefdfff81e4599953bfb02429456963 (diff)
parent51601e1768647b99baa9cee3118a831da9bffc61 (diff)
a broken but in progress merge
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx17
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx51
-rw-r--r--src/client/views/collections/CollectionSchemaView.scss138
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx298
-rw-r--r--src/client/views/collections/CollectionSubView.tsx6
-rw-r--r--src/client/views/collections/CollectionView.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss9
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx58
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx1
11 files changed, 287 insertions, 301 deletions
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 444f6fc26..a8b061b04 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -22,7 +22,7 @@ export interface CollectionRenderProps {
removeDocument: (document: Document) => boolean;
moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
active: () => boolean;
- onActiveChanged: (isActive: boolean) => void;
+ whenActiveChanged: (isActive: boolean) => void;
}
export interface CollectionViewProps extends FieldViewProps {
@@ -55,19 +55,22 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
//TODO should this be observable?
private _isChildActive = false;
- onActiveChanged = (isActive: boolean) => {
+ whenActiveChanged = (isActive: boolean) => {
this._isChildActive = isActive;
- this.props.onActiveChanged(isActive);
+ this.props.whenActiveChanged(isActive);
}
createsCycle(documentToAdd: Document, containerDocument: Document): boolean {
- let data = documentToAdd.GetList<Document>(KeyStore.Data, []);
- for (const doc of data) {
+ if (!(documentToAdd instanceof Document)) {
+ return false;
+ }
+ let data = documentToAdd.GetList(KeyStore.Data, [] as Document[]);
+ for (const doc of data.filter(d => d instanceof Document)) {
if (this.createsCycle(doc, containerDocument)) {
return true;
}
}
- let annots = documentToAdd.GetList<Document>(KeyStore.Annotations, []);
+ let annots = documentToAdd.GetList(KeyStore.Annotations, [] as Document[]);
for (const annot of annots) {
if (this.createsCycle(annot, containerDocument)) {
return true;
@@ -181,7 +184,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
removeDocument: this.removeDocument,
moveDocument: this.moveDocument,
active: this.active,
- onActiveChanged: this.onActiveChanged,
+ whenActiveChanged: this.whenActiveChanged,
};
const viewtype = this.collectionViewType;
return (
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 4ea21b2f5..39e27b601 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -19,6 +19,7 @@ import { ServerUtils } from "../../../server/ServerUtil";
import { DragManager, DragLinksAsDocuments } from "../../util/DragManager";
import { TextField } from "../../../fields/TextField";
import { ListField } from "../../../fields/ListField";
+import { thisExpression } from "babel-types";
@observer
export class CollectionDockingView extends React.Component<SubCollectionViewProps> {
@@ -315,7 +316,7 @@ interface DockedFrameProps {
@observer
export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
- private _mainCont = React.createRef<HTMLDivElement>();
+ _mainCont = React.createRef<HTMLDivElement>();
@observable private _panelWidth = 0;
@observable private _panelHeight = 0;
@observable private _document: Opt<Document>;
@@ -325,38 +326,46 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
Server.GetField(this.props.documentId, action((f: Opt<Field>) => this._document = f as Document));
}
- private _nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth);
- private _nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight);
- private _contentScaling = () => this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth);
+ nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth);
+ nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight);
+ contentScaling = () => {
+ let wscale = this._panelWidth / (this.nativeWidth() ? this.nativeWidth() : this._panelWidth);
+ if (wscale * this.nativeHeight() > this._panelHeight)
+ return this._panelHeight / (this.nativeHeight() ? this.nativeHeight() : this._panelHeight);
+ return wscale;
+ }
ScreenToLocalTransform = () => {
- let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
- return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._contentScaling());
+ let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!.children[0].firstChild as HTMLElement);
+ scale = Utils.GetScreenTransform(this._mainCont.current!).scale;
+ return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this.contentScaling());
}
+ get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; }
- render() {
- if (!this._document) {
- return (null);
- }
- var content =
- <div className="collectionDockingView-content" ref={this._mainCont}>
- <DocumentView key={this._document.Id} Document={this._document}
+ get content() {
+ return (
+ <div className="collectionDockingView-content" ref={this._mainCont}
+ style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
+ <DocumentView key={this._document!.Id} Document={this._document!}
addDocument={undefined}
removeDocument={undefined}
- ContentScaling={this._contentScaling}
- PanelWidth={this._nativeWidth}
- PanelHeight={this._nativeHeight}
+ ContentScaling={this.contentScaling}
+ PanelWidth={this.nativeWidth}
+ PanelHeight={this.nativeHeight}
ScreenToLocalTransform={this.ScreenToLocalTransform}
isTopMost={true}
selectOnLoad={false}
parentActive={returnTrue}
- onActiveChanged={emptyFunction}
+ whenActiveChanged={emptyFunction}
focus={emptyDocFunction}
ContainingCollectionView={undefined} />
- </div>;
+ </div>);
+ }
- return <Measure onResize={action((r: any) => { this._panelWidth = r.entry.width; this._panelHeight = r.entry.height; })}>
- {({ measureRef }) => <div ref={measureRef}> {content} </div>}
- </Measure>;
+ render() {
+ return !this._document ? (null) :
+ <Measure onResize={action((r: any) => { this._panelWidth = r.entry.width; this._panelHeight = r.entry.height; })}>
+ {({ measureRef }) => <div ref={measureRef}> {this.content} </div>}
+ </Measure>;
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index c8bfedff4..bced0d5d4 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -1,61 +1,5 @@
@import "../globalCssVariables";
-//options menu styling
-#schemaOptionsMenuBtn {
- position: absolute;
- height: 20px;
- width: 20px;
- border-radius: 50%;
- z-index: 21;
- right: 4px;
- top: 4px;
- pointer-events: auto;
- background-color:black;
- display:inline-block;
- padding: 0px;
- font-size: 100%;
-}
-
-ul {
- list-style-type: disc;
-}
-
-#schema-options-header {
- text-align: center;
- padding: 0px;
- margin: 0px;
-}
-.schema-options-subHeader {
- color: $intermediate-color;
- margin-bottom: 5px;
-}
-#schemaOptionsMenuBtn:hover {
- transform: scale(1.15);
-}
-
-#preview-schema-checkbox-div {
- margin-left: 20px;
- font-size: 12px;
-}
-
- #options-flyout-div {
- text-align: left;
- padding:0px;
- z-index: 100;
- font-family: $sans-serif;
- padding-left: 5px;
- }
-
- #schema-col-checklist {
- overflow: scroll;
- text-align: left;
- //background-color: $light-color-secondary;
- line-height: 25px;
- max-height: 175px;
- font-family: $sans-serif;
- font-size: 12px;
- }
-
.collectionSchemaView-container {
border-width: $COLLECTION_BORDER_WIDTH;
@@ -67,17 +11,26 @@ ul {
width: 100%;
height: 100%;
- .collectionSchemaView-content {
- position: absolute;
- height: 100%;
- width: 100%;
- overflow: auto;
- }
.collectionSchemaView-previewRegion {
position: relative;
background: $light-color;
float: left;
height: 100%;
+ .collectionSchemaView-previewDoc {
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ }
+ .collectionSchemaView-input {
+ position: absolute;
+ max-width: 150px;
+ width: 100%;
+ bottom: 0px;
+ }
+ .documentView-node:first-child {
+ position: relative;
+ background: $light-color;
+ }
}
.collectionSchemaView-previewHandle {
position: absolute;
@@ -193,6 +146,11 @@ ul {
border-bottom-style: solid;
border-bottom-width: 1;
}
+ .documentView-node-topmost {
+ text-align:left;
+ transform-origin: center top;
+ display: inline-block;
+ }
.documentView-node:first-child {
background: $light-color;
.imageBox-cont img {
@@ -200,6 +158,62 @@ ul {
}
}
}
+//options menu styling
+#schemaOptionsMenuBtn {
+ position: absolute;
+ height: 20px;
+ width: 20px;
+ border-radius: 50%;
+ z-index: 21;
+ right: 4px;
+ top: 4px;
+ pointer-events: auto;
+ background-color:black;
+ display:inline-block;
+ padding: 0px;
+ font-size: 100%;
+}
+
+ul {
+ list-style-type: disc;
+}
+
+#schema-options-header {
+ text-align: center;
+ padding: 0px;
+ margin: 0px;
+}
+.schema-options-subHeader {
+ color: $intermediate-color;
+ margin-bottom: 5px;
+}
+#schemaOptionsMenuBtn:hover {
+ transform: scale(1.15);
+}
+
+#preview-schema-checkbox-div {
+ margin-left: 20px;
+ font-size: 12px;
+}
+
+ #options-flyout-div {
+ text-align: left;
+ padding:0px;
+ z-index: 100;
+ font-family: $sans-serif;
+ padding-left: 5px;
+ }
+
+ #schema-col-checklist {
+ overflow: scroll;
+ text-align: left;
+ //background-color: $light-color-secondary;
+ line-height: 25px;
+ max-height: 175px;
+ font-family: $sans-serif;
+ font-size: 12px;
+ }
+
.Resizer {
box-sizing: border-box;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4f4068e7a..08c9740d0 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -4,7 +4,6 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, untracked } from "mobx";
import { observer } from "mobx-react";
-import Measure from "react-measure";
import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
import "react-table/react-table.css";
import { Document } from "../../../fields/Document";
@@ -12,7 +11,7 @@ import { Field, Opt } from "../../../fields/Field";
import { Key } from "../../../fields/Key";
import { KeyStore } from "../../../fields/KeyStore";
import { ListField } from "../../../fields/ListField";
-import { emptyDocFunction, emptyFunction, returnFalse, returnOne } from "../../../Utils";
+import { emptyDocFunction, emptyFunction, returnFalse } from "../../../Utils";
import { Server } from "../../Server";
import { SetupDrag } from "../../util/DragManager";
import { CompileScript, ToField } from "../../util/Scripting";
@@ -34,42 +33,35 @@ import { CollectionSubView } from "./CollectionSubView";
class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggle: (key: Key) => void }> {
@observable key: Key | undefined;
- componentWillReceiveProps() {
- Server.GetField(this.props.keyId, action((field: Opt<Field>) => {
- if (field instanceof Key) {
- this.key = field;
- }
- }));
+ constructor(props: any) {
+ super(props);
+ Server.GetField(this.props.keyId, action((field: Opt<Field>) => field instanceof Key && (this.key = field)));
}
render() {
- if (this.key) {
- return (<div key={this.key.Id}>
+ return !this.key ? (null) :
+ (<div key={this.key.Id}>
<input type="checkbox" checked={this.props.checked} onChange={() => this.key && this.props.toggle(this.key)} />
{this.key.Name}
</div>);
- }
- return (null);
}
}
@observer
export class CollectionSchemaView extends CollectionSubView {
- private _mainCont = React.createRef<HTMLDivElement>();
+ private _mainCont?: HTMLDivElement;
private _startSplitPercent = 0;
private DIVIDER_WIDTH = 4;
@observable _columns: Array<Key> = [KeyStore.Title, KeyStore.Data, KeyStore.Author];
- @observable _contentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ContentScaling prop of the DocumentView
- @observable _dividerX = 0;
- @observable _panelWidth = 0;
- @observable _panelHeight = 0;
@observable _selectedIndex = 0;
@observable _columnsPercentage = 0;
@observable _keys: Key[] = [];
+ @observable _newKeyName: string = "";
@computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); }
-
+ @computed get columns() { return this.props.Document.GetList(KeyStore.ColumnsKey, [] as Key[]); }
+ @computed get borderWidth() { return COLLECTION_BORDER_WIDTH; }
renderCell = (rowProps: CellInfo) => {
let props: FieldViewProps = {
@@ -83,7 +75,7 @@ export class CollectionSchemaView extends CollectionSubView {
ScreenToLocalTransform: Transform.Identity,
focus: emptyDocFunction,
active: returnFalse,
- onActiveChanged: emptyFunction,
+ whenActiveChanged: emptyFunction,
};
let contents = (
<FieldView {...props} />
@@ -165,9 +157,9 @@ export class CollectionSchemaView extends CollectionSubView {
};
}
- @computed
- get columns() {
- return this.props.Document.GetList<Key>(KeyStore.ColumnsKey, []);
+ private createTarget = (ele: HTMLDivElement) => {
+ this._mainCont = ele;
+ super.CreateDropTarget(ele);
}
@action
@@ -187,31 +179,12 @@ export class CollectionSchemaView extends CollectionSubView {
//toggles preview side-panel of schema
@action
toggleExpander = (event: React.ChangeEvent<HTMLInputElement>) => {
- this._startSplitPercent = this.splitPercentage;
- if (this._startSplitPercent === this.splitPercentage) {
- this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage === 0 ? 33 : 0);
- }
- }
-
- @computed
- get findAllDocumentKeys(): { [id: string]: boolean } {
- const docs = this.props.Document.GetList<Document>(this.props.fieldKey, []);
- let keys: { [id: string]: boolean } = {};
- if (this._optionsActivated > -1) {
- // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields.
- // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be
- // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked.
- // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu
- // is displayed (unlikely) it won't show up until something else changes.
- untracked(() => docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))));
- }
- this.columns.forEach(key => keys[key.Id] = true);
- return keys;
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage === 0 ? 33 : 0);
}
@action
onDividerMove = (e: PointerEvent): void => {
- let nativeWidth = this._mainCont.current!.getBoundingClientRect();
+ let nativeWidth = this._mainCont!.getBoundingClientRect();
this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, Math.max(0, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100)));
}
@action
@@ -230,155 +203,152 @@ export class CollectionSchemaView extends CollectionSubView {
document.addEventListener('pointerup', this.onDividerUp);
}
- @observable _tableWidth = 0;
- @action
- setTableDimensions = (r: any) => {
- this._tableWidth = r.entry.width;
- }
- @action
- setScaling = (r: any) => {
- const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
- const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
- this._panelWidth = r.entry.width;
- this._panelHeight = r.entry.height ? r.entry.height : this._panelHeight;
- this._contentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width);
+ onPointerDown = (e: React.PointerEvent): void => {
+ if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
+ if (this.props.isSelected())
+ e.stopPropagation();
+ else e.preventDefault();
+ }
}
- @computed
- get borderWidth() { return COLLECTION_BORDER_WIDTH; }
- getContentScaling = (): number => this._contentScaling;
- getPanelWidth = (): number => this._panelWidth;
- getPanelHeight = (): number => this._panelHeight;
- getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling);
- getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling);
-
- onPointerDown = (e: React.PointerEvent): void => {
- if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
+ onWheel = (e: React.WheelEvent): void => {
+ if (this.props.active()) {
e.stopPropagation();
}
}
@action
addColumn = () => {
- this.columns.push(new Key(this.newKeyName));
- this.newKeyName = "";
+ this.columns.push(new Key(this._newKeyName));
+ this._newKeyName = "";
}
- @observable
- newKeyName: string = "";
-
@action
newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- this.newKeyName = e.currentTarget.value;
- }
- onWheel = (e: React.WheelEvent): void => {
- if (this.props.active()) {
- e.stopPropagation();
- }
+ this._newKeyName = e.currentTarget.value;
}
- @observable _optionsActivated: number = 0;
- @action
- OptionsMenuDown = (e: React.PointerEvent) => {
- this._optionsActivated++;
- }
-
- @observable previewScript: string = "this";
+ @observable previewScript: string = "";
@action
onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.previewScript = e.currentTarget.value;
}
- render() {
- library.add(faCog);
- library.add(faPlus);
- const columns = this.columns;
- const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
+ get previewDocument(): Document | undefined {
+ const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
- //all the keys/columns that will be displayed in the schema
- const allKeys = this.findAllDocumentKeys;
- let doc: any = selected ? selected.Get(new Key(this.previewScript)) : undefined;
+ return selected ? (this.previewScript ? selected.Get(new Key(this.previewScript)) as Document : selected) : undefined;
+ }
+ get tableWidth() { return this.props.PanelWidth() * (1 - this.splitPercentage / 100); }
+ get previewRegionHeight() { return this.props.PanelHeight(); }
+ get previewRegionWidth() { return this.props.PanelWidth() * this.splitPercentage / 100 - this.DIVIDER_WIDTH; }
+
+ private previewDocNativeWidth = () => this.previewDocument!.GetNumber(KeyStore.NativeWidth, this.previewRegionWidth);
+ private previewDocNativeHeight = () => this.previewDocument!.GetNumber(KeyStore.NativeHeight, this.previewRegionHeight);
+ private previewContentScaling = () => {
+ let wscale = this.previewRegionWidth / (this.previewDocNativeWidth() ? this.previewDocNativeWidth() : this.previewRegionWidth);
+ if (wscale * this.previewDocNativeHeight() > this.previewRegionHeight)
+ return this.previewRegionHeight / (this.previewDocNativeHeight() ? this.previewDocNativeHeight() : this.previewRegionHeight);
+ return wscale;
+ }
+ private previewPanelWidth = () => this.previewDocNativeWidth() * this.previewContentScaling();
+ private previewPanelHeight = () => this.previewDocNativeHeight() * this.previewContentScaling();
+ get previewPanelCenteringOffset() { return (this.previewRegionWidth - this.previewDocNativeWidth() * this.previewContentScaling()) / 2; }
+ getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(
+ - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth - this.previewPanelCenteringOffset,
+ - this.borderWidth).scale(1 / this.previewContentScaling());
+ @computed
+ get previewPanel() {
// let doc = CompileScript(this.previewScript, { this: selected }, true)();
- let content = this._selectedIndex === -1 || !selected ? (null) : (
- <Measure onResize={this.setScaling}>
- {({ measureRef }) =>
- <div className="collectionSchemaView-content" ref={measureRef}>
- {doc instanceof Document ?
- <DocumentView Document={doc}
- addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
- isTopMost={false}
- selectOnLoad={false}
- ScreenToLocalTransform={this.getPreviewTransform}
- ContentScaling={this.getContentScaling}
- PanelWidth={this.getPanelWidth}
- PanelHeight={this.getPanelHeight}
- ContainingCollectionView={this.props.CollectionView}
- focus={emptyDocFunction}
- parentActive={this.props.active}
- onActiveChanged={this.props.onActiveChanged} /> : null}
- <input value={this.previewScript} onChange={this.onPreviewScriptChange}
- style={{ position: 'absolute', bottom: '0px' }} />
- </div>
- }
- </Measure>
- );
- let dividerDragger = this.splitPercentage === 0 ? (null) :
- <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
-
- //options button and menu
- let optionsMenu = !this.props.active() ? (null) : (<Flyout
- anchorPoint={anchorPoints.LEFT_TOP}
- content={<div>
- <div id="schema-options-header"><h5><b>Options</b></h5></div>
- <div id="options-flyout-div">
- <h6 className="schema-options-subHeader">Preview Window</h6>
- <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.splitPercentage !== 0} onChange={this.toggleExpander} /> Show Preview </div>
- <h6 className="schema-options-subHeader" >Displayed Columns</h6>
- <ul id="schema-col-checklist" >
- {Array.from(Object.keys(allKeys)).map(item =>
- (<KeyToggle checked={allKeys[item]} key={item} keyId={item} toggle={this.toggleKey} />))}
- </ul>
- <input value={this.newKeyName} onChange={this.newKeyChange} />
- <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
+ return !this.previewDocument ? (null) : (
+ <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
+ <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
+ <DocumentView Document={this.previewDocument} isTopMost={false} selectOnLoad={false}
+ addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+ ScreenToLocalTransform={this.getPreviewTransform}
+ ContentScaling={this.previewContentScaling}
+ PanelWidth={this.previewPanelWidth} PanelHeight={this.previewPanelHeight}
+ ContainingCollectionView={this.props.CollectionView}
+ focus={emptyDocFunction}
+ parentActive={this.props.active}
+ whenActiveChanged={this.props.whenActiveChanged}
+ />
</div>
+ <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
+ style={{ left: `calc(50% - ${Math.min(75, this.previewPanelWidth() / 2)}px)` }} />
</div>
- }>
- <button id="schemaOptionsMenuBtn" onPointerDown={this.OptionsMenuDown}><FontAwesomeIcon style={{ color: "white" }} icon="cog" size="sm" /></button>
- </Flyout>);
+ );
+ }
- return (
- <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel} ref={this._mainCont}>
- <div className="collectionSchemaView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
- <Measure onResize={this.setTableDimensions}>
- {({ measureRef }) =>
- <div className="collectionSchemaView-tableContainer" ref={measureRef} style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
- <ReactTable
- data={children}
- pageSize={children.length}
- page={0}
- showPagination={false}
- columns={columns.map(col => ({
- Header: col.Name,
- accessor: (doc: Document) => [doc, col],
- id: col.Id
- }))}
- column={{
- ...ReactTableDefaults.column,
- Cell: this.renderCell,
+ get documentKeysCheckList() {
+ const docs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
+ let keys: { [id: string]: boolean } = {};
+ // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields.
+ // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be
+ // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked.
+ // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu
+ // is displayed (unlikely) it won't show up until something else changes.
+ untracked(() => docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))));
- }}
- getTrProps={this.getTrProps}
- />
- </div>}
- </Measure>
- {dividerDragger}
- <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
- {content}
+ this.columns.forEach(key => keys[key.Id] = true);
+ return Array.from(Object.keys(keys)).map(item =>
+ (<KeyToggle checked={keys[item]} key={item} keyId={item} toggle={this.toggleKey} />));
+ }
+
+ get tableOptionsPanel() {
+ return !this.props.active() ? (null) :
+ (<Flyout
+ anchorPoint={anchorPoints.LEFT_TOP}
+ content={<div>
+ <div id="schema-options-header"><h5><b>Options</b></h5></div>
+ <div id="options-flyout-div">
+ <h6 className="schema-options-subHeader">Preview Window</h6>
+ <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.splitPercentage !== 0} onChange={this.toggleExpander} /> Show Preview </div>
+ <h6 className="schema-options-subHeader" >Displayed Columns</h6>
+ <ul id="schema-col-checklist" >
+ {this.documentKeysCheckList}
+ </ul>
+ <input value={this._newKeyName} onChange={this.newKeyChange} />
+ <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
</div>
- {optionsMenu}
</div>
- </div >
+ }>
+ <button id="schemaOptionsMenuBtn" ><FontAwesomeIcon style={{ color: "white" }} icon="cog" size="sm" /></button>
+ </Flyout>);
+ }
+
+ @computed
+ get dividerDragger() {
+ return this.splitPercentage === 0 ? (null) :
+ <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
+ }
+
+ render() {
+ library.add(faCog);
+ library.add(faPlus);
+ if (!this.previewDocument)
+ return (null);
+
+ const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
+ return (
+ <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
+ onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
+ <div className="collectionSchemaView-tableContainer" style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
+ <ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
+ columns={this.columns.map(col => ({
+ Header: col.Name,
+ accessor: (doc: Document) => [doc, col],
+ id: col.Id
+ }))}
+ column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
+ getTrProps={this.getTrProps}
+ />
+ </div>
+ {this.dividerDragger}
+ {this.previewPanel}
+ {this.tableOptionsPanel}
+ </div>
);
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index d3d69b1af..5c3b2e586 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -15,7 +15,6 @@ import { ServerUtils } from "../../../server/ServerUtil";
import { Server } from "../../Server";
import { FieldViewProps } from "../nodes/FieldView";
import * as rp from 'request-promise';
-import { emptyFunction } from "../../../Utils";
import { CollectionView } from "./CollectionView";
import { CollectionPDFView } from "./CollectionPDFView";
import { CollectionVideoView } from "./CollectionVideoView";
@@ -24,6 +23,8 @@ export interface CollectionViewProps extends FieldViewProps {
addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
removeDocument: (document: Document) => boolean;
moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
+ PanelWidth: () => number;
+ PanelHeight: () => number;
}
export interface SubCollectionViewProps extends CollectionViewProps {
@@ -42,6 +43,9 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
}
}
+ protected CreateDropTarget(ele: HTMLDivElement) {
+ this.createDropTarget(ele);
+ }
@action
protected setCursorPosition(position: [number, number]) {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index bd7a5635f..675e720e2 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -29,8 +29,10 @@ export class CollectionView extends React.Component<FieldViewProps> {
return (null);
}
+ get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's?
+
onContextMenu = (e: React.MouseEvent): void => {
- if (!e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+ if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)) });
ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema)) });
ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree)) });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 2f684a54e..cd74d3a84 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -16,9 +16,9 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
_brushReactionDisposer?: IReactionDisposer;
componentDidMount() {
- this._brushReactionDisposer = reaction(() => this.props.Document.GetList<Document>(this.props.fieldKey, []).map(doc => doc.GetNumber(KeyStore.X, 0)),
+ this._brushReactionDisposer = reaction(() => this.props.Document.GetList(this.props.fieldKey, [] as Document[]).map(doc => doc.GetNumber(KeyStore.X, 0)),
() => {
- let views = this.props.Document.GetList<Document>(this.props.fieldKey, []);
+ let views = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
for (let i = 0; i < views.length; i++) {
for (let j = 0; j < views.length; j++) {
let srcDoc = views[j];
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index 751ea8190..cf0a6de00 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -12,7 +12,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
protected getCursors(): CursorEntry[] {
let doc = this.props.Document;
let id = CurrentUserUtils.id;
- let cursors = doc.GetList<CursorEntry>(KeyStore.Cursors, []);
+ let cursors = doc.GetList(KeyStore.Cursors, [] as CursorEntry[]);
let notMe = cursors.filter(entry => entry.Data[0][0] !== id);
return id ? notMe : [];
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 392bd514f..57706b51e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -1,11 +1,4 @@
@import "../../globalCssVariables";
-.collectionfreeformview-measure {
- position: inherit;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- }
.collectionfreeformview {
position: inherit;
top: 0;
@@ -52,7 +45,7 @@
}
opacity: 0.99;
- border-width: 0;
+ border-width: 0;
border-color: transparent;
border-style: solid;
border-radius: $border-radius;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3ae64d2c6..228fc937e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -28,8 +28,8 @@ export class CollectionFreeFormView extends CollectionSubView {
private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type)
private _lastX: number = 0;
private _lastY: number = 0;
- @observable private _pwidth: number = 0;
- @observable private _pheight: number = 0;
+ private get _pwidth() { return this.props.PanelWidth(); }
+ private get _pheight() { return this.props.PanelHeight(); }
@computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
@computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
@@ -85,7 +85,9 @@ export class CollectionFreeFormView extends CollectionSubView {
d.SetNumber(KeyStore.Width, 300);
}
if (!d.GetNumber(KeyStore.Height, 0)) {
- d.SetNumber(KeyStore.Height, 300);
+ let nw = d.GetNumber(KeyStore.NativeWidth, 0);
+ let nh = d.GetNumber(KeyStore.NativeHeight, 0);
+ d.SetNumber(KeyStore.Height, nw && nh ? nh / nw * d.Width() : 300);
}
this.bringToFront(d);
});
@@ -218,7 +220,7 @@ export class CollectionFreeFormView extends CollectionSubView {
@action
bringToFront(doc: Document) {
- this.props.Document.GetList<Document>(this.props.fieldKey, []).slice().sort((doc1, doc2) => {
+ this.props.Document.GetList(this.props.fieldKey, [] as Document[]).slice().sort((doc1, doc2) => {
if (doc1 === doc) return 1;
if (doc2 === doc) return -1;
return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0);
@@ -248,7 +250,7 @@ export class CollectionFreeFormView extends CollectionSubView {
ContainingCollectionView: this.props.CollectionView,
focus: this.focusDocument,
parentActive: this.props.active,
- onActiveChanged: this.props.active,
+ whenActiveChanged: this.props.active,
};
}
@@ -269,11 +271,6 @@ export class CollectionFreeFormView extends CollectionSubView {
}
@action
- onResize = (r: any) => {
- this._pwidth = r.entry.width;
- this._pheight = r.entry.height;
- }
- @action
onCursorMove = (e: React.PointerEvent) => {
super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY));
}
@@ -281,29 +278,24 @@ export class CollectionFreeFormView extends CollectionSubView {
render() {
const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
return (
- <Measure onResize={this.onResize}>
- {({ measureRef }) => (
- <div className="collectionfreeformview-measure" ref={measureRef}>
- <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
- onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} >
- <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
- addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
- getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
- <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
- zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
- <CollectionFreeFormBackgroundView {...this.getDocumentViewProps(this.props.Document)} />
- <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
- <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
- {this.childViews}
- </InkingCanvas>
- </CollectionFreeFormLinksView>
- <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" />
- </CollectionFreeFormViewPannableContents>
- <CollectionFreeFormOverlayView {...this.getDocumentViewProps(this.props.Document)} />
- </MarqueeView>
- </div>
- </div>)}
- </Measure>
+ <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
+ onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} >
+ <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
+ addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
+ getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
+ <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
+ zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
+ <CollectionFreeFormBackgroundView {...this.getDocumentViewProps(this.props.Document)} />
+ <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
+ <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
+ {this.childViews}
+ </InkingCanvas>
+ </CollectionFreeFormLinksView>
+ <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" />
+ </CollectionFreeFormViewPannableContents>
+ <CollectionFreeFormOverlayView {...this.getDocumentViewProps(this.props.Document)} />
+ </MarqueeView>
+ </div>
);
}
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 96d59c831..65f461b27 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -147,7 +147,6 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
d.SetNumber(KeyStore.X, d.GetNumber(KeyStore.X, 0) - bounds.left - bounds.width / 2);
d.SetNumber(KeyStore.Y, d.GetNumber(KeyStore.Y, 0) - bounds.top - bounds.height / 2);
d.SetNumber(KeyStore.Page, -1);
- d.SetText(KeyStore.Title, "" + d.Width() + " " + d.Height());
return d;
});
let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);