mirror of
https://github.com/penpot/penpot.git
synced 2025-03-14 16:51:18 -05:00
Improve history handling on frontend.
This commit is contained in:
parent
691c359985
commit
94677f2f7e
11 changed files with 322 additions and 281 deletions
|
@ -2,160 +2,207 @@
|
||||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
;; 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/.
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
|
||||||
(ns uxbox.main.data.history
|
(ns uxbox.main.data.history
|
||||||
(:require [cuerdas.core :as str]
|
(:require [beicon.core :as rx]
|
||||||
[beicon.core :as rx]
|
|
||||||
[lentes.core :as l]
|
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[uxbox.util.router :as r]
|
|
||||||
[uxbox.main.repo :as rp]
|
|
||||||
[uxbox.util.i18n :refer (tr)]
|
|
||||||
[uxbox.util.forms :as sc]
|
|
||||||
[uxbox.main.data.pages :as udp]
|
[uxbox.main.data.pages :as udp]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.repo :as rp]
|
||||||
[uxbox.util.time :as dt]
|
[uxbox.util.data :refer [replace-by-id
|
||||||
[uxbox.util.data :refer (without-keys
|
index-by]]))
|
||||||
replace-by-id
|
|
||||||
index-by)]))
|
|
||||||
|
|
||||||
;; --- Watch Page Changes
|
;; --- Initialize History State
|
||||||
|
|
||||||
(declare fetch-page-history)
|
(declare fetch-history)
|
||||||
(declare fetch-pinned-page-history)
|
(declare fetch-pinned-history)
|
||||||
|
|
||||||
|
(deftype Initialize [page-id]
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [data {:section :main
|
||||||
|
:selected nil
|
||||||
|
:pinned #{}
|
||||||
|
:items #{}
|
||||||
|
:byver {}}]
|
||||||
|
(assoc-in state [:workspace :history] data)))
|
||||||
|
|
||||||
(deftype WatchPageChanges [id]
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [stopper (->> stream
|
(let [page-id (get-in state [:workspace :page])
|
||||||
(rx/filter #(= % ::udp/stop-page-watcher))
|
stopper (->> stream
|
||||||
|
(rx/filter #(= % ::stop-changes-watcher))
|
||||||
(rx/take 1))]
|
(rx/take 1))]
|
||||||
(->> stream
|
(rx/merge
|
||||||
(rx/take-until stopper)
|
(->> stream
|
||||||
(rx/filter udp/page-persisted?)
|
(rx/take-until stopper)
|
||||||
(rx/debounce 500)
|
(rx/filter udp/page-persisted?)
|
||||||
(rx/flat-map #(rx/of (fetch-page-history id)
|
(rx/flat-map #(rx/of (fetch-history page-id)
|
||||||
(fetch-pinned-page-history id)))))))
|
(fetch-pinned-history page-id))))
|
||||||
|
(rx/of (fetch-history page-id)
|
||||||
|
(fetch-pinned-history page-id))))))
|
||||||
|
|
||||||
(defn watch-page-changes
|
(defn initialize
|
||||||
[id]
|
[page-id]
|
||||||
(WatchPageChanges. id))
|
{:pre [(uuid? page-id)]}
|
||||||
|
(Initialize. page-id))
|
||||||
|
|
||||||
;; --- Pinned Page History Fetched
|
;; --- Pinned Page History Fetched
|
||||||
|
|
||||||
(declare update-history-index)
|
(deftype PinnedPageHistoryFetched [items]
|
||||||
|
|
||||||
(defrecord PinnedPageHistoryFetched [history]
|
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(let [items-map (index-by items :version)
|
||||||
(assoc-in [:workspace :history :pinned-items] (mapv :version history))
|
items-set (into #{} items)]
|
||||||
(update-history-index history true))))
|
(update-in state [:workspace :history]
|
||||||
|
(fn [history]
|
||||||
|
(-> history
|
||||||
|
(assoc :pinned items-set)
|
||||||
|
(update :byver merge items-map)))))))
|
||||||
|
|
||||||
|
(defn pinned-page-history-fetched
|
||||||
|
[items]
|
||||||
|
(PinnedPageHistoryFetched. items))
|
||||||
|
|
||||||
;; --- Fetch Pinned Page History
|
;; --- Fetch Pinned Page History
|
||||||
|
|
||||||
(defrecord FetchPinnedPageHistory [id]
|
(deftype FetchPinnedPageHistory [id]
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
(letfn [(on-success [{history :payload}]
|
(let [params {:page id :pinned true}]
|
||||||
(->PinnedPageHistoryFetched (into [] history)))]
|
(->> (rp/req :fetch/page-history params)
|
||||||
(let [params {:page id :pinned true}]
|
(rx/map :payload)
|
||||||
(->> (rp/req :fetch/page-history params)
|
(rx/map pinned-page-history-fetched)))))
|
||||||
(rx/map on-success))))))
|
|
||||||
|
|
||||||
(defn fetch-pinned-page-history
|
(defn fetch-pinned-history
|
||||||
[id]
|
[id]
|
||||||
(->FetchPinnedPageHistory id))
|
{:pre [(uuid? id)]}
|
||||||
|
(FetchPinnedPageHistory. id))
|
||||||
|
|
||||||
;; --- Page History Fetched
|
;; --- Page History Fetched
|
||||||
|
|
||||||
(defrecord PageHistoryFetched [history append?]
|
(deftype PageHistoryFetched [items]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(letfn [(update-counters [state items]
|
(let [versions (into #{} (map :version) items)
|
||||||
(-> (assoc state :min-version (apply min items))
|
items-map (index-by items :version)
|
||||||
(assoc :max-version (apply max items))))
|
min-version (apply min versions)
|
||||||
|
max-version (apply max versions)]
|
||||||
|
(update-in state [:workspace :history]
|
||||||
|
(fn [history]
|
||||||
|
(-> history
|
||||||
|
(assoc :min-version min-version)
|
||||||
|
(assoc :max-version max-version)
|
||||||
|
(update :byver merge items-map)
|
||||||
|
(update :items #(reduce conj % items))))))))
|
||||||
|
|
||||||
(update-lists [state items]
|
;; TODO: add spec to history items
|
||||||
(if append?
|
|
||||||
(update state :items #(reduce conj %1 items))
|
|
||||||
(assoc state :items items)))]
|
|
||||||
|
|
||||||
(let [items (mapv :version history)
|
(defn page-history-fetched
|
||||||
hstate (-> (get-in state [:workspace :history] {})
|
[items]
|
||||||
(update-counters items)
|
(PageHistoryFetched. items))
|
||||||
(update-lists items))]
|
|
||||||
(-> state
|
|
||||||
(assoc-in [:workspace :history] hstate)
|
|
||||||
(update-history-index history append?))))))
|
|
||||||
|
|
||||||
;; --- Fetch Page History
|
;; --- Fetch Page History
|
||||||
|
|
||||||
(defrecord FetchPageHistory [id since max]
|
(deftype FetchPageHistory [page-id since max]
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
(letfn [(on-success [{history :payload}]
|
(let [params (merge {:page page-id
|
||||||
(let [history (into [] history)]
|
:max (or max 15)}
|
||||||
(->PageHistoryFetched history (not (nil? since)))))]
|
(when since
|
||||||
(let [params (merge
|
{:since since}))]
|
||||||
{:page id :max (or max 15)}
|
(->> (rp/req :fetch/page-history params)
|
||||||
(when since {:since since}))]
|
(rx/map :payload)
|
||||||
(->> (rp/req :fetch/page-history params)
|
(rx/map page-history-fetched)))))
|
||||||
(rx/map on-success))))))
|
|
||||||
|
|
||||||
(defn fetch-page-history
|
(defn fetch-history
|
||||||
([id]
|
([id]
|
||||||
(fetch-page-history id nil))
|
(fetch-history id nil))
|
||||||
([id params]
|
([id {:keys [since max]}]
|
||||||
(map->FetchPageHistory (assoc params :id id))))
|
{:pre [(uuid? id)]}
|
||||||
|
(FetchPageHistory. id since max)))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Context Aware Events
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; --- Select Section
|
||||||
|
|
||||||
|
(deftype SelectSection [section]
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:workspace :history :section] section)))
|
||||||
|
|
||||||
|
(defn select-section
|
||||||
|
[section]
|
||||||
|
{:pre [(keyword? section)]}
|
||||||
|
(SelectSection. section))
|
||||||
|
|
||||||
|
;; --- Load More
|
||||||
|
|
||||||
|
(deftype LoadMore []
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page-id (get-in state [:workspace :page])
|
||||||
|
since (get-in state [:workspace :history :min-version])]
|
||||||
|
(rx/of (fetch-history page-id {:since since})))))
|
||||||
|
|
||||||
|
(defn load-more
|
||||||
|
[]
|
||||||
|
(LoadMore.))
|
||||||
|
|
||||||
;; --- Select Page History
|
;; --- Select Page History
|
||||||
|
|
||||||
(defrecord SelectPageHistory [version]
|
(deftype SelectPageHistory [version]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [item (get-in state [:workspace :history :by-version version])
|
(let [history (get-in state [:workspace :history])
|
||||||
|
item (get-in history [:byver version])
|
||||||
page (get-in state [:pages (:page item)])
|
page (get-in state [:pages (:page item)])
|
||||||
page (assoc page
|
|
||||||
:history true
|
page (-> (get-in state [:pages (:page item)])
|
||||||
:data (:data item))]
|
(assoc :history true
|
||||||
|
:data (:data item)))]
|
||||||
(-> state
|
(-> state
|
||||||
(udp/assoc-page page)
|
(udp/assoc-page page)
|
||||||
(assoc-in [:workspace :history :selected] version)))))
|
(assoc-in [:workspace :history :selected] version)))))
|
||||||
|
|
||||||
(defn select-page-history
|
(defn select-page-history
|
||||||
[version]
|
[version]
|
||||||
|
{:pre [(integer? version)]}
|
||||||
(SelectPageHistory. version))
|
(SelectPageHistory. version))
|
||||||
|
|
||||||
;; --- Apply selected history
|
;; --- Apply Selected History
|
||||||
|
|
||||||
(defrecord ApplySelectedHistory [id]
|
(deftype ApplySelectedHistory []
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(let [page-id (get-in state [:workspace :page])]
|
||||||
(update-in [:pages id] dissoc :history)
|
(-> state
|
||||||
(assoc-in [:workspace :history :selected] nil)))
|
(update-in [:pages page-id] dissoc :history)
|
||||||
|
(assoc-in [:workspace :history :selected] nil))))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
(rx/of (udp/persist-page id))))
|
(let [page-id (get-in state [:workspace :page])]
|
||||||
|
(rx/of (udp/persist-page page-id)))))
|
||||||
|
|
||||||
(defn apply-selected-history
|
(defn apply-selected-history
|
||||||
[id]
|
[]
|
||||||
(ApplySelectedHistory. id))
|
(ApplySelectedHistory.))
|
||||||
|
|
||||||
;; --- Deselect Page History
|
;; --- Deselect Page History
|
||||||
|
|
||||||
(defrecord DeselectPageHistory [id ^:mutable noop]
|
(deftype DeselectPageHistory [^:mutable noop]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [selected (get-in state [:workspace :history :selected])]
|
(let [page-id (get-in state [:workspace :page])
|
||||||
|
selected (get-in state [:workspace :history :selected])]
|
||||||
(if (nil? selected)
|
(if (nil? selected)
|
||||||
(do
|
(do
|
||||||
(set! noop true)
|
(set! noop true)
|
||||||
state)
|
state)
|
||||||
(let [packed (get-in state [:packed-pages id])]
|
(let [packed (get-in state [:packed-pages page-id])]
|
||||||
(-> (udp/assoc-page state packed)
|
(-> (udp/assoc-page state packed)
|
||||||
(assoc-in [:workspace :history :deselecting] true)
|
(assoc-in [:workspace :history :deselecting] true)
|
||||||
(assoc-in [:workspace :history :selected] nil))))))
|
(assoc-in [:workspace :history :selected] nil))))))
|
||||||
|
@ -168,18 +215,35 @@
|
||||||
(rx/delay 500)))))
|
(rx/delay 500)))))
|
||||||
|
|
||||||
(defn deselect-page-history
|
(defn deselect-page-history
|
||||||
[id]
|
[]
|
||||||
{:pre [(uuid? id)]}
|
(DeselectPageHistory. false))
|
||||||
(DeselectPageHistory. id false))
|
|
||||||
|
;; --- Refresh Page History
|
||||||
|
|
||||||
|
(deftype RefreshHistory []
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page-id (get-in state [:workspace :page])
|
||||||
|
history (get-in state [:workspace :history])
|
||||||
|
maxitems (count (:items history))]
|
||||||
|
(rx/of (fetch-history page-id {:max maxitems})
|
||||||
|
(fetch-pinned-history page-id)))))
|
||||||
|
|
||||||
|
(defn refres-history
|
||||||
|
[]
|
||||||
|
(RefreshHistory.))
|
||||||
|
|
||||||
;; --- History Item Updated
|
;; --- History Item Updated
|
||||||
|
|
||||||
(defrecord HistoryItemUpdated [item]
|
(deftype HistoryItemUpdated [item]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(update-in state [:workspace :history]
|
||||||
(update-in [:workspace :history :items] replace-by-id item)
|
(fn [history]
|
||||||
(update-in [:workspace :history :pinned-items] replace-by-id item))))
|
(-> history
|
||||||
|
(update :items #(into #{} (replace-by-id item) %))
|
||||||
|
(update :pinned #(into #{} (replace-by-id item) %))
|
||||||
|
(assoc-in [:byver (:id item)] item))))))
|
||||||
|
|
||||||
(defn history-updated?
|
(defn history-updated?
|
||||||
[item]
|
[item]
|
||||||
|
@ -189,33 +253,18 @@
|
||||||
[item]
|
[item]
|
||||||
(HistoryItemUpdated. item))
|
(HistoryItemUpdated. item))
|
||||||
|
|
||||||
;; --- Refresh Page History
|
|
||||||
|
|
||||||
(defrecord RefreshPageHistory [id]
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state s]
|
|
||||||
(let [history (get-in state [:workspace :history])
|
|
||||||
maxitems (count (:items history))]
|
|
||||||
(rx/of (fetch-page-history id {:max maxitems})
|
|
||||||
(fetch-pinned-page-history id)))))
|
|
||||||
|
|
||||||
(defn refres-page-history
|
|
||||||
[id]
|
|
||||||
(RefreshPageHistory. id))
|
|
||||||
|
|
||||||
;; --- Update History Item
|
;; --- Update History Item
|
||||||
|
|
||||||
(defrecord UpdateHistoryItem [item]
|
(deftype UpdateHistoryItem [item]
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state stream]
|
||||||
(letfn [(on-success [{item :payload}]
|
(rx/concat
|
||||||
(->HistoryItemUpdated item))]
|
(->> (rp/req :update/page-history item)
|
||||||
(rx/merge
|
(rx/map :payload)
|
||||||
(->> (rp/req :update/page-history item)
|
(rx/map history-updated))
|
||||||
(rx/map on-success))
|
(->> (rx/filter history-updated? stream)
|
||||||
(->> (rx/filter history-updated? s)
|
(rx/take 1)
|
||||||
(rx/take 1)
|
(rx/map refres-history)))))
|
||||||
(rx/map #(refres-page-history (:page item))))))))
|
|
||||||
|
|
||||||
(defn update-history-item
|
(defn update-history-item
|
||||||
[item]
|
[item]
|
||||||
|
@ -223,7 +272,7 @@
|
||||||
|
|
||||||
;; --- Forward to Next Version
|
;; --- Forward to Next Version
|
||||||
|
|
||||||
(defrecord ForwardToNextVersion []
|
(deftype ForwardToNextVersion []
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
(let [workspace (:workspace state)
|
(let [workspace (:workspace state)
|
||||||
|
@ -237,7 +286,7 @@
|
||||||
(rx/of (select-page-history (inc version)))
|
(rx/of (select-page-history (inc version)))
|
||||||
|
|
||||||
(> (inc version) (:max-version history))
|
(> (inc version) (:max-version history))
|
||||||
(rx/of (deselect-page-history (:page workspace)))
|
(rx/of (deselect-page-history))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(rx/empty)))))
|
(rx/empty)))))
|
||||||
|
@ -248,7 +297,7 @@
|
||||||
|
|
||||||
;; --- Backwards to Previous Version
|
;; --- Backwards to Previous Version
|
||||||
|
|
||||||
(defrecord BackwardsToPreviousVersion []
|
(deftype BackwardsToPreviousVersion []
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
(let [workspace (:workspace state)
|
(let [workspace (:workspace state)
|
||||||
|
@ -265,7 +314,7 @@
|
||||||
(let [since (:min-version history)
|
(let [since (:min-version history)
|
||||||
page (:page workspace)
|
page (:page workspace)
|
||||||
params {:since since}]
|
params {:since since}]
|
||||||
(rx/of (fetch-page-history page params)
|
(rx/of (fetch-history page params)
|
||||||
(select-page-history (dec version)))))
|
(select-page-history (dec version)))))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
@ -274,13 +323,3 @@
|
||||||
(defn backwards-to-previous-version
|
(defn backwards-to-previous-version
|
||||||
[]
|
[]
|
||||||
(BackwardsToPreviousVersion.))
|
(BackwardsToPreviousVersion.))
|
||||||
|
|
||||||
;; --- Helpers
|
|
||||||
|
|
||||||
(defn- update-history-index
|
|
||||||
[state history append?]
|
|
||||||
(let [index (index-by history :version)]
|
|
||||||
(if append?
|
|
||||||
(update-in state [:workspace :history :by-version] merge index)
|
|
||||||
(assoc-in state [:workspace :history :by-version] index))))
|
|
||||||
|
|
||||||
|
|
|
@ -262,6 +262,9 @@
|
||||||
;; --- Page Persisted
|
;; --- Page Persisted
|
||||||
|
|
||||||
(deftype PagePersisted [data]
|
(deftype PagePersisted [data]
|
||||||
|
IDeref
|
||||||
|
(-deref [_] data)
|
||||||
|
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [{:keys [id version]} data]
|
(let [{:keys [id version]} data]
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
(:require [cljs.spec :as s]
|
(:require [cljs.spec :as s]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[lentes.core :as l]
|
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.constants :as c]
|
[uxbox.main.constants :as c]
|
||||||
[uxbox.main.lenses :as ul]
|
[uxbox.main.lenses :as ul]
|
||||||
|
@ -47,16 +46,17 @@
|
||||||
|
|
||||||
(declare initialize-alignment)
|
(declare initialize-alignment)
|
||||||
|
|
||||||
(defrecord InitializeWorkspace [project-id page-id]
|
(defrecord Initialize [project-id page-id]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [default-flags #{:sitemap :drawtools :layers :element-options :rules}]
|
(let [default-flags #{:sitemap :drawtools :layers :element-options :rules}
|
||||||
|
default-flags #{:document-history}]
|
||||||
(if (:workspace state)
|
(if (:workspace state)
|
||||||
(update state :workspace merge
|
(update state :workspace merge
|
||||||
{:project project-id
|
{:project project-id
|
||||||
:page page-id
|
:page page-id
|
||||||
:selected #{}
|
:selected #{}
|
||||||
:flags default-flags
|
;; :flags default-flags
|
||||||
:drawing nil
|
:drawing nil
|
||||||
:drawing-tool nil
|
:drawing-tool nil
|
||||||
:tooltip nil})
|
:tooltip nil})
|
||||||
|
@ -77,21 +77,15 @@
|
||||||
;; Activate loaded if page is not fetched.
|
;; Activate loaded if page is not fetched.
|
||||||
(when-not page (reset! st/loader true))
|
(when-not page (reset! st/loader true))
|
||||||
|
|
||||||
(rx/merge
|
(if page
|
||||||
(if page
|
(rx/of (initialize-alignment page-id))
|
||||||
(rx/of (initialize-alignment page-id))
|
(rx/merge
|
||||||
(rx/merge
|
(rx/of (udp/fetch-pages project-id))
|
||||||
(rx/of (udp/fetch-pages project-id))
|
(->> stream
|
||||||
(->> (rx/filter udp/pages-fetched? stream)
|
(rx/filter udp/pages-fetched?)
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/do #(reset! st/loader false))
|
(rx/do #(reset! st/loader false))
|
||||||
(rx/map #(initialize-alignment page-id)))))
|
(rx/map #(initialize-alignment page-id)))))))
|
||||||
|
|
||||||
;; Initial history loading
|
|
||||||
;; FIXME: move this to the history sidebar component
|
|
||||||
(rx/of
|
|
||||||
(udh/fetch-page-history page-id)
|
|
||||||
(udh/fetch-pinned-page-history page-id)))))
|
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ state stream]
|
(effect [_ state stream]
|
||||||
|
@ -104,7 +98,7 @@
|
||||||
[project page]
|
[project page]
|
||||||
{:pre [(uuid? project)
|
{:pre [(uuid? project)
|
||||||
(uuid? page)]}
|
(uuid? page)]}
|
||||||
(InitializeWorkspace. project page))
|
(Initialize. project page))
|
||||||
|
|
||||||
;; --- Workspace Tooltips
|
;; --- Workspace Tooltips
|
||||||
|
|
||||||
|
@ -306,8 +300,6 @@
|
||||||
|
|
||||||
;; --- Grid Alignment
|
;; --- Grid Alignment
|
||||||
|
|
||||||
(declare initialize-alignment?)
|
|
||||||
|
|
||||||
(defrecord InitializeAlignment [id]
|
(defrecord InitializeAlignment [id]
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
|
@ -327,6 +319,7 @@
|
||||||
|
|
||||||
(defn initialize-alignment
|
(defn initialize-alignment
|
||||||
[id]
|
[id]
|
||||||
|
{:pre [(uuid? id)]}
|
||||||
(InitializeAlignment. id))
|
(InitializeAlignment. id))
|
||||||
|
|
||||||
;; --- Update Metadata
|
;; --- Update Metadata
|
||||||
|
|
|
@ -9,21 +9,20 @@
|
||||||
(:require [lentes.core :as l]
|
(:require [lentes.core :as l]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[uxbox.main.constants :as c]
|
[uxbox.main.constants :as c]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]))
|
||||||
[uxbox.main.lenses :as ul]))
|
|
||||||
|
|
||||||
;; --- Helpers
|
;; --- Helpers
|
||||||
|
|
||||||
(defn resolve-project
|
(defn resolve-project
|
||||||
"Retrieve the current project."
|
"Retrieve the current project."
|
||||||
[state]
|
[state]
|
||||||
(let [id (l/focus ul/selected-project state)]
|
(let [project-id (get-in state [:workspace :project])]
|
||||||
(get-in state [:projects id])))
|
(get-in state [:projects project-id])))
|
||||||
|
|
||||||
(defn resolve-page
|
(defn resolve-page
|
||||||
[state]
|
[state]
|
||||||
(let [id (l/focus ul/selected-page state)]
|
(let [page-id (get-in state [:workspace :page])]
|
||||||
(get-in state [:pages id])))
|
(get-in state [:pages page-id])))
|
||||||
|
|
||||||
(defn- resolve-project-pages
|
(defn- resolve-project-pages
|
||||||
[state]
|
[state]
|
||||||
|
@ -34,13 +33,19 @@
|
||||||
(sort-by get-order))))
|
(sort-by get-order))))
|
||||||
|
|
||||||
(def workspace
|
(def workspace
|
||||||
(l/derive ul/workspace st/state))
|
(-> (l/key :workspace)
|
||||||
|
(l/derive st/state)))
|
||||||
|
|
||||||
(def selected-project
|
(def selected-project
|
||||||
"Ref to the current selected project."
|
"Ref to the current selected project."
|
||||||
(-> (l/lens resolve-project)
|
(-> (l/lens resolve-project)
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
||||||
|
(def selected-project-id
|
||||||
|
"Ref to the current selected project id."
|
||||||
|
(-> (l/key :project)
|
||||||
|
(l/derive selected-project)))
|
||||||
|
|
||||||
(def selected-project-pages
|
(def selected-project-pages
|
||||||
(-> (l/lens resolve-project-pages)
|
(-> (l/lens resolve-project-pages)
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
(ns uxbox.main.ui.workspace
|
(ns uxbox.main.ui.workspace
|
||||||
(:require [beicon.core :as rx]
|
(:require [beicon.core :as rx]
|
||||||
[potok.core :as ptk]
|
|
||||||
[lentes.core :as l]
|
[lentes.core :as l]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.constants :as c]
|
[uxbox.main.constants :as c]
|
||||||
|
@ -55,7 +54,7 @@
|
||||||
|
|
||||||
(st/emit! (udp/watch-page-changes pageid)
|
(st/emit! (udp/watch-page-changes pageid)
|
||||||
(udu/watch-page-changes pageid)
|
(udu/watch-page-changes pageid)
|
||||||
(udh/watch-page-changes pageid))
|
#_(udh/watch-page-changes pageid))
|
||||||
|
|
||||||
(assoc own ::sub sub)))
|
(assoc own ::sub sub)))
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@
|
||||||
::udp/stop-page-watcher
|
::udp/stop-page-watcher
|
||||||
(udp/watch-page-changes pageid)
|
(udp/watch-page-changes pageid)
|
||||||
(udu/watch-page-changes pageid)
|
(udu/watch-page-changes pageid)
|
||||||
(udh/watch-page-changes pageid)))
|
#_(udh/watch-page-changes pageid)))
|
||||||
state))
|
state))
|
||||||
|
|
||||||
(defn- on-scroll
|
(defn- on-scroll
|
||||||
|
@ -110,10 +109,8 @@
|
||||||
:mixins [mx/static
|
:mixins [mx/static
|
||||||
mx/reactive
|
mx/reactive
|
||||||
shortcuts-mixin]}
|
shortcuts-mixin]}
|
||||||
[own]
|
[own project-id page-id]
|
||||||
(let [flags (mx/react refs/flags)
|
(let [flags (mx/react refs/flags)
|
||||||
page (mx/react workspace-page-ref)
|
|
||||||
|
|
||||||
left-sidebar? (not (empty? (keep flags [:layers :sitemap
|
left-sidebar? (not (empty? (keep flags [:layers :sitemap
|
||||||
:document-history])))
|
:document-history])))
|
||||||
right-sidebar? (not (empty? (keep flags [:icons :drawtools
|
right-sidebar? (not (empty? (keep flags [:icons :drawtools
|
||||||
|
@ -133,8 +130,7 @@
|
||||||
:on-scroll on-scroll
|
:on-scroll on-scroll
|
||||||
:on-wheel (partial on-wheel own)}
|
:on-wheel (partial on-wheel own)}
|
||||||
|
|
||||||
|
(history-dialog)
|
||||||
(history-dialog page)
|
|
||||||
|
|
||||||
;; Rules
|
;; Rules
|
||||||
(when (contains? flags :rules)
|
(when (contains? flags :rules)
|
||||||
|
@ -151,6 +147,6 @@
|
||||||
|
|
||||||
;; Aside
|
;; Aside
|
||||||
(when left-sidebar?
|
(when left-sidebar?
|
||||||
(left-sidebar))
|
(left-sidebar flags page-id))
|
||||||
(when right-sidebar?
|
(when right-sidebar?
|
||||||
(right-sidebar))]]))
|
(right-sidebar flags page-id))]]))
|
||||||
|
|
|
@ -6,46 +6,40 @@
|
||||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||||
|
|
||||||
(ns uxbox.main.ui.workspace.sidebar
|
(ns uxbox.main.ui.workspace.sidebar
|
||||||
(:require [lentes.core :as l]
|
(:require [uxbox.main.refs :as refs]
|
||||||
[potok.core :as ptk]
|
[uxbox.main.ui.workspace.sidebar.options :refer [options-toolbox]]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.ui.workspace.sidebar.layers :refer [layers-toolbox]]
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.ui.workspace.sidebar.sitemap :refer [sitemap-toolbox]]
|
||||||
[uxbox.main.ui.workspace.sidebar.options :refer (options-toolbox)]
|
[uxbox.main.ui.workspace.sidebar.history :refer [history-toolbox]]
|
||||||
[uxbox.main.ui.workspace.sidebar.layers :refer (layers-toolbox)]
|
[uxbox.main.ui.workspace.sidebar.icons :refer [icons-toolbox]]
|
||||||
[uxbox.main.ui.workspace.sidebar.sitemap :refer (sitemap-toolbox)]
|
[uxbox.main.ui.workspace.sidebar.drawtools :refer [draw-toolbox]]
|
||||||
[uxbox.main.ui.workspace.sidebar.history :refer (history-toolbox)]
|
|
||||||
[uxbox.main.ui.workspace.sidebar.icons :refer (icons-toolbox)]
|
|
||||||
[uxbox.main.ui.workspace.sidebar.drawtools :refer (draw-toolbox)]
|
|
||||||
[uxbox.util.router :as r]
|
|
||||||
[uxbox.util.mixins :as mx :include-macros true]))
|
[uxbox.util.mixins :as mx :include-macros true]))
|
||||||
|
|
||||||
;; --- Left Sidebar (Component)
|
;; --- Left Sidebar (Component)
|
||||||
|
|
||||||
(mx/defc left-sidebar
|
(mx/defc left-sidebar
|
||||||
{:mixins [mx/reactive mx/static]}
|
{:mixins [mx/static]}
|
||||||
[]
|
[flags page-id]
|
||||||
(let [flags (mx/react refs/flags)]
|
[:aside#settings-bar.settings-bar.settings-bar-left
|
||||||
[:aside#settings-bar.settings-bar.settings-bar-left
|
[:div.settings-bar-inside
|
||||||
[:div.settings-bar-inside
|
(when (contains? flags :sitemap)
|
||||||
(when (contains? flags :sitemap)
|
(sitemap-toolbox page-id))
|
||||||
(sitemap-toolbox))
|
(when (contains? flags :document-history)
|
||||||
(when (contains? flags :document-history)
|
(history-toolbox page-id))
|
||||||
(history-toolbox))
|
(when (contains? flags :layers)
|
||||||
(when (contains? flags :layers)
|
(layers-toolbox))]])
|
||||||
(layers-toolbox))]]))
|
|
||||||
|
|
||||||
;; --- Right Sidebar (Component)
|
;; --- Right Sidebar (Component)
|
||||||
|
|
||||||
(mx/defc right-sidebar
|
(mx/defc right-sidebar
|
||||||
{:mixins [mx/reactive mx/static]}
|
{:mixins [mx/static]}
|
||||||
[]
|
[flags page-id]
|
||||||
(let [flags (mx/react refs/flags)]
|
[:aside#settings-bar.settings-bar
|
||||||
[:aside#settings-bar.settings-bar
|
[:div.settings-bar-inside
|
||||||
[:div.settings-bar-inside
|
(when (contains? flags :drawtools)
|
||||||
(when (contains? flags :drawtools)
|
(draw-toolbox flags))
|
||||||
(draw-toolbox))
|
(when (contains? flags :element-options)
|
||||||
(when (contains? flags :element-options)
|
(options-toolbox))
|
||||||
(options-toolbox))
|
(when (contains? flags :icons)
|
||||||
(when (contains? flags :icons)
|
(icons-toolbox))]])
|
||||||
(icons-toolbox))]]))
|
|
||||||
|
|
||||||
|
|
|
@ -94,9 +94,8 @@
|
||||||
|
|
||||||
(mx/defc draw-toolbox
|
(mx/defc draw-toolbox
|
||||||
{:mixins [mx/static mx/reactive]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
[]
|
[flags]
|
||||||
(let [drawing-tool (mx/react refs/selected-drawing-tool)
|
(let [drawing-tool (mx/react refs/selected-drawing-tool)
|
||||||
flags (mx/react refs/flags)
|
|
||||||
close #(st/emit! (udw/toggle-flag :drawtools))
|
close #(st/emit! (udw/toggle-flag :drawtools))
|
||||||
tools (->> (into [] +draw-tools+)
|
tools (->> (into [] +draw-tools+)
|
||||||
(sort-by (comp :priority second)))
|
(sort-by (comp :priority second)))
|
||||||
|
|
|
@ -6,28 +6,19 @@
|
||||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||||
|
|
||||||
(ns uxbox.main.ui.workspace.sidebar.history
|
(ns uxbox.main.ui.workspace.sidebar.history
|
||||||
(:require [lentes.core :as l]
|
(:require [uxbox.builtins.icons :as i]
|
||||||
[potok.core :as ptk]
|
|
||||||
[uxbox.main.store :as st]
|
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.refs :as refs]
|
||||||
[uxbox.main.data.workspace :as dw]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.data.pages :as udp]
|
|
||||||
[uxbox.main.data.history :as udh]
|
[uxbox.main.data.history :as udh]
|
||||||
[uxbox.builtins.icons :as i]
|
[uxbox.main.data.pages :as udp]
|
||||||
[uxbox.util.i18n :refer (tr)]
|
[uxbox.main.data.workspace :as dw]
|
||||||
[uxbox.util.router :as r]
|
[uxbox.util.data :refer [read-string]]
|
||||||
[uxbox.util.data :refer (read-string)]
|
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
|
[uxbox.util.i18n :refer [tr]]
|
||||||
[uxbox.util.mixins :as mx :include-macros true]
|
[uxbox.util.mixins :as mx :include-macros true]
|
||||||
|
[uxbox.util.router :as r]
|
||||||
[uxbox.util.time :as dt]))
|
[uxbox.util.time :as dt]))
|
||||||
|
|
||||||
|
|
||||||
;; --- Lenses
|
|
||||||
|
|
||||||
(def history-ref
|
|
||||||
(-> (l/key :history)
|
|
||||||
(l/derive refs/workspace)))
|
|
||||||
|
|
||||||
;; --- History Item (Component)
|
;; --- History Item (Component)
|
||||||
|
|
||||||
(mx/defc history-item
|
(mx/defc history-item
|
||||||
|
@ -43,69 +34,83 @@
|
||||||
:label "no label"
|
:label "no label"
|
||||||
:pinned (not (:pinned item)))]
|
:pinned (not (:pinned item)))]
|
||||||
(st/emit! (udh/update-history-item item))))]
|
(st/emit! (udh/update-history-item item))))]
|
||||||
(let [selected? (= (:version item) selected)]
|
[:li {:class (when (= selected (:version item)) "current")
|
||||||
[:li {:class (when selected? "current") :on-click on-select}
|
:on-click on-select}
|
||||||
[:div.pin-icon {:on-click on-pinned
|
[:div.pin-icon {:on-click on-pinned
|
||||||
:class (when (:pinned item) "selected")}
|
:class (when (:pinned item) "selected")}
|
||||||
i/pin]
|
i/pin]
|
||||||
[:span (str "Version " (:version item)
|
[:span (str "Version " (:version item)
|
||||||
" (" (dt/timeago (:created-at item)) ")")]])))
|
" (" (dt/timeago (:created-at item)) ")")]]))
|
||||||
|
|
||||||
;; --- History List (Component)
|
;; --- History List (Component)
|
||||||
|
|
||||||
(mx/defc history-list
|
(mx/defc history-list
|
||||||
{:mixins [mx/static]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
[page history]
|
[{:keys [selected items min-version] :as history}]
|
||||||
(letfn [(on-select [event]
|
(let [items (reverse (sort-by :version items))
|
||||||
(dom/prevent-default event)
|
page (mx/react refs/selected-page)
|
||||||
(st/emit! (udh/deselect-page-history (:id page))))
|
show-more? (pos? min-version)
|
||||||
|
load-more #(st/emit! (udh/load-more))]
|
||||||
(on-load-more [event]
|
(println "selected" selected)
|
||||||
(dom/prevent-default event)
|
[:ul.history-content
|
||||||
(let [since (:min-version history)
|
(for [item items
|
||||||
params {:since since}]
|
:let [current? (= (:version item) (:version page))]]
|
||||||
(st/emit! (udh/fetch-page-history (:id page) params))))]
|
(-> (history-item item selected current?)
|
||||||
|
(mx/with-key (str (:id item)))))
|
||||||
(let [selected (:selected history)
|
(when show-more?
|
||||||
show-more? (pos? (:min-version history))]
|
[:li {:on-click load-more}
|
||||||
[:ul.history-content
|
[:a.btn-primary.btn-small
|
||||||
[:li {:class (when-not selected "current")
|
"view more"]])]))
|
||||||
:on-click on-select}
|
|
||||||
[:div.pin-icon i/pin]
|
|
||||||
[:span (str "Version " (:version page) " (current)")]]
|
|
||||||
(for [version (:items history)
|
|
||||||
:let [item (get-in history [:by-version version])]]
|
|
||||||
(-> (history-item item selected)
|
|
||||||
(mx/with-key (str (:id item)))))
|
|
||||||
(if show-more?
|
|
||||||
[:li {:on-click on-load-more}
|
|
||||||
[:a.btn-primary.btn-small
|
|
||||||
"view more"]])])))
|
|
||||||
|
|
||||||
;; --- History Pinned List (Component)
|
;; --- History Pinned List (Component)
|
||||||
|
|
||||||
(mx/defc history-pinned-list
|
(mx/defc history-pinned-list
|
||||||
{:mixins [mx/static]}
|
{:mixins [mx/static]}
|
||||||
[history]
|
[{:keys [pinned selected] :as history}]
|
||||||
[:ul.history-content
|
[:ul.history-content
|
||||||
(for [version (:pinned-items history)
|
(for [item (reverse (sort-by :version pinned))
|
||||||
:let [item (get-in history [:by-version version])]]
|
:let [selected? (= (:version item) selected)]]
|
||||||
(-> (history-item item (:selected history))
|
(-> (history-item item selected?)
|
||||||
(mx/with-key (str (:id item)))))])
|
(mx/with-key (str (:id item)))))])
|
||||||
|
|
||||||
;; --- History Toolbox (Component)
|
;; --- History Toolbox (Component)
|
||||||
|
|
||||||
(mx/defcs history-toolbox
|
|
||||||
{:mixins [mx/static mx/reactive (mx/local)]}
|
(defn- history-toolbox-will-mount
|
||||||
[{:keys [rum/local] :as own}]
|
[own]
|
||||||
(let [page (mx/react refs/selected-page)
|
(let [[page-id] (:rum/args own)]
|
||||||
history (mx/react refs/history)
|
(st/emit! (udh/initialize page-id))
|
||||||
section (:section @local :main)
|
own))
|
||||||
|
|
||||||
|
(defn- history-toolbox-did-remount
|
||||||
|
[oldown own]
|
||||||
|
(let [[old-page-id] (:rum/args oldown)
|
||||||
|
[new-page-id] (:rum/args own)]
|
||||||
|
(when-not (= old-page-id new-page-id)
|
||||||
|
(st/emit! ::udh/stop-changes-watcher
|
||||||
|
(udh/initialize new-page-id)))
|
||||||
|
own))
|
||||||
|
|
||||||
|
(defn- history-toolbox-will-unmount
|
||||||
|
[own]
|
||||||
|
(st/emit! ::udh/stop-changes-watcher)
|
||||||
|
own)
|
||||||
|
|
||||||
|
(mx/defc history-toolbox
|
||||||
|
{:mixins [mx/static mx/reactive]
|
||||||
|
:will-mount history-toolbox-will-mount
|
||||||
|
:will-unmount history-toolbox-will-unmount
|
||||||
|
:did-remount history-toolbox-did-remount}
|
||||||
|
[_]
|
||||||
|
(let [history (mx/react refs/history)
|
||||||
|
section (:section history :main)
|
||||||
|
|
||||||
close #(st/emit! (dw/toggle-flag :document-history))
|
close #(st/emit! (dw/toggle-flag :document-history))
|
||||||
main? (= section :main)
|
main? (= section :main)
|
||||||
pinned? (= section :pinned)
|
pinned? (= section :pinned)
|
||||||
show-main #(swap! local assoc :section :main)
|
|
||||||
show-pinned #(swap! local assoc :section :pinned)]
|
show-main #(st/emit! (udh/select-section :main))
|
||||||
|
show-pinned #(st/emit! (udh/select-section :pinned))]
|
||||||
[:div.document-history.tool-window
|
[:div.document-history.tool-window
|
||||||
[:div.tool-window-bar
|
[:div.tool-window-bar
|
||||||
[:div.tool-window-icon i/undo-history]
|
[:div.tool-window-icon i/undo-history]
|
||||||
|
@ -121,17 +126,17 @@
|
||||||
"Pinned"]]
|
"Pinned"]]
|
||||||
(if (= section :pinned)
|
(if (= section :pinned)
|
||||||
(history-pinned-list history)
|
(history-pinned-list history)
|
||||||
(history-list page history))]]))
|
(history-list history))]]))
|
||||||
|
|
||||||
;; --- History Dialog
|
;; --- History Dialog
|
||||||
|
|
||||||
(mx/defc history-dialog
|
(mx/defc history-dialog
|
||||||
{:mixins [mx/static mx/reactive]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
[page]
|
[]
|
||||||
(let [history (mx/react refs/history)
|
(let [history (mx/react refs/history)
|
||||||
version (:selected history)
|
version (:selected history)
|
||||||
on-accept #(st/emit! (udh/apply-selected-history page))
|
on-accept #(st/emit! (udh/apply-selected-history))
|
||||||
on-cancel #(st/emit! (udh/deselect-page-history page))]
|
on-cancel #(st/emit! (udh/deselect-page-history))]
|
||||||
(when (or version (:deselecting history))
|
(when (or version (:deselecting history))
|
||||||
[:div.message-version
|
[:div.message-version
|
||||||
{:class (when (:deselecting history) "hide-message")}
|
{:class (when (:deselecting history) "hide-message")}
|
||||||
|
|
|
@ -347,8 +347,6 @@
|
||||||
[]
|
[]
|
||||||
(let [selected (mx/react refs/selected-shapes)
|
(let [selected (mx/react refs/selected-shapes)
|
||||||
page (mx/react refs/selected-page)
|
page (mx/react refs/selected-page)
|
||||||
|
|
||||||
;; TODO: dont react to the whole shapes-by-id
|
|
||||||
shapes-map (mx/react refs/shapes-by-id)
|
shapes-map (mx/react refs/shapes-by-id)
|
||||||
close #(st/emit! (udw/toggle-flag :layers))
|
close #(st/emit! (udw/toggle-flag :layers))
|
||||||
dragel (volatile! nil)]
|
dragel (volatile! nil)]
|
||||||
|
|
|
@ -103,10 +103,9 @@
|
||||||
|
|
||||||
(mx/defc sitemap-toolbox
|
(mx/defc sitemap-toolbox
|
||||||
{:mixins [mx/static mx/reactive]}
|
{:mixins [mx/static mx/reactive]}
|
||||||
[]
|
[current]
|
||||||
(let [project (mx/react refs/selected-project)
|
(let [project (mx/react refs/selected-project)
|
||||||
pages (mx/react refs/selected-project-pages)
|
pages (mx/react refs/selected-project-pages)
|
||||||
current (mx/react refs/selected-page)
|
|
||||||
create #(udl/open! :page-form {:page {:project (:id project)}})
|
create #(udl/open! :page-form {:page {:project (:id project)}})
|
||||||
close #(st/emit! (dw/toggle-flag :sitemap))]
|
close #(st/emit! (dw/toggle-flag :sitemap))]
|
||||||
[:div.sitemap.tool-window
|
[:div.sitemap.tool-window
|
||||||
|
@ -120,6 +119,6 @@
|
||||||
[:div.add-page {:on-click create} i/close]]
|
[:div.add-page {:on-click create} i/close]]
|
||||||
[:ul.element-list
|
[:ul.element-list
|
||||||
(for [page pages
|
(for [page pages
|
||||||
:let [active? (= (:id page) (:id current))]]
|
:let [active? (= (:id page) current)]]
|
||||||
(-> (page-item page (count pages) active?)
|
(-> (page-item page (count pages) active?)
|
||||||
(mx/with-key (:id page))))]]]))
|
(mx/with-key (:id page))))]]]))
|
||||||
|
|
|
@ -57,13 +57,13 @@
|
||||||
coll)))
|
coll)))
|
||||||
|
|
||||||
(defn replace-by-id
|
(defn replace-by-id
|
||||||
[coll value]
|
([value]
|
||||||
{:pre [(vector? coll)]}
|
(map (fn [item]
|
||||||
(mapv (fn [item]
|
|
||||||
(if (= (:id item) (:id value))
|
(if (= (:id item) (:id value))
|
||||||
value
|
value
|
||||||
item)) coll))
|
item))))
|
||||||
|
([coll value]
|
||||||
|
(sequence (replace-by-id value) coll)))
|
||||||
|
|
||||||
(defn deep-merge
|
(defn deep-merge
|
||||||
"Like merge, but merges maps recursively."
|
"Like merge, but merges maps recursively."
|
||||||
|
@ -80,6 +80,16 @@
|
||||||
(disj s v)
|
(disj s v)
|
||||||
(conj s v)))
|
(conj s v)))
|
||||||
|
|
||||||
|
(defn seek
|
||||||
|
([pred coll]
|
||||||
|
(seek pred coll nil))
|
||||||
|
([pred coll not-found]
|
||||||
|
(reduce (fn [_ x]
|
||||||
|
(if (pred x)
|
||||||
|
(reduced x)
|
||||||
|
not-found))
|
||||||
|
not-found coll)))
|
||||||
|
|
||||||
;; --- String utils
|
;; --- String utils
|
||||||
|
|
||||||
(def +uuid-re+
|
(def +uuid-re+
|
||||||
|
|
Loading…
Add table
Reference in a new issue