mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-11 23:29:05 +00:00
Merge remote-tracking branch 'origin' into audit-log-revamp
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
import { DatePicker } from "./DatePicker";
|
||||
|
||||
const meta: Meta<typeof DatePicker> = {
|
||||
title: "Components/DatePicker",
|
||||
component: DatePicker,
|
||||
tags: ["v2"],
|
||||
argTypes: {}
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof DatePicker>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||
export const Primary: Story = {
|
||||
args: {}
|
||||
};
|
||||
@@ -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<DayPickerProps, "selected"> & {
|
||||
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 (
|
||||
<Popover {...popUpProps}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="outline_bg" leftIcon={<FontAwesomeIcon icon={faCalendar} />}>
|
||||
{value ? format(value, "PPP") : "Pick a date"}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-fit p-2" {...popUpContentProps}>
|
||||
<DayPicker {...props} mode="single" selected={value} onSelect={onChange} />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export type { DatePickerProps } from "./DatePicker";
|
||||
export { DatePicker } from "./DatePicker";
|
||||
@@ -49,6 +49,7 @@ export type DropdownMenuItemProps<T extends ElementType> =
|
||||
icon?: ReactNode;
|
||||
as?: T;
|
||||
inputRef?: Ref<T>;
|
||||
iconPos?: "left" | "right";
|
||||
};
|
||||
|
||||
export const DropdownMenuItem = <T extends ElementType = "button">({
|
||||
@@ -57,6 +58,7 @@ export const DropdownMenuItem = <T extends ElementType = "button">({
|
||||
className,
|
||||
icon,
|
||||
as: Item = "button",
|
||||
iconPos = "left",
|
||||
...props
|
||||
}: DropdownMenuItemProps<T> & ComponentPropsWithRef<T>) => (
|
||||
<DropdownMenuPrimitive.Item
|
||||
@@ -67,8 +69,9 @@ export const DropdownMenuItem = <T extends ElementType = "button">({
|
||||
)}
|
||||
>
|
||||
<Item type="button" role="menuitem" className="flex w-full items-center" ref={inputRef}>
|
||||
{icon && <span className="flex items-center mr-2">{icon}</span>}
|
||||
{icon && iconPos === "left" && <span className="flex items-center mr-2">{icon}</span>}
|
||||
<span className="flex-grow text-left">{children}</span>
|
||||
{icon && iconPos === "right" && <span className="flex items-center ml-2">{icon}</span>}
|
||||
</Item>
|
||||
</DropdownMenuPrimitive.Item>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// eslint-disable-next-line
|
||||
import { useArgs } from "@storybook/client-api";
|
||||
import type { Meta } from "@storybook/react";
|
||||
|
||||
import { Pagination, PaginationProps } from "./Pagination";
|
||||
|
||||
const meta: Meta<typeof Pagination> = {
|
||||
title: "Components/Pagination",
|
||||
component: Pagination,
|
||||
tags: ["v2"],
|
||||
args: {
|
||||
count: 50
|
||||
}
|
||||
};
|
||||
|
||||
export default meta;
|
||||
// type Story = StoryObj<typeof Pagination>;
|
||||
|
||||
export const Primary = (args: PaginationProps) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
|
||||
return (
|
||||
<Pagination
|
||||
{...args}
|
||||
onChangePage={(page) => updateArgs({ page })}
|
||||
onChangePerPage={(perPage) => updateArgs({ perPage, page: 1 })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
import {
|
||||
faCaretDown,
|
||||
faCheck,
|
||||
faChevronLeft,
|
||||
faChevronRight
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger
|
||||
} from "../Dropdown";
|
||||
import { IconButton } from "../IconButton";
|
||||
|
||||
export type PaginationProps = {
|
||||
count: number;
|
||||
page: number;
|
||||
perPage?: number;
|
||||
onChangePage: (pageNumber: number) => void;
|
||||
onChangePerPage: (newRows: number) => void;
|
||||
className: string;
|
||||
perPageList?: number[];
|
||||
};
|
||||
|
||||
export const Pagination = ({
|
||||
count,
|
||||
page = 1,
|
||||
perPage = 20,
|
||||
onChangePage,
|
||||
onChangePerPage,
|
||||
perPageList = [10, 20, 50, 100],
|
||||
className
|
||||
}: PaginationProps) => {
|
||||
const prevPageNumber = Math.max(1, page - 1);
|
||||
const canGoPrev = page > 1;
|
||||
|
||||
const upperLimit = Math.ceil(count / perPage);
|
||||
const nextPageNumber = Math.min(upperLimit, page + 1);
|
||||
const canGoNext = page + 1 <= upperLimit;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
"flex items-center justify-end text-white w-full p-4 bg-mineshaft-700",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className="mr-6 flex items-center space-x-2">
|
||||
<div className="text-sm">
|
||||
{(page - 1) * perPage} - {(page - 1) * perPage + perPage} of {count}
|
||||
</div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<IconButton ariaLabel="per-page-list" variant="plain">
|
||||
<FontAwesomeIcon icon={faCaretDown} />
|
||||
</IconButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="min-w-fit">
|
||||
{perPageList.map((perPageOption) => (
|
||||
<DropdownMenuItem
|
||||
key={`pagination-per-page-options-${perPageOption}`}
|
||||
icon={perPage === perPageOption && <FontAwesomeIcon size="sm" icon={faCheck} />}
|
||||
iconPos="right"
|
||||
onClick={() => onChangePerPage(perPageOption)}
|
||||
>
|
||||
{perPageOption} rows per page
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<IconButton
|
||||
variant="plain"
|
||||
ariaLabel="pagination-prev"
|
||||
onClick={() => onChangePage(prevPageNumber)}
|
||||
isDisabled={!canGoPrev}
|
||||
>
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
variant="plain"
|
||||
ariaLabel="pagination-next"
|
||||
onClick={() => onChangePage(nextPageNumber)}
|
||||
isDisabled={!canGoNext}
|
||||
>
|
||||
<FontAwesomeIcon icon={faChevronRight} />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export type { PaginationProps } from "./Pagination";
|
||||
export { Pagination } from "./Pagination";
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+3
-2
@@ -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={
|
||||
<div className="text-xs">
|
||||
<div>
|
||||
Updated At: {dayjs(updatedAt).format("YYYY-MM-DD, hh:mm A")}
|
||||
Updated At:{" "}
|
||||
{format(new Date(updatedAt), "YYYY-MM-DD, hh:mm aaa")}
|
||||
</div>
|
||||
{lastRunErrorMessage && (
|
||||
<div className="mt-2 text-red">
|
||||
|
||||
Reference in New Issue
Block a user