diff --git a/index.html b/index.html index def0c8f..09feefc 100644 --- a/index.html +++ b/index.html @@ -20052,7 +20052,6 @@
(defn- singular-cell-dimensions + (m/update-existing :visualization #(instantiate-visualization % bindings available-metrics))))
Return the set of ids referenced in a cell query
+(defn- singular-cell-dimension-field-ids [{:keys [cell-query]}] (letfn [(collect-dimensions [[op & args]] (case (some-> op qp.util/normalize-token) @@ -20409,7 +20408,7 @@Important Libraries
;; Why do we need (or do we) the last remove form? :filters (->> dashboard_filters (mapcat (comp :matches grounded-dimensions)) - (remove (comp (singular-cell-dimensions root) id-or-name))) + (remove (comp (singular-cell-dimension-field-ids root) id-or-name))) :cards dashcards)))
(def ^:private ^:const ^Long max-related 8) (def ^:private ^:const ^Long max-cards 15)
Turn entity
into an entry in :related.
Recursively finds key in coll, returns true or false
-(defn- key-in? - [coll k] - (boolean (let [coll-zip (zip/zipper coll? #(if (map? %) (vals %) %) nil coll)] - (loop [x coll-zip] - (when-not (zip/end? x) - (if (k (zip/node x)) true (recur (zip/next x))))))))
(defn- splice-in - [join-statement card-member] - (let [query (get-in card-member [:card :dataset_query :query])] - (if (key-in? query :join-alias) - ;; Always in the top level even if the join-alias is found deep in there - (assoc-in card-member [:card :dataset_query :query :joins] join-statement) - card-member)))
Hack to shove back in joins when they get automagically stripped out by the question decomposition into metrics
-(defn- maybe-enrich-joins + (collect-breakout-fields root question)])))
Hack to shove back in joins when they get automagically stripped out by the question decomposition into metrics
+(defn- preserve-joins [entity dashboard] (if-let [join-statement (get-in entity [:dataset_query :query :joins])] - (update dashboard :dashcards #(map (partial splice-in join-statement) %)) + (letfn [(splice-joins [dashcard] + (cond-> dashcard + (get-in dashcard [:card :dataset_query :query]) + (assoc-in [:card :dataset_query :query :joins] join-statement)))] + (update dashboard :dashcards (partial map splice-joins))) dashboard))
(defn- query-based-analysis [{:keys [entity] :as root} opts {:keys [cell-query cell-url]}] @@ -20711,7 +20701,7 @@Important Libraries
(let [title (tru "A closer look at {0}" (names/cell-title root cell-query))] {:transient_name title :name title})))))] - (maybe-enrich-joins (:entity root) transient-dash)))
(defmethod automagic-analysis Card [card {:keys [cell-query] :as opts}] (let [root (->root card) @@ -44939,7 +44929,7 @@`:abstract?` (default = false)
[n unit] (let [n (if (string? n) (keyword n) n) unit (if (string? unit) (keyword unit) unit)] - (lib.core/describe-relative-datetime n unit)))
Adds an aggregation to query.
+ (lib.core/describe-relative-datetime n unit)))Adds an aggregation to query.
(defn ^:export aggregate [a-query stage-number an-aggregate-clause] (lib.core/aggregate a-query stage-number (js->clj an-aggregate-clause :keywordize-keys true)))
Get the aggregations in a given stage of a query.
@@ -44987,14 +44977,14 @@Returns true if arg is a a ColumnMetadata
+ (fn [node] + (if (and (map? node) (= :mbql/expression-parts (:lib/type node))) + (let [{:keys [operator options args]} node] + #js {:operator (name operator) + :options (clj->js (select-keys options [:case-sensitive :include-current])) + :args (to-array (map #(if (keyword? %) (u/qualified-name %) %) args))}) + node)) + parts)))Returns true if arg is a a ColumnMetadata
(defn ^:export is-column-metadata [arg] (and (map? arg) (= :metadata/column (:lib/type arg))))
Sets boolean-expression
as a filter on query
.
Given a column metadata from eg. [[fieldable-columns]], return it as a legacy JSON field ref.
+ (to-array (lib.equality/mark-selected-columns a-query stage-number vis-columns ret-columns))))Return a sequence of column metadatas for columns returned by the query.
+(defn ^:export returned-columns + [a-query stage-number] + (let [stage (lib.util/query-stage a-query stage-number)] + (->> (lib.metadata.calculation/returned-columns a-query stage-number stage) + (map #(assoc % :selected? true)) + to-array)))
Given a column metadata from eg. [[fieldable-columns]], return it as a legacy JSON field ref.
(defn ^:export legacy-field-ref [column] (-> column @@ -46217,42 +46213,42 @@`:abstract?` (default = false)
(lib.dispatch/dispatch-value x)) :hierarchy lib.hierarchy/hierarchy)
(mr/register! ::display-info - [:map - [:display-name :string] - [:long-display-name {:optional true} :string] + [:map + [:display-name :string] + [:long-display-name {:optional true} :string] ;; for things that have a Table, e.g. a Field - [:table {:optional true} [:maybe [:ref ::display-info]]] + [:table {:optional true} [:maybe [:ref ::display-info]]] ;; these are derived from the `:lib/source`/`:metabase.lib.schema.metadata/column-source`, but instead of using ;; that value directly we're returning a different property so the FE doesn't break if we change those keys in the ;; future, e.g. if we consolidate or split some of those keys. This is all the FE really needs to know. ;; ;; if this is a Column, does it come from a previous stage? - [:is-from-previous-stage {:optional true} [:maybe :boolean]] + [:is-from-previous-stage {:optional true} [:maybe :boolean]] ;; if this is a Column, does it come from a join in this stage? - [:is-from-join {:optional true} [:maybe :boolean]] + [:is-from-join {:optional true} [:maybe :boolean]] ;; if this is a Column, is it 'calculated', i.e. does it come from an expression in this stage? - [:is-calculated {:optional true} [:maybe :boolean]] + [:is-calculated {:optional true} [:maybe :boolean]] ;; if this is a Column, is it an implicitly joinable one? I.e. is it from a different table that we have not ;; already joined, but could implicitly join against? - [:is-implicitly-joinable {:optional true} [:maybe :boolean]] + [:is-implicitly-joinable {:optional true} [:maybe :boolean]] ;; For the `:table` field of a Column, is this the source table, or a joined table? - [:is-source-table {:optional true} [:maybe :boolean]] + [:is-source-table {:optional true} [:maybe :boolean]] ;; does this column occur in the breakout clause? - [:is-breakout-column {:optional true} [:maybe :boolean]] + [:is-breakout-column {:optional true} [:maybe :boolean]] ;; does this column occur in the order-by clause? - [:is-order-by-column {:optional true} [:maybe :boolean]] + [:is-order-by-column {:optional true} [:maybe :boolean]] ;; for joins - [:name {:optional true} :string] + [:name {:optional true} :string] ;; for aggregation operators - [:column-name {:optional true} :string] - [:description {:optional true} :string] - [:short-name {:optional true} :string] - [:requires-column {:optional true} :boolean] - [:selected {:optional true} :boolean] + [:column-name {:optional true} :string] + [:description {:optional true} :string] + [:short-name {:optional true} :string] + [:requires-column {:optional true} :boolean] + [:selected {:optional true} :boolean] ;; for binning and bucketing - [:default {:optional true} :boolean] + [:default {:optional true} :boolean] ;; for order by - [:direction {:optional true} [:enum :asc :desc]]])
(mu/defn display-info :- ::display-info "Given some sort of Cljs object, return a map with the info you'd need to implement UI for it. This is mostly meant to power the Frontend JavaScript UI; in JS, results will be converted to plain JavaScript objects, so avoid returning @@ -46298,7 +46294,9 @@`:abstract?` (default = false)
{:is-from-previous-stage (= source :source/previous-stage) :is-from-join (= source :source/joins) :is-calculated (= source :source/expressions) - :is-implicitly-joinable (= source :source/implicitly-joinable)}) + :is-implicitly-joinable (= source :source/implicitly-joinable) + :is-aggregation (= source :source/aggregations) + :is-breakout (= source :source/breakouts)}) (when-some [selected (:selected? x-metadata)] {:selected selected}) (select-keys x-metadata [:breakout-position :order-by-position :filter-positions]))))
Given a list of dashcards, remove any dashcard that references cards that are either archived or not exist.
+(defn- remove-invalid-dashcards + [dashcards] + (let [card-ids (set (keep :card_id dashcards)) + active-card-ids (when-let [card-ids (seq card-ids)] + (t2/select-pks-set :model/Card :id [:in card-ids] :archived false)) + inactive-card-ids (set/difference card-ids active-card-ids)] + (remove #(contains? inactive-card-ids (:card_id %)) dashcards)))
(defmethod revision/revert-to-revision! :model/Dashboard [_model dashboard-id _user-id serialized-dashboard] ;; Update the dashboard description / name / permissions (t2/update! :model/Dashboard dashboard-id (dissoc serialized-dashboard :cards :tabs)) ;; Now update the tabs and cards as needed - (let [serialized-cards (:cards serialized-dashboard) + (let [serialized-dashcards (:cards serialized-dashboard) current-tabs (t2/select-fn-vec #(dissoc (t2.realize/realize %) :created_at :updated_at :entity_id :dashboard_id) :model/DashboardTab :dashboard_id dashboard-id) {:keys [old->new-tab-id]} (dashboard-tab/do-update-tabs! dashboard-id current-tabs (:tabs serialized-dashboard)) - serialized-cards (cond->> serialized-cards + serialized-dashcards (cond->> serialized-dashcards + true + remove-invalid-dashcards ;; in case reverting result in new tabs being created, ;; we need to remap the tab-id (seq old->new-tab-id) @@ -54584,7 +54591,7 @@`:abstract?` (default = false)
(if-let [new-tab-id (get old->new-tab-id (:dashboard_tab_id card))] (assoc card :dashboard_tab_id new-tab-id) card))))] - (revert-dashcards dashboard-id serialized-cards)) + (revert-dashcards dashboard-id serialized-dashcards)) serialized-dashboard)
(defmethod revision/diff-strings :model/Dashboard [_model prev-dashboard dashboard] @@ -55114,11 +55121,11 @@`:abstract?` (default = false)
(when (seq dashboard-cards) (t2/with-transaction [_conn] (let [dashboard-card-ids (t2/insert-returning-pks! - DashboardCard - (for [dashcard dashboard-cards] - (merge {:parameter_mappings [] - :visualization_settings {}} - (dissoc dashcard :id :created_at :updated_at :entity_id :series :card :collection_authority_level))))] + DashboardCard + (for [dashcard dashboard-cards] + (merge {:parameter_mappings [] + :visualization_settings {}} + (dissoc dashcard :id :created_at :updated_at :entity_id :series :card :collection_authority_level))))] ;; add series to the DashboardCard (update-dashboard-cards-series! (zipmap dashboard-card-ids (map #(get % :series []) dashboard-cards))) ;; return the full DashboardCard