From ce5811b86b5f19227e0c4bb97f66d9f74380a37e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 11 Jan 2017 19:47:15 +0100 Subject: [PATCH] Many fixes on the project/page creation process. --- frontend/src/uxbox/main/constants.cljs | 30 ++++ frontend/src/uxbox/main/data/pages.cljs | 10 +- frontend/src/uxbox/main/data/projects.cljs | 67 ++++++--- frontend/src/uxbox/main/data/shapes.cljs | 10 +- .../src/uxbox/main/ui/dashboard/projects.cljs | 127 +--------------- .../ui/dashboard/projects_createlightbox.cljs | 139 ++++++++++++++++++ .../workspace/sidebar/sitemap_pageform.cljs | 11 +- frontend/src/uxbox/util/forms.cljs | 6 + 8 files changed, 236 insertions(+), 164 deletions(-) create mode 100644 frontend/src/uxbox/main/ui/dashboard/projects_createlightbox.cljs diff --git a/frontend/src/uxbox/main/constants.cljs b/frontend/src/uxbox/main/constants.cljs index e6a23e02f..37c3c605c 100644 --- a/frontend/src/uxbox/main/constants.cljs +++ b/frontend/src/uxbox/main/constants.cljs @@ -32,3 +32,33 @@ 0.63 0.66 0.69 0.73 0.77 0.81 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.21 1.27 1.33 1.40 1.47 1.54 1.62 1.70 1.78 1.87 1.96 2.06 2.16 2.27 2.38 2.50 2.62 2.75 2.88 3.00]) + +(def page-defaults + {:width 1366 + :height 768 + :layout "notebook"}) + +(def project-defaults + (merge {:name ""} page-defaults)) + +(def page-layouts + {"mobile" + {:name "Mobile" + :id "mobile" + :width 320 + :height 480} + "tablet" + {:name "Tablet" + :id "tablet" + :width 1024 + :height 768} + "notebook" + {:name "Notebook" + :id "notebook" + :width 1366 + :height 768} + "desktop" + {:name "Desktop" + :id "desktop" + :width 1920 + :height 1080}}) diff --git a/frontend/src/uxbox/main/data/pages.cljs b/frontend/src/uxbox/main/data/pages.cljs index 45b65fd95..36ae5955a 100644 --- a/frontend/src/uxbox/main/data/pages.cljs +++ b/frontend/src/uxbox/main/data/pages.cljs @@ -51,9 +51,11 @@ (s/def ::user uuid?) (s/def ::created-at dt/instant?) (s/def ::modified-at dt/instant?) -(s/def ::shapes (s/coll-of uuid? :kind vector?)) +(s/def ::shapes + (-> (s/coll-of uuid? :kind vector?) + (s/nilable))) -(s/def ::page +(s/def ::page-entity (s/keys :req-un [::id ::name ::project @@ -296,8 +298,8 @@ (defn update-page [id data] - {:pre [(uuid? id) - (us/valid? ::page data)]} + (println "update-page" data) + {:pre [(uuid? id) (us/valid? ::page-entity data)]} (UpdatePage. id data)) ;; --- Update Page Metadata diff --git a/frontend/src/uxbox/main/data/projects.cljs b/frontend/src/uxbox/main/data/projects.cljs index de2f466a6..f0210f73c 100644 --- a/frontend/src/uxbox/main/data/projects.cljs +++ b/frontend/src/uxbox/main/data/projects.cljs @@ -2,25 +2,43 @@ ;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; -;; Copyright (c) 2015-2016 Andrey Antukh +;; Copyright (c) 2015-2017 Andrey Antukh (ns uxbox.main.data.projects - (:require [cuerdas.core :as str] + (:require [cljs.spec :as s] + [cuerdas.core :as str] [beicon.core :as rx] + [potok.core :as ptk] [uxbox.store :as st] [uxbox.main.repo :as rp] [uxbox.main.data.pages :as udp] - [potok.core :as ptk] - [uxbox.util.router :as rt] - [uxbox.util.i18n :refer (tr)] - [uxbox.util.forms :as sc] - [uxbox.main.data.pages :as udp])) + [uxbox.util.spec :as us] + [uxbox.util.time :as dt] + [uxbox.util.router :as rt])) + +;; --- Specs + +(s/def ::id uuid?) +(s/def ::name string?) +(s/def ::version integer?) +(s/def ::user uuid?) +(s/def ::created-at dt/instant?) +(s/def ::modified-at dt/instant?) + +(s/def ::project-entity + (s/keys ::req-un [::id + ::name + ::version + ::user + ::created-at + ::modified-at])) ;; --- Helpers (defn assoc-project-page "Assoc to the state the project's embedded page." [state project] + {:pre [(us/valid? ::project-entity project)]} (let [page {:id (:page-id project) :name (:page-name project) :version (:page-version project) @@ -36,6 +54,7 @@ (defn assoc-project "A reduce function for assoc the project to the state map." [state {:keys [id] :as project}] + {:pre [(us/valid? ::project-entity project)]} (let [project (dissoc project :page-name :page-version :page-data :page-metadata @@ -76,6 +95,7 @@ (defn projects-fetched [projects] + {:pre [(us/valid? (s/every ::project-entity) projects)]} (ProjectsFetched. projects)) (defn projects-fetched? @@ -159,30 +179,29 @@ (defrecord CreateProject [name width height layout] ptk/WatchEvent (watch [this state s] - (letfn [(on-finish [{project :payload}] - (rx/of (fetch-projects))) - (on-success [{project :payload}] - (->> (rp/req :create/page - {:name name - :project (:id project) + (let [project-data {:name name} + page-data {:name "Page 0" :data {} :metadata {:width width :height height :layout layout - :order 0}}) - (rx/mapcat on-finish)))] + :order 0}}] (->> (rp/req :create/project {:name name}) - (rx/mapcat on-success))))) + (rx/map :payload) + (rx/mapcat (fn [{:keys [id] :as project}] + (rp/req :create/page (assoc page-data :project id)))) + (rx/map #(fetch-projects)))))) + +(s/def ::create-project-event + (s/keys :req-un [::name + ::udp/width + ::udp/height + ::udp/layout])) -(def ^:private create-project-schema - {:name [sc/required sc/string] - :width [sc/required sc/integer] - :height [sc/required sc/integer] - :layout [sc/required sc/string]}) (defn create-project - [params] - (-> (sc/validate! params create-project-schema) - (map->CreateProject))) + [data] + {:pre [(us/valid? ::create-project-event data)]} + (map->CreateProject data)) ;; --- Go To & Go To Page diff --git a/frontend/src/uxbox/main/data/shapes.cljs b/frontend/src/uxbox/main/data/shapes.cljs index d47850377..bbcaaf38e 100644 --- a/frontend/src/uxbox/main/data/shapes.cljs +++ b/frontend/src/uxbox/main/data/shapes.cljs @@ -25,6 +25,8 @@ [uxbox.util.uuid :as uuid] [uxbox.util.workers :as uw])) +;; --- Specs + (s/def ::fill-color us/color?) (s/def ::fill-opacity number?) (s/def ::line-height number?) @@ -90,6 +92,9 @@ (s/def ::rect-like-shape (s/keys :req-un [::x1 ::y1 ::x2 ::y2 ::type])) +(s/def ::direction #{:up :down :right :left}) +(s/def ::speed #{:std :fast}) + ;; --- Shapes CRUD (deftype AddShape [data] @@ -654,8 +659,6 @@ ;; --- Move Selected Layer -(s/def ::direction #{:up :down}) - (deftype MoveSelectedLayer [loc] udp/IPageUpdate ptk/UpdateEvent @@ -715,9 +718,6 @@ (rx/from-coll (map #(apply-temporal-displacement % displacement) selected)) (rx/from-coll (map apply-displacement selected)))))) -(s/def ::direction #{:up :down :right :left}) -(s/def ::speed #{:std :fast}) - (defn move-selected [direction speed] {:pre [(us/valid? ::direction direction) diff --git a/frontend/src/uxbox/main/ui/dashboard/projects.cljs b/frontend/src/uxbox/main/ui/dashboard/projects.cljs index a45d37c8e..460095313 100644 --- a/frontend/src/uxbox/main/ui/dashboard/projects.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/projects.cljs @@ -2,17 +2,19 @@ ;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; -;; Copyright (c) 2015-2016 Andrey Antukh -;; Copyright (c) 2015-2016 Juan de la Cruz +;; Copyright (c) 2015-2017 Andrey Antukh +;; Copyright (c) 2015-2017 Juan de la Cruz (ns uxbox.main.ui.dashboard.projects (:require [lentes.core :as l] [cuerdas.core :as str] [uxbox.store :as st] + [uxbox.main.constants :as c] [uxbox.main.data.projects :as udp] [uxbox.main.data.lightbox :as udl] [uxbox.main.ui.icons :as i] [uxbox.main.ui.dashboard.header :refer (header)] + [uxbox.main.ui.dashboard.projects-createlightbox] [uxbox.main.ui.lightbox :as lbx] [uxbox.main.ui.messages :as uum] [uxbox.main.ui.keyboard :as kbd] @@ -28,34 +30,6 @@ ;; --- Helpers & Constants -(def ^:private +project-defaults+ - {:name "" - :width 1920 - :height 1080 - :layout "desktop"}) - -(def +layouts+ - {"mobile" - {:name "Mobile" - :id "mobile" - :width 320 - :height 480} - "tablet" - {:name "Tablet" - :id "tablet" - :width 1024 - :height 768} - "notebook" - {:name "Notebook" - :id "notebook" - :width 1366 - :height 768} - "desktop" - {:name "Desktop" - :id "desktop" - :width 1920 - :height 1080}}) - (def +ordering-options+ {:name "ds.project-ordering.by-name" :created "ds.project-ordering.by-creation-date"}) @@ -273,96 +247,3 @@ (menu state projects-map) (grid state projects-map)]])) -;; --- Lightbox: Layout input - -(mx/defc layout-input - [local layout-id] - (let [layout (get-in +layouts+ [layout-id]) - id (:id layout) - name (:name layout) - width (:width layout) - height (:height layout)] - [:div - [:input - {:type "radio" - :key id - :id id - :name "project-layout" - :value name - :checked (when (= layout-id (:layout @local)) "checked") - :on-change #(swap! local merge {:layout layout-id - :width width - :height height})}] - [:label {:value (:name @local) :for id} name]])) - -;; --- Lightbox: Layout selector - -(mx/defc layout-selector - [local] - [:div.input-radio.radio-primary - (layout-input local "mobile") - (layout-input local "tablet") - (layout-input local "notebook") - (layout-input local "desktop")]) - -;; -- New Project Lightbox - -(mx/defcs new-project-lightbox - {:mixins [(mx/local +project-defaults+)]} - [own] - (let [local (:rum/local own) - name (:name @local) - width (:width @local) - height (:height @local)] - [:div.lightbox-body - [:h3 "New project"] - [:form {:on-submit (constantly nil)} - [:input#project-name.input-text - {:placeholder "New project name" - :type "text" - :value name - :auto-focus true - :on-change #(swap! local assoc :name (.-value (.-target %)))}] - [:div.project-size - [:div.input-element.pixels - [:span "Width"] - [:input#project-witdh.input-text - {:placeholder "Width" - :type "number" - :min 0 ;;TODO check this value - :max 666666 ;;TODO check this value - :value width - :on-change #(swap! local assoc :width (.-value (.-target %)))}]] - [:a.toggle-layout - {:href "#" - :on-click #(swap! local assoc :width width :height height)} - i/toggle] - [:div.input-element.pixels - [:span "Height"] - [:input#project-height.input-text - {:placeholder "Height" - :type "number" - :min 0 ;;TODO check this value - :max 666666 ;;TODO check this value - :value height - :on-change #(swap! local assoc :height (.-value (.-target %)))}]]] - ;; Layout selector - (layout-selector local) - ;; Submit - (when-not (empty? (str/trim name)) - [:input#project-btn.btn-primary - {:value "Go go go!" - :on-click #(do - (dom/prevent-default %) - (st/emit! (udp/create-project @local)) - (udl/close!)) - - :type "submit"}])] - [:a.close {:href "#" - :on-click #(do (dom/prevent-default %) - (udl/close!))} - i/close]])) - -(defmethod lbx/render-lightbox :new-project - [_] - (new-project-lightbox)) diff --git a/frontend/src/uxbox/main/ui/dashboard/projects_createlightbox.cljs b/frontend/src/uxbox/main/ui/dashboard/projects_createlightbox.cljs new file mode 100644 index 000000000..8b5f6786a --- /dev/null +++ b/frontend/src/uxbox/main/ui/dashboard/projects_createlightbox.cljs @@ -0,0 +1,139 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) 2015-2017 Andrey Antukh +;; Copyright (c) 2015-2017 Juan de la Cruz + +(ns uxbox.main.ui.dashboard.projects-createlightbox + (:require [lentes.core :as l] + [cuerdas.core :as str] + [potok.core :as ptk] + [uxbox.store :as st] + [uxbox.main.constants :as c] + [uxbox.main.exports :as exports] + [uxbox.main.data.projects :as udp] + [uxbox.main.data.lightbox :as udl] + [uxbox.main.ui.icons :as i] + [uxbox.main.ui.dashboard.header :refer (header)] + [uxbox.main.ui.lightbox :as lbx] + [uxbox.main.ui.messages :as uum] + [uxbox.main.ui.keyboard :as kbd] + [uxbox.util.i18n :as t :refer (tr)] + [uxbox.util.router :as r] + [uxbox.util.forms :as forms] + [uxbox.util.data :refer (read-string)] + [uxbox.util.dom :as dom] + [uxbox.util.blob :as blob] + [uxbox.util.mixins :as mx :include-macros true] + [uxbox.util.time :as dt])) + +(def form-data (forms/focus-data :create-project st/state)) +(def form-errors (forms/focus-errors :create-project st/state)) +(def set-value! (partial forms/set-value! :create-project)) +(def set-error! (partial forms/set-error! :create-project)) +(def clear! (partial forms/clear! :create-project)) + +(def ^:private create-project-form + {:name [forms/required forms/string] + :width [forms/required forms/integer] + :height [forms/required forms/integer] + :layout [forms/required forms/string]}) + +;; --- Lightbox: Layout input + +(mx/defc layout-input + [data layout-id] + (let [layout (get c/page-layouts layout-id)] + [:div + [:input {:type "radio" + :key layout-id + :id layout-id + :name "project-layout" + :value (:name layout) + :checked (when (= layout-id (:layout data)) "checked") + :on-change #(do + (set-value! :layout layout-id) + (set-value! :width (:width layout)) + (set-value! :height (:height layout)))}] + [:label {:value (:name layout) + :for layout-id} + (:name layout)]])) + +;; --- Lightbox: Layout selector + +(mx/defc layout-selector + [data] + [:div.input-radio.radio-primary + (layout-input data "mobile") + (layout-input data "tablet") + (layout-input data "notebook") + (layout-input data "desktop")]) + +;; -- New Project Lightbox + +(mx/defcs new-project-lightbox + {:mixins [mx/static mx/reactive + (forms/clear-mixin :create-project)]} + [own] + (let [data (merge c/project-defaults (mx/react form-data)) + errors (mx/react form-errors) + valid? (forms/valid? data create-project-form)] + (letfn [(on-submit [event] + (dom/prevent-default event) + (when valid? + (st/emit! (udp/create-project data)) + (udl/close!))) + (set-value [event attr] + (set-value! attr (dom/event->value event))) + (swap-size [] + (set-value! :width (:height data)) + (set-value! :height (:width data))) + (close [] + (udl/close!) + (clear!))] + [:div.lightbox-body + [:h3 "New project"] + [:form {:on-submit on-submit} + [:input#project-name.input-text + {:placeholder "New project name" + :type "text" + :value (:name data) + :auto-focus true + :on-change #(set-value % :name)}] + [:div.project-size + [:div.input-element.pixels + [:span "Width"] + [:input#project-witdh.input-text + {:placeholder "Width" + :type "number" + :min 0 ;;TODO check this value + :max 666666 ;;TODO check this value + :value (:width data) + :on-change #(set-value % :width)}]] + [:a.toggle-layout {:on-click swap-size} i/toggle] + [:div.input-element.pixels + [:span "Height"] + [:input#project-height.input-text + {:placeholder "Height" + :type "number" + :min 0 ;;TODO check this value + :max 666666 ;;TODO check this value + :value (:height data) + :on-change #(set-value % :height)}]]] + + ;; Layout selector + (layout-selector data) + + ;; Submit + [:input#project-btn.btn-primary + {:value "Go go go!" + :class (when-not valid? "btn-disabled") + :disabled (not valid?) + :type "submit"}]] + [:a.close {:on-clic #(udl/close!)} i/close]]))) + +(defmethod lbx/render-lightbox :new-project + [_] + (new-project-lightbox)) + diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap_pageform.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap_pageform.cljs index d0d65bde7..fa647dbbf 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap_pageform.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap_pageform.cljs @@ -9,10 +9,10 @@ (:require [lentes.core :as l] [cuerdas.core :as str] [uxbox.store :as st] + [uxbox.main.constants :as c] [uxbox.main.data.pages :as udp] [uxbox.main.data.workspace :as dw] [uxbox.main.data.lightbox :as udl] - [uxbox.main.ui.dashboard.projects :refer (+layouts+)] [uxbox.main.ui.icons :as i] [uxbox.main.ui.lightbox :as lbx] [uxbox.util.i18n :refer (tr)] @@ -28,11 +28,6 @@ ;; --- Lightbox -(def +page-defaults+ - {:width 1920 - :height 1080 - :layout :desktop}) - (def +page-form+ {:name [forms/required forms/string] :width [forms/required forms/number] @@ -41,7 +36,7 @@ (mx/defc layout-input [data id] - (let [{:keys [id name width height]} (get +layouts+ id)] + (let [{:keys [id name width height]} (get c/page-layouts id)] (letfn [(on-change [event] (set-value! :layout id) (set-value! :width width) @@ -58,7 +53,7 @@ (mx/defc page-form {:mixins [mx/static mx/reactive]} [{:keys [metadata id] :as page}] - (let [data (merge +page-defaults+ + (let [data (merge c/page-defaults (select-keys page [:name :id :project]) (select-keys metadata [:width :height :layout]) (mx/react form-data)) diff --git a/frontend/src/uxbox/util/forms.cljs b/frontend/src/uxbox/util/forms.cljs index e9a5ecba2..e5b2abaee 100644 --- a/frontend/src/uxbox/util/forms.cljs +++ b/frontend/src/uxbox/util/forms.cljs @@ -263,3 +263,9 @@ (fn [own] (clear! type) own)) + +(defn clear-mixin + [type] + {:will-unmount (fn [own] + (clear! type) + own)})