mirror of
https://github.com/penpot/penpot.git
synced 2025-01-24 23:49:45 -05:00
♻️ Refactor import dialog on dashboard
This commit is contained in:
parent
afd373ffee
commit
c3f37fb8a3
2 changed files with 310 additions and 237 deletions
|
@ -38,17 +38,17 @@
|
|||
[project-id on-finish-import]
|
||||
(mf/use-fn
|
||||
(mf/deps project-id on-finish-import)
|
||||
(fn [files]
|
||||
(when files
|
||||
(let [files (->> files
|
||||
(mapv
|
||||
(fn [file]
|
||||
{:name (.-name file)
|
||||
:uri (wapi/create-uri file)})))]
|
||||
(fn [entries]
|
||||
(let [entries (->> entries
|
||||
(mapv (fn [file]
|
||||
{:name (.-name file)
|
||||
:uri (wapi/create-uri file)}))
|
||||
(not-empty))]
|
||||
(when entries
|
||||
(st/emit! (modal/show
|
||||
{:type :import
|
||||
:project-id project-id
|
||||
:files files
|
||||
:entries entries
|
||||
:on-finish-import on-finish-import})))))))
|
||||
|
||||
(mf/defc import-form
|
||||
|
@ -56,7 +56,6 @@
|
|||
::mf/props :obj}
|
||||
|
||||
[{:keys [project-id on-finish-import]} external-ref]
|
||||
|
||||
(let [on-file-selected (use-import-file project-id on-finish-import)]
|
||||
[:form.import-file {:aria-hidden "true"}
|
||||
[:& file-uploader {:accept ".penpot,.zip"
|
||||
|
@ -64,72 +63,70 @@
|
|||
:ref external-ref
|
||||
:on-selected on-file-selected}]]))
|
||||
|
||||
(defn update-file
|
||||
[files file-id new-name]
|
||||
(mapv
|
||||
(fn [file]
|
||||
(let [new-name (str/trim new-name)]
|
||||
(cond-> file
|
||||
(and (= (:file-id file) file-id)
|
||||
(not= "" new-name))
|
||||
(assoc :name new-name))))
|
||||
files))
|
||||
(defn- update-entry-name
|
||||
[entries file-id new-name]
|
||||
(mapv (fn [entry]
|
||||
(let [new-name (str/trim new-name)]
|
||||
(cond-> entry
|
||||
(and (= (:file-id entry) file-id)
|
||||
(not= "" new-name))
|
||||
(assoc :name new-name))))
|
||||
entries))
|
||||
|
||||
(defn remove-file
|
||||
[files file-id]
|
||||
(mapv
|
||||
(fn [file]
|
||||
(cond-> file
|
||||
(= (:file-id file) file-id)
|
||||
(assoc :deleted? true)))
|
||||
files))
|
||||
(defn- remove-entry
|
||||
[entries file-id]
|
||||
(mapv (fn [entry]
|
||||
(cond-> entry
|
||||
(= (:file-id entry) file-id)
|
||||
(assoc :deleted true)))
|
||||
entries))
|
||||
|
||||
(defn set-analyze-error
|
||||
[files uri error]
|
||||
(->> files
|
||||
(mapv (fn [file]
|
||||
(cond-> file
|
||||
(= uri (:uri file))
|
||||
(defn- update-with-analyze-error
|
||||
[entries uri error]
|
||||
(->> entries
|
||||
(mapv (fn [entry]
|
||||
(cond-> entry
|
||||
(= uri (:uri entry))
|
||||
(-> (assoc :status :analyze-error)
|
||||
(assoc :error error)))))))
|
||||
|
||||
(defn set-analyze-result
|
||||
[files uri type data]
|
||||
(let [existing-files? (into #{} (->> files (map :file-id) (filter some?)))
|
||||
replace-file
|
||||
(fn [file]
|
||||
(if (and (= uri (:uri file))
|
||||
(= (:status file) :analyzing))
|
||||
(->> (:files data)
|
||||
(remove (comp existing-files? first))
|
||||
(mapv (fn [[file-id file-data]]
|
||||
(-> file-data
|
||||
(assoc :file-id file-id
|
||||
:status :ready
|
||||
:uri uri
|
||||
:type type)))))
|
||||
[file]))]
|
||||
(into [] (mapcat replace-file) files)))
|
||||
(defn- update-with-analyze-result
|
||||
[entries uri type result]
|
||||
(let [existing-entries? (into #{} (keep :file-id) entries)
|
||||
replace-entry
|
||||
(fn [entry]
|
||||
(if (and (= uri (:uri entry))
|
||||
(= (:status entry) :analyzing))
|
||||
(->> (:files result)
|
||||
(remove (comp existing-entries? first))
|
||||
(map (fn [[file-id file-data]]
|
||||
(-> file-data
|
||||
(assoc :file-id file-id)
|
||||
(assoc :status :ready)
|
||||
(assoc :uri uri)
|
||||
(assoc :type type)))))
|
||||
[entry]))]
|
||||
(into [] (mapcat replace-entry) entries)))
|
||||
|
||||
(defn mark-files-importing
|
||||
[files]
|
||||
(->> files
|
||||
(defn- mark-entries-importing
|
||||
[entries]
|
||||
(->> entries
|
||||
(filter #(= :ready (:status %)))
|
||||
(mapv #(assoc % :status :importing))))
|
||||
|
||||
(defn update-status
|
||||
[files file-id status progress errors]
|
||||
(->> files
|
||||
(mapv (fn [file]
|
||||
(cond-> file
|
||||
(and (= file-id (:file-id file)) (not= status :import-progress))
|
||||
(assoc :status status)
|
||||
(defn- update-entry-status
|
||||
[entries file-id status progress errors]
|
||||
(mapv (fn [entry]
|
||||
(cond-> entry
|
||||
(and (= file-id (:file-id entry)) (not= status :import-progress))
|
||||
(assoc :status status)
|
||||
|
||||
(and (= file-id (:file-id file)) (= status :import-progress))
|
||||
(assoc :progress progress)
|
||||
(and (= file-id (:file-id entry)) (= status :import-progress))
|
||||
(assoc :progress progress)
|
||||
|
||||
(= file-id (:file-id file))
|
||||
(assoc :errors errors))))))
|
||||
(= file-id (:file-id entry))
|
||||
(assoc :errors errors)))
|
||||
entries))
|
||||
|
||||
(defn- parse-progress-message
|
||||
[message]
|
||||
|
@ -157,53 +154,116 @@
|
|||
|
||||
(str message)))
|
||||
|
||||
(defn- has-status-importing?
|
||||
[item]
|
||||
(= (:status item) :importing))
|
||||
|
||||
(defn- has-status-analyzing?
|
||||
[item]
|
||||
(= (:status item) :analyzing))
|
||||
|
||||
(defn- has-status-analyze-error?
|
||||
[item]
|
||||
(= (:status item) :analyzing))
|
||||
|
||||
(defn- has-status-success?
|
||||
[item]
|
||||
(and (= (:status item) :import-finish)
|
||||
(empty? (:errors item))))
|
||||
|
||||
(defn- has-status-error?
|
||||
[item]
|
||||
(and (= (:status item) :import-finish)
|
||||
(d/not-empty? (:errors item))))
|
||||
|
||||
(defn- has-status-ready?
|
||||
[item]
|
||||
(and (= :ready (:status item))
|
||||
(not (:deleted item))))
|
||||
|
||||
(defn- analyze-entries
|
||||
[state entries]
|
||||
(->> (uw/ask-many!
|
||||
{:cmd :analyze-import
|
||||
:files entries
|
||||
:features @features/features-ref})
|
||||
(rx/mapcat #(rx/delay emit-delay (rx/of %)))
|
||||
(rx/filter some?)
|
||||
(rx/subs!
|
||||
(fn [{:keys [uri data error type] :as msg}]
|
||||
(if (some? error)
|
||||
(swap! state update-with-analyze-error uri error)
|
||||
(swap! state update-with-analyze-result uri type data))))))
|
||||
|
||||
(defn- import-files!
|
||||
[state project-id entries]
|
||||
(st/emit! (ptk/data-event ::ev/event {::ev/name "import-files"
|
||||
:num-files (count entries)}))
|
||||
(->> (uw/ask-many!
|
||||
{:cmd :import-files
|
||||
:project-id project-id
|
||||
:files entries
|
||||
:features @features/features-ref})
|
||||
(rx/subs!
|
||||
(fn [{:keys [file-id status message errors] :as msg}]
|
||||
(swap! state update-entry-status file-id status message errors)))))
|
||||
|
||||
(mf/defc import-entry
|
||||
{::mf/props :obj}
|
||||
[{:keys [state file editing? can-be-deleted]}]
|
||||
(let [loading? (or (= :analyzing (:status file))
|
||||
(= :importing (:status file)))
|
||||
analyze-error? (= :analyze-error (:status file))
|
||||
import-finish? (= :import-finish (:status file))
|
||||
import-error? (= :import-error (:status file))
|
||||
import-warn? (d/not-empty? (:errors file))
|
||||
ready? (= :ready (:status file))
|
||||
is-shared? (:shared file)
|
||||
progress (:progress file)
|
||||
{::mf/props :obj
|
||||
::mf/memo true
|
||||
::mf/private true}
|
||||
[{:keys [entries entry edition can-be-deleted on-edit on-change on-delete]}]
|
||||
(let [status (:status entry)
|
||||
loading? (or (= :analyzing status)
|
||||
(= :importing status))
|
||||
analyze-error? (= :analyze-error status)
|
||||
import-finish? (= :import-finish status)
|
||||
import-error? (= :import-error status)
|
||||
import-warn? (d/not-empty? (:errors entry))
|
||||
ready? (= :ready status)
|
||||
is-shared? (:shared entry)
|
||||
progress (:progress entry)
|
||||
|
||||
handle-edit-key-press
|
||||
file-id (:file-id entry)
|
||||
editing? (and (some? file-id) (= edition file-id))
|
||||
|
||||
on-edit-key-press
|
||||
(mf/use-fn
|
||||
(fn [e]
|
||||
(when (or (kbd/enter? e) (kbd/esc? e))
|
||||
(dom/prevent-default e)
|
||||
(dom/stop-propagation e)
|
||||
(dom/blur! (dom/get-target e)))))
|
||||
(fn [event]
|
||||
(when (or (kbd/enter? event)
|
||||
(kbd/esc? event))
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(dom/blur! (dom/get-target event)))))
|
||||
|
||||
handle-edit-blur
|
||||
on-edit-blur
|
||||
(mf/use-fn
|
||||
(mf/deps file)
|
||||
(fn [e]
|
||||
(let [value (dom/get-target-val e)]
|
||||
(swap! state #(-> (assoc % :editing nil)
|
||||
(update :files update-file (:file-id file) value))))))
|
||||
(mf/deps file-id on-change)
|
||||
(fn [event]
|
||||
(let [value (dom/get-target-val event)]
|
||||
(on-change file-id value event))))
|
||||
|
||||
handle-edit-entry
|
||||
on-edit'
|
||||
(mf/use-fn
|
||||
(mf/deps file)
|
||||
(fn []
|
||||
(swap! state assoc :editing (:file-id file))))
|
||||
(mf/deps file-id on-change)
|
||||
(fn [event]
|
||||
(when (fn? on-edit)
|
||||
(on-edit file-id event))))
|
||||
|
||||
handle-remove-entry
|
||||
on-delete'
|
||||
(mf/use-fn
|
||||
(mf/deps file)
|
||||
(fn []
|
||||
(swap! state update :files remove-file (:file-id file))))]
|
||||
(mf/deps file-id on-delete)
|
||||
(fn [event]
|
||||
(when (fn? on-delete)
|
||||
(on-delete file-id event))))]
|
||||
|
||||
[:div {:class (stl/css-case :file-entry true
|
||||
:loading loading?
|
||||
:success (and import-finish? (not import-warn?) (not import-error?))
|
||||
:warning (and import-finish? import-warn? (not import-error?))
|
||||
:error (or import-error? analyze-error?)
|
||||
:editable (and ready? (not editing?)))}
|
||||
[:div {:class (stl/css-case
|
||||
:file-entry true
|
||||
:loading loading?
|
||||
:success (and import-finish? (not import-warn?) (not import-error?))
|
||||
:warning (and import-finish? import-warn? (not import-error?))
|
||||
:error (or import-error? analyze-error?)
|
||||
:editable (and ready? (not editing?)))}
|
||||
|
||||
[:div {:class (stl/css :file-name)}
|
||||
[:div {:class (stl/css-case :file-icon true
|
||||
|
@ -219,26 +279,28 @@
|
|||
[:div {:class (stl/css :file-name-edit)}
|
||||
[:input {:type "text"
|
||||
:auto-focus true
|
||||
:default-value (:name file)
|
||||
:on-key-press handle-edit-key-press
|
||||
:on-blur handle-edit-blur}]]
|
||||
:default-value (:name entry)
|
||||
:on-key-press on-edit-key-press
|
||||
:on-blur on-edit-blur}]]
|
||||
|
||||
[:div {:class (stl/css :file-name-label)}
|
||||
(:name file)
|
||||
(when is-shared?
|
||||
(:name entry)
|
||||
(when ^boolean is-shared?
|
||||
[:span {:class (stl/css :icon)}
|
||||
i/library-refactor])])
|
||||
|
||||
[:div {:class (stl/css :edit-entry-buttons)}
|
||||
(when (= "application/zip" (:type file))
|
||||
[:button {:on-click handle-edit-entry} i/curve-refactor])
|
||||
(when (and (= "application/zip" (:type entry))
|
||||
(= status :ready))
|
||||
[:button {:on-click on-edit'} i/curve-refactor])
|
||||
(when can-be-deleted
|
||||
[:button {:on-click handle-remove-entry} i/delete-refactor])]]
|
||||
[:button {:on-click on-delete'} i/delete-refactor])]]
|
||||
|
||||
(cond
|
||||
analyze-error?
|
||||
[:div {:class (stl/css :error-message)}
|
||||
(if (some? (:error file))
|
||||
(tr (:error file))
|
||||
(if (some? (:error entry))
|
||||
(tr (:error entry))
|
||||
(tr "dashboard.import.analyze-error"))]
|
||||
|
||||
import-error?
|
||||
|
@ -249,139 +311,143 @@
|
|||
[:div {:class (stl/css :progress-message)} (parse-progress-message progress)])
|
||||
|
||||
[:div {:class (stl/css :linked-libraries)}
|
||||
(for [library-id (:libraries file)]
|
||||
(let [library-data (->> @state :files (d/seek #(= library-id (:file-id %))))
|
||||
error? (or (:deleted? library-data) (:import-error library-data))]
|
||||
(for [library-id (:libraries entry)]
|
||||
(let [library-data (d/seek #(= library-id (:file-id %)) entries)
|
||||
error? (or (:deleted library-data)
|
||||
(:import-error library-data))]
|
||||
(when (some? library-data)
|
||||
[:div {:class (stl/css :linked-library)}
|
||||
[:div {:class (stl/css :linked-library)
|
||||
:key (dm/str library-id)}
|
||||
(:name library-data)
|
||||
[:span {:class (stl/css-case :linked-library-tag true
|
||||
:error error?)} i/detach-refactor]])))]]))
|
||||
[:span {:class (stl/css-case
|
||||
:linked-library-tag true
|
||||
:error error?)}
|
||||
i/detach-refactor]])))]]))
|
||||
|
||||
(mf/defc import-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :import
|
||||
::mf/props :obj}
|
||||
[{:keys [project-id files template on-finish-import]}]
|
||||
(let [state (mf/use-state
|
||||
{:status :analyzing
|
||||
:editing nil
|
||||
:importing-templates 0
|
||||
:files (->> files
|
||||
(mapv #(assoc % :status :analyzing)))})
|
||||
|
||||
analyze-import
|
||||
(mf/use-fn
|
||||
(fn [files]
|
||||
(->> (uw/ask-many!
|
||||
{:cmd :analyze-import
|
||||
:files files
|
||||
:features @features/features-ref})
|
||||
(rx/mapcat #(rx/delay emit-delay (rx/of %)))
|
||||
(rx/filter some?)
|
||||
(rx/subs!
|
||||
(fn [{:keys [uri data error type] :as msg}]
|
||||
(if (some? error)
|
||||
(swap! state update :files set-analyze-error uri error)
|
||||
(swap! state update :files set-analyze-result uri type data)))))))
|
||||
[{:keys [project-id entries template on-finish-import]}]
|
||||
|
||||
import-files
|
||||
(mf/use-fn
|
||||
(fn [project-id files]
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "import-files"
|
||||
:num-files (count files)}))
|
||||
(->> (uw/ask-many!
|
||||
{:cmd :import-files
|
||||
:project-id project-id
|
||||
:files files
|
||||
:features @features/features-ref})
|
||||
(rx/subs!
|
||||
(fn [{:keys [file-id status message errors] :as msg}]
|
||||
(swap! state update :files update-status file-id status message errors))))))
|
||||
(mf/with-effect []
|
||||
;; dispose uris when the component is umount
|
||||
(fn [] (run! wapi/revoke-uri (map :uri entries))))
|
||||
|
||||
handle-cancel
|
||||
(let [entries* (mf/use-state
|
||||
(fn [] (mapv #(assoc % :status :analyzing) entries)))
|
||||
entries (deref entries*)
|
||||
|
||||
status* (mf/use-state :analyzing)
|
||||
status (deref status*)
|
||||
|
||||
edition* (mf/use-state nil)
|
||||
edition (deref edition*)
|
||||
|
||||
on-template-cloned-success
|
||||
(mf/use-fn
|
||||
(mf/deps (:editing @state))
|
||||
(fn []
|
||||
(swap! status* (constantly :importing))
|
||||
;; (swap! state assoc :status :importing :importing-templates 0)
|
||||
(st/emit! (dd/fetch-recent-files))))
|
||||
|
||||
on-template-cloned-error
|
||||
(mf/use-fn
|
||||
(fn [cause]
|
||||
(swap! status* (constantly :error))
|
||||
;; (swap! state assoc :status :error :importing-templates 0)
|
||||
(errors/print-error! cause)
|
||||
(rx/of (modal/hide)
|
||||
(msg/error (tr "dashboard.libraries-and-templates.import-error")))))
|
||||
|
||||
continue-entries
|
||||
(mf/use-fn
|
||||
(mf/deps entries)
|
||||
(fn []
|
||||
(let [entries (filterv has-status-ready? entries)]
|
||||
(swap! status* (constantly :importing))
|
||||
(swap! entries* mark-entries-importing)
|
||||
(import-files! entries* project-id entries))))
|
||||
|
||||
continue-template
|
||||
(mf/use-fn
|
||||
(mf/deps on-template-cloned-success
|
||||
on-template-cloned-error
|
||||
template)
|
||||
(fn []
|
||||
(let [mdata {:on-success on-template-cloned-success
|
||||
:on-error on-template-cloned-error}
|
||||
params {:project-id project-id :template-id (:id template)}]
|
||||
(swap! status* (constantly :importing))
|
||||
(st/emit! (dd/clone-template (with-meta params mdata))))))
|
||||
|
||||
on-edit
|
||||
(mf/use-fn
|
||||
(fn [file-id _event]
|
||||
(swap! edition* (constantly file-id))))
|
||||
|
||||
on-entry-change
|
||||
(mf/use-fn
|
||||
(fn [file-id value]
|
||||
(swap! edition* (constantly nil))
|
||||
(swap! entries* update-entry-name file-id value)))
|
||||
|
||||
on-entry-delete
|
||||
(mf/use-fn
|
||||
(fn [file-id]
|
||||
(swap! entries* remove-entry file-id)))
|
||||
|
||||
on-cancel
|
||||
(mf/use-fn
|
||||
(mf/deps edition)
|
||||
(fn [event]
|
||||
(when (nil? (:editing @state))
|
||||
(when (nil? edition)
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (modal/hide)))))
|
||||
|
||||
on-template-cloned-success
|
||||
(fn []
|
||||
(swap! state assoc :status :importing :importing-templates 0)
|
||||
(st/emit! (dd/fetch-recent-files)))
|
||||
|
||||
on-template-cloned-error
|
||||
(fn [cause]
|
||||
(swap! state assoc :status :error :importing-templates 0)
|
||||
(errors/print-error! cause)
|
||||
(rx/of (modal/hide)
|
||||
(msg/error (tr "dashboard.libraries-and-templates.import-error"))))
|
||||
|
||||
continue-files
|
||||
(fn []
|
||||
(let [files (->> @state :files (filterv #(and (= :ready (:status %)) (not (:deleted? %)))))]
|
||||
(import-files project-id files))
|
||||
|
||||
(swap! state
|
||||
(fn [state]
|
||||
(-> state
|
||||
(assoc :status :importing)
|
||||
(update :files mark-files-importing)))))
|
||||
|
||||
continue-template
|
||||
(fn []
|
||||
(let [mdata {:on-success on-template-cloned-success
|
||||
:on-error on-template-cloned-error}
|
||||
params {:project-id project-id :template-id (:id template)}]
|
||||
(swap! state
|
||||
(fn [state]
|
||||
(-> state
|
||||
(assoc :status :importing :importing-templates 1))))
|
||||
(st/emit! (dd/clone-template (with-meta params mdata)))))
|
||||
|
||||
|
||||
handle-continue
|
||||
on-continue
|
||||
(mf/use-fn
|
||||
(mf/deps project-id (:files @state))
|
||||
(mf/deps template
|
||||
continue-template
|
||||
continue-entries)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(if (some? template)
|
||||
(continue-template)
|
||||
(continue-files))))
|
||||
(continue-entries))))
|
||||
|
||||
handle-accept
|
||||
on-accept
|
||||
(mf/use-fn
|
||||
(mf/deps on-finish-import)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (modal/hide))
|
||||
(when on-finish-import (on-finish-import))))
|
||||
(when (fn? on-finish-import)
|
||||
(on-finish-import))))
|
||||
|
||||
files (->> (:files @state) (filterv (comp not :deleted?)))
|
||||
entries (filterv (comp not :deleted) entries)
|
||||
num-importing (+ (count (filterv has-status-importing? entries))
|
||||
(if (some? template) 1 0))
|
||||
|
||||
num-importing (+
|
||||
(->> files (filter #(= (:status %) :importing)) count)
|
||||
(:importing-templates @state))
|
||||
success-num (if (some? template)
|
||||
1
|
||||
(count (filterv has-status-success? entries)))
|
||||
|
||||
warning-files (->> files (filter #(and (= (:status %) :import-finish) (d/not-empty? (:errors %)))) count)
|
||||
success-files (->> files (filter #(and (= (:status %) :import-finish) (empty? (:errors %)))) count)
|
||||
pending-analysis? (> (->> files (filter #(= (:status %) :analyzing)) count) 0)
|
||||
pending-import? (> num-importing 0)
|
||||
errors? (or (some has-status-error? entries)
|
||||
(zero? (count entries)))
|
||||
|
||||
valid-files? (or (some? template)
|
||||
(> (+ (->> files (filterv (fn [x] (not= (:status x) :analyze-error))) count)) 0))]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
(let [sub (analyze-import files)]
|
||||
#(rx/dispose! sub))))
|
||||
pending-analysis? (some has-status-analyzing? entries)
|
||||
pending-import? (pos? num-importing)
|
||||
valid-all-entries? (or (some? template)
|
||||
(not (some has-status-analyze-error? entries)))]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
;; dispose uris when the component is umount
|
||||
#(doseq [file files]
|
||||
(wapi/revoke-uri (:uri file)))))
|
||||
|
||||
;; Run analyze operation on component mount
|
||||
(mf/with-effect []
|
||||
(let [sub (analyze-entries entries* entries)]
|
||||
(partial rx/dispose! sub)))
|
||||
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
|
@ -389,52 +455,58 @@
|
|||
[:h2 {:class (stl/css :modal-title)} (tr "dashboard.import")]
|
||||
|
||||
[:button {:class (stl/css :modal-close-btn)
|
||||
:on-click handle-cancel} i/close-refactor]]
|
||||
:on-click on-cancel} i/close-refactor]]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
(when (and (= :analyzing status) errors?)
|
||||
[:& context-notification
|
||||
{:type :warning
|
||||
:content (tr "dashboard.import.import-warning")}])
|
||||
|
||||
(when (and (= :importing (:status @state)) (not pending-import?))
|
||||
(if (> warning-files 0)
|
||||
(when (and (= :importing status) (not ^boolean pending-import?))
|
||||
(cond
|
||||
errors?
|
||||
[:& context-notification
|
||||
{:type :warning
|
||||
:content (tr "dashboard.import.import-warning" warning-files success-files)}]
|
||||
:content (tr "dashboard.import.import-warning")}]
|
||||
|
||||
:else
|
||||
[:& context-notification
|
||||
{:type :success
|
||||
:content (tr "dashboard.import.import-message" (i18n/c (if (some? template) 1 success-files)))}]))
|
||||
:content (tr "dashboard.import.import-message" (i18n/c success-num))}]))
|
||||
|
||||
(for [file files]
|
||||
(let [editing? (and (some? (:file-id file))
|
||||
(= (:file-id file) (:editing @state)))]
|
||||
[:& import-entry {:state state
|
||||
:key (dm/str (:uri file))
|
||||
:file file
|
||||
:editing? editing?
|
||||
:can-be-deleted (> (count files) 1)}]))
|
||||
(for [entry entries]
|
||||
[:& import-entry {:edition edition
|
||||
:key (dm/str (:uri entry))
|
||||
:entry entry
|
||||
:entries entries
|
||||
:on-edit on-edit
|
||||
:on-change on-entry-change
|
||||
:on-delete on-entry-delete
|
||||
:can-be-deleted (> (count entries) 1)}])
|
||||
|
||||
(when (some? template)
|
||||
[:& import-entry {:state state
|
||||
:file (assoc template :status (if (= 1 (:importing-templates @state)) :importing :ready))
|
||||
:editing? false
|
||||
[:& import-entry {:entry (assoc template :status :ready)
|
||||
:can-be-deleted false}])]
|
||||
|
||||
[:div {:class (stl/css :modal-footer)}
|
||||
[:div {:class (stl/css :action-buttons)}
|
||||
(when (= :analyzing (:status @state))
|
||||
(when (= :analyzing status)
|
||||
[:input {:class (stl/css :cancel-button)
|
||||
:type "button"
|
||||
:value (tr "labels.cancel")
|
||||
:on-click handle-cancel}])
|
||||
:on-click on-cancel}])
|
||||
|
||||
(when (= :analyzing (:status @state))
|
||||
(when (and (= :analyzing status) (not errors?))
|
||||
[:input {:class (stl/css :accept-btn)
|
||||
:type "button"
|
||||
:value (tr "labels.continue")
|
||||
:disabled (or pending-analysis? (not valid-files?))
|
||||
:on-click handle-continue}])
|
||||
:disabled (or pending-analysis? (not valid-all-entries?))
|
||||
:on-click on-continue}])
|
||||
|
||||
(when (= :importing (:status @state))
|
||||
(when (and (= :importing status) (not errors?))
|
||||
[:input {:class (stl/css :accept-btn)
|
||||
:type "button"
|
||||
:value (tr "labels.accept")
|
||||
:disabled (or pending-import? (not valid-files?))
|
||||
:on-click handle-accept}])]]]]))
|
||||
:disabled (or pending-import? (not valid-all-entries?))
|
||||
:on-click on-accept}])]]]]))
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
grid-template-columns: 1fr;
|
||||
gap: $s-16;
|
||||
margin-bottom: $s-24;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
|
|
Loading…
Add table
Reference in a new issue