aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deploy/assets/loading.gifbin0 -> 114208 bytes
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.scss0
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx194
-rw-r--r--src/client/util/Import & Export/KeyValue.tsx79
-rw-r--r--src/client/views/MainView.tsx2
5 files changed, 217 insertions, 58 deletions
diff --git a/deploy/assets/loading.gif b/deploy/assets/loading.gif
new file mode 100644
index 000000000..0652bf021
--- /dev/null
+++ b/deploy/assets/loading.gif
Binary files differ
diff --git a/src/client/util/Import & Export/DirectoryImportBox.scss b/src/client/util/Import & Export/DirectoryImportBox.scss
deleted file mode 100644
index e69de29bb..000000000
--- a/src/client/util/Import & Export/DirectoryImportBox.scss
+++ /dev/null
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 2d77f6ae6..cbc8c6fdc 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx
@@ -3,44 +3,46 @@ import React = require("react");
import { Doc } from "../../../new_fields/Doc";
import { DocServer } from "../../DocServer";
import { RouteStore } from "../../../server/RouteStore";
-import { action, observable, runInAction } from "mobx";
+import { action, observable, autorun, runInAction } from "mobx";
import { FieldViewProps, FieldView } from "../../views/nodes/FieldView";
import Measure, { ContentRect } from "react-measure";
import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faArrowUp, faTag, faFileExcel } from '@fortawesome/free-solid-svg-icons';
+import { faArrowUp, faTag, faPlus } from '@fortawesome/free-solid-svg-icons';
import { Docs, DocumentOptions } from "../../documents/Documents";
-import { EditableView } from "../../views/EditableView";
+import { observer } from "mobx-react";
+import KeyValue from "./KeyValue";
+import { Utils } from "../../../Utils";
+import { doesNotReject } from "assert";
+import { remove } from "typescript-collections/dist/lib/arrays";
+@observer
export default class DirectoryImportBox extends React.Component<FieldViewProps> {
private selector = React.createRef<HTMLInputElement>();
@observable private top = 0;
@observable private left = 0;
private dimensions = 50;
- @observable private key = "Key";
- @observable private value = "Value";
+ @observable private editingMetadata = false;
+ @observable private metadata_guids: string[] = [];
+ @observable private entries: KeyValue[] = [];
+
+ @observable private quota = 1;
+ @observable private remaining = 1;
+
+ @observable private uploadBegun = false;
public static LayoutString() { return FieldView.LayoutString(DirectoryImportBox); }
constructor(props: FieldViewProps) {
super(props);
- library.add(faArrowUp, faTag);
- }
-
- updateKey = (newKey: string) => {
- runInAction(() => this.key = newKey);
- console.log("KEY ", this.key);
- return true;
- }
-
- updateValue = (newValue: string) => {
- runInAction(() => this.value = newValue);
- console.log("VALUE ", this.value);
- return true;
+ library.add(faArrowUp, faTag, faPlus);
}
+ @action
handleSelection = async (e: React.ChangeEvent<HTMLInputElement>) => {
+ this.uploadBegun = true;
+
let promises: Promise<void>[] = [];
let docs: Doc[] = [];
@@ -49,9 +51,15 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
let directory = (files.item(0) as any).webkitRelativePath.split("/", 1);
+ let validated: File[] = [];
for (let i = 0; i < files.length; i++) {
- let uploaded_file = files.item(i);
+ let file = files.item(i);
+ file && validated.push(file);
+ }
+
+ this.quota = validated.length;
+ for (let uploaded_file of validated) {
if (!uploaded_file) {
continue;
}
@@ -61,15 +69,18 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
let dropFileName = uploaded_file ? uploaded_file.name : "-empty-";
let type = uploaded_file.type;
+ this.remaining++;
+
let prom = fetch(DocServer.prepend(RouteStore.upload), {
method: 'POST',
body: formData
}).then(async (res: Response) => {
(await res.json()).map(action((file: any) => {
let path = DocServer.prepend(file);
- console.log(path);
let docPromise = Docs.getDocumentFromType(type, path, { nativeWidth: 300, width: 300, title: dropFileName });
- docPromise.then(doc => doc && docs.push(doc));
+ docPromise.then(doc => {
+ doc && docs.push(doc) && runInAction(() => this.remaining--);
+ });
}));
});
promises.push(prom);
@@ -77,11 +88,14 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
await Promise.all(promises);
+ docs.forEach(doc => this.entries.forEach(entry => doc[entry.key] = entry.value));
+
let doc = this.props.Document;
let options: DocumentOptions = { title: `Import of ${directory}`, width: 500, height: 500, x: Doc.GetT(doc, "x", "number"), y: Doc.GetT(doc, "y", "number") };
let parent = this.props.ContainingCollectionView;
if (parent) {
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);
}
@@ -103,9 +117,29 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
this.top = bounds.height / 2 - offset;
}
+ @action
+ addMetadataEntry = () => {
+ this.metadata_guids.push(Utils.GenerateGuid());
+ }
+
+ @action
+ remove = (entry: KeyValue) => {
+ let index = this.entries.indexOf(entry);
+ let key = entry.key;
+ this.entries.splice(index, 1);
+ this.metadata_guids.splice(this.metadata_guids.indexOf(key), 1);
+ }
+
render() {
let dimensions = 50;
- let keyValueStyle = { paddingLeft: 5, width: "50%" };
+ let guids = this.metadata_guids.map(el => el);
+ let isEditing = this.editingMetadata;
+ let remaining = this.remaining;
+ let quota = this.quota;
+ let percent = `${100 - (remaining / quota * 100)}`;
+ let uploadBegun = this.uploadBegun;
+ percent = percent.split(".")[0];
+ percent = percent.startsWith("100") ? "99" : percent;
return (
<Measure offset onResize={this.preserveCentering}>
{({ measureRef }) =>
@@ -113,14 +147,20 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
<input
id={"selector"}
ref={this.selector}
- name={"selector"}
onChange={this.handleSelection}
type="file"
style={{
position: "absolute",
display: "none"
}} />
- <label htmlFor={"selector"}>
+ <label
+ htmlFor={"selector"}
+ style={{
+ opacity: isEditing ? 0 : 1,
+ pointerEvents: isEditing ? "none" : "all",
+ transition: "0.4s ease opacity"
+ }}
+ >
<div style={{
width: dimensions,
height: dimensions,
@@ -132,46 +172,86 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
}} />
<div style={{
position: "absolute",
- left: this.left + 12.5,
- top: this.top + 11
+ left: this.left + 12.6,
+ top: this.top + 11,
+ opacity: uploadBegun ? 0 : 1,
+ transition: "0.4s opacity ease"
}}>
<FontAwesomeIcon icon={faArrowUp} color="#FFFFFF" size={"2x"} />
</div>
</label>
- <div style={{
- position: "absolute",
- top: 5,
- right: 5,
- borderRadius: "50%",
- width: 25,
- height: 25,
- background: "black"
- }} />
- <div style={{
- position: "absolute",
- right: 9.5,
- top: 11
- }}>
- <FontAwesomeIcon icon={faTag} color="#FFFFFF" size={"1x"} />
- </div>
- <div style={{ display: "flex", flexDirection: "row", borderBottom: "1px solid black", paddingBottom: 5 }} >
- <div className={"key_container"} style={keyValueStyle}>
- <EditableView
- contents={this.key}
- SetValue={this.updateKey}
- GetValue={() => this.key}
- oneLine={true}
- />
- </div>
- <div className={"value_container"} style={keyValueStyle}>
- <EditableView
- contents={this.value}
- SetValue={this.updateValue}
- GetValue={() => this.value}
- oneLine={true}
+ <div
+ style={{
+ transition: "0.4s opacity ease",
+ opacity: uploadBegun ? 1 : 0,
+ pointerEvents: "none",
+ position: "absolute",
+ left: 10,
+ top: this.top + 12.3,
+ fontSize: 18,
+ color: "white",
+ marginLeft: this.left - 1.6
+ }}>{percent}%</div>
+ <div
+ style={{
+ position: "absolute",
+ top: 10,
+ right: 10,
+ borderRadius: "50%",
+ width: 25,
+ height: 25,
+ background: "black"
+ }}
+ onClick={action(() => this.editingMetadata = !this.editingMetadata)}
+ />
+ <FontAwesomeIcon
+ style={{
+ pointerEvents: "none",
+ position: "absolute",
+ right: isEditing ? 16.3 : 14.5,
+ top: isEditing ? 15.4 : 16
+ }}
+ icon={isEditing ? faArrowUp : faTag}
+ color="#FFFFFF"
+ size={"1x"}
+ />
+ <div
+ style={{
+ transition: "0.4s ease opacity",
+ width: "100%",
+ height: "100%",
+ pointerEvents: isEditing ? "all" : "none",
+ opacity: isEditing ? 1 : 0,
+ overflowY: "scroll"
+ }}
+ >
+ <div
+ style={{
+ borderRadius: "50%",
+ width: 25,
+ height: 25,
+ marginLeft: 10,
+ position: "absolute",
+ right: 41,
+ top: 10
+ }}
+ onClick={this.addMetadataEntry}
+ >
+ <FontAwesomeIcon
+ style={{
+ pointerEvents: "none",
+ marginLeft: 6.4,
+ marginTop: 5.2
+ }}
+ icon={faPlus}
+ size={"1x"}
/>
</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); }} />)}
</div>
+ {/* <img style={{ width: 30, height: 30 }} src={"./loading.gif"}></img> */}
</div>
}
</Measure>
diff --git a/src/client/util/Import & Export/KeyValue.tsx b/src/client/util/Import & Export/KeyValue.tsx
new file mode 100644
index 000000000..15ef25f89
--- /dev/null
+++ b/src/client/util/Import & Export/KeyValue.tsx
@@ -0,0 +1,79 @@
+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/MainView.tsx b/src/client/views/MainView.tsx
index 3d059b2f3..60decff25 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -351,7 +351,7 @@ export class MainView extends React.Component {
let addColNode = action(() => Docs.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
let addTreeNode = action(() => CurrentUserUtils.UserDocument);
let addImageNode = action(() => Docs.ImageDocument(imgurl, { width: 200, title: "an image of a cat" }));
- let addImportCollectionNode = action(() => Docs.DirectoryImportDocument({ title: "Directory Import", width: 150, height: 150 }));
+ let addImportCollectionNode = action(() => Docs.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 }));
let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Doc][] = [
[React.createRef<HTMLDivElement>(), "image", "Add Image", addImageNode],