diff --git a/src/uxbox/data/pages.cljs b/src/uxbox/data/pages.cljs new file mode 100644 index 000000000..9ab7381d0 --- /dev/null +++ b/src/uxbox/data/pages.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-2016 Andrey Antukh +;; Copyright (c) 2015-2016 Juan de la Cruz + +(ns uxbox.data.pages + (:require [cuerdas.core :as str] + [promesa.core :as p] + [beicon.core :as rx] + [uxbox.rstore :as rs] + [uxbox.router :as r] + [uxbox.repo :as rp] + [uxbox.locales :refer (tr)] + [uxbox.schema :as sc] + [uxbox.state :as st] + [uxbox.state.project :as stpr] + [uxbox.ui.messages :as uum] + [uxbox.util.datetime :as dt] + [uxbox.util.data :refer (without-keys)])) + +;; (def ^:static +update-page-metadata-schema+ +;; {:name [sc/required sc/string] +;; :width [sc/required sc/integer] +;; :height [sc/required sc/integer] +;; :layout [sc/required sc/string]}) + +;; --- Pages Fetched + +(defrecord PagesFetched [pages] + rs/UpdateEvent + (-apply-update [_ state] + (reduce stpr/assoc-page state pages))) + +(defn pages-fetched? + [v] + (instance? PagesFetched v)) + +;; --- Fetch Pages (by project id) + +(defrecord FetchPages [projectid] + rs/WatchEvent + (-apply-watch [_ state s] + (letfn [(on-loaded [{pages :payload}] + (->PagesFetched pages)) + (on-error [err] + (js/console.error err) + (rx/empty))] + (->> (rp/do :fetch/pages-by-project {:project projectid}) + (rx/map on-loaded) + (rx/catch on-error))))) + +(defn fetch-pages + [projectid] + (FetchPages. projectid)) + +;; --- Create Page + +(defrecord CreatePage [name width height project layout] + rs/WatchEvent + (-apply-watch [this state s] + (letfn [(on-created [{page :payload}] + #(stpr/assoc-page % page)) + (on-failed [page] + (uum/error (tr "errors.auth")) + (rx/empty))] + (let [params (-> (into {} this) + (assoc :data {}))] + (->> (rp/do :create/page params) + (rx/map on-created) + (rx/catch on-failed)))))) + +(def ^:static +create-page-schema+ + {:name [sc/required sc/string] + :layout [sc/required sc/string] + :width [sc/required sc/integer] + :height [sc/required sc/integer] + :data [sc/required] + :project [sc/required sc/uuid]}) + +(defn create-page + [data] + (sc/validate! +create-page-schema+ data) + (map->CreatePage data)) + +;; --- Update Page + +(defrecord UpdatePage [id name width height layout] + rs/UpdateEvent + (-apply-update [_ state] + (letfn [(updater [page] + (merge page + (when width {:width width}) + (when height {:height height}) + (when name {:name name})))] + (update-in state [:pages-by-id id] updater))) + + rs/WatchEvent + (-apply-watch [this state s] + (letfn [(on-success [{page :payload}] + #(assoc-in % [:pages-by-id id :version] (:version page))) + (on-failure [e] + (uum/error (tr "errors.page-update")) + (rx/empty))] + (->> (rp/do :update/page (into {} this)) + (rx/map on-success) + (rx/catch on-failure))))) + +(def ^:static +update-page-schema+ + {:name [sc/required sc/string] + :width [sc/required sc/integer] + :height [sc/required sc/integer] + :data [sc/required] + :layout [sc/required sc/string]}) + +(defn update-page + [data] + (sc/validate! +update-page-schema+ data) + (map->UpdatePage data)) + +;; --- Delete Page (by id) + +(defrecord DeletePage [id] + rs/WatchEvent + (-apply-watch [_ state s] + (letfn [(on-success [_] + (rs/swap #(stpr/dissoc-page % id))) + (on-failure [e] + (println "ERROR" e) + (uum/error (tr "errors.delete-page")) + (rx/empty))] + (->> (rp/do :delete/page id) + (rx/map on-success) + (rx/catch on-failure))))) + +(defn delete-page + [id] + (DeletePage. id)) diff --git a/src/uxbox/data/projects.cljs b/src/uxbox/data/projects.cljs index 3aadec3d8..e29f68076 100644 --- a/src/uxbox/data/projects.cljs +++ b/src/uxbox/data/projects.cljs @@ -7,61 +7,25 @@ (ns uxbox.data.projects (:require [cuerdas.core :as str] - [promesa.core :as p] [beicon.core :as rx] [uxbox.rstore :as rs] [uxbox.router :as r] [uxbox.repo :as rp] [uxbox.locales :refer (tr)] [uxbox.schema :as sc] - [uxbox.state :as st] [uxbox.state.project :as stpr] - [uxbox.ui.messages :as uum] - [uxbox.util.datetime :as dt] - [uxbox.util.data :refer (without-keys)])) + [uxbox.data.pages :as udp] + [uxbox.ui.messages :as uum])) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Schemas -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; FIXME use only one ns for validators - -(def ^:static +project-schema+ - {:name [sc/required sc/string] - :width [sc/required sc/integer] - :height [sc/required sc/integer] - :layout [sc/required sc/string]}) - -(def ^:static +create-page-schema+ - {:name [sc/required sc/string] - :layout [sc/required sc/string] - :width [sc/required sc/integer] - :height [sc/required sc/integer] - :data [sc/required] - :project [sc/required sc/uuid]}) - -(def ^:static +update-page-schema+ - {:name [sc/required sc/string] - :width [sc/required sc/integer] - :height [sc/required sc/integer] - :data [sc/required] - :layout [sc/required sc/string]}) - -(def ^:static +update-page-metadata-schema+ - {:name [sc/required sc/string] - :width [sc/required sc/integer] - :height [sc/required sc/integer] - :layout [sc/required sc/string]}) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Helpers -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn sort-projects-by [ordering projs] (case ordering :name (sort-by :name projs) - :created (reverse (sort-by :created projs)) + :created (reverse (sort-by :created-at projs)) projs)) (defn contains-term? @@ -74,18 +38,22 @@ projs (filter #(contains-term? (:name %) term) projs))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Events -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defrecord LoadProjects [projects] +;; --- Projects Fetched + +(defrecord ProjectsFetched [projects] rs/UpdateEvent (-apply-update [_ state] (reduce stpr/assoc-project state projects))) -(defn load-projects +(defn projects-fetched [projects] - (LoadProjects. projects)) + (ProjectsFetched. projects)) + +;; --- Fetch Projects (defrecord FetchProjects [] rs/WatchEvent @@ -103,113 +71,36 @@ [] (FetchProjects.)) -(defrecord LoadPages [pages] - rs/UpdateEvent - (-apply-update [_ state] - (reduce stpr/assoc-page state pages))) - -(defn load-pages - [pages] - (LoadPages. pages)) - -(defrecord FetchPages [projectid] - rs/WatchEvent - (-apply-watch [_ state s] - (letfn [(on-loaded [{pages :payload}] - (load-pages pages)) - (on-error [err] - (js/console.error err) - (rx/empty))] - (->> (rp/do :fetch/pages-by-project {:project projectid}) - (rx/map on-loaded) - (rx/catch on-error))))) - -(defn fetch-pages - [projectid] - (FetchPages. projectid)) - -(defrecord CreatePage [name width height project layout] - rs/WatchEvent - (-apply-watch [this state s] - (letfn [(on-created [{page :payload}] - #(stpr/assoc-page % page)) - (on-failed [page] - (uum/error (tr "errors.auth")) - (rx/empty))] - (let [params (-> (into {} this) - (assoc :data {}))] - (->> (rp/do :create/page params) - (rx/map on-created) - (rx/catch on-failed)))))) - -(defn create-page - [data] - (sc/validate! +create-page-schema+ data) - (map->CreatePage data)) - -(defrecord UpdatePage [id name width height layout] - rs/UpdateEvent - (-apply-update [_ state] - (letfn [(updater [page] - (merge page - (when width {:width width}) - (when height {:height height}) - (when name {:name name})))] - (update-in state [:pages-by-id id] updater))) - - rs/WatchEvent - (-apply-watch [this state s] - (letfn [(on-success [{page :payload}] - #(assoc-in % [:pages-by-id id :version] (:version page))) - (on-failure [e] - (uum/error (tr "errors.page-update")) - (rx/empty))] - (->> (rp/do :update/page (into {} this)) - (rx/map on-success) - (rx/catch on-failure))))) - -(defn update-page - [data] - (sc/validate! +update-page-schema+ data) - (map->UpdatePage data)) - -(defrecord DeletePage [id] - rs/WatchEvent - (-apply-watch [_ state s] - (letfn [(on-success [_] - (rs/swap #(stpr/dissoc-page % id))) - (on-failure [e] - (println "ERROR" e) - (uum/error (tr "errors.delete-page")) - (rx/empty))] - (->> (rp/do :delete/page id) - (rx/map on-success) - (rx/catch on-failure))))) - -(defn delete-page - [id] - (DeletePage. id)) +;; --- Create Project (defrecord CreateProject [name width height layout] rs/WatchEvent (-apply-watch [this state s] (letfn [(on-success [project] (rx/of (rs/swap #(stpr/assoc-project % project)) - (create-page (assoc (into {} this) - :project (:id project) - :name "Page 1" - :data [])))) + (udp/create-page (assoc (into {} this) + :project (:id project) + :name "Page 1" + :data nil)))) (on-failure [err] (uum/error (tr "errors.create-project")))] (->> (rp/do :create/project {:name name}) (rx/mapcat on-success) (rx/catch on-failure))))) +(def ^:static +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 [{:keys [name width height layout] :as data}] (sc/validate! +project-schema+ data) (map->CreateProject data)) +;; --- Delete Project (by id) + (defrecord DeleteProject [id] rs/WatchEvent (-apply-watch [_ state s] @@ -227,6 +118,8 @@ (DeleteProject. (:id id)) (DeleteProject. id))) +;; --- Go To & Go To Page + (defrecord GoTo [projectid] rs/WatchEvent (-apply-watch [_ state s] @@ -236,8 +129,8 @@ :page-uuid pageid}] (r/navigate :workspace/page params)))] (rx/merge - (rx/of (fetch-pages projectid)) - (->> (rx/filter #(instance? LoadPages %) s) + (rx/of (udp/fetch-pages projectid)) + (->> (rx/filter udp/pages-fetched? s) (rx/take 1) (rx/map :pages) (rx/map navigate)))))) diff --git a/src/uxbox/ui/workspace.cljs b/src/uxbox/ui/workspace.cljs index 6159e074b..558c850bd 100644 --- a/src/uxbox/ui/workspace.cljs +++ b/src/uxbox/ui/workspace.cljs @@ -7,6 +7,7 @@ [uxbox.state :as st] [uxbox.data.workspace :as dw] [uxbox.data.projects :as dp] + [uxbox.data.pages :as udp] [uxbox.util.geom.point :as gpt] [uxbox.util.data :refer (classnames)] [uxbox.ui.core :as uuc] @@ -70,7 +71,7 @@ (let [[projectid pageid] (:rum/props own)] (rs/emit! (dw/initialize projectid pageid) (dp/fetch-projects) - (dp/fetch-pages projectid)) + (udp/fetch-pages projectid)) own)) (defn- workspace-did-mount diff --git a/src/uxbox/ui/workspace/sidebar/sitemap.cljs b/src/uxbox/ui/workspace/sidebar/sitemap.cljs index a2428fce3..892b6448b 100644 --- a/src/uxbox/ui/workspace/sidebar/sitemap.cljs +++ b/src/uxbox/ui/workspace/sidebar/sitemap.cljs @@ -17,6 +17,7 @@ [uxbox.shapes :as shapes] [uxbox.library :as library] [uxbox.data.projects :as dp] + [uxbox.data.pages :as udp] [uxbox.data.workspace :as dw] [uxbox.ui.dashboard.projects :refer (+layouts+)] [uxbox.ui.workspace.base :as wb] @@ -38,7 +39,7 @@ delete (fn [e] (dom/prevent-default e) (dom/stop-propagation e) - (rs/emit! (dp/delete-page (:id page)) + (rs/emit! (udp/delete-page (:id page)) (dp/go-to (:project page))))] (html [:li {:class (when active? "selected") @@ -112,7 +113,7 @@ (defn- page-form-lightbox-render [own local page] (let [edition? (:id page) - page (merge page @local {:data []}) + page (merge page @local {:data nil}) valid? (and (not (str/empty? (str/trim (:name page "")))) (pos? (:width page)) (pos? (:height page)))] @@ -134,8 +135,8 @@ (dom/prevent-default e) (lightbox/close!) (if edition? - (rs/emit! (dp/update-page page)) - (rs/emit! (dp/create-page page))))] + (rs/emit! (udp/update-page page)) + (rs/emit! (udp/create-page page))))] (html [:div.lightbox-body (if edition?