diff --git a/resources/migrations/037_add_card_parameters_column.yaml b/resources/migrations/037_add_card_parameters_column.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e3632403b213150bdb1f637e71c934fd43b39d66 --- /dev/null +++ b/resources/migrations/037_add_card_parameters_column.yaml @@ -0,0 +1,20 @@ +databaseChangeLog: + - changeSet: + id: 37 + author: agilliland + changes: + - addColumn: + tableName: report_card + columns: + - column: + name: parameters + type: text + constraints: + nullable: true + deferrable: false + initiallyDeferred: false + - addNotNullConstraint: + columnDataType: text + columnName: parameters + defaultNullValue: '[]' + tableName: report_card diff --git a/resources/migrations/liquibase.json b/resources/migrations/liquibase.json index 2ed788d166dacfcefb7a2a2a9861001a7d9c709e..83948e5af39e64296694e525a20cb5a9a35744f8 100644 --- a/resources/migrations/liquibase.json +++ b/resources/migrations/liquibase.json @@ -34,6 +34,7 @@ {"include": {"file": "migrations/033_add_physical_schema_tables.yaml"}}, {"include": {"file": "migrations/034_add_pulse_channel_enabled_field.yaml"}}, {"include": {"file": "migrations/035_modify_setting_value_length.yaml"}}, - {"include": {"file": "migrations/036_add_dashboard_filters_columns.yaml"}} + {"include": {"file": "migrations/036_add_dashboard_filters_columns.yaml"}}, + {"include": {"file": "migrations/037_add_card_parameters_column.yaml"}} ] } diff --git a/src/metabase/api/card.clj b/src/metabase/api/card.clj index e2ea51fceb4948e5621fd09697ab6bed2ecc8c24..d13fda5c564bcbe92e38e25b834ed1f68d6db6b7 100644 --- a/src/metabase/api/card.clj +++ b/src/metabase/api/card.clj @@ -144,19 +144,14 @@ (defendpoint POST "/" "Create a new `Card`." - [:as {{:keys [dataset_query description display name public_perms visualization_settings]} :body}] - {name [Required NonEmptyString] - public_perms [Required PublicPerms] - display [Required NonEmptyString]} - (->> (db/insert! Card - :creator_id *current-user-id* - :dataset_query dataset_query - :description description - :display display - :name name - :public_perms public_perms - :visualization_settings visualization_settings) - (events/publish-event :card-create))) + [:as {{:keys [dataset_query display name parameters public_perms visualization_settings], :as body} :body}] + {dataset_query [Required Dict] + display [Required NonEmptyString] + name [Required NonEmptyString] + parameters [Required ArrayOfMaps] + public_perms [Required PublicPerms] + visualization_settings [Required Dict]} + (card/create-card body *current-user-id*)) (defendpoint GET "/:id" "Get `Card` with ID." @@ -170,32 +165,25 @@ (defendpoint PUT "/:id" "Update a `Card`." - [id :as {{:keys [dataset_query description display name public_perms visualization_settings archived], :as body} :body}] - {name NonEmptyString - public_perms PublicPerms - display NonEmptyString - visualization_settings Dict - archived Boolean} + [id :as {{:keys [archived dataset_query display name parameters public_perms visualization_settings], :as body} :body}] + {archived [Boolean] + dataset_query [Required Dict] + display [Required NonEmptyString] + name [Required NonEmptyString] + parameters [Required ArrayOfMaps] + public_perms [Required PublicPerms] + visualization_settings [Required Dict]} (let-404 [card (Card id)] (write-check card) - (db/update-non-nil-keys! Card id - :dataset_query dataset_query - :description description - :display display - :name name - :public_perms public_perms - :visualization_settings visualization_settings - :archived archived) - (let [event (cond - ;; card was archived - (and archived - (not (:archived card))) :card-archive - ;; card was unarchived - (and (not (nil? archived)) - (not archived) - (:archived card)) :card-unarchive - :else :card-update)] - (events/publish-event event (assoc (Card id) :actor_id *current-user-id*))))) + (cond + ;; card is being archived + (and archived + (not (:archived card))) (card/archive-card id *current-user-id*) + ;; card is being unarchived + (and (not (nil? archived)) + (not archived) + (:archived card)) (card/unarchive-card id *current-user-id*) + :else (card/update-card body *current-user-id*)))) (defendpoint DELETE "/:id" "Delete a `Card`." diff --git a/src/metabase/models/card.clj b/src/metabase/models/card.clj index 987c036823cdef47d970ca484d7711135f476b72..a3b66f8e546c943612e7f800d866342f9d2aece6 100644 --- a/src/metabase/models/card.clj +++ b/src/metabase/models/card.clj @@ -1,6 +1,7 @@ (ns metabase.models.card (:require [medley.core :as m] [metabase.db :as db] + [metabase.events :as events] (metabase.models [card-label :refer [CardLabel]] [dependency :as dependency] [interface :as i] @@ -45,6 +46,62 @@ (db/cascade-delete! 'CardLabel :card_id id)) +;;; ## ---------------------------------------- PERSISTENCE FUNCTIONS ---------------------------------------- + + +(defn create-card + "Create a `Card`" + [{:keys [dataset_query description display name parameters public_perms visualization_settings], :as card} user-id] + {:pre [(map? card) + (u/nil-or-sequence-of-maps? parameters) + (integer? user-id)]} + (->> (db/insert! Card + :creator_id user-id + :dataset_query dataset_query + :description description + :display display + :name name + :public_perms public_perms + :visualization_settings visualization_settings) + (events/publish-event :card-create))) + +(defn update-card + "Update a `Card`" + [{:keys [dataset_query description display id name parameters public_perms visualization_settings], :as card} user-id] + {:pre [(map? card) + (integer? id) + (u/nil-or-sequence-of-maps? parameters) + (integer? user-id)]} + (db/update-non-nil-keys! Card id + :dataset_query dataset_query + :description description + :display display + :name name + :parameters parameters + :public_perms public_perms + :visualization_settings visualization_settings) + (u/prog1 (Card id) + (events/publish-event :card-update (assoc <> :actor_id user-id)))) + +(defn archive-card + "Archive a `Card`" + [card-id user-id] + {:pre [(integer? card-id) + (integer? user-id)]} + (db/update! Card card-id :archived true) + (u/prog1 (Card card-id) + (events/publish-event :card-archive (assoc <> :actor_id user-id)))) + +(defn unarchive-card + "Unarchive a `Card`" + [card-id user-id] + {:pre [(integer? card-id) + (integer? user-id)]} + (db/update! Card card-id :archived false) + (u/prog1 (Card card-id) + (events/publish-event :card-unarchive (assoc <> :actor_id user-id)))) + + ;;; ## ---------------------------------------- REVISIONS ---------------------------------------- @@ -71,7 +128,12 @@ i/IEntity (merge i/IEntityDefaults {:hydration-keys (constantly [:card]) - :types (constantly {:display :keyword, :query_type :keyword, :dataset_query :json, :visualization_settings :json, :description :clob}) + :types (constantly {:description :clob + :display :keyword + :dataset_query :json + :parameters :json + :query_type :keyword + :visualization_settings :json}) :timestamped? (constantly true) :can-read? i/publicly-readable? :can-write? i/publicly-writeable?