diff options
author | Sam Wilkins <samwilkins333@gmail.com> | 2019-07-05 20:37:06 -0400 |
---|---|---|
committer | Sam Wilkins <samwilkins333@gmail.com> | 2019-07-05 20:37:06 -0400 |
commit | 7db7bad21d25ad5be63810d9c4511ccb3428b2f5 (patch) | |
tree | 4e7687261ca6c01f2c3f0e962edd3440885ddb15 /src | |
parent | 07ef72f4703f99ab732ec4fdced353ec91e69947 (diff) |
data doc and persistence functionality added
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/Import & Export/DirectoryImportBox.tsx | 59 | ||||
-rw-r--r-- | src/client/util/Import & Export/ImportMetadataEntry.tsx | 119 | ||||
-rw-r--r-- | src/client/util/Import & Export/KeyValue.tsx | 79 | ||||
-rw-r--r-- | src/client/views/EditableView.tsx | 9 |
4 files changed, 178 insertions, 88 deletions
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 50086a306..88ce9c0e9 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -1,6 +1,6 @@ import "fs"; import React = require("react"); -import { Doc } from "../../../new_fields/Doc"; +import { Doc, Opt } from "../../../new_fields/Doc"; import { DocServer } from "../../DocServer"; import { RouteStore } from "../../../server/RouteStore"; import { action, observable, autorun, runInAction } from "mobx"; @@ -11,7 +11,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faArrowUp, faTag, faPlus } from '@fortawesome/free-solid-svg-icons'; import { Docs, DocumentOptions } from "../../documents/Documents"; import { observer } from "mobx-react"; -import KeyValue from "./KeyValue"; +import ImportMetadataEntry from "./ImportMetadataEntry"; import { Utils } from "../../../Utils"; import { DocumentManager } from "../DocumentManager"; @@ -24,12 +24,14 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> @observable private editingMetadata = false; @observable private metadata_guids: string[] = []; - @observable private entries: KeyValue[] = []; + @observable private entries: ImportMetadataEntry[] = []; @observable private quota = 1; @observable private remaining = 1; @observable private uploadBegun = false; + @observable private removeHover = false; + @observable private shouldKeep = false; public static LayoutString() { return FieldView.LayoutString(DirectoryImportBox); } @@ -87,7 +89,12 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> await Promise.all(promises); - docs.forEach(doc => this.entries.forEach(entry => doc[entry.key] = entry.value)); + docs.forEach(doc => { + this.entries.forEach(entry => { + let target = entry.onDataDoc ? Doc.GetProto(doc) : doc; + target[entry.key] = entry.value; + }); + }); let doc = this.props.Document; let options: DocumentOptions = { @@ -102,8 +109,11 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> let importContainer = Docs.StackingDocument(docs, options); importContainer.singleColumn = false; Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer); - this.props.removeDocument && this.props.removeDocument(doc); + !this.shouldKeep && this.props.removeDocument && this.props.removeDocument(doc); DocumentManager.Instance.jumpToDocument(importContainer, true); + this.uploadBegun = false; + this.quota = 1; + this.remaining = 1; } } @@ -129,7 +139,7 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> } @action - remove = (entry: KeyValue) => { + remove = (entry: ImportMetadataEntry) => { let index = this.entries.indexOf(entry); let key = entry.key; this.entries.splice(index, 1); @@ -144,6 +154,8 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> let quota = this.quota; let percent = `${100 - (remaining / quota * 100)}`; let uploadBegun = this.uploadBegun; + let showRemoveLabel = this.removeHover; + let keep = this.shouldKeep; percent = percent.split(".")[0]; percent = percent.startsWith("100") ? "99" : percent; return ( @@ -197,6 +209,30 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> }} src={"/assets/loading.gif"}></img> </label> + <input + type={"checkbox"} + onChange={e => runInAction(() => this.shouldKeep = e.target.checked)} + style={{ + margin: 0, + position: "absolute", + left: 10, + bottom: 10, + opacity: isEditing ? 0 : 1, + transition: "0.4s opacity ease", + pointerEvents: isEditing ? "none" : "all" + }} + onPointerEnter={action(() => this.removeHover = true)} + onPointerLeave={action(() => this.removeHover = false)} + /> + <p + style={{ + position: "absolute", + left: 27, + bottom: 8.4, + fontSize: 12, + opacity: showRemoveLabel ? 1 : 0, + transition: "0.4s opacity ease" + }}>Template will be {keep ? "kept" : "removed"} after upload</p> <div style={{ transition: "0.4s opacity ease", @@ -219,6 +255,7 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> height: 25, background: "black" }} + title={isEditing ? "Back to Upload" : "Add Metadata"} onClick={action(() => this.editingMetadata = !this.editingMetadata)} /> <FontAwesomeIcon @@ -252,6 +289,7 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> right: 41, top: 10 }} + title={"Add Metadata Entry"} onClick={this.addMetadataEntry} > <FontAwesomeIcon @@ -266,7 +304,14 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> </div> <p style={{ paddingLeft: 10, paddingTop: 8, paddingBottom: 7 }} >Add metadata to your import...</p> <hr style={{ margin: "6px 10px 12px 10px" }} /> - {guids.map(guid => <KeyValue remove={this.remove} key={guid} ref={(el) => { if (el) this.entries.push(el); }} />)} + {guids.map(guid => + <ImportMetadataEntry + key={guid} + remove={this.remove} + ref={(el) => { if (el) this.entries.push(el); }} + next={this.addMetadataEntry} + /> + )} </div> </div> } diff --git a/src/client/util/Import & Export/ImportMetadataEntry.tsx b/src/client/util/Import & Export/ImportMetadataEntry.tsx new file mode 100644 index 000000000..3b2a6ebb5 --- /dev/null +++ b/src/client/util/Import & Export/ImportMetadataEntry.tsx @@ -0,0 +1,119 @@ +import React = require("react"); +import { observer } from "mobx-react"; +import { EditableView } from "../../views/EditableView"; +import { observable, action, computed } from "mobx"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faPlus } from "@fortawesome/free-solid-svg-icons"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { Opt } from "../../../new_fields/Doc"; + +interface KeyValueProps { + remove: (self: ImportMetadataEntry) => void; + next: () => void; +} + +const keyPlaceholder = "Key"; +const valuePlaceholder = "Value"; + +@observer +export default class ImportMetadataEntry extends React.Component<KeyValueProps> { + @observable public key = keyPlaceholder; + @observable public value = valuePlaceholder; + + private keyRef = React.createRef<EditableView>(); + private valueRef = React.createRef<EditableView>(); + private checkRef = React.createRef<HTMLInputElement>(); + + constructor(props: KeyValueProps) { + super(props); + library.add(faPlus); + } + + @computed + public get valid() { + return (this.key.length > 0 && this.key !== keyPlaceholder) && (this.value.length > 0 && this.value !== valuePlaceholder); + } + + public get onDataDoc() { + return this.checkRef.current && this.checkRef.current.checked; + } + + @action + updateKey = (newKey: string) => { + this.key = newKey; + this.keyRef.current && this.keyRef.current.setIsFocused(false); + this.valueRef.current && this.valueRef.current.setIsFocused(true); + this.key.length === 0 && (this.key = keyPlaceholder); + return true; + } + + @action + updateValue = (newValue: string, shiftDown: boolean) => { + this.value = newValue; + this.valueRef.current && this.valueRef.current.setIsFocused(false); + this.value.length > 0 && shiftDown && this.props.next(); + this.value.length === 0 && (this.value = valuePlaceholder); + return true; + } + + render() { + let keyValueStyle: React.CSSProperties = { + paddingLeft: 10, + width: "50%", + opacity: this.valid ? 1 : 0.5, + }; + return ( + <div + style={{ + display: "flex", + flexDirection: "row", + paddingBottom: 5, + paddingRight: 5, + justifyContent: "center", + alignItems: "center", + alignContent: "center" + }} + > + <input + ref={this.checkRef} + style={{ margin: "0 10px 0 15px" }} + type="checkbox" + title={"Add to Data Document?"} + /> + <div className={"key_container"} style={keyValueStyle}> + <EditableView + ref={this.keyRef} + contents={this.key} + SetValue={this.updateKey} + GetValue={() => ""} + oneLine={true} + /> + </div> + <div + className={"value_container"} + style={keyValueStyle}> + <EditableView + ref={this.valueRef} + contents={this.value} + SetValue={this.updateValue} + GetValue={() => ""} + oneLine={true} + /> + </div> + <div onClick={() => this.props.remove(this)} title={"Delete Entry"}> + <FontAwesomeIcon + icon={faPlus} + color={"red"} + size={"1x"} + style={{ + marginLeft: 15, + marginRight: 15, + transform: "rotate(45deg)" + }} + /> + </div> + </div> + ); + } + +}
\ No newline at end of file diff --git a/src/client/util/Import & Export/KeyValue.tsx b/src/client/util/Import & Export/KeyValue.tsx deleted file mode 100644 index 15ef25f89..000000000 --- a/src/client/util/Import & Export/KeyValue.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React = require("react"); -import { observer } from "mobx-react"; -import { EditableView } from "../../views/EditableView"; -import { observable, action } from "mobx"; - -interface KeyValueProps { - remove: (self: KeyValue) => void; -} - -@observer -export default class KeyValue extends React.Component<KeyValueProps> { - @observable public key = "Key"; - @observable public value = "Value"; - - @action - updateKey = (newKey: string) => { - this.key = newKey; - return true; - } - - @action - updateValue = (newValue: string) => { - this.value = newValue; - return true; - } - - render() { - let keyValueStyle = { paddingLeft: 10, width: "50%" }; - let keySpecified = (this.key.length > 0 && this.key !== "Key"); - return ( - <div - style={{ - display: "flex", - flexDirection: "row", - paddingBottom: 5, - paddingRight: 5, - justifyContent: "center", - alignItems: "center", - alignContent: "center" - }} - onClick={() => this.props.remove(this)} - > - <input type="checkbox" /> - <div className={"key_container"} style={keyValueStyle}> - <EditableView - contents={this.key} - SetValue={this.updateKey} - GetValue={() => this.key} - oneLine={true} - /> - </div> - <div - className={"value_container"} - style={{ - opacity: keySpecified ? 1 : 0.5, - pointerEvents: keySpecified ? "all" : "none", - ...keyValueStyle - }}> - <EditableView - contents={this.value} - SetValue={this.updateValue} - GetValue={() => this.value} - oneLine={true} - /> - </div> - <div style={{ - borderRadius: "50%", - width: 10, - height: 10, - background: "red", - marginLeft: 15, - marginRight: 15 - }} /> - - </div> - ); - } - -}
\ No newline at end of file diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 97a2d19dd..ea6f48d0f 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -14,7 +14,7 @@ export interface EditableProps { * @param value - The string entered by the user to set the value to * @returns `true` if setting the value was successful, `false` otherwise * */ - SetValue(value: string): boolean; + SetValue(value: string, shiftDown?: boolean): boolean; OnFillDown?(value: string): void; @@ -52,7 +52,7 @@ export class EditableView extends React.Component<EditableProps> { this.props.OnTab && this.props.OnTab(); } else if (e.key === "Enter") { if (!e.ctrlKey) { - if (this.props.SetValue(e.currentTarget.value)) { + if (this.props.SetValue(e.currentTarget.value, e.shiftKey)) { this._editing = false; } } else if (this.props.OnFillDown) { @@ -76,6 +76,11 @@ export class EditableView extends React.Component<EditableProps> { e.stopPropagation(); } + @action + setIsFocused = (value: boolean) => { + this._editing = value; + } + render() { if (this._editing) { return <input className="editableView-input" defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus |