diff --git a/frontend/src/dashboard/components/Dashboard.jsx b/frontend/src/dashboard/components/Dashboard.jsx index 58ee3b8647c2d3abeb4dcb8353cb1d399412761a..ef511a4ad12412c8be0a7d4d3261e85b33838031 100644 --- a/frontend/src/dashboard/components/Dashboard.jsx +++ b/frontend/src/dashboard/components/Dashboard.jsx @@ -46,12 +46,12 @@ export default class Dashboard extends Component { <LoadingAndErrorWrapper className="Dashboard full-height" loading={!dashboard} error={error}> {() => <div className="full"> - <header className="bg-white border-bottom"> + <header className="bg-white border-bottom relative z2"> <DashboardHeader {...this.props} /> </header> <div className="Dash-wrapper wrapper"> { dashboard.ordered_cards.length === 0 ? - <div className="absolute top bottom left right flex flex-column layout-centered"> + <div className="absolute z1 top bottom left right flex flex-column layout-centered"> <span className="QuestionCircle">?</span> <div className="text-normal mt3 mb1">This dashboard is looking empty.</div> <div className="text-normal text-grey-2">Add a question to start making it useful!</div> diff --git a/frontend/src/dashboard/components/DashboardHeader.jsx b/frontend/src/dashboard/components/DashboardHeader.jsx index 19ea947437f1d1f4aad2df248ed7842d38e82f1b..f063ca4ef50b7fb6e2c0f7b62f64d19180ceb914 100644 --- a/frontend/src/dashboard/components/DashboardHeader.jsx +++ b/frontend/src/dashboard/components/DashboardHeader.jsx @@ -150,7 +150,7 @@ export default class DashboardHeader extends Component { ref="addQuestionModal" triggerElement={ <a data-metabase-event="Dashboard;Add Card Modal" title="Add a question to this dashboard"> - <Icon className={cx("text-brand-hover", { "Icon--pulse": isEmpty })} name="add" width="16px" height="16px" /> + <Icon className={cx("text-brand-hover cursor-pointer", { "Icon--pulse": isEmpty })} name="add" width="16px" height="16px" /> </a> } > diff --git a/src/metabase/db/migrations.clj b/src/metabase/db/migrations.clj index 6cf0f2333715c31144a9992dbee75426fe56adec..bf9c45eedf6f6d6c2a5f27a45733f79961dbedc9 100644 --- a/src/metabase/db/migrations.clj +++ b/src/metabase/db/migrations.clj @@ -7,6 +7,7 @@ (metabase.models [activity :refer [Activity]] [card :refer [Card]] [database :refer [Database]] + [foreign-key :refer [ForeignKey]] [table :refer [Table]] [setting :as setting]) [metabase.sample-data :as sample-data] @@ -96,3 +97,14 @@ (when-not (contains? activity-feed-topics :database-sync-begin) (k/delete Activity (k/where {:topic "database-sync"})))) + + +;; Clean up duplicate FK entries +(defmigration remove-duplicate-fk-entries + (let [existing-fks (db/sel :many ForeignKey) + grouped-fks (group-by #(str (:origin_id %) "_" (:destination_id %)) existing-fks)] + (doseq [[k fks] grouped-fks] + (when (< 1 (count fks)) + (log/debug "Removing duplicate FK entries for" k) + (doseq [duplicate-fk (drop-last fks)] + (db/del ForeignKey :id (:id duplicate-fk))))))) diff --git a/src/metabase/driver/sync.clj b/src/metabase/driver/sync.clj index 3cfeb2d92aead1ffa0e2112ce4dae13c09c3495c..0dc3183aaa49944dd636e04ac9e1cf66ec0cff50 100644 --- a/src/metabase/driver/sync.clj +++ b/src/metabase/driver/sync.clj @@ -476,18 +476,19 @@ infer-field-special-type (every? :dest-column-name fks)) "table-fks should return a set of maps with keys :fk-column-name, :dest-table, and :dest-column-name.") (when (seq fks) - (let [fk-name->id (sel :many :field->id [Field :name], :table_id (:id table), :name [in (map :fk-column-name fks)], :parent_id nil)] + (let [fk-name->id (sel :many :field->id [Field :name], :table_id (:id table), :name [in (map :fk-column-name fks)], :parent_id nil)] (doseq [{:keys [fk-column-name dest-column-name dest-table]} fks] (when-let [fk-column-id (fk-name->id fk-column-name)] (when-let [dest-table-id (sel :one :field [Table :id], :db_id (:db_id table) :name (:name dest-table) :schema (:schema dest-table))] (when-let [dest-column-id (sel :one :id Field, :table_id dest-table-id, :name dest-column-name, :parent_id nil)] (log/debug (u/format-color 'green "Marking foreign key '%s.%s' -> '%s.%s'." (:name table) fk-column-name (:name dest-table) dest-column-name)) - (ins ForeignKey - :origin_id fk-column-id - :destination_id dest-column-id - ;; TODO: do we even care about this? - ;:relationship (determine-fk-type {:id fk-column-id, :table (delay table)}) ; fake a Field instance - :relationship :Mt1) + (when-not (exists? ForeignKey :origin_id fk-column-id, :destination_id dest-column-id) + (ins ForeignKey + :origin_id fk-column-id + :destination_id dest-column-id + ;; TODO: do we even care about this? + ;:relationship (determine-fk-type {:id fk-column-id, :table (delay table)}) ; fake a Field instance + :relationship :Mt1)) (upd Field fk-column-id :special_type :fk))))))))))