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