(ns metabase.moderation (:require [medley.core :as m] [metabase.models.interface :as mi] [metabase.util :as u] [toucan2.core :as t2])) | |
Schema enum of the acceptable values for the | (def moderated-item-types [:enum "card" :card "dashboard" :dashboard]) |
Maps DB name of the moderated item type to the model symbol (used for t2/select and such) | (def moderated-item-type->model {"card" :model/Card :card :model/Card "dashboard" :model/Dashboard :dashboard :model/Dashboard}) |
Convert a moderated item instance to the keyword stored in the database | (defn- object->type [instance] (u/lower-case-en (name (t2/model instance)))) |
(mi/define-batched-hydration-method moderation-reviews-for-items :moderation_reviews "Hydrate moderation reviews onto a seq of items." [items] ;; no need to do work on empty items. Also, can have nil here due to text cards. I think this is a bug in toucan. To ;; get here we are `(t2/hydrate dashboard [:dashcards [:card :moderation_reviews] :series] ...)` But dashcards ;; dont have to have cards. but the hydration will pass the nil card id into here. NOTE: it is important that each ;; item that comes into this comes out. The nested hydration is positional, not by an id so everything that comes in ;; must go out in the same order (when (seq items) (let [item-ids (not-empty (keep :id items)) all-reviews (when item-ids (group-by (juxt :moderated_item_type :moderated_item_id) (t2/select :model/ModerationReview :moderated_item_id [:in item-ids] {:order-by [[:id :desc]]})))] (for [item items] (if (nil? item) nil (let [k ((juxt (comp keyword object->type) u/the-id) item)] (assoc item :moderation_reviews (get all-reviews k ())))))))) | |
(mi/define-batched-hydration-method moderation-user-details :moderator_details "User details on moderation reviews" [moderation-reviews] (when (seq moderation-reviews) (let [id->user (m/index-by :id (t2/select 'User :id [:in (map :moderator_id moderation-reviews)]))] (for [mr moderation-reviews] (assoc mr :user (get id->user (:moderator_id mr))))))) | |
(mi/define-batched-hydration-method moderation-status :moderation_status "Hydrate moderation status onto a seq of items" [items] (when (seq items) (let [item-ids (seq (keep :id items)) type+id->status (when item-ids (->> (t2/select [:model/ModerationReview :moderated_item_id :moderated_item_type :status] :moderated_item_id [:in item-ids] :most_recent true {:order-by [[:id :desc]]}) (group-by (juxt :moderated_item_type :moderated_item_id)) (m/map-vals #(:status (first %)))))] (for [item items] (some-> item (assoc :moderation_status (get type+id->status [(keyword (object->type item)) (u/the-id item)]))))))) | |