(ns metabase.timeline.models.timeline-event (:require [metabase.models.interface :as mi] [metabase.models.serialization :as serdes] [metabase.util.honey-sql-2 :as h2x] [methodical.core :as methodical] [toucan2.core :as t2])) | |
(methodical/defmethod t2/table-name :model/TimelineEvent [_model] :timeline_event) | |
(doto :model/TimelineEvent (derive :metabase/model) (derive :hook/timestamped?) (derive ::mi/read-policy.full-perms-for-perms-set) (derive ::mi/write-policy.full-perms-for-perms-set)) | |
schemas | |
The default icon for Timeline and TimelineEvents. | (def default-icon "star") |
Schema for Timeline and TimelineEvents | (def Icon [:enum default-icon "cake" "mail" "warning" "bell" "cloud"]) |
Timeline Event Source Schema. For Snowplow Events, where the Event is created from is important.
Events are added from one of three sources: | (def Source [:enum "collections" "question"]) |
transforms | |
(t2/define-after-select :model/TimelineEvent
[timeline-event]
;; We used to have a "balloons" icon but we removed it.
;; Use the default icon instead. (metabase#34586, metabase#35129)
(update timeline-event :icon (fn [icon]
(if (= icon "balloons") default-icon icon)))) | |
permissions | |
(defmethod mi/perms-objects-set :model/TimelineEvent
[event read-or-write]
(let [timeline (or (:timeline event)
(t2/select-one 'Timeline :id (:timeline_id event)))]
(mi/perms-objects-set timeline read-or-write))) | |
hydration | |
(methodical/defmethod t2/batched-hydrate [:model/TimelineEvent :timeline] [_model k events] (mi/instances-with-hydrated-data events k #(t2/select-pk->fn identity :model/Timeline :id [:in (map :timeline_id events)]) :timeline_id)) | |
Fetch events for timelines in | (defn- fetch-events
[timeline-ids {:events/keys [all? start end]}]
(let [clause {:where [:and
;; in our collections
[:in :timeline_id timeline-ids]
(when-not all?
[:= :archived false])
(when (or start end)
[:or
;; absolute time in bounds
[:and
[:= :time_matters true]
;; less than or equal?
(when start
[:<= start :timestamp])
(when end
[:<= :timestamp end])]
;; non-specic time in bounds
[:and
[:= :time_matters false]
(when start
[:<= (h2x/->date start) (h2x/->date :timestamp)])
(when end
[:<= (h2x/->date :timestamp) (h2x/->date end)])]])]}]
(t2/hydrate (t2/select :model/TimelineEvent clause) :creator))) |
Include events on | (defn include-events
[timelines options]
(if-not (seq timelines)
[]
(let [timeline-id->events (->> (fetch-events (map :id timelines) options)
(group-by :timeline_id))]
(for [{:keys [id] :as timeline} timelines]
(let [events (timeline-id->events id)]
(when timeline
(assoc timeline :events (if events events [])))))))) |
Similar to [[include-events]] but allows for passing a single timeline not in a collection. | (defn include-events-singular
([timeline] (include-events-singular timeline {}))
([timeline options]
(first (include-events [timeline] options)))) |
Look for a timeline and corresponding events associated with this dashcard. | (defn dashcard-timeline-events
[{{:keys [collection_id] :as _card} :card}]
(let [timelines (t2/select :model/Timeline
:collection_id collection_id
:archived false)]
(->> (t2/hydrate timelines :creator [:collection :can_write])
(map #(include-events-singular % {:events/all? true}))))) |
model | |
(defmethod serdes/hash-fields :model/TimelineEvent [_timeline-event] [:name :timestamp (serdes/hydrated-hash :timeline) :created_at]) | |
serialization | |
nested in Timeline | (defmethod serdes/make-spec "TimelineEvent" [_model-name _opts]
{:copy [:archived :description :icon :name :time_matters :timezone]
:skip []
:transform {:created_at (serdes/date)
:creator_id (serdes/fk :model/User)
:timeline_id (serdes/parent-ref)
:timestamp (serdes/date)}}) |