aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/Import & Export/ImageUtils.ts26
-rw-r--r--src/client/views/collections/CollectionView.tsx2
-rw-r--r--src/server/database.ts7
-rw-r--r--src/server/index.ts73
-rw-r--r--src/server/test.txt1
5 files changed, 76 insertions, 33 deletions
diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts
index bf482aea8..c9abf38fa 100644
--- a/src/client/util/Import & Export/ImageUtils.ts
+++ b/src/client/util/Import & Export/ImageUtils.ts
@@ -21,31 +21,11 @@ export namespace ImageUtils {
return data !== undefined;
};
- export type Hierarchy = { [id: string]: string | Hierarchy };
-
- export const ExportHierarchyToFileSystem = async (doc: Doc): Promise<void> => {
- const hierarchy: Hierarchy = {};
- await HierarchyTraverserRecursive(doc, hierarchy);
+ export const ExportHierarchyToFileSystem = async (collection: Doc): Promise<void> => {
const a = document.createElement("a");
- a.href = Utils.prepend(`${RouteStore.imageHierarchyExport}/${JSON.stringify(hierarchy)}`);
- a.download = `Full Export of ${StrCast(doc.title)}`;
+ a.href = Utils.prepend(`${RouteStore.imageHierarchyExport}/${collection[Id]}`);
+ a.download = `Dash Export [${StrCast(collection.title)}].zip`;
a.click();
};
- const HierarchyTraverserRecursive = async (collection: Doc, hierarchy: Hierarchy) => {
- const children = await DocListCastAsync(collection.data);
- if (children) {
- const local: Hierarchy = {};
- hierarchy[collection[Id]] = local;
- for (const child of children) {
- let imageData: Opt<ImageField>;
- if (imageData = Cast(child.data, ImageField)) {
- local[child[Id]] = imageData.url.href;
- } else {
- await HierarchyTraverserRecursive(child, local);
- }
- }
- }
- };
-
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 534246326..893763840 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -18,6 +18,7 @@ import { CollectionSchemaView } from "./CollectionSchemaView";
import { CollectionStackingView } from './CollectionStackingView';
import { CollectionTreeView } from "./CollectionTreeView";
import { CollectionViewBaseChrome } from './CollectionViewChromes';
+import { ImageUtils } from '../../util/Import & Export/ImageUtils';
export const COLLECTION_BORDER_WIDTH = 2;
library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy);
@@ -123,6 +124,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : [];
layoutItems.push({ description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" });
!existing && ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "hand-point-right" });
+ ContextMenu.Instance.addItem({ description: "Export Image Hierarchy", icon: "columns", event: () => ImageUtils.ExportHierarchyToFileSystem(this.props.Document) });
}
}
diff --git a/src/server/database.ts b/src/server/database.ts
index d2375ebd9..990441d5a 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -131,7 +131,7 @@ export namespace Database {
}
}
- public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = Database.DocumentsCollection) {
+ public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = "newDocuments") {
if (this.db) {
this.db.collection(collectionName).findOne({ _id: id }, (err, result) => {
if (result) {
@@ -165,7 +165,7 @@ export namespace Database {
}
}
- public async visit(ids: string[], fn: (result: any) => string[], collectionName = "newDocuments"): Promise<void> {
+ public async visit(ids: string[], fn: (result: any) => string[] | Promise<string[]>, collectionName = "newDocuments"): Promise<void> {
if (this.db) {
const visited = new Set<string>();
while (ids.length) {
@@ -179,10 +179,9 @@ export namespace Database {
for (const doc of docs) {
const id = doc.id;
visited.add(id);
- ids.push(...fn(doc));
+ ids.push(...(await fn(doc)));
}
}
-
} else {
return new Promise(res => {
this.onConnect.push(() => {
diff --git a/src/server/index.ts b/src/server/index.ts
index f9ca3de56..526cc6cce 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -54,6 +54,7 @@ import { BatchedArray, TimeUnit } from 'array-batcher';
import { ParsedPDF } from "./PdfTypes";
import { reject } from 'bluebird';
import { ExifData } from 'exif';
+import { Result } from '../client/northstar/model/idea/idea';
const download = (url: string, dest: fs.PathLike) => request.get(url).pipe(fs.createWriteStream(dest));
let youtubeApiKey: string;
@@ -320,16 +321,76 @@ app.get("/serializeDoc/:docId", async (req, res) => {
res.send({ docs, files: Array.from(files) });
});
-app.get(`${RouteStore.imageHierarchyExport}/:hierarchy`, async (req, res) => {
- const hierarchy = JSON.parse(req.params.hierarchy);
- Object.keys(hierarchy).map(key => {
- let value: any;
- if (value = hierarchy[key]) {
+export type Hierarchy = { [id: string]: string | Hierarchy };
+export type ZipMutator = (file: Archiver.Archiver) => void | Promise<void>;
- }
+app.get(`${RouteStore.imageHierarchyExport}/:docId`, async (req, res) => {
+ const id = req.params.docId;
+ const hierarchy: Hierarchy = {};
+ await targetedVisitorRecursive(id, hierarchy);
+ BuildAndDispatchZip(res, async zip => {
+ await hierarchyTraverserRecursive(zip, hierarchy);
});
});
+const BuildAndDispatchZip = async (res: Response, mutator: ZipMutator): Promise<void> => {
+ const zip = Archiver('zip');
+ zip.pipe(res);
+ await mutator(zip);
+ return zip.finalize();
+};
+
+const targetedVisitorRecursive = async (seedId: string, hierarchy: Hierarchy): Promise<void> => {
+ const local: Hierarchy = {};
+ const { title, data } = await getData(seedId);
+ const label = `${title} (${seedId})`;
+ if (Array.isArray(data)) {
+ hierarchy[label] = local;
+ await Promise.all(data.map(proxy => targetedVisitorRecursive(proxy.fieldId, local)));
+ } else {
+ hierarchy[label + path.extname(data)] = data;
+ }
+};
+
+const getData = async (seedId: string): Promise<{ data: string | any[], title: string }> => {
+ return new Promise<{ data: string | any[], title: string }>((resolve, reject) => {
+ Database.Instance.getDocument(seedId, async (result: any) => {
+ const { data, proto, title } = result.fields;
+ if (data) {
+ if (data.url) {
+ resolve({ data: data.url, title });
+ } else if (data.fields) {
+ resolve({ data: data.fields, title });
+ } else {
+ reject();
+ }
+ }
+ if (proto) {
+ getData(proto.fieldId).then(resolve, reject);
+ }
+ });
+ });
+};
+
+const hierarchyTraverserRecursive = async (file: Archiver.Archiver, hierarchy: Hierarchy, prefix = "Dash Export"): Promise<void> => {
+ for (const key of Object.keys(hierarchy)) {
+ const result = hierarchy[key];
+ if (typeof result === "string") {
+ let path: string;
+ let matches: RegExpExecArray | null;
+ if ((matches = /\:1050\/files\/(upload\_[\da-z]{32}.*)/g.exec(result)) !== null) {
+ path = `${__dirname}/public/files/${matches[1]}`;
+ } else {
+ const information = await DashUploadUtils.UploadImage(result);
+ path = information.mediaPaths[0];
+ }
+ file.file(path, { name: key, prefix });
+ } else {
+ await hierarchyTraverserRecursive(file, result, `${prefix}/${key}`);
+ }
+ }
+};
+
app.get("/downloadId/:docId", async (req, res) => {
res.set('Content-disposition', `attachment;`);
res.set('Content-Type', "application/zip");
diff --git a/src/server/test.txt b/src/server/test.txt
new file mode 100644
index 000000000..1c6f6d1f1
--- /dev/null
+++ b/src/server/test.txt
@@ -0,0 +1 @@
+"{"one":{"two":"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg","five":"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg","four":{"464d2fbb-8ad9-4bd1-833c-c04f6bb5450f":"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"},"three":"http://localhost:1050/files/upload_b94b0710bd7b72c0f201693597a2296a.jpg"}}" \ No newline at end of file