chore(frontend): setup eslint and prettier with better defaults (#15)

This commit is contained in:
Luca Steeb
2023-12-20 14:32:42 +07:00
committed by GitHub
parent 41f26b6bc8
commit 46a9d66d30
73 changed files with 3324 additions and 1174 deletions

View File

@@ -1,18 +0,0 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}

View File

@@ -0,0 +1,59 @@
{
"root": true,
"env": {
"browser": true,
"es2020": true
},
"extends": [
"airbnb-typescript",
"eslint:recommended",
"plugin:react/recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"prettier"
],
"ignorePatterns": [
"dist"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": [
"react-refresh",
"import",
"unused-imports",
"prettier"
],
"rules": {
"@typescript-eslint/no-shadow": "off",
"@typescript-eslint/no-throw-literal": "off",
"no-use-before-define": "off",
"react/prop-types": "off",
"react/no-unescaped-entities": "off",
"@typescript-eslint/no-use-before-define": "off",
"import/extensions": "off",
"react/react-in-jsx-scope": "off",
"react-refresh/only-export-components": [
"warn",
{
"allowConstantExport": true
}
],
"unused-imports/no-unused-imports": "error",
"no-unused-vars": "off",
"prettier/prettier": "error",
"@typescript-eslint/no-unused-vars": "warn",
"curly": "error",
"import/prefer-default-export": "off",
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": [
"vite.config.ts"
]
}
]
}
}

View File

@@ -0,0 +1 @@
src/lib/api/generated/

4
frontend/app/.prettierrc Normal file
View File

@@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "all"
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,12 @@
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:check": "npm run eslint:check && npm run prettier:check",
"lint:fix": "npm run eslint:fix && npm run prettier:fix",
"eslint:check": "eslint \"{src,apps,libs,test}/**/*.{ts,tsx,js}\"",
"eslint:fix": "eslint \"{src,apps,libs,test}/**/*.{ts,tsx,js}\" --fix",
"prettier:check": "prettier \"src/**/*.{ts,tsx}\" --list-different",
"prettier:fix": "prettier \"src/**/*.{ts,tsx}\" --write",
"preview": "vite preview"
},
"dependencies": {
@@ -69,12 +74,21 @@
"@typescript-eslint/parser": "^6.10.0",
"@vitejs/plugin-react": "^4.2.0",
"autoprefixer": "^10.4.16",
"eslint": "^8.53.0",
"eslint": "^8.56.0",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.4",
"eslint-plugin-unused-imports": "^3.0.0",
"postcss": "^8.4.31",
"prettier": "^3.1.1",
"tailwindcss": "^3.3.5",
"typescript": "^5.2.2",
"vite": "^5.0.0"
"vite": "^5.0.0",
"vite-plugin-eslint": "^1.8.1"
}
}

View File

@@ -1,25 +1,25 @@
import React from "react";
import { Group } from "@visx/group";
import { AreaClosed } from "@visx/shape";
import { AxisLeft, AxisBottom, AxisScale } from "@visx/axis";
import { LinearGradient } from "@visx/gradient";
import { curveMonotoneX } from "@visx/curve";
import { AppleStock } from "@visx/mock-data/lib/mocks/appleStock";
import React from 'react';
import { Group } from '@visx/group';
import { AreaClosed } from '@visx/shape';
import { AxisLeft, AxisBottom, AxisScale } from '@visx/axis';
import { LinearGradient } from '@visx/gradient';
import { curveMonotoneX } from '@visx/curve';
import { AppleStock } from '@visx/mock-data/lib/mocks/appleStock';
// Initialize some variables
const axisColor = "#fff";
const axisColor = '#fff';
const axisBottomTickLabelProps = {
textAnchor: "middle" as const,
fontFamily: "Arial",
textAnchor: 'middle' as const,
fontFamily: 'Arial',
fontSize: 10,
fill: axisColor,
};
const axisLeftTickLabelProps = {
dx: "-0.25em",
dy: "0.25em",
fontFamily: "Arial",
dx: '-0.25em',
dy: '0.25em',
fontFamily: 'Arial',
fontSize: 10,
textAnchor: "end" as const,
textAnchor: 'end' as const,
fill: axisColor,
};
@@ -54,7 +54,9 @@ export default function AreaChart({
left?: number;
children?: React.ReactNode;
}) {
if (width < 10) return null;
if (width < 10) {
return null;
}
return (
<Group left={left || margin.left} top={top || margin.top}>
<LinearGradient

View File

@@ -1,31 +1,31 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import { useRef, useState, useMemo } from "react";
import { scaleTime, scaleLinear } from "@visx/scale";
import appleStock, { AppleStock } from "@visx/mock-data/lib/mocks/appleStock";
import { Brush } from "@visx/brush";
import { Bounds } from "@visx/brush/lib/types";
import { useRef, useState, useMemo } from 'react';
import { scaleTime, scaleLinear } from '@visx/scale';
import appleStock, { AppleStock } from '@visx/mock-data/lib/mocks/appleStock';
import { Brush } from '@visx/brush';
import { Bounds } from '@visx/brush/lib/types';
import BaseBrush, {
BaseBrushState,
UpdateBrush,
} from "@visx/brush/lib/BaseBrush";
import { PatternLines } from "@visx/pattern";
import { Group } from "@visx/group";
import { max, extent } from "@visx/vendor/d3-array";
import { BrushHandleRenderProps } from "@visx/brush/lib/BrushHandle";
import AreaChart from "./area-chart";
import { Button } from "@/components/ui/button";
} from '@visx/brush/lib/BaseBrush';
import { PatternLines } from '@visx/pattern';
import { Group } from '@visx/group';
import { max, extent } from '@visx/vendor/d3-array';
import { BrushHandleRenderProps } from '@visx/brush/lib/BrushHandle';
import AreaChart from './area-chart';
import { Button } from '@/components/ui/button';
// Initialize some variables
const stock = appleStock.slice(1000);
const brushMargin = { top: 10, bottom: 15, left: 50, right: 20 };
const chartSeparation = 30;
const PATTERN_ID = "brush_pattern";
export const accentColor = "#ffffff44";
export const background = "#1E293B";
export const background2 = "#8c77e0";
const PATTERN_ID = 'brush_pattern';
export const accentColor = '#ffffff44';
export const background = '#1E293B';
export const background2 = '#8c77e0';
const selectedBrushStyle = {
fill: `url(#${PATTERN_ID})`,
stroke: "white",
stroke: 'white',
};
// accessors
@@ -54,7 +54,9 @@ function BrushChart({
const [filteredStock, setFilteredStock] = useState(stock);
const onBrushChange = (domain: Bounds | null) => {
if (!domain) return;
if (!domain) {
return;
}
const { x0, x1, y0, y1 } = domain;
const stockCopy = stock.filter((s) => {
const x = getDate(s).getTime();
@@ -77,7 +79,7 @@ function BrushChart({
const xBrushMax = Math.max(width - brushMargin.left - brushMargin.right, 0);
const yBrushMax = Math.max(
bottomChartHeight - brushMargin.top - brushMargin.bottom,
0
0,
);
// scales
@@ -87,7 +89,7 @@ function BrushChart({
range: [0, xMax],
domain: extent(filteredStock, getDate) as [Date, Date],
}),
[xMax, filteredStock]
[xMax, filteredStock],
);
const stockScale = useMemo(
() =>
@@ -96,7 +98,7 @@ function BrushChart({
domain: [0, max(filteredStock, getStockValue) || 0],
nice: true,
}),
[yMax, filteredStock]
[yMax, filteredStock],
);
const brushDateScale = useMemo(
() =>
@@ -104,7 +106,7 @@ function BrushChart({
range: [0, xBrushMax],
domain: extent(stock, getDate) as [Date, Date],
}),
[xBrushMax]
[xBrushMax],
);
const brushStockScale = useMemo(
() =>
@@ -113,7 +115,7 @@ function BrushChart({
domain: [0, max(stock, getStockValue) || 0],
nice: true,
}),
[yBrushMax]
[yBrushMax],
);
const initialBrushPosition = useMemo(
@@ -121,7 +123,7 @@ function BrushChart({
start: { x: brushDateScale(getDate(stock[50])) },
end: { x: brushDateScale(getDate(stock[100])) },
}),
[brushDateScale]
[brushDateScale],
);
// event handlers
@@ -137,7 +139,7 @@ function BrushChart({
const updater: UpdateBrush = (prevBrush) => {
const newExtent = brushRef.current!.getExtent(
initialBrushPosition.start,
initialBrushPosition.end
initialBrushPosition.end,
);
const newState: BaseBrushState = {
@@ -198,7 +200,7 @@ function BrushChart({
width={8}
stroke={accentColor}
strokeWidth={1}
orientation={["diagonal"]}
orientation={['diagonal']}
/>
<Brush
xScale={brushDateScale}
@@ -208,7 +210,7 @@ function BrushChart({
margin={brushMargin}
handleSize={8}
innerRef={brushRef}
resizeTriggerAreas={["left", "right"]}
resizeTriggerAreas={['left', 'right']}
brushDirection="horizontal"
initialBrushPosition={initialBrushPosition}
onChange={onBrushChange}
@@ -242,7 +244,7 @@ function BrushHandle({ x, height, isBrushActive }: BrushHandleRenderProps) {
d="M -4.5 0.5 L 3.5 0.5 L 3.5 15.5 L -4.5 15.5 L -4.5 0.5 M -1.5 4 L -1.5 12 M 0.5 4 L 0.5 12"
stroke="#999999"
strokeWidth="1"
style={{ cursor: "ew-resize" }}
style={{ cursor: 'ew-resize' }}
/>
</Group>
);

View File

@@ -3,18 +3,18 @@ import {
ArrowUpIcon,
CaretSortIcon,
EyeNoneIcon,
} from "@radix-ui/react-icons";
import { Column } from "@tanstack/react-table";
} from '@radix-ui/react-icons';
import { Column } from '@tanstack/react-table';
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
} from '@/components/ui/dropdown-menu';
interface DataTableColumnHeaderProps<TData, TValue>
extends React.HTMLAttributes<HTMLDivElement> {
@@ -28,11 +28,11 @@ export function DataTableColumnHeader<TData, TValue>({
className,
}: DataTableColumnHeaderProps<TData, TValue>) {
if (!column.getCanSort()) {
return <div className={cn(className, "text-xs")}>{title}</div>;
return <div className={cn(className, 'text-xs')}>{title}</div>;
}
return (
<div className={cn("flex items-center space-x-2", className)}>
<div className={cn('flex items-center space-x-2', className)}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
@@ -41,9 +41,9 @@ export function DataTableColumnHeader<TData, TValue>({
className="-ml-3 h-8 data-[state=open]:bg-accent"
>
<span>{title}</span>
{column.getIsSorted() === "desc" ? (
{column.getIsSorted() === 'desc' ? (
<ArrowDownIcon className="ml-2 h-4 w-4" />
) : column.getIsSorted() === "asc" ? (
) : column.getIsSorted() === 'asc' ? (
<ArrowUpIcon className="ml-2 h-4 w-4" />
) : (
<CaretSortIcon className="ml-2 h-4 w-4" />

View File

@@ -1,10 +1,10 @@
import * as React from "react";
import { CheckIcon, PlusCircledIcon } from "@radix-ui/react-icons";
import { Column } from "@tanstack/react-table";
import * as React from 'react';
import { CheckIcon, PlusCircledIcon } from '@radix-ui/react-icons';
import { Column } from '@tanstack/react-table';
import { cn } from "@/lib/utils";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { cn } from '@/lib/utils';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
Command,
CommandEmpty,
@@ -13,13 +13,13 @@ import {
CommandItem,
CommandList,
CommandSeparator,
} from "@/components/ui/command";
} from '@/components/ui/command';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { Separator } from "@/components/ui/separator";
} from '@/components/ui/popover';
import { Separator } from '@/components/ui/separator';
interface DataTableFacetedFilterProps<TData, TValue> {
column?: Column<TData, TValue>;
@@ -99,19 +99,19 @@ export function DataTableFacetedFilter<TData, TValue>({
}
const filterValues = Array.from(selectedValues);
column?.setFilterValue(
filterValues.length ? filterValues : undefined
filterValues.length ? filterValues : undefined,
);
}}
>
<div
className={cn(
"mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary",
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
isSelected
? "bg-primary text-primary-foreground"
: "opacity-50 [&_svg]:invisible"
? 'bg-primary text-primary-foreground'
: 'opacity-50 [&_svg]:invisible',
)}
>
<CheckIcon className={cn("h-4 w-4")} />
<CheckIcon className={cn('h-4 w-4')} />
</div>
{option.icon && (
<option.icon className="mr-2 h-4 w-4 text-muted-foreground" />

View File

@@ -3,17 +3,17 @@ import {
ChevronRightIcon,
DoubleArrowLeftIcon,
DoubleArrowRightIcon,
} from "@radix-ui/react-icons";
import { Table } from "@tanstack/react-table";
} from '@radix-ui/react-icons';
import { Table } from '@tanstack/react-table';
import { Button } from "@/components/ui/button";
import { Button } from '@/components/ui/button';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
} from '@/components/ui/select';
interface DataTablePaginationProps<TData> {
table: Table<TData>;
@@ -29,7 +29,7 @@ export function DataTablePagination<TData>({
return (
<div className="flex items-center justify-between px-2">
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredSelectedRowModel().rows.length} of{' '}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="flex items-center space-x-6 lg:space-x-8">
@@ -39,7 +39,9 @@ export function DataTablePagination<TData>({
value={`${pagination.pageSize}`}
onValueChange={(value) => {
table.setPageSize(Number(value));
onSetPageSize && onSetPageSize(Number(value));
if (onSetPageSize) {
onSetPageSize(Number(value));
}
}}
>
<SelectTrigger className="h-8 w-[70px]">

View File

@@ -1,7 +1,7 @@
import { DotsHorizontalIcon } from "@radix-ui/react-icons";
import { Row } from "@tanstack/react-table";
import { DotsHorizontalIcon } from '@radix-ui/react-icons';
import { Row } from '@tanstack/react-table';
import { Button } from "@/components/ui/button";
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
@@ -14,9 +14,9 @@ import {
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
} from '@/components/ui/dropdown-menu';
import { IDGetter } from "./data-table";
import { IDGetter } from './data-table';
interface Label {
label: string;

View File

@@ -1,10 +1,10 @@
import { Cross2Icon } from "@radix-ui/react-icons";
import { Table } from "@tanstack/react-table";
import { Cross2Icon } from '@radix-ui/react-icons';
import { Table } from '@tanstack/react-table';
import { Button } from "@/components/ui/button";
import { DataTableViewOptions } from "./data-table-view-options";
import { Button } from '@/components/ui/button';
import { DataTableViewOptions } from './data-table-view-options';
import { DataTableFacetedFilter } from "./data-table-faceted-filter";
import { DataTableFacetedFilter } from './data-table-faceted-filter';
export interface FilterOption {
label: string;
@@ -51,7 +51,7 @@ export function DataTableToolbar<TData>({
title={filter.title}
options={filter.options}
/>
)
),
)}
{isFiltered && (
<Button

View File

@@ -1,15 +1,15 @@
import { DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu";
import { MixerHorizontalIcon } from "@radix-ui/react-icons";
import { Table } from "@tanstack/react-table";
import { DropdownMenuTrigger } from '@radix-ui/react-dropdown-menu';
import { MixerHorizontalIcon } from '@radix-ui/react-icons';
import { Table } from '@tanstack/react-table';
import { Button } from "@/components/ui/button";
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu";
} from '@/components/ui/dropdown-menu';
interface DataTableViewOptionsProps<TData> {
table: Table<TData>;
@@ -37,7 +37,7 @@ export function DataTableViewOptions<TData>({
.getAllColumns()
.filter(
(column) =>
typeof column.accessorFn !== "undefined" && column.getCanHide()
typeof column.accessorFn !== 'undefined' && column.getCanHide(),
)
.map((column) => {
return (

View File

@@ -1,4 +1,4 @@
import * as React from "react";
import * as React from 'react';
import {
ColumnDef,
ColumnFiltersState,
@@ -16,7 +16,7 @@ import {
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
} from '@tanstack/react-table';
import {
Table,
@@ -25,12 +25,12 @@ import {
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
} from '@/components/ui/table';
import { DataTablePagination } from "./data-table-pagination";
import { DataTableToolbar, ToolbarFilters } from "./data-table-toolbar";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import { DataTablePagination } from './data-table-pagination';
import { DataTableToolbar, ToolbarFilters } from './data-table-toolbar';
import { Skeleton } from '@/components/ui/skeleton';
import { cn } from '@/lib/utils';
export interface IDGetter {
metadata: {
@@ -64,7 +64,7 @@ interface DataTableProps<TData extends IDGetter, TValue> {
| ((
originalRow: TData,
index: number,
parent?: Row<TData> | undefined
parent?: Row<TData> | undefined,
) => string)
| undefined;
}
@@ -91,7 +91,7 @@ export function DataTable<TData extends IDGetter, TValue>({
}: DataTableProps<TData, TValue>) {
const tableData = React.useMemo(
() => (isLoading ? Array(10).fill({}) : data),
[isLoading, data]
[isLoading, data],
);
const tableColumns = React.useMemo(
@@ -102,7 +102,7 @@ export function DataTable<TData extends IDGetter, TValue>({
cell: () => <Skeleton className="h-4 w-[100px]" />,
}))
: columns,
[isLoading, columns]
[isLoading, columns],
);
const table = useReactTable({
@@ -142,9 +142,9 @@ export function DataTable<TData extends IDGetter, TValue>({
return (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
data-state={row.getIsSelected() && 'selected'}
className={cn(
row.original.isExpandable && "cursor-pointer hover:bg-muted"
row.original.isExpandable && 'cursor-pointer hover:bg-muted',
)}
onClick={row.original.onClick}
>
@@ -174,7 +174,7 @@ export function DataTable<TData extends IDGetter, TValue>({
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
header.getContext(),
)}
</TableHead>
);

View File

@@ -1,6 +1,6 @@
import { createContext, useContext, useEffect, useState } from "react";
import { createContext, useContext, useEffect, useState } from 'react';
type Theme = "dark" | "light" | "system";
type Theme = 'dark' | 'light' | 'system';
type ThemeProviderProps = {
children: React.ReactNode;
@@ -14,7 +14,7 @@ type ThemeProviderState = {
};
const initialState: ThemeProviderState = {
theme: "system",
theme: 'system',
setTheme: () => null,
};
@@ -22,24 +22,24 @@ const ThemeProviderContext = createContext<ThemeProviderState>(initialState);
export function ThemeProvider({
children,
defaultTheme = "system",
storageKey = "vite-ui-theme",
defaultTheme = 'system',
storageKey = 'vite-ui-theme',
...props
}: ThemeProviderProps) {
const [theme, setTheme] = useState<Theme>(
() => (localStorage.getItem(storageKey) as Theme) || defaultTheme
() => (localStorage.getItem(storageKey) as Theme) || defaultTheme,
);
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove("light", "dark");
root.classList.remove('light', 'dark');
if (theme === "system") {
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
if (theme === 'system') {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)')
.matches
? "dark"
: "light";
? 'dark'
: 'light';
root.classList.add(systemTheme);
return;
@@ -66,8 +66,9 @@ export function ThemeProvider({
export const useTheme = () => {
const context = useContext(ThemeProviderContext);
if (context === undefined)
throw new Error("useTheme must be used within a ThemeProvider");
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};

View File

@@ -1,10 +1,10 @@
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { ChevronDownIcon } from "@radix-ui/react-icons"
import * as React from 'react';
import * as AccordionPrimitive from '@radix-ui/react-accordion';
import { ChevronDownIcon } from '@radix-ui/react-icons';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const Accordion = AccordionPrimitive.Root
const Accordion = AccordionPrimitive.Root;
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
@@ -12,11 +12,11 @@ const AccordionItem = React.forwardRef<
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={cn("border-b", className)}
className={cn('border-b', className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"
));
AccordionItem.displayName = 'AccordionItem';
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
@@ -26,8 +26,8 @@ const AccordionTrigger = React.forwardRef<
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
'flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
className,
)}
{...props}
>
@@ -35,8 +35,8 @@ const AccordionTrigger = React.forwardRef<
<ChevronDownIcon className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
));
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
@@ -47,9 +47,9 @@ const AccordionContent = React.forwardRef<
className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
<div className={cn('pb-4 pt-0', className)}>{children}</div>
</AccordionPrimitive.Content>
))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
));
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };

View File

@@ -1,7 +1,7 @@
import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar"
import * as React from 'react';
import * as AvatarPrimitive from '@radix-ui/react-avatar';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
@@ -10,13 +10,13 @@ const Avatar = React.forwardRef<
<AvatarPrimitive.Root
ref={ref}
className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className
'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
className,
)}
{...props}
/>
))
Avatar.displayName = AvatarPrimitive.Root.displayName
));
Avatar.displayName = AvatarPrimitive.Root.displayName;
const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
@@ -24,11 +24,11 @@ const AvatarImage = React.forwardRef<
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn("aspect-square h-full w-full", className)}
className={cn('aspect-square h-full w-full', className)}
{...props}
/>
))
AvatarImage.displayName = AvatarPrimitive.Image.displayName
));
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
@@ -37,12 +37,12 @@ const AvatarFallback = React.forwardRef<
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted",
className
'flex h-full w-full items-center justify-center rounded-full bg-muted',
className,
)}
{...props}
/>
))
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
));
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
export { Avatar, AvatarImage, AvatarFallback }
export { Avatar, AvatarImage, AvatarFallback };

View File

@@ -1,32 +1,32 @@
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from "@/lib/utils";
import { cn } from '@/lib/utils';
const badgeVariants = cva(
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
destructive:
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
outline: "text-foreground",
'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
outline: 'text-foreground',
successful:
"border-transparent rounded-sm px-1 font-normal text-green-400 bg-green-500/20 ring-green-500/30",
'border-transparent rounded-sm px-1 font-normal text-green-400 bg-green-500/20 ring-green-500/30',
failed:
"border-transparent rounded-sm px-1 font-normal text-red-400 bg-red-500/20 ring-red-500/30",
'border-transparent rounded-sm px-1 font-normal text-red-400 bg-red-500/20 ring-red-500/30',
inProgress:
"border-transparent rounded-sm px-1 font-normal text-yellow-400 bg-yellow-500/20 ring-yellow-500/30",
'border-transparent rounded-sm px-1 font-normal text-yellow-400 bg-yellow-500/20 ring-yellow-500/30',
},
},
defaultVariants: {
variant: "default",
variant: 'default',
},
}
},
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,

View File

@@ -1,57 +1,57 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from 'react';
import { Slot } from '@radix-ui/react-slot';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
'bg-primary text-primary-foreground shadow hover:bg-primary/90',
destructive:
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
outline:
"border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground",
'border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground',
secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
default: 'h-9 px-4 py-2',
sm: 'h-8 rounded-md px-3 text-xs',
lg: 'h-10 rounded-md px-8',
icon: 'h-9 w-9',
},
},
defaultVariants: {
variant: "default",
size: "default",
variant: 'default',
size: 'default',
},
}
)
},
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
asChild?: boolean;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
const Comp = asChild ? Slot : 'button';
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
);
},
);
Button.displayName = 'Button';
export { Button, buttonVariants }
export { Button, buttonVariants };

View File

@@ -1,8 +1,8 @@
import * as React from "react"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
import { CheckIcon } from "@radix-ui/react-icons"
import * as React from 'react';
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
import { CheckIcon } from '@radix-ui/react-icons';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
@@ -11,18 +11,18 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className
'peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
className,
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")}
className={cn('flex items-center justify-center text-current')}
>
<CheckIcon className="h-4 w-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
))
Checkbox.displayName = CheckboxPrimitive.Root.displayName
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
export { Checkbox }
export { Checkbox };

View File

@@ -1,15 +1,15 @@
import { cn } from "@/lib/utils";
import { Light as SyntaxHighlighter } from "react-syntax-highlighter";
import { cn } from '@/lib/utils';
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
import typescript from "react-syntax-highlighter/dist/esm/languages/hljs/typescript";
import yaml from "react-syntax-highlighter/dist/esm/languages/hljs/yaml";
import json from "react-syntax-highlighter/dist/esm/languages/hljs/json";
import typescript from 'react-syntax-highlighter/dist/esm/languages/hljs/typescript';
import yaml from 'react-syntax-highlighter/dist/esm/languages/hljs/yaml';
import json from 'react-syntax-highlighter/dist/esm/languages/hljs/json';
import { anOldHope } from "react-syntax-highlighter/dist/esm/styles/hljs";
import { anOldHope } from 'react-syntax-highlighter/dist/esm/styles/hljs';
SyntaxHighlighter.registerLanguage("typescript", typescript);
SyntaxHighlighter.registerLanguage("yaml", yaml);
SyntaxHighlighter.registerLanguage("json", json);
SyntaxHighlighter.registerLanguage('typescript', typescript);
SyntaxHighlighter.registerLanguage('yaml', yaml);
SyntaxHighlighter.registerLanguage('json', json);
export function Code({
children,
@@ -23,19 +23,20 @@ export function Code({
maxHeight?: string;
}) {
return (
<div className={cn("text-xs", className)}>
<div className={cn('text-xs', className)}>
<SyntaxHighlighter
children={children.trim()}
language={language}
style={anOldHope}
customStyle={{
background: "hsl(var(--muted) / 0.5)",
borderRadius: "0.5rem",
background: 'hsl(var(--muted) / 0.5)',
borderRadius: '0.5rem',
maxHeight: maxHeight,
fontFamily:
"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
}}
/>
>
{children.trim()}
</SyntaxHighlighter>
</div>
);
}

View File

@@ -1,10 +1,10 @@
import * as React from "react"
import { type DialogProps } from "@radix-ui/react-dialog"
import { MagnifyingGlassIcon } from "@radix-ui/react-icons"
import { Command as CommandPrimitive } from "cmdk"
import * as React from 'react';
import { type DialogProps } from '@radix-ui/react-dialog';
import { MagnifyingGlassIcon } from '@radix-ui/react-icons';
import { Command as CommandPrimitive } from 'cmdk';
import { cn } from "@/lib/utils"
import { Dialog, DialogContent } from "@/components/ui/dialog"
import { cn } from '@/lib/utils';
import { Dialog, DialogContent } from '@/components/ui/dialog';
const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>,
@@ -13,13 +13,13 @@ const Command = React.forwardRef<
<CommandPrimitive
ref={ref}
className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className
'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
className,
)}
{...props}
/>
))
Command.displayName = CommandPrimitive.displayName
));
Command.displayName = CommandPrimitive.displayName;
interface CommandDialogProps extends DialogProps {}
@@ -32,27 +32,31 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
</Command>
</DialogContent>
</Dialog>
)
}
);
};
const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>(({ className, ...props }, ref) => (
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<MagnifyingGlassIcon className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
ref={ref}
className={cn(
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
/>
</div>
))
>(({ className, ...props }, ref) => {
// noinspection HtmlUnknownAttribute
return (
// eslint-disable-next-line react/no-unknown-property
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<MagnifyingGlassIcon className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
ref={ref}
className={cn(
'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
{...props}
/>
</div>
);
});
CommandInput.displayName = CommandPrimitive.Input.displayName
CommandInput.displayName = CommandPrimitive.Input.displayName;
const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>,
@@ -60,12 +64,12 @@ const CommandList = React.forwardRef<
>(({ className, ...props }, ref) => (
<CommandPrimitive.List
ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
{...props}
/>
))
));
CommandList.displayName = CommandPrimitive.List.displayName
CommandList.displayName = CommandPrimitive.List.displayName;
const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
@@ -76,9 +80,9 @@ const CommandEmpty = React.forwardRef<
className="py-6 text-center text-sm"
{...props}
/>
))
));
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>,
@@ -87,14 +91,14 @@ const CommandGroup = React.forwardRef<
<CommandPrimitive.Group
ref={ref}
className={cn(
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
className
'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
className,
)}
{...props}
/>
))
));
CommandGroup.displayName = CommandPrimitive.Group.displayName
CommandGroup.displayName = CommandPrimitive.Group.displayName;
const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
@@ -102,11 +106,11 @@ const CommandSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator
ref={ref}
className={cn("-mx-1 h-px bg-border", className)}
className={cn('-mx-1 h-px bg-border', className)}
{...props}
/>
))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
));
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
@@ -115,14 +119,14 @@ const CommandItem = React.forwardRef<
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className,
)}
{...props}
/>
))
));
CommandItem.displayName = CommandPrimitive.Item.displayName
CommandItem.displayName = CommandPrimitive.Item.displayName;
const CommandShortcut = ({
className,
@@ -131,14 +135,14 @@ const CommandShortcut = ({
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
'ml-auto text-xs tracking-widest text-muted-foreground',
className,
)}
{...props}
/>
)
}
CommandShortcut.displayName = "CommandShortcut"
);
};
CommandShortcut.displayName = 'CommandShortcut';
export {
Command,
@@ -150,4 +154,4 @@ export {
CommandItem,
CommandShortcut,
CommandSeparator,
}
};

View File

@@ -1,16 +1,16 @@
import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog"
import { Cross2Icon } from "@radix-ui/react-icons"
import * as React from 'react';
import * as DialogPrimitive from '@radix-ui/react-dialog';
import { Cross2Icon } from '@radix-ui/react-icons';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const Dialog = DialogPrimitive.Root
const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger
const DialogTrigger = DialogPrimitive.Trigger;
const DialogPortal = DialogPrimitive.Portal
const DialogPortal = DialogPrimitive.Portal;
const DialogClose = DialogPrimitive.Close
const DialogClose = DialogPrimitive.Close;
const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>,
@@ -19,13 +19,13 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
'fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
className,
)}
{...props}
/>
))
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
@@ -36,8 +36,8 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
className
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
className,
)}
{...props}
>
@@ -48,8 +48,8 @@ const DialogContent = React.forwardRef<
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPortal>
))
DialogContent.displayName = DialogPrimitive.Content.displayName
));
DialogContent.displayName = DialogPrimitive.Content.displayName;
const DialogHeader = ({
className,
@@ -57,13 +57,13 @@ const DialogHeader = ({
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-1.5 text-center sm:text-left",
className
'flex flex-col space-y-1.5 text-center sm:text-left',
className,
)}
{...props}
/>
)
DialogHeader.displayName = "DialogHeader"
);
DialogHeader.displayName = 'DialogHeader';
const DialogFooter = ({
className,
@@ -71,13 +71,13 @@ const DialogFooter = ({
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
className,
)}
{...props}
/>
)
DialogFooter.displayName = "DialogFooter"
);
DialogFooter.displayName = 'DialogFooter';
const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>,
@@ -86,13 +86,13 @@ const DialogTitle = React.forwardRef<
<DialogPrimitive.Title
ref={ref}
className={cn(
"text-lg font-semibold leading-none tracking-tight",
className
'text-lg font-semibold leading-none tracking-tight',
className,
)}
{...props}
/>
))
DialogTitle.displayName = DialogPrimitive.Title.displayName
));
DialogTitle.displayName = DialogPrimitive.Title.displayName;
const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>,
@@ -100,11 +100,11 @@ const DialogDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
className={cn('text-sm text-muted-foreground', className)}
{...props}
/>
))
DialogDescription.displayName = DialogPrimitive.Description.displayName
));
DialogDescription.displayName = DialogPrimitive.Description.displayName;
export {
Dialog,
@@ -117,4 +117,4 @@ export {
DialogFooter,
DialogTitle,
DialogDescription,
}
};

View File

@@ -1,46 +1,46 @@
import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import * as React from 'react';
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
import {
CheckIcon,
ChevronRightIcon,
DotFilledIcon,
} from "@radix-ui/react-icons"
} from '@radix-ui/react-icons';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const DropdownMenu = DropdownMenuPrimitive.Root
const DropdownMenu = DropdownMenuPrimitive.Root;
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
const DropdownMenuGroup = DropdownMenuPrimitive.Group
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
const DropdownMenuSub = DropdownMenuPrimitive.Sub
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean
inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
inset && "pl-8",
className
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
inset && 'pl-8',
className,
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto h-4 w-4" />
</DropdownMenuPrimitive.SubTrigger>
))
));
DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName
DropdownMenuPrimitive.SubTrigger.displayName;
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
@@ -49,14 +49,14 @@ const DropdownMenuSubContent = React.forwardRef<
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
))
));
DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName
DropdownMenuPrimitive.SubContent.displayName;
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
@@ -67,33 +67,33 @@ const DropdownMenuContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
))
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
));
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
inset && 'pl-8',
className,
)}
{...props}
/>
))
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
));
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
@@ -102,8 +102,8 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className,
)}
checked={checked}
{...props}
@@ -115,9 +115,9 @@ const DropdownMenuCheckboxItem = React.forwardRef<
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
))
));
DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName
DropdownMenuPrimitive.CheckboxItem.displayName;
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
@@ -126,8 +126,8 @@ const DropdownMenuRadioItem = React.forwardRef<
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className,
)}
{...props}
>
@@ -138,26 +138,26 @@ const DropdownMenuRadioItem = React.forwardRef<
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
))
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
));
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Label
ref={ref}
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
'px-2 py-1.5 text-sm font-semibold',
inset && 'pl-8',
className,
)}
{...props}
/>
))
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
));
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
@@ -165,11 +165,11 @@ const DropdownMenuSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
className={cn('-mx-1 my-1 h-px bg-muted', className)}
{...props}
/>
))
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
const DropdownMenuShortcut = ({
className,
@@ -177,12 +177,12 @@ const DropdownMenuShortcut = ({
}: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
className={cn('ml-auto text-xs tracking-widest opacity-60', className)}
{...props}
/>
)
}
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
);
};
DropdownMenuShortcut.displayName = 'DropdownMenuShortcut';
export {
DropdownMenu,
@@ -200,4 +200,4 @@ export {
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
}
};

View File

@@ -1,27 +1,27 @@
import * as React from "react"
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
import * as React from 'react';
import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const HoverCard = HoverCardPrimitive.Root
const HoverCard = HoverCardPrimitive.Root;
const HoverCardTrigger = HoverCardPrimitive.Trigger
const HoverCardTrigger = HoverCardPrimitive.Trigger;
const HoverCardContent = React.forwardRef<
React.ElementRef<typeof HoverCardPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<HoverCardPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
'z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
))
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
));
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
export { HoverCard, HoverCardTrigger, HoverCardContent }
export { HoverCard, HoverCardTrigger, HoverCardContent };

View File

@@ -1,6 +1,6 @@
import * as React from "react"
import * as React from 'react';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
@@ -11,15 +11,15 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
ref={ref}
{...props}
/>
)
}
)
Input.displayName = "Input"
);
},
);
Input.displayName = 'Input';
export { Input }
export { Input };

View File

@@ -1,12 +1,12 @@
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from 'react';
import * as LabelPrimitive from '@radix-ui/react-label';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
);
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
@@ -18,7 +18,7 @@ const Label = React.forwardRef<
className={cn(labelVariants(), className)}
{...props}
/>
))
Label.displayName = LabelPrimitive.Root.displayName
));
Label.displayName = LabelPrimitive.Root.displayName;
export { Label }
export { Label };

View File

@@ -1,22 +1,22 @@
import * as React from "react"
import * as React from 'react';
import {
CheckIcon,
ChevronRightIcon,
DotFilledIcon,
} from "@radix-ui/react-icons"
import * as MenubarPrimitive from "@radix-ui/react-menubar"
} from '@radix-ui/react-icons';
import * as MenubarPrimitive from '@radix-ui/react-menubar';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const MenubarMenu = MenubarPrimitive.Menu
const MenubarMenu = MenubarPrimitive.Menu;
const MenubarGroup = MenubarPrimitive.Group
const MenubarGroup = MenubarPrimitive.Group;
const MenubarPortal = MenubarPrimitive.Portal
const MenubarPortal = MenubarPrimitive.Portal;
const MenubarSub = MenubarPrimitive.Sub
const MenubarSub = MenubarPrimitive.Sub;
const MenubarRadioGroup = MenubarPrimitive.RadioGroup
const MenubarRadioGroup = MenubarPrimitive.RadioGroup;
const Menubar = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Root>,
@@ -25,13 +25,13 @@ const Menubar = React.forwardRef<
<MenubarPrimitive.Root
ref={ref}
className={cn(
"flex h-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-sm",
className
'flex h-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-sm',
className,
)}
{...props}
/>
))
Menubar.displayName = MenubarPrimitive.Root.displayName
));
Menubar.displayName = MenubarPrimitive.Root.displayName;
const MenubarTrigger = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Trigger>,
@@ -40,34 +40,34 @@ const MenubarTrigger = React.forwardRef<
<MenubarPrimitive.Trigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
className
'flex cursor-default select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
className,
)}
{...props}
/>
))
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
));
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
const MenubarSubTrigger = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
inset?: boolean
inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
<MenubarPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
inset && "pl-8",
className
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
inset && 'pl-8',
className,
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto h-4 w-4" />
</MenubarPrimitive.SubTrigger>
))
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
));
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
const MenubarSubContent = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.SubContent>,
@@ -76,21 +76,21 @@ const MenubarSubContent = React.forwardRef<
<MenubarPrimitive.SubContent
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
))
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
));
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
const MenubarContent = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
>(
(
{ className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
ref
{ className, align = 'start', alignOffset = -4, sideOffset = 8, ...props },
ref,
) => (
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content
@@ -99,33 +99,33 @@ const MenubarContent = React.forwardRef<
alignOffset={alignOffset}
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
'z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
</MenubarPrimitive.Portal>
)
)
MenubarContent.displayName = MenubarPrimitive.Content.displayName
),
);
MenubarContent.displayName = MenubarPrimitive.Content.displayName;
const MenubarItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
inset?: boolean
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<MenubarPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
inset && 'pl-8',
className,
)}
{...props}
/>
))
MenubarItem.displayName = MenubarPrimitive.Item.displayName
));
MenubarItem.displayName = MenubarPrimitive.Item.displayName;
const MenubarCheckboxItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
@@ -134,8 +134,8 @@ const MenubarCheckboxItem = React.forwardRef<
<MenubarPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className,
)}
checked={checked}
{...props}
@@ -147,8 +147,8 @@ const MenubarCheckboxItem = React.forwardRef<
</span>
{children}
</MenubarPrimitive.CheckboxItem>
))
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
));
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
const MenubarRadioItem = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.RadioItem>,
@@ -157,8 +157,8 @@ const MenubarRadioItem = React.forwardRef<
<MenubarPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className,
)}
{...props}
>
@@ -169,26 +169,26 @@ const MenubarRadioItem = React.forwardRef<
</span>
{children}
</MenubarPrimitive.RadioItem>
))
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
));
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
const MenubarLabel = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
inset?: boolean
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<MenubarPrimitive.Label
ref={ref}
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
'px-2 py-1.5 text-sm font-semibold',
inset && 'pl-8',
className,
)}
{...props}
/>
))
MenubarLabel.displayName = MenubarPrimitive.Label.displayName
));
MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
const MenubarSeparator = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Separator>,
@@ -196,11 +196,11 @@ const MenubarSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<MenubarPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
className={cn('-mx-1 my-1 h-px bg-muted', className)}
{...props}
/>
))
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
));
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
const MenubarShortcut = ({
className,
@@ -209,14 +209,14 @@ const MenubarShortcut = ({
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
'ml-auto text-xs tracking-widest text-muted-foreground',
className,
)}
{...props}
/>
)
}
MenubarShortcut.displayname = "MenubarShortcut"
);
};
MenubarShortcut.displayname = 'MenubarShortcut';
export {
Menubar,
@@ -235,4 +235,4 @@ export {
MenubarGroup,
MenubarSub,
MenubarShortcut,
}
};

View File

@@ -1,29 +1,29 @@
import * as React from "react"
import * as PopoverPrimitive from "@radix-ui/react-popover"
import * as React from 'react';
import * as PopoverPrimitive from '@radix-ui/react-popover';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const Popover = PopoverPrimitive.Root
const Popover = PopoverPrimitive.Root;
const PopoverTrigger = PopoverPrimitive.Trigger
const PopoverTrigger = PopoverPrimitive.Trigger;
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
</PopoverPrimitive.Portal>
))
PopoverContent.displayName = PopoverPrimitive.Content.displayName
));
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
export { Popover, PopoverTrigger, PopoverContent }
export { Popover, PopoverTrigger, PopoverContent };

View File

@@ -1,19 +1,19 @@
import * as React from "react"
import * as React from 'react';
import {
CaretSortIcon,
CheckIcon,
ChevronDownIcon,
ChevronUpIcon,
} from "@radix-ui/react-icons"
import * as SelectPrimitive from "@radix-ui/react-select"
} from '@radix-ui/react-icons';
import * as SelectPrimitive from '@radix-ui/react-select';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const Select = SelectPrimitive.Root
const Select = SelectPrimitive.Root;
const SelectGroup = SelectPrimitive.Group
const SelectGroup = SelectPrimitive.Group;
const SelectValue = SelectPrimitive.Value
const SelectValue = SelectPrimitive.Value;
const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
@@ -22,8 +22,8 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
className,
)}
{...props}
>
@@ -32,8 +32,8 @@ const SelectTrigger = React.forwardRef<
<CaretSortIcon className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
))
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
@@ -42,15 +42,15 @@ const SelectScrollUpButton = React.forwardRef<
<SelectPrimitive.ScrollUpButton
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className
'flex cursor-default items-center justify-center py-1',
className,
)}
{...props}
>
<ChevronUpIcon />
</SelectPrimitive.ScrollUpButton>
))
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
@@ -59,29 +59,29 @@ const SelectScrollDownButton = React.forwardRef<
<SelectPrimitive.ScrollDownButton
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className
'flex cursor-default items-center justify-center py-1',
className,
)}
{...props}
>
<ChevronDownIcon />
</SelectPrimitive.ScrollDownButton>
))
));
SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName
SelectPrimitive.ScrollDownButton.displayName;
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => (
>(({ className, children, position = 'popper', ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
className,
)}
position={position}
{...props}
@@ -89,9 +89,9 @@ const SelectContent = React.forwardRef<
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
"p-1",
position === "popper" &&
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
'p-1',
position === 'popper' &&
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]',
)}
>
{children}
@@ -99,8 +99,8 @@ const SelectContent = React.forwardRef<
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
))
SelectContent.displayName = SelectPrimitive.Content.displayName
));
SelectContent.displayName = SelectPrimitive.Content.displayName;
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
@@ -108,11 +108,11 @@ const SelectLabel = React.forwardRef<
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={cn("px-2 py-1.5 text-sm font-semibold", className)}
className={cn('px-2 py-1.5 text-sm font-semibold', className)}
{...props}
/>
))
SelectLabel.displayName = SelectPrimitive.Label.displayName
));
SelectLabel.displayName = SelectPrimitive.Label.displayName;
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
@@ -121,8 +121,8 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className,
)}
{...props}
>
@@ -133,8 +133,8 @@ const SelectItem = React.forwardRef<
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName
));
SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
@@ -142,11 +142,11 @@ const SelectSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
className={cn('-mx-1 my-1 h-px bg-muted', className)}
{...props}
/>
))
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
export {
Select,
@@ -159,4 +159,4 @@ export {
SelectSeparator,
SelectScrollUpButton,
SelectScrollDownButton,
}
};

View File

@@ -1,29 +1,29 @@
import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"
import * as React from 'react';
import * as SeparatorPrimitive from '@radix-ui/react-separator';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(
(
{ className, orientation = "horizontal", decorative = true, ...props },
ref
{ className, orientation = 'horizontal', decorative = true, ...props },
ref,
) => (
<SeparatorPrimitive.Root
ref={ref}
decorative={decorative}
orientation={orientation}
className={cn(
"shrink-0 bg-border",
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
className
'shrink-0 bg-border',
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
className,
)}
{...props}
/>
)
)
Separator.displayName = SeparatorPrimitive.Root.displayName
),
);
Separator.displayName = SeparatorPrimitive.Root.displayName;
export { Separator }
export { Separator };

View File

@@ -1,4 +1,4 @@
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
function Skeleton({
className,
@@ -6,10 +6,10 @@ function Skeleton({
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-primary/10", className)}
className={cn('animate-pulse rounded-md bg-primary/10', className)}
{...props}
/>
)
);
}
export { Skeleton }
export { Skeleton };

View File

@@ -1,6 +1,6 @@
import * as React from "react"
import * as React from 'react';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const Table = React.forwardRef<
HTMLTableElement,
@@ -9,20 +9,20 @@ const Table = React.forwardRef<
<div className="relative w-full overflow-auto">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
className={cn('w-full caption-bottom text-sm', className)}
{...props}
/>
</div>
))
Table.displayName = "Table"
));
Table.displayName = 'Table';
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
))
TableHeader.displayName = "TableHeader"
<thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />
));
TableHeader.displayName = 'TableHeader';
const TableBody = React.forwardRef<
HTMLTableSectionElement,
@@ -30,11 +30,11 @@ const TableBody = React.forwardRef<
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
className={cn('[&_tr:last-child]:border-0', className)}
{...props}
/>
))
TableBody.displayName = "TableBody"
));
TableBody.displayName = 'TableBody';
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
@@ -43,13 +43,13 @@ const TableFooter = React.forwardRef<
<tfoot
ref={ref}
className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className
'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',
className,
)}
{...props}
/>
))
TableFooter.displayName = "TableFooter"
));
TableFooter.displayName = 'TableFooter';
const TableRow = React.forwardRef<
HTMLTableRowElement,
@@ -58,13 +58,13 @@ const TableRow = React.forwardRef<
<tr
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
className,
)}
{...props}
/>
))
TableRow.displayName = "TableRow"
));
TableRow.displayName = 'TableRow';
const TableHead = React.forwardRef<
HTMLTableCellElement,
@@ -73,13 +73,13 @@ const TableHead = React.forwardRef<
<th
ref={ref}
className={cn(
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
'h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
className,
)}
{...props}
/>
))
TableHead.displayName = "TableHead"
));
TableHead.displayName = 'TableHead';
const TableCell = React.forwardRef<
HTMLTableCellElement,
@@ -88,13 +88,13 @@ const TableCell = React.forwardRef<
<td
ref={ref}
className={cn(
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
'p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
className,
)}
{...props}
/>
))
TableCell.displayName = "TableCell"
));
TableCell.displayName = 'TableCell';
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
@@ -102,11 +102,11 @@ const TableCaption = React.forwardRef<
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
className={cn('mt-4 text-sm text-muted-foreground', className)}
{...props}
/>
))
TableCaption.displayName = "TableCaption"
));
TableCaption.displayName = 'TableCaption';
export {
Table,
@@ -117,4 +117,4 @@ export {
TableRow,
TableCell,
TableCaption,
}
};

View File

@@ -1,11 +1,11 @@
import * as React from "react"
import { Cross2Icon } from "@radix-ui/react-icons"
import * as ToastPrimitives from "@radix-ui/react-toast"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from 'react';
import { Cross2Icon } from '@radix-ui/react-icons';
import * as ToastPrimitives from '@radix-ui/react-toast';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const ToastProvider = ToastPrimitives.Provider
const ToastProvider = ToastPrimitives.Provider;
const ToastViewport = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Viewport>,
@@ -14,29 +14,29 @@ const ToastViewport = React.forwardRef<
<ToastPrimitives.Viewport
ref={ref}
className={cn(
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
className
'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',
className,
)}
{...props}
/>
))
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
));
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
const toastVariants = cva(
"group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
'group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
{
variants: {
variant: {
default: "border bg-background text-foreground",
default: 'border bg-background text-foreground',
destructive:
"destructive group border-destructive bg-destructive text-destructive-foreground",
'destructive group border-destructive bg-destructive text-destructive-foreground',
},
},
defaultVariants: {
variant: "default",
variant: 'default',
},
}
)
},
);
const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
@@ -49,9 +49,9 @@ const Toast = React.forwardRef<
className={cn(toastVariants({ variant }), className)}
{...props}
/>
)
})
Toast.displayName = ToastPrimitives.Root.displayName
);
});
Toast.displayName = ToastPrimitives.Root.displayName;
const ToastAction = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Action>,
@@ -60,13 +60,13 @@ const ToastAction = React.forwardRef<
<ToastPrimitives.Action
ref={ref}
className={cn(
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
className
'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive',
className,
)}
{...props}
/>
))
ToastAction.displayName = ToastPrimitives.Action.displayName
));
ToastAction.displayName = ToastPrimitives.Action.displayName;
const ToastClose = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Close>,
@@ -75,16 +75,16 @@ const ToastClose = React.forwardRef<
<ToastPrimitives.Close
ref={ref}
className={cn(
"absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
className
'absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600',
className,
)}
toast-close=""
{...props}
>
<Cross2Icon className="h-4 w-4" />
</ToastPrimitives.Close>
))
ToastClose.displayName = ToastPrimitives.Close.displayName
));
ToastClose.displayName = ToastPrimitives.Close.displayName;
const ToastTitle = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Title>,
@@ -92,11 +92,11 @@ const ToastTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
<ToastPrimitives.Title
ref={ref}
className={cn("text-sm font-semibold [&+div]:text-xs", className)}
className={cn('text-sm font-semibold [&+div]:text-xs', className)}
{...props}
/>
))
ToastTitle.displayName = ToastPrimitives.Title.displayName
));
ToastTitle.displayName = ToastPrimitives.Title.displayName;
const ToastDescription = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Description>,
@@ -104,15 +104,15 @@ const ToastDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<ToastPrimitives.Description
ref={ref}
className={cn("text-sm opacity-90", className)}
className={cn('text-sm opacity-90', className)}
{...props}
/>
))
ToastDescription.displayName = ToastPrimitives.Description.displayName
));
ToastDescription.displayName = ToastPrimitives.Description.displayName;
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
type ToastActionElement = React.ReactElement<typeof ToastAction>
type ToastActionElement = React.ReactElement<typeof ToastAction>;
export {
type ToastProps,
@@ -124,4 +124,4 @@ export {
ToastDescription,
ToastClose,
ToastAction,
}
};

View File

@@ -5,11 +5,11 @@ import {
ToastProvider,
ToastTitle,
ToastViewport,
} from "@/components/ui/toast"
import { useToast } from "@/components/ui/use-toast"
} from '@/components/ui/toast';
import { useToast } from '@/components/ui/use-toast';
export function Toaster() {
const { toasts } = useToast()
const { toasts } = useToast();
return (
<ToastProvider>
@@ -25,9 +25,9 @@ export function Toaster() {
{action}
<ToastClose />
</Toast>
)
);
})}
<ToastViewport />
</ToastProvider>
)
);
}

View File

@@ -1,104 +1,101 @@
// Inspired by react-hot-toast library
import * as React from "react"
import * as React from 'react';
import type {
ToastActionElement,
ToastProps,
} from "@/components/ui/toast"
import type { ToastActionElement, ToastProps } from '@/components/ui/toast';
const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000
const TOAST_LIMIT = 1;
const TOAST_REMOVE_DELAY = 1000000;
type ToasterToast = ToastProps & {
id: string
title?: React.ReactNode
description?: React.ReactNode
action?: ToastActionElement
}
id: string;
title?: React.ReactNode;
description?: React.ReactNode;
action?: ToastActionElement;
};
const actionTypes = {
ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST",
} as const
ADD_TOAST: 'ADD_TOAST',
UPDATE_TOAST: 'UPDATE_TOAST',
DISMISS_TOAST: 'DISMISS_TOAST',
REMOVE_TOAST: 'REMOVE_TOAST',
} as const;
let count = 0
let count = 0;
function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER
return count.toString()
count = (count + 1) % Number.MAX_SAFE_INTEGER;
return count.toString();
}
type ActionType = typeof actionTypes
type ActionType = typeof actionTypes;
type Action =
| {
type: ActionType["ADD_TOAST"]
toast: ToasterToast
type: ActionType['ADD_TOAST'];
toast: ToasterToast;
}
| {
type: ActionType["UPDATE_TOAST"]
toast: Partial<ToasterToast>
type: ActionType['UPDATE_TOAST'];
toast: Partial<ToasterToast>;
}
| {
type: ActionType["DISMISS_TOAST"]
toastId?: ToasterToast["id"]
type: ActionType['DISMISS_TOAST'];
toastId?: ToasterToast['id'];
}
| {
type: ActionType["REMOVE_TOAST"]
toastId?: ToasterToast["id"]
}
type: ActionType['REMOVE_TOAST'];
toastId?: ToasterToast['id'];
};
interface State {
toasts: ToasterToast[]
toasts: ToasterToast[];
}
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
return
return;
}
const timeout = setTimeout(() => {
toastTimeouts.delete(toastId)
toastTimeouts.delete(toastId);
dispatch({
type: "REMOVE_TOAST",
type: 'REMOVE_TOAST',
toastId: toastId,
})
}, TOAST_REMOVE_DELAY)
});
}, TOAST_REMOVE_DELAY);
toastTimeouts.set(toastId, timeout)
}
toastTimeouts.set(toastId, timeout);
};
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "ADD_TOAST":
case 'ADD_TOAST':
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
}
};
case "UPDATE_TOAST":
case 'UPDATE_TOAST':
return {
...state,
toasts: state.toasts.map((t) =>
t.id === action.toast.id ? { ...t, ...action.toast } : t
t.id === action.toast.id ? { ...t, ...action.toast } : t,
),
}
};
case "DISMISS_TOAST": {
const { toastId } = action
case 'DISMISS_TOAST': {
const { toastId } = action;
// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId)
addToRemoveQueue(toastId);
} else {
state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id)
})
addToRemoveQueue(toast.id);
});
}
return {
@@ -109,84 +106,86 @@ export const reducer = (state: State, action: Action): State => {
...t,
open: false,
}
: t
: t,
),
}
};
}
case "REMOVE_TOAST":
case 'REMOVE_TOAST':
if (action.toastId === undefined) {
return {
...state,
toasts: [],
}
};
}
return {
...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId),
}
};
}
}
};
const listeners: Array<(state: State) => void> = []
const listeners: Array<(state: State) => void> = [];
let memoryState: State = { toasts: [] }
let memoryState: State = { toasts: [] };
function dispatch(action: Action) {
memoryState = reducer(memoryState, action)
memoryState = reducer(memoryState, action);
listeners.forEach((listener) => {
listener(memoryState)
})
listener(memoryState);
});
}
type Toast = Omit<ToasterToast, "id">
type Toast = Omit<ToasterToast, 'id'>;
function toast({ ...props }: Toast) {
const id = genId()
const id = genId();
const update = (props: ToasterToast) =>
dispatch({
type: "UPDATE_TOAST",
type: 'UPDATE_TOAST',
toast: { ...props, id },
})
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
});
const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id });
dispatch({
type: "ADD_TOAST",
type: 'ADD_TOAST',
toast: {
...props,
id,
open: true,
onOpenChange: (open) => {
if (!open) dismiss()
if (!open) {
dismiss();
}
},
},
})
});
return {
id: id,
dismiss,
update,
}
};
}
function useToast() {
const [state, setState] = React.useState<State>(memoryState)
const [state, setState] = React.useState<State>(memoryState);
React.useEffect(() => {
listeners.push(setState)
listeners.push(setState);
return () => {
const index = listeners.indexOf(setState)
const index = listeners.indexOf(setState);
if (index > -1) {
listeners.splice(index, 1)
listeners.splice(index, 1);
}
}
}, [state])
};
}, [state]);
return {
...state,
toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
}
dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }),
};
}
export { useToast, toast }
export { useToast, toast };

View File

@@ -1,8 +1,8 @@
import { Api } from "./generated/Api";
import qs from "qs";
import { Api } from './generated/Api';
import qs from 'qs';
const api = new Api({
paramsSerializer: (params) => qs.stringify(params, { arrayFormat: "repeat" }),
paramsSerializer: (params) => qs.stringify(params, { arrayFormat: 'repeat' }),
});
export default api;

View File

@@ -1,4 +1,4 @@
import api from "./api";
export * from "./generated/data-contracts";
export { queries } from "./queries";
import api from './api';
export * from './generated/data-contracts';
export { queries } from './queries';
export default api;

View File

@@ -1,6 +1,6 @@
import { createQueryKeyStore } from "@lukemorales/query-key-factory";
import { createQueryKeyStore } from '@lukemorales/query-key-factory';
import api from "./api";
import api from './api';
type ListEventQuery = Parameters<typeof api.eventList>[1];
type ListWorkflowRunsQuery = Parameters<typeof api.workflowRunList>[1];
@@ -8,17 +8,17 @@ type ListWorkflowRunsQuery = Parameters<typeof api.workflowRunList>[1];
export const queries = createQueryKeyStore({
user: {
current: {
queryKey: ["user:get"],
queryKey: ['user:get'],
queryFn: async () => (await api.userGetCurrent()).data,
},
},
workflows: {
list: (tenant: string) => ({
queryKey: ["workflow:list", tenant],
queryKey: ['workflow:list', tenant],
queryFn: async () => (await api.workflowList(tenant)).data,
}),
getVersion: (workflow: string, version?: string) => ({
queryKey: ["workflow-version:get", workflow, version],
queryKey: ['workflow-version:get', workflow, version],
queryFn: async () =>
(
await api.workflowVersionGet(workflow, {
@@ -27,7 +27,7 @@ export const queries = createQueryKeyStore({
).data,
}),
getDefinition: (workflow: string, version?: string) => ({
queryKey: ["workflow-version:get:definition", workflow, version],
queryKey: ['workflow-version:get:definition', workflow, version],
queryFn: async () =>
(
await api.workflowVersionGetDefinition(workflow, {
@@ -38,35 +38,35 @@ export const queries = createQueryKeyStore({
},
workflowRuns: {
list: (tenant: string, query: ListWorkflowRunsQuery) => ({
queryKey: ["workflow-run:list", tenant, query],
queryKey: ['workflow-run:list', tenant, query],
queryFn: async () => (await api.workflowRunList(tenant, query)).data,
}),
get: (tenant: string, workflowRun: string) => ({
queryKey: ["workflow-run:get", tenant, workflowRun],
queryKey: ['workflow-run:get', tenant, workflowRun],
queryFn: async () => (await api.workflowRunGet(tenant, workflowRun)).data,
}),
},
events: {
list: (tenant: string, query: ListEventQuery) => ({
queryKey: ["event:list", tenant, query],
queryKey: ['event:list', tenant, query],
queryFn: async () => (await api.eventList(tenant, query)).data,
}),
listKeys: (tenant: string) => ({
queryKey: ["event-keys:list", tenant],
queryKey: ['event-keys:list', tenant],
queryFn: async () => (await api.eventKeyList(tenant)).data,
}),
getData: (event: string) => ({
queryKey: ["event-data:get", event],
queryKey: ['event-data:get', event],
queryFn: async () => (await api.eventDataGet(event)).data,
}),
},
workers: {
list: (tenant: string) => ({
queryKey: ["worker:list", tenant],
queryKey: ['worker:list', tenant],
queryFn: async () => (await api.workerList(tenant)).data,
}),
get: (worker: string) => ({
queryKey: ["worker:get", worker],
queryKey: ['worker:get', worker],
queryFn: async () => (await api.workerGet(worker)).data,
}),
},

View File

@@ -1,5 +1,5 @@
import { atom } from "jotai";
import { Tenant } from "./api";
import { atom } from 'jotai';
import { Tenant } from './api';
const getInitialValue = <T>(key: string): T | undefined => {
const item = localStorage.getItem(key);
@@ -11,7 +11,7 @@ const getInitialValue = <T>(key: string): T | undefined => {
return;
};
const currTenantKey = "currTenant";
const currTenantKey = 'currTenant';
const currTenantAtomInit = atom(getInitialValue<Tenant>(currTenantKey));
@@ -20,5 +20,5 @@ export const currTenantAtom = atom(
(_get, set, newVal: Tenant) => {
set(currTenantAtomInit, newVal);
localStorage.setItem(currTenantKey, JSON.stringify(newVal));
}
},
);

View File

@@ -1,8 +1,8 @@
import { useToast } from "@/components/ui/use-toast";
import { AxiosError } from "axios";
import { Dispatch, SetStateAction } from "react";
import { APIErrors } from "./api";
import { getFieldErrors } from "./utils";
import { useToast } from '@/components/ui/use-toast';
import { AxiosError } from 'axios';
import { Dispatch, SetStateAction } from 'react';
import { APIErrors } from './api';
import { getFieldErrors } from './utils';
export function useApiError(props: {
setFieldErrors?: Dispatch<SetStateAction<Record<string, string>>>;
@@ -15,8 +15,8 @@ export function useApiError(props: {
if (error.response?.status) {
if (error.response?.status >= 500) {
toast({
title: "Error",
description: "An internal error occurred.",
title: 'Error',
description: 'An internal error occurred.',
duration: 5000,
});
@@ -31,7 +31,9 @@ export function useApiError(props: {
const fieldErrors = getFieldErrors(apiErrors);
if (Object.keys(fieldErrors).length != 0) {
props.setFieldErrors && props.setFieldErrors(fieldErrors);
if (props.setFieldErrors) {
props.setFieldErrors(fieldErrors);
}
return;
}
@@ -40,8 +42,8 @@ export function useApiError(props: {
if (!apiErrors || !apiErrors.errors || apiErrors.errors.length === 0) {
toast({
title: "Error",
description: "An internal error occurred.",
title: 'Error',
description: 'An internal error occurred.',
duration: 5000,
});
@@ -51,7 +53,7 @@ export function useApiError(props: {
for (const error of apiErrors.errors) {
if (error.description) {
toast({
title: "Error",
title: 'Error',
description: error.description,
duration: 5000,
});

View File

@@ -1,5 +1,5 @@
import { useOutletContext } from "react-router-dom";
import { Tenant, TenantMember, User } from "./api";
import { useOutletContext } from 'react-router-dom';
import { Tenant, TenantMember, User } from './api';
export type TenantContextType = { tenant: Tenant };

View File

@@ -1,6 +1,6 @@
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
import { APIErrors } from "./api/generated/data-contracts";
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
import { APIErrors } from './api/generated/data-contracts';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
@@ -24,7 +24,7 @@ export function getFieldErrors(apiErrors: APIErrors): Record<string, string> {
export function capitalize(s: string) {
if (!s) {
return "";
return '';
} else if (s.length == 0) {
return s;
} else if (s.length == 1) {
@@ -36,18 +36,18 @@ export function capitalize(s: string) {
export function relativeDate(date?: string | number) {
if (!date) {
return "N/A";
return 'N/A';
}
const rtf = new Intl.RelativeTimeFormat("en", {
localeMatcher: "best fit", // other values: "lookup"
numeric: "auto", // other values: "auto"
style: "long", // other values: "short" or "narrow"
const rtf = new Intl.RelativeTimeFormat('en', {
localeMatcher: 'best fit', // other values: "lookup"
numeric: 'auto', // other values: "auto"
style: 'long', // other values: "short" or "narrow"
});
const time = timeFrom(date);
if (!time) {
return "N/A";
return 'N/A';
}
return rtf.format(-time.time, time.unitOfTime);
@@ -56,7 +56,9 @@ export function relativeDate(date?: string | number) {
function timeFrom(time: string | number, secondTime?: string | number) {
// Get timestamps
const unixTime = new Date(time).getTime();
if (!unixTime) return;
if (!unixTime) {
return;
}
let now = new Date().getTime();
@@ -69,20 +71,20 @@ function timeFrom(time: string | number, secondTime?: string | number) {
// Setup return object
const tfn: {
when: "past" | "now" | "future";
when: 'past' | 'now' | 'future';
unitOfTime: Intl.RelativeTimeFormatUnit;
time: number;
} = {
when: "now",
unitOfTime: "seconds",
when: 'now',
unitOfTime: 'seconds',
time: 0,
};
// Check if time is in the past, present, or future
if (difference > 0) {
tfn.when = "future";
tfn.when = 'future';
} else if (difference < -1) {
tfn.when = "past";
tfn.when = 'past';
}
// Convert difference to absolute
@@ -91,27 +93,27 @@ function timeFrom(time: string | number, secondTime?: string | number) {
// Calculate time unit
if (difference / (60 * 60 * 24 * 365) > 1) {
// Years
tfn.unitOfTime = "years";
tfn.unitOfTime = 'years';
tfn.time = Math.floor(difference / (60 * 60 * 24 * 365));
} else if (difference / (60 * 60 * 24 * 45) > 1) {
// Months
tfn.unitOfTime = "months";
tfn.unitOfTime = 'months';
tfn.time = Math.floor(difference / (60 * 60 * 24 * 45));
} else if (difference / (60 * 60 * 24) > 1) {
// Days
tfn.unitOfTime = "days";
tfn.unitOfTime = 'days';
tfn.time = Math.floor(difference / (60 * 60 * 24));
} else if (difference / (60 * 60) > 1) {
// Hours
tfn.unitOfTime = "hours";
tfn.unitOfTime = 'hours';
tfn.time = Math.floor(difference / (60 * 60));
} else if (difference / 60 > 1) {
// Minutes
tfn.unitOfTime = "minutes";
tfn.unitOfTime = 'minutes';
tfn.time = Math.floor(difference / 60);
} else {
// Seconds
tfn.unitOfTime = "seconds";
tfn.unitOfTime = 'seconds';
tfn.time = Math.floor(difference);
}

View File

@@ -1,11 +1,11 @@
import ReactDOM from "react-dom/client";
import "./index.css";
import { QueryClientProvider } from "@tanstack/react-query";
import queryClient from "./query-client.tsx";
import Router from "./router.tsx";
import ReactDOM from 'react-dom/client';
import './index.css';
import { QueryClientProvider } from '@tanstack/react-query';
import queryClient from './query-client.tsx';
import Router from './router.tsx';
ReactDOM.createRoot(document.getElementById("root")!).render(
ReactDOM.createRoot(document.getElementById('root')!).render(
<QueryClientProvider client={queryClient}>
<Router />
</QueryClientProvider>
</QueryClientProvider>,
);

View File

@@ -1,16 +1,16 @@
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Icons } from "@/components/ui/icons";
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Icons } from '@/components/ui/icons';
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
email: z.string().email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters long"),
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters long'),
});
interface UserLoginFormProps {
@@ -36,7 +36,7 @@ export function UserLoginForm({ className, ...props }: UserLoginFormProps) {
errors.password?.message?.toString() || props.fieldErrors?.password;
return (
<div className={cn("grid gap-6", className)}>
<div className={cn('grid gap-6', className)}>
<form
onSubmit={handleSubmit((d) => {
props.onSubmit(d);
@@ -46,7 +46,7 @@ export function UserLoginForm({ className, ...props }: UserLoginFormProps) {
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input
{...register("email")}
{...register('email')}
id="email"
placeholder="name@example.com"
type="email"
@@ -62,7 +62,7 @@ export function UserLoginForm({ className, ...props }: UserLoginFormProps) {
<div className="grid gap-2">
<Label htmlFor="password">Password</Label>
<Input
{...register("password")}
{...register('password')}
id="password"
placeholder="Password"
type="password"

View File

@@ -1,11 +1,11 @@
import { Link, useNavigate } from "react-router-dom";
import { UserLoginForm } from "./components/user-login-form";
import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button";
import { useMutation } from "@tanstack/react-query";
import api, { UserLoginRequest } from "@/lib/api";
import { useState } from "react";
import { useApiError } from "@/lib/hooks";
import { Link, useNavigate } from 'react-router-dom';
import { UserLoginForm } from './components/user-login-form';
import { cn } from '@/lib/utils';
import { buttonVariants } from '@/components/ui/button';
import { useMutation } from '@tanstack/react-query';
import api, { UserLoginRequest } from '@/lib/api';
import { useState } from 'react';
import { useApiError } from '@/lib/hooks';
export default function Login() {
const navigate = useNavigate();
@@ -15,12 +15,12 @@ export default function Login() {
});
const loginMutation = useMutation({
mutationKey: ["user:update:login"],
mutationKey: ['user:update:login'],
mutationFn: async (data: UserLoginRequest) => {
await api.userUpdateLogin(data);
},
onSuccess: () => {
navigate("/");
navigate('/');
},
onError: handleApiError,
});
@@ -31,8 +31,8 @@ export default function Login() {
<Link
to="/auth/register"
className={cn(
buttonVariants({ variant: "ghost" }),
"absolute right-4 top-4 md:right-8 md:top-8"
buttonVariants({ variant: 'ghost' }),
'absolute right-4 top-4 md:right-8 md:top-8',
)}
>
Register
@@ -53,14 +53,14 @@ export default function Login() {
fieldErrors={fieldErrors}
/>
<p className="px-8 text-center text-sm text-muted-foreground">
By clicking continue, you agree to our{" "}
By clicking continue, you agree to our{' '}
<Link
to="/terms"
className="underline underline-offset-4 hover:text-primary"
>
Terms of Service
</Link>{" "}
and{" "}
</Link>{' '}
and{' '}
<Link
to="/privacy"
className="underline underline-offset-4 hover:text-primary"

View File

@@ -1,24 +1,24 @@
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Icons } from "@/components/ui/icons";
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Icons } from '@/components/ui/icons';
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
name: z.string().min(3, "Name must be at least 3 characters long"),
email: z.string().email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters long"),
name: z.string().min(3, 'Name must be at least 3 characters long'),
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters long'),
});
type submitType = z.infer<typeof schema>;
type SubmitType = z.infer<typeof schema>;
interface UserRegisterFormProps {
className?: string;
onSubmit: (opts: submitType) => void;
onSubmit: (opts: SubmitType) => void;
isLoading: boolean;
fieldErrors?: Record<string, string>;
}
@@ -31,7 +31,7 @@ export function UserRegisterForm({
register,
handleSubmit,
formState: { errors },
} = useForm<submitType>({
} = useForm<SubmitType>({
resolver: zodResolver(schema),
});
@@ -44,7 +44,7 @@ export function UserRegisterForm({
errors.password?.message?.toString() || props.fieldErrors?.password;
return (
<div className={cn("grid gap-6", className)}>
<div className={cn('grid gap-6', className)}>
<form
onSubmit={handleSubmit((d) => {
props.onSubmit(d);
@@ -54,7 +54,7 @@ export function UserRegisterForm({
<div className="grid gap-2">
<Label htmlFor="name">Name</Label>
<Input
{...register("name")}
{...register('name')}
id="name"
placeholder="Boba Fett"
type="name"
@@ -69,7 +69,7 @@ export function UserRegisterForm({
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input
{...register("email")}
{...register('email')}
id="email"
placeholder="name@example.com"
type="email"
@@ -85,7 +85,7 @@ export function UserRegisterForm({
<div className="grid gap-2">
<Label htmlFor="password">Password</Label>
<Input
{...register("password")}
{...register('password')}
id="password"
placeholder="Password"
type="password"

View File

@@ -1,11 +1,11 @@
import { Link, useNavigate } from "react-router-dom";
import { UserRegisterForm } from "./components/user-register-form";
import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button";
import { useMutation } from "@tanstack/react-query";
import api, { UserRegisterRequest } from "@/lib/api";
import { useState } from "react";
import { useApiError } from "@/lib/hooks";
import { Link, useNavigate } from 'react-router-dom';
import { UserRegisterForm } from './components/user-register-form';
import { cn } from '@/lib/utils';
import { buttonVariants } from '@/components/ui/button';
import { useMutation } from '@tanstack/react-query';
import api, { UserRegisterRequest } from '@/lib/api';
import { useState } from 'react';
import { useApiError } from '@/lib/hooks';
export default function Login() {
const navigate = useNavigate();
@@ -15,12 +15,12 @@ export default function Login() {
});
const createMutation = useMutation({
mutationKey: ["user:create"],
mutationKey: ['user:create'],
mutationFn: async (data: UserRegisterRequest) => {
await api.userCreate(data);
},
onSuccess: () => {
navigate("/");
navigate('/');
},
onError: handleApiError,
});
@@ -31,8 +31,8 @@ export default function Login() {
<Link
to="/auth/login"
className={cn(
buttonVariants({ variant: "ghost" }),
"absolute right-4 top-4 md:right-8 md:top-8"
buttonVariants({ variant: 'ghost' }),
'absolute right-4 top-4 md:right-8 md:top-8',
)}
>
Login
@@ -53,14 +53,14 @@ export default function Login() {
fieldErrors={fieldErrors}
/>
<p className="px-8 text-center text-sm text-muted-foreground">
By clicking continue, you agree to our{" "}
By clicking continue, you agree to our{' '}
<Link
to="/terms"
className="underline underline-offset-4 hover:text-primary"
>
Terms of Service
</Link>{" "}
and{" "}
</Link>{' '}
and{' '}
<Link
to="/privacy"
className="underline underline-offset-4 hover:text-primary"

View File

@@ -3,16 +3,16 @@ import {
Outlet,
redirect,
useLoaderData,
} from "react-router-dom";
import api from "@/lib/api";
import queryClient from "@/query-client";
import { useContextFromParent } from "@/lib/outlet";
import { Icons } from "@/components/ui/icons";
} from 'react-router-dom';
import api from '@/lib/api';
import queryClient from '@/query-client';
import { useContextFromParent } from '@/lib/outlet';
import { Icons } from '@/components/ui/icons';
const authMiddleware = async (currentUrl: string) => {
try {
const user = await queryClient.fetchQuery({
queryKey: ["user:get:current"],
queryKey: ['user:get:current'],
queryFn: async () => {
const res = await api.userGetCurrent();
@@ -20,8 +20,8 @@ const authMiddleware = async (currentUrl: string) => {
},
});
if (!user.emailVerified && !currentUrl.includes("/verify-email")) {
throw redirect("/verify-email");
if (!user.emailVerified && !currentUrl.includes('/verify-email')) {
throw redirect('/verify-email');
}
return user;
@@ -29,10 +29,10 @@ const authMiddleware = async (currentUrl: string) => {
if (error instanceof Response) {
throw error;
} else if (
!currentUrl.includes("/auth/login") &&
!currentUrl.includes("/auth/register")
!currentUrl.includes('/auth/login') &&
!currentUrl.includes('/auth/register')
) {
throw redirect("/auth/login");
throw redirect('/auth/login');
}
}
};
@@ -43,7 +43,7 @@ const membershipsPopulator = async () => {
const memberships = res.data;
if (memberships.rows?.length === 0) {
throw redirect("/onboarding/create-tenant");
throw redirect('/onboarding/create-tenant');
}
return res.data.rows;

View File

@@ -1,22 +1,22 @@
import { ColumnDef } from "@tanstack/react-table";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { DataTableColumnHeader } from "../../../../components/molecules/data-table/data-table-column-header";
import { columns as workflowRunsColumns } from "../../workflow-runs/components/workflow-runs-columns";
import { Event, queries } from "@/lib/api";
import { relativeDate } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { ColumnDef } from '@tanstack/react-table';
import { Badge } from '@/components/ui/badge';
import { Checkbox } from '@/components/ui/checkbox';
import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header';
import { columns as workflowRunsColumns } from '../../workflow-runs/components/workflow-runs-columns';
import { Event, queries } from '@/lib/api';
import { relativeDate } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { useMemo, useState } from "react";
import { currTenantAtom } from "@/lib/atoms";
import { useQuery } from "@tanstack/react-query";
import { useAtom } from "jotai";
import invariant from "tiny-invariant";
import { DataTable } from "@/components/molecules/data-table/data-table";
} from '@/components/ui/popover';
import { useMemo, useState } from 'react';
import { currTenantAtom } from '@/lib/atoms';
import { useQuery } from '@tanstack/react-query';
import { useAtom } from 'jotai';
import invariant from 'tiny-invariant';
import { DataTable } from '@/components/molecules/data-table/data-table';
export const columns = ({
onRowClick,
@@ -25,12 +25,12 @@ export const columns = ({
}): ColumnDef<Event>[] => {
return [
{
id: "select",
id: 'select',
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
(table.getIsSomePageRowsSelected() && 'indeterminate')
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
@@ -49,7 +49,7 @@ export const columns = ({
enableHiding: false,
},
{
accessorKey: "key",
accessorKey: 'key',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Event" />
),
@@ -62,7 +62,7 @@ export const columns = ({
onRowClick?.(row.original);
}}
>
{row.getValue("key")}
{row.getValue('key')}
</Button>
</div>
),
@@ -70,7 +70,7 @@ export const columns = ({
enableHiding: false,
},
{
accessorKey: "Seen at",
accessorKey: 'Seen at',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Seen at" />
),
@@ -79,7 +79,7 @@ export const columns = ({
},
},
{
accessorKey: "Workflow Runs",
accessorKey: 'Workflow Runs',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Workflow Runs" />
),
@@ -104,7 +104,7 @@ function WorkflowRunSummary({ event }: { event: Event }) {
invariant(tenant);
const [hoverCardOpen, setPopoverOpen] = useState<
"failed" | "succeeded" | "running"
'failed' | 'succeeded' | 'running'
>();
const numFailed = event.workflowRunSummary?.failed || 0;
@@ -126,14 +126,14 @@ function WorkflowRunSummary({ event }: { event: Event }) {
return (
listWorkflowRunsQuery.data?.rows?.filter((run) => {
if (hoverCardOpen) {
if (hoverCardOpen == "failed") {
return run.status == "FAILED";
if (hoverCardOpen == 'failed') {
return run.status == 'FAILED';
}
if (hoverCardOpen == "succeeded") {
return run.status == "SUCCEEDED";
if (hoverCardOpen == 'succeeded') {
return run.status == 'SUCCEEDED';
}
if (hoverCardOpen == "running") {
return run.status == "RUNNING" || run.status == "PENDING";
if (hoverCardOpen == 'running') {
return run.status == 'RUNNING' || run.status == 'PENDING';
}
}
@@ -151,7 +151,7 @@ function WorkflowRunSummary({ event }: { event: Event }) {
pageCount={0}
columnVisibility={{
select: false,
"Triggered by": false,
'Triggered by': false,
actions: false,
}}
isLoading={listWorkflowRunsQuery.isLoading}
@@ -163,7 +163,7 @@ function WorkflowRunSummary({ event }: { event: Event }) {
<div className="flex flex-row gap-2 items-center justify-start">
{numFailed > 0 && (
<Popover
open={hoverCardOpen == "failed"}
open={hoverCardOpen == 'failed'}
// open={true}
onOpenChange={(open) => {
if (!open) {
@@ -175,7 +175,7 @@ function WorkflowRunSummary({ event }: { event: Event }) {
<Badge
variant="failed"
className="cursor-pointer"
onClick={() => setPopoverOpen("failed")}
onClick={() => setPopoverOpen('failed')}
>
{numFailed} Failed
</Badge>
@@ -190,7 +190,7 @@ function WorkflowRunSummary({ event }: { event: Event }) {
)}
{numSucceeded > 0 && (
<Popover
open={hoverCardOpen == "succeeded"}
open={hoverCardOpen == 'succeeded'}
onOpenChange={(open) => {
if (!open) {
setPopoverOpen(undefined);
@@ -201,7 +201,7 @@ function WorkflowRunSummary({ event }: { event: Event }) {
<Badge
variant="successful"
className="cursor-pointer"
onClick={() => setPopoverOpen("succeeded")}
onClick={() => setPopoverOpen('succeeded')}
>
{numSucceeded} Succeeded
</Badge>
@@ -216,7 +216,7 @@ function WorkflowRunSummary({ event }: { event: Event }) {
)}
{numRunning > 0 && (
<Popover
open={hoverCardOpen == "running"}
open={hoverCardOpen == 'running'}
onOpenChange={(open) => {
if (!open) {
setPopoverOpen(undefined);
@@ -227,7 +227,7 @@ function WorkflowRunSummary({ event }: { event: Event }) {
<Badge
variant="inProgress"
className="cursor-pointer"
onClick={() => setPopoverOpen("running")}
onClick={() => setPopoverOpen('running')}
>
{numRunning} Running
</Badge>

View File

@@ -1,43 +1,43 @@
import { DataTable } from "../../../components/molecules/data-table/data-table";
import { columns } from "./components/event-columns";
import { columns as workflowRunsColumns } from "../workflow-runs/components/workflow-runs-columns";
import { Separator } from "@/components/ui/separator";
import { useEffect, useMemo, useState } from "react";
import { DataTable } from '../../../components/molecules/data-table/data-table';
import { columns } from './components/event-columns';
import { columns as workflowRunsColumns } from '../workflow-runs/components/workflow-runs-columns';
import { Separator } from '@/components/ui/separator';
import { useEffect, useMemo, useState } from 'react';
import {
ColumnFiltersState,
PaginationState,
RowSelectionState,
SortingState,
} from "@tanstack/react-table";
import { useMutation, useQuery } from "@tanstack/react-query";
} from '@tanstack/react-table';
import { useMutation, useQuery } from '@tanstack/react-query';
import api, {
Event,
EventOrderByDirection,
EventOrderByField,
ReplayEventRequest,
queries,
} from "@/lib/api";
import invariant from "tiny-invariant";
import { useAtom } from "jotai";
import { currTenantAtom } from "@/lib/atoms";
import { Icons } from "@/components/ui/icons";
import { FilterOption } from "@/components/molecules/data-table/data-table-toolbar";
} from '@/lib/api';
import invariant from 'tiny-invariant';
import { useAtom } from 'jotai';
import { currTenantAtom } from '@/lib/atoms';
import { Icons } from '@/components/ui/icons';
import { FilterOption } from '@/components/molecules/data-table/data-table-toolbar';
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { relativeDate } from "@/lib/utils";
import { Code } from "@/components/ui/code";
import { useSearchParams } from "react-router-dom";
import { Button } from "@/components/ui/button";
} from '@/components/ui/dialog';
import { relativeDate } from '@/lib/utils';
import { Code } from '@/components/ui/code';
import { useSearchParams } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import {
ArrowPathIcon,
ArrowPathRoundedSquareIcon,
} from "@heroicons/react/24/outline";
import { useApiError } from "@/lib/hooks";
} from '@heroicons/react/24/outline';
import { useApiError } from '@/lib/hooks';
export default function Events() {
return (
@@ -65,14 +65,14 @@ function EventsTable() {
useEffect(() => {
if (
selectedEvent &&
(!searchParams.get("eventId") ||
searchParams.get("eventId") !== selectedEvent.metadata.id)
(!searchParams.get('eventId') ||
searchParams.get('eventId') !== selectedEvent.metadata.id)
) {
setSearchParams({ eventId: selectedEvent.metadata.id });
} else if (
!selectedEvent &&
searchParams.get("eventId") &&
searchParams.get("eventId") !== ""
searchParams.get('eventId') &&
searchParams.get('eventId') !== ''
) {
setSearchParams({});
}
@@ -103,14 +103,14 @@ function EventsTable() {
}
switch (sorting[0]?.id) {
case "Seen at":
case 'Seen at':
default:
return EventOrderByField.CreatedAt;
}
}, [sorting]);
const keys = useMemo(() => {
const filter = columnFilters.find((filter) => filter.id === "key");
const filter = columnFilters.find((filter) => filter.id === 'key');
if (!filter) {
return;
@@ -138,7 +138,7 @@ function EventsTable() {
});
const replayEventsMutation = useMutation({
mutationKey: ["event:update:replay", tenant.metadata.id],
mutationKey: ['event:update:replay', tenant.metadata.id],
mutationFn: async (data: ReplayEventRequest) => {
await api.eventUpdateReplay(tenant.metadata.id, data);
},
@@ -186,8 +186,9 @@ function EventsTable() {
const actions = [
<Button
key="replay"
disabled={Object.keys(rowSelection).length === 0}
variant={Object.keys(rowSelection).length === 0 ? "outline" : "default"}
variant={Object.keys(rowSelection).length === 0 ? 'outline' : 'default'}
size="sm"
className="h-8 px-2 lg:px-3 gap-2"
onClick={() => {
@@ -200,16 +201,17 @@ function EventsTable() {
Replay
</Button>,
<Button
key="refresh"
className="h-8 px-2 lg:px-3"
size="sm"
onClick={() => {
listEventsQuery.refetch();
setRotate(!rotate);
}}
variant={"outline"}
variant={'outline'}
>
<ArrowPathIcon
className={`h-4 w-4 transition-transform ${rotate ? "rotate-180" : ""}`}
className={`h-4 w-4 transition-transform ${rotate ? 'rotate-180' : ''}`}
/>
</Button>,
];
@@ -231,8 +233,8 @@ function EventsTable() {
data={listEventsQuery.data?.rows || []}
filters={[
{
columnId: "key",
title: "Key",
columnId: 'key',
title: 'Key',
options: eventKeyFilters,
},
]}
@@ -320,7 +322,7 @@ function EventWorkflowRunsList({ event }: { event: Event }) {
filters={[]}
pageCount={listWorkflowRunsQuery.data?.pagination?.num_pages || 0}
columnVisibility={{
"Triggered by": false,
'Triggered by': false,
}}
isLoading={listWorkflowRunsQuery.isLoading}
/>

View File

@@ -1,6 +1,6 @@
import BrushChart from "@/components/molecules/brush-chart/brush-chart";
import { Separator } from "@/components/ui/separator";
import ParentSize from "@visx/responsive/lib/components/ParentSize";
import BrushChart from '@/components/molecules/brush-chart/brush-chart';
import { Separator } from '@/components/ui/separator';
import ParentSize from '@visx/responsive/lib/components/ParentSize';
export default function EventMetrics() {
return (

View File

@@ -1,5 +1,5 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import {
AdjustmentsHorizontalIcon,
BuildingOffice2Icon,
@@ -9,7 +9,7 @@ import {
ServerStackIcon,
Squares2X2Icon,
UserCircleIcon,
} from "@heroicons/react/24/outline";
} from '@heroicons/react/24/outline';
import {
DropdownMenu,
DropdownMenuContent,
@@ -18,9 +18,9 @@ import {
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import hatchet from "@/assets/hatchet_logo.png";
import invariant from "tiny-invariant";
} from '@/components/ui/dropdown-menu';
import hatchet from '@/assets/hatchet_logo.png';
import invariant from 'tiny-invariant';
import {
Command,
@@ -28,27 +28,27 @@ import {
CommandItem,
CommandList,
CommandSeparator,
} from "@/components/ui/command";
} from '@/components/ui/command';
import { Link, Outlet, useNavigate, useOutletContext } from "react-router-dom";
import api, { TenantMember, User } from "@/lib/api";
import { useApiError } from "@/lib/hooks";
import { useMutation } from "@tanstack/react-query";
import { CaretSortIcon, PlusCircledIcon } from "@radix-ui/react-icons";
import { Link, Outlet, useNavigate, useOutletContext } from 'react-router-dom';
import api, { TenantMember, User } from '@/lib/api';
import { useApiError } from '@/lib/hooks';
import { useMutation } from '@tanstack/react-query';
import { CaretSortIcon, PlusCircledIcon } from '@radix-ui/react-icons';
import {
PopoverTrigger,
Popover,
PopoverContent,
} from "@radix-ui/react-popover";
import React, { useEffect } from "react";
} from '@radix-ui/react-popover';
import React, { useEffect } from 'react';
import {
MembershipsContextType,
UserContextType,
useContextFromParent,
} from "@/lib/outlet";
import { useAtom } from "jotai";
import { currTenantAtom } from "@/lib/atoms";
import { Icons } from "@/components/ui/icons";
} from '@/lib/outlet';
import { useAtom } from 'jotai';
import { currTenantAtom } from '@/lib/atoms';
import { Icons } from '@/components/ui/icons';
function Main() {
const { user, memberships } = useOutletContext<
@@ -96,7 +96,7 @@ interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {
function Sidebar({ className, memberships }: SidebarProps) {
return (
<div className={cn("h-full border-r max-w-xs", className)}>
<div className={cn('h-full border-r max-w-xs', className)}>
<div className="flex flex-col justify-between items-start space-y-4 px-4 py-4 h-full">
<div className="grow">
<div className="py-2">
@@ -158,12 +158,12 @@ function MainNav({ user }: MainNavProps) {
const { handleApiError } = useApiError({});
const logoutMutation = useMutation({
mutationKey: ["user:update:logout"],
mutationKey: ['user:update:logout'],
mutationFn: async () => {
await api.userUpdateLogout();
},
onSuccess: () => {
navigate("/auth/login");
navigate('/auth/login');
},
onError: handleApiError,
});
@@ -242,7 +242,7 @@ function TenantSwitcher({ className, memberships }: TenantSwitcherProps) {
role="combobox"
aria-expanded={open}
aria-label="Select a team"
className={cn("w-full justify-between", className)}
className={cn('w-full justify-between', className)}
>
<BuildingOffice2Icon className="mr-2 h-4 w-4" />
{currTenant.name}
@@ -268,10 +268,10 @@ function TenantSwitcher({ className, memberships }: TenantSwitcherProps) {
{membership.tenant?.name}
<CheckIcon
className={cn(
"ml-auto h-4 w-4",
'ml-auto h-4 w-4',
currTenant.slug === membership.tenant?.slug
? "opacity-100"
: "opacity-0"
? 'opacity-100'
: 'opacity-0',
)}
/>
</CommandItem>

View File

@@ -1,13 +1,13 @@
import { ColumnDef } from "@tanstack/react-table";
import { DataTableColumnHeader } from "@/components/molecules/data-table/data-table-column-header";
import { StepRun } from "@/lib/api";
import { relativeDate } from "@/lib/utils";
import { Link } from "react-router-dom";
import { RunStatus } from "@/pages/main/workflow-runs/components/run-statuses";
import { ColumnDef } from '@tanstack/react-table';
import { DataTableColumnHeader } from '@/components/molecules/data-table/data-table-column-header';
import { StepRun } from '@/lib/api';
import { relativeDate } from '@/lib/utils';
import { Link } from 'react-router-dom';
import { RunStatus } from '@/pages/main/workflow-runs/components/run-statuses';
export const columns: ColumnDef<StepRun>[] = [
{
accessorKey: "action",
accessorKey: 'action',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Action" />
),
@@ -22,13 +22,13 @@ export const columns: ColumnDef<StepRun>[] = [
enableHiding: false,
},
{
accessorKey: "id",
accessorKey: 'id',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Step Id" />
),
cell: ({ row }) => {
return (
<Link to={"/workflow-runs/" + row.original.jobRun?.workflowRunId}>
<Link to={'/workflow-runs/' + row.original.jobRun?.workflowRunId}>
<div className="pl-0 cursor-pointer hover:underline min-w-fit whitespace-nowrap">
{row.original.step?.readableId}
</div>
@@ -39,7 +39,7 @@ export const columns: ColumnDef<StepRun>[] = [
enableHiding: false,
},
{
accessorKey: "status",
accessorKey: 'status',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Status" />
),
@@ -48,7 +48,7 @@ export const columns: ColumnDef<StepRun>[] = [
enableHiding: false,
},
{
accessorKey: "Started at",
accessorKey: 'Started at',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Started at" />
),
@@ -59,14 +59,14 @@ export const columns: ColumnDef<StepRun>[] = [
enableHiding: false,
},
{
accessorKey: "Finished at",
accessorKey: 'Finished at',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Finished at" />
),
cell: ({ row }) => {
const finishedAt = row.original.finishedAt
? relativeDate(row.original.finishedAt)
: "N/A";
: 'N/A';
return <div>{finishedAt}</div>;
},

View File

@@ -1,16 +1,16 @@
import { Icons } from "@/components/ui/icons";
import { Separator } from "@/components/ui/separator";
import { queries } from "@/lib/api";
import { currTenantAtom } from "@/lib/atoms";
import { useQuery } from "@tanstack/react-query";
import { useAtom } from "jotai";
import { useParams } from "react-router-dom";
import invariant from "tiny-invariant";
import { relativeDate } from "@/lib/utils";
import { ServerStackIcon } from "@heroicons/react/24/outline";
import { Button } from "@/components/ui/button";
import { DataTable } from "@/components/molecules/data-table/data-table";
import { columns } from "./components/step-runs-columns";
import { Icons } from '@/components/ui/icons';
import { Separator } from '@/components/ui/separator';
import { queries } from '@/lib/api';
import { currTenantAtom } from '@/lib/atoms';
import { useQuery } from '@tanstack/react-query';
import { useAtom } from 'jotai';
import { useParams } from 'react-router-dom';
import invariant from 'tiny-invariant';
import { relativeDate } from '@/lib/utils';
import { ServerStackIcon } from '@heroicons/react/24/outline';
import { Button } from '@/components/ui/button';
import { DataTable } from '@/components/molecules/data-table/data-table';
import { columns } from './components/step-runs-columns';
export default function ExpandedWorkflowRun() {
const [tenant] = useAtom(currTenantAtom);
@@ -62,7 +62,11 @@ export default function ExpandedWorkflowRun() {
</h3>
<div className="flex-wrap flex flex-row gap-4">
{worker.actions?.map((action) => {
return <Button variant="outline">{action}</Button>;
return (
<Button variant="outline" key={action}>
{action}
</Button>
);
})}
</div>
</div>

View File

@@ -1,13 +1,13 @@
import { Separator } from "@/components/ui/separator";
import { useQuery } from "@tanstack/react-query";
import { queries } from "@/lib/api";
import invariant from "tiny-invariant";
import { useAtom } from "jotai";
import { currTenantAtom } from "@/lib/atoms";
import { Icons } from "@/components/ui/icons";
import { relativeDate } from "@/lib/utils";
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Separator } from '@/components/ui/separator';
import { useQuery } from '@tanstack/react-query';
import { queries } from '@/lib/api';
import invariant from 'tiny-invariant';
import { useAtom } from 'jotai';
import { currTenantAtom } from '@/lib/atoms';
import { Icons } from '@/components/ui/icons';
import { relativeDate } from '@/lib/utils';
import { Link } from 'react-router-dom';
import { Button } from '@/components/ui/button';
export default function Workers() {
const [tenant] = useAtom(currTenantAtom);

View File

@@ -1,15 +1,15 @@
import { ColumnDef } from "@tanstack/react-table";
import { DataTableColumnHeader } from "@/components/molecules/data-table/data-table-column-header";
import { JobRun, StepRun } from "@/lib/api";
import { relativeDate } from "@/lib/utils";
import { RunStatus } from "../../components/run-statuses";
import { ColumnDef } from '@tanstack/react-table';
import { DataTableColumnHeader } from '@/components/molecules/data-table/data-table-column-header';
import { JobRun, StepRun } from '@/lib/api';
import { relativeDate } from '@/lib/utils';
import { RunStatus } from '../../components/run-statuses';
type JobRunRow = {
kind: "job";
kind: 'job';
} & JobRun;
type StepRunRow = {
kind: "step";
kind: 'step';
onClick?: () => void;
} & StepRun;
@@ -20,10 +20,10 @@ export type JobRunColumns = (JobRunRow | StepRunRow) & {
export const columns: ColumnDef<JobRunColumns>[] = [
{
accessorKey: "id",
accessorKey: 'id',
header: () => <></>,
cell: ({ row }) => {
if (row.original.kind === "job") {
if (row.original.kind === 'job') {
return <></>;
}
return (
@@ -36,14 +36,14 @@ export const columns: ColumnDef<JobRunColumns>[] = [
enableHiding: false,
},
{
accessorKey: "status",
accessorKey: 'status',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Status" />
),
cell: ({ row }) => {
let reason;
if (row.original.kind == "step") {
if (row.original.kind == 'step') {
reason = row.original.cancelledReason;
}
@@ -53,7 +53,7 @@ export const columns: ColumnDef<JobRunColumns>[] = [
enableHiding: false,
},
{
accessorKey: "Started at",
accessorKey: 'Started at',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Started at" />
),
@@ -64,14 +64,14 @@ export const columns: ColumnDef<JobRunColumns>[] = [
enableHiding: false,
},
{
accessorKey: "Finished at",
accessorKey: 'Finished at',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Finished at" />
),
cell: ({ row }) => {
const finishedAt = row.original.finishedAt
? relativeDate(row.original.finishedAt)
: "N/A";
: 'N/A';
return <div>{finishedAt}</div>;
},

View File

@@ -1,27 +1,27 @@
import { Icons } from "@/components/ui/icons";
import { Separator } from "@/components/ui/separator";
import { JobRun, StepRun, StepRunStatus, queries, Event } from "@/lib/api";
import CronPrettifier from "cronstrue";
import { currTenantAtom } from "@/lib/atoms";
import { useQuery } from "@tanstack/react-query";
import { useAtom } from "jotai";
import { Link, useParams } from "react-router-dom";
import invariant from "tiny-invariant";
import { Badge } from "@/components/ui/badge";
import { relativeDate } from "@/lib/utils";
import { Icons } from '@/components/ui/icons';
import { Separator } from '@/components/ui/separator';
import { JobRun, StepRun, StepRunStatus, queries, Event } from '@/lib/api';
import CronPrettifier from 'cronstrue';
import { currTenantAtom } from '@/lib/atoms';
import { useQuery } from '@tanstack/react-query';
import { useAtom } from 'jotai';
import { Link, useParams } from 'react-router-dom';
import invariant from 'tiny-invariant';
import { Badge } from '@/components/ui/badge';
import { relativeDate } from '@/lib/utils';
import {
AdjustmentsHorizontalIcon,
BoltIcon,
Square3Stack3DIcon,
} from "@heroicons/react/24/outline";
import { Button } from "@/components/ui/button";
import { DataTable } from "@/components/molecules/data-table/data-table";
import { JobRunColumns, columns } from "./components/job-runs-columns";
import { TableCell, TableRow } from "@/components/ui/table";
import { RunStatus } from "../components/run-statuses";
import { ColumnDef } from "@tanstack/react-table";
import { useState } from "react";
import { Code } from "@/components/ui/code";
} from '@heroicons/react/24/outline';
import { Button } from '@/components/ui/button';
import { DataTable } from '@/components/molecules/data-table/data-table';
import { JobRunColumns, columns } from './components/job-runs-columns';
import { TableCell, TableRow } from '@/components/ui/table';
import { RunStatus } from '../components/run-statuses';
import { ColumnDef } from '@tanstack/react-table';
import { useState } from 'react';
import { Code } from '@/components/ui/code';
export default function ExpandedWorkflowRun() {
const [expandedStepRuns, setExpandedStepRuns] = useState<string[]>([]);
@@ -55,7 +55,7 @@ export default function ExpandedWorkflowRun() {
<h2 className="text-2xl font-bold leading-tight text-foreground">
{run?.metadata.id}
</h2>
<Badge className="text-sm mt-1" variant={"secondary"}>
<Badge className="text-sm mt-1" variant={'secondary'}>
{/* {workflow.versions && workflow.versions[0].version} */}
{run.status}
</Badge>
@@ -106,7 +106,7 @@ export default function ExpandedWorkflowRun() {
?.map((jobRun): JobRunColumns[] => {
return [
{
kind: "job",
kind: 'job',
isExpandable: false,
getRow: () => {
return getJobRunRow({ jobRun, columns });
@@ -117,7 +117,7 @@ export default function ExpandedWorkflowRun() {
?.map((stepRun): JobRunColumns[] => {
const res: JobRunColumns[] = [
{
kind: "step",
kind: 'step',
isExpandable: true,
onClick: () => {
if (
@@ -125,8 +125,8 @@ export default function ExpandedWorkflowRun() {
) {
setExpandedStepRuns(
expandedStepRuns.filter(
(id) => id != stepRun.metadata.id
)
(id) => id != stepRun.metadata.id,
),
);
} else {
setExpandedStepRuns([
@@ -141,7 +141,7 @@ export default function ExpandedWorkflowRun() {
if (expandedStepRuns.includes(stepRun.metadata.id)) {
res.push({
kind: "step",
kind: 'step',
isExpandable: false,
getRow: () => {
@@ -212,7 +212,7 @@ function getExpandedStepRunRow({
}
function StepInputSection({ stepRun }: { stepRun: StepRun }) {
const input = stepRun.input || "{}";
const input = stepRun.input || '{}';
return (
<>
@@ -227,7 +227,7 @@ function StepInputSection({ stepRun }: { stepRun: StepRun }) {
}
function StepOutputSection({ stepRun }: { stepRun: StepRun }) {
const output = stepRun.output || "{}";
const output = stepRun.output || '{}';
return (
<>
@@ -242,14 +242,14 @@ function StepOutputSection({ stepRun }: { stepRun: StepRun }) {
}
function StepStatusSection({ stepRun }: { stepRun: StepRun }) {
let statusText = "Unknown";
let statusText = 'Unknown';
switch (stepRun.status) {
case StepRunStatus.RUNNING:
statusText = "This step is currently running";
statusText = 'This step is currently running';
break;
case StepRunStatus.FAILED:
statusText = "This step failed";
statusText = 'This step failed';
if (stepRun.error) {
statusText = `This step failed with error ${stepRun.error}`;
@@ -257,16 +257,17 @@ function StepStatusSection({ stepRun }: { stepRun: StepRun }) {
break;
case StepRunStatus.CANCELLED:
statusText = "This step was cancelled";
statusText = 'This step was cancelled';
switch (stepRun.cancelledReason) {
case "TIMED_OUT":
case 'TIMED_OUT':
statusText = `This step was cancelled because it exceeded its timeout of ${
stepRun.step?.timeout || "60s"
stepRun.step?.timeout || '60s'
}`;
break;
case "PREVIOUS_STEP_TIMED_OUT":
statusText = `This step was cancelled because the previous step timed out`;
case 'PREVIOUS_STEP_TIMED_OUT':
statusText =
'This step was cancelled because the previous step timed out';
break;
default:
break;
@@ -274,10 +275,10 @@ function StepStatusSection({ stepRun }: { stepRun: StepRun }) {
break;
case StepRunStatus.SUCCEEDED:
statusText = "This step succeeded";
statusText = 'This step succeeded';
break;
case StepRunStatus.PENDING:
statusText = "This step is pending";
statusText = 'This step is pending';
break;
default:
break;
@@ -300,7 +301,7 @@ function StepConfigurationSection({ stepRun }: { stepRun: StepRun }) {
Configuration
</h3>
<div className="text-sm text-muted-foreground">
Timeout: {stepRun.step?.timeout || "60s"}
Timeout: {stepRun.step?.timeout || '60s'}
</div>
</div>
);
@@ -343,7 +344,7 @@ function EventDataSection({ event }: { event: Event }) {
function TriggeringCronSection({ cron }: { cron: string }) {
const prettyInterval = `Runs ${CronPrettifier.toString(
cron
cron,
).toLowerCase()} UTC`;
return (

View File

@@ -1,32 +1,32 @@
import { Badge } from "@/components/ui/badge";
import { JobRunStatus, StepRunStatus, WorkflowRunStatus } from "@/lib/api";
import { capitalize } from "@/lib/utils";
import { Badge } from '@/components/ui/badge';
import { JobRunStatus, StepRunStatus, WorkflowRunStatus } from '@/lib/api';
import { capitalize } from '@/lib/utils';
type RunStatus = `${StepRunStatus | WorkflowRunStatus | JobRunStatus}`;
type RunStatusType = `${StepRunStatus | WorkflowRunStatus | JobRunStatus}`;
export function RunStatus({
status,
reason,
}: {
status: RunStatus;
status: RunStatusType;
reason?: string;
}) {
let variant: "inProgress" | "successful" | "failed" = "inProgress";
let text = "Running";
let variant: 'inProgress' | 'successful' | 'failed' = 'inProgress';
let text = 'Running';
switch (status) {
case "SUCCEEDED":
variant = "successful";
text = "Succeeded";
case 'SUCCEEDED':
variant = 'successful';
text = 'Succeeded';
break;
case "FAILED":
case "CANCELLED":
variant = "failed";
text = "Cancelled";
case 'FAILED':
case 'CANCELLED':
variant = 'failed';
text = 'Cancelled';
switch (reason) {
case "TIMED_OUT":
text = "Timed out";
case 'TIMED_OUT':
text = 'Timed out';
break;
default:
break;

View File

@@ -1,19 +1,19 @@
import { ColumnDef } from "@tanstack/react-table";
import { Checkbox } from "@/components/ui/checkbox";
import { DataTableColumnHeader } from "../../../../components/molecules/data-table/data-table-column-header";
import { WorkflowRun } from "@/lib/api";
import { relativeDate } from "@/lib/utils";
import { Link } from "react-router-dom";
import { RunStatus } from "./run-statuses";
import { ColumnDef } from '@tanstack/react-table';
import { Checkbox } from '@/components/ui/checkbox';
import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header';
import { WorkflowRun } from '@/lib/api';
import { relativeDate } from '@/lib/utils';
import { Link } from 'react-router-dom';
import { RunStatus } from './run-statuses';
export const columns: ColumnDef<WorkflowRun>[] = [
{
id: "select",
id: 'select',
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
(table.getIsSomePageRowsSelected() && 'indeterminate')
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
@@ -32,12 +32,12 @@ export const columns: ColumnDef<WorkflowRun>[] = [
enableHiding: false,
},
{
accessorKey: "id",
accessorKey: 'id',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Run Id" />
),
cell: ({ row }) => (
<Link to={"/workflow-runs/" + row.original.metadata.id}>
<Link to={'/workflow-runs/' + row.original.metadata.id}>
<div className="cursor-pointer hover:underline min-w-fit whitespace-nowrap">
{row.original.metadata.id}
</div>
@@ -47,7 +47,7 @@ export const columns: ColumnDef<WorkflowRun>[] = [
enableHiding: false,
},
{
accessorKey: "status",
accessorKey: 'status',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Status" />
),
@@ -56,13 +56,13 @@ export const columns: ColumnDef<WorkflowRun>[] = [
enableHiding: false,
},
{
accessorKey: "Workflow",
accessorKey: 'Workflow',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Workflow" />
),
cell: ({ row }) => {
const workflowName =
row.original.workflowVersion?.workflow?.name || "N/A";
row.original.workflowVersion?.workflow?.name || 'N/A';
return <div className="min-w-fit whitespace-nowrap">{workflowName}</div>;
},
@@ -70,12 +70,12 @@ export const columns: ColumnDef<WorkflowRun>[] = [
enableHiding: false,
},
{
accessorKey: "Triggered by",
accessorKey: 'Triggered by',
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Triggered by" />
),
cell: ({ row }) => {
const eventKey = row.original.triggeredBy?.event?.key || "N/A";
const eventKey = row.original.triggeredBy?.event?.key || 'N/A';
return <div>{eventKey}</div>;
},
@@ -83,7 +83,7 @@ export const columns: ColumnDef<WorkflowRun>[] = [
enableHiding: false,
},
{
accessorKey: "Started at",
accessorKey: 'Started at',
header: ({ column }) => (
<DataTableColumnHeader
column={column}
@@ -102,7 +102,7 @@ export const columns: ColumnDef<WorkflowRun>[] = [
enableHiding: false,
},
{
accessorKey: "Finished at",
accessorKey: 'Finished at',
header: ({ column }) => (
<DataTableColumnHeader
column={column}
@@ -113,7 +113,7 @@ export const columns: ColumnDef<WorkflowRun>[] = [
cell: ({ row }) => {
const finishedAt = row.original.finishedAt
? relativeDate(row.original.finishedAt)
: "N/A";
: 'N/A';
return <div className="whitespace-nowrap">{finishedAt}</div>;
},

View File

@@ -1,18 +1,18 @@
import { DataTable } from "../../../components/molecules/data-table/data-table";
import { columns } from "./components/workflow-runs-columns";
import { Separator } from "@/components/ui/separator";
import { useMemo, useState } from "react";
import { DataTable } from '../../../components/molecules/data-table/data-table';
import { columns } from './components/workflow-runs-columns';
import { Separator } from '@/components/ui/separator';
import { useMemo, useState } from 'react';
import {
ColumnFiltersState,
PaginationState,
SortingState,
} from "@tanstack/react-table";
import { useQuery } from "@tanstack/react-query";
import invariant from "tiny-invariant";
import { useAtom } from "jotai";
import { currTenantAtom } from "@/lib/atoms";
import { Icons } from "@/components/ui/icons";
import { queries } from "@/lib/api";
} from '@tanstack/react-table';
import { useQuery } from '@tanstack/react-query';
import invariant from 'tiny-invariant';
import { useAtom } from 'jotai';
import { currTenantAtom } from '@/lib/atoms';
import { Icons } from '@/components/ui/icons';
import { queries } from '@/lib/api';
export default function WorkflowRuns() {
return (

View File

@@ -1,24 +1,24 @@
import { DataTable } from "@/components/molecules/data-table/data-table";
import { Icons } from "@/components/ui/icons";
import { Separator } from "@/components/ui/separator";
import api, { Workflow, queries } from "@/lib/api";
import { currTenantAtom } from "@/lib/atoms";
import { useQuery } from "@tanstack/react-query";
import { isAxiosError } from "axios";
import { useAtom } from "jotai";
import { DataTable } from '@/components/molecules/data-table/data-table';
import { Icons } from '@/components/ui/icons';
import { Separator } from '@/components/ui/separator';
import api, { Workflow, queries } from '@/lib/api';
import { currTenantAtom } from '@/lib/atoms';
import { useQuery } from '@tanstack/react-query';
import { isAxiosError } from 'axios';
import { useAtom } from 'jotai';
import {
LoaderFunctionArgs,
redirect,
useLoaderData,
useParams,
} from "react-router-dom";
import invariant from "tiny-invariant";
import { columns } from "../../workflow-runs/components/workflow-runs-columns";
import { WorkflowTags } from "../components/workflow-tags";
import { Code } from "@/components/ui/code";
import { Badge } from "@/components/ui/badge";
import { relativeDate } from "@/lib/utils";
import { Square3Stack3DIcon } from "@heroicons/react/24/outline";
} from 'react-router-dom';
import invariant from 'tiny-invariant';
import { columns } from '../../workflow-runs/components/workflow-runs-columns';
import { WorkflowTags } from '../components/workflow-tags';
import { Code } from '@/components/ui/code';
import { Badge } from '@/components/ui/badge';
import { relativeDate } from '@/lib/utils';
import { Square3Stack3DIcon } from '@heroicons/react/24/outline';
export async function loader({
params,
@@ -37,7 +37,8 @@ export async function loader({
throw error;
} else if (isAxiosError(error)) {
// TODO: handle error better
throw redirect("/unauthorized");
redirect('/unauthorized');
throw new Error('unauthorized');
}
}
@@ -72,9 +73,9 @@ export default function ExpandedWorkflow() {
</div>
<div className="flex flex-row justify-start items-center mt-4">
<div className="text-sm text-muted-foreground">
Updated{" "}
Updated{' '}
{relativeDate(
workflow.versions && workflow.versions[0].metadata.updatedAt
workflow.versions && workflow.versions[0].metadata.updatedAt,
)}
</div>
</div>

View File

@@ -1,13 +1,13 @@
import { Workflow } from "@/lib/api";
import { cn, relativeDate } from "@/lib/utils";
import { ChevronRightIcon } from "@heroicons/react/24/outline";
import { Link } from "react-router-dom";
import { WorkflowTags } from "./workflow-tags";
import { Workflow } from '@/lib/api';
import { cn, relativeDate } from '@/lib/utils';
import { ChevronRightIcon } from '@heroicons/react/24/outline';
import { Link } from 'react-router-dom';
import { WorkflowTags } from './workflow-tags';
const statuses = {
offline: "text-gray-500 bg-gray-100/10",
online: "text-green-400 bg-green-400/10",
error: "text-rose-400 bg-rose-400/10",
offline: 'text-gray-500 bg-gray-100/10',
online: 'text-green-400 bg-green-400/10',
error: 'text-rose-400 bg-rose-400/10',
};
interface WorkflowListProps {
@@ -25,7 +25,7 @@ export default function WorkflowList({ workflows }: WorkflowListProps) {
<div className="min-w-0 flex-auto">
<div className="flex items-center gap-x-3">
<div
className={cn(statuses["online"], "flex-none rounded-full p-1")}
className={cn(statuses.online, 'flex-none rounded-full p-1')}
>
<div className="h-2 w-2 rounded-full bg-current" />
</div>

View File

@@ -1,5 +1,5 @@
import { WorkflowTag } from "@/lib/api";
import { cn } from "@/lib/utils";
import { WorkflowTag } from '@/lib/api';
import { cn } from '@/lib/utils';
export function WorkflowTags({ tags }: { tags: WorkflowTag[] }) {
return tags?.map((tag) => {
@@ -8,7 +8,7 @@ export function WorkflowTags({ tags }: { tags: WorkflowTag[] }) {
key={tag.name}
className={cn(
`text-[${tag.color}] bg-[${tag.color}]/10 ring-[${tag.color}]/30`,
"flex-none rounded-full py-1 px-2 text-xs font-medium ring-1 ring-inset"
'flex-none rounded-full py-1 px-2 text-xs font-medium ring-1 ring-inset',
)}
>
{tag.name}

View File

@@ -1,11 +1,11 @@
import { Separator } from "@/components/ui/separator";
import WorkflowList from "./components/workflow-list";
import { useQuery } from "@tanstack/react-query";
import { queries } from "@/lib/api";
import invariant from "tiny-invariant";
import { useAtom } from "jotai";
import { currTenantAtom } from "@/lib/atoms";
import { Icons } from "@/components/ui/icons";
import { Separator } from '@/components/ui/separator';
import WorkflowList from './components/workflow-list';
import { useQuery } from '@tanstack/react-query';
import { queries } from '@/lib/api';
import invariant from 'tiny-invariant';
import { useAtom } from 'jotai';
import { currTenantAtom } from '@/lib/atoms';
import { Icons } from '@/components/ui/icons';
export default function Workflows() {
const [tenant] = useAtom(currTenantAtom);

View File

@@ -1,13 +1,13 @@
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Icons } from "@/components/ui/icons";
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Icons } from '@/components/ui/icons';
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useEffect, useState } from "react";
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { useEffect, useState } from 'react';
const schema = z.object({
name: z.string().min(4).max(32),
@@ -42,21 +42,21 @@ export function TenantCreateForm({
useEffect(() => {
const subscription = watch((value, { name }) => {
switch (name) {
case "name":
case 'name':
if (!isSlugSuffixed) {
const slug = value.name
?.toLowerCase()
.replace(/[^a-z0-9-]/g, "-")
.replace(/-+/g, "-")
.replace(/^-|-$/g, "");
.replace(/[^a-z0-9-]/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '');
if (slug) {
setValue("slug", slug);
setValue('slug', slug);
}
}
break;
case "slug":
case 'slug':
break;
}
});
@@ -70,7 +70,7 @@ export function TenantCreateForm({
const slugError = errors.slug?.message?.toString() || props.fieldErrors?.slug;
return (
<div className={cn("grid gap-6", className)}>
<div className={cn('grid gap-6', className)}>
<form
onSubmit={handleSubmit((d) => {
props.onSubmit(d);
@@ -83,7 +83,7 @@ export function TenantCreateForm({
A display name for your tenant.
</div>
<Input
{...register("name")}
{...register('name')}
id="name"
placeholder="My Awesome Tenant"
type="name"
@@ -95,10 +95,10 @@ export function TenantCreateForm({
// add a random suffix to the slug if it's not modified
if (!isSlugSuffixed) {
const newSlug =
getValues("slug") +
"-" +
getValues('slug') +
'-' +
Math.random().toString(36).substr(2, 5);
setValue("slug", newSlug);
setValue('slug', newSlug);
setIsSlugSuffixed(true);
}
}}
@@ -113,7 +113,7 @@ export function TenantCreateForm({
A URI-friendly identifier for your tenant.
</div>
<Input
{...register("slug")}
{...register('slug')}
id="slug"
placeholder="my-awesome-tenant-123456"
type="name"

View File

@@ -1,9 +1,9 @@
import api, { CreateTenantRequest } from "@/lib/api";
import { useApiError } from "@/lib/hooks";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { TenantCreateForm } from "./components/tenant-create-form";
import api, { CreateTenantRequest } from '@/lib/api';
import { useApiError } from '@/lib/hooks';
import { useMutation } from '@tanstack/react-query';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { TenantCreateForm } from './components/tenant-create-form';
export default function CreateTenant() {
const navigate = useNavigate();
@@ -13,12 +13,12 @@ export default function CreateTenant() {
});
const createMutation = useMutation({
mutationKey: ["user:update:login"],
mutationKey: ['user:update:login'],
mutationFn: async (data: CreateTenantRequest) => {
await api.tenantCreate(data);
},
onSuccess: () => {
navigate("/");
navigate('/');
},
onError: handleApiError,
});

View File

@@ -1,6 +1,6 @@
import { ThemeProvider } from "@/components/theme-provider";
import { Toaster } from "@/components/ui/toaster";
import { Outlet } from "react-router-dom";
import { ThemeProvider } from '@/components/theme-provider';
import { Toaster } from '@/components/ui/toaster';
import { Outlet } from 'react-router-dom';
function Root() {
return (

View File

@@ -1,4 +1,4 @@
import { QueryClient } from "@tanstack/react-query";
import { QueryClient } from '@tanstack/react-query';
const queryClient: QueryClient = new QueryClient({});

View File

@@ -1,38 +1,38 @@
import React from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import React from 'react';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
const routes = [
{
path: "/",
path: '/',
lazy: async () =>
import("./pages/root.tsx").then((res) => {
import('./pages/root.tsx').then((res) => {
return {
Component: res.default,
};
}),
children: [
{
path: "/auth/login",
path: '/auth/login',
lazy: async () =>
import("./pages/auth/login").then((res) => {
import('./pages/auth/login').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/auth/register",
path: '/auth/register',
lazy: async () =>
import("./pages/auth/register").then((res) => {
import('./pages/auth/register').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/",
path: '/',
lazy: async () =>
import("./pages/main/auth").then((res) => {
import('./pages/main/auth').then((res) => {
return {
loader: res.loader,
Component: res.default,
@@ -40,54 +40,54 @@ const routes = [
}),
children: [
{
path: "/onboarding/create-tenant",
path: '/onboarding/create-tenant',
lazy: async () =>
import("./pages/onboarding/create-tenant").then((res) => {
import('./pages/onboarding/create-tenant').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/",
path: '/',
lazy: async () =>
import("./pages/main").then((res) => {
import('./pages/main').then((res) => {
return {
Component: res.default,
};
}),
children: [
{
path: "/events",
path: '/events',
lazy: async () =>
import("./pages/main/events").then((res) => {
import('./pages/main/events').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/events/metrics",
path: '/events/metrics',
lazy: async () =>
import("./pages/main/events/metrics").then((res) => {
import('./pages/main/events/metrics').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/workflows",
path: '/workflows',
lazy: async () =>
import("./pages/main/workflows").then((res) => {
import('./pages/main/workflows').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/workflows/:workflow",
path: '/workflows/:workflow',
lazy: async () =>
import("./pages/main/workflows/$workflow").then((res) => {
import('./pages/main/workflows/$workflow').then((res) => {
return {
Component: res.default,
loader: res.loader,
@@ -95,36 +95,36 @@ const routes = [
}),
},
{
path: "/workflow-runs",
path: '/workflow-runs',
lazy: async () =>
import("./pages/main/workflow-runs").then((res) => {
import('./pages/main/workflow-runs').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/workflow-runs/:run",
path: '/workflow-runs/:run',
lazy: async () =>
import("./pages/main/workflow-runs/$run").then((res) => {
import('./pages/main/workflow-runs/$run').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/workers",
path: '/workers',
lazy: async () =>
import("./pages/main/workers").then((res) => {
import('./pages/main/workers').then((res) => {
return {
Component: res.default,
};
}),
},
{
path: "/workers/:worker",
path: '/workers/:worker',
lazy: async () =>
import("./pages/main/workers/$worker").then((res) => {
import('./pages/main/workers/$worker').then((res) => {
return {
Component: res.default,
};
@@ -138,7 +138,7 @@ const routes = [
},
];
const router = createBrowserRouter(routes, { basename: "/" });
const router = createBrowserRouter(routes, { basename: '/' });
const Router: React.FC = () => {
return <RouterProvider router={router} />;

View File

@@ -2,31 +2,39 @@
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"baseUrl": ".",
"paths": {
"@/*": [
"./src/*"
]
},
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
"include": [
"vite.config.ts",
"postcss.config.js",
"src/**/*.tsx",
"src/**/*.ts"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}

View File

@@ -1,12 +1,12 @@
import path from "path";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import path from 'path';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
'@': path.resolve(__dirname, './src'),
},
},
});