mirror of
https://github.com/penpot/penpot.git
synced 2025-06-02 21:11:38 +02:00
278 lines
7.7 KiB
Clojure
278 lines
7.7 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) 2016 Andrey Antukh <niwi@niwi.nz>
|
|
|
|
(ns uxbox.main.data.history
|
|
(:require [cuerdas.core :as str]
|
|
[beicon.core :as rx]
|
|
[lentes.core :as l]
|
|
[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.store :as st]
|
|
[uxbox.util.time :as dt]
|
|
[uxbox.util.data :refer (without-keys
|
|
replace-by-id
|
|
index-by)]))
|
|
|
|
;; --- Watch Page Changes
|
|
|
|
(declare fetch-page-history)
|
|
(declare fetch-pinned-page-history)
|
|
|
|
(deftype WatchPageChanges [id]
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(let [stopper (->> stream
|
|
(rx/filter #(= % ::udp/stop-page-watcher))
|
|
(rx/take 1))]
|
|
(->> stream
|
|
(rx/take-until stopper)
|
|
(rx/filter udp/page-persisted?)
|
|
(rx/debounce 500)
|
|
(rx/flat-map #(rx/of (fetch-page-history id)
|
|
(fetch-pinned-page-history id)))))))
|
|
|
|
(defn watch-page-changes
|
|
[id]
|
|
(WatchPageChanges. id))
|
|
|
|
;; --- Pinned Page History Fetched
|
|
|
|
(declare update-history-index)
|
|
|
|
(defrecord PinnedPageHistoryFetched [history]
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(-> state
|
|
(assoc-in [:workspace :history :pinned-items] (mapv :version history))
|
|
(update-history-index history true))))
|
|
|
|
;; --- Fetch Pinned Page History
|
|
|
|
(defrecord FetchPinnedPageHistory [id]
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(letfn [(on-success [{history :payload}]
|
|
(->PinnedPageHistoryFetched (into [] history)))]
|
|
(let [params {:page id :pinned true}]
|
|
(->> (rp/req :fetch/page-history params)
|
|
(rx/map on-success))))))
|
|
|
|
(defn fetch-pinned-page-history
|
|
[id]
|
|
(->FetchPinnedPageHistory id))
|
|
|
|
;; --- Page History Fetched
|
|
|
|
(defrecord PageHistoryFetched [history append?]
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(letfn [(update-counters [state items]
|
|
(-> (assoc state :min-version (apply min items))
|
|
(assoc :max-version (apply max items))))
|
|
|
|
(update-lists [state items]
|
|
(if append?
|
|
(update state :items #(reduce conj %1 items))
|
|
(assoc state :items items)))]
|
|
|
|
(let [items (mapv :version history)
|
|
hstate (-> (get-in state [:workspace :history] {})
|
|
(update-counters items)
|
|
(update-lists items))]
|
|
(-> state
|
|
(assoc-in [:workspace :history] hstate)
|
|
(update-history-index history append?))))))
|
|
|
|
;; --- Fetch Page History
|
|
|
|
(defrecord FetchPageHistory [id since max]
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(letfn [(on-success [{history :payload}]
|
|
(let [history (into [] history)]
|
|
(->PageHistoryFetched history (not (nil? since)))))]
|
|
(let [params (merge
|
|
{:page id :max (or max 15)}
|
|
(when since {:since since}))]
|
|
(->> (rp/req :fetch/page-history params)
|
|
(rx/map on-success))))))
|
|
|
|
(defn fetch-page-history
|
|
([id]
|
|
(fetch-page-history id nil))
|
|
([id params]
|
|
(map->FetchPageHistory (assoc params :id id))))
|
|
|
|
;; --- Select Page History
|
|
|
|
(defrecord SelectPageHistory [version]
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(let [item (get-in state [:workspace :history :by-version version])
|
|
page (get-in state [:pages (:page item)])
|
|
page (assoc page
|
|
:history true
|
|
:data (:data item))]
|
|
(-> state
|
|
(udp/assoc-page page)
|
|
(assoc-in [:workspace :history :selected] version)))))
|
|
|
|
(defn select-page-history
|
|
[version]
|
|
(SelectPageHistory. version))
|
|
|
|
;; --- Apply selected history
|
|
|
|
(defrecord ApplySelectedHistory [id]
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(-> state
|
|
(update-in [:pages id] dissoc :history)
|
|
(assoc-in [:workspace :history :selected] nil)))
|
|
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(rx/of (udp/persist-page id))))
|
|
|
|
(defn apply-selected-history
|
|
[id]
|
|
(ApplySelectedHistory. id))
|
|
|
|
;; --- Deselect Page History
|
|
|
|
(defrecord DeselectPageHistory [id]
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(let [packed (get-in state [:packed-pages id])]
|
|
(-> (udp/assoc-page state packed)
|
|
(assoc-in [:workspace :history :deselecting] true)
|
|
(assoc-in [:workspace :history :selected] nil))))
|
|
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(->> (rx/of #(assoc-in % [:workspace :history :deselecting] false))
|
|
(rx/delay 500))))
|
|
|
|
(defn deselect-page-history
|
|
[id]
|
|
(DeselectPageHistory. id))
|
|
|
|
;; --- History Item Updated
|
|
|
|
(defrecord HistoryItemUpdated [item]
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(-> state
|
|
(update-in [:workspace :history :items] replace-by-id item)
|
|
(update-in [:workspace :history :pinned-items] replace-by-id item))))
|
|
|
|
(defn history-updated?
|
|
[item]
|
|
(instance? HistoryItemUpdated item))
|
|
|
|
(defn history-updated
|
|
[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
|
|
|
|
(defrecord UpdateHistoryItem [item]
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(letfn [(on-success [{item :payload}]
|
|
(->HistoryItemUpdated item))]
|
|
(rx/merge
|
|
(->> (rp/req :update/page-history item)
|
|
(rx/map on-success))
|
|
(->> (rx/filter history-updated? s)
|
|
(rx/take 1)
|
|
(rx/map #(refres-page-history (:page item))))))))
|
|
|
|
(defn update-history-item
|
|
[item]
|
|
(UpdateHistoryItem. item))
|
|
|
|
;; --- Forward to Next Version
|
|
|
|
(defrecord ForwardToNextVersion []
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(let [workspace (:workspace state)
|
|
history (:history workspace)
|
|
version (:selected history)]
|
|
(cond
|
|
(nil? version)
|
|
(rx/empty)
|
|
|
|
(>= (:max-version history) (inc version))
|
|
(rx/of (select-page-history (inc version)))
|
|
|
|
(> (inc version) (:max-version history))
|
|
(rx/of (deselect-page-history (:page workspace)))
|
|
|
|
:else
|
|
(rx/empty)))))
|
|
|
|
(defn forward-to-next-version
|
|
[]
|
|
(ForwardToNextVersion.))
|
|
|
|
;; --- Backwards to Previous Version
|
|
|
|
(defrecord BackwardsToPreviousVersion []
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(let [workspace (:workspace state)
|
|
history (:history workspace)
|
|
version (:selected history)]
|
|
(cond
|
|
(nil? version)
|
|
(let [maxv (:max-version history)]
|
|
(rx/of (select-page-history maxv)))
|
|
|
|
(pos? (dec version))
|
|
(if (contains? (:by-version history) (dec version))
|
|
(rx/of (select-page-history (dec version)))
|
|
(let [since (:min-version history)
|
|
page (:page workspace)
|
|
params {:since since}]
|
|
(rx/of (fetch-page-history page params)
|
|
(select-page-history (dec version)))))
|
|
|
|
:else
|
|
(rx/empty)))))
|
|
|
|
(defn backwards-to-previous-version
|
|
[]
|
|
(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))))
|
|
|