diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 987ebd5c8..568410bb2 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -47,7 +47,7 @@ "classnames": "^2.3.1", "cookies": "^0.8.0", "cva": "npm:class-variance-authority@^0.4.0", - "dayjs": "^1.11.9", + "date-fns": "^2.30.0", "framer-motion": "^6.2.3", "fs": "^0.0.2", "gray-matter": "^4.0.3", @@ -69,6 +69,7 @@ "react-beautiful-dnd": "^13.1.1", "react-code-input": "^3.10.1", "react-contenteditable": "^3.3.7", + "react-day-picker": "^8.8.0", "react-dom": "^17.0.2", "react-grid-layout": "^1.3.4", "react-hook-form": "^7.43.0", @@ -95,6 +96,7 @@ "@storybook/addon-links": "^7.0.23", "@storybook/addon-styling": "^1.3.0", "@storybook/blocks": "^7.0.23", + "@storybook/client-api": "^7.2.1", "@storybook/nextjs": "^7.0.23", "@storybook/react": "^7.0.23", "@storybook/testing-library": "^0.2.0", @@ -5781,6 +5783,20 @@ } } }, + "node_modules/@storybook/builder-webpack5/node_modules/@storybook/client-api": { + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.0.23.tgz", + "integrity": "sha512-Z2ubbWJXORuhb1Faur3DL5zV8OObanQY7ow506CmEwNKRgy2LVzkBwpm4woEJHgw95sOyGuz3f3xfDP2DC6M7A==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "7.0.23", + "@storybook/preview-api": "7.0.23" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { "version": "16.18.36", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.36.tgz", @@ -6126,13 +6142,96 @@ "dev": true }, "node_modules/@storybook/client-api": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.0.23.tgz", - "integrity": "sha512-Z2ubbWJXORuhb1Faur3DL5zV8OObanQY7ow506CmEwNKRgy2LVzkBwpm4woEJHgw95sOyGuz3f3xfDP2DC6M7A==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.2.1.tgz", + "integrity": "sha512-VeRUxc4ufSaGAQPe/LM4aucpEx2UHHw9c+tzolV3hzGIp6pmIAS8XI6thL2IccYmsNMS2zz9oDESYP9cNlTsyA==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.23", - "@storybook/preview-api": "7.0.23" + "@storybook/client-logger": "7.2.1", + "@storybook/preview-api": "7.2.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/client-api/node_modules/@storybook/channels": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.2.1.tgz", + "integrity": "sha512-3ZogzjwlFG+oarwnI7TTvWvHVOUtJbjrgZkM5QuLMlxNzIR1XuBY8f01yf4K8+VpdNy9DY+7Q/j6tBThfwYvpA==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "7.2.1", + "@storybook/core-events": "7.2.1", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.0.3", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/client-api/node_modules/@storybook/client-logger": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.2.1.tgz", + "integrity": "sha512-Lyht/lJg2S65CXRy9rXAZXP/Mgye7jbi/aqQL8z9VRMGChbL+k/3pSZnXTTrD1OVSpCEr4UWA+9bStzT4VjtYA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/client-api/node_modules/@storybook/core-events": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.2.1.tgz", + "integrity": "sha512-EUXYb3gyQ2EzpDAWkgfoDl1EPabj3OE6+zntsD/gwvzQU85BTocs10ksnRyS55bfrQpYbf+Z+gw2CZboyagLgg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/client-api/node_modules/@storybook/preview-api": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.2.1.tgz", + "integrity": "sha512-WKecuOdeh9+og6bPR9KoQf/JCeSRPCcfZv9uNfJzAp3IiTnS3UpfCz+HBZzZJQrisgbd7OulNY400HQUmxY2Ag==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.2.1", + "@storybook/client-logger": "7.2.1", + "@storybook/core-events": "7.2.1", + "@storybook/csf": "^0.1.0", + "@storybook/global": "^5.0.0", + "@storybook/types": "7.2.1", + "@types/qs": "^6.9.5", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/client-api/node_modules/@storybook/types": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.2.1.tgz", + "integrity": "sha512-YwlIY1uyxfJjijbB5x1d1QOKaUUDJnMX8BSb8oGqU4cyT76X/Is4CbGs+vccFsJo0tZu1GfuahYXl0EDT0nnSQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.2.1", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" }, "funding": { "type": "opencollective", @@ -10724,10 +10823,20 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "node_modules/dayjs": { - "version": "1.11.9", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", - "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } }, "node_modules/debug": { "version": "4.3.4", @@ -19041,6 +19150,19 @@ "react": ">=16.3" } }, + "node_modules/react-day-picker": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.8.0.tgz", + "integrity": "sha512-QIC3uOuyGGbtypbd5QEggsCSqVaPNu8kzUWquZ7JjW9fuWB9yv7WyixKmnaFelTLXFdq7h7zU6n/aBleBqe/dA==", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/gpbl" + }, + "peerDependencies": { + "date-fns": "^2.28.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-docgen": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-5.4.3.tgz", @@ -26972,6 +27094,16 @@ "webpack-virtual-modules": "^0.4.3" }, "dependencies": { + "@storybook/client-api": { + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.0.23.tgz", + "integrity": "sha512-Z2ubbWJXORuhb1Faur3DL5zV8OObanQY7ow506CmEwNKRgy2LVzkBwpm4woEJHgw95sOyGuz3f3xfDP2DC6M7A==", + "dev": true, + "requires": { + "@storybook/client-logger": "7.0.23", + "@storybook/preview-api": "7.0.23" + } + }, "@types/node": { "version": "16.18.36", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.36.tgz", @@ -27215,13 +27347,78 @@ } }, "@storybook/client-api": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.0.23.tgz", - "integrity": "sha512-Z2ubbWJXORuhb1Faur3DL5zV8OObanQY7ow506CmEwNKRgy2LVzkBwpm4woEJHgw95sOyGuz3f3xfDP2DC6M7A==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.2.1.tgz", + "integrity": "sha512-VeRUxc4ufSaGAQPe/LM4aucpEx2UHHw9c+tzolV3hzGIp6pmIAS8XI6thL2IccYmsNMS2zz9oDESYP9cNlTsyA==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.23", - "@storybook/preview-api": "7.0.23" + "@storybook/client-logger": "7.2.1", + "@storybook/preview-api": "7.2.1" + }, + "dependencies": { + "@storybook/channels": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.2.1.tgz", + "integrity": "sha512-3ZogzjwlFG+oarwnI7TTvWvHVOUtJbjrgZkM5QuLMlxNzIR1XuBY8f01yf4K8+VpdNy9DY+7Q/j6tBThfwYvpA==", + "dev": true, + "requires": { + "@storybook/client-logger": "7.2.1", + "@storybook/core-events": "7.2.1", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.0.3", + "tiny-invariant": "^1.3.1" + } + }, + "@storybook/client-logger": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.2.1.tgz", + "integrity": "sha512-Lyht/lJg2S65CXRy9rXAZXP/Mgye7jbi/aqQL8z9VRMGChbL+k/3pSZnXTTrD1OVSpCEr4UWA+9bStzT4VjtYA==", + "dev": true, + "requires": { + "@storybook/global": "^5.0.0" + } + }, + "@storybook/core-events": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.2.1.tgz", + "integrity": "sha512-EUXYb3gyQ2EzpDAWkgfoDl1EPabj3OE6+zntsD/gwvzQU85BTocs10ksnRyS55bfrQpYbf+Z+gw2CZboyagLgg==", + "dev": true + }, + "@storybook/preview-api": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.2.1.tgz", + "integrity": "sha512-WKecuOdeh9+og6bPR9KoQf/JCeSRPCcfZv9uNfJzAp3IiTnS3UpfCz+HBZzZJQrisgbd7OulNY400HQUmxY2Ag==", + "dev": true, + "requires": { + "@storybook/channels": "7.2.1", + "@storybook/client-logger": "7.2.1", + "@storybook/core-events": "7.2.1", + "@storybook/csf": "^0.1.0", + "@storybook/global": "^5.0.0", + "@storybook/types": "7.2.1", + "@types/qs": "^6.9.5", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/types": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.2.1.tgz", + "integrity": "sha512-YwlIY1uyxfJjijbB5x1d1QOKaUUDJnMX8BSb8oGqU4cyT76X/Is4CbGs+vccFsJo0tZu1GfuahYXl0EDT0nnSQ==", + "dev": true, + "requires": { + "@storybook/channels": "7.2.1", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + } + } } }, "@storybook/client-logger": { @@ -30800,10 +30997,13 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "dayjs": { - "version": "1.11.9", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", - "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" + "date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "requires": { + "@babel/runtime": "^7.21.0" + } }, "debug": { "version": "4.3.4", @@ -36915,6 +37115,12 @@ "prop-types": "^15.7.1" } }, + "react-day-picker": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.8.0.tgz", + "integrity": "sha512-QIC3uOuyGGbtypbd5QEggsCSqVaPNu8kzUWquZ7JjW9fuWB9yv7WyixKmnaFelTLXFdq7h7zU6n/aBleBqe/dA==", + "requires": {} + }, "react-docgen": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-5.4.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index e779e95b1..9aa355d4b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -55,7 +55,7 @@ "classnames": "^2.3.1", "cookies": "^0.8.0", "cva": "npm:class-variance-authority@^0.4.0", - "dayjs": "^1.11.9", + "date-fns": "^2.30.0", "framer-motion": "^6.2.3", "fs": "^0.0.2", "gray-matter": "^4.0.3", @@ -77,6 +77,7 @@ "react-beautiful-dnd": "^13.1.1", "react-code-input": "^3.10.1", "react-contenteditable": "^3.3.7", + "react-day-picker": "^8.8.0", "react-dom": "^17.0.2", "react-grid-layout": "^1.3.4", "react-hook-form": "^7.43.0", @@ -103,6 +104,7 @@ "@storybook/addon-links": "^7.0.23", "@storybook/addon-styling": "^1.3.0", "@storybook/blocks": "^7.0.23", + "@storybook/client-api": "^7.2.1", "@storybook/nextjs": "^7.0.23", "@storybook/react": "^7.0.23", "@storybook/testing-library": "^0.2.0", diff --git a/frontend/src/components/v2/DatePicker/DatePicker.stories.tsx b/frontend/src/components/v2/DatePicker/DatePicker.stories.tsx new file mode 100644 index 000000000..4c6e95b5e --- /dev/null +++ b/frontend/src/components/v2/DatePicker/DatePicker.stories.tsx @@ -0,0 +1,18 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { DatePicker } from "./DatePicker"; + +const meta: Meta = { + title: "Components/DatePicker", + component: DatePicker, + tags: ["v2"], + argTypes: {} +}; + +export default meta; +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args +export const Primary: Story = { + args: {} +}; diff --git a/frontend/src/components/v2/DatePicker/DatePicker.tsx b/frontend/src/components/v2/DatePicker/DatePicker.tsx new file mode 100644 index 000000000..4c59c00b1 --- /dev/null +++ b/frontend/src/components/v2/DatePicker/DatePicker.tsx @@ -0,0 +1,37 @@ +import { DayPicker, DayPickerProps } from "react-day-picker"; +import { faCalendar } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { PopoverContentProps, PopoverProps } from "@radix-ui/react-popover"; +import { format } from "date-fns"; + +import { Button } from "../Button"; +import { Popover, PopoverContent, PopoverTrigger } from "../Popoverv2"; + +export type DatePickerProps = Omit & { + value?: Date; + onChange: (date?: Date) => void; + popUpProps: PopoverProps; + popUpContentProps: PopoverContentProps; +}; + +// Doc: https://react-day-picker.js.org/ +export const DatePicker = ({ + value, + onChange, + popUpProps, + popUpContentProps, + ...props +}: DatePickerProps) => { + return ( + + + + + + + + + ); +}; diff --git a/frontend/src/components/v2/DatePicker/index.tsx b/frontend/src/components/v2/DatePicker/index.tsx new file mode 100644 index 000000000..86fa9e298 --- /dev/null +++ b/frontend/src/components/v2/DatePicker/index.tsx @@ -0,0 +1,2 @@ +export type { DatePickerProps } from "./DatePicker"; +export { DatePicker } from "./DatePicker"; diff --git a/frontend/src/components/v2/Dropdown/Dropdown.tsx b/frontend/src/components/v2/Dropdown/Dropdown.tsx index def928c74..8d2427c1c 100644 --- a/frontend/src/components/v2/Dropdown/Dropdown.tsx +++ b/frontend/src/components/v2/Dropdown/Dropdown.tsx @@ -49,6 +49,7 @@ export type DropdownMenuItemProps = icon?: ReactNode; as?: T; inputRef?: Ref; + iconPos?: "left" | "right"; }; export const DropdownMenuItem = ({ @@ -57,6 +58,7 @@ export const DropdownMenuItem = ({ className, icon, as: Item = "button", + iconPos = "left", ...props }: DropdownMenuItemProps & ComponentPropsWithRef) => ( ({ )} > - {icon && {icon}} + {icon && iconPos === "left" && {icon}} {children} + {icon && iconPos === "right" && {icon}} ); diff --git a/frontend/src/components/v2/index.tsx b/frontend/src/components/v2/index.tsx index b4412b47b..8d23594dc 100644 --- a/frontend/src/components/v2/index.tsx +++ b/frontend/src/components/v2/index.tsx @@ -1,6 +1,7 @@ export * from "./Button"; export * from "./Card"; export * from "./Checkbox"; +export * from "./DatePicker"; export * from "./DeleteActionModal"; export * from "./Drawer"; export * from "./Dropdown"; @@ -12,6 +13,7 @@ export * from "./IconButton"; export * from "./Input"; export * from "./Menu"; export * from "./Modal"; +export * from "./Pagination"; export * from "./Popoverv2"; export * from "./SecretInput"; export * from "./Select"; diff --git a/frontend/src/pages/_app.tsx b/frontend/src/pages/_app.tsx index 82e642245..332557732 100644 --- a/frontend/src/pages/_app.tsx +++ b/frontend/src/pages/_app.tsx @@ -28,6 +28,7 @@ import { queryClient } from "@app/reactQuery"; import "nprogress/nprogress.css"; import "@fortawesome/fontawesome-svg-core/styles.css"; +import "react-day-picker/dist/style.css"; import "../styles/globals.css"; import "@app/i18n"; diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css index ed191a319..ae8d17427 100644 --- a/frontend/src/styles/globals.css +++ b/frontend/src/styles/globals.css @@ -1,5 +1,20 @@ @tailwind base; @tailwind components; + +.rdp-day, +.rdp-nav_button { + @apply rounded-md hover:text-mineshaft-500; +} + +.rdp-button:hover:not([disabled]):not(.rdp-day_selected), +.rdp-nav_button:hover { + @apply bg-primary; +} + +.rdp-day_today { + @apply bg-primary/50 hover:bg-primary-600 text-mineshaft-500; +} + @tailwind utilities; @layer utilities { diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/WebhooksTab/WebhooksTab.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/WebhooksTab/WebhooksTab.tsx index 598af0360..d5cb16b7b 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/WebhooksTab/WebhooksTab.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/WebhooksTab/WebhooksTab.tsx @@ -1,7 +1,7 @@ import { useTranslation } from "react-i18next"; import { faInfoCircle, faPlug, faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import dayjs from "dayjs"; +import { format } from "date-fns"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { @@ -196,7 +196,8 @@ export const WebhooksTab = () => { content={
- Updated At: {dayjs(updatedAt).format("YYYY-MM-DD, hh:mm A")} + Updated At:{" "} + {format(new Date(updatedAt), "YYYY-MM-DD, hh:mm aaa")}
{lastRunErrorMessage && (