(ns metabase.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])) | |
Used to be the toucan1 model name defined using [[toucan.models/defmodel]], now it's a reference to the toucan2 model name. We'll keep this till we replace all the symbols in our codebase. | (def TimelineEvent :model/TimelineEvent) |
(methodical/defmethod t2/table-name :model/TimelineEvent [_model] :timeline_event) | |
(doto 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 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)))) |
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)}}) |