diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/Import & Export/ImageUtils.ts | 26 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 2 | ||||
-rw-r--r-- | src/server/database.ts | 7 | ||||
-rw-r--r-- | src/server/index.ts | 73 | ||||
-rw-r--r-- | src/server/test.txt | 1 |
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 |