From b7672d114e02b5f8850ba379053017cc476bbe18 Mon Sep 17 00:00:00 2001
From: Paul Rosenzweig <paulrosenzweig@users.noreply.github.com>
Date: Fri, 24 Jul 2020 09:47:48 -0400
Subject: [PATCH] don't parse unix date query params, fix field value loading
 (#12983)

---
 frontend/src/metabase/entities/fields.js      | 44 +++++++++----------
 .../parameters/components/Parameters.jsx      |  3 +-
 .../components/Parameters.unit.spec.js        | 10 +++++
 3 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/frontend/src/metabase/entities/fields.js b/frontend/src/metabase/entities/fields.js
index 0d2adf1b10c..794cecbc77a 100644
--- a/frontend/src/metabase/entities/fields.js
+++ b/frontend/src/metabase/entities/fields.js
@@ -1,9 +1,12 @@
 import { createEntity } from "metabase/lib/entities";
 import {
+  compose,
+  withAction,
+  withCachedDataAndRequestState,
+  withNormalize,
   handleActions,
   createAction,
   createThunkAction,
-  fetchData,
   updateData,
 } from "metabase/lib/redux";
 import { normalize } from "normalizr";
@@ -38,7 +41,7 @@ export const ADD_REMAPPINGS = "metabase/entities/fields/ADD_REMAPPINGS";
 export const ADD_PARAM_VALUES = "metabase/entities/fields/ADD_PARAM_VALUES";
 export const ADD_FIELDS = "metabase/entities/fields/ADD_FIELDS";
 
-export default createEntity({
+const Fields = createEntity({
   name: "fields",
   path: "/api/field",
   schema: FieldSchema,
@@ -64,18 +67,19 @@ export default createEntity({
   // ACTION CREATORS
 
   objectActions: {
-    fetchFieldValues: createThunkAction(
-      FETCH_FIELD_VALUES,
-      ({ id }, reload) => (dispatch, getState) =>
-        fetchData({
-          dispatch,
-          getState,
-          requestStatePath: ["entities", "fields", id, "values"],
-          existingStatePath: ["entities", "fields", id, "values"],
-          getData: () => MetabaseApi.field_values({ fieldId: id }),
-          reload,
-        }),
-    ),
+    fetchFieldValues: compose(
+      withAction(FETCH_FIELD_VALUES),
+      withCachedDataAndRequestState(
+        ({ id }) => [...Fields.getObjectStatePath(id)],
+        ({ id }) => [...Fields.getObjectStatePath(id), "values"],
+      ),
+      withNormalize(FieldSchema),
+    )(({ id: fieldId }) => async (dispatch, getState) => {
+      const { field_id: id, values } = await MetabaseApi.field_values({
+        fieldId,
+      });
+      return { id, values };
+    }),
 
     // Docstring from m.api.field:
     // Update the human-readable values for a `Field` whose special type is
@@ -139,16 +143,6 @@ export default createEntity({
 
   reducer: handleActions(
     {
-      [FETCH_FIELD_VALUES]: {
-        next: (state, { payload: fieldValues }) =>
-          fieldValues
-            ? assocIn(
-                state,
-                [fieldValues.field_id, "values"],
-                fieldValues.values,
-              )
-            : state,
-      },
       [ADD_PARAM_VALUES]: {
         next: (state, { payload: paramValues }) => {
           for (const fieldValues of Object.values(paramValues)) {
@@ -201,3 +195,5 @@ export default createEntity({
       ].filter(f => f),
   },
 });
+
+export default Fields;
diff --git a/frontend/src/metabase/parameters/components/Parameters.jsx b/frontend/src/metabase/parameters/components/Parameters.jsx
index ade7ec814f1..c31b35893d5 100644
--- a/frontend/src/metabase/parameters/components/Parameters.jsx
+++ b/frontend/src/metabase/parameters/components/Parameters.jsx
@@ -268,7 +268,8 @@ export function parseQueryParam(
   }
   // [].every is always true, so only check if there are some fields
   if (fields.length > 0) {
-    if (fields.every(f => f.isNumeric())) {
+    // unix dates fields are numeric but query params shouldn't be parsed as numbers
+    if (fields.every(f => f.isNumeric() && !f.isDate())) {
       return parseFloat(value);
     }
     if (fields.every(f => f.isBoolean())) {
diff --git a/frontend/test/metabase/parameters/components/Parameters.unit.spec.js b/frontend/test/metabase/parameters/components/Parameters.unit.spec.js
index f3fd1f41ebb..97ea01d93f8 100644
--- a/frontend/test/metabase/parameters/components/Parameters.unit.spec.js
+++ b/frontend/test/metabase/parameters/components/Parameters.unit.spec.js
@@ -1,3 +1,5 @@
+import Field from "metabase-lib/lib/metadata/Field";
+
 import { ORDERS, PRODUCTS } from "__support__/sample_dataset_fixture";
 
 import { parseQueryParam } from "metabase/parameters/components/Parameters";
@@ -24,5 +26,13 @@ describe("Parameters", () => {
       const result = parseQueryParam("123", []);
       expect(result).toBe("123");
     });
+    it("should not parse date/numeric fields", () => {
+      const dateField = new Field({
+        ...ORDERS.QUANTITY, // some numeric field
+        special_type: "type/UNIXTimestampSeconds", // make it a date
+      });
+      const result = parseQueryParam("past30days", [dateField]);
+      expect(result).toBe("past30days");
+    });
   });
 });
-- 
GitLab