mirror of
https://github.com/penpot/penpot.git
synced 2025-03-17 18:21:23 -05:00
🎉 Add file thumbnails on dashboard.
This commit is contained in:
parent
ba2ffb9c0a
commit
ab4171b8ec
7 changed files with 86 additions and 70 deletions
|
@ -29,7 +29,8 @@
|
|||
"select distinct on (pf.id, pf.created_at)
|
||||
pf.*,
|
||||
p.name as project_name,
|
||||
array_agg(pp.id) over pages_w as pages
|
||||
array_agg(pp.id) over pages_w as pages,
|
||||
first_value(pp.data) over pages_w as data
|
||||
from project_files as pf
|
||||
inner join projects as p on (pf.project_id = p.id)
|
||||
inner join project_users as pu on (p.id = pu.project_id)
|
||||
|
@ -131,8 +132,9 @@
|
|||
;; --- Helpers
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [metadata pages] :as row}]
|
||||
[{:keys [metadata pages data] :as row}]
|
||||
(when row
|
||||
(cond-> row
|
||||
data (assoc :data (blob/decode data))
|
||||
pages (assoc :pages (vec (remove nil? pages)))
|
||||
metadata (assoc :metadata (blob/decode metadata)))))
|
||||
|
|
|
@ -7,18 +7,20 @@
|
|||
(ns uxbox.main.exports
|
||||
"The main logic for SVG export functionality."
|
||||
(:require
|
||||
[cljsjs.react.dom.server]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.store :as st]
|
||||
;; [uxbox.main.ui.shapes.circle :refer [circle-shape]]
|
||||
;; [uxbox.main.ui.shapes.group :refer [group-shape]]
|
||||
;; [uxbox.main.ui.shapes.icon :refer [icon-shape]]
|
||||
;; [uxbox.main.ui.shapes.image :refer [image-shape]]
|
||||
;; [uxbox.main.ui.shapes.path :refer [path-shape]]
|
||||
;; [uxbox.main.ui.shapes.rect :refer [rect-shape]]
|
||||
;; [uxbox.main.ui.shapes.text :refer [text-shape]]
|
||||
[uxbox.util.dom :as dom]))
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.ui.shapes.canvas :as canvas]
|
||||
[uxbox.main.ui.shapes.circle :as circle]
|
||||
[uxbox.main.ui.shapes.icon :as icon]
|
||||
[uxbox.main.ui.shapes.image :as image]
|
||||
[uxbox.main.ui.shapes.path :as path]
|
||||
[uxbox.main.ui.shapes.rect :as rect]
|
||||
[uxbox.main.ui.shapes.text :as text]))
|
||||
|
||||
;; (def ^:dynamic *state* st/state)
|
||||
(defn- render-html
|
||||
[component]
|
||||
(.renderToStaticMarkup js/ReactDOMServer component))
|
||||
|
||||
(mf/defc background
|
||||
[]
|
||||
|
@ -26,47 +28,52 @@
|
|||
{:x 0 :y 0
|
||||
:width "100%"
|
||||
:height "100%"
|
||||
:fill "white"}])
|
||||
:fill "#b1b2b5"}])
|
||||
|
||||
(declare shape-component)
|
||||
(declare shape-wrapper)
|
||||
(defn- calculate-width
|
||||
[data]
|
||||
(let [shapes (vals (:shapes-by-id data))
|
||||
shape (geom/shapes->rect-shape shapes)]
|
||||
{:width (+ (:x shape) (:width shape) 100)
|
||||
:height (+ (:y shape) (:height shape) 100)}))
|
||||
|
||||
(defn- make-shape-element
|
||||
[state shape]
|
||||
#_(mf/html
|
||||
(case (:type shape)
|
||||
;; :text [:& text-shape {:shape shape}]
|
||||
:icon [:& icon-shape {:shape shape}]
|
||||
:rect [:& rect-shape {:shape shape}]
|
||||
:path [:& path-shape {:shape shape}]
|
||||
:circle [:& circle-shape {:shape shape}]
|
||||
:image (let [image-id (:image shape)
|
||||
image (get-in state [:images image-id])]
|
||||
[:& image-shape {:shape shape :image image}]))))
|
||||
(mf/defc shape-wrapper
|
||||
[{:keys [shape] :as props}]
|
||||
(when (and shape (not (:hidden shape)))
|
||||
(case (:type shape)
|
||||
:canvas [:& rect/rect-shape {:shape shape}]
|
||||
:curve [:& path/path-shape {:shape shape}]
|
||||
:text [:& text/text-shape {:shape shape}]
|
||||
:icon [:& icon/icon-shape {:shape shape}]
|
||||
:rect [:& rect/rect-shape {:shape shape}]
|
||||
:path [:& path/path-shape {:shape shape}]
|
||||
:image [:& image/image-shape {:shape shape}]
|
||||
:circle [:& circle/circle-shape {:shape shape}])))
|
||||
|
||||
(mf/defc page-svg
|
||||
[{:keys [page state] :as props}]
|
||||
#_(let [{:keys [width height]} (:metadata page)]
|
||||
[{:keys [data] :as props}]
|
||||
(let [shapes-by-id (:shapes-by-id data)
|
||||
shapes (map #(get shapes-by-id %) (:shapes data []))
|
||||
canvas (map #(get shapes-by-id %) (:canvas data []))
|
||||
{:keys [width height]} (calculate-width data)]
|
||||
[:svg {:width width
|
||||
:height height
|
||||
:view-box (str "0 0 " width " " height)
|
||||
:version "1.1"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns "http://www.w3.org/2000/svg"}
|
||||
;; TODO: properly handle background
|
||||
#_(background)
|
||||
(for [sid (reverse (:shapes page))]
|
||||
(when-let [shape (get-in state [:shapes sid])]
|
||||
[:g {:key sid} (make-shape-element state shape)]))]))
|
||||
(background)
|
||||
[:*
|
||||
(for [item canvas]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])
|
||||
(for [item shapes]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])]]))
|
||||
|
||||
(defn render-page
|
||||
[id]
|
||||
#_(try
|
||||
(let [state (deref st/state)
|
||||
page (get-in state [:pages id])]
|
||||
(when (:shapes page)
|
||||
(dom/render-to-html
|
||||
(mf/element page-svg #js {:page page :state state}))))
|
||||
(defn render
|
||||
[{:keys [data] :as page}]
|
||||
(try
|
||||
(-> (mf/element page-svg #js {:data data})
|
||||
(render-html))
|
||||
(catch :default e
|
||||
(js/console.log e)
|
||||
nil)))
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.projects :as udp]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.exports :as exports]
|
||||
[uxbox.main.ui.modal :as modal]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.confirm :refer [confirm-dialog]]
|
||||
|
@ -66,10 +67,27 @@
|
|||
|
||||
;; --- Grid Item Thumbnail
|
||||
|
||||
;; (mf/defc grid-item-thumbnail
|
||||
;; [{:keys [file] :as props}]
|
||||
;; [:div.grid-item-th
|
||||
;; [:img.img-th {:src "/images/project-placeholder.svg"}]])
|
||||
|
||||
;; (defn use-thumbnail
|
||||
;; [file]
|
||||
|
||||
(mf/defc grid-item-thumbnail
|
||||
[{:keys [project] :as props}]
|
||||
[:div.grid-item-th
|
||||
[:img.img-th {:src "/images/project-placeholder.svg"}]])
|
||||
[{:keys [file] :as props}]
|
||||
(let [url (mf/use-memo
|
||||
{:fn #(let [content (exports/render file)
|
||||
blob (js/Blob. #js [content] #js {:type "image/svg+xml"})]
|
||||
(js/URL.createObjectURL blob))
|
||||
:deps (mf/deps (:id file))})]
|
||||
(mf/use-effect
|
||||
{:fn (fn []
|
||||
#(js/URL.revokeObjectURL url))
|
||||
:deps (mf/deps (:id file))})
|
||||
[:div.grid-item-th
|
||||
[:img.img-th {:src url}]]))
|
||||
|
||||
;; --- Grid Item
|
||||
|
||||
|
|
|
@ -32,16 +32,3 @@
|
|||
:image [:& image/image-wrapper {:shape shape}]
|
||||
:circle [:& circle/circle-wrapper {:shape shape}])))
|
||||
|
||||
(mf/defc canvas-and-shapes
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[{:keys [page] :as props}]
|
||||
(let [shapes-by-id (mf/deref refs/shapes-by-id)
|
||||
shapes (map #(get shapes-by-id %) (:shapes page []))
|
||||
canvas (map #(get shapes-by-id %) (:canvas page []))]
|
||||
[:*
|
||||
(for [item canvas]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])
|
||||
(for [item shapes]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])]))
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,14 @@
|
|||
[uxbox.util.color :as color]
|
||||
[uxbox.util.data :refer [classnames normalize-props]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.matrix :as gmt]))
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[cljsjs.react.dom.server]))
|
||||
|
||||
(defn- render-html
|
||||
[component]
|
||||
(.renderToStaticMarkup js/ReactDOMServer component))
|
||||
|
||||
|
||||
|
||||
;; TODO: this code need a good refactor
|
||||
|
||||
|
@ -150,7 +157,7 @@
|
|||
(fn [own]
|
||||
(let [shape (get-in own [::mf/props :shape])
|
||||
dom (mf/ref-node (::fobject own))
|
||||
html (dom/render-to-html (text-shape-html shape))]
|
||||
html (render-html (text-shape-html shape))]
|
||||
(set! (.-innerHTML dom) html))
|
||||
own)
|
||||
|
||||
|
@ -204,7 +211,7 @@
|
|||
(fn [own]
|
||||
(let [shape (::mf/props own)
|
||||
dom (mf/ref-node (::fobject own))
|
||||
html (dom/render-to-html (text-shape-html shape))]
|
||||
html (render-html (text-shape-html shape))]
|
||||
(set! (.-innerHTML dom) html))
|
||||
own)
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.data.lightbox :as udl]
|
||||
[uxbox.main.exports :as exports]
|
||||
;; [uxbox.main.exports :as exports]
|
||||
[uxbox.main.ui.lightbox :as lbx]
|
||||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.data :refer (read-string)]
|
||||
|
@ -44,7 +44,7 @@
|
|||
|
||||
(defn- download-page-svg
|
||||
[{:keys [name id] :as page}]
|
||||
(let [content (or (exports/render-page id) "")
|
||||
(let [content (or #_(exports/render-page id) "")
|
||||
blob (blob/create content "image/svg+xml")
|
||||
uri (blob/create-uri blob)
|
||||
link (.createElement js/document "a")
|
||||
|
@ -64,7 +64,7 @@
|
|||
(defn- generate-files
|
||||
[pages]
|
||||
(reduce (fn [acc {:keys [id name]}]
|
||||
(let [content (or (exports/render-page id) "")]
|
||||
(let [content (or #_(exports/render-page id) "")]
|
||||
(conj acc [(str (str/uslug name) ".svg")
|
||||
(blob/create content "image/svg+xml")])))
|
||||
[]
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.util.dom
|
||||
(:require [goog.dom :as dom]
|
||||
[cljsjs.react.dom.server]))
|
||||
(:require [goog.dom :as dom]))
|
||||
|
||||
;; --- Deprecated methods
|
||||
|
||||
|
@ -25,10 +24,6 @@
|
|||
|
||||
;; --- New methods
|
||||
|
||||
(defn render-to-html
|
||||
[component]
|
||||
(.renderToStaticMarkup js/ReactDOMServer component))
|
||||
|
||||
(defn get-element-by-class
|
||||
([classname]
|
||||
(dom/getElementByClass classname))
|
||||
|
|
Loading…
Add table
Reference in a new issue