aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx59
-rw-r--r--src/client/util/Import & Export/ImportMetadataEntry.tsx119
-rw-r--r--src/client/util/Import & Export/KeyValue.tsx79
-rw-r--r--src/client/views/EditableView.tsx9
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