mirror of
https://github.com/penpot/penpot.git
synced 2025-03-10 14:51:37 -05:00
✨ Add images to libraries, and to files
This commit is contained in:
parent
49c57be84a
commit
af2c49dd16
8 changed files with 81 additions and 39 deletions
|
@ -172,7 +172,11 @@
|
||||||
opts (assoc imgs/thumbnail-options
|
opts (assoc imgs/thumbnail-options
|
||||||
:input {:mtype (:mtype info)
|
:input {:mtype (:mtype info)
|
||||||
:path path})
|
:path path})
|
||||||
thumb (imgs/persist-image-thumbnail-on-fs opts)]
|
thumb (if-not (= (:mtype info) "image/svg+xml")
|
||||||
|
(imgs/persist-image-thumbnail-on-fs opts)
|
||||||
|
(assoc info
|
||||||
|
:path path
|
||||||
|
:quality 0))]
|
||||||
|
|
||||||
(-> (db/insert! conn :file-image
|
(-> (db/insert! conn :file-image
|
||||||
{:file-id file-id
|
{:file-id file-id
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
;; --- Rename Library
|
;; --- Rename Library
|
||||||
|
|
||||||
(declare select-library-for-update)
|
(declare select-file-for-update)
|
||||||
|
|
||||||
(s/def ::rename-image-library
|
(s/def ::rename-image-library
|
||||||
(s/keys :req-un [::id ::profile-id ::name]))
|
(s/keys :req-un [::id ::profile-id ::name]))
|
||||||
|
@ -70,15 +70,26 @@
|
||||||
(sm/defmutation ::rename-image-library
|
(sm/defmutation ::rename-image-library
|
||||||
[{:keys [profile-id id name] :as params}]
|
[{:keys [profile-id id name] :as params}]
|
||||||
(db/with-atomic [conn db/pool]
|
(db/with-atomic [conn db/pool]
|
||||||
(let [lib (select-library-for-update conn id)]
|
(let [lib (select-file-for-update conn id)]
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
||||||
(db/update! conn :image-library
|
(db/update! conn :image-library
|
||||||
{:name name}
|
{:name name}
|
||||||
{:id id}))))
|
{:id id}))))
|
||||||
|
|
||||||
(defn- select-library-for-update
|
(def ^:private sql:select-file-for-update
|
||||||
|
"select file.*,
|
||||||
|
project.team_id as team_id
|
||||||
|
from file
|
||||||
|
inner join project on (project.id = file.project_id)
|
||||||
|
where file.id = ?
|
||||||
|
for update of file")
|
||||||
|
|
||||||
|
(defn- select-file-for-update
|
||||||
[conn id]
|
[conn id]
|
||||||
(db/get-by-id conn :image-library id {:for-update true}))
|
(let [row (db/exec-one! conn [sql:select-file-for-update id])]
|
||||||
|
(when-not row
|
||||||
|
(ex/raise :type :not-found))
|
||||||
|
row))
|
||||||
|
|
||||||
|
|
||||||
;; --- Delete Library
|
;; --- Delete Library
|
||||||
|
@ -91,7 +102,7 @@
|
||||||
(sm/defmutation ::delete-image-library
|
(sm/defmutation ::delete-image-library
|
||||||
[{:keys [id profile-id] :as params}]
|
[{:keys [id profile-id] :as params}]
|
||||||
(db/with-atomic [conn db/pool]
|
(db/with-atomic [conn db/pool]
|
||||||
(let [lib (select-library-for-update conn id)]
|
(let [lib (select-file-for-update conn id)]
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
||||||
|
|
||||||
;; Schedule object deletion
|
;; Schedule object deletion
|
||||||
|
@ -138,8 +149,8 @@
|
||||||
(sm/defmutation ::add-image-from-url
|
(sm/defmutation ::add-image-from-url
|
||||||
[{:keys [profile-id file-id url] :as params}]
|
[{:keys [profile-id file-id url] :as params}]
|
||||||
(db/with-atomic [conn db/pool]
|
(db/with-atomic [conn db/pool]
|
||||||
(let [lib (select-library-for-update conn file-id)]
|
(let [file (select-file-for-update conn file-id)]
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
||||||
(let [content (images/download-image url)
|
(let [content (images/download-image url)
|
||||||
params' (merge params {:content content
|
params' (merge params {:content content
|
||||||
:name (:filename content)})]
|
:name (:filename content)})]
|
||||||
|
@ -148,8 +159,8 @@
|
||||||
(sm/defmutation ::upload-image
|
(sm/defmutation ::upload-image
|
||||||
[{:keys [profile-id file-id] :as params}]
|
[{:keys [profile-id file-id] :as params}]
|
||||||
(db/with-atomic [conn db/pool]
|
(db/with-atomic [conn db/pool]
|
||||||
(let [lib (select-library-for-update conn file-id)]
|
(let [file (select-file-for-update conn file-id)]
|
||||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
(teams/check-edition-permissions! conn profile-id (:team-id file))
|
||||||
(create-image conn params))))
|
(create-image conn params))))
|
||||||
|
|
||||||
(defn create-image
|
(defn create-image
|
||||||
|
@ -240,8 +251,6 @@
|
||||||
(ex/raise :type :not-found))
|
(ex/raise :type :not-found))
|
||||||
row))
|
row))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Delete Image
|
;; --- Delete Image
|
||||||
|
|
||||||
(s/def ::delete-image
|
(s/def ::delete-image
|
||||||
|
|
|
@ -110,6 +110,7 @@
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,7 +353,7 @@
|
||||||
|
|
||||||
;; --- Create Image
|
;; --- Create Image
|
||||||
(declare create-images-result)
|
(declare create-images-result)
|
||||||
(def allowed-file-types #{"image/jpeg" "image/png" "image/webp"})
|
(def allowed-file-types #{"image/jpeg" "image/png" "image/webp" "image/svg+xml"})
|
||||||
(def max-file-size (* 5 1024 1024))
|
(def max-file-size (* 5 1024 1024))
|
||||||
|
|
||||||
;; TODO: unify with upload-image at main/data/workspace/persistence.cljs
|
;; TODO: unify with upload-image at main/data/workspace/persistence.cljs
|
||||||
|
@ -361,9 +361,9 @@
|
||||||
;; https://tree.taiga.io/project/uxboxproject/us/440
|
;; https://tree.taiga.io/project/uxboxproject/us/440
|
||||||
|
|
||||||
(defn create-images
|
(defn create-images
|
||||||
([library-id files] (create-images library-id files identity))
|
([file-id files] (create-images file-id files identity))
|
||||||
([library-id files on-uploaded]
|
([file-id files on-uploaded]
|
||||||
(us/verify (s/nilable ::us/uuid) library-id)
|
(us/verify (s/nilable ::us/uuid) file-id)
|
||||||
(us/verify fn? on-uploaded)
|
(us/verify fn? on-uploaded)
|
||||||
(ptk/reify ::create-images
|
(ptk/reify ::create-images
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
|
@ -397,7 +397,7 @@
|
||||||
prepare
|
prepare
|
||||||
(fn [file]
|
(fn [file]
|
||||||
{:name (.-name file)
|
{:name (.-name file)
|
||||||
:library-id library-id
|
:file-id file-id
|
||||||
:content file})]
|
:content file})]
|
||||||
|
|
||||||
(st/emit! (dm/show {:content (tr "image.loading")
|
(st/emit! (dm/show {:content (tr "image.loading")
|
||||||
|
@ -411,17 +411,17 @@
|
||||||
(rx/reduce conj [])
|
(rx/reduce conj [])
|
||||||
(rx/do on-success)
|
(rx/do on-success)
|
||||||
(rx/mapcat identity)
|
(rx/mapcat identity)
|
||||||
(rx/map (partial create-images-result library-id))
|
(rx/map (partial create-images-result file-id))
|
||||||
(rx/catch on-error)))))))
|
(rx/catch on-error)))))))
|
||||||
|
|
||||||
;; --- Image Created
|
;; --- Image Created
|
||||||
|
|
||||||
(defn create-images-result
|
(defn create-images-result
|
||||||
[library-id item]
|
[file-id image]
|
||||||
#_(us/verify ::image item)
|
#_(us/verify ::image image)
|
||||||
(ptk/reify ::create-images-result
|
(ptk/reify ::create-images-result
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(-> state
|
||||||
(update-in [:library-items :images library-id] #(into [item] %))))))
|
(assoc-in [:workspace-images (:id image)] image)))))
|
||||||
|
|
||||||
|
|
|
@ -448,7 +448,8 @@
|
||||||
(ptk/reify ::image-created
|
(ptk/reify ::image-created
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(update state :workspace-images assoc (:id item) item))))
|
state)))
|
||||||
|
;; (update state :workspace-images assoc (:id item) item))))
|
||||||
|
|
||||||
|
|
||||||
;; --- Delete image
|
;; --- Delete image
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
[uxbox.common.geom.point :as gpt]
|
[uxbox.common.geom.point :as gpt]
|
||||||
[uxbox.main.ui.icons :as i]
|
[uxbox.main.ui.icons :as i]
|
||||||
[uxbox.main.data.workspace :as dw]
|
[uxbox.main.data.workspace :as dw]
|
||||||
|
[uxbox.main.data.images :as di]
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.refs :as refs]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.ui.keyboard :as kbd]
|
[uxbox.main.ui.keyboard :as kbd]
|
||||||
|
@ -28,8 +29,9 @@
|
||||||
[uxbox.common.uuid :as uuid]
|
[uxbox.common.uuid :as uuid]
|
||||||
[uxbox.util.i18n :as i18n :refer [tr]]
|
[uxbox.util.i18n :as i18n :refer [tr]]
|
||||||
[uxbox.util.data :refer [classnames]]
|
[uxbox.util.data :refer [classnames]]
|
||||||
[uxbox.main.ui.components.tab-container :refer [tab-container tab-element]]
|
|
||||||
[uxbox.main.data.library :as dlib]
|
[uxbox.main.data.library :as dlib]
|
||||||
|
[uxbox.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||||
|
[uxbox.main.ui.components.file-uploader :refer [file-uploader]]
|
||||||
[uxbox.main.ui.components.context-menu :refer [context-menu]]))
|
[uxbox.main.ui.components.context-menu :refer [context-menu]]))
|
||||||
|
|
||||||
(defn matches-search
|
(defn matches-search
|
||||||
|
@ -47,32 +49,54 @@
|
||||||
:left nil
|
:left nil
|
||||||
:image-id nil})
|
:image-id nil})
|
||||||
|
|
||||||
add-graphic #(println "añadir gráfico")
|
file-input (mf/use-ref nil)
|
||||||
|
|
||||||
|
add-graphic
|
||||||
|
#(dom/click (mf/ref-val file-input))
|
||||||
|
|
||||||
delete-graphic
|
delete-graphic
|
||||||
#(st/emit! (dw/delete-file-image library-id (:image-id @state)))
|
#(st/emit! (dw/delete-file-image library-id (:image-id @state)))
|
||||||
|
|
||||||
on-context-menu (fn [image-id]
|
on-files-selected
|
||||||
(fn [event]
|
(fn [files]
|
||||||
(let [pos (dom/get-client-position event)
|
(st/emit! (di/create-images library-id files)))
|
||||||
top (:y pos)
|
|
||||||
left (- (:x pos) 20)]
|
on-context-menu
|
||||||
(dom/prevent-default event)
|
(fn [image-id]
|
||||||
(swap! state assoc :menu-open true
|
(fn [event]
|
||||||
:top top
|
(let [pos (dom/get-client-position event)
|
||||||
:left left
|
top (:y pos)
|
||||||
:image-id image-id))))]
|
left (- (:x pos) 20)]
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(swap! state assoc :menu-open true
|
||||||
|
:top top
|
||||||
|
:left left
|
||||||
|
:image-id image-id))))
|
||||||
|
|
||||||
|
on-drag-start
|
||||||
|
(fn [uri]
|
||||||
|
(fn [event]
|
||||||
|
(dnd/set-data! event "text/uri-list" uri)
|
||||||
|
(dnd/set-allowed-effect! event "move")))]
|
||||||
|
|
||||||
[:div.asset-group
|
[:div.asset-group
|
||||||
[:div.group-title
|
[:div.group-title
|
||||||
(tr "workspace.assets.graphics")
|
(tr "workspace.assets.graphics")
|
||||||
[:span (str "\u00A0(") (count images) ")"] ;; Unicode 00A0 is non-breaking space
|
[:span (str "\u00A0(") (count images) ")"] ;; Unicode 00A0 is non-breaking space
|
||||||
[:div.group-button {:on-click add-graphic} i/plus]]
|
[:div.group-button {:on-click add-graphic}
|
||||||
|
i/plus
|
||||||
|
[:& file-uploader {:accept "image/jpeg,image/png,image/webp,image/svg+xml"
|
||||||
|
:multi true
|
||||||
|
:input-ref file-input
|
||||||
|
:on-selected on-files-selected}]]]
|
||||||
[:div.group-grid
|
[:div.group-grid
|
||||||
(for [image (sort-by :name images)]
|
(for [image (sort-by :name images)]
|
||||||
[:div.grid-cell {:key (:id image)
|
[:div.grid-cell {:key (:id image)
|
||||||
:on-context-menu (on-context-menu (:id image))}
|
:draggable true
|
||||||
[:img {:src (:thumb-uri image)}]
|
:on-context-menu (on-context-menu (:id image))
|
||||||
|
:on-drag-start (on-drag-start (:uri image))}
|
||||||
|
[:img {:src (:thumb-uri image)
|
||||||
|
:draggable false}] ;; Also need to add css pointer-events: none
|
||||||
[:div.cell-name (:name image)]])
|
[:div.cell-name (:name image)]])
|
||||||
[:& context-menu
|
[:& context-menu
|
||||||
{:selectable false
|
{:selectable false
|
||||||
|
|
|
@ -113,7 +113,7 @@
|
||||||
(if (= section :icons)
|
(if (= section :icons)
|
||||||
[:svg {:view-box (->> item :metadata :view-box (str/join " "))
|
[:svg {:view-box (->> item :metadata :view-box (str/join " "))
|
||||||
:width (-> item :metadata :width)
|
:width (-> item :metadata :width)
|
||||||
:height (-> item :metadat :height)
|
:height (-> item :metadata :height)
|
||||||
:dangerouslySetInnerHTML {:__html (:content item)}}]
|
:dangerouslySetInnerHTML {:__html (:content item)}}]
|
||||||
[:img {:draggable false
|
[:img {:draggable false
|
||||||
:src (:thumb-uri item)}])
|
:src (:thumb-uri item)}])
|
||||||
|
|
|
@ -58,7 +58,10 @@
|
||||||
(set-data! e "uxbox/data" data))
|
(set-data! e "uxbox/data" data))
|
||||||
([e data-type data]
|
([e data-type data]
|
||||||
(let [dt (.-dataTransfer e)]
|
(let [dt (.-dataTransfer e)]
|
||||||
(.setData dt data-type (t/encode data))
|
(if (or (str/starts-with? data-type "application")
|
||||||
|
(str/starts-with? data-type "uxbox"))
|
||||||
|
(.setData dt data-type (t/encode data))
|
||||||
|
(.setData dt data-type data))
|
||||||
e)))
|
e)))
|
||||||
|
|
||||||
(defn set-drag-image!
|
(defn set-drag-image!
|
||||||
|
|
Loading…
Add table
Reference in a new issue