[DEV] correct models

This commit is contained in:
Edouard DUPIN 2025-02-10 19:40:27 +01:00
parent 44b4fa37d3
commit 332c65360d
73 changed files with 1431 additions and 1283 deletions

View File

@ -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"
}

View File

@ -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();

View File

@ -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/**',
],
};

View File

@ -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",

View File

@ -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>

View File

@ -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>
);
};

View File

@ -6,8 +6,8 @@ export const EmptyEnd = () => {
width="full"
height="25%"
minHeight="250px"
// borderWidth="1px"
// borderColor="red"
// borderWidth="1px"
// borderColor="red"
></Box>
);
};

View File

@ -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 = () => {
</>
);
};

View File

@ -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';

View File

@ -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;

View File

@ -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';

View File

@ -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>
}
);
};

View File

@ -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>
}
);
};

View File

@ -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>
}
);
};

View File

@ -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>
}
);
};

View File

@ -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>
}
);
};

View File

@ -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 = {

View File

@ -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>
);
};

View File

@ -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>
);
};

View File

@ -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"

View File

@ -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>
);

View File

@ -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>
);
};

View File

@ -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';

View File

@ -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';

View File

@ -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}

View File

@ -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;

View File

@ -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

View File

@ -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'

View File

@ -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>
)
},
)
);
}
);

View File

@ -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>
)
},
)
);
}
);

View File

@ -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>
)
},
)
);
}
);

View File

@ -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>
)
})
);
});

View File

@ -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>
)
})
);
});

View File

@ -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;

View File

@ -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;

View File

@ -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>
)
},
)
);
}
);

View File

@ -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>
)
},
)
);
}
);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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>
)
);
}

View File

@ -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;

View File

@ -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>
)
},
)
);
}
);

View File

@ -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>
)
}
);
};

View File

@ -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>
)
},
)
);
}
);

View File

@ -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);

View File

@ -1,2 +0,0 @@
import './axios';
import './dayjs';

View File

@ -1,2 +0,0 @@
export const DATE_FORMAT = 'YYYY-MM-DD';
export const DATE_FORMAT_FULL = 'dddd DD MMMM HH:mm';

View File

@ -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" };

View File

@ -1 +0,0 @@
export * from './date'

View File

@ -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.

View File

@ -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>

View File

@ -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>
</>

View File

@ -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>
</>

View File

@ -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} />;
};

View File

@ -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>
);
}

View File

@ -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>

View File

@ -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 = () => {

View File

@ -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 };
};

View File

@ -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>
</>
);
};

View File

@ -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>
</>
);
};

View File

@ -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 };
};
}

View File

@ -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,

View File

@ -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]
);

View File

@ -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,
});
};
}

View File

@ -1,7 +1,6 @@
type PandaColorModel = {
value: string;
}
};
type ThemeModel = {
50: PandaColorModel;
100: PandaColorModel;

View File

@ -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}' },
},
},
},

View File

@ -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;
}

View File

@ -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;

View File

@ -1,4 +1,4 @@
import { JwtToken, RESTConfig } from '@/back-api';
import { RESTConfig } from '@/back-api';
import { getApiUrl } from '@/environment';
import { getUserToken } from '@/service/session';

View File

@ -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 };
};

View File

@ -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);
}

View File

@ -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);
}