[DEV] correct models
This commit is contained in:
parent
44b4fa37d3
commit
332c65360d
@ -1,6 +0,0 @@
|
||||
{
|
||||
"display": "2025-02-09",
|
||||
"version": "0.0.1-dev\n - 2025-02-09T21:15:14+01:00",
|
||||
"commit": "0.0.1-dev\n",
|
||||
"date": "2025-02-09T21:15:14+01:00"
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const generateAppBuild = () => {
|
||||
const getVersion = () => fs.readFileSync('version.txt', 'utf8');
|
||||
|
||||
const commit = process.env.VERCEL_GIT_COMMIT_SHA
|
||||
? process.env.VERCEL_GIT_COMMIT_SHA
|
||||
: getVersion();
|
||||
|
||||
const appBuildContent = {
|
||||
display: `${dayjs().format('YYYY-MM-DD')}`,
|
||||
version: `${commit} - ${dayjs().format()}`,
|
||||
commit,
|
||||
date: dayjs().format(),
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
'./app-build.json',
|
||||
JSON.stringify(appBuildContent, null, 2)
|
||||
);
|
||||
};
|
||||
|
||||
generateAppBuild();
|
@ -7,11 +7,6 @@ const config: KnipConfig = {
|
||||
// Related to tests
|
||||
'tests/**',
|
||||
'**.conf.js',
|
||||
'steps.d.ts',
|
||||
'steps_file.js',
|
||||
'env_ci/codecept.conf.js',
|
||||
// Generic components are useful.
|
||||
'src/components/**',
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest watch",
|
||||
"build": "tsc && vite build",
|
||||
"static:build": "node build.js && pnpm build",
|
||||
"static:build": "pnpm build",
|
||||
"dev": "vite",
|
||||
"pretty": "prettier -w .",
|
||||
"lint": "pnpm tsc --noEmit",
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { EnvDevelopment } from './components/EnvDevelopment/EnvDevelopment';
|
||||
|
||||
import { ErrorBoundary } from '@/errors/ErrorBoundary';
|
||||
import { AppRoutes } from '@/scene/AppRoutes';
|
||||
import { ServiceContextProvider } from '@/service/ServiceContext';
|
||||
|
||||
import { EnvDevelopment } from './components/EnvDevelopment/EnvDevelopment';
|
||||
|
||||
export const App = () => {
|
||||
return (
|
||||
<ServiceContextProvider>
|
||||
|
@ -3,13 +3,14 @@ import { ReactElement, useEffect, useState } from 'react';
|
||||
import { Box, BoxProps, Flex, FlexProps } from '@chakra-ui/react';
|
||||
import { Image } from '@chakra-ui/react';
|
||||
|
||||
import { DataUrlAccess } from '@/utils/data-url-access';
|
||||
import { Icon } from './Icon';
|
||||
import { ObjectId } from '@/back-api';
|
||||
import { DataUrlAccess } from '@/utils/data-url-access';
|
||||
|
||||
export type CoversProps = Omit<BoxProps, "iconEmpty"> & {
|
||||
import { Icon } from './Icon';
|
||||
|
||||
export type CoversProps = Omit<BoxProps, 'iconEmpty'> & {
|
||||
data?: ObjectId[];
|
||||
size?: BoxProps["width"];
|
||||
size?: BoxProps['width'];
|
||||
iconEmpty?: ReactElement;
|
||||
slideshow?: boolean;
|
||||
};
|
||||
@ -33,7 +34,9 @@ export const Covers = ({
|
||||
setPreviousImageIndex(currentImageIndex);
|
||||
setTopOpacity(0.0);
|
||||
setTimeout(() => {
|
||||
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % (data?.length ?? 1));
|
||||
setCurrentImageIndex(
|
||||
(prevIndex) => (prevIndex + 1) % (data?.length ?? 1)
|
||||
);
|
||||
setTopOpacity(1.0);
|
||||
}, 1500);
|
||||
}, 3000);
|
||||
@ -60,40 +63,50 @@ export const Covers = ({
|
||||
}
|
||||
if (slideshow === false || data.length === 1) {
|
||||
const url = DataUrlAccess.getThumbnailUrl(data[0]);
|
||||
return <Image loading="lazy" src={url} maxWidth={size} boxSize={size} /*{...rest}*/ />;
|
||||
return (
|
||||
<Image
|
||||
loading="lazy"
|
||||
src={url}
|
||||
maxWidth={size}
|
||||
boxSize={size} /*{...rest}*/
|
||||
/>
|
||||
);
|
||||
}
|
||||
const urlCurrent = DataUrlAccess.getThumbnailUrl(data[currentImageIndex]);
|
||||
const urlPrevious = DataUrlAccess.getThumbnailUrl(data[previousImageIndex]);
|
||||
return <Flex
|
||||
position="relative"
|
||||
// {...rest}
|
||||
maxWidth={size}
|
||||
width={size}
|
||||
height={size}
|
||||
overflow="hidden">
|
||||
<Image
|
||||
src={urlPrevious}
|
||||
loading="lazy"
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
zIndex={1}
|
||||
boxSize={size}
|
||||
/>
|
||||
<Image
|
||||
src={urlCurrent}
|
||||
loading="lazy"
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
boxSize={size}
|
||||
transition="opacity 0.5s ease-in-out"
|
||||
opacity={topOpacity}
|
||||
zIndex={2}
|
||||
/>
|
||||
</Flex>
|
||||
return (
|
||||
<Flex
|
||||
position="relative"
|
||||
// {...rest}
|
||||
maxWidth={size}
|
||||
width={size}
|
||||
height={size}
|
||||
overflow="hidden"
|
||||
>
|
||||
<Image
|
||||
src={urlPrevious}
|
||||
loading="lazy"
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
zIndex={1}
|
||||
boxSize={size}
|
||||
/>
|
||||
<Image
|
||||
src={urlCurrent}
|
||||
loading="lazy"
|
||||
position="absolute"
|
||||
top="0"
|
||||
left="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
boxSize={size}
|
||||
transition="opacity 0.5s ease-in-out"
|
||||
opacity={topOpacity}
|
||||
zIndex={2}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@ -6,8 +6,8 @@ export const EmptyEnd = () => {
|
||||
width="full"
|
||||
height="25%"
|
||||
minHeight="250px"
|
||||
// borderWidth="1px"
|
||||
// borderColor="red"
|
||||
// borderWidth="1px"
|
||||
// borderColor="red"
|
||||
></Box>
|
||||
);
|
||||
};
|
||||
|
@ -1,38 +1,37 @@
|
||||
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
createListCollection,
|
||||
Dialog,
|
||||
Select,
|
||||
Span,
|
||||
Stack,
|
||||
Text,
|
||||
createListCollection,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { useSessionService } from '@/service/session';
|
||||
import { useLogin } from '@/scene/connection/useLogin';
|
||||
import { useSessionService } from '@/service/session';
|
||||
|
||||
export const USERS_COLLECTION = createListCollection({
|
||||
items: [
|
||||
{ label: "karadmin", value: "adminA@666" },
|
||||
{ label: "karuser", value: "userA@666" },
|
||||
{ label: "NO_USER", value: "" },
|
||||
{ label: 'karadmin', value: 'adminA@666' },
|
||||
{ label: 'karuser', value: 'userA@666' },
|
||||
{ label: 'NO_USER', value: '' },
|
||||
],
|
||||
})
|
||||
});
|
||||
|
||||
export const EnvDevelopment = () => {
|
||||
const dialog = useDisclosure();
|
||||
|
||||
const {clearToken} = useSessionService();
|
||||
const {connect, lastError} = useLogin();
|
||||
const { clearToken } = useSessionService();
|
||||
const { connect, lastError } = useLogin();
|
||||
|
||||
const buildEnv =
|
||||
process.env.NODE_ENV === 'development'
|
||||
? 'Development'
|
||||
: import.meta.env.VITE_DEV_ENV_NAME;
|
||||
const envName: Array<string> = [];
|
||||
const envName: Array<string> = [];
|
||||
!!buildEnv && envName.push(buildEnv);
|
||||
|
||||
if (!envName.length) {
|
||||
@ -77,23 +76,32 @@ export const EnvDevelopment = () => {
|
||||
>
|
||||
{envName.join(' : ')}
|
||||
</Text>
|
||||
</Box >
|
||||
</Box>
|
||||
|
||||
<Dialog.Root open={dialog.open} onOpenChange={dialog.onClose}>
|
||||
<Dialog.Positioner>
|
||||
<Dialog.Backdrop/>
|
||||
<Dialog.Backdrop />
|
||||
<Dialog.Content>
|
||||
<Dialog.Header>Development tools</Dialog.Header>
|
||||
<Dialog.Body>
|
||||
<Stack>
|
||||
<Text>User <Span color="red" fontWeight="bold">{lastError}</Span></Text>
|
||||
<Text>
|
||||
User{' '}
|
||||
<Span color="red" fontWeight="bold">
|
||||
{lastError}
|
||||
</Span>
|
||||
</Text>
|
||||
<Select.Root collection={USERS_COLLECTION}>
|
||||
<Select.Trigger>
|
||||
<Select.ValueText placeholder="Select test user" />
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
{USERS_COLLECTION.items.map((value) => (
|
||||
<Select.Item item={value} key={value.value}onClick={()=>handleChange(value.label, value.value)} >
|
||||
<Select.Item
|
||||
item={value}
|
||||
key={value.value}
|
||||
onClick={() => handleChange(value.label, value.value)}
|
||||
>
|
||||
{value.label}
|
||||
</Select.Item>
|
||||
))}
|
||||
@ -110,4 +118,3 @@ export const EnvDevelopment = () => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,41 +1,40 @@
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
FlexProps,
|
||||
} from '@chakra-ui/react';
|
||||
import { forwardRef, ReactNode } from 'react';
|
||||
import { ReactNode, forwardRef } from 'react';
|
||||
|
||||
import { Box, Flex, FlexProps } from '@chakra-ui/react';
|
||||
|
||||
export type IconProps = FlexProps & {
|
||||
children: ReactNode;
|
||||
color?: string;
|
||||
sizeIcon?: FlexProps['width'];
|
||||
children: ReactNode;
|
||||
color?: string;
|
||||
sizeIcon?: FlexProps['width'];
|
||||
};
|
||||
|
||||
export const Icon = forwardRef<HTMLDivElement, IconProps>(
|
||||
({ children, color, sizeIcon = '1em', ...rest }, ref) => {
|
||||
return (
|
||||
<Flex flex="none"
|
||||
minWidth={sizeIcon}
|
||||
minHeight={sizeIcon}
|
||||
maxWidth={sizeIcon}
|
||||
maxHeight={sizeIcon}
|
||||
align="center"
|
||||
padding="1px"
|
||||
ref={ref}
|
||||
{...rest}>
|
||||
<Box
|
||||
marginX="auto"
|
||||
width="100%"
|
||||
minWidth="100%"
|
||||
height="100%"
|
||||
color={color}
|
||||
asChild
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
({ children, color, sizeIcon = '1em', ...rest }, ref) => {
|
||||
return (
|
||||
<Flex
|
||||
flex="none"
|
||||
minWidth={sizeIcon}
|
||||
minHeight={sizeIcon}
|
||||
maxWidth={sizeIcon}
|
||||
maxHeight={sizeIcon}
|
||||
align="center"
|
||||
padding="1px"
|
||||
ref={ref}
|
||||
{...rest}
|
||||
>
|
||||
<Box
|
||||
marginX="auto"
|
||||
width="100%"
|
||||
minWidth="100%"
|
||||
height="100%"
|
||||
color={color}
|
||||
asChild
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Icon.displayName = 'Icon';
|
||||
|
@ -4,8 +4,8 @@ import { Flex, FlexProps } from '@chakra-ui/react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||
import { colors } from '@/theme/colors';
|
||||
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||
import { colors } from '@/theme/colors';
|
||||
|
||||
export type LayoutProps = FlexProps & {
|
||||
children: ReactNode;
|
||||
|
@ -1,22 +1,20 @@
|
||||
|
||||
export {
|
||||
ParameterLayoutContent as Content,
|
||||
type ParameterLayoutContentProps as ContentProps
|
||||
ParameterLayoutContent as Content,
|
||||
type ParameterLayoutContentProps as ContentProps,
|
||||
} from './ParameterLayoutContent';
|
||||
export {
|
||||
ParameterLayoutFooter as Footer,
|
||||
type ParameterLayoutFooterProps as FooterProps
|
||||
ParameterLayoutFooter as Footer,
|
||||
type ParameterLayoutFooterProps as FooterProps,
|
||||
} from './ParameterLayoutFooter';
|
||||
export {
|
||||
ParameterLayoutHeader as Header,
|
||||
type ParameterLayoutHeaderProps as HeaderProps
|
||||
ParameterLayoutHeader as Header,
|
||||
type ParameterLayoutHeaderProps as HeaderProps,
|
||||
} from './ParameterLayoutHeader';
|
||||
export {
|
||||
ParameterLayoutHeaderBase as HeaderBase,
|
||||
type ParameterLayoutHeaderBaseProps as HeaderBaseProps
|
||||
ParameterLayoutHeaderBase as HeaderBase,
|
||||
type ParameterLayoutHeaderBaseProps as HeaderBaseProps,
|
||||
} from './ParameterLayoutHeaderBase';
|
||||
export {
|
||||
ParameterLayoutRoot as Root,
|
||||
type ParameterLayoutRootProps as RootProps
|
||||
ParameterLayoutRoot as Root,
|
||||
type ParameterLayoutRootProps as RootProps,
|
||||
} from './ParameterLayoutRoot';
|
||||
|
||||
|
@ -1,19 +1,25 @@
|
||||
import { Flex } from "@chakra-ui/react";
|
||||
import { ReactNode } from "react";
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
|
||||
export type ParameterLayoutContentProps = {
|
||||
children?:ReactNode;
|
||||
}
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
export const ParameterLayoutContent = ({children}:ParameterLayoutContentProps) => {
|
||||
return <Flex
|
||||
export const ParameterLayoutContent = ({
|
||||
children,
|
||||
}: ParameterLayoutContentProps) => {
|
||||
return (
|
||||
<Flex
|
||||
direction="column"
|
||||
width="full"
|
||||
borderY="1px solid black"
|
||||
paddingY="15px"
|
||||
paddingX="25px"
|
||||
minHeight="10px"
|
||||
background="gray.700">
|
||||
{children}
|
||||
background="gray.700"
|
||||
>
|
||||
{children}
|
||||
</Flex>
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -1,16 +1,17 @@
|
||||
import { Flex } from "@chakra-ui/react";
|
||||
import { ReactNode } from "react";
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
|
||||
export type ParameterLayoutFooterProps = {
|
||||
children?: ReactNode;
|
||||
}
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
export const ParameterLayoutFooter = ({children}:ParameterLayoutFooterProps) => {
|
||||
return <Flex
|
||||
width="full"
|
||||
paddingY="15px"
|
||||
paddingX="25px"
|
||||
minHeight="10px">
|
||||
{children}
|
||||
export const ParameterLayoutFooter = ({
|
||||
children,
|
||||
}: ParameterLayoutFooterProps) => {
|
||||
return (
|
||||
<Flex width="full" paddingY="15px" paddingX="25px" minHeight="10px">
|
||||
{children}
|
||||
</Flex>
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { Flex } from "@chakra-ui/react";
|
||||
import { ReactNode } from "react";
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
|
||||
export type ParameterLayoutHeaderProps = {
|
||||
children?:ReactNode;
|
||||
}
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
export const ParameterLayoutHeader = ({children}:ParameterLayoutHeaderProps) => {
|
||||
return <Flex
|
||||
width="full"
|
||||
paddingY="15px"
|
||||
paddingX="25px"
|
||||
minHeight="10px"
|
||||
>
|
||||
{children}
|
||||
export const ParameterLayoutHeader = ({
|
||||
children,
|
||||
}: ParameterLayoutHeaderProps) => {
|
||||
return (
|
||||
<Flex width="full" paddingY="15px" paddingX="25px" minHeight="10px">
|
||||
{children}
|
||||
</Flex>
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -1,23 +1,24 @@
|
||||
import { Flex, Text } from "@chakra-ui/react";
|
||||
import { ParameterLayoutHeader } from "./ParameterLayoutHeader";
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
|
||||
import { ParameterLayoutHeader } from './ParameterLayoutHeader';
|
||||
|
||||
export type ParameterLayoutHeaderBaseProps = {
|
||||
title:string;
|
||||
description?: string,
|
||||
}
|
||||
title: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export const ParameterLayoutHeaderBase = ({
|
||||
title,
|
||||
description,
|
||||
}:ParameterLayoutHeaderBaseProps) => {
|
||||
return <ParameterLayoutHeader>
|
||||
<Flex direction="column">
|
||||
<Text
|
||||
fontSize="25px"
|
||||
fontWeight="bold">
|
||||
{title}
|
||||
title,
|
||||
description,
|
||||
}: ParameterLayoutHeaderBaseProps) => {
|
||||
return (
|
||||
<ParameterLayoutHeader>
|
||||
<Flex direction="column">
|
||||
<Text fontSize="25px" fontWeight="bold">
|
||||
{title}
|
||||
</Text>
|
||||
{description && <Text>{description}</Text>}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ParameterLayoutHeader>
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -1,17 +1,24 @@
|
||||
|
||||
import { VStack } from '@chakra-ui/react';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export type ParameterLayoutRootProps = {
|
||||
children?: ReactNode;
|
||||
}
|
||||
import { VStack } from '@chakra-ui/react';
|
||||
|
||||
export const ParameterLayoutRoot = ({children}:ParameterLayoutRootProps) => {
|
||||
return <VStack gap="0px" marginX="15%" marginY="20px" justify="center"
|
||||
//borderRadius="20px"
|
||||
borderRadius="0px"
|
||||
border="1px solid black"
|
||||
background="gray.500">
|
||||
{children}
|
||||
export type ParameterLayoutRootProps = {
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
export const ParameterLayoutRoot = ({ children }: ParameterLayoutRootProps) => {
|
||||
return (
|
||||
<VStack
|
||||
gap="0px"
|
||||
marginX="15%"
|
||||
marginY="20px"
|
||||
justify="center"
|
||||
//borderRadius="20px"
|
||||
borderRadius="0px"
|
||||
border="1px solid black"
|
||||
background="gray.500"
|
||||
>
|
||||
{children}
|
||||
</VStack>
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import {
|
||||
Group,
|
||||
Input,
|
||||
} from '@chakra-ui/react';
|
||||
import { Group, Input } from '@chakra-ui/react';
|
||||
import { MdSearch } from 'react-icons/md';
|
||||
|
||||
export type SearchInputProps = {
|
||||
|
@ -2,15 +2,15 @@ import { ReactNode } from 'react';
|
||||
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ConditionalValue,
|
||||
Flex,
|
||||
HStack,
|
||||
IconButton,
|
||||
Text,
|
||||
useDisclosure,
|
||||
Button,
|
||||
ConditionalValue,
|
||||
Span,
|
||||
Text,
|
||||
chakra,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
LuAlignJustify,
|
||||
@ -22,13 +22,18 @@ import {
|
||||
LuSettings,
|
||||
LuSun,
|
||||
} from 'react-icons/lu';
|
||||
import {
|
||||
MdHelp,
|
||||
MdHome,
|
||||
MdKey,
|
||||
MdMore,
|
||||
MdOutlineDashboardCustomize,
|
||||
MdOutlineGroup,
|
||||
MdSettings,
|
||||
MdSupervisedUserCircle,
|
||||
} from 'react-icons/md';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useServiceContext } from '@/service/ServiceContext';
|
||||
import { colors } from '@/theme/colors';
|
||||
import { useSessionService } from '@/service/session';
|
||||
import { MdHelp, MdHome, MdKey, MdMore, MdOutlineDashboardCustomize, MdOutlineGroup, MdSettings, MdSupervisedUserCircle } from 'react-icons/md';
|
||||
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '@/components/ui/menu';
|
||||
import { useColorMode, useColorModeValue } from '@/components/ui/color-mode';
|
||||
import {
|
||||
DrawerBody,
|
||||
@ -36,11 +41,22 @@ import {
|
||||
DrawerHeader,
|
||||
DrawerRoot,
|
||||
} from '@/components/ui/drawer';
|
||||
import {
|
||||
MenuContent,
|
||||
MenuItem,
|
||||
MenuRoot,
|
||||
MenuTrigger,
|
||||
} from '@/components/ui/menu';
|
||||
import { useServiceContext } from '@/service/ServiceContext';
|
||||
import { useSessionService } from '@/service/session';
|
||||
import { colors } from '@/theme/colors';
|
||||
|
||||
export const TOP_BAR_HEIGHT = '50px';
|
||||
|
||||
export const BUTTON_TOP_BAR_PROPERTY = {
|
||||
variant: "ghost" as ConditionalValue<"ghost" | "outline" | "solid" | "subtle" | "surface" | "plain" | undefined>,
|
||||
variant: 'ghost' as ConditionalValue<
|
||||
'ghost' | 'outline' | 'solid' | 'subtle' | 'surface' | 'plain' | undefined
|
||||
>,
|
||||
//colorPalette: "brand",
|
||||
fontSize: '20px',
|
||||
textTransform: 'uppercase',
|
||||
@ -52,31 +68,41 @@ export type TopBarProps = {
|
||||
title?: string;
|
||||
};
|
||||
|
||||
const ButtonMenuLeft = ({ dest, title, icon,
|
||||
onClickEnd = () => { }, }: {
|
||||
dest: string, title: string, icon: ReactNode
|
||||
onClickEnd?: () => void;
|
||||
}) => {
|
||||
const ButtonMenuLeft = ({
|
||||
dest,
|
||||
title,
|
||||
icon,
|
||||
onClickEnd = () => {},
|
||||
}: {
|
||||
dest: string;
|
||||
title: string;
|
||||
icon: ReactNode;
|
||||
onClickEnd?: () => void;
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
return <>
|
||||
<Button
|
||||
background="#00000000"
|
||||
borderRadius="0px"
|
||||
onClick={() => {
|
||||
navigate(dest);
|
||||
onClickEnd();
|
||||
}}
|
||||
width="full"
|
||||
{...BUTTON_TOP_BAR_PROPERTY}
|
||||
>
|
||||
<Box asChild style={{ width: "45px", height: "45px" }}>{icon}</Box>
|
||||
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
||||
{title}
|
||||
</Text>
|
||||
</Button>
|
||||
<Box marginY="5" marginX="10" height="2px" background="brand.600" />
|
||||
</>
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
background="#00000000"
|
||||
borderRadius="0px"
|
||||
onClick={() => {
|
||||
navigate(dest);
|
||||
onClickEnd();
|
||||
}}
|
||||
width="full"
|
||||
{...BUTTON_TOP_BAR_PROPERTY}
|
||||
>
|
||||
<Box asChild style={{ width: '45px', height: '45px' }}>
|
||||
{icon}
|
||||
</Box>
|
||||
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
||||
{title}
|
||||
</Text>
|
||||
</Button>
|
||||
<Box marginY="5" marginX="10" height="2px" background="brand.600" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
const { colorMode, toggleColorMode } = useColorMode();
|
||||
|
||||
@ -138,7 +164,10 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
<Flex right="0">
|
||||
{!session?.token && (
|
||||
<>
|
||||
<Button {...BUTTON_TOP_BAR_PROPERTY} onClick={() => navigate('/login')}>
|
||||
<Button
|
||||
{...BUTTON_TOP_BAR_PROPERTY}
|
||||
onClick={() => navigate('/login')}
|
||||
>
|
||||
<LuLogIn />
|
||||
<Text paddingLeft="3px" fontWeight="bold">
|
||||
Sign-in
|
||||
@ -163,24 +192,55 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
//asChild
|
||||
{...BUTTON_TOP_BAR_PROPERTY}
|
||||
width={TOP_BAR_HEIGHT}
|
||||
><LuCircleUserRound/></IconButton>
|
||||
>
|
||||
<LuCircleUserRound />
|
||||
</IconButton>
|
||||
</MenuTrigger>
|
||||
<MenuContent>
|
||||
<MenuItem value="user" valueText="user" color={useColorModeValue('brand.800', 'brand.200')}>
|
||||
<MenuItem
|
||||
value="user"
|
||||
valueText="user"
|
||||
color={useColorModeValue('brand.800', 'brand.200')}
|
||||
>
|
||||
<MdSupervisedUserCircle />
|
||||
<Box flex="1">Sign in as {session?.login ?? 'Fail'}</Box>
|
||||
</MenuItem>
|
||||
<MenuItem value="Settings" valueText="Settings" onClick={() => navigate('/settings')}><LuSettings />Settings</MenuItem>
|
||||
<MenuItem value="Help" valueText="Help" onClick={() => navigate('/help')}><MdHelp /> Help</MenuItem>
|
||||
<MenuItem value="Sign-out" valueText="Sign-out" onClick={() => navigate('/signout')}>
|
||||
<MenuItem
|
||||
value="Settings"
|
||||
valueText="Settings"
|
||||
onClick={() => navigate('/settings')}
|
||||
>
|
||||
<LuSettings />
|
||||
Settings
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
value="Help"
|
||||
valueText="Help"
|
||||
onClick={() => navigate('/help')}
|
||||
>
|
||||
<MdHelp /> Help
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
value="Sign-out"
|
||||
valueText="Sign-out"
|
||||
onClick={() => navigate('/signout')}
|
||||
>
|
||||
<LuLogOut /> Sign-out
|
||||
</MenuItem>
|
||||
{colorMode === 'light' ? (
|
||||
<MenuItem value="set-dark" valueText="set-dark" onClick={toggleColorMode}>
|
||||
<MenuItem
|
||||
value="set-dark"
|
||||
valueText="set-dark"
|
||||
onClick={toggleColorMode}
|
||||
>
|
||||
<LuMoon /> Set dark mode
|
||||
</MenuItem>
|
||||
) : (
|
||||
<MenuItem value="set-light" valueText="set-light" onClick={toggleColorMode}>
|
||||
<MenuItem
|
||||
value="set-light"
|
||||
valueText="set-light"
|
||||
onClick={toggleColorMode}
|
||||
>
|
||||
<LuSun /> Set light mode
|
||||
</MenuItem>
|
||||
)}
|
||||
@ -194,8 +254,7 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
open={drawerDisclose.open}
|
||||
data-testid="top-bar_drawer-root"
|
||||
>
|
||||
<DrawerContent
|
||||
data-testid="top-bar_drawer-content">
|
||||
<DrawerContent data-testid="top-bar_drawer-content">
|
||||
<DrawerHeader
|
||||
paddingY="auto"
|
||||
as="button"
|
||||
@ -205,24 +264,46 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
||||
color={useColorModeValue('brand.900', 'brand.50')}
|
||||
textTransform="uppercase"
|
||||
>
|
||||
<HStack
|
||||
{...BUTTON_TOP_BAR_PROPERTY} cursor="pointer">
|
||||
<HStack {...BUTTON_TOP_BAR_PROPERTY} cursor="pointer">
|
||||
<LuArrowBigLeft />
|
||||
<Span paddingLeft="3px">
|
||||
karso
|
||||
</Span>
|
||||
<Span paddingLeft="3px">karso</Span>
|
||||
</HStack>
|
||||
</DrawerHeader>
|
||||
<DrawerBody paddingX="0px">
|
||||
<Box marginY="3" />
|
||||
<ButtonMenuLeft onClickEnd={drawerDisclose.onClose} dest="/" title="Home" icon={<MdHome />} />
|
||||
<ButtonMenuLeft onClickEnd={drawerDisclose.onClose} dest="/change-password" title="Change password" icon={<MdKey />} />
|
||||
<ButtonMenuLeft onClickEnd={drawerDisclose.onClose} dest="/admin-settings" title="Admin settings" icon={<MdSettings />} />
|
||||
<ButtonMenuLeft onClickEnd={drawerDisclose.onClose} dest="/manage-account" title="Manage account" icon={<MdOutlineGroup />} />
|
||||
<ButtonMenuLeft onClickEnd={drawerDisclose.onClose} dest="/manage-application" title="Manage application" icon={<MdOutlineDashboardCustomize />} />
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/"
|
||||
title="Home"
|
||||
icon={<MdHome />}
|
||||
/>
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/change-password"
|
||||
title="Change password"
|
||||
icon={<MdKey />}
|
||||
/>
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/admin-settings"
|
||||
title="Admin settings"
|
||||
icon={<MdSettings />}
|
||||
/>
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/manage-account"
|
||||
title="Manage account"
|
||||
icon={<MdOutlineGroup />}
|
||||
/>
|
||||
<ButtonMenuLeft
|
||||
onClickEnd={drawerDisclose.onClose}
|
||||
dest="/manage-application"
|
||||
title="Manage application"
|
||||
icon={<MdOutlineDashboardCustomize />}
|
||||
/>
|
||||
</DrawerBody>
|
||||
</DrawerContent>
|
||||
</DrawerRoot>
|
||||
</Flex >
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { ReactNode, useState } from 'react';
|
||||
|
||||
import { LuMenu } from 'react-icons/lu';
|
||||
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '../ui/menu';
|
||||
import { Button } from '../ui/button';
|
||||
|
||||
import { Button } from '../ui/button';
|
||||
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '../ui/menu';
|
||||
|
||||
export type MenuElement = {
|
||||
icon?: ReactNode;
|
||||
@ -20,27 +20,33 @@ export const ContextMenu = ({ elements }: ContextMenuProps) => {
|
||||
return <></>;
|
||||
}
|
||||
return (
|
||||
<MenuRoot
|
||||
data-testid="context-menu">
|
||||
<MenuTrigger asChild
|
||||
<MenuRoot data-testid="context-menu">
|
||||
<MenuTrigger
|
||||
asChild
|
||||
marginY="auto"
|
||||
marginRight="4px"
|
||||
data-testid="context-menu_trigger">
|
||||
data-testid="context-menu_trigger"
|
||||
>
|
||||
{/* This is very stupid, we need to set as span to prevent a button in button... WTF */}
|
||||
<Button variant="ghost" color="brand.500">
|
||||
<LuMenu />
|
||||
</Button>
|
||||
</MenuTrigger>
|
||||
<MenuContent
|
||||
data-testid="context-menu_content">
|
||||
<MenuContent data-testid="context-menu_content">
|
||||
{elements?.map((data) => (
|
||||
<MenuItem key={data.name} value={data.name} onClick={data.onClick} height="65px" fontSize="25px"
|
||||
data-test-id="context-menu_item" >
|
||||
<MenuItem
|
||||
key={data.name}
|
||||
value={data.name}
|
||||
onClick={data.onClick}
|
||||
height="65px"
|
||||
fontSize="25px"
|
||||
data-test-id="context-menu_item"
|
||||
>
|
||||
{data.icon}
|
||||
{data.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuContent>
|
||||
</MenuRoot >
|
||||
</MenuRoot>
|
||||
);
|
||||
};
|
||||
|
@ -3,6 +3,7 @@ import { RefObject } from 'react';
|
||||
import { Input } from '@chakra-ui/react';
|
||||
|
||||
import { FormGroup, FormGroupProps } from '@/components/form/FormGroup';
|
||||
|
||||
import { useFormidableContextElement } from '../formidable';
|
||||
|
||||
export type FormInputProps = {
|
||||
@ -19,12 +20,9 @@ export const FormInput = ({
|
||||
placeholder,
|
||||
...rest
|
||||
}: FormInputProps) => {
|
||||
const {value, onChange} = useFormidableContextElement(name);
|
||||
const { value, onChange } = useFormidableContextElement(name);
|
||||
return (
|
||||
<FormGroup
|
||||
name={name}
|
||||
{...rest}
|
||||
>
|
||||
<FormGroup name={name} {...rest}>
|
||||
<Input
|
||||
ref={ref}
|
||||
type="text"
|
||||
|
@ -4,6 +4,7 @@ import { Box } from '@chakra-ui/react';
|
||||
|
||||
import { FormSelect } from '@/components/form/FormSelect';
|
||||
import { useFormidable } from '@/components/formidable/FormidableConfig';
|
||||
|
||||
import { Formidable } from '../formidable';
|
||||
|
||||
export default {
|
||||
@ -109,7 +110,7 @@ export const DarkBackground = {
|
||||
{ id: 222, name: 'Second Item' },
|
||||
{ id: 333, name: 'third item' },
|
||||
]}
|
||||
/>
|
||||
/>
|
||||
</Box>
|
||||
</Formidable.From>
|
||||
);
|
||||
|
@ -4,6 +4,7 @@ import { Box } from '@chakra-ui/react';
|
||||
|
||||
import { FormSelectMultiple } from '@/components/form/FormSelectMultiple';
|
||||
import { useFormidable } from '@/components/formidable/FormidableConfig';
|
||||
|
||||
import { Formidable } from '../formidable';
|
||||
|
||||
export default {
|
||||
@ -58,7 +59,7 @@ export const ChangeName = () => {
|
||||
{ id: 222, name: 'Second Item' },
|
||||
{ id: 333, name: 'third item' },
|
||||
]}
|
||||
/>
|
||||
/>
|
||||
</Formidable.From>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
export {type FormidableConfig as config,
|
||||
useFormidable
|
||||
export {
|
||||
type FormidableConfig as config,
|
||||
useFormidable,
|
||||
} from './FormidableConfig';
|
||||
export {FormidableForm as From,
|
||||
type FormidableFormProps as FormProps
|
||||
export {
|
||||
FormidableForm as From,
|
||||
type FormidableFormProps as FormProps,
|
||||
} from './FormidableForm';
|
@ -1,11 +1,7 @@
|
||||
export * as Formidable from './Fromidable';
|
||||
export {
|
||||
useFormidableContext,
|
||||
useFormidableContextElement
|
||||
} from './FormidableContext'
|
||||
export {
|
||||
useFormidable
|
||||
} from './FormidableConfig';
|
||||
export {
|
||||
zodResolver
|
||||
} from './utils';
|
||||
useFormidableContext,
|
||||
useFormidableContextElement,
|
||||
} from './FormidableContext';
|
||||
export { useFormidable } from './FormidableConfig';
|
||||
export { zodResolver } from './utils';
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { useRef } from 'react';
|
||||
|
||||
import {
|
||||
Button,
|
||||
UseDisclosureReturn,
|
||||
} from '@chakra-ui/react';
|
||||
import { Button, UseDisclosureReturn } from '@chakra-ui/react';
|
||||
|
||||
import {
|
||||
DialogBody,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogRoot,
|
||||
} from '@/components/ui/dialog';
|
||||
|
||||
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||
export type ConfirmPopUpProps = {
|
||||
title: string;
|
||||
body: string;
|
||||
@ -27,7 +31,8 @@ export const ConfirmPopUp = ({
|
||||
};
|
||||
const cancelRef = useRef<HTMLButtonElement>(null);
|
||||
return (
|
||||
<DialogRoot role="alertdialog"
|
||||
<DialogRoot
|
||||
role="alertdialog"
|
||||
open={disclosure.open}
|
||||
//leastDestructiveRef={cancelRef}
|
||||
onOpenChange={disclosure.onClose}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { useRef } from 'react';
|
||||
|
||||
import { Button, Flex, Progress, Text } from '@chakra-ui/react';
|
||||
|
||||
import {
|
||||
Flex,
|
||||
Progress,
|
||||
Text,
|
||||
Button,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||
|
||||
DialogBody,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogRoot,
|
||||
} from '@/components/ui/dialog';
|
||||
|
||||
export type PopUpUploadProgressProps = {
|
||||
title: string;
|
||||
|
@ -102,14 +102,20 @@ export const SelectMultiple = ({
|
||||
const createNewItem = !onCreate
|
||||
? undefined
|
||||
: (data: string) => {
|
||||
onCreate(data);
|
||||
setCurrentSearch(undefined);
|
||||
};
|
||||
onCreate(data);
|
||||
setCurrentSearch(undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex direction="column" width="full" gap="0px">
|
||||
{selectedOptions && (
|
||||
<HStack wrap="wrap" gap="5px" justify="left" width="full" marginBottom="2px">
|
||||
<HStack
|
||||
wrap="wrap"
|
||||
gap="5px"
|
||||
justify="left"
|
||||
width="full"
|
||||
marginBottom="2px"
|
||||
>
|
||||
{selectedOptions.map((data) => (
|
||||
<Flex align="flex-start" key={data[keyKey]}>
|
||||
<Tag.Root
|
||||
@ -119,7 +125,10 @@ export const SelectMultiple = ({
|
||||
backgroundColor="green.800"
|
||||
>
|
||||
<Tag.Label>{data[keyValue] ?? `id=${data[keyKey]}`}</Tag.Label>
|
||||
<Tag.CloseTrigger boxSize="5" onClick={() => selectValue(data)} />
|
||||
<Tag.CloseTrigger
|
||||
boxSize="5"
|
||||
onClick={() => selectValue(data)}
|
||||
/>
|
||||
</Tag.Root>
|
||||
</Flex>
|
||||
))}
|
||||
@ -134,7 +143,13 @@ export const SelectMultiple = ({
|
||||
//onSubmit={onSubmit}
|
||||
onFocus={() => setShowList(true)}
|
||||
onBlur={() => setTimeout(() => setShowList(false), 200)}
|
||||
value={showList ? (currentSearch ?? '') : hasSuggestion ? `suggest: ${currentSearch}` : ''}
|
||||
value={
|
||||
showList
|
||||
? (currentSearch ?? '')
|
||||
: hasSuggestion
|
||||
? `suggest: ${currentSearch}`
|
||||
: ''
|
||||
}
|
||||
borderRadius="5px 0 0 5px"
|
||||
/>
|
||||
<Button
|
||||
|
@ -50,7 +50,9 @@ export const SelectSingle = ({
|
||||
onCreate ? suggestion : undefined
|
||||
);
|
||||
useEffect(() => {
|
||||
console.log(`Update suggestion : ${onCreate} ${suggestion} ==> ${onCreate ? suggestion : undefined} .. ${onCreate && !isNullOrUndefined(suggestion) ? true : false}`);
|
||||
console.log(
|
||||
`Update suggestion : ${onCreate} ${suggestion} ==> ${onCreate ? suggestion : undefined} .. ${onCreate && !isNullOrUndefined(suggestion) ? true : false}`
|
||||
);
|
||||
setCurrentSearch(onCreate ? suggestion : undefined);
|
||||
setHasSuggestion(onCreate && !isNullOrUndefined(suggestion) ? true : false);
|
||||
}, [suggestion]);
|
||||
@ -95,10 +97,10 @@ export const SelectSingle = ({
|
||||
const createNewItem = !onCreate
|
||||
? undefined
|
||||
: (data: string) => {
|
||||
onCreate(data);
|
||||
setCurrentSearch(undefined);
|
||||
setHasSuggestion(false);
|
||||
};
|
||||
onCreate(data);
|
||||
setCurrentSearch(undefined);
|
||||
setHasSuggestion(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex direction="column" width="full" gap="0px">
|
||||
@ -110,7 +112,10 @@ export const SelectSingle = ({
|
||||
onFocus={() => setShowList(true)}
|
||||
onBlur={() => setTimeout(() => setShowList(false), 200)}
|
||||
value={
|
||||
showList ? (currentSearch ?? '') : (selectedOptions?.name ?? (hasSuggestion ? `suggest: ${currentSearch}` : ''))
|
||||
showList
|
||||
? (currentSearch ?? '')
|
||||
: (selectedOptions?.name ??
|
||||
(hasSuggestion ? `suggest: ${currentSearch}` : ''))
|
||||
}
|
||||
backgroundColor={
|
||||
showList || !selectedOptions ? undefined : 'green.800'
|
||||
|
@ -1,24 +1,25 @@
|
||||
"use client"
|
||||
'use client';
|
||||
|
||||
import type { GroupProps, SlotRecipeProps } from "@chakra-ui/react"
|
||||
import { Avatar as ChakraAvatar, Group } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
type ImageProps = React.ImgHTMLAttributes<HTMLImageElement>
|
||||
import type { GroupProps, SlotRecipeProps } from '@chakra-ui/react';
|
||||
import { Avatar as ChakraAvatar, Group } from '@chakra-ui/react';
|
||||
|
||||
type ImageProps = React.ImgHTMLAttributes<HTMLImageElement>;
|
||||
|
||||
export interface AvatarProps extends ChakraAvatar.RootProps {
|
||||
name?: string
|
||||
src?: string
|
||||
srcSet?: string
|
||||
loading?: ImageProps["loading"]
|
||||
icon?: React.ReactElement
|
||||
fallback?: React.ReactNode
|
||||
name?: string;
|
||||
src?: string;
|
||||
srcSet?: string;
|
||||
loading?: ImageProps['loading'];
|
||||
icon?: React.ReactElement;
|
||||
fallback?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(
|
||||
function Avatar(props, ref) {
|
||||
const { name, src, srcSet, loading, icon, fallback, children, ...rest } =
|
||||
props
|
||||
props;
|
||||
return (
|
||||
<ChakraAvatar.Root ref={ref} {...rest}>
|
||||
<AvatarFallback name={name} icon={icon}>
|
||||
@ -27,18 +28,18 @@ export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(
|
||||
<ChakraAvatar.Image src={src} srcSet={srcSet} loading={loading} />
|
||||
{children}
|
||||
</ChakraAvatar.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
interface AvatarFallbackProps extends ChakraAvatar.FallbackProps {
|
||||
name?: string
|
||||
icon?: React.ReactElement
|
||||
name?: string;
|
||||
icon?: React.ReactElement;
|
||||
}
|
||||
|
||||
const AvatarFallback = React.forwardRef<HTMLDivElement, AvatarFallbackProps>(
|
||||
function AvatarFallback(props, ref) {
|
||||
const { name, icon, children, ...rest } = props
|
||||
const { name, icon, children, ...rest } = props;
|
||||
return (
|
||||
<ChakraAvatar.Fallback ref={ref} {...rest}>
|
||||
{children}
|
||||
@ -47,28 +48,28 @@ const AvatarFallback = React.forwardRef<HTMLDivElement, AvatarFallbackProps>(
|
||||
<ChakraAvatar.Icon asChild={!!icon}>{icon}</ChakraAvatar.Icon>
|
||||
)}
|
||||
</ChakraAvatar.Fallback>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
function getInitials(name: string) {
|
||||
const names = name.trim().split(" ")
|
||||
const firstName = names[0] != null ? names[0] : ""
|
||||
const lastName = names.length > 1 ? names[names.length - 1] : ""
|
||||
const names = name.trim().split(' ');
|
||||
const firstName = names[0] != null ? names[0] : '';
|
||||
const lastName = names.length > 1 ? names[names.length - 1] : '';
|
||||
return firstName && lastName
|
||||
? `${firstName.charAt(0)}${lastName.charAt(0)}`
|
||||
: firstName.charAt(0)
|
||||
: firstName.charAt(0);
|
||||
}
|
||||
|
||||
interface AvatarGroupProps extends GroupProps, SlotRecipeProps<"avatar"> {}
|
||||
interface AvatarGroupProps extends GroupProps, SlotRecipeProps<'avatar'> {}
|
||||
|
||||
export const AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(
|
||||
function AvatarGroup(props, ref) {
|
||||
const { size, variant, borderless, ...rest } = props
|
||||
const { size, variant, borderless, ...rest } = props;
|
||||
return (
|
||||
<ChakraAvatar.PropsProvider value={{ size, variant, borderless }}>
|
||||
<Group gap="0" spaceX="-3" ref={ref} {...rest} />
|
||||
</ChakraAvatar.PropsProvider>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -1,22 +1,23 @@
|
||||
import type { ButtonProps as ChakraButtonProps } from "@chakra-ui/react"
|
||||
import * as React from 'react';
|
||||
|
||||
import type { ButtonProps as ChakraButtonProps } from '@chakra-ui/react';
|
||||
import {
|
||||
AbsoluteCenter,
|
||||
Button as ChakraButton,
|
||||
Span,
|
||||
Spinner,
|
||||
} from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
interface ButtonLoadingProps {
|
||||
loading?: boolean
|
||||
loadingText?: React.ReactNode
|
||||
loading?: boolean;
|
||||
loadingText?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface ButtonProps extends ChakraButtonProps, ButtonLoadingProps {}
|
||||
|
||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
function Button(props, ref) {
|
||||
const { loading, disabled, loadingText, children, ...rest } = props
|
||||
const { loading, disabled, loadingText, children, ...rest } = props;
|
||||
return (
|
||||
<ChakraButton disabled={loading || disabled} ref={ref} {...rest}>
|
||||
{loading && !loadingText ? (
|
||||
@ -35,6 +36,6 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
children
|
||||
)}
|
||||
</ChakraButton>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { Checkbox as ChakraCheckbox } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import { Checkbox as ChakraCheckbox } from '@chakra-ui/react';
|
||||
|
||||
export interface CheckboxProps extends ChakraCheckbox.RootProps {
|
||||
icon?: React.ReactNode
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
rootRef?: React.Ref<HTMLLabelElement>
|
||||
icon?: React.ReactNode;
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
|
||||
rootRef?: React.Ref<HTMLLabelElement>;
|
||||
}
|
||||
|
||||
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
function Checkbox(props, ref) {
|
||||
const { icon, children, inputProps, rootRef, ...rest } = props
|
||||
const { icon, children, inputProps, rootRef, ...rest } = props;
|
||||
return (
|
||||
<ChakraCheckbox.Root ref={rootRef} {...rest}>
|
||||
<ChakraCheckbox.HiddenInput ref={ref} {...inputProps} />
|
||||
@ -20,6 +21,6 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
<ChakraCheckbox.Label>{children}</ChakraCheckbox.Label>
|
||||
)}
|
||||
</ChakraCheckbox.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -1,9 +1,10 @@
|
||||
import type { ButtonProps } from "@chakra-ui/react"
|
||||
import { IconButton as ChakraIconButton } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import { LuX } from "react-icons/lu"
|
||||
import * as React from 'react';
|
||||
|
||||
export type CloseButtonProps = ButtonProps
|
||||
import type { ButtonProps } from '@chakra-ui/react';
|
||||
import { IconButton as ChakraIconButton } from '@chakra-ui/react';
|
||||
import { LuX } from 'react-icons/lu';
|
||||
|
||||
export type CloseButtonProps = ButtonProps;
|
||||
|
||||
export const CloseButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
@ -13,5 +14,5 @@ export const CloseButton = React.forwardRef<
|
||||
<ChakraIconButton variant="ghost" aria-label="Close" ref={ref} {...props}>
|
||||
{props.children ?? <LuX />}
|
||||
</ChakraIconButton>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -1,57 +1,58 @@
|
||||
"use client"
|
||||
'use client';
|
||||
|
||||
import type { IconButtonProps } from "@chakra-ui/react"
|
||||
import { ClientOnly, IconButton, Skeleton } from "@chakra-ui/react"
|
||||
import { ThemeProvider, useTheme } from "next-themes"
|
||||
import type { ThemeProviderProps } from "next-themes"
|
||||
import * as React from "react"
|
||||
import { LuMoon, LuSun } from "react-icons/lu"
|
||||
import * as React from 'react';
|
||||
|
||||
import type { IconButtonProps } from '@chakra-ui/react';
|
||||
import { ClientOnly, IconButton, Skeleton } from '@chakra-ui/react';
|
||||
import { ThemeProvider, useTheme } from 'next-themes';
|
||||
import type { ThemeProviderProps } from 'next-themes';
|
||||
import { LuMoon, LuSun } from 'react-icons/lu';
|
||||
|
||||
export interface ColorModeProviderProps extends ThemeProviderProps {}
|
||||
|
||||
export function ColorModeProvider(props: ColorModeProviderProps) {
|
||||
return (
|
||||
<ThemeProvider attribute="class" disableTransitionOnChange {...props} />
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export type ColorMode = "light" | "dark"
|
||||
export type ColorMode = 'light' | 'dark';
|
||||
|
||||
export interface UseColorModeReturn {
|
||||
colorMode: ColorMode
|
||||
setColorMode: (colorMode: ColorMode) => void
|
||||
toggleColorMode: () => void
|
||||
colorMode: ColorMode;
|
||||
setColorMode: (colorMode: ColorMode) => void;
|
||||
toggleColorMode: () => void;
|
||||
}
|
||||
|
||||
export function useColorMode(): UseColorModeReturn {
|
||||
const { resolvedTheme, setTheme } = useTheme()
|
||||
const { resolvedTheme, setTheme } = useTheme();
|
||||
const toggleColorMode = () => {
|
||||
setTheme(resolvedTheme === "light" ? "dark" : "light")
|
||||
}
|
||||
setTheme(resolvedTheme === 'light' ? 'dark' : 'light');
|
||||
};
|
||||
return {
|
||||
colorMode: resolvedTheme as ColorMode,
|
||||
setColorMode: setTheme,
|
||||
toggleColorMode,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function useColorModeValue<T>(light: T, dark: T) {
|
||||
const { colorMode } = useColorMode()
|
||||
return colorMode === "dark" ? dark : light
|
||||
const { colorMode } = useColorMode();
|
||||
return colorMode === 'dark' ? dark : light;
|
||||
}
|
||||
|
||||
export function ColorModeIcon() {
|
||||
const { colorMode } = useColorMode()
|
||||
return colorMode === "dark" ? <LuMoon /> : <LuSun />
|
||||
const { colorMode } = useColorMode();
|
||||
return colorMode === 'dark' ? <LuMoon /> : <LuSun />;
|
||||
}
|
||||
|
||||
interface ColorModeButtonProps extends Omit<IconButtonProps, "aria-label"> {}
|
||||
interface ColorModeButtonProps extends Omit<IconButtonProps, 'aria-label'> {}
|
||||
|
||||
export const ColorModeButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ColorModeButtonProps
|
||||
>(function ColorModeButton(props, ref) {
|
||||
const { toggleColorMode } = useColorMode()
|
||||
const { toggleColorMode } = useColorMode();
|
||||
return (
|
||||
<ClientOnly fallback={<Skeleton boxSize="8" />}>
|
||||
<IconButton
|
||||
@ -63,13 +64,13 @@ export const ColorModeButton = React.forwardRef<
|
||||
{...props}
|
||||
css={{
|
||||
_icon: {
|
||||
width: "5",
|
||||
height: "5",
|
||||
width: '5',
|
||||
height: '5',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ColorModeIcon />
|
||||
</IconButton>
|
||||
</ClientOnly>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Dialog as ChakraDialog, Portal } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import { Dialog as ChakraDialog, Portal } from '@chakra-ui/react';
|
||||
|
||||
import { CloseButton } from './close-button';
|
||||
|
||||
interface DialogContentProps extends ChakraDialog.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
backdrop?: boolean
|
||||
portalled?: boolean;
|
||||
portalRef?: React.RefObject<HTMLElement>;
|
||||
backdrop?: boolean;
|
||||
}
|
||||
|
||||
export const DialogContent = React.forwardRef<
|
||||
@ -18,7 +20,7 @@ export const DialogContent = React.forwardRef<
|
||||
portalRef,
|
||||
backdrop = true,
|
||||
...rest
|
||||
} = props
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
@ -29,8 +31,8 @@ export const DialogContent = React.forwardRef<
|
||||
</ChakraDialog.Content>
|
||||
</ChakraDialog.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const DialogCloseTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
@ -48,15 +50,15 @@ export const DialogCloseTrigger = React.forwardRef<
|
||||
{props.children}
|
||||
</CloseButton>
|
||||
</ChakraDialog.CloseTrigger>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const DialogRoot = ChakraDialog.Root
|
||||
export const DialogFooter = ChakraDialog.Footer
|
||||
export const DialogHeader = ChakraDialog.Header
|
||||
export const DialogBody = ChakraDialog.Body
|
||||
export const DialogBackdrop = ChakraDialog.Backdrop
|
||||
export const DialogTitle = ChakraDialog.Title
|
||||
export const DialogDescription = ChakraDialog.Description
|
||||
export const DialogTrigger = ChakraDialog.Trigger
|
||||
export const DialogActionTrigger = ChakraDialog.ActionTrigger
|
||||
export const DialogRoot = ChakraDialog.Root;
|
||||
export const DialogFooter = ChakraDialog.Footer;
|
||||
export const DialogHeader = ChakraDialog.Header;
|
||||
export const DialogBody = ChakraDialog.Body;
|
||||
export const DialogBackdrop = ChakraDialog.Backdrop;
|
||||
export const DialogTitle = ChakraDialog.Title;
|
||||
export const DialogDescription = ChakraDialog.Description;
|
||||
export const DialogTrigger = ChakraDialog.Trigger;
|
||||
export const DialogActionTrigger = ChakraDialog.ActionTrigger;
|
||||
|
@ -1,18 +1,20 @@
|
||||
import { Drawer as ChakraDrawer, Portal } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import { Drawer as ChakraDrawer, Portal } from '@chakra-ui/react';
|
||||
|
||||
import { CloseButton } from './close-button';
|
||||
|
||||
interface DrawerContentProps extends ChakraDrawer.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
offset?: ChakraDrawer.ContentProps["padding"]
|
||||
portalled?: boolean;
|
||||
portalRef?: React.RefObject<HTMLElement>;
|
||||
offset?: ChakraDrawer.ContentProps['padding'];
|
||||
}
|
||||
|
||||
export const DrawerContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
DrawerContentProps
|
||||
>(function DrawerContent(props, ref) {
|
||||
const { children, portalled = true, portalRef, offset, ...rest } = props
|
||||
const { children, portalled = true, portalRef, offset, ...rest } = props;
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraDrawer.Positioner padding={offset}>
|
||||
@ -21,8 +23,8 @@ export const DrawerContent = React.forwardRef<
|
||||
</ChakraDrawer.Content>
|
||||
</ChakraDrawer.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const DrawerCloseTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
@ -38,15 +40,15 @@ export const DrawerCloseTrigger = React.forwardRef<
|
||||
>
|
||||
<CloseButton size="sm" ref={ref} />
|
||||
</ChakraDrawer.CloseTrigger>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const DrawerTrigger = ChakraDrawer.Trigger
|
||||
export const DrawerRoot = ChakraDrawer.Root
|
||||
export const DrawerFooter = ChakraDrawer.Footer
|
||||
export const DrawerHeader = ChakraDrawer.Header
|
||||
export const DrawerBody = ChakraDrawer.Body
|
||||
export const DrawerBackdrop = ChakraDrawer.Backdrop
|
||||
export const DrawerDescription = ChakraDrawer.Description
|
||||
export const DrawerTitle = ChakraDrawer.Title
|
||||
export const DrawerActionTrigger = ChakraDrawer.ActionTrigger
|
||||
export const DrawerTrigger = ChakraDrawer.Trigger;
|
||||
export const DrawerRoot = ChakraDrawer.Root;
|
||||
export const DrawerFooter = ChakraDrawer.Footer;
|
||||
export const DrawerHeader = ChakraDrawer.Header;
|
||||
export const DrawerBody = ChakraDrawer.Body;
|
||||
export const DrawerBackdrop = ChakraDrawer.Backdrop;
|
||||
export const DrawerDescription = ChakraDrawer.Description;
|
||||
export const DrawerTitle = ChakraDrawer.Title;
|
||||
export const DrawerActionTrigger = ChakraDrawer.ActionTrigger;
|
||||
|
@ -1,17 +1,18 @@
|
||||
import { Field as ChakraField } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
export interface FieldProps extends Omit<ChakraField.RootProps, "label"> {
|
||||
label?: React.ReactNode
|
||||
helperText?: React.ReactNode
|
||||
errorText?: React.ReactNode
|
||||
optionalText?: React.ReactNode
|
||||
import { Field as ChakraField } from '@chakra-ui/react';
|
||||
|
||||
export interface FieldProps extends Omit<ChakraField.RootProps, 'label'> {
|
||||
label?: React.ReactNode;
|
||||
helperText?: React.ReactNode;
|
||||
errorText?: React.ReactNode;
|
||||
optionalText?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
||||
function Field(props, ref) {
|
||||
const { label, children, helperText, errorText, optionalText, ...rest } =
|
||||
props
|
||||
props;
|
||||
return (
|
||||
<ChakraField.Root ref={ref} {...rest}>
|
||||
{label && (
|
||||
@ -28,6 +29,6 @@ export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
||||
<ChakraField.ErrorText>{errorText}</ChakraField.ErrorText>
|
||||
)}
|
||||
</ChakraField.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -1,15 +1,16 @@
|
||||
import type { BoxProps, InputElementProps } from "@chakra-ui/react"
|
||||
import { Group, InputElement } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import type { BoxProps, InputElementProps } from '@chakra-ui/react';
|
||||
import { Group, InputElement } from '@chakra-ui/react';
|
||||
|
||||
export interface InputGroupProps extends BoxProps {
|
||||
startElementProps?: InputElementProps
|
||||
endElementProps?: InputElementProps
|
||||
startElement?: React.ReactNode
|
||||
endElement?: React.ReactNode
|
||||
children: React.ReactElement<InputElementProps>
|
||||
startOffset?: InputElementProps["paddingStart"]
|
||||
endOffset?: InputElementProps["paddingEnd"]
|
||||
startElementProps?: InputElementProps;
|
||||
endElementProps?: InputElementProps;
|
||||
startElement?: React.ReactNode;
|
||||
endElement?: React.ReactNode;
|
||||
children: React.ReactElement<InputElementProps>;
|
||||
startOffset?: InputElementProps['paddingStart'];
|
||||
endOffset?: InputElementProps['paddingEnd'];
|
||||
}
|
||||
|
||||
export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
||||
@ -20,13 +21,13 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
||||
endElement,
|
||||
endElementProps,
|
||||
children,
|
||||
startOffset = "6px",
|
||||
endOffset = "6px",
|
||||
startOffset = '6px',
|
||||
endOffset = '6px',
|
||||
...rest
|
||||
} = props
|
||||
} = props;
|
||||
|
||||
const child =
|
||||
React.Children.only<React.ReactElement<InputElementProps>>(children)
|
||||
React.Children.only<React.ReactElement<InputElementProps>>(children);
|
||||
|
||||
return (
|
||||
<Group ref={ref} {...rest}>
|
||||
@ -48,6 +49,6 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
||||
</InputElement>
|
||||
)}
|
||||
</Group>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -1,26 +1,27 @@
|
||||
"use client"
|
||||
'use client';
|
||||
|
||||
import { AbsoluteCenter, Menu as ChakraMenu, Portal } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import { LuCheck, LuChevronRight } from "react-icons/lu"
|
||||
import * as React from 'react';
|
||||
|
||||
import { AbsoluteCenter, Menu as ChakraMenu, Portal } from '@chakra-ui/react';
|
||||
import { LuCheck, LuChevronRight } from 'react-icons/lu';
|
||||
|
||||
interface MenuContentProps extends ChakraMenu.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
portalled?: boolean;
|
||||
portalRef?: React.RefObject<HTMLElement>;
|
||||
}
|
||||
|
||||
export const MenuContent = React.forwardRef<HTMLDivElement, MenuContentProps>(
|
||||
function MenuContent(props, ref) {
|
||||
const { portalled = true, portalRef, ...rest } = props
|
||||
const { portalled = true, portalRef, ...rest } = props;
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraMenu.Positioner>
|
||||
<ChakraMenu.Content ref={ref} {...rest} />
|
||||
</ChakraMenu.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const MenuArrow = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
@ -30,8 +31,8 @@ export const MenuArrow = React.forwardRef<
|
||||
<ChakraMenu.Arrow ref={ref} {...props}>
|
||||
<ChakraMenu.ArrowTip />
|
||||
</ChakraMenu.Arrow>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const MenuCheckboxItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
@ -44,14 +45,14 @@ export const MenuCheckboxItem = React.forwardRef<
|
||||
</ChakraMenu.ItemIndicator>
|
||||
{props.children}
|
||||
</ChakraMenu.CheckboxItem>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const MenuRadioItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraMenu.RadioItemProps
|
||||
>(function MenuRadioItem(props, ref) {
|
||||
const { children, ...rest } = props
|
||||
const { children, ...rest } = props;
|
||||
return (
|
||||
<ChakraMenu.RadioItem ps="8" ref={ref} {...rest}>
|
||||
<AbsoluteCenter axis="horizontal" left="4" asChild>
|
||||
@ -61,14 +62,14 @@ export const MenuRadioItem = React.forwardRef<
|
||||
</AbsoluteCenter>
|
||||
<ChakraMenu.ItemText>{children}</ChakraMenu.ItemText>
|
||||
</ChakraMenu.RadioItem>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const MenuItemGroup = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ChakraMenu.ItemGroupProps
|
||||
>(function MenuItemGroup(props, ref) {
|
||||
const { title, children, ...rest } = props
|
||||
const { title, children, ...rest } = props;
|
||||
return (
|
||||
<ChakraMenu.ItemGroup ref={ref} {...rest}>
|
||||
{title && (
|
||||
@ -78,33 +79,33 @@ export const MenuItemGroup = React.forwardRef<
|
||||
)}
|
||||
{children}
|
||||
</ChakraMenu.ItemGroup>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export interface MenuTriggerItemProps extends ChakraMenu.ItemProps {
|
||||
startIcon?: React.ReactNode
|
||||
startIcon?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const MenuTriggerItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
MenuTriggerItemProps
|
||||
>(function MenuTriggerItem(props, ref) {
|
||||
const { startIcon, children, ...rest } = props
|
||||
const { startIcon, children, ...rest } = props;
|
||||
return (
|
||||
<ChakraMenu.TriggerItem ref={ref} {...rest}>
|
||||
{startIcon}
|
||||
{children}
|
||||
<LuChevronRight />
|
||||
</ChakraMenu.TriggerItem>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const MenuRadioItemGroup = ChakraMenu.RadioItemGroup
|
||||
export const MenuContextTrigger = ChakraMenu.ContextTrigger
|
||||
export const MenuRoot = ChakraMenu.Root
|
||||
export const MenuSeparator = ChakraMenu.Separator
|
||||
export const MenuRadioItemGroup = ChakraMenu.RadioItemGroup;
|
||||
export const MenuContextTrigger = ChakraMenu.ContextTrigger;
|
||||
export const MenuRoot = ChakraMenu.Root;
|
||||
export const MenuSeparator = ChakraMenu.Separator;
|
||||
|
||||
export const MenuItem = ChakraMenu.Item
|
||||
export const MenuItemText = ChakraMenu.ItemText
|
||||
export const MenuItemCommand = ChakraMenu.ItemCommand
|
||||
export const MenuTrigger = ChakraMenu.Trigger
|
||||
export const MenuItem = ChakraMenu.Item;
|
||||
export const MenuItemText = ChakraMenu.ItemText;
|
||||
export const MenuItemCommand = ChakraMenu.ItemCommand;
|
||||
export const MenuTrigger = ChakraMenu.Trigger;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { NumberInput as ChakraNumberInput } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import { NumberInput as ChakraNumberInput } from '@chakra-ui/react';
|
||||
|
||||
export interface NumberInputProps extends ChakraNumberInput.RootProps {}
|
||||
|
||||
@ -7,7 +8,7 @@ export const NumberInputRoot = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
NumberInputProps
|
||||
>(function NumberInput(props, ref) {
|
||||
const { children, ...rest } = props
|
||||
const { children, ...rest } = props;
|
||||
return (
|
||||
<ChakraNumberInput.Root ref={ref} variant="outline" {...rest}>
|
||||
{children}
|
||||
@ -16,9 +17,9 @@ export const NumberInputRoot = React.forwardRef<
|
||||
<ChakraNumberInput.DecrementTrigger />
|
||||
</ChakraNumberInput.Control>
|
||||
</ChakraNumberInput.Root>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const NumberInputField = ChakraNumberInput.Input
|
||||
export const NumberInputScrubber = ChakraNumberInput.Scrubber
|
||||
export const NumberInputLabel = ChakraNumberInput.Label
|
||||
export const NumberInputField = ChakraNumberInput.Input;
|
||||
export const NumberInputScrubber = ChakraNumberInput.Scrubber;
|
||||
export const NumberInputLabel = ChakraNumberInput.Label;
|
||||
|
@ -1,25 +1,27 @@
|
||||
import { Popover as ChakraPopover, Portal } from "@chakra-ui/react"
|
||||
import { CloseButton } from "./close-button"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import { Popover as ChakraPopover, Portal } from '@chakra-ui/react';
|
||||
|
||||
import { CloseButton } from './close-button';
|
||||
|
||||
interface PopoverContentProps extends ChakraPopover.ContentProps {
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
portalled?: boolean;
|
||||
portalRef?: React.RefObject<HTMLElement>;
|
||||
}
|
||||
|
||||
export const PopoverContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
PopoverContentProps
|
||||
>(function PopoverContent(props, ref) {
|
||||
const { portalled = true, portalRef, ...rest } = props
|
||||
const { portalled = true, portalRef, ...rest } = props;
|
||||
return (
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraPopover.Positioner>
|
||||
<ChakraPopover.Content ref={ref} {...rest} />
|
||||
</ChakraPopover.Positioner>
|
||||
</Portal>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const PopoverArrow = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
@ -29,8 +31,8 @@ export const PopoverArrow = React.forwardRef<
|
||||
<ChakraPopover.Arrow {...props} ref={ref}>
|
||||
<ChakraPopover.ArrowTip />
|
||||
</ChakraPopover.Arrow>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const PopoverCloseTrigger = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
@ -47,13 +49,13 @@ export const PopoverCloseTrigger = React.forwardRef<
|
||||
>
|
||||
<CloseButton size="sm" />
|
||||
</ChakraPopover.CloseTrigger>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
export const PopoverTitle = ChakraPopover.Title
|
||||
export const PopoverDescription = ChakraPopover.Description
|
||||
export const PopoverFooter = ChakraPopover.Footer
|
||||
export const PopoverHeader = ChakraPopover.Header
|
||||
export const PopoverRoot = ChakraPopover.Root
|
||||
export const PopoverBody = ChakraPopover.Body
|
||||
export const PopoverTrigger = ChakraPopover.Trigger
|
||||
export const PopoverTitle = ChakraPopover.Title;
|
||||
export const PopoverDescription = ChakraPopover.Description;
|
||||
export const PopoverFooter = ChakraPopover.Footer;
|
||||
export const PopoverHeader = ChakraPopover.Header;
|
||||
export const PopoverRoot = ChakraPopover.Root;
|
||||
export const PopoverBody = ChakraPopover.Body;
|
||||
export const PopoverTrigger = ChakraPopover.Trigger;
|
||||
|
@ -1,15 +1,13 @@
|
||||
"use client"
|
||||
'use client';
|
||||
|
||||
import { ChakraProvider, defaultSystem } from "@chakra-ui/react"
|
||||
import {
|
||||
ColorModeProvider,
|
||||
type ColorModeProviderProps,
|
||||
} from "./color-mode"
|
||||
import { ChakraProvider, defaultSystem } from '@chakra-ui/react';
|
||||
|
||||
import { ColorModeProvider, type ColorModeProviderProps } from './color-mode';
|
||||
|
||||
export function Provider(props: ColorModeProviderProps) {
|
||||
return (
|
||||
<ChakraProvider value={defaultSystem}>
|
||||
<ColorModeProvider {...props} />
|
||||
</ChakraProvider>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
import { RadioGroup as ChakraRadioGroup } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import { RadioGroup as ChakraRadioGroup } from '@chakra-ui/react';
|
||||
|
||||
export interface RadioProps extends ChakraRadioGroup.ItemProps {
|
||||
rootRef?: React.Ref<HTMLDivElement>
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
rootRef?: React.Ref<HTMLDivElement>;
|
||||
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
|
||||
}
|
||||
|
||||
export const Radio = React.forwardRef<HTMLInputElement, RadioProps>(
|
||||
function Radio(props, ref) {
|
||||
const { children, inputProps, rootRef, ...rest } = props
|
||||
const { children, inputProps, rootRef, ...rest } = props;
|
||||
return (
|
||||
<ChakraRadioGroup.Item ref={rootRef} {...rest}>
|
||||
<ChakraRadioGroup.ItemHiddenInput ref={ref} {...inputProps} />
|
||||
@ -17,8 +18,8 @@ export const Radio = React.forwardRef<HTMLInputElement, RadioProps>(
|
||||
<ChakraRadioGroup.ItemText>{children}</ChakraRadioGroup.ItemText>
|
||||
)}
|
||||
</ChakraRadioGroup.Item>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const RadioGroup = ChakraRadioGroup.Root
|
||||
export const RadioGroup = ChakraRadioGroup.Root;
|
||||
|
@ -1,23 +1,24 @@
|
||||
import { Slider as ChakraSlider, For, HStack } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import { Slider as ChakraSlider, For, HStack } from '@chakra-ui/react';
|
||||
|
||||
export interface SliderProps extends ChakraSlider.RootProps {
|
||||
marks?: Array<number | { value: number; label: React.ReactNode }>
|
||||
label?: React.ReactNode
|
||||
showValue?: boolean
|
||||
marks?: Array<number | { value: number; label: React.ReactNode }>;
|
||||
label?: React.ReactNode;
|
||||
showValue?: boolean;
|
||||
}
|
||||
|
||||
export const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
|
||||
function Slider(props, ref) {
|
||||
const { marks: marksProp, label, showValue, ...rest } = props
|
||||
const value = props.defaultValue ?? props.value
|
||||
const { marks: marksProp, label, showValue, ...rest } = props;
|
||||
const value = props.defaultValue ?? props.value;
|
||||
|
||||
const marks = marksProp?.map((mark) => {
|
||||
if (typeof mark === "number") return { value: mark, label: undefined }
|
||||
return mark
|
||||
})
|
||||
if (typeof mark === 'number') return { value: mark, label: undefined };
|
||||
return mark;
|
||||
});
|
||||
|
||||
const hasMarkLabel = !!marks?.some((mark) => mark.label)
|
||||
const hasMarkLabel = !!marks?.some((mark) => mark.label);
|
||||
|
||||
return (
|
||||
<ChakraSlider.Root ref={ref} thumbAlignment="center" {...rest}>
|
||||
@ -38,12 +39,12 @@ export const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
|
||||
<SliderMarks marks={marks} />
|
||||
</ChakraSlider.Control>
|
||||
</ChakraSlider.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
function SliderThumbs(props: { value?: number[] }) {
|
||||
const { value } = props
|
||||
const { value } = props;
|
||||
return (
|
||||
<For each={value}>
|
||||
{(_, index) => (
|
||||
@ -52,31 +53,31 @@ function SliderThumbs(props: { value?: number[] }) {
|
||||
</ChakraSlider.Thumb>
|
||||
)}
|
||||
</For>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
interface SliderMarksProps {
|
||||
marks?: Array<number | { value: number; label: React.ReactNode }>
|
||||
marks?: Array<number | { value: number; label: React.ReactNode }>;
|
||||
}
|
||||
|
||||
const SliderMarks = React.forwardRef<HTMLDivElement, SliderMarksProps>(
|
||||
function SliderMarks(props, ref) {
|
||||
const { marks } = props
|
||||
if (!marks?.length) return null
|
||||
const { marks } = props;
|
||||
if (!marks?.length) return null;
|
||||
|
||||
return (
|
||||
<ChakraSlider.MarkerGroup ref={ref}>
|
||||
{marks.map((mark, index) => {
|
||||
const value = typeof mark === "number" ? mark : mark.value
|
||||
const label = typeof mark === "number" ? undefined : mark.label
|
||||
const value = typeof mark === 'number' ? mark : mark.value;
|
||||
const label = typeof mark === 'number' ? undefined : mark.label;
|
||||
return (
|
||||
<ChakraSlider.Marker key={index} value={value}>
|
||||
<ChakraSlider.MarkerIndicator />
|
||||
{label}
|
||||
</ChakraSlider.Marker>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</ChakraSlider.MarkerGroup>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -1,6 +1,5 @@
|
||||
"use client"
|
||||
'use client';
|
||||
|
||||
import { RestErrorResponse } from "@/back-api";
|
||||
import {
|
||||
Toaster as ChakraToaster,
|
||||
Portal,
|
||||
@ -8,12 +7,14 @@ import {
|
||||
Stack,
|
||||
Toast,
|
||||
createToaster,
|
||||
} from "@chakra-ui/react"
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { RestErrorResponse } from '@/back-api';
|
||||
|
||||
export const toaster = createToaster({
|
||||
placement: "bottom-end",
|
||||
placement: 'bottom-end',
|
||||
pauseOnPageIdle: true,
|
||||
})
|
||||
});
|
||||
|
||||
export const toasterAPIError = (error: RestErrorResponse) => {
|
||||
toaster.create({
|
||||
@ -25,10 +26,10 @@ export const toasterAPIError = (error: RestErrorResponse) => {
|
||||
export const Toaster = () => {
|
||||
return (
|
||||
<Portal>
|
||||
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
|
||||
<ChakraToaster toaster={toaster} insetInline={{ mdDown: '4' }}>
|
||||
{(toast) => (
|
||||
<Toast.Root width={{ md: "sm" }}>
|
||||
{toast.type === "loading" ? (
|
||||
<Toast.Root width={{ md: 'sm' }}>
|
||||
{toast.type === 'loading' ? (
|
||||
<Spinner size="sm" color="blue.solid" />
|
||||
) : (
|
||||
<Toast.Indicator />
|
||||
@ -47,5 +48,5 @@ export const Toaster = () => {
|
||||
)}
|
||||
</ChakraToaster>
|
||||
</Portal>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { Tooltip as ChakraTooltip, Portal } from "@chakra-ui/react"
|
||||
import * as React from "react"
|
||||
import * as React from 'react';
|
||||
|
||||
import { Tooltip as ChakraTooltip, Portal } from '@chakra-ui/react';
|
||||
|
||||
export interface TooltipProps extends ChakraTooltip.RootProps {
|
||||
showArrow?: boolean
|
||||
portalled?: boolean
|
||||
portalRef?: React.RefObject<HTMLElement>
|
||||
content: React.ReactNode
|
||||
contentProps?: ChakraTooltip.ContentProps
|
||||
disabled?: boolean
|
||||
showArrow?: boolean;
|
||||
portalled?: boolean;
|
||||
portalRef?: React.RefObject<HTMLElement>;
|
||||
content: React.ReactNode;
|
||||
contentProps?: ChakraTooltip.ContentProps;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
|
||||
@ -21,9 +22,9 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
|
||||
contentProps,
|
||||
portalRef,
|
||||
...rest
|
||||
} = props
|
||||
} = props;
|
||||
|
||||
if (disabled) return children
|
||||
if (disabled) return children;
|
||||
|
||||
return (
|
||||
<ChakraTooltip.Root {...rest}>
|
||||
@ -41,6 +42,6 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
|
||||
</ChakraTooltip.Positioner>
|
||||
</Portal>
|
||||
</ChakraTooltip.Root>
|
||||
)
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -1,28 +0,0 @@
|
||||
import dayjs from 'dayjs';
|
||||
import 'dayjs/locale/fr';
|
||||
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||
import dayOfYear from 'dayjs/plugin/dayOfYear';
|
||||
import duration from 'dayjs/plugin/duration';
|
||||
import isBetween from 'dayjs/plugin/isBetween';
|
||||
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
|
||||
import isToday from 'dayjs/plugin/isToday';
|
||||
import isTomorrow from 'dayjs/plugin/isTomorrow';
|
||||
import isYesterday from 'dayjs/plugin/isYesterday';
|
||||
import quarterOfYear from 'dayjs/plugin/quarterOfYear';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import weekOfYear from 'dayjs/plugin/weekOfYear';
|
||||
|
||||
dayjs.locale('fr');
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.extend(customParseFormat);
|
||||
dayjs.extend(weekOfYear);
|
||||
dayjs.extend(isSameOrAfter);
|
||||
dayjs.extend(isToday);
|
||||
dayjs.extend(isTomorrow);
|
||||
dayjs.extend(isYesterday);
|
||||
dayjs.extend(dayOfYear);
|
||||
dayjs.extend(isBetween);
|
||||
dayjs.extend(advancedFormat);
|
||||
dayjs.extend(quarterOfYear);
|
||||
dayjs.extend(duration);
|
@ -1,2 +0,0 @@
|
||||
import './axios';
|
||||
import './dayjs';
|
@ -1,2 +0,0 @@
|
||||
export const DATE_FORMAT = 'YYYY-MM-DD';
|
||||
export const DATE_FORMAT_FULL = 'dddd DD MMMM HH:mm';
|
@ -1,4 +0,0 @@
|
||||
export const BASE_WRAP_SPACING = { base: "5px", md: "10px", lg: "20px" };
|
||||
export const BASE_WRAP_WIDTH = { base: "90%", md: "45%", lg: "270px" };
|
||||
export const BASE_WRAP_HEIGHT = { base: "75px", lg: "120px" };
|
||||
export const BASE_WRAP_ICON_SIZE = { base: "50px", lg: "100px" };
|
@ -1 +0,0 @@
|
||||
export * from './date'
|
@ -42,8 +42,9 @@ export const isDevelopmentEnvironment = () => {
|
||||
return import.meta.env.MODE === 'development';
|
||||
};
|
||||
|
||||
export const environment = isDevelopmentEnvironment() ? environment_local : environment_back_prod;
|
||||
|
||||
export const environment = isDevelopmentEnvironment()
|
||||
? environment_local
|
||||
: environment_back_prod;
|
||||
|
||||
/**
|
||||
* get the current REST api URL. Depend on the VITE_API_BASE_URL env variable.
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Box, Button, Center, Heading, Link, Text } from '@chakra-ui/react';
|
||||
import { Box, Center, Heading, Link, Text } from '@chakra-ui/react';
|
||||
import { MdControlCamera } from 'react-icons/md';
|
||||
|
||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||
@ -10,15 +10,17 @@ export const Error401 = () => {
|
||||
<TopBar />
|
||||
<PageLayoutInfoCenter padding="25px">
|
||||
<Center>
|
||||
<MdControlCamera style={{ width: "250px", height: "250px", color: "orange" }} />
|
||||
<MdControlCamera
|
||||
style={{ width: '250px', height: '250px', color: 'orange' }}
|
||||
/>
|
||||
</Center>
|
||||
<Box textAlign="center">
|
||||
<Heading>Erreur 401</Heading>
|
||||
<Heading>Error 401</Heading>
|
||||
<Text color="red.600">
|
||||
Vous n'êtes pas autorisé a accéder a ce contenu.
|
||||
You are not authorized to access this content.
|
||||
</Text>
|
||||
<Link as="a" href="/">
|
||||
Retour à l'accueil
|
||||
Back to Homepage
|
||||
</Link>
|
||||
</Box>
|
||||
</PageLayoutInfoCenter>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Box, Button, Center, Heading, Link, Text } from '@chakra-ui/react';
|
||||
import { Box, Center, Heading, Link, Text } from '@chakra-ui/react';
|
||||
import { MdDangerous } from 'react-icons/md';
|
||||
|
||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||
@ -10,14 +10,14 @@ export const Error403 = () => {
|
||||
<TopBar />
|
||||
<PageLayoutInfoCenter padding="25px">
|
||||
<Center>
|
||||
<MdDangerous style={{ width: "250px", height: "250px", color: "red" }} />
|
||||
<MdDangerous
|
||||
style={{ width: '250px', height: '250px', color: 'red' }}
|
||||
/>
|
||||
</Center>
|
||||
<Box textAlign="center">
|
||||
<Heading>Erreur 403</Heading>
|
||||
<Text color="orange.600">Cette page vous est interdite</Text>
|
||||
<Link href="/">
|
||||
Retour à l'accueil
|
||||
</Link>
|
||||
<Heading>Error 403</Heading>
|
||||
<Text color="orange.600">This page is forbidden to you.</Text>
|
||||
<Link href="/">Back to Homepage</Link>
|
||||
</Box>
|
||||
</PageLayoutInfoCenter>
|
||||
</>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Box, Button, Center, Heading, Link, Text } from '@chakra-ui/react';
|
||||
import { Box, Center, Heading, Link, Text } from '@chakra-ui/react';
|
||||
import { MdSignpost } from 'react-icons/md';
|
||||
|
||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||
@ -10,16 +10,16 @@ export const Error404 = () => {
|
||||
<TopBar />
|
||||
<PageLayoutInfoCenter padding="25px">
|
||||
<Center>
|
||||
<MdSignpost style={{ width: "250px", height: "250px", color: "aqua" }} />
|
||||
<MdSignpost
|
||||
style={{ width: '250px', height: '250px', color: 'aqua' }}
|
||||
/>
|
||||
</Center>
|
||||
<Box textAlign="center">
|
||||
<Heading>Erreur 404</Heading>
|
||||
<Heading>Error 404</Heading>
|
||||
<Text color="gray.600">
|
||||
Cette page n'existe plus ou l'URL a changé
|
||||
This page no longer exists or the URL has changed.
|
||||
</Text>
|
||||
<Link href="/">
|
||||
Retour à l'accueil
|
||||
</Link>
|
||||
<Link href="/">Back to Homepage</Link>
|
||||
</Box>
|
||||
</PageLayoutInfoCenter>
|
||||
</>
|
||||
|
@ -1,11 +1,6 @@
|
||||
import React, { FC } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import {
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
Box,
|
||||
Alert,
|
||||
} from '@chakra-ui/react';
|
||||
import { Alert, AlertDescription, AlertTitle, Box } from '@chakra-ui/react';
|
||||
import {
|
||||
FallbackProps,
|
||||
ErrorBoundary as ReactErrorBoundary,
|
||||
@ -17,8 +12,15 @@ const ErrorFallback = ({ error }: FallbackProps) => {
|
||||
<Alert.Root status="error" borderRadius="md">
|
||||
<Alert.Indicator height="75px" width="75px" />
|
||||
<Box flex="1">
|
||||
<AlertTitle fontWeight="bold" fontSize="35px">An unexpected error has occurred.</AlertTitle>
|
||||
<AlertDescription padding="5" marginTop="3" fontSize="20px" lineHeight="1.4">
|
||||
<AlertTitle fontWeight="bold" fontSize="35px">
|
||||
An unexpected error has occurred.
|
||||
</AlertTitle>
|
||||
<AlertDescription
|
||||
padding="5"
|
||||
marginTop="3"
|
||||
fontSize="20px"
|
||||
lineHeight="1.4"
|
||||
>
|
||||
<br />
|
||||
{error.message}
|
||||
</AlertDescription>
|
||||
@ -28,6 +30,6 @@ const ErrorFallback = ({ error }: FallbackProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const ErrorBoundary: FC<React.PropsWithChildren<unknown>> = (props) => {
|
||||
export const ErrorBoundary = ({ children }: { children: ReactNode }) => {
|
||||
return <ReactErrorBoundary FallbackComponent={ErrorFallback} {...props} />;
|
||||
};
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { StrictMode } from 'react';
|
||||
|
||||
import { ChakraProvider } from '@chakra-ui/react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
|
||||
import App from '@/App';
|
||||
import { ColorModeProvider } from './components/ui/color-mode';
|
||||
|
||||
import { ChakraProvider } from '@chakra-ui/react';
|
||||
import { systemTheme } from './theme/theme';
|
||||
import { ColorModeProvider } from './components/ui/color-mode';
|
||||
import { Toaster } from './components/ui/toaster';
|
||||
import { systemTheme } from './theme/theme';
|
||||
|
||||
// Render the app
|
||||
const rootElement = document.getElementById('root');
|
||||
@ -15,12 +15,12 @@ if (rootElement && !rootElement.innerHTML) {
|
||||
const root = ReactDOM.createRoot(rootElement);
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<ColorModeProvider>
|
||||
<ChakraProvider value={systemTheme}>
|
||||
<App />
|
||||
<Toaster />
|
||||
</ChakraProvider>
|
||||
</ColorModeProvider>
|
||||
<ColorModeProvider>
|
||||
<ChakraProvider value={systemTheme}>
|
||||
<App />
|
||||
<Toaster />
|
||||
</ChakraProvider>
|
||||
</ColorModeProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
}
|
||||
|
@ -9,11 +9,12 @@ import { Error404 } from '@/errors';
|
||||
import { HelpPage } from '@/scene/home/HelpPage';
|
||||
import { HomePage } from '@/scene/home/HomePage';
|
||||
import { useHasRight } from '@/service/session';
|
||||
import { SettingsPage } from './home/SettingsPage';
|
||||
|
||||
import { ManageAccountPage } from './account/ManageAccountPage';
|
||||
import { SignInDonePage } from './connection/SignInDonePage';
|
||||
import { SignInPage } from './connection/SignInPage';
|
||||
import { SignOutPage } from './connection/SignOutPage';
|
||||
import { SignInDonePage } from './connection/SignInDonePage';
|
||||
import { ManageAccountPage } from './account/ManageAccountPage';
|
||||
import { SettingsPage } from './home/SettingsPage';
|
||||
|
||||
export const AppRoutes = () => {
|
||||
const { isReadable } = useHasRight('USER');
|
||||
@ -28,8 +29,14 @@ export const AppRoutes = () => {
|
||||
<>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
{/* Connection page after SSO */}
|
||||
<Route path="signin/:applicationName/:applicationData/*" element={<SignInDonePage />} />
|
||||
<Route path="signin/:applicationName/*" element={<SignInDonePage />} />
|
||||
<Route
|
||||
path="signin/:applicationName/:applicationData/*"
|
||||
element={<SignInDonePage />}
|
||||
/>
|
||||
<Route
|
||||
path="signin/:applicationName/*"
|
||||
element={<SignInDonePage />}
|
||||
/>
|
||||
<Route path="signout/*" element={<SignOutPage />} />
|
||||
<Route path="manage-account/*" element={<ManageAccountPage />} />
|
||||
<Route path="help" element={<HelpPage />} />
|
||||
@ -39,7 +46,7 @@ export const AppRoutes = () => {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Route path="*" element={<SignInPage />} />
|
||||
<Route path="*" element={<SignInPage />} />
|
||||
</>
|
||||
)}
|
||||
</Routes>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useEffect} from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useSessionService } from '@/service/session';
|
||||
|
||||
export const SignOutPage = () => {
|
||||
|
@ -1,60 +1,60 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { UserResource } from '@/back-api';
|
||||
import { toaster, toasterAPIError } from '@/components/ui/toaster';
|
||||
import { useSessionService } from '@/service/session';
|
||||
//import { useSessionContext } from '@/context/SessionContext';
|
||||
import { getRestConfig } from '@/utils/http';
|
||||
import { sha512 } from '@/utils/sha512';
|
||||
import { toaster, toasterAPIError } from '@/components/ui/toaster';
|
||||
import { useSessionService } from '@/service/session';
|
||||
import { UserResource } from '@/back-api';
|
||||
|
||||
export const useLogin = () => {
|
||||
const [isConnectionLoading, setIsConnectionLoading] =
|
||||
useState<boolean>(false);
|
||||
const [lastError, setLastError] = useState<string>('');
|
||||
const { setToken, clearToken } = useSessionService();
|
||||
const [isConnectionLoading, setIsConnectionLoading] =
|
||||
useState<boolean>(false);
|
||||
const [lastError, setLastError] = useState<string>('');
|
||||
const { setToken, clearToken } = useSessionService();
|
||||
|
||||
/**
|
||||
* Log-in with a clear password
|
||||
* @param login The user's login identifier (username or email address)
|
||||
* @param password The user's plain-text password
|
||||
* @returns promise on connection
|
||||
*/
|
||||
const connect = (login: string, password: string) => {
|
||||
console.log(`call connect`);
|
||||
clearToken();
|
||||
setIsConnectionLoading(true);
|
||||
setLastError('');
|
||||
const currentDate: string = new Date().toISOString();
|
||||
const data = {
|
||||
login,
|
||||
method: 'v1',
|
||||
time: currentDate,
|
||||
// we mix the password to be sure that it can not be used an other time ...
|
||||
password: sha512(
|
||||
`login='${login}';pass='${sha512(password)}';date='${currentDate}'`
|
||||
),
|
||||
};
|
||||
console.log(`call backend : ${JSON.stringify(data, null, 2)}`);
|
||||
UserResource.getToken({
|
||||
restConfig: getRestConfig(),
|
||||
data,
|
||||
})
|
||||
.then((response) => {
|
||||
setToken(response.jwt);
|
||||
toaster.create({
|
||||
title: 'Connection done',
|
||||
description: `Welcome, ${login}!`,
|
||||
});
|
||||
setIsConnectionLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
toaster.create({
|
||||
title: 'Connection fail',
|
||||
description: `Fail to connect with identification: '${login}'`,
|
||||
});
|
||||
setLastError('The connection Fail');
|
||||
setIsConnectionLoading(false);
|
||||
});
|
||||
/**
|
||||
* Log-in with a clear password
|
||||
* @param login The user's login identifier (username or email address)
|
||||
* @param password The user's plain-text password
|
||||
* @returns promise on connection
|
||||
*/
|
||||
const connect = (login: string, password: string) => {
|
||||
console.log(`call connect`);
|
||||
clearToken();
|
||||
setIsConnectionLoading(true);
|
||||
setLastError('');
|
||||
const currentDate: string = new Date().toISOString();
|
||||
const data = {
|
||||
login,
|
||||
method: 'v1',
|
||||
time: currentDate,
|
||||
// we mix the password to be sure that it can not be used an other time ...
|
||||
password: sha512(
|
||||
`login='${login}';pass='${sha512(password)}';date='${currentDate}'`
|
||||
),
|
||||
};
|
||||
return { connect, lastError, isConnectionLoading };
|
||||
console.log(`call backend : ${JSON.stringify(data, null, 2)}`);
|
||||
UserResource.getToken({
|
||||
restConfig: getRestConfig(),
|
||||
data,
|
||||
})
|
||||
.then((response) => {
|
||||
setToken(response.jwt);
|
||||
toaster.create({
|
||||
title: 'Connection done',
|
||||
description: `Welcome, ${login}!`,
|
||||
});
|
||||
setIsConnectionLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
toaster.create({
|
||||
title: 'Connection fail',
|
||||
description: `Fail to connect with identification: '${login}'`,
|
||||
});
|
||||
setLastError('The connection Fail');
|
||||
setIsConnectionLoading(false);
|
||||
});
|
||||
};
|
||||
return { connect, lastError, isConnectionLoading };
|
||||
};
|
@ -5,9 +5,7 @@ export const HelpPage = () => {
|
||||
return (
|
||||
<>
|
||||
<TopBar title="Help" />
|
||||
<PageLayout>
|
||||
No help available right now
|
||||
</PageLayout>
|
||||
<PageLayout>No help available right now</PageLayout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,14 +1,11 @@
|
||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||
import { TopBar } from '@/components/TopBar/TopBar';
|
||||
|
||||
|
||||
export const SettingsPage = () => {
|
||||
return (
|
||||
<>
|
||||
<TopBar title="Help" />
|
||||
<PageLayout>
|
||||
No settings available right now
|
||||
</PageLayout>
|
||||
<PageLayout>No settings available right now</PageLayout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { ApplicationToken, ApplicationTokenResource, CreateTokenRequestWrite, Integer, Long, RestErrorResponse } from '@/back-api';
|
||||
import {
|
||||
ApplicationToken,
|
||||
ApplicationTokenResource,
|
||||
CreateTokenRequestWrite,
|
||||
Integer,
|
||||
Long,
|
||||
RestErrorResponse,
|
||||
} from '@/back-api';
|
||||
import { useSessionService } from '@/service/session';
|
||||
import { useQuery, useQueryCall, useQueryCallProps } from '@/utils/query';
|
||||
|
||||
|
||||
export namespace ApplicationTokenService {
|
||||
|
||||
|
||||
export const useApplicationTokens = (applicationId: Long) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
return useQuery({
|
||||
@ -13,7 +17,7 @@ export namespace ApplicationTokenService {
|
||||
return ApplicationTokenResource.gets({
|
||||
restConfig: getRestConfig(),
|
||||
params: {
|
||||
applicationId
|
||||
applicationId,
|
||||
},
|
||||
});
|
||||
},
|
||||
@ -22,10 +26,15 @@ export namespace ApplicationTokenService {
|
||||
|
||||
export const useApplicationTokenCreate = (
|
||||
applicationId: Long,
|
||||
config: { config?: Omit<useQueryCallProps<ApplicationToken, any>, 'queryFunction'> }
|
||||
config: {
|
||||
config?: Omit<useQueryCallProps<ApplicationToken, any>, 'queryFunction'>;
|
||||
}
|
||||
) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
const { call, ...rest } = useQueryCall<ApplicationToken, CreateTokenRequestWrite>({
|
||||
const { call, ...rest } = useQueryCall<
|
||||
ApplicationToken,
|
||||
CreateTokenRequestWrite
|
||||
>({
|
||||
queryFunction: (inputData) => {
|
||||
return ApplicationTokenResource.create({
|
||||
restConfig: getRestConfig(),
|
||||
@ -43,15 +52,18 @@ export namespace ApplicationTokenService {
|
||||
config: { config?: Omit<useQueryCallProps<void, any>, 'queryFunction'> }
|
||||
) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
const { call, ...rest } = useQueryCall<void, {
|
||||
tokenId: Integer,
|
||||
}>({
|
||||
const { call, ...rest } = useQueryCall<
|
||||
void,
|
||||
{
|
||||
tokenId: Integer;
|
||||
}
|
||||
>({
|
||||
queryFunction: (inputData) => {
|
||||
return ApplicationTokenResource.remove({
|
||||
restConfig: getRestConfig(),
|
||||
params: {
|
||||
applicationId,
|
||||
...inputData
|
||||
...inputData,
|
||||
},
|
||||
});
|
||||
},
|
||||
@ -59,5 +71,4 @@ export namespace ApplicationTokenService {
|
||||
});
|
||||
return { removeApplicationToken: call, ...rest };
|
||||
};
|
||||
|
||||
}
|
@ -11,13 +11,11 @@ export type ServiceContextType = {
|
||||
session: SessionServiceProps;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export const ServiceContext = createContext<ServiceContextType>({
|
||||
session: {
|
||||
isConnected: false,
|
||||
setToken: (_token: string) => { },
|
||||
clearToken: () => { },
|
||||
setToken: (_token: string) => {},
|
||||
clearToken: () => {},
|
||||
hasReadRight: (_part: RightGroup) => false,
|
||||
hasWriteRight: (_part: RightGroup) => false,
|
||||
getRestConfig: getRestConfig,
|
||||
|
@ -22,7 +22,7 @@ export function getRestConfig(): RESTConfig {
|
||||
|
||||
export type SessionServiceProps = {
|
||||
token?: string;
|
||||
isConnected: boolean,
|
||||
isConnected: boolean;
|
||||
setToken: (token: string) => void;
|
||||
clearToken: () => void;
|
||||
login?: string;
|
||||
@ -59,7 +59,6 @@ export const useSessionServiceWrapped = (): SessionServiceProps => {
|
||||
localStorage.setItem(TOKEN_KEY, token);
|
||||
}
|
||||
}
|
||||
|
||||
}, [localStorage, parseToken, token]);
|
||||
|
||||
const setTokenLocal = useCallback(
|
||||
@ -71,7 +70,7 @@ export const useSessionServiceWrapped = (): SessionServiceProps => {
|
||||
);
|
||||
|
||||
const clearToken = useCallback(() => {
|
||||
console.log("Clear Token");
|
||||
console.log('Clear Token');
|
||||
setToken(undefined);
|
||||
updateRight();
|
||||
}, [updateRight, setToken]);
|
||||
@ -85,7 +84,9 @@ export const useSessionServiceWrapped = (): SessionServiceProps => {
|
||||
if (right === undefined) {
|
||||
return false;
|
||||
}
|
||||
return [PartRight.READ, PartRight.READ_WRITE].includes(right?.[group] ?? 0);
|
||||
return [PartRight.READ, PartRight.READ_WRITE].includes(
|
||||
right?.[group] ?? 0
|
||||
);
|
||||
},
|
||||
[config]
|
||||
);
|
||||
@ -99,7 +100,9 @@ export const useSessionServiceWrapped = (): SessionServiceProps => {
|
||||
if (right === undefined) {
|
||||
return false;
|
||||
}
|
||||
return [PartRight.READ, PartRight.READ_WRITE].includes(right?.[group] ?? 0);
|
||||
return [PartRight.READ, PartRight.READ_WRITE].includes(
|
||||
right?.[group] ?? 0
|
||||
);
|
||||
},
|
||||
[config]
|
||||
);
|
||||
|
@ -3,45 +3,52 @@
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import {
|
||||
RESTConfig,
|
||||
UserAuthGet,
|
||||
UserCreateWrite,
|
||||
UserResource,
|
||||
} from '@/back-api';
|
||||
import { useQuery, useQueryCall, useQueryCallProps } from '@/utils/query';
|
||||
|
||||
import { RESTConfig, UserAuthGet, UserCreateWrite, UserResource } from "@/back-api";
|
||||
import { useQuery, useQueryCall, useQueryCallProps } from "@/utils/query";
|
||||
import { useSessionService } from "./session";
|
||||
import { useSessionService } from './session';
|
||||
|
||||
export namespace UserService {
|
||||
// export const useGetData = <RETURN_TYPE>(queryFunction: (config: RESTConfig) => Promise<RETURN_TYPE>) => {
|
||||
// const { getRestConfig } = useSessionService();
|
||||
// return useQuery({ queryFunction: () => queryFunction(getRestConfig()) });
|
||||
// };
|
||||
|
||||
// export const useGetData = <RETURN_TYPE>(queryFunction: (config: RESTConfig) => Promise<RETURN_TYPE>) => {
|
||||
// const { getRestConfig } = useSessionService();
|
||||
// return useQuery({ queryFunction: () => queryFunction(getRestConfig()) });
|
||||
// };
|
||||
// export const useGets2 = useGetData((restConfig) => {
|
||||
// return UserResource.gets({
|
||||
// restConfig
|
||||
// });
|
||||
// });
|
||||
|
||||
// export const useGets2 = useGetData((restConfig) => {
|
||||
// return UserResource.gets({
|
||||
// restConfig
|
||||
// });
|
||||
// });
|
||||
|
||||
export const useGets = () => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
return useQuery({
|
||||
queryFunction: () => {
|
||||
return UserResource.gets({
|
||||
restConfig: getRestConfig()
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
export const useCreate = ({ config }: { config?: Omit<useQueryCallProps<UserAuthGet, any>, 'queryFunction'> }) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
return useQueryCall<UserAuthGet, UserCreateWrite>({
|
||||
queryFunction: (data) => {
|
||||
return UserResource.create({
|
||||
restConfig: getRestConfig(),
|
||||
data: { ...data },
|
||||
});
|
||||
},
|
||||
...config
|
||||
});
|
||||
};
|
||||
export const useGets = () => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
return useQuery({
|
||||
queryFunction: () => {
|
||||
return UserResource.gets({
|
||||
restConfig: getRestConfig(),
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
export const useCreate = ({
|
||||
config,
|
||||
}: {
|
||||
config?: Omit<useQueryCallProps<UserAuthGet, any>, 'queryFunction'>;
|
||||
}) => {
|
||||
const { getRestConfig } = useSessionService();
|
||||
return useQueryCall<UserAuthGet, UserCreateWrite>({
|
||||
queryFunction: (data) => {
|
||||
return UserResource.create({
|
||||
restConfig: getRestConfig(),
|
||||
data: { ...data },
|
||||
});
|
||||
},
|
||||
...config,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
type PandaColorModel = {
|
||||
value: string;
|
||||
}
|
||||
};
|
||||
type ThemeModel = {
|
||||
50: PandaColorModel;
|
||||
100: PandaColorModel;
|
||||
|
@ -1,5 +1,11 @@
|
||||
import { createSystem, defaultConfig, mergeConfigs, SystemConfig } from "@chakra-ui/react"
|
||||
import { colors } from "./colors"
|
||||
import {
|
||||
SystemConfig,
|
||||
createSystem,
|
||||
defaultConfig,
|
||||
mergeConfigs,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { colors } from './colors';
|
||||
|
||||
const baseTheme: SystemConfig = {
|
||||
globalCss: {
|
||||
@ -8,25 +14,23 @@ const baseTheme: SystemConfig = {
|
||||
bg: { _light: 'back.50', _dark: 'back.700' },
|
||||
color: { _light: 'text.900', _dark: 'text.50' },
|
||||
fontFamily: 'Roboto, Helvetica, Arial, "sans-serif"',
|
||||
userSelect: 'none', /* Prevents text selection */
|
||||
userSelect: 'none' /* Prevents text selection */,
|
||||
},
|
||||
svg: {
|
||||
width: "32px",
|
||||
height: "32px",
|
||||
aspectRatio: "square",
|
||||
}
|
||||
width: '32px',
|
||||
height: '32px',
|
||||
aspectRatio: 'square',
|
||||
},
|
||||
},
|
||||
theme: {
|
||||
slotRecipes: {
|
||||
dialog: {
|
||||
slots: [
|
||||
"header"
|
||||
],
|
||||
slots: ['header'],
|
||||
base: {
|
||||
header: {
|
||||
fontWeight: "bold",
|
||||
fontSize: "2xl",
|
||||
color: { _dark: "brand.400", _light: "brand.500" }
|
||||
fontWeight: 'bold',
|
||||
fontSize: '2xl',
|
||||
color: { _dark: 'brand.400', _light: 'brand.500' },
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -36,21 +40,27 @@ const baseTheme: SystemConfig = {
|
||||
base: {
|
||||
borderRadius: 0,
|
||||
_hover: {
|
||||
boxShadow: { _light: "0 8px 20px #000000e6", _dark: "0 8px 20px #000000e6" }
|
||||
boxShadow: {
|
||||
_light: '0 8px 20px #000000e6',
|
||||
_dark: '0 8px 20px #000000e6',
|
||||
},
|
||||
},
|
||||
transitionDuration: "slower"
|
||||
}
|
||||
transitionDuration: 'slower',
|
||||
},
|
||||
},
|
||||
input: {
|
||||
base: {
|
||||
borderRadius: 0,
|
||||
_hover: {
|
||||
boxShadow: { _light: "0 2px 5px #000000e6", _dark: "0 2px 5px #000000e6" }
|
||||
boxShadow: {
|
||||
_light: '0 2px 5px #000000e6',
|
||||
_dark: '0 2px 5px #000000e6',
|
||||
},
|
||||
},
|
||||
//borderColor: { _light: "gray.800", _dark: "gray.50" },
|
||||
backgroundColor: { _light: "gray.200", _dark: "gray.700" },
|
||||
transitionDuration: "slower"
|
||||
}
|
||||
backgroundColor: { _light: 'gray.200', _dark: 'gray.700' },
|
||||
transitionDuration: 'slower',
|
||||
},
|
||||
},
|
||||
},
|
||||
tokens: {
|
||||
@ -62,23 +72,23 @@ const baseTheme: SystemConfig = {
|
||||
},
|
||||
semanticTokens: {
|
||||
colors: {
|
||||
"@danger": {
|
||||
solid: { value: "{colors.danger.500}" },
|
||||
contrast: { value: "{colors.danger.100}" },
|
||||
fg: { value: "{colors.danger.900}" },
|
||||
muted: { value: "{colors.danger.100}" },
|
||||
subtle: { value: "{colors.danger.200}" },
|
||||
emphasized: { value: "{colors.danger.300}" },
|
||||
focusRing: { value: "{colors.danger.500}" },
|
||||
'@danger': {
|
||||
solid: { value: '{colors.danger.500}' },
|
||||
contrast: { value: '{colors.danger.100}' },
|
||||
fg: { value: '{colors.danger.900}' },
|
||||
muted: { value: '{colors.danger.100}' },
|
||||
subtle: { value: '{colors.danger.200}' },
|
||||
emphasized: { value: '{colors.danger.300}' },
|
||||
focusRing: { value: '{colors.danger.500}' },
|
||||
},
|
||||
"brand": {
|
||||
solid: { value: "{colors.brand.500}" },
|
||||
contrast: { value: "{colors.brand.100}" },
|
||||
fg: { value: "{colors.brand.900}" },
|
||||
muted: { value: "{colors.brand.100}" },
|
||||
subtle: { value: "{colors.brand.200}" },
|
||||
emphasized: { value: "{colors.brand.300}" },
|
||||
focusRing: { value: "{colors.brand.500}" },
|
||||
brand: {
|
||||
solid: { value: '{colors.brand.500}' },
|
||||
contrast: { value: '{colors.brand.100}' },
|
||||
fg: { value: '{colors.brand.900}' },
|
||||
muted: { value: '{colors.brand.100}' },
|
||||
subtle: { value: '{colors.brand.200}' },
|
||||
emphasized: { value: '{colors.brand.300}' },
|
||||
focusRing: { value: '{colors.brand.500}' },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1,22 +1,19 @@
|
||||
|
||||
|
||||
export function arrayUnique(array: any[]) {
|
||||
var a = array.concat();
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
for (var j = i + 1; j < a.length; ++j) {
|
||||
if (a[i] === a[j])
|
||||
a.splice(j--, 1);
|
||||
}
|
||||
var a = array.concat();
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
for (var j = i + 1; j < a.length; ++j) {
|
||||
if (a[i] === a[j]) a.splice(j--, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
return a;
|
||||
}
|
||||
|
||||
export function shuffleArray<T>(array: T[]): T[] {
|
||||
const out = [...array];
|
||||
for (let i = out.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[out[i], out[j]] = [out[j], out[i]];
|
||||
}
|
||||
return out;
|
||||
const out = [...array];
|
||||
for (let i = out.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[out[i], out[j]] = [out[j], out[i]];
|
||||
}
|
||||
return out;
|
||||
}
|
@ -6,8 +6,8 @@
|
||||
import { DependencyList, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { RestErrorResponse } from '@/back-api';
|
||||
import { isNullOrUndefined } from '@/utils/validator';
|
||||
import { toasterAPIError } from '@/components/ui/toaster';
|
||||
import { isNullOrUndefined } from '@/utils/validator';
|
||||
|
||||
export type DataStoreType<TYPE> = {
|
||||
isLoading: boolean;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { JwtToken, RESTConfig } from '@/back-api';
|
||||
import { RESTConfig } from '@/back-api';
|
||||
import { getApiUrl } from '@/environment';
|
||||
import { getUserToken } from '@/service/session';
|
||||
|
||||
|
@ -1,83 +1,88 @@
|
||||
import { RestErrorResponse } from "@/back-api";
|
||||
import { toasterAPIError, toaster } from "@/components/ui/toaster";
|
||||
import { useSessionService } from "@/service/session";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { RestErrorResponse } from '@/back-api';
|
||||
import { toaster, toasterAPIError } from '@/components/ui/toaster';
|
||||
import { useSessionService } from '@/service/session';
|
||||
|
||||
export type useQueryProps<TYPE> = {
|
||||
queryFunction: () => Promise<TYPE>;
|
||||
onSuccess?: (data: TYPE) => Promise<TYPE>;
|
||||
onFail?: (error: RestErrorResponse) => void;
|
||||
}
|
||||
export const useQuery = <TYPE,>({
|
||||
queryFunction,
|
||||
onSuccess,
|
||||
onFail,
|
||||
queryFunction: () => Promise<TYPE>;
|
||||
onSuccess?: (data: TYPE) => Promise<TYPE>;
|
||||
onFail?: (error: RestErrorResponse) => void;
|
||||
};
|
||||
export const useQuery = <TYPE>({
|
||||
queryFunction,
|
||||
onSuccess,
|
||||
onFail,
|
||||
}: useQueryProps<TYPE>) => {
|
||||
const { clearToken } = useSessionService();
|
||||
const [data, setData] = useState<TYPE | undefined>(undefined);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<RestErrorResponse | undefined>(undefined);
|
||||
useEffect(() => {
|
||||
queryFunction().then((received) => {
|
||||
setData(received);
|
||||
setIsLoading(false);
|
||||
if (onSuccess) {
|
||||
onSuccess(received);
|
||||
}
|
||||
}).catch((error) => {
|
||||
setError(error);
|
||||
setIsLoading(false);
|
||||
if (onFail) {
|
||||
onFail(error);
|
||||
}
|
||||
toasterAPIError(error);
|
||||
if (error.status == 401) {
|
||||
// Authentication error ==> auto_disconnect
|
||||
clearToken();
|
||||
toaster.create({
|
||||
title: "Disconnected by server",
|
||||
description: "Token is no more available",
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [setError, setIsLoading, setData, toasterAPIError, clearToken, toaster])
|
||||
return { data, isLoading, error };
|
||||
}
|
||||
const { clearToken } = useSessionService();
|
||||
const [data, setData] = useState<TYPE | undefined>(undefined);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<RestErrorResponse | undefined>(undefined);
|
||||
useEffect(() => {
|
||||
queryFunction()
|
||||
.then((received) => {
|
||||
setData(received);
|
||||
setIsLoading(false);
|
||||
if (onSuccess) {
|
||||
onSuccess(received);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
setError(error);
|
||||
setIsLoading(false);
|
||||
if (onFail) {
|
||||
onFail(error);
|
||||
}
|
||||
toasterAPIError(error);
|
||||
if (error.status == 401) {
|
||||
// Authentication error ==> auto_disconnect
|
||||
clearToken();
|
||||
toaster.create({
|
||||
title: 'Disconnected by server',
|
||||
description: 'Token is no more available',
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [setError, setIsLoading, setData, toasterAPIError, clearToken, toaster]);
|
||||
return { data, isLoading, error };
|
||||
};
|
||||
export type useQueryCallProps<RETURN_TYPE, PARAMETER_TYPE> = {
|
||||
queryFunction: (params: PARAMETER_TYPE) => Promise<RETURN_TYPE>;
|
||||
onSuccess?: (data: RETURN_TYPE) => Promise<RETURN_TYPE>;
|
||||
onFail?: (error: RestErrorResponse) => void;
|
||||
}
|
||||
queryFunction: (params: PARAMETER_TYPE) => Promise<RETURN_TYPE>;
|
||||
onSuccess?: (data: RETURN_TYPE) => Promise<RETURN_TYPE>;
|
||||
onFail?: (error: RestErrorResponse) => void;
|
||||
};
|
||||
export const useQueryCall = <TYPE, PARAMETERS>({
|
||||
queryFunction,
|
||||
onSuccess,
|
||||
onFail,
|
||||
queryFunction,
|
||||
onSuccess,
|
||||
onFail,
|
||||
}: useQueryCallProps<TYPE, PARAMETERS>) => {
|
||||
const { clearToken } = useSessionService();
|
||||
const [isCalling, setIsCalling] = useState<boolean>(true);
|
||||
const [error, setError] = useState<RestErrorResponse | undefined>(undefined);
|
||||
const call = (params: PARAMETERS) => {
|
||||
queryFunction(params).then((received) => {
|
||||
setIsCalling(false);
|
||||
if (onSuccess) {
|
||||
onSuccess(received);
|
||||
}
|
||||
}).catch((error) => {
|
||||
setIsCalling(false);
|
||||
if (onFail) {
|
||||
onFail(error);
|
||||
}
|
||||
toasterAPIError(error);
|
||||
setError(error);
|
||||
if (error.status == 401) {
|
||||
// Authentication error ==> auto_disconnect
|
||||
clearToken();
|
||||
toaster.create({
|
||||
title: "Disconnected by server",
|
||||
description: "Token is no more available",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return { call, isCalling, error };
|
||||
}
|
||||
const { clearToken } = useSessionService();
|
||||
const [isCalling, setIsCalling] = useState<boolean>(true);
|
||||
const [error, setError] = useState<RestErrorResponse | undefined>(undefined);
|
||||
const call = (params: PARAMETERS) => {
|
||||
queryFunction(params)
|
||||
.then((received) => {
|
||||
setIsCalling(false);
|
||||
if (onSuccess) {
|
||||
onSuccess(received);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
setIsCalling(false);
|
||||
if (onFail) {
|
||||
onFail(error);
|
||||
}
|
||||
toasterAPIError(error);
|
||||
setError(error);
|
||||
if (error.status == 401) {
|
||||
// Authentication error ==> auto_disconnect
|
||||
clearToken();
|
||||
toaster.create({
|
||||
title: 'Disconnected by server',
|
||||
description: 'Token is no more available',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
return { call, isCalling, error };
|
||||
};
|
||||
|
@ -3,340 +3,368 @@
|
||||
*/
|
||||
|
||||
export function sha512(str) {
|
||||
function int64(msint_32, lsint_32) {
|
||||
this.highOrder = msint_32;
|
||||
this.lowOrder = lsint_32;
|
||||
}
|
||||
function int64(msint_32, lsint_32) {
|
||||
this.highOrder = msint_32;
|
||||
this.lowOrder = lsint_32;
|
||||
}
|
||||
|
||||
let H = [
|
||||
new int64(0x6a09e667, 0xf3bcc908),
|
||||
new int64(0xbb67ae85, 0x84caa73b),
|
||||
new int64(0x3c6ef372, 0xfe94f82b),
|
||||
new int64(0xa54ff53a, 0x5f1d36f1),
|
||||
new int64(0x510e527f, 0xade682d1),
|
||||
new int64(0x9b05688c, 0x2b3e6c1f),
|
||||
new int64(0x1f83d9ab, 0xfb41bd6b),
|
||||
new int64(0x5be0cd19, 0x137e2179),
|
||||
];
|
||||
let H = [
|
||||
new int64(0x6a09e667, 0xf3bcc908),
|
||||
new int64(0xbb67ae85, 0x84caa73b),
|
||||
new int64(0x3c6ef372, 0xfe94f82b),
|
||||
new int64(0xa54ff53a, 0x5f1d36f1),
|
||||
new int64(0x510e527f, 0xade682d1),
|
||||
new int64(0x9b05688c, 0x2b3e6c1f),
|
||||
new int64(0x1f83d9ab, 0xfb41bd6b),
|
||||
new int64(0x5be0cd19, 0x137e2179),
|
||||
];
|
||||
|
||||
let K = [
|
||||
new int64(0x428a2f98, 0xd728ae22),
|
||||
new int64(0x71374491, 0x23ef65cd),
|
||||
new int64(0xb5c0fbcf, 0xec4d3b2f),
|
||||
new int64(0xe9b5dba5, 0x8189dbbc),
|
||||
new int64(0x3956c25b, 0xf348b538),
|
||||
new int64(0x59f111f1, 0xb605d019),
|
||||
new int64(0x923f82a4, 0xaf194f9b),
|
||||
new int64(0xab1c5ed5, 0xda6d8118),
|
||||
new int64(0xd807aa98, 0xa3030242),
|
||||
new int64(0x12835b01, 0x45706fbe),
|
||||
new int64(0x243185be, 0x4ee4b28c),
|
||||
new int64(0x550c7dc3, 0xd5ffb4e2),
|
||||
new int64(0x72be5d74, 0xf27b896f),
|
||||
new int64(0x80deb1fe, 0x3b1696b1),
|
||||
new int64(0x9bdc06a7, 0x25c71235),
|
||||
new int64(0xc19bf174, 0xcf692694),
|
||||
new int64(0xe49b69c1, 0x9ef14ad2),
|
||||
new int64(0xefbe4786, 0x384f25e3),
|
||||
new int64(0x0fc19dc6, 0x8b8cd5b5),
|
||||
new int64(0x240ca1cc, 0x77ac9c65),
|
||||
new int64(0x2de92c6f, 0x592b0275),
|
||||
new int64(0x4a7484aa, 0x6ea6e483),
|
||||
new int64(0x5cb0a9dc, 0xbd41fbd4),
|
||||
new int64(0x76f988da, 0x831153b5),
|
||||
new int64(0x983e5152, 0xee66dfab),
|
||||
new int64(0xa831c66d, 0x2db43210),
|
||||
new int64(0xb00327c8, 0x98fb213f),
|
||||
new int64(0xbf597fc7, 0xbeef0ee4),
|
||||
new int64(0xc6e00bf3, 0x3da88fc2),
|
||||
new int64(0xd5a79147, 0x930aa725),
|
||||
new int64(0x06ca6351, 0xe003826f),
|
||||
new int64(0x14292967, 0x0a0e6e70),
|
||||
new int64(0x27b70a85, 0x46d22ffc),
|
||||
new int64(0x2e1b2138, 0x5c26c926),
|
||||
new int64(0x4d2c6dfc, 0x5ac42aed),
|
||||
new int64(0x53380d13, 0x9d95b3df),
|
||||
new int64(0x650a7354, 0x8baf63de),
|
||||
new int64(0x766a0abb, 0x3c77b2a8),
|
||||
new int64(0x81c2c92e, 0x47edaee6),
|
||||
new int64(0x92722c85, 0x1482353b),
|
||||
new int64(0xa2bfe8a1, 0x4cf10364),
|
||||
new int64(0xa81a664b, 0xbc423001),
|
||||
new int64(0xc24b8b70, 0xd0f89791),
|
||||
new int64(0xc76c51a3, 0x0654be30),
|
||||
new int64(0xd192e819, 0xd6ef5218),
|
||||
new int64(0xd6990624, 0x5565a910),
|
||||
new int64(0xf40e3585, 0x5771202a),
|
||||
new int64(0x106aa070, 0x32bbd1b8),
|
||||
new int64(0x19a4c116, 0xb8d2d0c8),
|
||||
new int64(0x1e376c08, 0x5141ab53),
|
||||
new int64(0x2748774c, 0xdf8eeb99),
|
||||
new int64(0x34b0bcb5, 0xe19b48a8),
|
||||
new int64(0x391c0cb3, 0xc5c95a63),
|
||||
new int64(0x4ed8aa4a, 0xe3418acb),
|
||||
new int64(0x5b9cca4f, 0x7763e373),
|
||||
new int64(0x682e6ff3, 0xd6b2b8a3),
|
||||
new int64(0x748f82ee, 0x5defb2fc),
|
||||
new int64(0x78a5636f, 0x43172f60),
|
||||
new int64(0x84c87814, 0xa1f0ab72),
|
||||
new int64(0x8cc70208, 0x1a6439ec),
|
||||
new int64(0x90befffa, 0x23631e28),
|
||||
new int64(0xa4506ceb, 0xde82bde9),
|
||||
new int64(0xbef9a3f7, 0xb2c67915),
|
||||
new int64(0xc67178f2, 0xe372532b),
|
||||
new int64(0xca273ece, 0xea26619c),
|
||||
new int64(0xd186b8c7, 0x21c0c207),
|
||||
new int64(0xeada7dd6, 0xcde0eb1e),
|
||||
new int64(0xf57d4f7f, 0xee6ed178),
|
||||
new int64(0x06f067aa, 0x72176fba),
|
||||
new int64(0x0a637dc5, 0xa2c898a6),
|
||||
new int64(0x113f9804, 0xbef90dae),
|
||||
new int64(0x1b710b35, 0x131c471b),
|
||||
new int64(0x28db77f5, 0x23047d84),
|
||||
new int64(0x32caab7b, 0x40c72493),
|
||||
new int64(0x3c9ebe0a, 0x15c9bebc),
|
||||
new int64(0x431d67c4, 0x9c100d4c),
|
||||
new int64(0x4cc5d4be, 0xcb3e42b6),
|
||||
new int64(0x597f299c, 0xfc657e2a),
|
||||
new int64(0x5fcb6fab, 0x3ad6faec),
|
||||
new int64(0x6c44198c, 0x4a475817),
|
||||
];
|
||||
let K = [
|
||||
new int64(0x428a2f98, 0xd728ae22),
|
||||
new int64(0x71374491, 0x23ef65cd),
|
||||
new int64(0xb5c0fbcf, 0xec4d3b2f),
|
||||
new int64(0xe9b5dba5, 0x8189dbbc),
|
||||
new int64(0x3956c25b, 0xf348b538),
|
||||
new int64(0x59f111f1, 0xb605d019),
|
||||
new int64(0x923f82a4, 0xaf194f9b),
|
||||
new int64(0xab1c5ed5, 0xda6d8118),
|
||||
new int64(0xd807aa98, 0xa3030242),
|
||||
new int64(0x12835b01, 0x45706fbe),
|
||||
new int64(0x243185be, 0x4ee4b28c),
|
||||
new int64(0x550c7dc3, 0xd5ffb4e2),
|
||||
new int64(0x72be5d74, 0xf27b896f),
|
||||
new int64(0x80deb1fe, 0x3b1696b1),
|
||||
new int64(0x9bdc06a7, 0x25c71235),
|
||||
new int64(0xc19bf174, 0xcf692694),
|
||||
new int64(0xe49b69c1, 0x9ef14ad2),
|
||||
new int64(0xefbe4786, 0x384f25e3),
|
||||
new int64(0x0fc19dc6, 0x8b8cd5b5),
|
||||
new int64(0x240ca1cc, 0x77ac9c65),
|
||||
new int64(0x2de92c6f, 0x592b0275),
|
||||
new int64(0x4a7484aa, 0x6ea6e483),
|
||||
new int64(0x5cb0a9dc, 0xbd41fbd4),
|
||||
new int64(0x76f988da, 0x831153b5),
|
||||
new int64(0x983e5152, 0xee66dfab),
|
||||
new int64(0xa831c66d, 0x2db43210),
|
||||
new int64(0xb00327c8, 0x98fb213f),
|
||||
new int64(0xbf597fc7, 0xbeef0ee4),
|
||||
new int64(0xc6e00bf3, 0x3da88fc2),
|
||||
new int64(0xd5a79147, 0x930aa725),
|
||||
new int64(0x06ca6351, 0xe003826f),
|
||||
new int64(0x14292967, 0x0a0e6e70),
|
||||
new int64(0x27b70a85, 0x46d22ffc),
|
||||
new int64(0x2e1b2138, 0x5c26c926),
|
||||
new int64(0x4d2c6dfc, 0x5ac42aed),
|
||||
new int64(0x53380d13, 0x9d95b3df),
|
||||
new int64(0x650a7354, 0x8baf63de),
|
||||
new int64(0x766a0abb, 0x3c77b2a8),
|
||||
new int64(0x81c2c92e, 0x47edaee6),
|
||||
new int64(0x92722c85, 0x1482353b),
|
||||
new int64(0xa2bfe8a1, 0x4cf10364),
|
||||
new int64(0xa81a664b, 0xbc423001),
|
||||
new int64(0xc24b8b70, 0xd0f89791),
|
||||
new int64(0xc76c51a3, 0x0654be30),
|
||||
new int64(0xd192e819, 0xd6ef5218),
|
||||
new int64(0xd6990624, 0x5565a910),
|
||||
new int64(0xf40e3585, 0x5771202a),
|
||||
new int64(0x106aa070, 0x32bbd1b8),
|
||||
new int64(0x19a4c116, 0xb8d2d0c8),
|
||||
new int64(0x1e376c08, 0x5141ab53),
|
||||
new int64(0x2748774c, 0xdf8eeb99),
|
||||
new int64(0x34b0bcb5, 0xe19b48a8),
|
||||
new int64(0x391c0cb3, 0xc5c95a63),
|
||||
new int64(0x4ed8aa4a, 0xe3418acb),
|
||||
new int64(0x5b9cca4f, 0x7763e373),
|
||||
new int64(0x682e6ff3, 0xd6b2b8a3),
|
||||
new int64(0x748f82ee, 0x5defb2fc),
|
||||
new int64(0x78a5636f, 0x43172f60),
|
||||
new int64(0x84c87814, 0xa1f0ab72),
|
||||
new int64(0x8cc70208, 0x1a6439ec),
|
||||
new int64(0x90befffa, 0x23631e28),
|
||||
new int64(0xa4506ceb, 0xde82bde9),
|
||||
new int64(0xbef9a3f7, 0xb2c67915),
|
||||
new int64(0xc67178f2, 0xe372532b),
|
||||
new int64(0xca273ece, 0xea26619c),
|
||||
new int64(0xd186b8c7, 0x21c0c207),
|
||||
new int64(0xeada7dd6, 0xcde0eb1e),
|
||||
new int64(0xf57d4f7f, 0xee6ed178),
|
||||
new int64(0x06f067aa, 0x72176fba),
|
||||
new int64(0x0a637dc5, 0xa2c898a6),
|
||||
new int64(0x113f9804, 0xbef90dae),
|
||||
new int64(0x1b710b35, 0x131c471b),
|
||||
new int64(0x28db77f5, 0x23047d84),
|
||||
new int64(0x32caab7b, 0x40c72493),
|
||||
new int64(0x3c9ebe0a, 0x15c9bebc),
|
||||
new int64(0x431d67c4, 0x9c100d4c),
|
||||
new int64(0x4cc5d4be, 0xcb3e42b6),
|
||||
new int64(0x597f299c, 0xfc657e2a),
|
||||
new int64(0x5fcb6fab, 0x3ad6faec),
|
||||
new int64(0x6c44198c, 0x4a475817),
|
||||
];
|
||||
|
||||
let W = new Array(64);
|
||||
let a, b, c, d, e, f, g, h, i, j;
|
||||
let T1, T2;
|
||||
let charsize = 8;
|
||||
let W = new Array(64);
|
||||
let a, b, c, d, e, f, g, h, i, j;
|
||||
let T1, T2;
|
||||
let charsize = 8;
|
||||
|
||||
function utf8_encode(data: any) {
|
||||
return unescape(encodeURIComponent(data));
|
||||
}
|
||||
function utf8_encode(data: any) {
|
||||
return unescape(encodeURIComponent(data));
|
||||
}
|
||||
|
||||
function str2binb(data: any) {
|
||||
let bin: any[] = [];
|
||||
let mask = (1 << charsize) - 1;
|
||||
let len = data.length * charsize;
|
||||
function str2binb(data: any) {
|
||||
let bin: any[] = [];
|
||||
let mask = (1 << charsize) - 1;
|
||||
let len = data.length * charsize;
|
||||
|
||||
for (let i = 0; i < len; i += charsize) {
|
||||
bin[i >> 5] |= (data.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32));
|
||||
}
|
||||
for (let i = 0; i < len; i += charsize) {
|
||||
bin[i >> 5] |=
|
||||
(data.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32));
|
||||
}
|
||||
|
||||
return bin;
|
||||
}
|
||||
return bin;
|
||||
}
|
||||
|
||||
function binb2hex(binarray: any) {
|
||||
let hex_tab = '0123456789abcdef';
|
||||
let data = '';
|
||||
let length = binarray.length * 4;
|
||||
let srcByte;
|
||||
function binb2hex(binarray: any) {
|
||||
let hex_tab = '0123456789abcdef';
|
||||
let data = '';
|
||||
let length = binarray.length * 4;
|
||||
let srcByte;
|
||||
|
||||
for (let i = 0; i < length; i += 1) {
|
||||
srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
|
||||
data += hex_tab.charAt((srcByte >> 4) & 0xf) + hex_tab.charAt(srcByte & 0xf);
|
||||
}
|
||||
for (let i = 0; i < length; i += 1) {
|
||||
srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
|
||||
data +=
|
||||
hex_tab.charAt((srcByte >> 4) & 0xf) + hex_tab.charAt(srcByte & 0xf);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function safe_add_2(x: any, y: any) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
function safe_add_2(x: any, y: any) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
|
||||
lsw = (x.lowOrder & 0xffff) + (y.lowOrder & 0xffff);
|
||||
msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
lsw = (x.lowOrder & 0xffff) + (y.lowOrder & 0xffff);
|
||||
msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
lsw = (x.highOrder & 0xffff) + (y.highOrder & 0xffff) + (msw >>> 16);
|
||||
msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
lsw = (x.highOrder & 0xffff) + (y.highOrder & 0xffff) + (msw >>> 16);
|
||||
msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
|
||||
function safe_add_4(a, b, c, d) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
function safe_add_4(a, b, c, d) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
|
||||
lsw = (a.lowOrder & 0xffff) + (b.lowOrder & 0xffff) + (c.lowOrder & 0xffff) + (d.lowOrder & 0xffff);
|
||||
msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
lsw =
|
||||
(a.lowOrder & 0xffff) +
|
||||
(b.lowOrder & 0xffff) +
|
||||
(c.lowOrder & 0xffff) +
|
||||
(d.lowOrder & 0xffff);
|
||||
msw =
|
||||
(a.lowOrder >>> 16) +
|
||||
(b.lowOrder >>> 16) +
|
||||
(c.lowOrder >>> 16) +
|
||||
(d.lowOrder >>> 16) +
|
||||
(lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
lsw =
|
||||
(a.highOrder & 0xffff) +
|
||||
(b.highOrder & 0xffff) +
|
||||
(c.highOrder & 0xffff) +
|
||||
(d.highOrder & 0xffff) +
|
||||
(msw >>> 16);
|
||||
msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
lsw =
|
||||
(a.highOrder & 0xffff) +
|
||||
(b.highOrder & 0xffff) +
|
||||
(c.highOrder & 0xffff) +
|
||||
(d.highOrder & 0xffff) +
|
||||
(msw >>> 16);
|
||||
msw =
|
||||
(a.highOrder >>> 16) +
|
||||
(b.highOrder >>> 16) +
|
||||
(c.highOrder >>> 16) +
|
||||
(d.highOrder >>> 16) +
|
||||
(lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
|
||||
function safe_add_5(a, b, c, d, e) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
function safe_add_5(a, b, c, d, e) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
|
||||
lsw =
|
||||
(a.lowOrder & 0xffff) +
|
||||
(b.lowOrder & 0xffff) +
|
||||
(c.lowOrder & 0xffff) +
|
||||
(d.lowOrder & 0xffff) +
|
||||
(e.lowOrder & 0xffff);
|
||||
msw =
|
||||
(a.lowOrder >>> 16) +
|
||||
(b.lowOrder >>> 16) +
|
||||
(c.lowOrder >>> 16) +
|
||||
(d.lowOrder >>> 16) +
|
||||
(e.lowOrder >>> 16) +
|
||||
(lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
lsw =
|
||||
(a.lowOrder & 0xffff) +
|
||||
(b.lowOrder & 0xffff) +
|
||||
(c.lowOrder & 0xffff) +
|
||||
(d.lowOrder & 0xffff) +
|
||||
(e.lowOrder & 0xffff);
|
||||
msw =
|
||||
(a.lowOrder >>> 16) +
|
||||
(b.lowOrder >>> 16) +
|
||||
(c.lowOrder >>> 16) +
|
||||
(d.lowOrder >>> 16) +
|
||||
(e.lowOrder >>> 16) +
|
||||
(lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
lsw =
|
||||
(a.highOrder & 0xffff) +
|
||||
(b.highOrder & 0xffff) +
|
||||
(c.highOrder & 0xffff) +
|
||||
(d.highOrder & 0xffff) +
|
||||
(e.highOrder & 0xffff) +
|
||||
(msw >>> 16);
|
||||
msw =
|
||||
(a.highOrder >>> 16) +
|
||||
(b.highOrder >>> 16) +
|
||||
(c.highOrder >>> 16) +
|
||||
(d.highOrder >>> 16) +
|
||||
(e.highOrder >>> 16) +
|
||||
(lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
lsw =
|
||||
(a.highOrder & 0xffff) +
|
||||
(b.highOrder & 0xffff) +
|
||||
(c.highOrder & 0xffff) +
|
||||
(d.highOrder & 0xffff) +
|
||||
(e.highOrder & 0xffff) +
|
||||
(msw >>> 16);
|
||||
msw =
|
||||
(a.highOrder >>> 16) +
|
||||
(b.highOrder >>> 16) +
|
||||
(c.highOrder >>> 16) +
|
||||
(d.highOrder >>> 16) +
|
||||
(e.highOrder >>> 16) +
|
||||
(lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
|
||||
function maj(x, y, z) {
|
||||
return new int64(
|
||||
(x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder),
|
||||
(x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder)
|
||||
);
|
||||
}
|
||||
function maj(x, y, z) {
|
||||
return new int64(
|
||||
(x.highOrder & y.highOrder) ^
|
||||
(x.highOrder & z.highOrder) ^
|
||||
(y.highOrder & z.highOrder),
|
||||
(x.lowOrder & y.lowOrder) ^
|
||||
(x.lowOrder & z.lowOrder) ^
|
||||
(y.lowOrder & z.lowOrder)
|
||||
);
|
||||
}
|
||||
|
||||
function ch(x, y, z) {
|
||||
return new int64(
|
||||
(x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
|
||||
(x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
|
||||
);
|
||||
}
|
||||
function ch(x, y, z) {
|
||||
return new int64(
|
||||
(x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
|
||||
(x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
|
||||
);
|
||||
}
|
||||
|
||||
function rotr(x, n) {
|
||||
if (n <= 32) {
|
||||
return new int64(
|
||||
(x.highOrder >>> n) | (x.lowOrder << (32 - n)),
|
||||
(x.lowOrder >>> n) | (x.highOrder << (32 - n))
|
||||
);
|
||||
} else {
|
||||
return new int64(
|
||||
(x.lowOrder >>> n) | (x.highOrder << (32 - n)),
|
||||
(x.highOrder >>> n) | (x.lowOrder << (32 - n))
|
||||
);
|
||||
}
|
||||
}
|
||||
function rotr(x, n) {
|
||||
if (n <= 32) {
|
||||
return new int64(
|
||||
(x.highOrder >>> n) | (x.lowOrder << (32 - n)),
|
||||
(x.lowOrder >>> n) | (x.highOrder << (32 - n))
|
||||
);
|
||||
} else {
|
||||
return new int64(
|
||||
(x.lowOrder >>> n) | (x.highOrder << (32 - n)),
|
||||
(x.highOrder >>> n) | (x.lowOrder << (32 - n))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function sigma0(x) {
|
||||
let rotr28 = rotr(x, 28);
|
||||
let rotr34 = rotr(x, 34);
|
||||
let rotr39 = rotr(x, 39);
|
||||
function sigma0(x) {
|
||||
let rotr28 = rotr(x, 28);
|
||||
let rotr34 = rotr(x, 34);
|
||||
let rotr39 = rotr(x, 39);
|
||||
|
||||
return new int64(
|
||||
rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
|
||||
rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder
|
||||
);
|
||||
}
|
||||
return new int64(
|
||||
rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
|
||||
rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder
|
||||
);
|
||||
}
|
||||
|
||||
function sigma1(x) {
|
||||
let rotr14 = rotr(x, 14);
|
||||
let rotr18 = rotr(x, 18);
|
||||
let rotr41 = rotr(x, 41);
|
||||
function sigma1(x) {
|
||||
let rotr14 = rotr(x, 14);
|
||||
let rotr18 = rotr(x, 18);
|
||||
let rotr41 = rotr(x, 41);
|
||||
|
||||
return new int64(
|
||||
rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
|
||||
rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder
|
||||
);
|
||||
}
|
||||
return new int64(
|
||||
rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
|
||||
rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder
|
||||
);
|
||||
}
|
||||
|
||||
function gamma0(x) {
|
||||
let rotr1 = rotr(x, 1),
|
||||
rotr8 = rotr(x, 8),
|
||||
shr7 = shr(x, 7);
|
||||
function gamma0(x) {
|
||||
let rotr1 = rotr(x, 1),
|
||||
rotr8 = rotr(x, 8),
|
||||
shr7 = shr(x, 7);
|
||||
|
||||
return new int64(
|
||||
rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
|
||||
rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
|
||||
);
|
||||
}
|
||||
return new int64(
|
||||
rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
|
||||
rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
|
||||
);
|
||||
}
|
||||
|
||||
function gamma1(x) {
|
||||
let rotr19 = rotr(x, 19);
|
||||
let rotr61 = rotr(x, 61);
|
||||
let shr6 = shr(x, 6);
|
||||
function gamma1(x) {
|
||||
let rotr19 = rotr(x, 19);
|
||||
let rotr61 = rotr(x, 61);
|
||||
let shr6 = shr(x, 6);
|
||||
|
||||
return new int64(
|
||||
rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
|
||||
rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
|
||||
);
|
||||
}
|
||||
return new int64(
|
||||
rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
|
||||
rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
|
||||
);
|
||||
}
|
||||
|
||||
function shr(x, n) {
|
||||
if (n <= 32) {
|
||||
return new int64(x.highOrder >>> n, (x.lowOrder >>> n) | (x.highOrder << (32 - n)));
|
||||
} else {
|
||||
return new int64(0, x.highOrder << (32 - n));
|
||||
}
|
||||
}
|
||||
function shr(x, n) {
|
||||
if (n <= 32) {
|
||||
return new int64(
|
||||
x.highOrder >>> n,
|
||||
(x.lowOrder >>> n) | (x.highOrder << (32 - n))
|
||||
);
|
||||
} else {
|
||||
return new int64(0, x.highOrder << (32 - n));
|
||||
}
|
||||
}
|
||||
|
||||
str = utf8_encode(str);
|
||||
let strlen = str.length * charsize;
|
||||
str = str2binb(str);
|
||||
str = utf8_encode(str);
|
||||
let strlen = str.length * charsize;
|
||||
str = str2binb(str);
|
||||
|
||||
str[strlen >> 5] |= 0x80 << (24 - (strlen % 32));
|
||||
str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
|
||||
str[strlen >> 5] |= 0x80 << (24 - (strlen % 32));
|
||||
str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
|
||||
|
||||
for (let i = 0; i < str.length; i += 32) {
|
||||
a = H[0];
|
||||
b = H[1];
|
||||
c = H[2];
|
||||
d = H[3];
|
||||
e = H[4];
|
||||
f = H[5];
|
||||
g = H[6];
|
||||
h = H[7];
|
||||
for (let i = 0; i < str.length; i += 32) {
|
||||
a = H[0];
|
||||
b = H[1];
|
||||
c = H[2];
|
||||
d = H[3];
|
||||
e = H[4];
|
||||
f = H[5];
|
||||
g = H[6];
|
||||
h = H[7];
|
||||
|
||||
for (let j = 0; j < 80; j++) {
|
||||
if (j < 16) {
|
||||
W[j] = new int64(str[j * 2 + i], str[j * 2 + i + 1]);
|
||||
} else {
|
||||
W[j] = safe_add_4(gamma1(W[j - 2]), W[j - 7], gamma0(W[j - 15]), W[j - 16]);
|
||||
}
|
||||
for (let j = 0; j < 80; j++) {
|
||||
if (j < 16) {
|
||||
W[j] = new int64(str[j * 2 + i], str[j * 2 + i + 1]);
|
||||
} else {
|
||||
W[j] = safe_add_4(
|
||||
gamma1(W[j - 2]),
|
||||
W[j - 7],
|
||||
gamma0(W[j - 15]),
|
||||
W[j - 16]
|
||||
);
|
||||
}
|
||||
|
||||
T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]);
|
||||
T2 = safe_add_2(sigma0(a), maj(a, b, c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = safe_add_2(d, T1);
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = safe_add_2(T1, T2);
|
||||
}
|
||||
T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]);
|
||||
T2 = safe_add_2(sigma0(a), maj(a, b, c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = safe_add_2(d, T1);
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = safe_add_2(T1, T2);
|
||||
}
|
||||
|
||||
H[0] = safe_add_2(a, H[0]);
|
||||
H[1] = safe_add_2(b, H[1]);
|
||||
H[2] = safe_add_2(c, H[2]);
|
||||
H[3] = safe_add_2(d, H[3]);
|
||||
H[4] = safe_add_2(e, H[4]);
|
||||
H[5] = safe_add_2(f, H[5]);
|
||||
H[6] = safe_add_2(g, H[6]);
|
||||
H[7] = safe_add_2(h, H[7]);
|
||||
}
|
||||
H[0] = safe_add_2(a, H[0]);
|
||||
H[1] = safe_add_2(b, H[1]);
|
||||
H[2] = safe_add_2(c, H[2]);
|
||||
H[3] = safe_add_2(d, H[3]);
|
||||
H[4] = safe_add_2(e, H[4]);
|
||||
H[5] = safe_add_2(f, H[5]);
|
||||
H[6] = safe_add_2(g, H[6]);
|
||||
H[7] = safe_add_2(h, H[7]);
|
||||
}
|
||||
|
||||
const binarray: any = [];
|
||||
for (let i = 0; i < H.length; i++) {
|
||||
binarray.push(H[i].highOrder);
|
||||
binarray.push(H[i].lowOrder);
|
||||
}
|
||||
return binb2hex(binarray);
|
||||
const binarray: any = [];
|
||||
for (let i = 0; i < H.length; i++) {
|
||||
binarray.push(H[i].highOrder);
|
||||
binarray.push(H[i].lowOrder);
|
||||
}
|
||||
return binb2hex(binarray);
|
||||
}
|
||||
|
@ -1,98 +1,97 @@
|
||||
|
||||
export function isNumeric(val: string): boolean {
|
||||
return !isNaN(Number(val));
|
||||
return !isNaN(Number(val));
|
||||
}
|
||||
|
||||
export function isNumber(data: any): data is number {
|
||||
return typeof data === 'number';
|
||||
return typeof data === 'number';
|
||||
}
|
||||
export function isNumberFinite(data: any): data is number {
|
||||
return isNumber(data) && isFinite(data);
|
||||
return isNumber(data) && isFinite(data);
|
||||
}
|
||||
export function isBoolean(data: any): data is boolean {
|
||||
return typeof data === 'boolean';
|
||||
return typeof data === 'boolean';
|
||||
}
|
||||
export function isString(data: any): data is string {
|
||||
return typeof data === 'string';
|
||||
return typeof data === 'string';
|
||||
}
|
||||
export function isArray(data: any): data is any[] {
|
||||
return Array.isArray(data);
|
||||
return Array.isArray(data);
|
||||
}
|
||||
export function isNull(data: any): data is null {
|
||||
return data === null;
|
||||
return data === null;
|
||||
}
|
||||
export function isUndefined(data: any): data is undefined {
|
||||
return data === undefined;
|
||||
return data === undefined;
|
||||
}
|
||||
export function isNullOrUndefined(data: any): data is undefined | null {
|
||||
return data === undefined || data === null;
|
||||
return data === undefined || data === null;
|
||||
}
|
||||
export function isStringNullOrUndefined(data: any): data is undefined | null {
|
||||
return data === 'undefined' || data === 'null' || data === '';
|
||||
return data === 'undefined' || data === 'null' || data === '';
|
||||
}
|
||||
export function isObject(data: any): data is any {
|
||||
return !isNullOrUndefined(data) && typeof data === 'object' && !isArray(data);
|
||||
return !isNullOrUndefined(data) && typeof data === 'object' && !isArray(data);
|
||||
}
|
||||
export function isInArray(data: any, listElement: any[]): boolean {
|
||||
for (let iii = 0; iii < listElement.length; iii++) {
|
||||
if (listElement[iii] === data) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
for (let iii = 0; iii < listElement.length; iii++) {
|
||||
if (listElement[iii] === data) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isArrayOf<TYPE>(
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE,
|
||||
length?: number
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE,
|
||||
length?: number
|
||||
): data is TYPE[] {
|
||||
if (!isArray(data)) {
|
||||
return false;
|
||||
}
|
||||
if (!data.every(typeChecker)) {
|
||||
return false;
|
||||
}
|
||||
if (!isUndefined(length) && data.length != length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (!isArray(data)) {
|
||||
return false;
|
||||
}
|
||||
if (!data.every(typeChecker)) {
|
||||
return false;
|
||||
}
|
||||
if (!isUndefined(length) && data.length != length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
export function isArrayOfs<TYPE, TYPE2, TYPE3>(
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE,
|
||||
typeChecker2?: (subData: any) => subData is TYPE2,
|
||||
typeChecker3?: (subData: any) => subData is TYPE3
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE,
|
||||
typeChecker2?: (subData: any) => subData is TYPE2,
|
||||
typeChecker3?: (subData: any) => subData is TYPE3
|
||||
): data is (TYPE | TYPE2 | TYPE3)[] {
|
||||
if (!isArray(data)) {
|
||||
return false;
|
||||
}
|
||||
for (let iii = 0; iii < data.length; iii++) {
|
||||
let elem = data[iii];
|
||||
if (typeChecker(elem)) {
|
||||
continue;
|
||||
}
|
||||
if (typeChecker2 != undefined && typeChecker2(elem)) {
|
||||
continue;
|
||||
}
|
||||
if (typeChecker3 != undefined && typeChecker3(elem)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (!isArray(data)) {
|
||||
return false;
|
||||
}
|
||||
for (let iii = 0; iii < data.length; iii++) {
|
||||
let elem = data[iii];
|
||||
if (typeChecker(elem)) {
|
||||
continue;
|
||||
}
|
||||
if (typeChecker2 != undefined && typeChecker2(elem)) {
|
||||
continue;
|
||||
}
|
||||
if (typeChecker3 != undefined && typeChecker3(elem)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isOptionalOf<TYPE>(
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE
|
||||
): data is TYPE | undefined {
|
||||
return isUndefined(data) || typeChecker(data);
|
||||
return isUndefined(data) || typeChecker(data);
|
||||
}
|
||||
|
||||
export function isOptionalArrayOf<TYPE>(
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE
|
||||
): data is TYPE[] | undefined {
|
||||
return isUndefined(data) || isArrayOf(data, typeChecker);
|
||||
return isUndefined(data) || isArrayOf(data, typeChecker);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user