From cb69cc44602f2254087789e9ea80e2207fa488a3 Mon Sep 17 00:00:00 2001
From: Ariya Hidayat <ariya@metabase.com>
Date: Wed, 11 May 2022 09:40:07 -0700
Subject: [PATCH] Improve YearPicker component (#22603)

* migrate to TypeScript, add type annotations
* include props definition
* support Storybook
* add a basic unit test
---
 .../YearPicker/YearPicker.stories.tsx         | 24 +++++++++++++++++
 .../components/YearPicker/YearPicker.tsx      | 26 +++++++++++++++++++
 .../YearPicker/YearPicker.unit.spec.tsx       | 11 ++++++++
 .../metabase/components/YearPicker/index.tsx  |  1 +
 .../widgets/DateMonthYearWidget.jsx           |  5 ++--
 .../widgets/DateQuarterYearWidget.jsx         |  5 ++--
 .../components/widgets/YearPicker.jsx         | 20 --------------
 7 files changed, 67 insertions(+), 25 deletions(-)
 create mode 100644 frontend/src/metabase/components/YearPicker/YearPicker.stories.tsx
 create mode 100644 frontend/src/metabase/components/YearPicker/YearPicker.tsx
 create mode 100644 frontend/src/metabase/components/YearPicker/YearPicker.unit.spec.tsx
 create mode 100644 frontend/src/metabase/components/YearPicker/index.tsx
 delete mode 100644 frontend/src/metabase/parameters/components/widgets/YearPicker.jsx

diff --git a/frontend/src/metabase/components/YearPicker/YearPicker.stories.tsx b/frontend/src/metabase/components/YearPicker/YearPicker.stories.tsx
new file mode 100644
index 00000000000..77824720b5b
--- /dev/null
+++ b/frontend/src/metabase/components/YearPicker/YearPicker.stories.tsx
@@ -0,0 +1,24 @@
+import React from "react";
+import { ComponentStory } from "@storybook/react";
+import { useArgs } from "@storybook/client-api";
+import YearPicker from "./YearPicker";
+
+export default {
+  title: "Parameters/YearPicker",
+  component: YearPicker,
+};
+
+const Template: ComponentStory<typeof YearPicker> = args => {
+  const [{ value }, updateArgs] = useArgs();
+
+  const handleChange = (year: number) => {
+    updateArgs({ value: year });
+  };
+
+  return <YearPicker {...args} value={value} onChange={handleChange} />;
+};
+
+export const Default = Template.bind({});
+Default.args = {
+  value: 2022,
+};
diff --git a/frontend/src/metabase/components/YearPicker/YearPicker.tsx b/frontend/src/metabase/components/YearPicker/YearPicker.tsx
new file mode 100644
index 00000000000..42f502b8ffe
--- /dev/null
+++ b/frontend/src/metabase/components/YearPicker/YearPicker.tsx
@@ -0,0 +1,26 @@
+import React, { ChangeEvent } from "react";
+
+import Select from "metabase/core/components/Select";
+import _ from "underscore";
+
+const YEARS = _.range(new Date().getFullYear(), 1900, -1);
+
+export interface YearPickerProps {
+  value: number;
+  onChange: (v: number) => void;
+}
+
+const YearPicker = ({ value, onChange }: YearPickerProps) => (
+  <Select
+    className="borderless"
+    value={value}
+    options={YEARS}
+    optionNameFn={(option: any) => option}
+    optionValueFn={(option: any) => option}
+    onChange={({ target: { value } }: ChangeEvent<HTMLInputElement>) =>
+      onChange(parseInt(value as string, 10))
+    }
+  />
+);
+
+export default YearPicker;
diff --git a/frontend/src/metabase/components/YearPicker/YearPicker.unit.spec.tsx b/frontend/src/metabase/components/YearPicker/YearPicker.unit.spec.tsx
new file mode 100644
index 00000000000..343b066e1e5
--- /dev/null
+++ b/frontend/src/metabase/components/YearPicker/YearPicker.unit.spec.tsx
@@ -0,0 +1,11 @@
+import React from "react";
+import { render, screen } from "@testing-library/react";
+
+import YearPicker from "./YearPicker";
+
+describe("YearPicker", () => {
+  it("should render correctly", () => {
+    render(<YearPicker value={2022} onChange={jest.fn()}></YearPicker>);
+    expect(screen.getByRole("button")).toHaveTextContent("2022");
+  });
+});
diff --git a/frontend/src/metabase/components/YearPicker/index.tsx b/frontend/src/metabase/components/YearPicker/index.tsx
new file mode 100644
index 00000000000..89d4b7ad30a
--- /dev/null
+++ b/frontend/src/metabase/components/YearPicker/index.tsx
@@ -0,0 +1 @@
+export { default } from "./YearPicker";
diff --git a/frontend/src/metabase/parameters/components/widgets/DateMonthYearWidget.jsx b/frontend/src/metabase/parameters/components/widgets/DateMonthYearWidget.jsx
index 528b3e858b5..1fbbe4d01e0 100644
--- a/frontend/src/metabase/parameters/components/widgets/DateMonthYearWidget.jsx
+++ b/frontend/src/metabase/parameters/components/widgets/DateMonthYearWidget.jsx
@@ -1,10 +1,11 @@
 /* eslint-disable react/prop-types */
 import React from "react";
-import YearPicker from "./YearPicker";
-
 import moment from "moment";
 import _ from "underscore";
 import cx from "classnames";
+
+import YearPicker from "metabase/components/YearPicker";
+
 import { MonthContainer, MonthList } from "./DateMonthYearWidget.styled";
 
 export default class DateMonthYearWidget extends React.Component {
diff --git a/frontend/src/metabase/parameters/components/widgets/DateQuarterYearWidget.jsx b/frontend/src/metabase/parameters/components/widgets/DateQuarterYearWidget.jsx
index 54a10f0e750..1af4d83d881 100644
--- a/frontend/src/metabase/parameters/components/widgets/DateQuarterYearWidget.jsx
+++ b/frontend/src/metabase/parameters/components/widgets/DateQuarterYearWidget.jsx
@@ -1,13 +1,12 @@
 /* eslint-disable react/prop-types */
 import React, { Component } from "react";
-
-import YearPicker from "./YearPicker";
-
 import moment from "moment";
 import _ from "underscore";
 import cx from "classnames";
 import { t } from "ttag";
 
+import YearPicker from "metabase/components/YearPicker";
+
 // translator: this is a "moment" format string (https://momentjs.com/docs/#/displaying/format/) It should include "Q" for the quarter number, and raw text can be escaped by brackets. For eample "[Quarter] Q" will be rendered as "Quarter 1" etc
 const QUARTER_FORMAT_STRING = t`[Q]Q`;
 
diff --git a/frontend/src/metabase/parameters/components/widgets/YearPicker.jsx b/frontend/src/metabase/parameters/components/widgets/YearPicker.jsx
deleted file mode 100644
index d23a976d4eb..00000000000
--- a/frontend/src/metabase/parameters/components/widgets/YearPicker.jsx
+++ /dev/null
@@ -1,20 +0,0 @@
-/* eslint-disable react/prop-types */
-import React from "react";
-
-import Select from "metabase/core/components/Select";
-import _ from "underscore";
-
-const YEARS = _.range(new Date().getFullYear(), 1900, -1);
-
-const YearPicker = ({ value, onChange }) => (
-  <Select
-    className="borderless"
-    value={value}
-    options={YEARS}
-    optionNameFn={option => option}
-    optionValueFn={option => option}
-    onChange={({ target: { value } }) => onChange(value)}
-  />
-);
-
-export default YearPicker;
-- 
GitLab