2021-05-28 12:59:43 +02:00
|
|
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
;;
|
|
|
|
;; Copyright (c) UXBOX Labs SL
|
|
|
|
|
|
|
|
(ns app.worker.import
|
2021-06-29 21:56:05 +02:00
|
|
|
(:refer-clojure :exclude [resolve])
|
2021-05-28 12:59:43 +02:00
|
|
|
(:require
|
|
|
|
[app.common.data :as d]
|
|
|
|
[app.common.file-builder :as fb]
|
2021-06-02 15:52:51 +02:00
|
|
|
[app.common.pages :as cp]
|
2021-06-29 21:56:05 +02:00
|
|
|
[app.common.text :as ct]
|
2021-06-02 15:52:51 +02:00
|
|
|
[app.common.uuid :as uuid]
|
|
|
|
[app.main.repo :as rp]
|
2021-06-23 15:51:06 +02:00
|
|
|
[app.util.dom :as dom]
|
2021-06-03 22:11:25 +02:00
|
|
|
[app.util.http :as http]
|
2021-06-02 15:52:51 +02:00
|
|
|
[app.util.import.parser :as cip]
|
2021-06-07 22:02:16 +02:00
|
|
|
[app.util.json :as json]
|
2021-05-28 12:59:43 +02:00
|
|
|
[app.util.zip :as uz]
|
|
|
|
[app.worker.impl :as impl]
|
|
|
|
[beicon.core :as rx]
|
2021-06-29 21:56:05 +02:00
|
|
|
[cuerdas.core :as str]
|
2021-07-05 18:14:49 +02:00
|
|
|
[tubax.core :as tubax]
|
|
|
|
[app.util.logging :as log]))
|
|
|
|
|
|
|
|
(log/set-level! :trace)
|
2021-05-28 12:59:43 +02:00
|
|
|
|
2021-06-02 15:52:51 +02:00
|
|
|
;; Upload changes batches size
|
|
|
|
(def change-batch-size 100)
|
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(defn get-file
|
|
|
|
"Resolves the file inside the context given its id and the data"
|
|
|
|
([context type]
|
|
|
|
(get-file context type nil nil))
|
|
|
|
|
|
|
|
([context type id]
|
|
|
|
(get-file context type id nil))
|
|
|
|
|
|
|
|
([context type id media]
|
|
|
|
(let [file-id (:file-id context)
|
|
|
|
path (case type
|
|
|
|
:manifest (str "manifest.json")
|
|
|
|
:page (str file-id "/" id ".svg")
|
|
|
|
:colors (str file-id "/colors.json")
|
|
|
|
:typographies (str file-id "/typographies.json")
|
|
|
|
:media-list (str file-id "/media.json")
|
|
|
|
:media (let [ext (dom/mtype->extension (:mtype media))]
|
|
|
|
(str file-id "/media/" id "." ext))
|
|
|
|
:components (str file-id "/components.svg"))
|
|
|
|
|
2021-07-05 18:14:49 +02:00
|
|
|
parse-svg? (and (not= type :media) (str/ends-with? path "svg"))
|
|
|
|
parse-json? (and (not= type :media) (str/ends-with? path "json"))
|
|
|
|
no-parse? (or (= type :media)
|
|
|
|
(not (or parse-svg? parse-json?)))
|
|
|
|
|
|
|
|
file-type (if (or parse-svg? parse-json?) "text" "blob")]
|
2021-06-29 21:56:05 +02:00
|
|
|
|
2021-07-05 18:14:49 +02:00
|
|
|
(log/debug :action "parsing" :path path)
|
2021-06-29 21:56:05 +02:00
|
|
|
|
|
|
|
(cond->> (uz/get-file (:zip context) path file-type)
|
2021-07-05 18:14:49 +02:00
|
|
|
parse-svg?
|
2021-06-29 21:56:05 +02:00
|
|
|
(rx/map (comp tubax/xml->clj :content))
|
|
|
|
|
2021-07-05 18:14:49 +02:00
|
|
|
parse-json?
|
2021-06-29 21:56:05 +02:00
|
|
|
(rx/map (comp json/decode :content))
|
|
|
|
|
2021-07-05 18:14:49 +02:00
|
|
|
no-parse?
|
2021-06-29 21:56:05 +02:00
|
|
|
(rx/map :content)))))
|
|
|
|
|
|
|
|
(defn resolve-factory
|
|
|
|
"Creates a wrapper around the atom to remap ids to new ids and keep
|
|
|
|
their relationship so they ids are coherent."
|
|
|
|
[]
|
|
|
|
(let [id-mapping-atom (atom {})
|
|
|
|
resolve
|
|
|
|
(fn [id-mapping id]
|
2021-07-01 17:47:32 +02:00
|
|
|
(assert (uuid? id) (str id))
|
2021-06-29 21:56:05 +02:00
|
|
|
(get id-mapping id))
|
|
|
|
|
|
|
|
set-id
|
|
|
|
(fn [id-mapping id]
|
2021-07-01 17:47:32 +02:00
|
|
|
(assert (uuid? id) (str id))
|
2021-06-29 21:56:05 +02:00
|
|
|
(cond-> id-mapping
|
|
|
|
(nil? (resolve id-mapping id))
|
|
|
|
(assoc id (uuid/next))))]
|
|
|
|
|
|
|
|
(fn [id]
|
2021-07-01 17:47:32 +02:00
|
|
|
(when (some? id)
|
|
|
|
(swap! id-mapping-atom set-id id)
|
|
|
|
(resolve @id-mapping-atom id)))))
|
2021-06-29 21:56:05 +02:00
|
|
|
|
2021-06-03 22:11:25 +02:00
|
|
|
(defn create-file
|
2021-06-02 15:52:51 +02:00
|
|
|
"Create a new file on the back-end"
|
2021-07-01 17:47:32 +02:00
|
|
|
[context]
|
2021-06-29 21:56:05 +02:00
|
|
|
(let [resolve (:resolve context)
|
2021-07-01 17:47:32 +02:00
|
|
|
file-id (resolve (:file-id context))]
|
2021-06-03 22:11:25 +02:00
|
|
|
(rp/mutation
|
2021-06-07 22:02:16 +02:00
|
|
|
:create-temp-file
|
2021-06-03 22:11:25 +02:00
|
|
|
{:id file-id
|
2021-06-29 21:56:05 +02:00
|
|
|
:name (:name context)
|
|
|
|
:is-shared (:shared context)
|
|
|
|
:project-id (:project-id context)
|
2021-06-03 22:11:25 +02:00
|
|
|
:data (-> cp/empty-file-data (assoc :id file-id))})))
|
2021-06-02 15:52:51 +02:00
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(defn link-file-libraries
|
|
|
|
"Create a new file on the back-end"
|
2021-07-01 17:47:32 +02:00
|
|
|
[context]
|
2021-06-29 21:56:05 +02:00
|
|
|
(let [resolve (:resolve context)
|
2021-07-01 17:47:32 +02:00
|
|
|
file-id (resolve (:file-id context))
|
2021-06-29 21:56:05 +02:00
|
|
|
libraries (->> context :libraries (mapv resolve))]
|
|
|
|
(->> (rx/from libraries)
|
|
|
|
(rx/map #(hash-map :file-id file-id :library-id %))
|
|
|
|
(rx/flat-map (partial rp/mutation :link-file-to-library)))))
|
|
|
|
|
2021-07-01 17:47:32 +02:00
|
|
|
(defn persist-file [file]
|
|
|
|
(rp/mutation :persist-temp-file {:id (:id file)}))
|
|
|
|
|
2021-06-02 15:52:51 +02:00
|
|
|
(defn send-changes
|
|
|
|
"Creates batches of changes to be sent to the backend"
|
2021-06-03 22:11:25 +02:00
|
|
|
[file]
|
|
|
|
(let [revn (atom (:revn file))
|
2021-06-02 15:52:51 +02:00
|
|
|
file-id (:id file)
|
|
|
|
session-id (uuid/next)
|
|
|
|
changes-batches
|
|
|
|
(->> (fb/generate-changes file)
|
|
|
|
(partition change-batch-size change-batch-size nil)
|
|
|
|
(mapv vec))]
|
|
|
|
|
2021-06-07 22:02:16 +02:00
|
|
|
(rx/concat
|
|
|
|
(->> (rx/from changes-batches)
|
|
|
|
(rx/mapcat
|
2021-06-10 15:45:03 +02:00
|
|
|
#(rp/mutation
|
|
|
|
:update-file
|
|
|
|
{:id file-id
|
|
|
|
:session-id session-id
|
|
|
|
:revn @revn
|
|
|
|
:changes %}))
|
|
|
|
(rx/map first)
|
2021-06-07 22:02:16 +02:00
|
|
|
(rx/tap #(reset! revn (:revn %))))
|
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(rp/mutation :persist-temp-file {:id file-id}))))
|
2021-06-02 15:52:51 +02:00
|
|
|
|
2021-06-03 22:11:25 +02:00
|
|
|
(defn upload-media-files
|
|
|
|
"Upload a image to the backend and returns its id"
|
|
|
|
[file-id name data-uri]
|
2021-07-05 18:14:49 +02:00
|
|
|
|
|
|
|
(log/debug :action "uploading" :file-id file-id :name name)
|
|
|
|
|
2021-06-03 22:11:25 +02:00
|
|
|
(->> (http/send!
|
|
|
|
{:uri data-uri
|
|
|
|
:response-type :blob
|
|
|
|
:method :get})
|
|
|
|
(rx/map :body)
|
|
|
|
(rx/map
|
|
|
|
(fn [blob]
|
|
|
|
{:name name
|
|
|
|
:file-id file-id
|
|
|
|
:content blob
|
|
|
|
:is-local true}))
|
|
|
|
(rx/flat-map #(rp/mutation! :upload-file-media-object %))))
|
2021-06-02 15:52:51 +02:00
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(defn resolve-text-content [node context]
|
|
|
|
(let [resolve (:resolve context)]
|
|
|
|
(->> node
|
|
|
|
(ct/transform-nodes
|
|
|
|
(fn [item]
|
2021-07-05 18:14:49 +02:00
|
|
|
(cond-> item
|
|
|
|
(uuid? (get item :fill-color-ref-id))
|
|
|
|
(d/update-when :fill-color-ref-id resolve)
|
|
|
|
|
|
|
|
(uuid? (get item :fill-color-ref-file))
|
|
|
|
(d/update-when :fill-color-ref-file resolve)
|
|
|
|
|
|
|
|
(uuid? (get item :typography-ref-id))
|
|
|
|
(d/update-when :typography-ref-id resolve)
|
|
|
|
|
|
|
|
(uuid? (get item :typography-ref-file))
|
|
|
|
(d/update-when :typography-ref-file resolve)))))))
|
2021-06-29 21:56:05 +02:00
|
|
|
|
|
|
|
(defn resolve-data-ids
|
|
|
|
[data type context]
|
|
|
|
(let [resolve (:resolve context)]
|
|
|
|
(-> data
|
|
|
|
(d/update-when :fill-color-ref-id resolve)
|
|
|
|
(d/update-when :fill-color-ref-file resolve)
|
|
|
|
(d/update-when :stroke-color-ref-id resolve)
|
|
|
|
(d/update-when :stroke-color-ref-file resolve)
|
|
|
|
(d/update-when :component-id resolve)
|
|
|
|
(d/update-when :component-file resolve)
|
|
|
|
(d/update-when :shape-ref resolve)
|
|
|
|
|
|
|
|
(cond-> (= type :text)
|
|
|
|
(d/update-when :content resolve-text-content context)))))
|
|
|
|
|
|
|
|
(defn process-import-node
|
|
|
|
[context file node]
|
2021-06-02 15:52:51 +02:00
|
|
|
|
2021-06-17 16:24:39 +02:00
|
|
|
(let [type (cip/get-type node)
|
|
|
|
close? (cip/close? node)]
|
2021-06-02 15:52:51 +02:00
|
|
|
(if close?
|
|
|
|
(case type
|
2021-06-17 16:24:39 +02:00
|
|
|
:frame (fb/close-artboard file)
|
|
|
|
:group (fb/close-group file)
|
|
|
|
:svg-raw (fb/close-svg-raw file)
|
|
|
|
#_default file)
|
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(let [resolve (:resolve context)
|
2021-06-17 16:24:39 +02:00
|
|
|
old-id (cip/get-id node)
|
2021-06-29 21:56:05 +02:00
|
|
|
interactions (->> (cip/parse-interactions node)
|
|
|
|
(mapv #(update % :destination resolve)))
|
|
|
|
|
|
|
|
data (-> (cip/parse-data type node)
|
|
|
|
(resolve-data-ids type context)
|
|
|
|
(assoc :id (resolve old-id)))
|
2021-06-17 16:24:39 +02:00
|
|
|
|
|
|
|
file (case type
|
2021-06-29 21:56:05 +02:00
|
|
|
:frame (fb/add-artboard file data)
|
|
|
|
:group (fb/add-group file data)
|
|
|
|
:rect (fb/create-rect file data)
|
|
|
|
:circle (fb/create-circle file data)
|
|
|
|
:path (fb/create-path file data)
|
|
|
|
:text (fb/create-text file data)
|
|
|
|
:image (fb/create-image file data)
|
2021-06-17 16:24:39 +02:00
|
|
|
:svg-raw (fb/create-svg-raw file data)
|
|
|
|
#_default file)]
|
|
|
|
|
|
|
|
(assert (some? old-id) "ID not found")
|
|
|
|
|
|
|
|
;; We store this data for post-processing after every shape has been
|
|
|
|
;; added
|
|
|
|
(cond-> file
|
2021-06-18 15:29:07 +02:00
|
|
|
(d/not-empty? interactions)
|
2021-06-29 21:56:05 +02:00
|
|
|
(assoc-in [:interactions (:id data)] interactions))))))
|
2021-06-17 16:24:39 +02:00
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(defn setup-interactions
|
2021-06-17 16:24:39 +02:00
|
|
|
[file]
|
2021-06-02 15:52:51 +02:00
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(letfn [(add-interactions
|
|
|
|
[file [id interactions]]
|
|
|
|
(->> interactions
|
|
|
|
(reduce #(fb/add-interaction %1 id %2) file)))
|
2021-06-10 15:45:03 +02:00
|
|
|
|
2021-06-17 16:24:39 +02:00
|
|
|
(process-interactions
|
|
|
|
[file]
|
2021-06-29 21:56:05 +02:00
|
|
|
(let [interactions (:interactions file)
|
|
|
|
file (dissoc file :interactions)]
|
|
|
|
(->> interactions (reduce add-interactions file))))]
|
2021-06-02 15:52:51 +02:00
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(-> file process-interactions)))
|
2021-06-03 22:11:25 +02:00
|
|
|
|
2021-06-23 15:51:06 +02:00
|
|
|
(defn resolve-media
|
2021-06-03 22:11:25 +02:00
|
|
|
[file-id node]
|
2021-06-14 17:04:14 +02:00
|
|
|
(if (and (not (cip/close? node))
|
2021-06-17 10:59:25 +02:00
|
|
|
(cip/has-image? node))
|
2021-06-03 22:11:25 +02:00
|
|
|
(let [name (cip/get-image-name node)
|
|
|
|
data-uri (cip/get-image-data node)]
|
|
|
|
(->> (upload-media-files file-id name data-uri)
|
2021-07-06 11:19:38 +02:00
|
|
|
(rx/catch #(do (.error js/console %)
|
|
|
|
(rx/of node)))
|
2021-06-03 22:11:25 +02:00
|
|
|
(rx/map
|
|
|
|
(fn [media]
|
|
|
|
(-> node
|
|
|
|
(assoc-in [:attrs :penpot:media-id] (:id media))
|
|
|
|
(assoc-in [:attrs :penpot:media-width] (:width media))
|
|
|
|
(assoc-in [:attrs :penpot:media-height] (:height media))
|
|
|
|
(assoc-in [:attrs :penpot:media-mtype] (:mtype media)))))))
|
|
|
|
|
|
|
|
;; If the node is not an image just return the node
|
2021-06-10 15:45:03 +02:00
|
|
|
(->> (rx/of node)
|
|
|
|
(rx/observe-on :async))))
|
2021-06-03 22:11:25 +02:00
|
|
|
|
2021-06-02 15:52:51 +02:00
|
|
|
(defn import-page
|
2021-06-29 21:56:05 +02:00
|
|
|
[context file [page-id page-name content]]
|
|
|
|
(let [nodes (->> content cip/node-seq)
|
|
|
|
file-id (:id file)
|
|
|
|
resolve (:resolve context)
|
|
|
|
page-data (-> (cip/parse-page-data content)
|
|
|
|
(assoc :name page-name)
|
|
|
|
(assoc :id (resolve page-id)))
|
|
|
|
file (-> file (fb/add-page page-data))]
|
|
|
|
(->> (rx/from nodes)
|
|
|
|
(rx/filter cip/shape?)
|
|
|
|
(rx/mapcat (partial resolve-media file-id))
|
|
|
|
(rx/reduce (partial process-import-node context) file)
|
|
|
|
(rx/map (comp fb/close-page setup-interactions)))))
|
|
|
|
|
|
|
|
(defn import-component [context file node]
|
|
|
|
(let [resolve (:resolve context)
|
|
|
|
content (cip/find-node node :g)
|
|
|
|
file-id (:id file)
|
|
|
|
old-id (cip/get-id node)
|
|
|
|
id (resolve old-id)
|
2021-07-05 18:14:49 +02:00
|
|
|
path (get-in node [:attrs :penpot:path] "")
|
2021-06-29 21:56:05 +02:00
|
|
|
data (-> (cip/parse-data :group content)
|
2021-07-05 18:14:49 +02:00
|
|
|
(assoc :path path)
|
2021-06-29 21:56:05 +02:00
|
|
|
(assoc :id id))
|
|
|
|
|
|
|
|
file (-> file (fb/start-component data))
|
|
|
|
children (cip/node-seq node)]
|
|
|
|
|
|
|
|
(->> (rx/from children)
|
|
|
|
(rx/filter cip/shape?)
|
|
|
|
(rx/skip 1)
|
2021-07-05 11:35:56 +02:00
|
|
|
(rx/skip-last 1)
|
2021-06-29 21:56:05 +02:00
|
|
|
(rx/mapcat (partial resolve-media file-id))
|
|
|
|
(rx/reduce (partial process-import-node context) file)
|
|
|
|
(rx/map fb/finish-component))))
|
|
|
|
|
|
|
|
(defn process-pages
|
|
|
|
[context file]
|
|
|
|
(let [index (:pages-index context)
|
|
|
|
get-page-data
|
|
|
|
(fn [page-id]
|
|
|
|
[page-id (get-in index [page-id :name])])
|
|
|
|
|
|
|
|
pages (->> (:pages context) (mapv get-page-data))]
|
|
|
|
|
2021-06-07 22:02:16 +02:00
|
|
|
(->> (rx/from pages)
|
2021-06-29 21:56:05 +02:00
|
|
|
(rx/mapcat
|
|
|
|
(fn [[page-id page-name]]
|
|
|
|
(->> (get-file context :page page-id)
|
|
|
|
(rx/map (fn [page-data] [page-id page-name page-data])))))
|
2021-07-05 11:35:56 +02:00
|
|
|
(rx/concat-reduce (partial import-page context) file))))
|
2021-06-23 15:51:06 +02:00
|
|
|
|
|
|
|
(defn process-library-colors
|
2021-06-29 21:56:05 +02:00
|
|
|
[context file]
|
|
|
|
(if (:has-colors context)
|
|
|
|
(let [resolve (:resolve context)
|
|
|
|
add-color
|
2021-06-23 15:51:06 +02:00
|
|
|
(fn [file [id color]]
|
2021-06-29 21:56:05 +02:00
|
|
|
(let [color (-> color
|
|
|
|
(d/update-in-when [:gradient :type] keyword)
|
|
|
|
(assoc :id (resolve id)))]
|
|
|
|
(fb/add-library-color file color)))]
|
|
|
|
(->> (get-file context :colors)
|
|
|
|
(rx/flat-map (comp d/kebab-keys cip/string->uuid))
|
2021-06-23 15:51:06 +02:00
|
|
|
(rx/reduce add-color file)))
|
|
|
|
|
|
|
|
(rx/of file)))
|
|
|
|
|
|
|
|
(defn process-library-typographies
|
2021-06-29 21:56:05 +02:00
|
|
|
[context file]
|
|
|
|
(if (:has-typographies context)
|
|
|
|
(let [resolve (:resolve context)]
|
|
|
|
(->> (get-file context :typographies)
|
|
|
|
(rx/flat-map (comp d/kebab-keys cip/string->uuid))
|
|
|
|
(rx/map (fn [[id typography]]
|
|
|
|
(-> typography
|
|
|
|
(d/kebab-keys)
|
|
|
|
(assoc :id (resolve id)))))
|
|
|
|
(rx/reduce fb/add-library-typography file)))
|
2021-06-23 15:51:06 +02:00
|
|
|
|
|
|
|
(rx/of file)))
|
|
|
|
|
|
|
|
(defn process-library-media
|
2021-06-29 21:56:05 +02:00
|
|
|
[context file]
|
|
|
|
(if (:has-media context)
|
|
|
|
(let [resolve (:resolve context)]
|
|
|
|
(->> (get-file context :media-list)
|
|
|
|
(rx/flat-map (comp d/kebab-keys cip/string->uuid))
|
2021-06-23 15:51:06 +02:00
|
|
|
(rx/flat-map
|
|
|
|
(fn [[id media]]
|
2021-06-29 21:56:05 +02:00
|
|
|
(let [media (assoc media :id (resolve id))]
|
|
|
|
(->> (get-file context :media id media)
|
|
|
|
(rx/map (fn [blob]
|
2021-06-23 15:51:06 +02:00
|
|
|
(let [content (.slice blob 0 (.-size blob) (:mtype media))]
|
|
|
|
{:name (:name media)
|
2021-06-29 21:56:05 +02:00
|
|
|
:id (:id media)
|
2021-06-23 15:51:06 +02:00
|
|
|
:file-id (:id file)
|
|
|
|
:content content
|
|
|
|
:is-local false})))
|
|
|
|
(rx/flat-map #(rp/mutation! :upload-file-media-object %))
|
2021-06-29 21:56:05 +02:00
|
|
|
(rx/map (constantly media))))))
|
|
|
|
(rx/reduce fb/add-library-media file)))
|
2021-06-23 15:51:06 +02:00
|
|
|
|
|
|
|
(rx/of file)))
|
|
|
|
|
|
|
|
(defn process-library-components
|
2021-06-29 21:56:05 +02:00
|
|
|
[context file]
|
|
|
|
(if (:has-components context)
|
|
|
|
(let [split-components
|
|
|
|
(fn [content] (->> (cip/node-seq content)
|
|
|
|
(filter #(= :symbol (:tag %)))))]
|
|
|
|
|
|
|
|
(->> (get-file context :components)
|
|
|
|
(rx/flat-map split-components)
|
2021-07-05 11:35:56 +02:00
|
|
|
(rx/concat-reduce (partial import-component context) file)))
|
2021-06-24 16:18:06 +02:00
|
|
|
(rx/of file)))
|
2021-06-23 15:51:06 +02:00
|
|
|
|
|
|
|
(defn process-file
|
2021-06-29 21:56:05 +02:00
|
|
|
[context file]
|
|
|
|
|
|
|
|
(->> (rx/of file)
|
|
|
|
(rx/flat-map (partial process-pages context))
|
|
|
|
(rx/flat-map (partial process-library-colors context))
|
|
|
|
(rx/flat-map (partial process-library-typographies context))
|
|
|
|
(rx/flat-map (partial process-library-media context))
|
|
|
|
(rx/flat-map (partial process-library-components context))
|
2021-07-01 17:47:32 +02:00
|
|
|
(rx/flat-map send-changes)))
|
2021-06-29 21:56:05 +02:00
|
|
|
|
2021-07-01 17:47:32 +02:00
|
|
|
(defn create-files
|
|
|
|
[context files]
|
2021-06-29 21:56:05 +02:00
|
|
|
|
2021-07-01 17:47:32 +02:00
|
|
|
(let [data (group-by :file-id files)]
|
|
|
|
(rx/concat
|
|
|
|
(->> (rx/from files)
|
|
|
|
(rx/map #(merge context %))
|
|
|
|
(rx/flat-map
|
|
|
|
(fn [context]
|
|
|
|
(->> (create-file context)
|
|
|
|
(rx/map #(vector % (first (get data (:file-id context)))))))))
|
|
|
|
|
|
|
|
(->> (rx/from files)
|
|
|
|
(rx/map #(merge context %))
|
|
|
|
(rx/flat-map link-file-libraries)
|
|
|
|
(rx/ignore)))))
|
|
|
|
|
|
|
|
(defmethod impl/handler :analyze-import
|
|
|
|
[{:keys [files]}]
|
|
|
|
|
|
|
|
(->> (rx/from files)
|
2021-06-29 21:56:05 +02:00
|
|
|
(rx/flat-map
|
2021-07-01 17:47:32 +02:00
|
|
|
(fn [uri]
|
|
|
|
(->> (rx/of uri)
|
|
|
|
(rx/flat-map uz/load-from-url)
|
|
|
|
(rx/flat-map #(get-file {:zip %} :manifest))
|
|
|
|
(rx/map (comp d/kebab-keys cip/string->uuid))
|
|
|
|
(rx/map #(hash-map :uri uri :data %))
|
|
|
|
(rx/catch #(rx/of {:uri uri :error (.-message %)})))))))
|
|
|
|
|
|
|
|
(defmethod impl/handler :import-files
|
2021-05-28 12:59:43 +02:00
|
|
|
[{:keys [project-id files]}]
|
|
|
|
|
2021-06-29 21:56:05 +02:00
|
|
|
(let [context {:project-id project-id
|
|
|
|
:resolve (resolve-factory)}]
|
2021-07-01 17:47:32 +02:00
|
|
|
(->> (create-files context files)
|
|
|
|
(rx/catch #(.error js/console "IMPORT ERROR" %))
|
|
|
|
(rx/flat-map
|
|
|
|
(fn [[file data]]
|
|
|
|
(->> (uz/load-from-url (:uri data))
|
|
|
|
(rx/map #(-> context (assoc :zip %) (merge data)))
|
|
|
|
(rx/flat-map #(process-file % file))
|
|
|
|
(rx/map
|
|
|
|
(fn [_]
|
|
|
|
{:status :import-success
|
|
|
|
:file-id (:file-id data)}))
|
|
|
|
|
|
|
|
(rx/catch
|
|
|
|
(fn [err]
|
|
|
|
(.error js/console "ERROR" (:file-id data) err)
|
|
|
|
(rx/of {:status :import-error
|
|
|
|
:file-id (:file-id data)
|
|
|
|
:error (.-message err)
|
|
|
|
:error-data (clj->js (.-data err))})))))))))
|