From 25def8c24542b0f09c708bcfa0552d16c4e65bda Mon Sep 17 00:00:00 2001 From: xion Date: Tue, 18 Mar 2025 13:10:40 +0800 Subject: [PATCH] feat: add resources --- packages/components/src/theme/index.tsx | 23 +- packages/resources/index.html | 3 +- packages/resources/package.json | 14 +- packages/resources/public/config.js | 6 + packages/resources/src/assets/index.css | 38 ++ packages/resources/src/main.ts | 50 +-- packages/resources/src/modules/query.ts | 14 +- packages/resources/src/pages/App.tsx | 77 +++- packages/resources/src/pages/Bootstrap.tsx | 61 +++ .../resources/src/pages/file/FileIcon.tsx | 80 ++++ .../src/pages/file/draw/FileDrawer.tsx | 58 ++- .../src/pages/file/draw/QuickTabs.tsx | 27 ++ .../pages/file/draw/modules/ContextForm.tsx | 29 ++ .../pages/file/draw/modules/DatePicker.tsx | 28 ++ .../src/pages/file/draw/modules/DialogKey.tsx | 39 ++ .../src/pages/file/draw/modules/MetaForm.tsx | 368 ++++++++++++++++++ .../pages/file/draw/modules/SelectPicker.tsx | 18 + .../src/pages/file/draw/quick/QuickLink.tsx | 11 + .../pages/file/draw/quick/QuickPreview.tsx | 131 +++++++ .../src/pages/file/draw/quick/index.tsx | 41 ++ .../src/pages/file/list/FileTable.tsx | 31 +- packages/resources/src/pages/main.tsx | 5 +- .../src/pages/message/ToastLogin.tsx | 5 +- .../resources/src/pages/settings/index.tsx | 1 - .../src/pages/store/resource-file.ts | 19 + .../resources/src/pages/store/resource.ts | 14 +- .../resources/src/pages/store/settings.ts | 41 +- packages/resources/src/pages/upload/index.tsx | 22 +- .../src/pages/upload/utils/upload.ts | 15 +- packages/resources/vite.config.mjs | 26 +- pnpm-lock.yaml | 256 +++++++++++- 31 files changed, 1432 insertions(+), 119 deletions(-) create mode 100644 packages/resources/public/config.js create mode 100644 packages/resources/src/pages/Bootstrap.tsx create mode 100644 packages/resources/src/pages/file/draw/QuickTabs.tsx create mode 100644 packages/resources/src/pages/file/draw/modules/ContextForm.tsx create mode 100644 packages/resources/src/pages/file/draw/modules/DatePicker.tsx create mode 100644 packages/resources/src/pages/file/draw/modules/DialogKey.tsx create mode 100644 packages/resources/src/pages/file/draw/modules/MetaForm.tsx create mode 100644 packages/resources/src/pages/file/draw/modules/SelectPicker.tsx create mode 100644 packages/resources/src/pages/file/draw/quick/QuickLink.tsx create mode 100644 packages/resources/src/pages/file/draw/quick/QuickPreview.tsx create mode 100644 packages/resources/src/pages/file/draw/quick/index.tsx diff --git a/packages/components/src/theme/index.tsx b/packages/components/src/theme/index.tsx index b4c6dda..279e96b 100644 --- a/packages/components/src/theme/index.tsx +++ b/packages/components/src/theme/index.tsx @@ -1,6 +1,6 @@ import { createTheme, Shadows, ThemeOptions } from '@mui/material/styles'; import { useTheme as useMuiTheme, Theme } from '@mui/material/styles'; -import { amber } from '@mui/material/colors'; +import { amber, red } from '@mui/material/colors'; const generateShadows = (color: string): Shadows => { return [ 'none', @@ -56,6 +56,9 @@ export const themeOptions: ThemeOptions = { default: '#ffffff', // 设置默认背景颜色 // paper: '#f5f5f5', // 设置纸张背景颜色 }, + error: { + main: red[500], + }, }, shadows: generateShadows('rgba(255, 193, 7, 0.2)'), typography: { @@ -103,6 +106,24 @@ export const themeOptions: ThemeOptions = { }, }, }, + MuiSelect: { + styleOverrides: { + root: { + '& .MuiOutlinedInput-notchedOutline': { + borderColor: amber[300], + }, + '&:hover .MuiOutlinedInput-notchedOutline': { + borderColor: amber[500], + }, + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { + borderColor: amber[500], + }, + '& .MuiSelect-icon': { + color: amber[500], // Set arrow icon color to primary + }, + }, + }, + }, MuiCard: { styleOverrides: { root: { diff --git a/packages/resources/index.html b/packages/resources/index.html index a4cb3fe..f0a0768 100644 --- a/packages/resources/index.html +++ b/packages/resources/index.html @@ -20,7 +20,8 @@ height: 100%; } - + + diff --git a/packages/resources/package.json b/packages/resources/package.json index 7038575..146146c 100644 --- a/packages/resources/package.json +++ b/packages/resources/package.json @@ -3,10 +3,15 @@ "version": "0.0.1", "description": "", "main": "index.js", + "basename": "/root/resources", "scripts": { "dev": "vite", - "build": "vite build" + "build": "vite build", + "pub": "envision deploy ./dist -k resources -v 0.0.1 -u -o root" }, + "files": [ + "src" + ], "keywords": [], "author": "abearxiong ", "license": "MIT", @@ -17,7 +22,7 @@ "@kevisual/center-components": "workspace:*", "@kevisual/router": "^0.0.9", "@kevisual/store": "^0.0.2", - "@mui/material": "^6.4.7", + "@mui/material": "^6.4.8", "@types/lodash-es": "^4.17.12", "@types/nprogress": "^0.2.3", "@vitejs/plugin-basic-ssl": "^2.0.0", @@ -25,10 +30,11 @@ "immer": "^10.1.1", "lodash-es": "^4.17.21", "lucide-react": "^0.482.0", - "nanoid": "^5.1.3", + "nanoid": "^5.1.4", "nprogress": "^0.2.0", "pretty-bytes": "^6.1.1", "react": "19.0.0", + "react-datepicker": "^8.2.1", "react-dom": "19.0.0", "react-dropzone": "^14.3.8", "react-toastify": "^11.0.5", @@ -37,4 +43,4 @@ "devDependencies": { "@kevisual/types": "^0.0.6" } -} +} \ No newline at end of file diff --git a/packages/resources/public/config.js b/packages/resources/public/config.js new file mode 100644 index 0000000..7197d1c --- /dev/null +++ b/packages/resources/public/config.js @@ -0,0 +1,6 @@ +export const config = { + api: () => location.origin, + apps: { + login: '/user/login', + }, +}; diff --git a/packages/resources/src/assets/index.css b/packages/resources/src/assets/index.css index f7676de..535d44f 100644 --- a/packages/resources/src/assets/index.css +++ b/packages/resources/src/assets/index.css @@ -7,6 +7,8 @@ } :root { --scrollbar-color: #ffbf00; + --primary-color: #ffc107; + --secondary-color: #ffa000; } #root { width: 100%; @@ -26,3 +28,39 @@ scrollbar-width: thin; scrollbar-color: var(--scrollbar-color) #fff; } + +.scrollbar::-webkit-scrollbar { + height: 4px; + width: 4px; +} + +.scrollbar::-webkit-scrollbar-thumb { + background-color: var(--scrollbar-color); + border-radius: 10px; +} + +.scrollbar::-webkit-scrollbar-track { + background: #fff; +} + +.ant-select-outlined.ant-select-multiple .ant-select-selection-item { + background: var(--secondary-color); + color: white; + svg { + color: white; + } +} +.ant-select-selection-item { + color: var(--primary-color); +} +.ant-select { + .ant-select-arrow { + display: none !important; + } +} +.ant-picker-input { + .ant-picker-suffix, + .ant-picker-clear { + color: var(--primary-color); + } +} diff --git a/packages/resources/src/main.ts b/packages/resources/src/main.ts index 504665e..917d1dd 100644 --- a/packages/resources/src/main.ts +++ b/packages/resources/src/main.ts @@ -1,50 +1,4 @@ -import { page, app } from './app.ts'; -import { basename } from './modules/basename.ts'; -import './pages/main.tsx'; +import { bootstrap } from './pages/Bootstrap'; -export const render = ({ renderRoot }) => { - renderRoot.innerHTML = ` -

Hello, World!

- `; -}; -console.log('basename', basename, page, app); +bootstrap('#ai-root'); -if (page) { - page.addPage('/', 'home'); - page.subscribe('home', () => { - render({ - renderRoot: document.getElementById('ai-root'), - }); - }); - page.addPage('', 'index'); - page.subscribe('index', () => { - const root = document.getElementById('ai-root') as HTMLElement; - root.innerHTML = ` -

Hello, World!

- `; - }); -} - -if (app) { - app - .route({ - path: 'app-template', - key: 'render', - }) - .define(async (ctx) => { - let { renderRoot } = ctx.query; - if (!renderRoot) { - ctx.throw(404, 'renderRoot is required'); - } - if (typeof renderRoot === 'string') { - renderRoot = document.querySelector(renderRoot); - } - if (!renderRoot) { - ctx.throw(404, 'renderRoot not found'); - } - render({ - renderRoot, - }); - }) - .addTo(app); -} diff --git a/packages/resources/src/modules/query.ts b/packages/resources/src/modules/query.ts index f4660b4..5c3e436 100644 --- a/packages/resources/src/modules/query.ts +++ b/packages/resources/src/modules/query.ts @@ -1,3 +1,15 @@ +import { toastLogin } from '@/pages/message/ToastLogin'; import { QueryClient } from '@kevisual/query'; -export const query = new QueryClient(); \ No newline at end of file +export const query = new QueryClient(); + +query.afterResponse = async (response) => { + if (response.code === 401) { + toastLogin(); + return { + ...response, + noMsg: true, + }; + } + return response; +}; diff --git a/packages/resources/src/pages/App.tsx b/packages/resources/src/pages/App.tsx index 8532ba2..61e56c2 100644 --- a/packages/resources/src/pages/App.tsx +++ b/packages/resources/src/pages/App.tsx @@ -5,10 +5,47 @@ import { Left } from './layout/Left'; import { Main } from './main/index'; import { ToastContainer } from 'react-toastify'; import { useSettingsStore } from './store/settings'; -import { CircularProgress } from '@mui/material'; +import { CircularProgress, useTheme } from '@mui/material'; import { useResourceStore } from './store/resource'; +import dayjs from 'dayjs'; +import 'dayjs/locale/zh-cn'; -export const App = () => { +import zhCN from 'antd/locale/zh_CN'; +import ConfigProvider from 'antd/es/config-provider'; + +dayjs.locale('zh-cn'); +export const AntdConfigProvider = ({ children }: { children: React.ReactNode }) => { + const theme = useTheme(); + const primaryColor = theme.palette.primary.main; + const secondaryColor = theme.palette.secondary.main; + return ( + + {children} + + ); +}; +export const InitProvider = ({ children }: { children: React.ReactNode }) => { const { init, mounted, settings } = useSettingsStore(); const { setPrefix, init: initResource } = useResourceStore(); useEffect(() => { @@ -16,24 +53,46 @@ export const App = () => { initResource(); }, []); useEffect(() => { - if (settings.prefix && mounted) { + if (settings.prefix && mounted === 'success') { setPrefix(settings.prefix); } }, [mounted, settings.prefix]); - if (!mounted) { + + const handleRetry = () => { + init(); + initResource(); + }; + + if (mounted === 'loading') { return (
); + } else if (mounted === 'error') { + return ( +
+

出现问题

+

加载设置时遇到错误。请重试。

+ +
+ ); } - + return <>{children}; +}; +export const App = () => { return ( - -
- - + + + +
+ + + + ); }; diff --git a/packages/resources/src/pages/Bootstrap.tsx b/packages/resources/src/pages/Bootstrap.tsx new file mode 100644 index 0000000..b9f76ba --- /dev/null +++ b/packages/resources/src/pages/Bootstrap.tsx @@ -0,0 +1,61 @@ +import { createRoot } from 'react-dom/client'; +import { App } from './App'; +import React from 'react'; + +export class ReactRenderer { + component: any; + element: HTMLElement; + ref: React.RefObject; + props: any; + root: any; + constructor(component: any, { props, className }: any) { + this.component = component; + const el = document.createElement('div'); + this.element = el; + this.ref = React.createRef(); + this.props = { + ...props, + ref: this.ref, + }; + el.className = className; + this.root = createRoot(this.element); + this.render(); + } + + updateProps(props: any) { + this.props = { + ...this.props, + ...props, + }; + this.render(); + } + + render() { + this.root.render(React.createElement(this.component, this.props)); + } + + destroy() { + this.root.unmount(); + } +} + +export default ReactRenderer; + +export const bootstrap = (el: HTMLElement | string) => { + // createRoot(document.getElementById('ai-root')!).render(); + const root = typeof el === 'string' ? document.querySelector(el) : el; + if (root) { + const renderer = new ReactRenderer(App, { + props: {}, + className: 'resources-root w-full h-full', + }); + if (window.context) { + window.context.resourcesApp = renderer; + } else { + window.context = { + resourcesApp: renderer, + }; + } + root.appendChild(renderer.element); + } +}; diff --git a/packages/resources/src/pages/file/FileIcon.tsx b/packages/resources/src/pages/file/FileIcon.tsx index 61c4826..ad1b7bd 100644 --- a/packages/resources/src/pages/file/FileIcon.tsx +++ b/packages/resources/src/pages/file/FileIcon.tsx @@ -90,3 +90,83 @@ export const getIcon = (name: string) => { return ; } }; + +/** + * 获取文件类型,文件大类 + * @param name 文件名 + * @returns 文件类型 + */ +export const getFileType = (name?: string) => { + if (!name) { + return ''; + } + const extension = getExtension(name); + switch (extension) { + case 'pdf': + return 'pdf'; + case 'jpg': + case 'jpeg': + case 'gif': + case 'png': + return 'image'; + case 'mp3': + case 'wav': + case 'ogg': + case 'm4a': + case 'aac': + case 'flac': + case 'wma': + return 'audio'; + case 'mp4': + return 'video'; + case 'doc': + case 'docx': + return 'word'; + case 'ppt': + case 'pptx': + return 'ppt'; + case 'xls': + case 'xlsx': + return 'excel'; + case 'zip': + case 'rar': + case '7z': + case 'tar': + case 'gz': + case 'bz2': + return 'zip'; + case 'txt': + case 'md': + case 'csv': + case 'json': + case 'xml': + case 'yaml': + case 'yml': + case 'toml': + case 'ini': + case 'conf': + case 'cfg': + case 'config': + case 'props': + case 'properties': + case 'log': + case 'sh': + case 'bash': + case 'zsh': + case 'fish': + case 'bat': + case 'cmd': + return 'text'; + case 'html': + case 'htm': + return 'html'; + case 'css': + case 'js': + case 'ts': + case 'jsx': + case 'tsx': + return 'code'; + default: + return 'other'; + } +}; diff --git a/packages/resources/src/pages/file/draw/FileDrawer.tsx b/packages/resources/src/pages/file/draw/FileDrawer.tsx index 53365f1..29e72f6 100644 --- a/packages/resources/src/pages/file/draw/FileDrawer.tsx +++ b/packages/resources/src/pages/file/draw/FileDrawer.tsx @@ -1,16 +1,60 @@ import { useResourceStore } from '@/pages/store/resource'; import { useResourceFileStore } from '@/pages/store/resource-file'; -import { Drawer } from '@mui/material'; +import { Box, Divider, Drawer, Tab, Tabs } from '@mui/material'; +import { useMemo, useState } from 'react'; +import { QuickValues, QuickTabs } from './QuickTabs'; export const FileDrawer = () => { const { prefix } = useResourceStore(); const { resource, openDrawer, setOpenDrawer } = useResourceFileStore(); + const [tab, setTab] = useState(QuickValues[0]); + const quickCom = useMemo(() => { + return QuickTabs.find((item) => item.value === tab)?.component; + }, [tab]); return ( - setOpenDrawer(false)} anchor='right' {...(!openDrawer && { inert: true })}> -
-

{resource?.name ? resource.name.replace(prefix, '') : resource?.prefix?.replace(prefix, '')}

-
{JSON.stringify(resource, null, 2)}
-
-
+ <> + { + // document.getElementById('focus-safe-element')?.focus(); + const activeElement = document.activeElement as HTMLElement; + if (activeElement) { + activeElement.blur(); + } + setOpenDrawer(false); + }} + ModalProps={{ + keepMounted: true, + }} + anchor='right' + style={{ + zIndex: 1000, + }}> +
+
+

+ {resource?.name ? resource.name.replace(prefix, '') : resource?.prefix?.replace(prefix, '')} +

+ + + setTab(value)}> + {QuickTabs.map((item) => ( + + ))} + + +
+ +
+ {quickCom && quickCom()} +
+
+
+
+ + ); }; diff --git a/packages/resources/src/pages/file/draw/QuickTabs.tsx b/packages/resources/src/pages/file/draw/QuickTabs.tsx new file mode 100644 index 0000000..76c1526 --- /dev/null +++ b/packages/resources/src/pages/file/draw/QuickTabs.tsx @@ -0,0 +1,27 @@ +import { MetaForm } from './modules/MetaForm'; +import { ContentForm } from './modules/ContextForm'; +import { Cpu, File, FileText, Rabbit } from 'lucide-react'; +import { Quick } from './quick'; +export const QuickTabs = [ + { + label: 'Quick', + value: 'quick', + icon: , + index: 99, + component: () => , + }, + { + label: '元数据', + value: 'meta', + icon: , + component: () => , + }, + { + label: '内容', + value: 'content', + icon: , + component: () => , + }, +].sort((a, b) => (b?.index || 0) - (a?.index || 0)); + +export const QuickValues = QuickTabs.map((item) => item.value); diff --git a/packages/resources/src/pages/file/draw/modules/ContextForm.tsx b/packages/resources/src/pages/file/draw/modules/ContextForm.tsx new file mode 100644 index 0000000..3209b9e --- /dev/null +++ b/packages/resources/src/pages/file/draw/modules/ContextForm.tsx @@ -0,0 +1,29 @@ +import { useResourceFileStore } from '@/pages/store/resource-file'; +import { Box, Typography } from '@mui/material'; +import prettyBytes from 'pretty-bytes'; +import dayjs from 'dayjs'; + +type ContentShowType = { + size: number; + lastModified: string; + etag: string; + name?: string; +}; +export const ContentForm = () => { + const { resource } = useResourceFileStore(); + const contentShow = resource as ContentShowType; + return ( + + {/* {contentShow?.name || 'No Name Available'} */} + + Size: {contentShow?.size ? prettyBytes(contentShow?.size) : 'N/A'} + + + Last Modified: {contentShow?.lastModified ? dayjs(contentShow?.lastModified).format('YYYY-MM-DD HH:mm:ss') : 'N/A'} + + + ETag: {contentShow?.etag || 'N/A'} + + + ); +}; diff --git a/packages/resources/src/pages/file/draw/modules/DatePicker.tsx b/packages/resources/src/pages/file/draw/modules/DatePicker.tsx new file mode 100644 index 0000000..4be43fb --- /dev/null +++ b/packages/resources/src/pages/file/draw/modules/DatePicker.tsx @@ -0,0 +1,28 @@ +import ReactDatePicker from 'antd/es/date-picker'; +import { useTheme } from '@mui/material'; +import 'antd/es/date-picker/style/index'; +interface DatePickerProps { + value?: Date | null; + onChange?: (date: Date | null) => void; +} + +export const DatePicker = ({ value, onChange }: DatePickerProps) => { + const theme = useTheme(); + const primaryColor = theme.palette.primary.main; + return ( +
+ onChange?.(date)} // + style={{ + color: primaryColor, + }} + popupStyle={{ zIndex: 2000 }} + /> +
+ ); +}; diff --git a/packages/resources/src/pages/file/draw/modules/DialogKey.tsx b/packages/resources/src/pages/file/draw/modules/DialogKey.tsx new file mode 100644 index 0000000..5c3f4ec --- /dev/null +++ b/packages/resources/src/pages/file/draw/modules/DialogKey.tsx @@ -0,0 +1,39 @@ +import { Button, Dialog, DialogContent, DialogTitle, FormControlLabel, TextField } from '@mui/material'; +import { useState } from 'react'; +import { useMetaStore } from './MetaForm'; +export const DialogKey = ({ onAdd }: { onAdd: (key: string) => void }) => { + const { openPropertyModal, setOpenPropertyModal } = useMetaStore(); + const [key, setKey] = useState(''); + return ( + setOpenPropertyModal(false)}> + 添加元数据key + +
+ setKey(e.target.value)} />} + sx={{ + alignItems: 'flex-start', + '& .MuiFormControlLabel-label': { + textAlign: 'left', + width: '100%', + }, + }} + /> + +
+
+
+ ); +}; diff --git a/packages/resources/src/pages/file/draw/modules/MetaForm.tsx b/packages/resources/src/pages/file/draw/modules/MetaForm.tsx new file mode 100644 index 0000000..7505dbf --- /dev/null +++ b/packages/resources/src/pages/file/draw/modules/MetaForm.tsx @@ -0,0 +1,368 @@ +import { useResourceFileStore } from '@/pages/store/resource-file'; +import { FormControlLabel, Box, TextField, Button, IconButton, ButtonGroup, Tooltip, Select, MenuItem, Typography, FormGroup } from '@mui/material'; +import { Info, Plus, Save, Share, Shuffle, Trash } from 'lucide-react'; +import { useState, useEffect, useMemo } from 'react'; +import { toast } from 'react-toastify'; +import { create } from 'zustand'; +import { uniq } from 'lodash-es'; +import { DatePicker } from './DatePicker'; +import { SelectPicker } from './SelectPicker'; +import dayjs from 'dayjs'; +import { DialogKey } from './DialogKey'; + +export const setShareKeysOperate = (value: 'public' | 'protected' | 'private') => { + const keys = ['password', 'usernames', 'expiration-time']; + const deleteKeys = keys.map((item) => { + return { + key: item, + operate: 'delete', + }; + }); + if (value === 'protected') { + return deleteKeys.map((item) => { + return { + ...item, + operate: 'add', + }; + }); + } + return deleteKeys; +}; +export const keysTips = [ + { + key: 'share', + tips: `共享设置 + 1. 设置公共可以直接访问 + 2. 设置受保护需要登录后访问 + 3. 设置私有只有自己可以访问。\n + 受保护可以设置密码,设置访问的用户名。切换共享状态后,需要重新设置密码和用户名。`, + }, + { + key: 'content-type', + tips: `内容类型,设置文件的内容类型。默认不要修改。`, + }, + { + key: 'app-source', + tips: `应用来源,上传方式。默认不要修改。`, + }, + { + key: 'cache-control', + tips: `缓存控制,设置文件的缓存控制。默认不要修改。`, + }, + { + key: 'password', + tips: `密码,设置文件的密码。不设置默认是所有人都可以访问。`, + }, + { + key: 'usernames', + tips: `用户名,设置文件的用户名。不设置默认是所有人都可以访问。`, + parse: (value: string) => { + if (!value) { + return []; + } + return value.split(','); + }, + stringify: (value: string[]) => { + if (!value) { + return ''; + } + return value.join(','); + }, + }, + { + key: 'expiration-time', + tips: `过期时间,设置文件的过期时间。不设置默认是永久。`, + parse: (value: Date) => { + if (!value) { + return null; + } + return dayjs(value); + }, + stringify: (value?: dayjs.Dayjs) => { + if (!value) { + return ''; + } + return value.toISOString(); + }, + }, +]; +export class KeyParse { + static parse(metadata: Record) { + const keys = Object.keys(metadata); + const newMetadata = {}; + keys.forEach((key) => { + const tip = keysTips.find((item) => item.key === key); + if (tip && tip.parse) { + newMetadata[key] = tip.parse(metadata[key]); + } else { + newMetadata[key] = metadata[key]; + } + }); + return newMetadata; + } + static stringify(metadata: Record) { + const keys = Object.keys(metadata); + const newMetadata = {}; + keys.forEach((key) => { + const tip = keysTips.find((item) => item.key === key); + if (tip && tip.stringify) { + newMetadata[key] = tip.stringify(metadata[key]); + } else { + newMetadata[key] = metadata[key]; + } + }); + return newMetadata; + } +} +export const useMetaOperate = ({ + onSave, + metaStore, + handleFormDataChange, +}: { + onSave: () => void; + metaStore: MetaStore; + handleFormDataChange: (key: string, value: string | Date | null | string[]) => void; +}) => { + const { keys, setKeys, openPropertyModal, setOpenPropertyModal } = metaStore; + const hasShare = keys.includes('share'); + const hasPassword = keys.includes('password'); + const addMeta = (key: string) => { + setKeys(uniq([...keys, key])); + }; + const defaultBtnList = [ + { + icon: , + key: 'save', + tooltip: '保存元数据, 修改后需要手动保存', + onClick: () => onSave(), + }, + { + icon: , + key: 'add', + tooltip: '添加元数据', + onClick: () => setOpenPropertyModal(true), + }, + ]; + if (!hasShare) { + defaultBtnList.push({ + icon: , + key: 'share', + tooltip: '开启共享', + onClick: () => addMeta('share'), + }); + } + if (hasShare && hasPassword) { + defaultBtnList.push({ + icon: , + key: 'password', + tooltip: '随机生成密码', + onClick: () => { + const password = Math.random().toString(36).substring(2, 8); + handleFormDataChange('password', password); + }, + }); + } + return defaultBtnList; +}; +type MetaStore = { + keys: string[]; + setKeys: (keys: string[]) => void; + openPropertyModal: boolean; + setOpenPropertyModal: (openPropertyModal: boolean) => void; +}; +export const useMetaStore = create((set) => ({ + keys: [], + setKeys: (keys) => set({ keys }), + openPropertyModal: false, + setOpenPropertyModal: (openPropertyModal) => set({ openPropertyModal }), +})); +export const MetaForm = () => { + const { resource, updateMeta } = useResourceFileStore(); + const [formData, setFormData] = useState({}); + const metaStore = useMetaStore(); + const { keys, setKeys } = metaStore; + useEffect(() => { + // setFormData(resource?.metaData || {}); + setFormData(KeyParse.parse(resource?.metaData || {})); + }, [resource]); + useEffect(() => { + setKeys(Object.keys(resource?.metaData || {})); + }, [resource]); + if (!keys.length) { + return
没有元数据
; + } + + const handleFormDataChange = (key: string, value: string | Date | null | string[]) => { + // setFormData({ ...formData, [key]: value }); + const _formData = { ...formData }; + if (key === 'share') { + const shareKeysOperate = setShareKeysOperate(value as 'public' | 'protected' | 'private'); + shareKeysOperate.forEach((item) => { + if (item.operate === 'add') { + _formData[item.key] = ''; + } else if (item.operate === 'delete') { + delete _formData[item.key]; + } + }); + _formData.share = value; + setFormData(_formData); + const newKeys = keys + .map((item) => { + const operate = shareKeysOperate.find((item2) => item2.key === item); + if (operate && operate.operate === 'delete') { + return null; + } + return item; + }) + .filter((item) => item !== null); + const addKeys = shareKeysOperate.filter((item) => item.operate === 'add').map((item) => item.key); + const _newKeys = uniq([...newKeys, ...addKeys]); + setKeys(_newKeys); + console.log(_newKeys); + return; + } else { + _formData[key] = value; + } + setFormData(_formData); + }; + const deleteMeta = (key: string) => { + setKeys(keys.filter((item) => item !== key)); + delete formData[key]; + setFormData({ ...formData }); + }; + const onSave = () => { + const newMetadata = KeyParse.stringify(formData); + updateMeta(newMetadata); + }; + const addMetaKey = (key: string) => { + if (keys.includes(key)) { + toast.error('元数据key已存在'); + return; + } + formData[key] = ''; + setKeys([...keys, key]); + setFormData({ ...formData }); + }; + const btnList = useMetaOperate({ onSave, metaStore, handleFormDataChange }); + + return ( +
+ +
+
+ + {btnList.map((item) => { + const icon = ( + + {item.icon} + + ); + if (item.tooltip) { + return ( + + {icon} + + ); + } + return <>{icon}; + })} + +
+
+
+ + {keys.map((key) => { + let control: React.ReactNode | null = null; + if (key === 'share') { + control = handleFormDataChange(key, value)} />; + } else if (key === 'expiration-time') { + control = handleFormDataChange(key, date)} />; + } else if (key === 'usernames') { + control = handleFormDataChange(key, value)} />; + } else { + control = handleFormDataChange(key, value)} />; + } + const Label = () => { + const tip = keysTips.find((item) => item.key === key); + return ( +
+
+ + {key} + + {tip && ( + + + + )} +
+ deleteMeta(key)}> + + +
+ ); + }; + return ( +
+ } + labelPlacement='top' + control={control} + sx={{ + alignItems: 'flex-start', + '& .MuiFormControlLabel-label': { + textAlign: 'left', + width: '100%', + }, + }} + /> +
+ ); + })} +
+ +
+ ); +}; + +const KeyTextField = ({ name, value, onChange }: { name: string; value: string; onChange?: (value: string) => void }) => { + return ( + onChange?.(e.target.value)} + sx={{ + width: '100%', + marginBottom: '16px', + }} + /> + ); +}; +const KeyShareSelect = ({ name, value, onChange }: { name: string; value: string; onChange?: (value: string) => void }) => { + return ( + + ); +}; diff --git a/packages/resources/src/pages/file/draw/modules/SelectPicker.tsx b/packages/resources/src/pages/file/draw/modules/SelectPicker.tsx new file mode 100644 index 0000000..0f6b209 --- /dev/null +++ b/packages/resources/src/pages/file/draw/modules/SelectPicker.tsx @@ -0,0 +1,18 @@ +import { styled } from '@mui/material'; +import Select from 'antd/es/select'; +import 'antd/es/select/style/index'; + +interface SelectPickerProps { + value: string[]; + onChange: (value: string[]) => void; +} + +export const SelectPickerCom = ({ value, onChange }: SelectPickerProps) => { + return + ); }; -export const Upload = () => { +export const Upload = ({ uploadDirectory = false }: { uploadDirectory?: boolean }) => { const onDrop = async (acceptedFiles) => { console.log(acceptedFiles); if (acceptedFiles.length > 1) { @@ -87,7 +94,14 @@ export const Upload = () => { }}> diff --git a/packages/resources/src/pages/upload/utils/upload.ts b/packages/resources/src/pages/upload/utils/upload.ts index 595d7fb..6a18638 100644 --- a/packages/resources/src/pages/upload/utils/upload.ts +++ b/packages/resources/src/pages/upload/utils/upload.ts @@ -14,12 +14,25 @@ export const uploadFiles = async (files: File[], opts: ConvertOpts) => { const { directory } = opts; return new Promise((resolve, reject) => { const formData = new FormData(); + const webkitRelativePath = files[0]?.webkitRelativePath; + const keepDirectory = webkitRelativePath !== ''; + const root = keepDirectory ? webkitRelativePath.split('/')[0] : ''; for (let i = 0; i < files.length; i++) { - formData.append('file', files[i], files[i].name); + const file = files[i]; + if (keepDirectory) { + // relativePath 去除第一级 + const webkitRelativePath = file.webkitRelativePath.replace(root + '/', ''); + formData.append('file', file, webkitRelativePath); // 保留文件夹路径 + } else { + formData.append('file', files[i], files[i].name); + } } if (directory) { formData.append('directory', directory); } + console.log('formData', formData, files); + resolve(null); + return; const token = localStorage.getItem('token'); if (!token) { toastLogin(); diff --git a/packages/resources/vite.config.mjs b/packages/resources/vite.config.mjs index 8d4ecb2..a74ea76 100644 --- a/packages/resources/vite.config.mjs +++ b/packages/resources/vite.config.mjs @@ -15,6 +15,7 @@ if (true) { target: 'https://kevisual.silkyai.cn', changeOrigin: true, ws: true, + cookieDomainRewrite: 'localhost', rewrite: (path) => path.replace(/^\/api/, '/api'), }, '/api/router': { @@ -27,6 +28,7 @@ if (true) { '/user/login': { target: 'https://kevisual.silkyai.cn', changeOrigin: true, + cookieDomainRewrite: 'localhost', rewrite: (path) => path.replace(/^\/user/, '/user'), }, }; @@ -41,12 +43,27 @@ export default defineConfig({ resolve: { alias: { '@': path.resolve(__dirname, './src'), + // 'react/jsx-dev-runtime': 'https://cdn.jsdelivr.net/npm/react/jsx-dev-runtime/+esm', + // 'react/jsx-runtime': 'https://cdn.jsdelivr.net/npm/react/jsx-runtime/+esm', + // 'react/jsx-runtime': path.resolve(__dirname, './node_modules/react/jsx-runtime'), + // 'react/jsx-dev-runtime': path.resolve(__dirname, './node_modules/react/jsx-dev-runtime'), + // 'react-dom/client': 'https://cdn.jsdelivr.net/npm/react-dom/client/+esm', + // react: 'https://cdn.jsdelivr.net/npm/react@19.0.0/+esm', + // 'react-dom': 'https://cdn.jsdelivr.net/npm/react-dom@19.0.0/+esm', + }, }, define: { DEV_SERVER: JSON.stringify(process.env.NODE_ENV === 'development'), + BASE_NAME: JSON.stringify('/root/resources/'), + }, + base: './', + // base: isDev ? '/' : '/root/resources/', + build: { + rollupOptions: { + // external: ['react', 'react-dom'], + }, }, - base: isDev ? '/' : '/root/resources/', server: { port: 6022, host: '0.0.0.0', @@ -59,6 +76,7 @@ export default defineConfig({ target: 'http://localhost:4005', changeOrigin: true, ws: true, + cookieDomainRewrite: 'localhost', rewrite: (path) => path.replace(/^\/api/, '/api'), }, '/api/router': { @@ -68,12 +86,6 @@ export default defineConfig({ rewriteWsOrigin: true, rewrite: (path) => path.replace(/^\/api/, '/api'), }, - '/api/s1/events': { - target: 'https://kevisual.silkyai.cn', - changeOrigin: true, - ws: true, - rewrite: (path) => path.replace(/^\/api/, '/api'), - }, ...proxy, }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1fc20c..5a0f18f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,7 +52,7 @@ importers: version: 12.4.4(@types/react@19.0.10)(immer@10.1.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) antd: specifier: ^5.24.3 - version: 5.24.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 5.24.3(date-fns@4.1.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) classnames: specifier: ^2.5.1 version: 2.5.1 @@ -227,8 +227,8 @@ importers: specifier: ^0.0.2 version: 0.0.2(rollup@4.34.7) '@mui/material': - specifier: ^6.4.7 - version: 6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: ^6.4.8 + version: 6.4.8(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 @@ -251,8 +251,8 @@ importers: specifier: ^0.482.0 version: 0.482.0(react@19.0.0) nanoid: - specifier: ^5.1.3 - version: 5.1.3 + specifier: ^5.1.4 + version: 5.1.4 nprogress: specifier: ^0.2.0 version: 0.2.0 @@ -262,6 +262,9 @@ importers: react: specifier: 19.0.0 version: 19.0.0 + react-datepicker: + specifier: ^8.2.1 + version: 8.2.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react-dom: specifier: 19.0.0 version: 19.0.0(react@19.0.0) @@ -685,6 +688,27 @@ packages: resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@floating-ui/core@1.6.9': + resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} + + '@floating-ui/dom@1.6.13': + resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} + + '@floating-ui/react-dom@2.1.2': + resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/react@0.27.5': + resolution: {integrity: sha512-BX3jKxo39Ba05pflcQmqPPwc0qdNsdNi/eweAFtoIdrJWNen2sVEWMEac3i6jU55Qfx+lOcdMNKYn2CtWmlnOQ==} + peerDependencies: + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@floating-ui/utils@0.2.9': + resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -777,6 +801,9 @@ packages: '@mui/core-downloads-tracker@6.4.7': resolution: {integrity: sha512-XjJrKFNt9zAKvcnoIIBquXyFyhfrHYuttqMsoDS7lM7VwufYG4fAPw4kINjBFg++fqXM2BNAuWR9J7XVIuKIKg==} + '@mui/core-downloads-tracker@6.4.8': + resolution: {integrity: sha512-vjP4+A1ybyCRhDZC7r5EPWu/gLseFZxaGyPdDl94vzVvk6Yj6gahdaqcjbhkaCrJjdZj90m3VioltWPAnWF/zw==} + '@mui/material@6.4.7': resolution: {integrity: sha512-K65StXUeGAtFJ4ikvHKtmDCO5Ab7g0FZUu2J5VpoKD+O6Y3CjLYzRi+TMlI3kaL4CL158+FccMoOd/eaddmeRQ==} engines: {node: '>=14.0.0'} @@ -797,6 +824,26 @@ packages: '@types/react': optional: true + '@mui/material@6.4.8': + resolution: {integrity: sha512-5S9UTjKZZBd9GfbcYh/nYfD9cv6OXmj5Y7NgKYfk7JcSoshp8/pW5zP4wecRiroBSZX8wcrywSgogpVNO+5W0Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@mui/material-pigment-css': ^6.4.8 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@mui/material-pigment-css': + optional: true + '@types/react': + optional: true + '@mui/private-theming@6.4.6': resolution: {integrity: sha512-T5FxdPzCELuOrhpA2g4Pi6241HAxRwZudzAuL9vBvniuB5YU82HCmrARw32AuCiyTfWzbrYGGpZ4zyeqqp9RvQ==} engines: {node: '>=14.0.0'} @@ -807,6 +854,16 @@ packages: '@types/react': optional: true + '@mui/private-theming@6.4.8': + resolution: {integrity: sha512-sWwQoNSn6elsPTAtSqCf+w5aaGoh7AASURNmpy+QTTD/zwJ0Jgwt0ZaaP6mXq2IcgHxYnYloM/+vJgHPMkRKTQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@mui/styled-engine@6.4.6': resolution: {integrity: sha512-vSWYc9ZLX46be5gP+FCzWVn5rvDr4cXC5JBZwSIkYk9xbC7GeV+0kCvB8Q6XLFQJy+a62bbqtmdwS4Ghi9NBlQ==} engines: {node: '>=14.0.0'} @@ -820,6 +877,19 @@ packages: '@emotion/styled': optional: true + '@mui/styled-engine@6.4.8': + resolution: {integrity: sha512-oyjx1b1FvUCI85ZMO4trrjNxGm90eLN3Ohy0AP/SqK5gWvRQg1677UjNf7t6iETOKAleHctJjuq0B3aXO2gtmw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@mui/system@6.4.7': resolution: {integrity: sha512-7wwc4++Ak6tGIooEVA9AY7FhH2p9fvBMORT4vNLMAysH3Yus/9B9RYMbrn3ANgsOyvT3Z7nE+SP8/+3FimQmcg==} engines: {node: '>=14.0.0'} @@ -836,6 +906,22 @@ packages: '@types/react': optional: true + '@mui/system@6.4.8': + resolution: {integrity: sha512-gV7iBHoqlsIenU2BP0wq14BefRoZcASZ/4LeyuQglayBl+DfLX5rEd3EYR3J409V2EZpR0NOM1LATAGlNk2cyA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + '@mui/types@7.2.21': resolution: {integrity: sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==} peerDependencies: @@ -844,6 +930,14 @@ packages: '@types/react': optional: true + '@mui/types@7.2.24': + resolution: {integrity: sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@mui/utils@6.4.6': resolution: {integrity: sha512-43nZeE1pJF2anGafNydUcYFPtHwAqiBiauRtaMvurdrZI3YrUjHkAu43RBsxef7OFtJMXGiHFvq43kb7lig0sA==} engines: {node: '>=14.0.0'} @@ -854,6 +948,16 @@ packages: '@types/react': optional: true + '@mui/utils@6.4.8': + resolution: {integrity: sha512-C86gfiZ5BfZ51KqzqoHi1WuuM2QdSKoFhbkZeAfQRB+jCc4YNhhj11UXFVMMsqBgZ+Zy8IHNJW3M9Wj/LOwRXQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1676,6 +1780,9 @@ packages: resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} engines: {node: '>=12'} + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} @@ -2189,6 +2296,11 @@ packages: engines: {node: ^18 || >=20} hasBin: true + nanoid@5.1.4: + resolution: {integrity: sha512-GTFcMIDgR7tqji/LpSY8rtg464VnJl/j6ypoehYnuGb+Y8qZUdtKB8WVCXon0UEZgFDbuUxpIl//6FHLHgXSNA==} + engines: {node: ^18 || >=20} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -2550,6 +2662,12 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' + react-datepicker@8.2.1: + resolution: {integrity: sha512-1pyALWM9mTZ7DG7tfcApwBy2kkld9Kz/EI++LhPnoXJAASbvuq6fdsDfkoB3q1JrxF7vhghVmQ759H/rOwUNNw==} + peerDependencies: + react: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc + react-dom: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc + react-dom@19.0.0: resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} peerDependencies: @@ -2767,6 +2885,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + tailwind-merge@3.0.2: resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==} @@ -3432,6 +3553,31 @@ snapshots: '@eslint/core': 0.12.0 levn: 0.4.1 + '@floating-ui/core@1.6.9': + dependencies: + '@floating-ui/utils': 0.2.9 + + '@floating-ui/dom@1.6.13': + dependencies: + '@floating-ui/core': 1.6.9 + '@floating-ui/utils': 0.2.9 + + '@floating-ui/react-dom@2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@floating-ui/dom': 1.6.13 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@floating-ui/react@0.27.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@floating-ui/react-dom': 2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@floating-ui/utils': 0.2.9 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + tabbable: 6.2.0 + + '@floating-ui/utils@0.2.9': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -3479,7 +3625,7 @@ snapshots: '@emotion/css': 11.13.4 crypto-js: 4.2.0 eventemitter3: 5.0.1 - nanoid: 5.1.3 + nanoid: 5.1.4 rollup-plugin-dts: 6.1.1(rollup@4.34.7)(typescript@5.8.2) scheduler: 0.23.2 zustand: 4.5.5(@types/react@19.0.10)(immer@10.1.1)(react@19.0.0) @@ -3548,6 +3694,8 @@ snapshots: '@mui/core-downloads-tracker@6.4.7': {} + '@mui/core-downloads-tracker@6.4.8': {} + '@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 @@ -3569,6 +3717,27 @@ snapshots: '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) '@types/react': 19.0.10 + '@mui/material@6.4.8(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.0 + '@mui/core-downloads-tracker': 6.4.8 + '@mui/system': 6.4.8(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) + '@mui/types': 7.2.24(@types/react@19.0.10) + '@mui/utils': 6.4.8(@types/react@19.0.10)(react@19.0.0) + '@popperjs/core': 2.11.8 + '@types/react-transition-group': 4.4.12(@types/react@19.0.10) + clsx: 2.1.1 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-is: 19.0.0 + react-transition-group: 4.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) + '@types/react': 19.0.10 + '@mui/private-theming@6.4.6(@types/react@19.0.10)(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 @@ -3578,6 +3747,15 @@ snapshots: optionalDependencies: '@types/react': 19.0.10 + '@mui/private-theming@6.4.8(@types/react@19.0.10)(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.0 + '@mui/utils': 6.4.8(@types/react@19.0.10)(react@19.0.0) + prop-types: 15.8.1 + react: 19.0.0 + optionalDependencies: + '@types/react': 19.0.10 + '@mui/styled-engine@6.4.6(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 @@ -3591,6 +3769,19 @@ snapshots: '@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0) '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) + '@mui/styled-engine@6.4.8(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.0 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 + '@emotion/sheet': 1.4.0 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 19.0.0 + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) + '@mui/system@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 @@ -3607,10 +3798,30 @@ snapshots: '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) '@types/react': 19.0.10 + '@mui/system@6.4.8(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.0 + '@mui/private-theming': 6.4.8(@types/react@19.0.10)(react@19.0.0) + '@mui/styled-engine': 6.4.8(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(react@19.0.0) + '@mui/types': 7.2.24(@types/react@19.0.10) + '@mui/utils': 6.4.8(@types/react@19.0.10)(react@19.0.0) + clsx: 2.1.1 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 19.0.0 + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) + '@types/react': 19.0.10 + '@mui/types@7.2.21(@types/react@19.0.10)': optionalDependencies: '@types/react': 19.0.10 + '@mui/types@7.2.24(@types/react@19.0.10)': + optionalDependencies: + '@types/react': 19.0.10 + '@mui/utils@6.4.6(@types/react@19.0.10)(react@19.0.0)': dependencies: '@babel/runtime': 7.26.0 @@ -3623,6 +3834,18 @@ snapshots: optionalDependencies: '@types/react': 19.0.10 + '@mui/utils@6.4.8(@types/react@19.0.10)(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.0 + '@mui/types': 7.2.24(@types/react@19.0.10) + '@types/prop-types': 15.7.14 + clsx: 2.1.1 + prop-types: 15.8.1 + react: 19.0.0 + react-is: 19.0.0 + optionalDependencies: + '@types/react': 19.0.10 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -4187,7 +4410,7 @@ snapshots: dependencies: color-convert: 2.0.1 - antd@5.24.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + antd@5.24.3(date-fns@4.1.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@ant-design/colors': 7.2.0 '@ant-design/cssinjs': 1.23.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -4219,7 +4442,7 @@ snapshots: rc-motion: 2.9.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) rc-notification: 5.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) rc-pagination: 5.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - rc-picker: 4.11.3(dayjs@1.11.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + rc-picker: 4.11.3(date-fns@4.1.0)(dayjs@1.11.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) rc-progress: 4.0.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) rc-rate: 2.13.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) rc-resize-observer: 1.4.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -4542,6 +4765,8 @@ snapshots: d3-transition: 3.0.1(d3-selection@3.0.0) d3-zoom: 3.0.0 + date-fns@4.1.0: {} + dayjs@1.11.13: {} debug@4.3.7: @@ -5062,6 +5287,8 @@ snapshots: nanoid@5.1.3: {} + nanoid@5.1.4: {} + natural-compare@1.4.0: {} node-forge@1.3.1: {} @@ -5329,7 +5556,7 @@ snapshots: react: 19.0.0 react-dom: 19.0.0(react@19.0.0) - rc-picker@4.11.3(dayjs@1.11.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + rc-picker@4.11.3(date-fns@4.1.0)(dayjs@1.11.13)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@babel/runtime': 7.26.0 '@rc-component/trigger': 2.2.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -5340,6 +5567,7 @@ snapshots: react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: + date-fns: 4.1.0 dayjs: 1.11.13 rc-progress@4.0.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0): @@ -5505,6 +5733,14 @@ snapshots: react: 19.0.0 react-dom: 19.0.0(react@19.0.0) + react-datepicker@8.2.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + '@floating-ui/react': 0.27.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + clsx: 2.1.1 + date-fns: 4.1.0 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-dom@19.0.0(react@19.0.0): dependencies: react: 19.0.0 @@ -5737,6 +5973,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + tabbable@6.2.0: {} + tailwind-merge@3.0.2: {} tailwindcss-animate@1.0.7(tailwindcss@4.0.12):