diff --git a/resources/automagic_dashboards/field/Country.yaml b/resources/automagic_dashboards/field/Country.yaml
index fa493bb6e66d221a2461f005f143cc0bd20b9690..9cd91ba6b52cd88f3fc5c87d0a139ea99e38510d 100644
--- a/resources/automagic_dashboards/field/Country.yaml
+++ b/resources/automagic_dashboards/field/Country.yaml
@@ -38,7 +38,7 @@ groups:
   - Overview:
       title: Overview
   - Breakdowns:
-      title: How [[this]] are distributed
+      title: How the [[this]] is distributed
 cards:
   - Count:
       title: Count
@@ -60,7 +60,7 @@ cards:
       group: Overview
       width: 6
   - Distribution:
-      title: Distribution of [[this]]
+      title: How the [[this]] is distributed
       visualization:
         map:
           map.type: region
diff --git a/resources/automagic_dashboards/field/DateTime.yaml b/resources/automagic_dashboards/field/DateTime.yaml
index 8af35916858fee9120726dc52d316e1fb9e77ef5..346f802e8882b3a25a9d9b26f883e325bdf79d9d 100644
--- a/resources/automagic_dashboards/field/DateTime.yaml
+++ b/resources/automagic_dashboards/field/DateTime.yaml
@@ -32,9 +32,9 @@ groups:
   - Overview:
       title: Overview
   - Breakdowns:
-      title: How [[this]] is distributed
+      title: How the [[this]] is distributed
   - Seasonality:
-      title: Seasonal patterns in [[this]]
+      title: Seasonal patterns in the [[this]]
 cards:
   - Count:
       title: Count
diff --git a/resources/automagic_dashboards/field/GenericField.yaml b/resources/automagic_dashboards/field/GenericField.yaml
index 71d7143394f2565736faabb1212144b36bedb305..fe5396453e26c0e6edfa2e0a58b5e0d5c94f9a8b 100644
--- a/resources/automagic_dashboards/field/GenericField.yaml
+++ b/resources/automagic_dashboards/field/GenericField.yaml
@@ -38,7 +38,7 @@ groups:
   - Overview:
       title: Overview
   - Breakdowns:
-      title: How [[this]] are distributed
+      title: How the [[this]] is distributed
 cards:
   - Count:
       title: Count
@@ -60,7 +60,7 @@ cards:
       group: Overview
       width: 6
   - Distribution:
-      title: How [[this]] is distributed
+      title: How the [[this]] is distributed
       visualization: bar
       metrics: Count
       dimensions: this
@@ -68,12 +68,13 @@ cards:
       width: 12
   - ByNumber:
       title: "[[GenericNumber]] by [[this]]"
-      visualization: line
+      visualization: bar
       metrics:
       - Sum
       - Avg
       dimensions: this
       group: Breakdowns
+      height: 8
   - Crosstab:
       title: "[[this]] by [[GenericCategoryMedium]]"
       visualization: table
diff --git a/resources/automagic_dashboards/field/Number.yaml b/resources/automagic_dashboards/field/Number.yaml
index 937e04ec5c0dfeb17a1e3476c76ea85495433b9a..01a3864a03780028d76f0b91e6068583ceceec84 100644
--- a/resources/automagic_dashboards/field/Number.yaml
+++ b/resources/automagic_dashboards/field/Number.yaml
@@ -38,11 +38,11 @@ groups:
   - Overview:
       title: Overview
   - Breakdowns:
-      title: How [[this]] is distributed across categories
+      title: How the [[this]] is distributed across categories
   - Seasonality:
-      title: How [[this]] changes with time
+      title: How the [[this]] changes with time
   - Geographical:
-      title: How [[this]] is distributed geographically
+      title: How the [[this]] is distributed geographically
 cards:
   - Count:
       title: Count
@@ -75,7 +75,7 @@ cards:
       group: Overview
       width: 9
   - Distribution:
-      title: How [[this]] is distributed
+      title: How the [[this]] is distributed
       visualization: bar
       metrics: Count
       dimensions:
diff --git a/resources/automagic_dashboards/field/State.yaml b/resources/automagic_dashboards/field/State.yaml
index 2df61dca59ed4c93b5e5eb2c57ca5ff746e10690..f6c19178b715e7573c616ae8d185fa75316a7842 100644
--- a/resources/automagic_dashboards/field/State.yaml
+++ b/resources/automagic_dashboards/field/State.yaml
@@ -38,7 +38,7 @@ groups:
   - Overview:
       title: Overview
   - Breakdowns:
-      title: How [[this]] are distributed
+      title: How the [[this]] is distributed
 cards:
   - Count:
       title: Count
diff --git a/resources/automagic_dashboards/metric/GenericMetric.yaml b/resources/automagic_dashboards/metric/GenericMetric.yaml
index 46287df7733281d6a26caeae4dc995a39a2901e2..f76fa1582a60e4a626713555d609a7a48f3df03d 100644
--- a/resources/automagic_dashboards/metric/GenericMetric.yaml
+++ b/resources/automagic_dashboards/metric/GenericMetric.yaml
@@ -1,5 +1,5 @@
-title: A look at your [[this]]
-transient_title: Here's a quick look at your [[this]]
+title: A look at the [[this]]
+transient_title: Here's a quick look at the [[this]]
 description: How it's distributed across time and other categories.
 applies_to: GenericTable
 metrics:
@@ -35,15 +35,17 @@ dimensions:
       field_type: GenericTable.ZipCode
 groups:
   - Periodicity:
-      title: "[[this]] over time"
+      title: The [[this]] over time
   - Geographical:
-      title: "[[this]] by location"
+      title: The [[this]] by location
   - Categories:
-      title: How [[this]] is distributed across different categories
+      title: How this metric is distributed across different categories
   - Numbers:
-      title: How [[this]] is distributed across different numbers
-  - LargeCategories:
-      title: Top and bottom [[this]]
+      title: How this metric is distributed across different numbers
+  - LargeCategoriesTop:
+      title: Top 5 per category
+  - LargeCategoriesBottom:
+      title: Bottom 5 per category
 dashboard_filters:
   - Timestamp
   - State
@@ -119,9 +121,11 @@ cards:
           map.region: us_states
   - ByNumber:
       group: Numbers
-      title: How [[this]] is distributed across [[GenericNumber]]
+      title: "[[this]] by [[GenericNumber]]"
       metrics: this
-      dimensions: GenericNumber
+      dimensions:
+        - GenericNumber:
+            aggregation: default
       visualization: bar
   - ByCategoryMedium:
       group: Categories
@@ -151,7 +155,7 @@ cards:
       order_by:
         this: descending
   - ByCategoryLargeTop:
-      group: LargeCategories
+      group: LargeCategoriesTop
       title: "[[this]] per [[GenericCategoryLarge]], top 5"
       metrics: this
       dimensions: GenericCategoryLarge
@@ -160,7 +164,7 @@ cards:
         this: descending
       limit: 5
   - ByCategoryLargeBottom:
-      group: LargeCategories
+      group: LargeCategoriesBottom
       title: "[[this]] per [[GenericCategoryLarge]], bottom 5"
       metrics: this
       dimensions: GenericCategoryLarge
diff --git a/resources/automagic_dashboards/question/GenericQuestion.yaml b/resources/automagic_dashboards/question/GenericQuestion.yaml
index a7d0cfaa713b033f4af334319fbefdb4fbc5fcaa..ad7a7b8b067df81e1decbd24ceb1b06efb700844 100644
--- a/resources/automagic_dashboards/question/GenericQuestion.yaml
+++ b/resources/automagic_dashboards/question/GenericQuestion.yaml
@@ -1,4 +1,4 @@
 title: "A closer look at your [[this]]"
 transient_title: "Here's a closer look at your [[this]]"
-description: Here is breakdown of metrics and dimensions used in [[this]].
-applies_to: GenericTable
\ No newline at end of file
+description: A closer look at the metrics and dimensions used in this saved question.
+applies_to: GenericTable
diff --git a/resources/automagic_dashboards/table/GenericTable.yaml b/resources/automagic_dashboards/table/GenericTable.yaml
index cb9744168ce4201e9fcf07687c4cd9c450e53fae..d06fc4986ef3c61f0a399bb5782081e23fb1c5ef 100644
--- a/resources/automagic_dashboards/table/GenericTable.yaml
+++ b/resources/automagic_dashboards/table/GenericTable.yaml
@@ -20,10 +20,6 @@ dimensions:
   - Source:
       field_type: GenericTable.Source
       score: 100
-  - GenericCategorySmall:
-      field_type: GenericTable.Category
-      score: 80
-      max_cardinality: 5
   - GenericCategoryMedium:
       field_type: GenericTable.Category
       score: 75
@@ -91,13 +87,13 @@ groups:
 - Overview:
     title: Summary
 - Singletons:
-    title: These are the same for all your [[this]]
+    title: These are the same for all your [[this.short-name]]
 - ByTime:
-    title: "[[this]] across time"
+    title: "These [[this.short-name]] across time"
 - Geographical:
-    title: Where your [[this]] are
+    title: Where your [[this.short-name]] are
 - General:
-    title: How [[this]] are distributed
+    title: How these [[this.short-name]] are distributed
 dashboard_filters:
 - Timestamp
 - Date
@@ -112,13 +108,13 @@ dashboard_filters:
 cards:
 # Overview
   - Rowcount:
-      title: Total [[this]]
+      title: Total [[this.short-name]]
       visualization: scalar
       metrics: Count
       score: 100
       group: Overview
   - RowcountLast30Days:
-      title: New [[this]] in the last 30 days
+      title: "[[this.short-name]] added in the last 30 days"
       visualization: scalar
       metrics: Count
       score: 100
@@ -132,7 +128,7 @@ cards:
       group: Overview
 # General
   - NumberDistribution:
-      title: How [[this]] are distributed across [[GenericNumber]]
+      title: "[[this.short-name]] by [[GenericNumber]]"
       dimensions:
         - GenericNumber:
             aggregation: default
@@ -141,7 +137,7 @@ cards:
       score: 90
       group: General
   - CountByCategoryMedium:
-      title: "[[this]] per [[GenericCategoryMedium]]"
+      title: "[[this.short-name]] per [[GenericCategoryMedium]]"
       dimensions: GenericCategoryMedium
       metrics: Count
       visualization: row
@@ -151,7 +147,7 @@ cards:
       order_by:
         - Count: descending
   - CountByCategoryLarge:
-      title: "[[this]] per [[GenericCategoryLarge]]"
+      title: "[[this.short-name]] per [[GenericCategoryLarge]]"
       dimensions: GenericCategoryLarge
       metrics: Count
       visualization: table
@@ -162,7 +158,7 @@ cards:
         - Count: descending
 # Geographical
   - CountByCountry:
-      title: "[[this]] per country"
+      title: "[[this.short-name]] per country"
       metrics: Count
       dimensions: Country
       score: 90
@@ -173,7 +169,7 @@ cards:
       group: Geographical
       height: 6
   - CountByState:
-      title: "[[this]] per state"
+      title: "[[this.short-name]] per state"
       metrics: Count
       dimensions: State
       score: 90
@@ -184,7 +180,7 @@ cards:
       group: Geographical
       height: 6
   - CountByCoords:
-      title: "[[this]] by coordinates"
+      title: "[[this.short-name]] by coordinates"
       metrics: Count
       dimensions:
         - Long
@@ -195,42 +191,42 @@ cards:
       height: 6
 # By Time
   - CountByJoinDate:
-      title: "[[this]] that have joined over time"
+      title: "[[this.short-name]] that have joined over time"
       visualization: line
       dimensions: JoinTimestamp
       metrics: Count
       score: 90
       group: ByTime
   - CountByJoinDate:
-      title: "[[this]] that have joined over time"
+      title: "[[this.short-name]] that have joined over time"
       visualization: line
       dimensions: JoinDate
       metrics: Count
       score: 90
       group: ByTime
   - CountByCreateDate:
-      title: New [[this]] over time
+      title: New [[this.short-name]] over time
       visualization: line
       dimensions: CreateTimestamp
       metrics: Count
       score: 90
       group: ByTime
   - CountByCreateDate:
-      title: New [[this]] over time
+      title: New [[this.short-name]] over time
       visualization: line
       dimensions: CreateDate
       metrics: Count
       score: 90
       group: ByTime
   - CountByTimestamp:
-      title: "[[this]] by [[Timestamp]]"
+      title: "[[this.short-name]] by [[Timestamp]]"
       visualization: line
       dimensions: Timestamp
       metrics: Count
       score: 20
       group: ByTime
   - CountByTimestamp:
-      title: "[[this]] by [[Timestamp]]"
+      title: "[[this.short-name]] by [[Timestamp]]"
       visualization: line
       dimensions: Date
       metrics: Count
@@ -371,7 +367,7 @@ cards:
       group: ByTime
       x_label: "[[Timestamp]]"
   - DayOfWeekCreateDate:
-      title: Weekdays when new [[this]] were added
+      title: Weekdays when [[this.short-name]] were added
       visualization: bar
       dimensions:
         - CreateTimestamp:
@@ -381,7 +377,7 @@ cards:
       group: ByTime
       x_label: Created At by day of the week
   - DayOfWeekCreateDate:
-      title: Weekdays when new [[this]] were added
+      title: Weekdays when [[this.short-name]] were added
       visualization: bar
       dimensions:
         - CreateDate:
@@ -391,7 +387,7 @@ cards:
       group: ByTime
       x_label: Created At by day of the week
   - HourOfDayCreateDate:
-      title: Hours when new [[this]] were added
+      title: Hours when [[this.short-name]] were added
       visualization: bar
       dimensions:
       - CreateTimestamp:
@@ -401,7 +397,7 @@ cards:
       group: ByTime
       x_label: Created At by hour of the day
   - HourOfDayCreateDate:
-      title: Hours when new [[this]] were added
+      title: Hours when [[this.short-name]] were added
       visualization: bar
       dimensions:
       - CreateTime:
@@ -411,7 +407,7 @@ cards:
       group: ByTime
       x_label: Created At by hour of the day
   - DayOfMonthCreateDate:
-      title: Days when new [[this]] were added
+      title: Days when [[this.short-name]] were added
       visualization: bar
       dimensions:
         - CreateTimestamp:
@@ -421,7 +417,7 @@ cards:
       group: ByTime
       x_label: Created At by day of the month
   - DayOfMonthCreateDate:
-      title: Days when new [[this]] were added
+      title: Days when [[this.short-name]] were added
       visualization: bar
       dimensions:
         - CreateDate:
@@ -431,7 +427,7 @@ cards:
       group: ByTime
       x_label: Created At by day of the month
   - MonthOfYearCreateDate:
-      title: Months when new [[this]] were added
+      title: Months when [[this.short-name]] were added
       visualization: bar
       dimensions:
         - CreateTimestamp:
@@ -441,7 +437,7 @@ cards:
       group: ByTime
       x_label: Created At by month of the year
   - MonthOfYearCreateDate:
-      title: Months when new [[this]] were added
+      title: Months when [[this.short-name]] were added
       visualization: bar
       dimensions:
         - CreateDate:
@@ -451,7 +447,7 @@ cards:
       group: ByTime
       x_label: Created At by month of the year
   - QuerterOfYearCreateDate:
-      title: Quarters when new [[this]] were added
+      title: Quarters when [[this.short-name]] were added
       visualization: bar
       dimensions:
         - CreateTimestamp:
@@ -461,7 +457,7 @@ cards:
       group: ByTime
       x_label: Created At by quarter of the year
   - QuerterOfYearCreateDate:
-      title: Quarters when new [[this]] were added
+      title: Quarters when [[this.short-name]] were added
       visualization: bar
       dimensions:
         - CreateDate:
@@ -471,7 +467,7 @@ cards:
       group: ByTime
       x_label: Created At by quarter of the year
   - DayOfWeekJoinDate:
-      title: Weekdays when [[this]] joined
+      title: Weekdays when [[this.short-name]] joined
       visualization: bar
       dimensions:
         - JoinTimestamp:
@@ -481,7 +477,7 @@ cards:
       group: ByTime
       x_label: Join date by day of the week
   - DayOfWeekJoinDate:
-      title: Weekdays when [[this]] joined
+      title: Weekdays when [[this.short-name]] joined
       visualization: bar
       dimensions:
         - JoinDate:
@@ -491,7 +487,7 @@ cards:
       group: ByTime
       x_label: Join date by day of the week
   - HourOfDayJoinDate:
-      title: Hours when [[this]] joined
+      title: Hours when [[this.short-name]] joined
       visualization: bar
       dimensions:
       - JoinTimestamp:
@@ -501,7 +497,7 @@ cards:
       group: ByTime
       x_label: Join date by hour of the day
   - HourOfDayJoinDate:
-      title: Hours when [[this]] joined
+      title: Hours when [[this.short-name]] joined
       visualization: bar
       dimensions:
       - JoinTime:
@@ -511,7 +507,7 @@ cards:
       group: ByTime
       x_label: Join date by hour of the day
   - DayOfMonthJoinDate:
-      title: Days of the month when [[this]] joined
+      title: Days of the month when [[this.short-name]] joined
       visualization: bar
       dimensions:
         - JoinTimestamp:
@@ -521,7 +517,7 @@ cards:
       group: ByTime
       x_label: Join date by day of the month
   - DayOfMonthJoinDate:
-      title: Days of the month when [[this]] joined
+      title: Days of the month when [[this.short-name]] joined
       visualization: bar
       dimensions:
         - JoinDate:
@@ -531,7 +527,7 @@ cards:
       group: ByTime
       x_label: Join date by day of the month
   - MonthOfYearJoinDate:
-      title: Months when [[this]] joined
+      title: Months when [[this.short-name]] joined
       visualization: bar
       dimensions:
         - JoinTimestamp:
@@ -541,7 +537,7 @@ cards:
       group: ByTime
       x_label: Join date by month of the year
   - MonthOfYearJoinDate:
-      title: Months when [[this]] joined
+      title: Months when [[this.short-name]] joined
       visualization: bar
       dimensions:
         - JoinDate:
@@ -551,7 +547,7 @@ cards:
       group: ByTime
       x_label: Join date by month of the year
   - QuerterOfYearJoinDate:
-      title: Quarters when [[this]] joined
+      title: Quarters when [[this.short-name]] joined
       visualization: bar
       dimensions:
         - JoinTimestamp:
@@ -561,7 +557,7 @@ cards:
       group: ByTime
       x_label: Join date by quarter of the year
   - QuerterOfYearJoinDate:
-      title: Quarters when [[this]] joined
+      title: Quarters when [[this.short-name]] joined
       visualization: bar
       dimensions:
         - JoinDate:
diff --git a/resources/automagic_dashboards/table/UserTable.yaml b/resources/automagic_dashboards/table/UserTable.yaml
index 1844a20527cb0c73019e8a347b9a960085c61c08..b6297d02f83611b6ea7cdda861c6dbfd49c57668 100644
--- a/resources/automagic_dashboards/table/UserTable.yaml
+++ b/resources/automagic_dashboards/table/UserTable.yaml
@@ -23,14 +23,11 @@ dimensions:
 - JoinDate:
     field_type: Date
     score: 30
-- Source:
-    field_type: Source
 - GenericNumber:
     field_type: GenericTable.Number
     score: 80
 - Source:
     field_type: GenericTable.Source
-    score: 100
 - GenericCategoryMedium:
     field_type: GenericTable.Category
     score: 75
@@ -54,9 +51,9 @@ groups:
 - Overview:
     title: Overview
 - Geographical:
-    title: Where these [[this]] are
+    title: Where these [[this.short-name]] are
 - General:
-    title: How these [[this]] are distributed
+    title: How these [[this.short-name]] are distributed
 dashboard_filters:
 - JoinDate
 - GenericCategoryMedium
@@ -66,7 +63,7 @@ dashboard_filters:
 cards:
 # Overview
   - Rowcount:
-      title: Total [[this]]
+      title: Total [[this.short-name]]
       visualization: scalar
       metrics: Count
       score: 100
@@ -74,7 +71,7 @@ cards:
       width: 5
       height: 3
   - RowcountLast30Days:
-      title: New [[this]] in the last 30 days
+      title: New [[this.short-name]] in the last 30 days
       visualization: scalar
       metrics: Count
       score: 100
@@ -84,8 +81,7 @@ cards:
       height: 3
   - NewUsersByMonth:
       visualization: line
-      title: New [[this]] per month
-      description: The number of new [[this]] each month
+      title: New [[this.short-name]] per month
       dimensions: JoinDate
       metrics: Count
       score: 100
@@ -94,7 +90,7 @@ cards:
       height: 7
 # Geographical
   - CountByCountry:
-      title: Number of [[this]] per country
+      title: Per country
       metrics: Count
       dimensions: Country
       score: 90
@@ -104,7 +100,7 @@ cards:
           map.region: world_countries
       group: Geographical
   - CountByState:
-      title: "[[this]] per state"
+      title: "Per state"
       metrics: Count
       dimensions: State
       score: 90
@@ -115,7 +111,7 @@ cards:
           map.region: us_states
       group: Geographical
   - CountByCoords:
-      title: "[[this]] by coordinates"
+      title: "By coordinates"
       metrics: Count
       dimensions:
         - Long
@@ -135,7 +131,7 @@ cards:
       score: 90
       group: General
   - CountByCategoryMedium:
-      title: "[[this]] per [[GenericCategoryMedium]]"
+      title: "Per [[GenericCategoryMedium]]"
       dimensions: GenericCategoryMedium
       metrics: Count
       visualization: row
@@ -144,8 +140,18 @@ cards:
       group: General
       order_by:
         - Count: descending
+  - CountBySource:
+      title: "Per [[Source]]"
+      dimensions: Source
+      metrics: Count
+      visualization: row
+      score: 80
+      height: 8
+      group: General
+      order_by:
+        - Count: descending
   - CountByCategoryLarge:
-      title: "[[this]] per [[GenericCategoryLarge]]"
+      title: "Per [[GenericCategoryLarge]]"
       dimensions: GenericCategoryLarge
       metrics: Count
       visualization: table
diff --git a/src/metabase/automagic_dashboards/core.clj b/src/metabase/automagic_dashboards/core.clj
index d0610e428eced2a73c309e6f916152ca8ce4572c..641b40a1239bbdf57cf9f4c7f7d4775eff205c5e 100644
--- a/src/metabase/automagic_dashboards/core.clj
+++ b/src/metabase/automagic_dashboards/core.clj
@@ -32,10 +32,12 @@
             [metabase.related :as related]
             [metabase.sync.analyze.classify :as classify]
             [metabase.util :as u]
+            [metabase.util.date :as date]
             [puppetlabs.i18n.core :as i18n :refer [tru trs]]
             [ring.util.codec :as codec]
             [schema.core :as s]
-            [toucan.db :as db]))
+            [toucan.db :as db])
+  (:import java.util.TimeZone))
 
 (def ^:private public-endpoint "/auto/dashboard/")
 
@@ -46,57 +48,80 @@
   [root id-or-name]
   (if (->> root :source (instance? (type Table)))
     (Field id-or-name)
-    (let [field (->> root
+    (when-let [field (->> root
                      :source
                      :result_metadata
-                     (some (comp #{id-or-name} :name)))]
+                     (m/find-first (comp #{id-or-name} :name)))]
       (-> field
           (update :base_type keyword)
           (update :special_type keyword)
           field/map->FieldInstance
           (classify/run-classifiers {})))))
 
-(defn- metric->description
-  [root metric]
-  (let [aggregation-clause (-> metric :definition :aggregation first)
-        field              (some->> aggregation-clause
-                                    second
-                                    filters/field-reference->id
-                                    (->field root))]
-    (if field
-      (tru "{0} of {1}" (-> aggregation-clause first name str/capitalize) (:display_name field))
-      (-> aggregation-clause first name str/capitalize))))
+(def ^:private ^{:arglists '([root])} source-name
+  (comp (some-fn :display_name :name) :source))
+
+(def ^:private op->name
+  {:sum       (tru "sum")
+   :avg       (tru "average")
+   :min       (tru "minumum")
+   :max       (tru "maximum")
+   :count     (tru "number")
+   :distinct  (tru "distinct count")
+   :stddev    (tru "standard deviation")
+   :cum-count (tru "cumulative count")
+   :cum-sum   (tru "cumulative sum")})
+
+(def ^:private ^{:arglists '([metric])} saved-metric?
+  (comp #{:metric} qp.util/normalize-token first))
+
+(def ^:private ^{:arglists '([metric])} custom-expression?
+  (comp #{:named} qp.util/normalize-token first))
+
+(def ^:private ^{:arglists '([metric])} adhoc-metric?
+  (complement (some-fn saved-metric? custom-expression?)))
+
+(defn- metric-name
+  [[op & args :as metric]]
+  (cond
+    (adhoc-metric? metric) (-> op qp.util/normalize-token op->name)
+    (saved-metric? metric) (-> args first Metric :name)
+    :else                  (second args)))
 
 (defn- join-enumeration
-  [[x & xs]]
-  (if xs
+  [xs]
+  (if (next xs)
     (tru "{0} and {1}" (str/join ", " (butlast xs)) (last xs))
-    x))
+    (first xs)))
+
+(defn- metric->description
+  [root aggregation-clause]
+  (join-enumeration
+   (for [metric (if (sequential? (first aggregation-clause))
+                  aggregation-clause
+                  [aggregation-clause])]
+     (if (adhoc-metric? metric)
+       (tru "{0} of {1}" (metric-name metric) (or (some->> metric
+                                                           second
+                                                           filters/field-reference->id
+                                                           (->field root)
+                                                           :display_name)
+                                                  (source-name root)))
+       (metric-name metric)))))
 
 (defn- question-description
   [root question]
   (let [aggregations (->> (qp.util/get-in-normalized question [:dataset_query :query :aggregation])
-                          (map (fn [[op arg]]
-                                 (cond
-                                   (-> op qp.util/normalize-token (= :metric))
-                                   (-> arg Metric :name)
-
-                                   arg
-                                   (tru "{0} of {1}" (name op) (->> arg
-                                                                    filters/field-reference->id
-                                                                    (->field root)
-                                                                    :display_name))
-
-                                   :else
-                                   (name op))))
-                          join-enumeration)
+                          (metric->description root))
         dimensions   (->> (qp.util/get-in-normalized question [:dataset_query :query :breakout])
                           (mapcat filters/collect-field-references)
                           (map (comp :display_name
                                      (partial ->field root)
                                      filters/field-reference->id))
                           join-enumeration)]
-    (tru "{0} by {1}" aggregations dimensions)))
+    (if dimensions
+      (tru "{0} by {1}" aggregations dimensions)
+      aggregations)))
 
 (def ^:private ^{:arglists '([x])} encode-base64-json
   (comp codec/base64-encode codecs/str->bytes json/encode))
@@ -112,6 +137,7 @@
    :full-name    (if (isa? (:entity_type table) :entity/GoogleAnalyticsTable)
                    (:display_name table)
                    (tru "{0} table" (:display_name table)))
+   :short-name   (:display_name table)
    :source       table
    :database     (:db_id table)
    :url          (format "%stable/%s" public-endpoint (u/get-id table))
@@ -121,10 +147,11 @@
   [segment]
   (let [table (-> segment :table_id Table)]
     {:entity       segment
-     :full-name    (tru "{0} segment" (:name segment))
+     :full-name    (tru "{0} in the {1} segment" (:display_name table) (:name segment))
+     :short-name   (:display_name table)
      :source       table
      :database     (:db_id table)
-     :query-filter (-> segment :definition :filter)
+     :query-filter [:SEGMENT (u/get-id segment)]
      :url          (format "%ssegment/%s" public-endpoint (u/get-id segment))
      :rules-prefix ["table"]}))
 
@@ -132,7 +159,10 @@
   [metric]
   (let [table (-> metric :table_id Table)]
     {:entity       metric
-     :full-name    (tru "{0} metric" (:name metric))
+     :full-name    (if (:id metric)
+                     (tru "{0} metric" (:name metric))
+                     (:name metric))
+     :short-name   (:name metric)
      :source       table
      :database     (:db_id table)
      ;; We use :id here as it might not be a concrete field but rather one from a nested query which
@@ -145,6 +175,7 @@
   (let [table (field/table field)]
     {:entity       field
      :full-name    (tru "{0} field" (:display_name field))
+     :short-name   (:display_name field)
      :source       table
      :database     (:db_id table)
      ;; We use :id here as it might not be a concrete metric but rather one from a nested query
@@ -176,31 +207,35 @@
                              source-question
                              (assoc :entity_type :entity/GenericTable))
     (native-query? card) (-> card (assoc :entity_type :entity/GenericTable))
-    :else                (-> card ((some-fn :table_id :table-id)) Table)))
+    :else                (-> card (qp.util/get-normalized :table-id) Table)))
 
 (defmethod ->root (type Card)
   [card]
-  {:entity       card
-   :source       (source card)
-   :database     (:database_id card)
-   :query-filter (qp.util/get-in-normalized card [:dataset_query :query :filter])
-   :full-name    (tru "{0} question" (:name card))
-   :url          (format "%squestion/%s" public-endpoint (u/get-id card))
-   :rules-prefix [(if (table-like? card)
-                    "table"
-                    "question")]})
+  (let [source (source card)]
+    {:entity       card
+     :source       source
+     :database     (:database_id card)
+     :query-filter (qp.util/get-in-normalized card [:dataset_query :query :filter])
+     :full-name    (tru "\"{0}\" question" (:name card))
+     :short-name   (source-name {:source source})
+     :url          (format "%squestion/%s" public-endpoint (u/get-id card))
+     :rules-prefix [(if (table-like? card)
+                      "table"
+                      "question")]}))
 
 (defmethod ->root (type Query)
   [query]
-  (let [source   (source query)]
+  (let [source (source query)]
     {:entity       query
      :source       source
      :database     (:database-id query)
+     :query-filter (qp.util/get-in-normalized query [:dataset_query :query :filter])
      :full-name    (cond
                      (native-query? query) (tru "Native query")
                      (table-like? query)   (-> source ->root :full-name)
                      :else                 (question-description {:source source} query))
-     :url          (format "%sadhoc/%s" public-endpoint (encode-base64-json query))
+     :short-name   (source-name {:source source})
+     :url          (format "%sadhoc/%s" public-endpoint (encode-base64-json (:dataset_query query)))
      :rules-prefix [(if (table-like? query)
                       "table"
                       "question")]}))
@@ -349,8 +384,13 @@
                                  bindings)
                           (comp first #(filter-tables % tables) rules/->entity)
                           identity)]
-    (str/replace s #"\[\[(\w+)\]\]" (fn [[_ identifier]]
-                                     (->reference template-type (bindings identifier))))))
+    (str/replace s #"\[\[(\w+)(?:\.([\w\-]+))?\]\]"
+                 (fn [[_ identifier attribute]]
+                   (let [entity    (bindings identifier)
+                         attribute (some-> attribute qp.util/normalize-token)]
+                     (or (and (ifn? entity) (entity attribute))
+                         (root attribute)
+                         (->reference template-type entity)))))))
 
 (defn- field-candidates
   [context {:keys [field_type links_to named max_cardinality] :as constraints}]
@@ -440,9 +480,9 @@
                                         (-> context :source u/get-id)
                                         (->> context :source u/get-id (str "card__")))}
                  (not-empty filters)
-                 (assoc :filter (transduce (map :filter)
-                                           merge-filter-clauses
-                                           filters))
+                 (assoc :filter (->> filters
+                                     (map :filter)
+                                     (apply merge-filter-clauses)))
 
                  (not-empty dimensions)
                  (assoc :breakout dimensions)
@@ -487,21 +527,41 @@
            (u/update-when :graph.metrics metric->name)
            (u/update-when :graph.dimensions dimension->name))]))
 
+(defn- capitalize-first
+  [s]
+  (str (str/upper-case (subs s 0 1)) (subs s 1)))
+
 (defn- instantiate-metadata
   [x context bindings]
   (-> (walk/postwalk
        (fn [form]
          (if (string? form)
-           (fill-templates :string context bindings form)
+           (let [new-form (fill-templates :string context bindings form)]
+             (if (not= new-form form)
+               (capitalize-first new-form)
+               new-form))
            form))
        x)
       (u/update-when :visualization #(instantate-visualization % bindings (:metrics context)))))
 
 (defn- valid-breakout-dimension?
-  [{:keys [base_type engine] :as f}]
+  [{:keys [base_type engine]}]
   (not (and (isa? base_type :type/Number)
             (= engine :druid))))
 
+(defn- singular-cell-dimensions
+  [root]
+  (letfn [(collect-dimensions [[op & args]]
+            (case (some-> op qp.util/normalize-token)
+              :and (mapcat collect-dimensions args)
+              :=   (filters/collect-field-references args)
+              nil))]
+    (->> root
+         :cell-query
+         collect-dimensions
+         (map filters/field-reference->id)
+         set)))
+
 (defn- card-candidates
   "Generate all potential cards given a card definition and bindings for
    dimensions, metrics, and filters."
@@ -509,8 +569,7 @@
   (let [order_by        (build-order-by dimensions metrics order_by)
         metrics         (map (partial get (:metrics context)) metrics)
         filters         (cond-> (map (partial get (:filters context)) filters)
-                          (:query-filter context)
-                          (conj {:filter (:query-filter context)}))
+                          (:query-filter context) (conj {:filter (:query-filter context)}))
         score           (if query
                           score
                           (* (or (->> dimensions
@@ -520,33 +579,35 @@
                                  rules/max-score)
                              (/ score rules/max-score)))
         dimensions      (map (comp (partial into [:dimension]) first) dimensions)
-        used-dimensions (rules/collect-dimensions [dimensions metrics filters query])]
+        used-dimensions (rules/collect-dimensions [dimensions metrics filters query])
+        cell-dimension? (->> context :root singular-cell-dimensions)]
     (->> used-dimensions
          (map (some-fn #(get-in (:dimensions context) [% :matches])
                        (comp #(filter-tables % (:tables context)) rules/->entity)))
          (apply combo/cartesian-product)
-         (filter (fn [instantiations]
+         (map (partial zipmap used-dimensions))
+         (filter (fn [bindings]
                    (->> dimensions
-                        (map (comp (zipmap used-dimensions instantiations) second))
-                        (every? valid-breakout-dimension?))))
-         (map (fn [instantiations]
-                (let [bindings (zipmap used-dimensions instantiations)
-                      query    (if query
-                                 (build-query context bindings query)
-                                 (build-query context bindings
-                                              filters
-                                              metrics
-                                              dimensions
-                                              limit
-                                              order_by))]
+                        (map (comp bindings second))
+                        (every? (every-pred valid-breakout-dimension?
+                                            (complement (comp cell-dimension? id-or-name)))))))
+         (map (fn [bindings]
+                (let [query (if query
+                              (build-query context bindings query)
+                              (build-query context bindings
+                                           filters
+                                           metrics
+                                           dimensions
+                                           limit
+                                           order_by))]
                   (-> card
-                      (assoc :metrics metrics)
                       (instantiate-metadata context (->> metrics
                                                          (map :name)
                                                          (zipmap (:metrics card))
                                                          (merge bindings)))
-                      (assoc :score         score
-                             :dataset_query query))))))))
+                      (assoc :dataset_query query
+                             :metrics       (map (some-fn :name (comp metric-name :metric)) metrics)
+                             :score         score))))))))
 
 (defn- matching-rules
   "Return matching rules orderd by specificity.
@@ -632,7 +693,7 @@
                                         (update :special_type keyword)
                                         field/map->FieldInstance
                                         (classify/run-classifiers {})
-                                        (map #(assoc % :engine engine)))))
+                                        (assoc :engine engine))))
                              constantly))]
     (as-> {:source       (assoc source :fields (table->fields source))
            :root         root
@@ -664,8 +725,7 @@
   ([root rule context]
    (-> rule
        (select-keys [:title :description :transient_title :groups])
-       (instantiate-metadata context {})
-       (assoc :refinements (:cell-query root)))))
+       (instantiate-metadata context {}))))
 
 (s/defn ^:private apply-rule
   [root, rule :- rules/Rule]
@@ -673,15 +733,16 @@
         dashboard (make-dashboard root rule context)
         filters   (->> rule
                        :dashboard_filters
-                       (mapcat (comp :matches (:dimensions context))))
+                       (mapcat (comp :matches (:dimensions context)))
+                       (remove (comp (singular-cell-dimensions root) id-or-name)))
         cards     (make-cards context rule)]
     (when (or (not-empty cards)
               (-> rule :cards nil?))
       [(assoc dashboard
-         :filters  filters
-         :cards    cards
-         :context  context)
-       rule])))
+         :filters filters
+         :cards   cards)
+       rule
+       context])))
 
 (def ^:private ^:const ^Long max-related 6)
 (def ^:private ^:const ^Long max-cards 15)
@@ -709,16 +770,15 @@
   [root, rule :- (s/maybe rules/Rule)]
   (->> (rules/get-rules (concat (:rules-prefix root) [(:rule rule)]))
        (keep (fn [indepth]
-               (when-let [[dashboard _] (apply-rule root indepth)]
+               (when-let [[dashboard _ _] (apply-rule root indepth)]
                  {:title       ((some-fn :short-title :title) dashboard)
                   :description (:description dashboard)
                   :url         (format "%s/rule/%s/%s" (:url root) (:rule rule) (:rule indepth))})))
        (hash-map :indepth)))
 
 (defn- drilldown-fields
-  [dashboard]
-  (->> dashboard
-       :context
+  [context]
+  (->> context
        :dimensions
        vals
        (mapcat :matches)
@@ -786,47 +846,57 @@
                     [sideways sideways sideways down down up])})
 
 (s/defn ^:private related
-  "Build a balancee list of related X-rays. General composition of the list is determined for each
+  "Build a balanced list of related X-rays. General composition of the list is determined for each
    root type individually via `related-selectors`. That recepie is then filled round-robin style."
-  [dashboard, rule :- (s/maybe rules/Rule)]
-  (let [root (-> dashboard :context :root)]
-    (->> (merge (indepth root rule)
-                (drilldown-fields dashboard)
-                (related-entities root))
-         (fill-related max-related (related-selectors (-> root :entity type)))
-         (group-by :selector)
-         (m/map-vals (partial map :entity)))))
+  [{:keys [root] :as context}, rule :- (s/maybe rules/Rule)]
+  (->> (merge (indepth root rule)
+              (drilldown-fields context)
+              (related-entities root))
+       (fill-related max-related (related-selectors (-> root :entity type)))
+       (group-by :selector)
+       (m/map-vals (partial map :entity))))
+
+(defn- filter-referenced-fields
+  "Return a map of fields referenced in filter cluase."
+  [root filter-clause]
+  (->> filter-clause
+       filters/collect-field-references
+       (mapcat (fn [[_ & ids]]
+                 (for [id ids]
+                   [id (->field root id)])))
+       (remove (comp nil? second))
+       (into {})))
 
 (defn- automagic-dashboard
   "Create dashboards for table `root` using the best matching heuristics."
-  [{:keys [rule show rules-prefix query-filter cell-query full-name] :as root}]
-  (if-let [[dashboard rule] (if rule
-                              (apply-rule root (rules/get-rule rule))
-                              (->> root
-                                   (matching-rules (rules/get-rules rules-prefix))
-                                   (keep (partial apply-rule root))
-                                   ;; `matching-rules` returns an `ArraySeq` (via `sort-by`) so
-                                   ;; `first` realises one element at a time (no chunking).
-                                   first))]
-    (do
+  [{:keys [rule show rules-prefix full-name] :as root}]
+  (if-let [[dashboard rule context] (if rule
+                                      (apply-rule root (rules/get-rule rule))
+                                      (->> root
+                                           (matching-rules (rules/get-rules rules-prefix))
+                                           (keep (partial apply-rule root))
+                                           ;; `matching-rules` returns an `ArraySeq` (via `sort-by`)
+                                           ;; so `first` realises one element at a time
+                                           ;; (no chunking).
+                                           first))]
+    (let [show (or show max-cards)]
       (log/infof (trs "Applying heuristic %s to %s.") (:rule rule) full-name)
       (log/infof (trs "Dimensions bindings:\n%s")
-                 (->> dashboard
-                      :context
+                 (->> context
                       :dimensions
                       (m/map-vals #(update % :matches (partial map :name)))
                       u/pprint-to-str))
       (log/infof (trs "Using definitions:\nMetrics:\n%s\nFilters:\n%s")
-                 (-> dashboard :context :metrics u/pprint-to-str)
-                 (-> dashboard :context :filters u/pprint-to-str))
-      (-> (cond-> dashboard
-            (or query-filter cell-query)
-            (assoc :title (tru "A closer look at {0}" full-name)))
-          (populate/create-dashboard (or show max-cards))
-          (assoc :related (related dashboard rule))
-          (assoc :more (when (and (-> dashboard :cards count (> max-cards))
-                                (not= show :all))
-                         (format "%s#show=all" (:url root))))))
+                 (-> context :metrics u/pprint-to-str)
+                 (-> context :filters u/pprint-to-str))
+      (-> dashboard
+          (populate/create-dashboard show)
+          (assoc :related           (related context rule)
+                 :more              (when (and (not= show :all)
+                                               (-> dashboard :cards count (> show)))
+                                      (format "%s#show=all" (:url root)))
+                 :transient_filters (:query-filter context)
+                 :param_fields      (->> context :query-filter (filter-referenced-fields root)))))
     (throw (ex-info (trs "Can''t create dashboard for {0}" full-name)
              {:root            root
               :available-rules (map :rule (or (some-> rule rules/get-rule vector)
@@ -858,11 +928,11 @@
                  qp.util/normalize-token
                  (= :metric))
            (-> aggregation-clause second Metric)
-           (let [metric (metric/map->MetricInstance
-                         {:definition {:aggregation  [aggregation-clause]
-                                       :source_table (:table_id question)}
-                          :table_id   (:table_id question)})]
-             (assoc metric :name (metric->description root metric)))))
+           (let [table-id (qp.util/get-normalized question :table-id)]
+             (metric/map->MetricInstance {:definition {:aggregation  [aggregation-clause]
+                                                       :source_table table-id}
+                                          :name       (metric->description root aggregation-clause)
+                                          :table_id   table-id}))))
        (qp.util/get-in-normalized question [:dataset_query :query :aggregation])))
 
 (defn- collect-breakout-fields
@@ -876,48 +946,158 @@
 (defn- decompose-question
   [root question opts]
   (map #(automagic-analysis % (assoc opts
-                                :source   (:source root)
-                                :database (:database root)))
+                                :source       (:source root)
+                                :query-filter (:query-filter root)
+                                :database     (:database root)))
        (concat (collect-metrics root question)
                (collect-breakout-fields root question))))
 
+(defn- pluralize
+  [x]
+  (case (mod x 10)
+    1 (tru "{0}st" x)
+    2 (tru "{0}nd" x)
+    3 (tru "{0}rd" x)
+    (tru "{0}th" x)))
+
+(defn- humanize-datetime
+  [dt unit]
+  (let [dt                     (date/str->date-time dt)
+        tz                     (.getID ^TimeZone @date/jvm-timezone)
+        unparse-with-formatter (fn [formatter dt]
+                                 (t.format/unparse
+                                  (t.format/formatter formatter (t/time-zone-for-id tz))
+                                  dt))]
+    (case unit
+      :minute          (tru "at {0}" (unparse-with-formatter "h:mm a, MMMM d, YYYY" dt))
+      :hour            (tru "at {0}" (unparse-with-formatter "h a, MMMM d, YYYY" dt))
+      :day             (tru "on {0}" (unparse-with-formatter "MMMM d, YYYY" dt))
+      :week            (tru "in {0} week - {1}"
+                            (pluralize (date/date-extract :week-of-year dt tz))
+                            (str (date/date-extract :year dt tz)))
+      :month           (tru "in {0}" (unparse-with-formatter "MMMM YYYY" dt))
+      :quarter         (tru "in Q{0} - {1}"
+                            (date/date-extract :quarter-of-year dt tz)
+                            (str (date/date-extract :year dt tz)))
+      :year            (unparse-with-formatter "YYYY" dt)
+      :day-of-week     (unparse-with-formatter "EEEE" dt)
+      :hour-of-day     (tru "at {0}" (unparse-with-formatter "h a" dt))
+      :month-of-year   (unparse-with-formatter "MMMM" dt)
+      :quarter-of-year (tru "Q{0}" (date/date-extract :quarter-of-year dt tz))
+      (:minute-of-hour
+       :day-of-month
+       :day-of-year
+       :week-of-year)  (date/date-extract unit dt tz))))
+
+(defn- field-reference->field
+  [root field-reference]
+  (cond-> (->> field-reference
+               filters/collect-field-references
+               first
+               filters/field-reference->id
+               (->field root))
+    (-> field-reference first qp.util/normalize-token (= :datetime-field))
+    (assoc :unit (-> field-reference last qp.util/normalize-token))))
+
+(defmulti
+  ^{:private true
+    :arglists '([fieldset [op & args]])}
+  humanize-filter-value (fn [_ [op & args]]
+                          (qp.util/normalize-token op)))
+
+(def ^:private unit-name (comp {:minute-of-hour  "minute"
+                                :hour-of-day     "hour"
+                                :day-of-week     "day of week"
+                                :day-of-month    "day of month"
+                                :day-of-year     "day of year"
+                                :week-of-year    "week"
+                                :month-of-year   "month"
+                                :quarter-of-year "quarter"}
+                               qp.util/normalize-token))
+
+(defn- field-name
+  ([root field-reference]
+   (->> field-reference (field-reference->field root) field-name))
+  ([{:keys [display_name unit] :as field}]
+   (cond->> display_name
+     (and (filters/periodic-datetime? field) unit) (format "%s of %s" (unit-name unit)))))
+
+(defmethod humanize-filter-value :=
+  [root [_ field-reference value]]
+  (let [field      (field-reference->field root field-reference)
+        field-name (field-name field)]
+    (if (or (filters/datetime? field)
+            (filters/periodic-datetime? field))
+      (tru "{0} is {1}" field-name (humanize-datetime value (:unit field)))
+      (tru "{0} is {1}" field-name value))))
+
+(defmethod humanize-filter-value :between
+  [root [_ field-reference min-value max-value]]
+  (tru "{0} is between {1} and {2}" (field-name root field-reference) min-value max-value))
+
+(defmethod humanize-filter-value :inside
+  [root [_ lat-reference lon-reference lat-max lon-min lat-min lon-max]]
+  (tru "{0} is between {1} and {2}; and {3} is between {4} and {5}"
+       (field-name root lon-reference) lon-min lon-max
+       (field-name root lat-reference) lat-min lat-max))
+
+(defmethod humanize-filter-value :and
+  [root [_ & clauses]]
+  (->> clauses
+       (map (partial humanize-filter-value root))
+       join-enumeration))
+
+(defn- cell-title
+  [root cell-query]
+  (str/join " " [(->> (qp.util/get-in-normalized (-> root :entity) [:dataset_query :query :aggregation])
+                      (metric->description root))
+                 (tru "where {0}" (humanize-filter-value root cell-query))]))
+
 (defmethod automagic-analysis (type Card)
   [card {:keys [cell-query] :as opts}]
-  (let [root (->root card)]
-    (if (or (table-like? card)
-            cell-query)
+  (let [root     (->root card)
+        cell-url (format "%squestion/%s/cell/%s" public-endpoint
+                         (u/get-id card)
+                         (encode-base64-json cell-query))]
+    (if (table-like? card)
       (automagic-dashboard
        (merge (cond-> root
-                cell-query (merge {:url          (format "%squestion/%s/cell/%s" public-endpoint
-                                                         (u/get-id card)
-                                                         (encode-base64-json cell-query))
+                cell-query (merge {:url          cell-url
                                    :entity       (:source root)
                                    :rules-prefix ["table"]}))
               opts))
       (let [opts (assoc opts :show :all)]
-        (->> (decompose-question root card opts)
-             (apply populate/merge-dashboards (automagic-dashboard root))
-             (merge {:related (related {:context {:root {:entity card}}} nil)}))))))
+        (cond-> (apply populate/merge-dashboards
+                       (automagic-dashboard (merge (cond-> root
+                                                     cell-query (assoc :url cell-url))
+                                                   opts))
+                       (decompose-question root card opts))
+          cell-query (merge (let [title (tru "A closer look at {0}" (cell-title root cell-query))]
+                              {:transient_name  title
+                               :name            title})))))))
 
 (defmethod automagic-analysis (type Query)
   [query {:keys [cell-query] :as opts}]
-  (let [root (->root query)]
-    (if (or (table-like? query)
-            (:cell-query opts))
+  (let [root     (->root query)
+        cell-url (format "%sadhoc/%s/cell/%s" public-endpoint
+                         (encode-base64-json (:dataset_query query))
+                         (encode-base64-json cell-query))]
+    (if (table-like? query)
       (automagic-dashboard
        (merge (cond-> root
-                cell-query (merge {:url          (format "%sadhoc/%s/cell/%s" public-endpoint
-                                                         (encode-base64-json (:dataset_query query))
-                                                         (encode-base64-json cell-query))
+                cell-query (merge {:url          cell-url
                                    :entity       (:source root)
                                    :rules-prefix ["table"]}))
-              (update opts :cell-query
-                      (partial filters/inject-refinement
-                               (qp.util/get-in-normalized query [:dataset_query :query :filter])))))
+              opts))
       (let [opts (assoc opts :show :all)]
-        (->> (decompose-question root query opts)
-             (apply populate/merge-dashboards (automagic-dashboard root))
-             (merge {:related (related {:context {:root {:entity query}}} nil)}))))))
+        (cond-> (apply populate/merge-dashboards
+                       (automagic-dashboard (merge (cond-> root
+                                                     cell-query (assoc :url cell-url))
+                                                   opts))
+                       (decompose-question root query opts))
+          cell-query (merge (let [title (tru "A closer look at the {0}" (cell-title root cell-query))]
+                              {:transient_name  title
+                               :name            title})))))))
 
 (defmethod automagic-analysis (type Field)
   [field opts]
@@ -930,8 +1110,7 @@
                                       :from     [Field]
                                       :where    [:in :table_id (map u/get-id tables)]
                                       :group-by [:table_id]})
-                           (into {} (map (fn [{:keys [count table_id]}]
-                                           [table_id count]))))
+                           (into {} (map (juxt :table_id :count))))
           list-like?  (->> (when-let [candidates (->> field-count
                                                       (filter (comp (partial >= 2) val))
                                                       (map key)
diff --git a/src/metabase/automagic_dashboards/filters.clj b/src/metabase/automagic_dashboards/filters.clj
index d6d7c5b8c7e63ca1e0765a8e163006720c68e912..a560f807175fb0419c0947f2ac78df022bdb8cca 100644
--- a/src/metabase/automagic_dashboards/filters.clj
+++ b/src/metabase/automagic_dashboards/filters.clj
@@ -11,7 +11,7 @@
   [(s/one (s/constrained su/KeywordOrString
                          (comp #{:field-id :fk-> :field-literal} qp.util/normalize-token))
           "head")
-   s/Any])
+   (s/cond-pre s/Int su/KeywordOrString)])
 
 (def ^:private ^{:arglists '([form])} field-reference?
   "Is given form an MBQL field reference?"
@@ -25,7 +25,7 @@
 (defmethod field-reference->id :field-id
   [[_ id]]
   (if (sequential? id)
-    (second id)
+    (field-reference->id id)
     id))
 
 (defmethod field-reference->id :fk->
@@ -44,12 +44,14 @@
        (tree-seq (some-fn sequential? map?) identity)
        (filter field-reference?)))
 
-(def ^:private ^{:arglists '([field])} periodic-datetime?
+(def ^{:arglists '([field])} periodic-datetime?
+  "Is `field` a periodic datetime (eg. day of month)?"
   (comp #{:minute-of-hour :hour-of-day :day-of-week :day-of-month :day-of-year :week-of-year
           :month-of-year :quarter-of-year}
         :unit))
 
-(defn- datetime?
+(defn datetime?
+  "Is `field` a datetime?"
   [field]
   (and (not (periodic-datetime? field))
        (or (isa? (:base_type field) :type/DateTime)
@@ -154,10 +156,10 @@
           remove-unqualified
           (sort-by interestingness >)
           (take max-filters)
-          (map #(assoc % :fk-map (build-fk-map fks %)))
           (reduce
            (fn [dashboard candidate]
-             (let [filter-id     (-> candidate hash str)
+             (let [filter-id     (-> candidate ((juxt :id :name :unit)) hash str)
+                   candidate     (assoc candidate :fk-map (build-fk-map fks candidate))
                    dashcards     (:ordered_cards dashboard)
                    dashcards-new (map #(add-filter % filter-id candidate) dashcards)]
                ;; Only add filters that apply to all cards.
@@ -172,17 +174,6 @@
            dashboard)))))
 
 
-(defn filter-referenced-fields
-  "Return a map of fields referenced in filter cluase."
-  [filter-clause]
-  (->> filter-clause
-       collect-field-references
-       (mapcat (fn [[_ & ids]]
-                 (for [id ids]
-                   [id (Field id)])))
-       (into {})))
-
-
 (defn- flatten-filter-clause
   [filter-clause]
   (when (not-empty filter-clause)
@@ -208,4 +199,4 @@
     (->> filter-clause
          flatten-filter-clause
          (remove (comp in-refinement? collect-field-references))
-         (reduce merge-filter-clauses refinement))))
+         (apply merge-filter-clauses refinement))))
diff --git a/src/metabase/automagic_dashboards/populate.clj b/src/metabase/automagic_dashboards/populate.clj
index fb1c1c048d320d38acf44a7f2a4795bce621e52a..60fd4bce4fa89b1add9f12ec40ffbac9d8fc402f 100644
--- a/src/metabase/automagic_dashboards/populate.clj
+++ b/src/metabase/automagic_dashboards/populate.clj
@@ -4,10 +4,9 @@
             [clojure.tools.logging :as log]
             [metabase.api.common :as api]
             [metabase.automagic-dashboards.filters :as filters]
-            [metabase.models
-             [card :as card]
-             [field :refer [Field]]]
+            [metabase.models.card :as card]
             [metabase.query-processor.util :as qp.util]
+            [metabase.util :as u]
             [puppetlabs.i18n.core :as i18n :refer [trs]]
             [toucan.db :as db]))
 
@@ -80,17 +79,17 @@
 
 (defn- visualization-settings
   [{:keys [metrics x_label y_label series_labels visualization dimensions] :as card}]
-  (let [metric-name (some-fn :name (comp str/capitalize name first :metric))
-        [display visualization-settings] visualization]
+  (let [[display visualization-settings] visualization]
     {:display display
-     :visualization_settings
-     (-> visualization-settings
-         (merge (colorize card))
-         (cond->
-           (some :name metrics) (assoc :graph.series_labels (map metric-name metrics))
-           series_labels        (assoc :graph.series_labels series_labels)
-           x_label              (assoc :graph.x_axis.title_text x_label)
-           y_label              (assoc :graph.y_axis.title_text y_label)))}))
+     :visualization_settings (-> visualization-settings
+                                 (assoc :graph.series_labels metrics)
+                                 (merge (colorize card))
+                                 (cond->
+                                     series_labels (assoc :graph.series_labels series_labels)
+
+                                     x_label       (assoc :graph.x_axis.title_text x_label)
+
+                                     y_label       (assoc :graph.y_axis.title_text y_label)))}))
 
 (defn- add-card
   "Add a card to dashboard `dashboard` at position [`x`, `y`]."
@@ -236,15 +235,13 @@
 (defn create-dashboard
   "Create dashboard and populate it with cards."
   ([dashboard] (create-dashboard dashboard :all))
-  ([{:keys [title transient_title description groups filters cards refinements fieldset]} n]
+  ([{:keys [title transient_title description groups filters cards refinements]} n]
    (let [n             (cond
                          (= n :all)   (count cards)
                          (keyword? n) (Integer/parseInt (name n))
                          :else        n)
          dashboard     {:name              title
                         :transient_name    (or transient_title title)
-                        :transient_filters refinements
-                        :param_fields      (filters/filter-referenced-fields refinements)
                         :description       description
                         :creator_id        api/*current-user-id*
                         :parameters        []}
@@ -265,43 +262,62 @@
      (cond-> dashboard
        (not-empty filters) (filters/add-filters filters max-filters)))))
 
+(defn- downsize-titles
+  [markdown]
+  (->> markdown
+       str/split-lines
+       (map (fn [line]
+              (if (str/starts-with? line "#")
+                (str "#" line)
+                line)))
+       str/join))
+
+(defn- merge-filters
+  [ds]
+  (when (->> ds
+             (mapcat :ordered_cards)
+             (keep (comp :table_id :card))
+             distinct
+             count
+             (= 1))
+   [(->> ds (mapcat :parameters) distinct)
+    (->> ds
+         (mapcat :ordered_cards)
+         (mapcat :parameter_mappings)
+         (map #(dissoc % :card_id))
+         distinct)]))
+
 (defn merge-dashboards
   "Merge dashboards `ds` into dashboard `d`."
-  [d & ds]
-  (let [filter-targets (when (->> ds
-                                  (mapcat :ordered_cards)
-                                  (keep (comp :table_id :card))
-                                  distinct
-                                  count
-                                  (= 1))
-                         (->> ds
-                              (mapcat :ordered_cards)
-                              (mapcat :parameter_mappings)
-                              (mapcat (comp filters/collect-field-references :target))
-                              (map filters/field-reference->id)
-                              distinct
-                              (map Field)))]
-    (cond-> (reduce
-             (fn [target dashboard]
-               (let [offset (->> target
-                                 :ordered_cards
-                                 (map #(+ (:row %) (:sizeY %)))
-                                 (apply max -1) ; -1 so it neturalizes +1 for spacing if
-                                                ; the target dashboard is empty.
-                                 inc)]
-                 (-> target
-                     (add-text-card {:width                  grid-width
-                                     :height                 group-heading-height
-                                     :text                   (format "# %s" (:name dashboard))
-                                     :visualization-settings {:dashcard.background false
-                                                              :text.align_vertical :bottom}}
-                                    [offset 0])
-                     (update :ordered_cards concat
-                             (->> dashboard
-                                  :ordered_cards
-                                  (map #(-> %
-                                            (update :row + offset group-heading-height)
-                                            (dissoc :parameter_mappings))))))))
-             d
-             ds)
-      (not-empty filter-targets) (filters/add-filters filter-targets max-filters))))
+  [& ds]
+  (let [[paramters parameter-mappings] (merge-filters ds)]
+    (reduce
+     (fn [target dashboard]
+       (let [offset (->> target
+                         :ordered_cards
+                         (map #(+ (:row %) (:sizeY %)))
+                         (apply max -1) ; -1 so it neturalizes +1 for spacing if
+                                        ; the target dashboard is empty.
+                         inc)
+             cards  (->> dashboard
+                         :ordered_cards
+                         (map #(-> %
+                                   (update :row + offset group-heading-height)
+                                   (u/update-in-when [:visualization_settings :text]
+                                                     downsize-titles)
+                                   (assoc :parameter_mappings
+                                     (when (:card_id %)
+                                       (for [mapping parameter-mappings]
+                                         (assoc mapping :card_id (:card_id %))))))))]
+         (-> target
+             (add-text-card {:width                  grid-width
+                             :height                 group-heading-height
+                             :text                   (format "# %s" (:name dashboard))
+                             :visualization-settings {:dashcard.background false
+                                                      :text.align_vertical :bottom}}
+                            [offset 0])
+             (update :ordered_cards concat cards))))
+     (-> ds
+         first
+         (assoc :parameters paramters))
+     (rest ds))))
diff --git a/src/metabase/automagic_dashboards/rules.clj b/src/metabase/automagic_dashboards/rules.clj
index 50bad7029869ed93be85428e75301a0876ac2905..6e6842033f60c07b16edf0c3aae7e21fcd7fde51 100644
--- a/src/metabase/automagic_dashboards/rules.clj
+++ b/src/metabase/automagic_dashboards/rules.clj
@@ -4,6 +4,7 @@
             [clojure.string :as str]
             [clojure.tools.logging :as log]
             [metabase.automagic-dashboards.populate :as populate]
+            [metabase.query-processor.util :as qp.util]
             [metabase.util :as u]
             [metabase.util.schema :as su]
             [puppetlabs.i18n.core :as i18n :refer [trs]]
@@ -119,8 +120,7 @@
   (mapcat (comp k val first) cards))
 
 (def ^:private DimensionForm
-  [(s/one (s/constrained (s/cond-pre s/Str s/Keyword)
-                         (comp #{"dimension"} str/lower-case name))
+  [(s/one (s/constrained (s/cond-pre s/Str s/Keyword) (comp #{:dimension} qp.util/normalize-token))
           "dimension")
    (s/one s/Str "identifier")
    su/Map])
diff --git a/src/metabase/query_processor/middleware/expand_macros.clj b/src/metabase/query_processor/middleware/expand_macros.clj
index d4365fa7d252632e1a8feb8c2315d73de698e5a6..dd4a878c8c36635be1568d3f970a54953f446038 100644
--- a/src/metabase/query_processor/middleware/expand_macros.clj
+++ b/src/metabase/query_processor/middleware/expand_macros.clj
@@ -112,13 +112,14 @@
   "Merge filter clauses."
   ([] [])
   ([clause] clause)
-  ([base-clause additional-clauses]
-   (cond
-     (and (seq base-clause)
-          (seq additional-clauses)) [:and base-clause additional-clauses]
-     (seq base-clause)              base-clause
-     (seq additional-clauses)       additional-clauses
-     :else                          [])))
+  ([base-clause & additional-clauses]
+   (let [additional-clauses (filter seq additional-clauses)]
+     (cond
+       (and (seq base-clause)
+            (seq additional-clauses)) (apply vector :and base-clause additional-clauses)
+       (seq base-clause)              base-clause
+       (seq additional-clauses)       (apply merge-filter-clauses additional-clauses)
+       :else                          []))))
 
 (defn- add-metrics-filter-clauses
   "Add any FILTER-CLAUSES to the QUERY-DICT. If query has existing filter clauses, the new ones are
diff --git a/src/metabase/util/date.clj b/src/metabase/util/date.clj
index 03a07b3fdb73e443a668b66843bd2497a5d41be2..d74ccbe438a3d429b4d60c67d4d7d3917bbd0c1f 100644
--- a/src/metabase/util/date.clj
+++ b/src/metabase/util/date.clj
@@ -41,7 +41,8 @@
   "UTC TimeZone"
   (coerce-to-timezone "UTC"))
 
-(def ^:private jvm-timezone
+(def jvm-timezone
+  "Machine time zone"
   (delay (coerce-to-timezone (System/getProperty "user.timezone"))))
 
 (defn- warn-on-timezone-conflict
diff --git a/test/metabase/automagic_dashboards/core_test.clj b/test/metabase/automagic_dashboards/core_test.clj
index fd17104868250334e912012325ff03e054eece9c..9e7c3f72a9a92343762d116cad09b2d67b349140 100644
--- a/test/metabase/automagic_dashboards/core_test.clj
+++ b/test/metabase/automagic_dashboards/core_test.clj
@@ -1,14 +1,20 @@
 (ns metabase.automagic-dashboards.core-test
-  (:require [expectations :refer :all]
+  (:require [clj-time
+             [core :as t]
+             [format :as t.format]]
+            [expectations :refer :all]
             [metabase.api.common :as api]
             [metabase.automagic-dashboards
              [core :refer :all :as magic]
              [rules :as rules]]
             [metabase.models
              [card :refer [Card]]
+             [collection :refer [Collection]]
              [database :refer [Database]]
              [field :as field :refer [Field]]
              [metric :refer [Metric]]
+             [permissions :as perms]
+             [permissions-group :as perms-group]
              [query :as query]
              [table :refer [Table] :as table]
              [user :as user]]
@@ -16,6 +22,8 @@
             [metabase.test.data :as data]
             [metabase.test.data.users :as test-users]
             [metabase.test.util :as tu]
+            [metabase.util.date :as date]
+            [puppetlabs.i18n.core :as i18n :refer [tru]]
             [toucan.db :as db]
             [toucan.util.test :as tt]))
 
@@ -82,15 +90,15 @@
        (tree-seq (some-fn sequential? map?) identity)
        (keep (fn [form]
                (when (map? form)
-                 (:url form))))))
+                 ((some-fn :url :more) form))))))
 
 (defn- valid-urls?
   [dashboard]
   (->> dashboard
        collect-urls
        (every? (fn [url]
-                 ((test-users/user->client :rasta) :get 200 (format "automagic-dashboards/%s"
-                                                                    (subs url 16)))))))
+                 ((test-users/user->client :rasta) :get 200
+                  (format "automagic-dashboards/%s" (subs url 16)))))))
 
 (def ^:private valid-card?
   (comp qp/expand :dataset_query))
@@ -103,12 +111,28 @@
   (assert (every? valid-card? (keep :card (:ordered_cards dashboard))))
   true)
 
+(defn- test-automagic-analysis
+  ([entity] (test-automagic-analysis entity nil))
+  ([entity cell-query]
+   ;; We want to both generate as many cards as we can to catch all aberrations, but also make sure
+   ;; that size limiting works.
+   (and (valid-dashboard? (automagic-analysis entity {:cell-query cell-query :show :all}))
+        (valid-dashboard? (automagic-analysis entity {:cell-query cell-query :show 1})))))
+
 (expect
   (with-rasta
     (with-dashboard-cleanup
       (->> (db/select Table :db_id (data/id))
-           (keep #(automagic-analysis % {}))
-           (every? valid-dashboard?)))))
+           (every? test-automagic-analysis)))))
+
+(expect
+  (with-rasta
+    (with-dashboard-cleanup
+      (->> (automagic-analysis (Table (data/id :venues)) {:show 1})
+           :ordered_cards
+           (filter :card)
+           count
+           (= 1)))))
 
 (expect
   (with-rasta
@@ -116,28 +140,32 @@
       (->> (db/select Field
              :table_id [:in (db/select-field :id Table :db_id (data/id))]
              :visibility_type "normal")
-           (keep #(automagic-analysis % {}))
-           (every? valid-dashboard?)))))
+           (every? test-automagic-analysis)))))
 
 (expect
   (tt/with-temp* [Metric [{metric-id :id} {:table_id (data/id :venues)
                                            :definition {:query {:aggregation ["count"]}}}]]
     (with-rasta
       (with-dashboard-cleanup
-        (->> (Metric) (keep #(automagic-analysis % {})) (every? valid-dashboard?))))))
+        (->> (Metric) (every? test-automagic-analysis))))))
 
 (expect
-  (tt/with-temp* [Card [{card-id :id} {:table_id      (data/id :venues)
+  (tt/with-temp* [Collection [{collection-id :id}]
+                  Card [{card-id :id} {:table_id      (data/id :venues)
+                                       :collection_id collection-id
                                        :dataset_query {:query {:filter [:> [:field-id (data/id :venues :price)] 10]
                                                                :source_table (data/id :venues)}
                                                        :type :query
                                                        :database (data/id)}}]]
     (with-rasta
       (with-dashboard-cleanup
-        (-> card-id Card (automagic-analysis {}) valid-dashboard?)))))
+        (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection-id)
+        (-> card-id Card test-automagic-analysis)))))
 
 (expect
-  (tt/with-temp* [Card [{card-id :id} {:table_id      (data/id :venues)
+  (tt/with-temp* [Collection [{collection-id :id}]
+                  Card [{card-id :id} {:table_id      (data/id :venues)
+                                       :collection_id collection-id
                                        :dataset_query {:query {:aggregation [[:count]]
                                                                :breakout [[:field-id (data/id :venues :category_id)]]
                                                                :source_table (data/id :venues)}
@@ -145,80 +173,98 @@
                                                        :database (data/id)}}]]
     (with-rasta
       (with-dashboard-cleanup
-        (-> card-id Card (automagic-analysis {}) valid-dashboard?)))))
+        (-> card-id Card test-automagic-analysis)))))
 
 (expect
-  (tt/with-temp* [Card [{card-id :id} {:table_id      nil
+  (tt/with-temp* [Collection [{collection-id :id}]
+                  Card [{card-id :id} {:table_id      nil
+                                       :collection_id collection-id
                                        :dataset_query {:native {:query "select * from users"}
                                                        :type :native
                                                        :database (data/id)}}]]
     (with-rasta
       (with-dashboard-cleanup
-        (-> card-id Card (automagic-analysis {}) valid-dashboard?)))))
+        (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection-id)
+        (-> card-id Card test-automagic-analysis)))))
 
 (expect
-  (tt/with-temp* [Card [{source-id :id} {:table_id      (data/id :venues)
+  (tt/with-temp* [Collection [{collection-id :id}]
+                  Card [{source-id :id} {:table_id      (data/id :venues)
+                                         :collection_id collection-id
                                          :dataset_query {:query    {:source_table (data/id :venues)}
                                                          :type     :query
                                                          :database (data/id)}}]
                   Card [{card-id :id} {:table_id      (data/id :venues)
+                                       :collection_id collection-id
                                        :dataset_query {:query    {:filter       [:> [:field-id (data/id :venues :price)] 10]
                                                                   :source_table (str "card__" source-id)}
                                                        :type     :query
                                                        :database -1337}}]]
     (with-rasta
       (with-dashboard-cleanup
-        (-> card-id Card (automagic-analysis {}) valid-dashboard?)))))
+        (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection-id)
+        (-> card-id Card test-automagic-analysis)))))
 
 (expect
-  (tt/with-temp* [Card [{source-id :id} {:table_id      nil
+  (tt/with-temp* [Collection [{collection-id :id}]
+                  Card [{source-id :id} {:table_id      nil
+                                         :collection_id collection-id
                                          :dataset_query {:native {:query "select * from users"}
                                                          :type :native
                                                          :database (data/id)}}]
                   Card [{card-id :id} {:table_id      (data/id :venues)
+                                       :collection_id collection-id
                                        :dataset_query {:query    {:filter       [:> [:field-id (data/id :venues :price)] 10]
                                                                   :source_table (str "card__" source-id)}
                                                        :type     :query
                                                        :database -1337}}]]
     (with-rasta
       (with-dashboard-cleanup
-        (-> card-id Card (automagic-analysis {}) valid-dashboard?)))))
+        (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection-id)
+        (-> card-id Card test-automagic-analysis)))))
 
 (expect
-  (tt/with-temp* [Card [{card-id :id} {:table_id      nil
+  (tt/with-temp* [Collection [{collection-id :id}]
+                  Card [{card-id :id} {:table_id      nil
+                                       :collection_id collection-id
                                        :dataset_query {:native {:query "select * from users"}
                                                        :type :native
                                                        :database (data/id)}}]]
     (with-rasta
       (with-dashboard-cleanup
-        (-> card-id Card (automagic-analysis {}) valid-dashboard?)))))
+        (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection-id)
+        (-> card-id Card test-automagic-analysis)))))
 
 (expect
-  (tt/with-temp* [Card [{card-id :id} {:table_id      (data/id :venues)
+  (tt/with-temp* [Collection [{collection-id :id}]
+                  Card [{card-id :id} {:table_id      (data/id :venues)
+                                       :collection_id collection-id
                                        :dataset_query {:query {:filter [:> [:field-id (data/id :venues :price)] 10]
                                                                :source_table (data/id :venues)}
                                                        :type :query
                                                        :database (data/id)}}]]
     (with-rasta
       (with-dashboard-cleanup
+        (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection-id)
         (-> card-id
             Card
-            (automagic-analysis {:cell-query [:= [:field-id (data/id :venues :category_id)] 2]})
-            valid-dashboard?)))))
+            (test-automagic-analysis [:= [:field-id (data/id :venues :category_id)] 2]))))))
 
 
 (expect
-  (tt/with-temp* [Card [{card-id :id} {:table_id      (data/id :venues)
+  (tt/with-temp* [Collection [{collection-id :id}]
+                  Card [{card-id :id} {:table_id      (data/id :venues)
+                                       :collection_id collection-id
                                        :dataset_query {:query {:filter [:> [:field-id (data/id :venues :price)] 10]
                                                                :source_table (data/id :venues)}
                                                        :type :query
                                                        :database (data/id)}}]]
     (with-rasta
       (with-dashboard-cleanup
+        (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection-id)
         (-> card-id
             Card
-            (automagic-analysis {:cell-query [:!= [:field-id (data/id :venues :category_id)] 2]})
-            valid-dashboard?)))))
+            (test-automagic-analysis [:= [:field-id (data/id :venues :category_id)] 2]))))))
 
 
 (expect
@@ -228,7 +274,7 @@
                                           :source_table (data/id :venues)}
                                   :type :query
                                   :database (data/id)})]
-        (-> q (automagic-analysis {}) valid-dashboard?)))))
+        (test-automagic-analysis q)))))
 
 (expect
   (with-rasta
@@ -238,7 +284,7 @@
                                           :source_table (data/id :venues)}
                                   :type :query
                                   :database (data/id)})]
-        (-> q (automagic-analysis {}) valid-dashboard?)))))
+        (test-automagic-analysis q)))))
 
 (expect
   (with-rasta
@@ -248,7 +294,7 @@
                                           :source_table (data/id :checkins)}
                                   :type :query
                                   :database (data/id)})]
-        (-> q (automagic-analysis {}) valid-dashboard?)))))
+        (test-automagic-analysis q)))))
 
 (expect
   (with-rasta
@@ -257,9 +303,7 @@
                                           :source_table (data/id :venues)}
                                   :type :query
                                   :database (data/id)})]
-        (-> q
-            (automagic-analysis {:cell-query [:= [:field-id (data/id :venues :category_id)] 2]})
-            valid-dashboard?)))))
+        (test-automagic-analysis q [:= [:field-id (data/id :venues :category_id)] 2])))))
 
 
 ;;; ------------------- /candidates -------------------
@@ -408,3 +452,60 @@
   (#'magic/optimal-datetime-resolution
    {:fingerprint {:type {:type/DateTime {:earliest "2017-01-01T00:00:00"
                                          :latest   "2017-01-01T00:02:00"}}}}))
+
+
+;;; ------------------- Datetime humanization (for chart and dashboard titles) -------------------
+
+(let [tz                     (-> date/jvm-timezone deref ^TimeZone .getID)
+      dt                     (t/from-time-zone (t/date-time 1990 9 9 12 30)
+                                               (t/time-zone-for-id tz))
+      unparse-with-formatter (fn [formatter dt]
+                                 (t.format/unparse
+                                  (t.format/formatter formatter (t/time-zone-for-id tz)) dt))]
+  (expect
+    [(tru "at {0}" (unparse-with-formatter "h:mm a, MMMM d, YYYY" dt))
+     (tru "at {0}" (unparse-with-formatter "h a, MMMM d, YYYY" dt))
+     (tru "on {0}" (unparse-with-formatter "MMMM d, YYYY" dt))
+     (tru "in {0} week - {1}"
+          (#'magic/pluralize (date/date-extract :week-of-year dt tz))
+          (str (date/date-extract :year dt tz)))
+     (tru "in {0}" (unparse-with-formatter "MMMM YYYY" dt))
+     (tru "in Q{0} - {1}"
+          (date/date-extract :quarter-of-year dt tz)
+          (str (date/date-extract :year dt tz)))
+     (unparse-with-formatter "YYYY" dt)
+     (unparse-with-formatter "EEEE" dt)
+     (tru "at {0}" (unparse-with-formatter "h a" dt))
+     (unparse-with-formatter "MMMM" dt)
+     (tru "Q{0}" (date/date-extract :quarter-of-year dt tz))
+     (date/date-extract :minute-of-hour dt tz)
+     (date/date-extract :day-of-month dt tz)
+     (date/date-extract :week-of-year dt tz)]
+    (let [dt (t.format/unparse (t.format/formatters :date-hour-minute-second) dt)]
+      [(#'magic/humanize-datetime dt :minute)
+       (#'magic/humanize-datetime dt :hour)
+       (#'magic/humanize-datetime dt :day)
+       (#'magic/humanize-datetime dt :week)
+       (#'magic/humanize-datetime dt :month)
+       (#'magic/humanize-datetime dt :quarter)
+       (#'magic/humanize-datetime dt :year)
+       (#'magic/humanize-datetime dt :day-of-week)
+       (#'magic/humanize-datetime dt :hour-of-day)
+       (#'magic/humanize-datetime dt :month-of-year)
+       (#'magic/humanize-datetime dt :quarter-of-year)
+       (#'magic/humanize-datetime dt :minute-of-hour)
+       (#'magic/humanize-datetime dt :day-of-month)
+       (#'magic/humanize-datetime dt :week-of-year)])))
+
+(expect
+  [(tru "{0}st" 1)
+   (tru "{0}nd" 22)
+   (tru "{0}rd" 303)
+   (tru "{0}th" 0)
+   (tru "{0}th" 8)]
+  (map #'magic/pluralize [1 22 303 0 8]))
+
+;; Make sure we have handlers for all the units available
+(expect
+  (every? (partial #'magic/humanize-datetime "1990-09-09T12:30:00")
+          (concat (var-get #'date/date-extract-units) (var-get #'date/date-trunc-units))))
diff --git a/test/metabase/automagic_dashboards/filters_test.clj b/test/metabase/automagic_dashboards/filters_test.clj
index 28f3e6584d08378e691066376a2e9873e2db5b2b..0c64afef3910cf613e903d9ec06febc39101572a 100644
--- a/test/metabase/automagic_dashboards/filters_test.clj
+++ b/test/metabase/automagic_dashboards/filters_test.clj
@@ -12,7 +12,7 @@
 
 ;; If there's no overlap between filter clauses, just merge using `:and`.
 (expect
-  [:and [:and [:and [:= [:field-id 3] 42] [:= [:fk-> 1 9] "foo"]] [:> [:field-id 2] 10]] [:< [:field-id 2] 100]]
+  [:and [:= [:field-id 3] 42] [:= [:fk-> 1 9] "foo"] [:> [:field-id 2] 10] [:< [:field-id 2] 100]]
   (inject-refinement [:and [:= [:fk-> 1 9] "foo"]
                            [:and [:> [:field-id 2] 10]
                                  [:< [:field-id 2] 100]]]
diff --git a/test/metabase/models/dashboard_test.clj b/test/metabase/models/dashboard_test.clj
index f3548eb6f6c6cee6f1b7dbccb9601acd5856708f..1c7338e6491f802e8b26a15fe453e86c385905b6 100644
--- a/test/metabase/models/dashboard_test.clj
+++ b/test/metabase/models/dashboard_test.clj
@@ -229,14 +229,15 @@
 
 ;; test that we save a transient dashboard
 (expect
-  8
   (tu/with-model-cleanup ['Card 'Dashboard 'DashboardCard 'Collection]
     (binding [api/*current-user-id*              (users/user->id :rasta)
               api/*current-user-permissions-set* (-> :rasta
                                                      users/user->id
                                                      user/permissions-set
                                                      atom)]
-      (->> (magic/automagic-analysis (Table (id :venues)) {})
-           save-transient-dashboard!
-           :id
-           (db/count 'DashboardCard :dashboard_id)))))
+      (let [dashboard (magic/automagic-analysis (Table (id :venues)) {})]
+        (->> dashboard
+             save-transient-dashboard!
+             :id
+             (db/count 'DashboardCard :dashboard_id)
+             (= (-> dashboard :ordered_cards count)))))))