diff --git a/web/app/components/app/configuration/config-vision/index.tsx b/web/app/components/app/configuration/config-vision/index.tsx index 50af0f7e9d..2057976a83 100644 --- a/web/app/components/app/configuration/config-vision/index.tsx +++ b/web/app/components/app/configuration/config-vision/index.tsx @@ -15,7 +15,7 @@ import Switch from '@/app/components/base/switch' import { SupportUploadFileTypes } from '@/app/components/workflow/types' import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card' import { Resolution } from '@/types/app' -import { noop } from 'lodash' +import { noop } from 'lodash-es' import cn from '@/utils/classnames' const ConfigVision: FC = () => { diff --git a/web/app/components/base/alert.tsx b/web/app/components/base/alert.tsx new file mode 100644 index 0000000000..1ea329e380 --- /dev/null +++ b/web/app/components/base/alert.tsx @@ -0,0 +1,59 @@ +import { + memo, +} from 'react' +import { + RiCloseLine, + RiInformation2Fill, +} from '@remixicon/react' +import { cva } from 'class-variance-authority' +import cn from '@/utils/classnames' + +type Props = { + type?: 'info' + message: string + onHide: () => void + className?: string +} +const bgVariants = cva( + '', + { + variants: { + type: { + info: 'from-components-badge-status-light-normal-halo to-background-gradient-mask-transparent', + }, + }, + }, +) +const Alert: React.FC = ({ + type = 'info', + message, + onHide, + className, +}) => { + return ( +
+
+
+
+
+ +
+
+
+ {message} +
+
+
+ +
+
+
+ ) +} + +export default memo(Alert) diff --git a/web/app/components/base/chat/chat/chat-input-area/operation.tsx b/web/app/components/base/chat/chat/chat-input-area/operation.tsx index b13d23f7fa..f080157345 100644 --- a/web/app/components/base/chat/chat/chat-input-area/operation.tsx +++ b/web/app/components/base/chat/chat/chat-input-area/operation.tsx @@ -13,7 +13,7 @@ import ActionButton from '@/app/components/base/action-button' import { FileUploaderInChatInput } from '@/app/components/base/file-uploader' import type { FileUpload } from '@/app/components/base/features/types' import cn from '@/utils/classnames' -import { noop } from 'lodash' +import { noop } from 'lodash-es' type OperationProps = { readonly?: boolean diff --git a/web/app/components/explore/try-app/app/text-generation.tsx b/web/app/components/explore/try-app/app/text-generation.tsx index 866b935df4..a0e8ffa660 100644 --- a/web/app/components/explore/try-app/app/text-generation.tsx +++ b/web/app/components/explore/try-app/app/text-generation.tsx @@ -15,11 +15,12 @@ import { userInputsFormToPromptVariables } from '@/utils/model-config' import type { VisionFile, VisionSettings } from '@/types/app' import { Resolution, TransferMethod } from '@/types/app' import { useBoolean } from 'ahooks' -import { noop } from 'lodash' +import { noop } from 'lodash-es' import type { Task } from '../../../share/text-generation/types' import Res from '@/app/components/share/text-generation/result' import { AppSourceType } from '@/service/share' import { TaskStatus } from '@/app/components/share/text-generation/types' +import Alert from '@/app/components/base/alert' type Props = { appId: string @@ -144,19 +145,13 @@ const TextGeneration: FC = ({
+ {renderRes()}
@@ -220,15 +215,7 @@ const TextGeneration: FC = ({ {/* Result */} -
+
{!isPC && (
= ({ {isLoading ? (
diff --git a/web/i18n-config/check-i18n-sync.js b/web/i18n-config/check-i18n-sync.js index e67c567f49..8935e1d58b 100644 --- a/web/i18n-config/check-i18n-sync.js +++ b/web/i18n-config/check-i18n-sync.js @@ -2,19 +2,19 @@ const fs = require('fs') const path = require('path') -const { camelCase } = require('lodash') +const { camelCase } = require('lodash-es') // Import the NAMESPACES array from i18next-config.ts function getNamespacesFromConfig() { const configPath = path.join(__dirname, 'i18next-config.ts') const configContent = fs.readFileSync(configPath, 'utf8') - + // Extract NAMESPACES array using regex const namespacesMatch = configContent.match(/const NAMESPACES = \[([\s\S]*?)\]/) if (!namespacesMatch) { throw new Error('Could not find NAMESPACES array in i18next-config.ts') } - + // Parse the namespaces const namespacesStr = namespacesMatch[1] const namespaces = namespacesStr @@ -22,25 +22,25 @@ function getNamespacesFromConfig() { .map(line => line.trim()) .filter(line => line.startsWith("'") || line.startsWith('"')) .map(line => line.slice(1, -1)) // Remove quotes - + return namespaces } function getNamespacesFromTypes() { const typesPath = path.join(__dirname, '../types/i18n.d.ts') - + if (!fs.existsSync(typesPath)) { return null } - + const typesContent = fs.readFileSync(typesPath, 'utf8') - + // Extract namespaces from Messages type const messagesMatch = typesContent.match(/export type Messages = \{([\s\S]*?)\}/) if (!messagesMatch) { return null } - + // Parse the properties const propertiesStr = messagesMatch[1] const properties = propertiesStr @@ -49,66 +49,66 @@ function getNamespacesFromTypes() { .filter(line => line.includes(':')) .map(line => line.split(':')[0].trim()) .filter(prop => prop.length > 0) - + return properties } function main() { try { console.log('πŸ” Checking i18n types synchronization...') - + // Get namespaces from config const configNamespaces = getNamespacesFromConfig() console.log(`πŸ“¦ Found ${configNamespaces.length} namespaces in config`) - + // Convert to camelCase for comparison const configCamelCase = configNamespaces.map(ns => camelCase(ns)).sort() - + // Get namespaces from type definitions const typeNamespaces = getNamespacesFromTypes() - + if (!typeNamespaces) { console.error('❌ Type definitions file not found or invalid') console.error(' Run: pnpm run gen:i18n-types') process.exit(1) } - + console.log(`πŸ”§ Found ${typeNamespaces.length} namespaces in types`) - + const typeCamelCase = typeNamespaces.sort() - + // Compare arrays const configSet = new Set(configCamelCase) const typeSet = new Set(typeCamelCase) - + // Find missing in types const missingInTypes = configCamelCase.filter(ns => !typeSet.has(ns)) - + // Find extra in types const extraInTypes = typeCamelCase.filter(ns => !configSet.has(ns)) - + let hasErrors = false - + if (missingInTypes.length > 0) { hasErrors = true console.error('❌ Missing in type definitions:') missingInTypes.forEach(ns => console.error(` - ${ns}`)) } - + if (extraInTypes.length > 0) { hasErrors = true console.error('❌ Extra in type definitions:') extraInTypes.forEach(ns => console.error(` - ${ns}`)) } - + if (hasErrors) { console.error('\nπŸ’‘ To fix synchronization issues:') console.error(' Run: pnpm run gen:i18n-types') process.exit(1) } - + console.log('βœ… i18n types are synchronized') - + } catch (error) { console.error('❌ Error:', error.message) process.exit(1) @@ -117,4 +117,4 @@ function main() { if (require.main === module) { main() -} \ No newline at end of file +} diff --git a/web/i18n-config/generate-i18n-types.js b/web/i18n-config/generate-i18n-types.js index ba34446962..c1ca0b59be 100644 --- a/web/i18n-config/generate-i18n-types.js +++ b/web/i18n-config/generate-i18n-types.js @@ -2,19 +2,19 @@ const fs = require('fs') const path = require('path') -const { camelCase } = require('lodash') +const { camelCase } = require('lodash-es') // Import the NAMESPACES array from i18next-config.ts function getNamespacesFromConfig() { const configPath = path.join(__dirname, 'i18next-config.ts') const configContent = fs.readFileSync(configPath, 'utf8') - + // Extract NAMESPACES array using regex const namespacesMatch = configContent.match(/const NAMESPACES = \[([\s\S]*?)\]/) if (!namespacesMatch) { throw new Error('Could not find NAMESPACES array in i18next-config.ts') } - + // Parse the namespaces const namespacesStr = namespacesMatch[1] const namespaces = namespacesStr @@ -22,7 +22,7 @@ function getNamespacesFromConfig() { .map(line => line.trim()) .filter(line => line.startsWith("'") || line.startsWith('"')) .map(line => line.slice(1, -1)) // Remove quotes - + return namespaces } @@ -90,40 +90,40 @@ declare module 'i18next' { function main() { const args = process.argv.slice(2) const checkMode = args.includes('--check') - + try { console.log('πŸ“¦ Generating i18n type definitions...') - + // Get namespaces from config const namespaces = getNamespacesFromConfig() console.log(`βœ… Found ${namespaces.length} namespaces`) - + // Generate type definitions const typeDefinitions = generateTypeDefinitions(namespaces) - + const outputPath = path.join(__dirname, '../types/i18n.d.ts') - + if (checkMode) { // Check mode: compare with existing file if (!fs.existsSync(outputPath)) { console.error('❌ Type definitions file does not exist') process.exit(1) } - + const existingContent = fs.readFileSync(outputPath, 'utf8') if (existingContent.trim() !== typeDefinitions.trim()) { console.error('❌ Type definitions are out of sync') console.error(' Run: pnpm run gen:i18n-types') process.exit(1) } - + console.log('βœ… Type definitions are in sync') } else { // Generate mode: write file fs.writeFileSync(outputPath, typeDefinitions) console.log(`βœ… Generated type definitions: ${outputPath}`) } - + } catch (error) { console.error('❌ Error:', error.message) process.exit(1) @@ -132,4 +132,4 @@ function main() { if (require.main === module) { main() -} \ No newline at end of file +}