diff options
author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-02-03 22:35:33 -0500 |
---|---|---|
committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-02-03 22:35:33 -0500 |
commit | e6871754b90e2179a140c6f0c365b95be80e245b (patch) | |
tree | b84d122909540036df201a93e7ec375e9f81d7e8 /src | |
parent | 0748b6c92a0a8239596330bc0ba2054ee114a943 (diff) |
Added preview box in schema view, added ScrollBox control,
added resizable grid layout, cleaned up some styling for collection
freeform view
Diffstat (limited to 'src')
-rw-r--r-- | src/documents/Documents.ts | 2 | ||||
-rw-r--r-- | src/util/ScrollBox.tsx | 21 | ||||
-rw-r--r-- | src/views/collections/CollectionFreeFormView.scss | 9 | ||||
-rw-r--r-- | src/views/collections/CollectionFreeFormView.tsx | 12 | ||||
-rw-r--r-- | src/views/collections/CollectionSchemaView.scss | 108 | ||||
-rw-r--r-- | src/views/collections/CollectionSchemaView.tsx | 96 | ||||
-rw-r--r-- | src/views/nodes/DocumentView.tsx | 19 | ||||
-rw-r--r-- | src/views/nodes/FieldTextBox.tsx | 18 |
8 files changed, 246 insertions, 39 deletions
diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts index a5edebda2..932abf7bc 100644 --- a/src/documents/Documents.ts +++ b/src/documents/Documents.ts @@ -57,7 +57,7 @@ export namespace Documents { export function TextDocument(options: DocumentOptions = {}): Document { let doc = GetTextPrototype().MakeDelegate(); setupOptions(doc, options); - doc.SetField(KeyStore.Data, new RichTextField()); + // doc.SetField(KeyStore.Data, new RichTextField()); return doc; } diff --git a/src/util/ScrollBox.tsx b/src/util/ScrollBox.tsx new file mode 100644 index 000000000..b6b088170 --- /dev/null +++ b/src/util/ScrollBox.tsx @@ -0,0 +1,21 @@ +import React = require("react") + +export class ScrollBox extends React.Component { + onWheel = (e: React.WheelEvent) => { + if (e.currentTarget.scrollHeight > e.currentTarget.clientHeight) { // If the element has a scroll bar, then we don't want the containing collection to zoom + e.stopPropagation(); + } + } + + render() { + return ( + <div style={{ + overflow: "auto", + width: "100%", + height: "100%", + }} onWheel={this.onWheel}> + {this.props.children} + </div> + ) + } +}
\ No newline at end of file diff --git a/src/views/collections/CollectionFreeFormView.scss b/src/views/collections/CollectionFreeFormView.scss index 870e48556..e9d134e7b 100644 --- a/src/views/collections/CollectionFreeFormView.scss +++ b/src/views/collections/CollectionFreeFormView.scss @@ -2,10 +2,19 @@ position: relative; top: 0; left: 0; + width: 100%; + height: 100%; overflow: hidden; .collectionfreeformview { position: absolute; top: 0; left: 0; } +} + +.border { + border-style: solid; + box-sizing: border-box; + width: 100%; + height: 100%; }
\ No newline at end of file diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx index c77bd5820..403dbf503 100644 --- a/src/views/collections/CollectionFreeFormView.tsx +++ b/src/views/collections/CollectionFreeFormView.tsx @@ -204,13 +204,15 @@ export class CollectionFreeFormView extends React.Component<CollectionViewProps> return ( <div className="border" style={{ - borderStyle: "solid", borderWidth: `${COLLECTION_BORDER_WIDTH}px`, }}> - <div className="collectionfreeformview-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel} onContextMenu={(e) => e.preventDefault()} style={{ - width: "100%", - height: `calc(100% - 2*${COLLECTION_BORDER_WIDTH}px)`, - }} onDrop={this.onDrop} onDragOver={this.onDragOver} ref={this._containerRef}> + <div className="collectionfreeformview-container" + onPointerDown={this.onPointerDown} + onWheel={this.onPointerWheel} + onContextMenu={(e) => e.preventDefault()} + onDrop={this.onDrop} + onDragOver={this.onDragOver} + ref={this._containerRef}> <div className="collectionfreeformview" style={{ transform: `translate(${panx}px, ${pany}px) scale(${currScale}, ${currScale})`, transformOrigin: `left, top` }} ref={this._canvasRef}> <div className="node-container" ref={this._nodeContainerRef}> diff --git a/src/views/collections/CollectionSchemaView.scss b/src/views/collections/CollectionSchemaView.scss index e69de29bb..707b44db6 100644 --- a/src/views/collections/CollectionSchemaView.scss +++ b/src/views/collections/CollectionSchemaView.scss @@ -0,0 +1,108 @@ +.Resizer { + box-sizing: border-box; + background: #000; + opacity: 0.5; + z-index: 1; + background-clip: padding-box; + &.horizontal { + height: 11px; + margin: -5px 0; + border-top: 5px solid rgba(255, 255, 255, 0); + border-bottom: 5px solid rgba(255, 255, 255, 0); + cursor: row-resize; + width: 100%; + &:hover { + border-top: 5px solid rgba(0, 0, 0, 0.5); + border-bottom: 5px solid rgba(0, 0, 0, 0.5); + } + } + &.vertical { + width: 11px; + margin: 0 -5px; + border-left: 5px solid rgba(255, 255, 255, 0); + border-right: 5px solid rgba(255, 255, 255, 0); + cursor: col-resize; + &:hover { + border-left: 5px solid rgba(0, 0, 0, 0.5); + border-right: 5px solid rgba(0, 0, 0, 0.5); + } + } + &:hover { + -webkit-transition: all 2s ease; + transition: all 2s ease; + } +} + +.vertical { + section { + width: 100vh; + height: 100vh; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } + header { + padding: 1rem; + background: #eee; + } + footer { + padding: 1rem; + background: #eee; + } +} + +.horizontal { + section { + width: 100vh; + height: 100vh; + display: flex; + flex-direction: column; + } + header { + padding: 1rem; + background: #eee; + } + footer { + padding: 1rem; + background: #eee; + } +} + +.parent { + width: 100%; + height: 100%; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +.header { + background: #aaa; + height: 3rem; + line-height: 3rem; +} + +.wrapper { + background: #ffa; + margin: 5rem; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; +}
\ No newline at end of file diff --git a/src/views/collections/CollectionSchemaView.tsx b/src/views/collections/CollectionSchemaView.tsx index 01a5ab639..b95faeebe 100644 --- a/src/views/collections/CollectionSchemaView.tsx +++ b/src/views/collections/CollectionSchemaView.tsx @@ -1,16 +1,23 @@ -import { CollectionViewProps, DocumentFieldViewProps } from "../nodes/DocumentView"; +import { CollectionViewProps, DocumentFieldViewProps, DocumentView, DocumentContents } from "../nodes/DocumentView"; import React = require("react") -import ReactTable, { ReactTableDefaults, CellInfo } from "react-table"; +import ReactTable, { ReactTableDefaults, CellInfo, ComponentPropsGetterRC, ComponentPropsGetterR } from "react-table"; import { observer } from "mobx-react"; import { KeyStore as KS, Key } from "../../fields/Key"; import { Document } from "../../fields/Document"; import { FieldView } from "../nodes/FieldView"; import "react-table/react-table.css" +import { observable, action } from "mobx"; +import SplitPane from "react-split-pane" +import "./CollectionSchemaView.scss" +import { ScrollBox } from "../../util/ScrollBox"; @observer export class CollectionSchemaView extends React.Component<CollectionViewProps> { public static LayoutString() { return '<CollectionSchemaView Document={Document} fieldKey={DataKey} ContainingDocumentView={ContainingDocumentView}/>'; } + @observable + selectedIndex = 0; + renderCell = (rowProps: CellInfo) => { if (!this.props.ContainingDocumentView) { return <div></div> @@ -20,7 +27,38 @@ export class CollectionSchemaView extends React.Component<CollectionViewProps> { fieldKey: rowProps.value[1], containingDocumentView: this.props.ContainingDocumentView } - return <FieldView {...props} /> + return ( + <FieldView {...props} /> + ) + } + + private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { + const that = this; + if (!rowInfo) { + return {}; + } + return { + onClick: action((e: React.MouseEvent, handleOriginal: Function) => { + that.selectedIndex = rowInfo.index; + const doc: Document = rowInfo.original; + console.log("Row clicked: ", doc.Title) + + if (handleOriginal) { + handleOriginal() + } + }), + style: { + background: rowInfo.index == this.selectedIndex ? "#00afec" : "white", + color: rowInfo.index == this.selectedIndex ? "white" : "black" + } + }; + } + + onPointerDown = (e: React.PointerEvent) => { + let target = e.target as HTMLElement; + if (target.tagName == "SPAN" && target.className.includes("Resizer")) { + e.stopPropagation(); + } } render() { @@ -28,22 +66,44 @@ export class CollectionSchemaView extends React.Component<CollectionViewProps> { const children = Document.GetListField<Document>(fieldKey, []); const columns = Document.GetListField(KS.ColumnsKey, [KS.Title, KS.Data, KS.Author]) + let content; + if (this.selectedIndex != -1) { + content = (<DocumentContents Document={children[this.selectedIndex]} + ContainingDocumentView={this.props.ContainingDocumentView} + ContainingCollectionView={undefined} />) + } else { + content = <div /> + } return ( - <ReactTable - data={children} - columns={columns.map(col => { - return ( - { - Header: col.Name, - accessor: (doc: Document) => [doc, col], - id: col.Id - }) - })} - column={{ - ...ReactTableDefaults.column, - Cell: this.renderCell - }} - /> + <div onPointerDown={this.onPointerDown} > + <SplitPane split={"vertical"} defaultSize="60%"> + <ScrollBox> + <ReactTable + data={children} + pageSize={children.length} + page={0} + showPagination={false} + style={{ + display: "inline-block" + }} + columns={columns.map(col => { + return ( + { + Header: col.Name, + accessor: (doc: Document) => [doc, col], + id: col.Id + }) + })} + column={{ + ...ReactTableDefaults.column, + Cell: this.renderCell + }} + getTrProps={this.getTrProps} + /> + </ScrollBox> + {content} + </SplitPane> + </div> ) } }
\ No newline at end of file diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index 7f11300cc..9e8df0d79 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -52,7 +52,7 @@ interface CollectionView { } @observer -class DocumentContents extends React.Component<DocumentViewProps> { +export class DocumentContents extends React.Component<DocumentViewProps> { @computed get layout(): string { @@ -80,13 +80,15 @@ class DocumentContents extends React.Component<DocumentViewProps> { bindings[key.Name] = field.GetValue(); } } - return <JsxParser - components={{ FieldTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }} - bindings={bindings} - jsx={this.layout} - showWarnings={true} - onError={(test: any) => { console.log(test) }} - /> + return ( + <JsxParser + components={{ FieldTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView }} + bindings={bindings} + jsx={this.layout} + showWarnings={true} + onError={(test: any) => { console.log(test) }} + /> + ) } } @@ -365,7 +367,6 @@ export class DocumentView extends React.Component<DocumentViewProps> { } } - render() { var freestyling = this.props.ContainingCollectionView instanceof CollectionFreeFormView; return ( diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx index 9809f3aed..1e03bf0f9 100644 --- a/src/views/nodes/FieldTextBox.tsx +++ b/src/views/nodes/FieldTextBox.tsx @@ -8,11 +8,11 @@ import { EditorView } from "prosemirror-view"; import { Document } from "../../fields/Document"; import { Opt } from "../../fields/Field"; import { Key } from "../../fields/Key"; -import { TextField } from "../../fields/TextField"; import { SelectionManager } from "../../util/SelectionManager"; import { DocumentView, DocumentFieldViewProps } from "./DocumentView"; import "./FieldTextBox.scss"; import React = require("react") +import { RichTextField } from "../../fields/RichTextField"; // FieldTextBox: Displays an editable plain text node that maps to a specified Key of a Document @@ -51,7 +51,7 @@ export class FieldTextBox extends React.Component<DocumentFieldViewProps> { const state = this._editorView.state.apply(tx); this._editorView.updateState(state); const { doc, fieldKey } = this.props; - doc.SetFieldValue(fieldKey, JSON.stringify(state.toJSON()), TextField); + doc.SetFieldValue(fieldKey, JSON.stringify(state.toJSON()), RichTextField); } } @@ -67,7 +67,7 @@ export class FieldTextBox extends React.Component<DocumentFieldViewProps> { ] }; - let field = doc.GetFieldT(fieldKey, TextField); + let field = doc.GetFieldT(fieldKey, RichTextField); if (field) { state = EditorState.fromJSON(config, JSON.parse(field.Data)); } else { @@ -81,7 +81,7 @@ export class FieldTextBox extends React.Component<DocumentFieldViewProps> { } this._reactionDisposer = reaction(() => { - const field = this.props.doc.GetFieldT(this.props.fieldKey, TextField); + const field = this.props.doc.GetFieldT(this.props.fieldKey, RichTextField); return field ? field.Data : undefined; }, (field) => { if (field && this._editorView) { @@ -106,7 +106,7 @@ export class FieldTextBox extends React.Component<DocumentFieldViewProps> { @action onChange(e: React.ChangeEvent<HTMLInputElement>) { const { fieldKey, doc } = this.props; - doc.SetFieldValue(fieldKey, e.target.value, TextField); + doc.SetFieldValue(fieldKey, e.target.value, RichTextField); } onPointerDown = (e: React.PointerEvent): void => { let me = this; @@ -115,6 +115,12 @@ export class FieldTextBox extends React.Component<DocumentFieldViewProps> { } } render() { - return (<div className="fieldTextBox-cont" onPointerDown={this.onPointerDown} ref={this._ref} />) + return (<div className="fieldTextBox-cont" + style={{ + color: "initial", + whiteSpace: "initial" + }} + onPointerDown={this.onPointerDown} + ref={this._ref} />) } }
\ No newline at end of file |