feat: add app and config
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { JSX, useEffect, useState } from 'react';
|
||||
import { useConfigStore } from '../store/config';
|
||||
import { CardBlank } from '@/components/card';
|
||||
import { Button, ButtonGroup, Divider, Drawer, Tab, Tabs, Tooltip } from '@mui/material';
|
||||
import { Edit, Plus, Save, Trash, X } from 'lucide-react';
|
||||
import { Button, ButtonGroup, Divider, Drawer, FormControlLabel, Tab, Tabs, Tooltip, useTheme } from '@mui/material';
|
||||
import { Edit, Plus, Save, Share, Trash, X } from 'lucide-react';
|
||||
import ShareAltOutlined from '@ant-design/icons/ShareAltOutlined';
|
||||
import { useModal } from '@kevisual/center-components/modal/Confirm.tsx';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { TextField } from '@mui/material';
|
||||
import { useController } from 'react-hook-form';
|
||||
|
||||
import { TextField, TextFieldLabel } from '@kevisual/center-components/input/TextField.tsx';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IconButton } from '@kevisual/center-components/button/index.tsx';
|
||||
import { useShallow } from 'zustand/shallow';
|
||||
@@ -13,7 +16,8 @@ import { load, dump } from 'js-yaml';
|
||||
import CodeEditor from '@uiw/react-textarea-code-editor';
|
||||
import { toast } from 'react-toastify';
|
||||
import { isEmpty, pick } from 'lodash-es';
|
||||
|
||||
import { usePermissionModal } from '@kevisual/resources/index.ts';
|
||||
import React from 'react';
|
||||
type DataYamlEditProps = {
|
||||
onSave: (data: any) => Promise<void>;
|
||||
type?: 'yaml' | 'json';
|
||||
@@ -42,7 +46,6 @@ export const DataYamlEdit = ({ onSave, type }: DataYamlEditProps) => {
|
||||
}
|
||||
}
|
||||
}, [formData]);
|
||||
console.log(formData);
|
||||
const handleSave = () => {
|
||||
let data: any = {};
|
||||
try {
|
||||
@@ -109,14 +112,16 @@ export const DrawerEdit = () => {
|
||||
await updateData({ ...values, id: formData.id }, { refresh: true });
|
||||
};
|
||||
const onSubmit = (data) => {
|
||||
console.log('Form Data:', data);
|
||||
const pickValue = pick(data, ['title', 'key', 'description']);
|
||||
onSave(pickValue);
|
||||
};
|
||||
const theme = useTheme();
|
||||
const defaultProps = theme.components?.MuiTextField?.defaultProps;
|
||||
return (
|
||||
<Drawer
|
||||
open={showEdit}
|
||||
anchor='right'
|
||||
container={document.getElementById('for-drawer')}
|
||||
slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
@@ -139,22 +144,21 @@ export const DrawerEdit = () => {
|
||||
<Tab label='JSON Config' value='json' />
|
||||
</Tabs>
|
||||
{tab === 'base' && (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className='w-full p-2'>
|
||||
<Controller
|
||||
name='title'
|
||||
control={control}
|
||||
render={({ field }) => <TextField {...field} label='Title' variant='outlined' fullWidth margin='normal' />}
|
||||
/>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className='w-full p-2 flex flex-col gap-6'>
|
||||
<Controller control={control} name='title' render={({ field }) => <TextField {...field} label='Title' />} />
|
||||
<Controller
|
||||
name='key'
|
||||
control={control}
|
||||
render={({ field }) => <TextField {...field} label='Key' variant='outlined' fullWidth margin='normal' />}
|
||||
/>
|
||||
<Controller
|
||||
name='description'
|
||||
control={control}
|
||||
render={({ field }) => <TextField {...field} label='Description' variant='outlined' fullWidth margin='normal' multiline rows={4} />}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
label={
|
||||
<TextFieldLabel label='Key' tips='Key is the unique identifier for the configuration. if set and id is none will change data by key;' />
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller name='description' control={control} render={({ field }) => <TextField {...field} label='Description' multiline rows={4} />} />
|
||||
<Button type='submit' variant='contained' color='primary'>
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
@@ -174,14 +178,36 @@ export const DrawerEdit = () => {
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
||||
export const MyController = React.forwardRef(
|
||||
({ control, name, Component, componentProps }: { control: any; name: string; Component: (props: any) => JSX.Element; componentProps: any }, ref) => {
|
||||
const theme = useTheme();
|
||||
const defaultProps = theme.components?.MuiTextField?.defaultProps;
|
||||
console.log(defaultProps, 'defaultProps');
|
||||
const { field } = useController({ control, name });
|
||||
return <Component {...field} {...componentProps} ref={ref} />;
|
||||
},
|
||||
);
|
||||
export const List = () => {
|
||||
const { list, getConfig, setShowEdit, setFormData, deleteConfig } = useConfigStore();
|
||||
const { list, getConfig, setShowEdit, setFormData, deleteConfig, updateData, formData } = useConfigStore();
|
||||
const [modal, contextHolder] = useModal();
|
||||
useEffect(() => {
|
||||
getConfig();
|
||||
}, []);
|
||||
const { setOpen, contextHolder: contextHolderPermission } = usePermissionModal({
|
||||
onSave: async (values) => {
|
||||
const permission = values;
|
||||
console.log(permission, formData.id);
|
||||
if (permission && formData.id) {
|
||||
const res = await updateData({ data: { permission }, id: formData.id }, { refresh: true });
|
||||
console.log(res);
|
||||
return res.code === 200;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
return true;
|
||||
},
|
||||
});
|
||||
console.log(list);
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className='w-full h-full flex bg-gray-100'>
|
||||
<div className='h-full bg-white'>
|
||||
@@ -191,17 +217,26 @@ export const List = () => {
|
||||
setShowEdit(true);
|
||||
setFormData({});
|
||||
}}>
|
||||
<Plus />
|
||||
<Plus size={16} />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className=' grow p-4'>
|
||||
<div className=' grow p-4 '>
|
||||
<div className='w-full h-full bg-white rounded-lg p-2 scrollbar '>
|
||||
<div className='flex flex-wrap gap-2'>
|
||||
<div className='flex flex-wrap gap-2 '>
|
||||
{list.map((item) => (
|
||||
<div className='card w-[300px]' key={item.id}>
|
||||
<div className='card w-[300px] ' key={item.id}>
|
||||
<div className='card-title flex font-bold justify-between'>{item.title}</div>
|
||||
<div className='card-content'>{item.description}</div>
|
||||
<div className='card-content'>
|
||||
<div className='flex gap-2'>
|
||||
<div>{t('Description')}:</div>
|
||||
<div>{item.description}</div>
|
||||
</div>
|
||||
<div className='flex gap-2'>
|
||||
<div>{t('Key')}:</div>
|
||||
<div>{item.key}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='card-footer flex justify-end'>
|
||||
<ButtonGroup variant='contained'>
|
||||
<Button
|
||||
@@ -211,6 +246,15 @@ export const List = () => {
|
||||
}}>
|
||||
<Edit />
|
||||
</Button>
|
||||
<Tooltip title={t('Permission')}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setFormData(item);
|
||||
setOpen(true, item.data?.permission);
|
||||
}}>
|
||||
<ShareAltOutlined style={{ fontSize: 20 }} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
onClick={() => {
|
||||
modal.confirm({
|
||||
@@ -233,6 +277,7 @@ export const List = () => {
|
||||
</div>
|
||||
<DrawerEdit />
|
||||
{contextHolder}
|
||||
{contextHolderPermission}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { query } from '@/modules/query';
|
||||
import { toast } from 'react-toastify';
|
||||
import { QueryConfig } from '@kevisual/query-config';
|
||||
|
||||
export const queryConfig = new QueryConfig({ query });
|
||||
export const queryConfig = new QueryConfig({ query: query as any });
|
||||
|
||||
interface ConfigStore {
|
||||
list: any[];
|
||||
|
||||
Reference in New Issue
Block a user