diff --git a/backend/src/uxbox/services/queries/project_files.clj b/backend/src/uxbox/services/queries/project_files.clj index 21510c820..c103cc87b 100644 --- a/backend/src/uxbox/services/queries/project_files.clj +++ b/backend/src/uxbox/services/queries/project_files.clj @@ -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))))) diff --git a/frontend/src/uxbox/main/exports.cljs b/frontend/src/uxbox/main/exports.cljs index f2cfdebd0..548f6b6cd 100644 --- a/frontend/src/uxbox/main/exports.cljs +++ b/frontend/src/uxbox/main/exports.cljs @@ -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))) diff --git a/frontend/src/uxbox/main/ui/dashboard/projects.cljs b/frontend/src/uxbox/main/ui/dashboard/projects.cljs index e63cc3fcc..f18cd23b3 100644 --- a/frontend/src/uxbox/main/ui/dashboard/projects.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/projects.cljs @@ -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 diff --git a/frontend/src/uxbox/main/ui/shapes.cljs b/frontend/src/uxbox/main/ui/shapes.cljs index b39457bdb..666acc9e3 100644 --- a/frontend/src/uxbox/main/ui/shapes.cljs +++ b/frontend/src/uxbox/main/ui/shapes.cljs @@ -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)}])])) - - diff --git a/frontend/src/uxbox/main/ui/shapes/text.cljs b/frontend/src/uxbox/main/ui/shapes/text.cljs index 2ce42d6dd..b55f88b7d 100644 --- a/frontend/src/uxbox/main/ui/shapes/text.cljs +++ b/frontend/src/uxbox/main/ui/shapes/text.cljs @@ -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) diff --git a/frontend/src/uxbox/main/ui/workspace/download.cljs b/frontend/src/uxbox/main/ui/workspace/download.cljs index 7d524c6fc..34cb3a50e 100644 --- a/frontend/src/uxbox/main/ui/workspace/download.cljs +++ b/frontend/src/uxbox/main/ui/workspace/download.cljs @@ -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")]))) [] diff --git a/frontend/src/uxbox/util/dom.cljs b/frontend/src/uxbox/util/dom.cljs index 26c20159a..ebf5f42e9 100644 --- a/frontend/src/uxbox/util/dom.cljs +++ b/frontend/src/uxbox/util/dom.cljs @@ -6,8 +6,7 @@ ;; Copyright (c) 2015-2016 Juan de la Cruz (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))