0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 15:51:37 -05:00
penpot/frontend/src/uxbox/main/data/projects.cljs
2019-08-26 21:42:12 +02:00

207 lines
4.8 KiB
Clojure

;; 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 <niwi@niwi.nz>
(ns uxbox.main.data.projects
(:require [cljs.spec.alpha :as s]
[cuerdas.core :as str]
[beicon.core :as rx]
[potok.core :as ptk]
[uxbox.main.store :as st]
[uxbox.main.repo :as rp]
[uxbox.main.data.pages :as udp]
[uxbox.util.uuid :as uuid]
[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 inst?)
(s/def ::modified-at inst?)
(s/def ::project-entity
(s/keys ::req-un [::id
::name
::version
::user
::created-at
::modified-at]))
;; --- Helpers
(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)]}
(update-in state [:projects id] merge project))
(defn dissoc-project
"A reduce function for dissoc the project from the state map."
[state id]
(update state :projects dissoc id))
;; --- Initialize
(declare fetch-projects)
(declare projects-fetched?)
(defrecord Initialize []
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:dashboard :section] :dashboard/projects))
ptk/WatchEvent
(watch [_ state s]
(rx/of (fetch-projects))))
(defn initialize
[]
(Initialize.))
;; --- Projects Fetched
(defrecord ProjectsFetched [projects]
ptk/UpdateEvent
(update [_ state]
(reduce assoc-project state projects))
ptk/WatchEvent
(watch [_ state stream]
(->> (rx/from-coll (map :id projects))
(rx/map udp/fetch-pages))))
(defn projects-fetched
[projects]
{:pre [(us/valid? (s/every ::project-entity) projects)]}
(ProjectsFetched. projects))
(defn projects-fetched?
[v]
(instance? ProjectsFetched v))
;; --- Fetch Projects
(defrecord FetchProjects []
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/req :fetch/projects)
(rx/map :payload)
(rx/map projects-fetched))))
(defn fetch-projects
[]
(FetchProjects.))
;; --- Project Persisted
(defrecord ProjectPersisted [data]
ptk/UpdateEvent
(update [_ state]
(assoc-project state data)))
(defn project-persisted
[data]
{:pre [(map? data)]}
(ProjectPersisted. data))
;; --- Persist Project
(defrecord PersistProject [id]
ptk/WatchEvent
(watch [_ state stream]
(let [project (get-in state [:projects id])]
(->> (rp/req :update/project project)
(rx/map :payload)
(rx/map project-persisted)))))
(defn persist-project
[id]
{:pre [(uuid? id)]}
(PersistProject. id))
;; --- Rename Project
(defrecord RenameProject [id name]
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:projects id :name] name))
ptk/WatchEvent
(watch [_ state stream]
(rx/of (persist-project id))))
(defn rename-project
[id name]
{:pre [(uuid? id) (string? name)]}
(RenameProject. id name))
;; --- Delete Project (by id)
(defrecord DeleteProject [id]
ptk/WatchEvent
(watch [_ state s]
(letfn [(on-success [_]
#(dissoc-project % id))]
(->> (rp/req :delete/project id)
(rx/map on-success)))))
(defn delete-project
[id]
(if (map? id)
(DeleteProject. (:id id))
(DeleteProject. id)))
;; --- Create Project
(s/def ::create-project-params
(s/keys :req-un [::name ::udp/width ::udp/height]))
(defn create-project
[{:keys [name] :as params}]
{:pre [(us/valid? ::create-project-params params)]}
(reify
ptk/WatchEvent
(watch [this state stream]
(rx/merge
(->> (rp/req :create/project {:name name})
(rx/map :payload)
(rx/map (fn [{:keys [id] :as project}]
(udp/create-page (assoc params :project id)))))
(->> stream
(rx/filter udp/page-created?)
(rx/take 1)
(rx/map #(fetch-projects)))))))
;; --- Go To Project
(defn go-to
[id]
{:pre [(uuid? id)]}
(reify
ptk/WatchEvent
(watch [_ state stream]
(let [[page & rest-pages] (get-in state [:projects id :pages])]
(when page
(let [params {:project id :page page}]
(rx/of (rt/nav :workspace/page params))))))))
;; --- Update Opts (Filtering & Ordering)
(defrecord UpdateOpts [order filter]
ptk/UpdateEvent
(update [_ state]
(update-in state [:dashboard :projects] merge
(when order {:order order})
(when filter {:filter filter}))))
(defn update-opts
[& {:keys [order filter] :as opts}]
(UpdateOpts. order filter))