diff --git a/enterprise/backend/test/metabase_enterprise/models/entity_id_test.clj b/enterprise/backend/test/metabase_enterprise/models/entity_id_test.clj index da94c10c915bd19fd6b7556130ead8e404ecdcc9..3c4518d18b8bc9e3225712e7be2c454b53ad6913 100644 --- a/enterprise/backend/test/metabase_enterprise/models/entity_id_test.clj +++ b/enterprise/backend/test/metabase_enterprise/models/entity_id_test.clj @@ -45,7 +45,7 @@ :metabase.models.bookmark/DashboardBookmark :metabase.models.collection.root/RootCollection :metabase.models.collection-permission-graph-revision/CollectionPermissionGraphRevision - :metabase.models.dashboard-card-series/DashboardCardSeries + :model/DashboardCardSeries :metabase.models.field-values/FieldValues :metabase.models.login-history/LoginHistory :metabase.models.metric-important-field/MetricImportantField diff --git a/enterprise/backend/test/metabase_enterprise/serialization/upsert_test.clj b/enterprise/backend/test/metabase_enterprise/serialization/upsert_test.clj index 5ca7a2a45a6f8bdda46e7da23c14b55e55fd88f8..b859d757c67436f212b35566391f486a32f10483 100644 --- a/enterprise/backend/test/metabase_enterprise/serialization/upsert_test.clj +++ b/enterprise/backend/test/metabase_enterprise/serialization/upsert_test.clj @@ -44,8 +44,8 @@ ;; the new style. Feel free to give them better names - Cam (deftest maybe-upsert-many!-skip-test (mt/with-model-cleanup [Card] - (let [existing-ids (t2/insert-returning-pks! Card @cards) - inserted-ids (vec (upsert/maybe-upsert-many! {:mode :skip} Card @cards))] + (let [existing-ids (sort (t2/insert-returning-pks! Card @cards)) + inserted-ids (sort (vec (upsert/maybe-upsert-many! {:mode :skip} Card @cards)))] (is (= existing-ids inserted-ids))))) (deftest maybe-upsert-many!-same-objects-test diff --git a/src/metabase/api/dashboard.clj b/src/metabase/api/dashboard.clj index be84366f61f8e5f500c8e2334f1de19c5aa178db..02048ca6820d2159d9f21280730eb30ab3889f72 100644 --- a/src/metabase/api/dashboard.clj +++ b/src/metabase/api/dashboard.clj @@ -50,11 +50,11 @@ (set! *warn-on-reflection* true) (defn- dashboards-list [filter-option] - (as-> (t2/select Dashboard {:where [:and (case (or (keyword filter-option) :all) - (:all :archived) true - :mine [:= :creator_id api/*current-user-id*]) - [:= :archived (= (keyword filter-option) :archived)]] - :order-by [:%lower.name]}) <> + (as-> (t2/select :model/Dashboard {:where [:and (case (or (keyword filter-option) :all) + (:all :archived) true + :mine [:= :creator_id api/*current-user-id*]) + [:= :archived (= (keyword filter-option) :archived)]] + :order-by [:%lower.name]}) <> (hydrate <> :creator) (filter mi/can-read? <>))) @@ -100,7 +100,7 @@ ;; position, check that and fix up if needed (api/maybe-reconcile-collection-position! dashboard-data) ;; Ok, now save the Dashboard - (first (t2/insert-returning-instances! Dashboard dashboard-data)))] + (first (t2/insert-returning-instances! :model/Dashboard dashboard-data)))] (events/publish-event! :dashboard-create dash) (snowplow/track-event! ::snowplow/dashboard-created api/*current-user-id* {:dashboard-id (u/the-id dash)}) (assoc dash :last-edit-info (last-edit/edit-information-for-user @api/*current-user*)))) @@ -212,7 +212,7 @@ (defn- get-dashboard "Get Dashboard with ID." [id] - (-> (t2/select-one Dashboard :id id) + (-> (t2/select-one :model/Dashboard :id id) api/check-404 ;; i'm a bit worried that this is an n+1 situation here. The cards can be batch hydrated i think because they ;; have a hydration key and an id. moderation_reviews currently aren't batch hydrated but i'm worried they @@ -339,7 +339,7 @@ ;; collection to change position, check that and fix up if needed (api/maybe-reconcile-collection-position! dashboard-data) ;; Ok, now save the Dashboard - (let [dash (first (t2/insert-returning-instances! Dashboard dashboard-data)) + (let [dash (first (t2/insert-returning-instances! :model/Dashboard dashboard-data)) {id->new-card :copied uncopied :uncopied} (when is_deep_copy (duplicate-cards existing-dashboard collection_id))] @@ -401,7 +401,7 @@ collection_id (s/maybe su/IntGreaterThanZero) collection_position (s/maybe su/IntGreaterThanZero) cache_ttl (s/maybe su/IntGreaterThanZero)} - (let [dash-before-update (api/write-check Dashboard id)] + (let [dash-before-update (api/write-check :model/Dashboard id)] ;; Do various permissions checks as needed (collection/check-allowed-to-change-collection dash-before-update dash-updates) (check-allowed-to-change-embedding dash-before-update dash-updates) @@ -415,9 +415,9 @@ :present #{:description :position :collection_id :collection_position :cache_ttl} :non-nil #{:name :parameters :caveats :points_of_interest :show_in_getting_started :enable_embedding :embedding_params :archived :auto_apply_filters}))] - (t2/update! Dashboard id updates)))) + (t2/update! :model/Dashboard id updates)))) ;; now publish an event and return the updated Dashboard - (let [dashboard (t2/select-one Dashboard :id id)] + (let [dashboard (t2/select-one :model/Dashboard :id id)] (events/publish-event! :dashboard-update (assoc dashboard :actor_id api/*current-user-id*)) (assoc dashboard :last-edit-info (last-edit/edit-information-for-user @api/*current-user*)))) @@ -431,8 +431,8 @@ [id] (log/warn (str "DELETE /api/dashboard/:id is deprecated. Instead of deleting a Dashboard, you should change its " "`archived` value via PUT /api/dashboard/:id.")) - (let [dashboard (api/write-check Dashboard id)] - (t2/delete! Dashboard :id id) + (let [dashboard (api/write-check :model/Dashboard id)] + (t2/delete! :model/Dashboard :id id) (events/publish-event! :dashboard-delete (assoc dashboard :actor_id api/*current-user-id*))) api/generic-204-no-content) @@ -616,17 +616,17 @@ (api/defendpoint-schema GET "/:id/revisions" "Fetch `Revisions` for Dashboard with ID." [id] - (api/read-check Dashboard id) - (revision/revisions+details Dashboard id)) + (api/read-check :model/Dashboard id) + (revision/revisions+details :model/Dashboard id)) #_{:clj-kondo/ignore [:deprecated-var]} (api/defendpoint-schema POST "/:id/revert" "Revert a Dashboard to a prior `Revision`." [id :as {{:keys [revision_id]} :body}] {revision_id su/IntGreaterThanZero} - (api/write-check Dashboard id) + (api/write-check :model/Dashboard id) (revision/revert! - :entity Dashboard + :entity :model/Dashboard :id id :user-id api/*current-user-id* :revision-id revision_id)) @@ -641,10 +641,10 @@ [dashboard-id] (api/check-superuser) (validation/check-public-sharing-enabled) - (api/check-not-archived (api/read-check Dashboard dashboard-id)) - {:uuid (or (t2/select-one-fn :public_uuid Dashboard :id dashboard-id) + (api/check-not-archived (api/read-check :model/Dashboard dashboard-id)) + {:uuid (or (t2/select-one-fn :public_uuid :model/Dashboard :id dashboard-id) (u/prog1 (str (UUID/randomUUID)) - (t2/update! Dashboard dashboard-id + (t2/update! :model/Dashboard dashboard-id {:public_uuid <> :made_public_by_id api/*current-user-id*})))}) @@ -654,8 +654,8 @@ [dashboard-id] (validation/check-has-application-permission :setting) (validation/check-public-sharing-enabled) - (api/check-exists? Dashboard :id dashboard-id, :public_uuid [:not= nil], :archived false) - (t2/update! Dashboard dashboard-id + (api/check-exists? :model/Dashboard :id dashboard-id, :public_uuid [:not= nil], :archived false) + (t2/update! :model/Dashboard dashboard-id {:public_uuid nil :made_public_by_id nil}) {:status 204, :body nil}) @@ -667,7 +667,7 @@ [] (validation/check-has-application-permission :setting) (validation/check-public-sharing-enabled) - (t2/select [Dashboard :name :id :public_uuid], :public_uuid [:not= nil], :archived false)) + (t2/select [:model/Dashboard :name :id :public_uuid], :public_uuid [:not= nil], :archived false)) #_{:clj-kondo/ignore [:deprecated-var]} (api/defendpoint-schema GET "/embeddable" @@ -676,13 +676,13 @@ [] (validation/check-has-application-permission :setting) (validation/check-embedding-enabled) - (t2/select [Dashboard :name :id], :enable_embedding true, :archived false)) + (t2/select [:model/Dashboard :name :id], :enable_embedding true, :archived false)) #_{:clj-kondo/ignore [:deprecated-var]} (api/defendpoint-schema GET "/:id/related" "Return related entities." [id] - (-> (t2/select-one Dashboard :id id) api/read-check related/related)) + (-> (t2/select-one :model/Dashboard :id id) api/read-check related/related)) ;;; ---------------------------------------------- Transient dashboards ---------------------------------------------- @@ -811,7 +811,7 @@ ;; fetch values for Dashboard 1 parameter 'abc' that are possible when parameter 'def' is set to 100 GET /api/dashboard/1/params/abc/values?def=100" [id param-key :as {:keys [query-params]}] - (let [dashboard (api/read-check Dashboard id)] + (let [dashboard (api/read-check :model/Dashboard id)] ;; If a user can read the dashboard, then they can lookup filters. This also works with sandboxing. (binding [qp.perms/*param-values-query* true] (param-values dashboard param-key query-params)))) @@ -827,7 +827,7 @@ Currently limited to first 1000 results." [id param-key query :as {:keys [query-params]}] - (let [dashboard (api/read-check Dashboard id)] + (let [dashboard (api/read-check :model/Dashboard id)] ;; If a user can read the dashboard, then they can lookup filters. This also works with sandboxing. (binding [qp.perms/*param-values-query* true] (param-values dashboard param-key query-params query)))) @@ -887,7 +887,7 @@ {dashboard-id su/IntGreaterThanZero dashcard-id su/IntGreaterThanZero parameters su/JSONString} - (api/read-check Dashboard dashboard-id) + (api/read-check :model/Dashboard dashboard-id) (actions.execution/fetch-values dashboard-id dashcard-id (json/parse-string parameters))) #_{:clj-kondo/ignore [:deprecated-var]} @@ -900,7 +900,7 @@ {dashboard-id su/IntGreaterThanZero dashcard-id su/IntGreaterThanZero parameters (s/maybe {s/Keyword s/Any})} - (api/read-check Dashboard dashboard-id) + (api/read-check :model/Dashboard dashboard-id) ;; Undo middleware string->keyword coercion (actions.execution/execute-dashcard! dashboard-id dashcard-id (update-keys parameters name))) diff --git a/src/metabase/db/util.clj b/src/metabase/db/util.clj index d77ccbdc0d6f3a7b452016f122046d93490c352e..3d2a934dd30ea546ac9aeb8ea94ae17c5311eda7 100644 --- a/src/metabase/db/util.clj +++ b/src/metabase/db/util.clj @@ -10,8 +10,7 @@ [toucan2.model :as t2.model])) (defn toucan-model? - "Check if `model` is a toucan model. - In toucan2 any keywords can be a model so it's always true for keyword." + "Check if `model` is a toucan model." [model] (or ;; toucan 2 models diff --git a/src/metabase/models/dashboard.clj b/src/metabase/models/dashboard.clj index bdf708e83b4eed798f61bec817d0f2acefd83bb3..aa9e9e85c314b7c09e9f432fbf682d1c06cb3201 100644 --- a/src/metabase/models/dashboard.clj +++ b/src/metabase/models/dashboard.clj @@ -32,69 +32,49 @@ [metabase.util.malli :as mu] [metabase.util.malli.schema :as ms] [metabase.util.schema :as su] + [methodical.core :as methodical] [schema.core :as s] [toucan.hydrate :refer [hydrate]] - [toucan.models :as models] [toucan2.core :as t2])) -;;; --------------------------------------------------- Hydration ---------------------------------------------------- - -(mi/define-simple-hydration-method ordered-cards - :ordered_cards - "Return the DashboardCards associated with `dashboard`, in the order they were created." - [dashboard-or-id] - (t2/select DashboardCard - {:select [:dashcard.* [:collection.authority_level :collection_authority_level]] - :from [[:report_dashboardcard :dashcard]] - :left-join [[:report_card :card] [:= :dashcard.card_id :card.id] - [:collection :collection] [:= :collection.id :card.collection_id]] - :where [:and - [:= :dashcard.dashboard_id (u/the-id dashboard-or-id)] - [:or - [:= :card.archived false] - [:= :card.archived nil]]] ; e.g. DashCards with no corresponding Card, e.g. text Cards - :order-by [[:dashcard.created_at :asc]]})) - -(mi/define-batched-hydration-method collections-authority-level - :collection_authority_level - "Efficiently hydrate the `:collection_authority_level` of a sequence of dashboards." - [dashboards] - (when (seq dashboards) - (let [coll-id->level (into {} - (map (juxt :id :authority_level)) - (mdb.query/query {:select [:dashboard.id :collection.authority_level] - :from [[:report_dashboard :dashboard]] - :left-join [[:collection :collection] [:= :collection.id :dashboard.collection_id]] - :where [:in :dashboard.id (into #{} (map u/the-id) dashboards)]}))] - (for [dashboard dashboards] - (assoc dashboard :collection_authority_level (get coll-id->level (u/the-id dashboard))))))) +(def Dashboard + "Used to be the toucan1 model name defined using [[toucan.models/defmodel]], not it's a reference to the toucan2 model name. + We'll keep this till we replace all the Dashboard symbol in our codebase." + :model/Dashboard) -(comment moderation/keep-me) +(methodical/defmethod t2/table-name :model/Dashboard [_model] :report_dashboard) -(models/defmodel Dashboard :report_dashboard) +(doto :model/Dashboard + (derive ::perms/use-parent-collection-perms) + (derive :metabase/model) + (derive :hook/timestamped?) + (derive :hook/entity-id)) -(derive Dashboard ::perms/use-parent-collection-perms) +(t2/deftransforms :model/Dashboard + {:parameters mi/transform-parameters-list + :embedding_params mi/transform-json}) -;;; ----------------------------------------------- Entity & Lifecycle ----------------------------------------------- - -(defn- pre-delete [dashboard] +(t2/define-before-delete :model/Dashboard + [dashboard] (let [dashboard-id (u/the-id dashboard)] (parameter-card/delete-all-for-parameterized-object! "dashboard" dashboard-id) (t2/delete! 'Revision :model "Dashboard" :model_id dashboard-id))) -(defn- pre-insert [dashboard] +(t2/define-before-insert :model/Dashboard + [dashboard] (let [defaults {:parameters []} dashboard (merge defaults dashboard)] (u/prog1 dashboard (params/assert-valid-parameters dashboard) (collection/check-collection-namespace Dashboard (:collection_id dashboard))))) -(defn- post-insert +(t2/define-after-insert :model/Dashboard [dashboard] (u/prog1 dashboard (parameter-card/upsert-or-delete-from-parameters! "dashboard" (:id dashboard) (:parameters dashboard)))) -(defn- pre-update [dashboard] +(t2/define-before-update :model/Dashboard + [dashboard] (u/prog1 dashboard (params/assert-valid-parameters dashboard) (parameter-card/upsert-or-delete-from-parameters! "dashboard" (:id dashboard) (:parameters dashboard)) @@ -142,30 +122,56 @@ :collection_id (:collection_id dashboard)}) (pulse-card/bulk-create! new-pulse-cards))))))) -(defn- post-update +(t2/define-after-update :model/Dashboard [dashboard] (update-dashboard-subscription-pulses! dashboard)) -(mi/define-methods - Dashboard - {:properties (constantly {::mi/timestamped? true - ::mi/entity-id true}) - :types (constantly {:parameters :parameters-list, :embedding_params :json}) - :pre-delete pre-delete - :pre-insert pre-insert - :post-insert post-insert - :pre-update pre-update - :post-update post-update - :post-select (comp public-settings/remove-public-uuid-if-public-sharing-is-disabled)}) - -(defmethod serdes/hash-fields Dashboard +(t2/define-after-select :model/Dashboard + [dashboard] + (-> dashboard + public-settings/remove-public-uuid-if-public-sharing-is-disabled)) + +(defmethod serdes/hash-fields :model/Dashboard [_dashboard] [:name (serdes/hydrated-hash :collection) :created_at]) +;;; --------------------------------------------------- Hydration ---------------------------------------------------- + +(mi/define-simple-hydration-method ordered-cards + :ordered_cards + "Return the DashboardCards associated with `dashboard`, in the order they were created." + [dashboard-or-id] + (t2/select DashboardCard + {:select [:dashcard.* [:collection.authority_level :collection_authority_level]] + :from [[:report_dashboardcard :dashcard]] + :left-join [[:report_card :card] [:= :dashcard.card_id :card.id] + [:collection :collection] [:= :collection.id :card.collection_id]] + :where [:and + [:= :dashcard.dashboard_id (u/the-id dashboard-or-id)] + [:or + [:= :card.archived false] + [:= :card.archived nil]]] ; e.g. DashCards with no corresponding Card, e.g. text Cards + :order-by [[:dashcard.created_at :asc]]})) + +(mi/define-batched-hydration-method collections-authority-level + :collection_authority_level + "Efficiently hydrate the `:collection_authority_level` of a sequence of dashboards." + [dashboards] + (when (seq dashboards) + (let [coll-id->level (into {} + (map (juxt :id :authority_level)) + (mdb.query/query {:select [:dashboard.id :collection.authority_level] + :from [[:report_dashboard :dashboard]] + :left-join [[:collection :collection] [:= :collection.id :dashboard.collection_id]] + :where [:in :dashboard.id (into #{} (map u/the-id) dashboards)]}))] + (for [dashboard dashboards] + (assoc dashboard :collection_authority_level (get coll-id->level (u/the-id dashboard))))))) + +(comment moderation/keep-me) ;;; --------------------------------------------------- Revisions ---------------------------------------------------- -(defmethod revision/serialize-instance Dashboard +(defmethod revision/serialize-instance :model/Dashboard [_model _id dashboard] (-> dashboard (select-keys [:description :name :cache_ttl :auto_apply_filters]) @@ -173,10 +179,10 @@ (-> (select-keys dashboard-card [:size_x :size_y :row :col :id :card_id]) (assoc :series (mapv :id (dashboard-card/series dashboard-card))))))))) -(defmethod revision/revert-to-revision! Dashboard +(defmethod revision/revert-to-revision! :model/Dashboard [_model dashboard-id user-id serialized-dashboard] ;; Update the dashboard description / name / permissions - (t2/update! Dashboard dashboard-id, (dissoc serialized-dashboard :cards)) + (t2/update! :model/Dashboard dashboard-id, (dissoc serialized-dashboard :cards)) ;; Now update the cards as needed (let [serialized-cards (:cards serialized-dashboard) id->serialized-card (zipmap (map :id serialized-cards) serialized-cards) @@ -202,7 +208,7 @@ serialized-dashboard) -(defmethod revision/diff-str Dashboard +(defmethod revision/diff-str :model/Dashboard [_model dashboard1 dashboard2] (let [[removals changes] (diff dashboard1 dashboard2) check-series-change (fn [idx card-changes] @@ -376,7 +382,7 @@ "Automatically generated cards." parent-collection-id) dashboard (first (t2/insert-returning-instances! - Dashboard + :model/Dashboard (-> dashboard (dissoc :ordered_cards :rule :related :transient_name :transient_filters :param_fields :more) diff --git a/src/metabase/models/dashboard_card.clj b/src/metabase/models/dashboard_card.clj index 6d5d0ee845eab6fc8c746a8f201f468a12d40ff1..48a4799207de16af4af456343bfcca15fd9b841b 100644 --- a/src/metabase/models/dashboard_card.clj +++ b/src/metabase/models/dashboard_card.clj @@ -17,23 +17,40 @@ [metabase.util.malli :as mu] [metabase.util.malli.schema :as ms] [metabase.util.schema :as su] + [methodical.core :as methodical] [schema.core :as s] [toucan.db :as db] [toucan.hydrate :refer [hydrate]] - [toucan.models :as models] [toucan2.core :as t2])) -(models/defmodel DashboardCard :report_dashboardcard) +(def DashboardCard + "Used to be the toucan1 model name defined using [[toucan.models/defmodel]], not it's a reference to the toucan2 model name. + We'll keep this till we replace all the DashboardCard symbol in our codebase." + :model/DashboardCard) -(doto DashboardCard +(methodical/defmethod t2/table-name :model/DashboardCard [_model] :report_dashboardcard) + +(doto :model/DashboardCard + (derive :metabase/model) (derive ::mi/read-policy.full-perms-for-perms-set) - (derive ::mi/write-policy.full-perms-for-perms-set)) + (derive ::mi/write-policy.full-perms-for-perms-set) + (derive :hook/timestamped?) + (derive :hook/entity-id)) + +(t2/deftransforms :model/DashboardCard + {:parameter_mappings mi/transform-parameters-list + :visualization_settings mi/transform-visualization-settings}) + +(t2/define-before-insert :model/DashboardCard + [dashcard] + (merge {:parameter_mappings [] + :visualization_settings {}} dashcard)) (declare series) ;;; Return the set of permissions required to `read-or-write` this DashboardCard. If `:card` and `:series` are already ;;; hydrated this method doesn't need to make any DB calls. -(defmethod mi/perms-objects-set DashboardCard +(defmethod mi/perms-objects-set :model/DashboardCard [dashcard read-or-write] (let [card (or (:card dashcard) (t2/select-one [Card :dataset_query] :id (u/the-id (:card_id dashcard)))) @@ -42,19 +59,6 @@ (apply set/union (mi/perms-objects-set card read-or-write) (for [series-card series] (mi/perms-objects-set series-card read-or-write))))) -(defn- pre-insert [dashcard] - (let [defaults {:parameter_mappings [] - :visualization_settings {}}] - (merge defaults dashcard))) - -(mi/define-methods - DashboardCard - {:properties (constantly {::mi/timestamped? true - ::mi/entity-id true}) - :types (constantly {:parameter_mappings :parameters-list - :visualization_settings :visualization-settings}) - :pre-insert pre-insert}) - (defn from-parsed-json "Convert a map with dashboard-card into a Toucan instance assuming it came from parsed JSON and the map keys have been keywordized. This is useful if the data from a request body inside a `defendpoint` body, and you need it in the @@ -71,12 +75,12 @@ true ```" [dashboard-card] - (t2/instance DashboardCard + (t2/instance :model/DashboardCard (-> dashboard-card (m/update-existing :parameter_mappings mi/normalize-parameters-list) (m/update-existing :visualization_settings mi/normalize-visualization-settings)))) -(defmethod serdes/hash-fields DashboardCard +(defmethod serdes/hash-fields :model/DashboardCard [_dashboard-card] [(serdes/hydrated-hash :card) ; :card is optional, eg. text cards (comp serdes/identity-hash @@ -105,7 +109,7 @@ (s/defn retrieve-dashboard-card "Fetch a single DashboardCard by its ID value." [id :- su/IntGreaterThanZero] - (-> (t2/select-one DashboardCard :id id) + (-> (t2/select-one :model/DashboardCard :id id) (hydrate :series))) (defn dashcard->multi-cards @@ -182,7 +186,7 @@ updates (shallow-updates (select-keys dashboard-card update-ks) (select-keys old-dashboard-card update-ks))] (when (seq updates) - (t2/update! DashboardCard id updates)) + (t2/update! :model/DashboardCard id updates)) (when (not= (:series dashboard-card []) (:series old-dashboard-card [])) (update-dashboard-cards-series! {(:id dashboard-card) (:series dashboard-card)})) diff --git a/src/metabase/models/dashboard_card_series.clj b/src/metabase/models/dashboard_card_series.clj index 5277f622e64d4c901f853560b67341c11b41914a..fcbc2475d4678ac9209a27346a562b099fbfed76 100644 --- a/src/metabase/models/dashboard_card_series.clj +++ b/src/metabase/models/dashboard_card_series.clj @@ -1,15 +1,23 @@ (ns metabase.models.dashboard-card-series (:require [metabase.models.serialization :as serdes] - [toucan.models :as models] + [methodical.core :as methodical] [toucan2.core :as t2])) -(models/defmodel DashboardCardSeries :dashboardcard_series) +(def DashboardCardSeries + "Used to be the toucan1 model name defined using [[toucan.models/defmodel]], not it's a reference to the toucan2 model name. + We'll keep this till we replace all the DashboardCardSeries symbol in our codebase." + :model/DashboardCardSeries) + +(methodical/defmethod t2/table-name :model/DashboardCardSeries [_model] :dashboardcard_series) + +(doto :model/DashboardCardSeries + (derive :metabase/model)) (defn- dashboard-card [{:keys [dashboardcard_id]}] - (t2/select-one 'DashboardCard :id dashboardcard_id)) + (t2/select-one :model/DashboardCardSeries :id dashboardcard_id)) -(defmethod serdes/hash-fields DashboardCardSeries +(defmethod serdes/hash-fields :model/DashboardCardSeries [_dashboard-card-series] [(comp serdes/identity-hash dashboard-card) (serdes/hydrated-hash :card) diff --git a/src/metabase/models/params.clj b/src/metabase/models/params.clj index a30e3190061e6db79d46dde5b5bccb2eb199bce7..ba818326ee63b3f05d5c81d3284b08b71b3a14a5 100644 --- a/src/metabase/models/params.clj +++ b/src/metabase/models/params.clj @@ -241,16 +241,17 @@ id)) (cards->card-param-field-ids (map :card dashcards)))) + (defn- dashboard->param-field-values "Return a map of Field ID to FieldValues (if any) for any Fields referenced by Cards in `dashboard`, or `nil` if none are referenced or none of them have FieldValues." [dashboard] (field-ids->param-field-values (dashcards->param-field-ids (:ordered_cards dashboard)))) -(defmethod param-values :metabase.models.dashboard/Dashboard [dashboard] +(defmethod param-values :model/Dashboard [dashboard] (dashboard->param-field-values dashboard)) -(defmethod param-fields :metabase.models.dashboard/Dashboard [dashboard] +(defmethod param-fields :model/Dashboard [dashboard] (-> (hydrate dashboard [:ordered_cards :card]) :ordered_cards dashcards->param-field-ids diff --git a/src/metabase/models/serialization.clj b/src/metabase/models/serialization.clj index e5bcb2df484e8441954101d8ba126ce87d7f7817..776b8570a03f21c0398f67d8de775f8205659a06 100644 --- a/src/metabase/models/serialization.clj +++ b/src/metabase/models/serialization.clj @@ -857,7 +857,7 @@ "dataset" :model/Card "collection" :metabase.models.collection/Collection "database" :metabase.models.database/Database - "dashboard" :metabase.models.dashboard/Dashboard + "dashboard" :model/Dashboard "table" :metabase.models.table/Table}) (defn- export-viz-link-card diff --git a/test/metabase/api/public_test.clj b/test/metabase/api/public_test.clj index d254355d4b49df32a067511a7382bd5bae521637..c371625fc577b95a4a5e88ca717274763d1925ac 100644 --- a/test/metabase/api/public_test.clj +++ b/test/metabase/api/public_test.clj @@ -166,7 +166,8 @@ :widget-type "category" :required true}}}}}] (is (= {(mt/id :categories :name) {:values (t2/select-one-fn (comp count :values) - 'FieldValues :field_id category-name-id) + 'FieldValues :field_id category-name-id + :type :full) :human_readable_values [] :field_id category-name-id}} (-> (:param_values (#'api.public/public-card :id (u/the-id card))) diff --git a/test/metabase/models/card_test.clj b/test/metabase/models/card_test.clj index f7f49152bbf261e07f843ad7811598f4bd628b51..60dffd7fd8058a8a23a1657a3e8630c91e04cdd5 100644 --- a/test/metabase/models/card_test.clj +++ b/test/metabase/models/card_test.clj @@ -484,7 +484,7 @@ :parameterized_object_type :card :parameterized_object_id card-id-2 :parameter_id "_CATEGORY_NAME_"}] - (t2/select 'ParameterCard :card_id source-card-id))) + (t2/select 'ParameterCard :card_id source-card-id {:order-by [[:parameterized_object_id :asc]]}))) (t2/delete! :model/Card :id source-card-id) (is (= [] (t2/select 'ParameterCard :card_id source-card-id))))))) @@ -519,7 +519,7 @@ :parameter_id "param_2" :parameterized_object_type :dashboard :parameterized_object_id (:id dashboard)}] - (t2/select ParameterCard :card_id source-card-id))) + (t2/select ParameterCard :card_id source-card-id {:order-by [[:parameter_id :asc]]}))) ;; update card with removing the products.category (testing "on update result_metadata" (t2/update! :model/Card source-card-id diff --git a/test/metabase/test/util.clj b/test/metabase/test/util.clj index 00bf9023f2a0177ac648920f2234c4fcb3f40989..014b9b5298ff98a60caa1ee4065db6077f37a3c0 100644 --- a/test/metabase/test/util.clj +++ b/test/metabase/test/util.clj @@ -17,9 +17,6 @@ [metabase.models :refer [Card Collection - Dashboard - DashboardCard - DashboardCardSeries Database Dimension Field @@ -123,17 +120,17 @@ (fn [_] {:name (tu.random/random-name) :color "#ABCDEF"}) - Dashboard + :model/Dashboard (fn [_] {:creator_id (rasta-id) :name (tu.random/random-name)}) - DashboardCard + :model/DashboardCard (fn [_] {:row 0 :col 0 :size_x 4 :size_y 4}) - DashboardCardSeries + :model/DashboardCardSeries (constantly {:position 0}) Database