Compare commits
	
		
			42 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 74c1730425 | ||
|  | 94bed7fcce | ||
|  | 8abf2a7bfc | ||
|  | ee659eaa03 | ||
|  | 7c5db0848e | ||
|  | 4b43f720e9 | ||
|  | 766b5164b8 | ||
|  | 7868ca9f42 | ||
|  | 0411742864 | ||
|  | 9831ac5a10 | ||
|  | 91c6fb9249 | ||
|  | c155013668 | ||
|  | 1b0f293c87 | ||
|  | df2dc03aa0 | ||
|  | 205d431c89 | ||
|  | 0abe18cdf9 | ||
|  | a151f56b5d | ||
|  | 2b6b733261 | ||
|  | b56b04925c | ||
|  | 635fb53c9f | ||
|  | d6659795bc | ||
|  | 348f80568e | ||
|  | 5f9c74a9ad | ||
|  | 5409288388 | ||
|  | 2309306ef5 | ||
|  | 3574cecc7c | ||
|  | 29b8edc051 | ||
|  | 5fc10a7e64 | ||
|  | 807cd22e0c | ||
|  | 03772f6b4f | ||
|  | 885eb719de | ||
|  | 94656ec7a5 | ||
|  | a0e966b64f | ||
|  | a8fe491c1b | ||
|  | ddeef3b134 | ||
|  | d45677e92d | ||
|  | 9c7d03c285 | ||
|  | be1b109f23 | ||
|  | 05eaf85a3d | ||
|  | 53f443d452 | ||
|  | 134c62f931 | ||
|  | 4bb4766e1a | 
| @@ -1,29 +0,0 @@ | ||||
| module.exports = { | ||||
|     root: true, | ||||
|     env: { browser: true, es2020: true }, | ||||
|     extends: [ | ||||
|         'eslint:recommended', | ||||
|         'plugin:react/recommended', | ||||
|         'plugin:@typescript-eslint/recommended', | ||||
|         'plugin:react-hooks/recommended', | ||||
|         'plugin:css-modules/recommended', | ||||
|         'plugin:tailwindcss/recommended', | ||||
|         'plugin:prettier/recommended', | ||||
|         // 'plugin:jsx-a11y/recommended', | ||||
|     ], | ||||
|     ignorePatterns: ['dist', '.eslintrc.cjs'], | ||||
|     parser: '@typescript-eslint/parser', | ||||
|     plugins: ['react-refresh', 'css-modules', 'tailwindcss', 'jsx-a11y'], | ||||
|     rules: { | ||||
|         '@typescript-eslint/consistent-type-imports': 'error', | ||||
|         'react-refresh/only-export-components': [ | ||||
|             'warn', | ||||
|             { allowConstantExport: true }, | ||||
|         ], | ||||
|         'react/no-unescaped-entities': 'off', | ||||
|         'react/prop-types': 'off', | ||||
|     }, | ||||
|     settings: { | ||||
|         react: { version: 'detect' }, | ||||
|     }, | ||||
| }; | ||||
							
								
								
									
										65
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						| @@ -1,5 +1,70 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## [1.6.0](https://github.com/chartdb/chartdb/compare/v1.5.1...v1.6.0) (2025-01-02) | ||||
|  | ||||
|  | ||||
| ### Features | ||||
|  | ||||
| * **view-menu:** add toggle for mini map visibility ([#496](https://github.com/chartdb/chartdb/issues/496)) ([#505](https://github.com/chartdb/chartdb/issues/505)) ([8abf2a7](https://github.com/chartdb/chartdb/commit/8abf2a7bfcc36d39e60ac133b0e5e569de1bbc72)) | ||||
|  | ||||
|  | ||||
| ### Bug Fixes | ||||
|  | ||||
| * add loadDiagramFromData logic to chartdb provider ([#513](https://github.com/chartdb/chartdb/issues/513)) ([ee659ea](https://github.com/chartdb/chartdb/commit/ee659eaa038a94ee13801801e84152df4d79683d)) | ||||
| * **dependency:** upgrade react query to v7 - clean console warnings ([#504](https://github.com/chartdb/chartdb/issues/504)) ([7c5db08](https://github.com/chartdb/chartdb/commit/7c5db0848e49dfdb7e7120f77003d1e37f8d71b0)) | ||||
| * **i18n:** translation/Arabic ([#509](https://github.com/chartdb/chartdb/issues/509)) ([4b43f72](https://github.com/chartdb/chartdb/commit/4b43f720e90e49d5461e68d188e3865000f52497)) | ||||
|  | ||||
| ## [1.5.1](https://github.com/chartdb/chartdb/compare/v1.5.0...v1.5.1) (2024-12-15) | ||||
|  | ||||
|  | ||||
| ### Bug Fixes | ||||
|  | ||||
| * **export:** fix SQL server field.nullable type to boolean ([#486](https://github.com/chartdb/chartdb/issues/486)) ([a151f56](https://github.com/chartdb/chartdb/commit/a151f56b5d950e0b5cc54363684ada95889024b3)) | ||||
| * **readme:** Update README.md - add CockroachDB ([#482](https://github.com/chartdb/chartdb/issues/482)) ([2b6b733](https://github.com/chartdb/chartdb/commit/2b6b73326155f18d6d56779c0657a3506e2d2cde)) | ||||
|  | ||||
| ## [1.5.0](https://github.com/chartdb/chartdb/compare/v1.4.0...v1.5.0) (2024-12-11) | ||||
|  | ||||
|  | ||||
| ### Features | ||||
|  | ||||
| * **CockroachDB:** Add CockroachDB support ([#472](https://github.com/chartdb/chartdb/issues/472)) ([5409288](https://github.com/chartdb/chartdb/commit/54092883883b135f6ace51d86754b1df76603d30)) | ||||
| * **i18n:** translate share and dialog sections in Indonesian locale files ([#468](https://github.com/chartdb/chartdb/issues/468)) ([3574cec](https://github.com/chartdb/chartdb/commit/3574cecc7c73dcab404b82115d20e1ad0cd26b37)) | ||||
|  | ||||
|  | ||||
| ### Bug Fixes | ||||
|  | ||||
| * **core:** fix update diagram id ([#477](https://github.com/chartdb/chartdb/issues/477)) ([348f805](https://github.com/chartdb/chartdb/commit/348f80568e0f686ee478147fdc43a5d43b5c1ebb)) | ||||
| * **dialogs:** fix footer position on dialogs ([#470](https://github.com/chartdb/chartdb/issues/470)) ([2309306](https://github.com/chartdb/chartdb/commit/2309306ef590783b00a2489209092107dd9a3788)) | ||||
| * **sql-server import:** nullable should be boolean instead of string ([#480](https://github.com/chartdb/chartdb/issues/480)) ([635fb53](https://github.com/chartdb/chartdb/commit/635fb53c9f7ebd1e5ef4d9274af041edc08f04c3)) | ||||
|  | ||||
| ## [1.4.0](https://github.com/chartdb/chartdb/compare/v1.3.1...v1.4.0) (2024-12-02) | ||||
|  | ||||
|  | ||||
| ### Features | ||||
|  | ||||
| * **add templates:** add six more templates  ([#452](https://github.com/chartdb/chartdb/issues/452)) ([be1b109](https://github.com/chartdb/chartdb/commit/be1b109f23e62df4cc63fa8914c2754f7809cc08)) | ||||
| * **add templates:** add six more templates (django-axes, laravel-activitylog, octobox, pay-rails, pixelfed, polr) ([#460](https://github.com/chartdb/chartdb/issues/460)) ([03772f6](https://github.com/chartdb/chartdb/commit/03772f6b4f99f9c4350356aa0f2a4666f4f1794d)) | ||||
| * **add templates:** add six more templates (reversion, screeenly, staytus, deployer, devise, talk) ([#457](https://github.com/chartdb/chartdb/issues/457)) ([ddeef3b](https://github.com/chartdb/chartdb/commit/ddeef3b134efa893e1c1e15e2f87c27157200e2d)) | ||||
| * **clickhouse:** add ClickHouse support ([#463](https://github.com/chartdb/chartdb/issues/463)) ([807cd22](https://github.com/chartdb/chartdb/commit/807cd22e0c739f339fa07fe1d2f043c5411ae41f)) | ||||
| * **i18n:** Added bangla translations ([#432](https://github.com/chartdb/chartdb/issues/432)) ([885eb71](https://github.com/chartdb/chartdb/commit/885eb719de577c2652fbed1ed287f38fcc98c148)) | ||||
| * **side-panel:** Add functionality of order tables by drag & drop ([#425](https://github.com/chartdb/chartdb/issues/425)) ([a0e966b](https://github.com/chartdb/chartdb/commit/a0e966b64f8070d4595d47b2fb39e8bbf427b794)) | ||||
|  | ||||
|  | ||||
| ### Bug Fixes | ||||
|  | ||||
| * **clipboard:** defensive for navigator clipboard ([#462](https://github.com/chartdb/chartdb/issues/462)) ([5fc10a7](https://github.com/chartdb/chartdb/commit/5fc10a7e649fc5877bb297b519b1b6a8b81f1323)) | ||||
| * **import-database:** update database type after importing into an existing generic diagra ([#456](https://github.com/chartdb/chartdb/issues/456)) ([a8fe491](https://github.com/chartdb/chartdb/commit/a8fe491c1b5a30d9f4144cefa9111dd3dfd5df1a)) | ||||
| * **Last Saved:** Translate the "last saved" relative date message ([#400](https://github.com/chartdb/chartdb/issues/400)) ([d45677e](https://github.com/chartdb/chartdb/commit/d45677e92d72efc6cea8f865ce46f0be6ec9961f)) | ||||
| * **mariadb-types:** Add uuid data type ([#459](https://github.com/chartdb/chartdb/issues/459)) ([94656ec](https://github.com/chartdb/chartdb/commit/94656ec7a5435c2da262fb3bc6a6d381d554b0c1)) | ||||
| * window type ([#454](https://github.com/chartdb/chartdb/issues/454)) ([9c7d03c](https://github.com/chartdb/chartdb/commit/9c7d03c285ff6f818eef3199c9b7a530d03a1fec)) | ||||
|  | ||||
| ## [1.3.1](https://github.com/chartdb/chartdb/compare/v1.3.0...v1.3.1) (2024-11-26) | ||||
|  | ||||
|  | ||||
| ### Bug Fixes | ||||
|  | ||||
| * **docker:** make OPENAI_API_KEY optional in docker run ([#448](https://github.com/chartdb/chartdb/issues/448)) ([4bb4766](https://github.com/chartdb/chartdb/commit/4bb4766e1ac8d69e138668eb8a46de5affe62ceb)) | ||||
|  | ||||
| ## [1.3.0](https://github.com/chartdb/chartdb/compare/v1.2.0...v1.3.0) (2024-11-25) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -16,9 +16,11 @@ RUN npm run build | ||||
| FROM nginx:stable-alpine AS production | ||||
|  | ||||
| COPY --from=builder /usr/src/app/dist /usr/share/nginx/html | ||||
| COPY ./default.conf /etc/nginx/conf.d/default.conf | ||||
| COPY ./default.conf.template /etc/nginx/conf.d/default.conf.template | ||||
| COPY entrypoint.sh /entrypoint.sh | ||||
| RUN chmod +x /entrypoint.sh | ||||
|  | ||||
| # Expose the default port for the Nginx web server | ||||
| EXPOSE 80 | ||||
|  | ||||
| CMD ["nginx", "-g", "daemon off;"] | ||||
| ENTRYPOINT ["/entrypoint.sh"] | ||||
|   | ||||
							
								
								
									
										13
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @@ -68,6 +68,7 @@ ChartDB is currently in Public Beta. Star and watch this repository to get notif | ||||
| -   ✅ SQL Server | ||||
| -   ✅ MariaDB | ||||
| -   ✅ SQLite | ||||
| -   ✅ CockroachDB | ||||
| -   ✅ ClickHouse | ||||
|  | ||||
| ## Getting Started | ||||
| @@ -95,11 +96,15 @@ npm install | ||||
| VITE_OPENAI_API_KEY=<YOUR_OPEN_AI_KEY> npm run build | ||||
| ``` | ||||
|  | ||||
| ### Running the Docker Container | ||||
|  | ||||
| ### Run the Docker Container | ||||
| ```bash | ||||
| docker build -t chartdb . (If you want AI capabilities, use `docker build --build-arg VITE_OPENAI_API_KEY=<YOUR_OPEN_AI_KEY> -t chartdb .`) | ||||
| docker run -p 8080:80 chartdb | ||||
| docker run -e OPENAI_API_KEY=<YOUR_OPEN_AI_KEY> -p 8080:80 ghcr.io/chartdb/chartdb:latest | ||||
| ``` | ||||
|  | ||||
| #### Build and Run locally | ||||
| ```bash | ||||
| docker build -t chartdb . | ||||
| docker run -e OPENAI_API_KEY=<YOUR_OPEN_AI_KEY> -p 8080:80 chartdb | ||||
| ``` | ||||
|  | ||||
| Open your browser and navigate to `http://localhost:8080`. | ||||
|   | ||||
| @@ -8,6 +8,11 @@ server { | ||||
| 	    try_files  $uri $uri/ /index.html; | ||||
|     } | ||||
| 
 | ||||
|     location /config.js { | ||||
|         default_type application/javascript; | ||||
|         return 200 "window.env = { OPENAI_API_KEY: \"$OPENAI_API_KEY\" };"; | ||||
|     } | ||||
| 
 | ||||
|     error_page   500 502 503 504  /50x.html; | ||||
|     location = /50x.html { | ||||
|         root   /usr/share/nginx/html; | ||||
							
								
								
									
										7
									
								
								entrypoint.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,7 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| # Replace placeholders in nginx.conf | ||||
| envsubst '${OPENAI_API_KEY}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf | ||||
|  | ||||
| # Start Nginx | ||||
| nginx -g "daemon off;" | ||||
							
								
								
									
										77
									
								
								eslint.config.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,77 @@ | ||||
| import { fixupConfigRules, fixupPluginRules } from '@eslint/compat'; | ||||
| import reactRefresh from 'eslint-plugin-react-refresh'; | ||||
| import cssModules from 'eslint-plugin-css-modules'; | ||||
| import tailwindcss from 'eslint-plugin-tailwindcss'; | ||||
| import jsxA11Y from 'eslint-plugin-jsx-a11y'; | ||||
| import globals from 'globals'; | ||||
| import tsParser from '@typescript-eslint/parser'; | ||||
| import path from 'node:path'; | ||||
| import { fileURLToPath } from 'node:url'; | ||||
| import js from '@eslint/js'; | ||||
| import { FlatCompat } from '@eslint/eslintrc'; | ||||
|  | ||||
| const __filename = fileURLToPath(import.meta.url); | ||||
| const __dirname = path.dirname(__filename); | ||||
| const compat = new FlatCompat({ | ||||
|     baseDirectory: __dirname, | ||||
|     recommendedConfig: js.configs.recommended, | ||||
|     allConfig: js.configs.all, | ||||
| }); | ||||
|  | ||||
| export default [ | ||||
|     { | ||||
|         ignores: ['**/dist', '**/.eslintrc.cjs', '**/tailwind.config.js'], | ||||
|         // files: ['**/*.ts', '**/*.tsx'], | ||||
|     }, | ||||
|     ...fixupConfigRules( | ||||
|         compat.extends( | ||||
|             'eslint:recommended', | ||||
|             'plugin:react/recommended', | ||||
|             'plugin:@typescript-eslint/recommended', | ||||
|             'plugin:react-hooks/recommended', | ||||
|             'plugin:css-modules/recommended', | ||||
|             'plugin:tailwindcss/recommended', | ||||
|             'plugin:prettier/recommended' | ||||
|         ) | ||||
|     ), | ||||
|     { | ||||
|         plugins: { | ||||
|             'react-refresh': reactRefresh, | ||||
|             'css-modules': fixupPluginRules(cssModules), | ||||
|             tailwindcss: fixupPluginRules(tailwindcss), | ||||
|             'jsx-a11y': jsxA11Y, | ||||
|         }, | ||||
|  | ||||
|         languageOptions: { | ||||
|             globals: { | ||||
|                 ...globals.browser, | ||||
|             }, | ||||
|  | ||||
|             parser: tsParser, | ||||
|             // parserOptions: { | ||||
|             //     project: './tsconfig.json', | ||||
|             // }, | ||||
|         }, | ||||
|  | ||||
|         settings: { | ||||
|             react: { | ||||
|                 version: 'detect', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         rules: { | ||||
|             '@typescript-eslint/consistent-type-imports': 'error', | ||||
|  | ||||
|             'react-refresh/only-export-components': [ | ||||
|                 'warn', | ||||
|                 { | ||||
|                     allowConstantExport: true, | ||||
|                 }, | ||||
|             ], | ||||
|  | ||||
|             'react/no-unescaped-entities': 'off', | ||||
|             'react/prop-types': 'off', | ||||
|             '@typescript-eslint/no-empty-object-type': 'off', | ||||
|         }, | ||||
|     }, | ||||
| ]; | ||||
| @@ -12,6 +12,7 @@ | ||||
|             href="https://fonts.googleapis.com/css2?family=Raleway:ital,wght@0,100..900;1,100..900&display=swap" | ||||
|             rel="stylesheet" | ||||
|         /> | ||||
|         <script src="/config.js"></script> | ||||
|         <script | ||||
|             src="https://cdn.usefathom.com/script.js" | ||||
|             data-site="PRHIVBNN" | ||||
|   | ||||
							
								
								
									
										21108
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
							
								
								
									
										18
									
								
								package.json
									
									
									
									
									
								
							
							
						
						| @@ -1,12 +1,12 @@ | ||||
| { | ||||
|     "name": "chartdb", | ||||
|     "private": true, | ||||
|     "version": "1.3.0", | ||||
|     "version": "1.6.0", | ||||
|     "type": "module", | ||||
|     "scripts": { | ||||
|         "dev": "vite", | ||||
|         "build": "npm run lint && tsc -b && vite build", | ||||
|         "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", | ||||
|         "lint": "eslint . --report-unused-disable-directives --max-warnings 0", | ||||
|         "lint:fix": "npm run lint -- --fix", | ||||
|         "preview": "vite preview", | ||||
|         "prepare": "husky" | ||||
| @@ -60,7 +60,7 @@ | ||||
|         "react-i18next": "^15.0.1", | ||||
|         "react-resizable-panels": "^2.0.22", | ||||
|         "react-responsive": "^10.0.0", | ||||
|         "react-router-dom": "^6.26.0", | ||||
|         "react-router-dom": "^7.1.1", | ||||
|         "react-use": "^17.5.1", | ||||
|         "tailwind-merge": "^2.4.0", | ||||
|         "tailwindcss-animate": "^1.0.7", | ||||
| @@ -69,22 +69,26 @@ | ||||
|         "zod": "^3.23.8" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@eslint/compat": "^1.2.4", | ||||
|         "@eslint/eslintrc": "^3.2.0", | ||||
|         "@eslint/js": "^9.16.0", | ||||
|         "@types/node": "^22.1.0", | ||||
|         "@types/react": "^18.3.3", | ||||
|         "@types/react-dom": "^18.3.0", | ||||
|         "@typescript-eslint/eslint-plugin": "^7.15.0", | ||||
|         "@typescript-eslint/parser": "^7.15.0", | ||||
|         "@typescript-eslint/eslint-plugin": "^8.18.0", | ||||
|         "@typescript-eslint/parser": "^8.18.0", | ||||
|         "@vitejs/plugin-react": "^4.3.1", | ||||
|         "autoprefixer": "^10.4.20", | ||||
|         "eslint": "^8.57.0", | ||||
|         "eslint": "^9.16.0", | ||||
|         "eslint-config-prettier": "^9.1.0", | ||||
|         "eslint-plugin-css-modules": "^2.12.0", | ||||
|         "eslint-plugin-jsx-a11y": "^6.9.0", | ||||
|         "eslint-plugin-prettier": "^5.2.1", | ||||
|         "eslint-plugin-react": "^7.35.0", | ||||
|         "eslint-plugin-react-hooks": "^4.6.2", | ||||
|         "eslint-plugin-react-hooks": "^5.1.0", | ||||
|         "eslint-plugin-react-refresh": "^0.4.7", | ||||
|         "eslint-plugin-tailwindcss": "^3.17.4", | ||||
|         "globals": "^15.13.0", | ||||
|         "husky": "^9.1.5", | ||||
|         "postcss": "^8.4.40", | ||||
|         "prettier": "^3.3.3", | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								public/buckle-animated.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 404 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/buckle.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 28 KiB | 
							
								
								
									
										0
									
								
								public/config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								src/assets/clickhouse_logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/clickhouse_logo_2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/clickhouse_logo_dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/cockroachdb_logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 8.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/cockroachdb_logo_2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 270 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/cockroachdb_logo_dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 20 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/cachet-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 447 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/cachet-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 486 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/canvas-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 346 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/canvas-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 379 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/deployer-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 424 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/deployer-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 497 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/devise-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 207 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/devise-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 231 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/django-axes-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 250 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/django-axes-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 264 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/doorkeeper-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 288 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/doorkeeper-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 319 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/flipper-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 189 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/flipper-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 207 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/laravel-activitylog-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 198 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/laravel-activitylog-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 217 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/octobox-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 352 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/octobox-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 382 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/orchid-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 303 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/orchid-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 340 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/pay-rails-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 352 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/pay-rails-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 371 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/pixelfed-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 593 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/pixelfed-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 687 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/polr-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 246 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/polr-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 278 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/reversion-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 229 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/reversion-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 266 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/screeenly-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 251 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/screeenly-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 266 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/staytus-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 424 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/staytus-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 471 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/taggit-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 169 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/taggit-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 184 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/talk-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 229 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/talk-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 253 KiB | 
| @@ -3,6 +3,7 @@ import React, { lazy, Suspense, useCallback, useEffect } from 'react'; | ||||
| import { Spinner } from '../spinner/spinner'; | ||||
| import { useTheme } from '@/hooks/use-theme'; | ||||
| import { useMonaco } from '@monaco-editor/react'; | ||||
| import { useToast } from '@/components/toast/use-toast'; | ||||
| import { Button } from '../button/button'; | ||||
| import { Copy, CopyCheck } from 'lucide-react'; | ||||
| import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip/tooltip'; | ||||
| @@ -38,6 +39,7 @@ export const CodeSnippet: React.FC<CodeSnippetProps> = React.memo( | ||||
|         const { t } = useTranslation(); | ||||
|         const monaco = useMonaco(); | ||||
|         const { effectiveTheme } = useTheme(); | ||||
|         const { toast } = useToast(); | ||||
|         const [isCopied, setIsCopied] = React.useState(false); | ||||
|         const [tooltipOpen, setTooltipOpen] = React.useState(false); | ||||
|  | ||||
| @@ -66,10 +68,32 @@ export const CodeSnippet: React.FC<CodeSnippetProps> = React.memo( | ||||
|             } | ||||
|         }, [code, monaco, autoScroll]); | ||||
|  | ||||
|         const copyToClipboard = useCallback(() => { | ||||
|             navigator.clipboard.writeText(code); | ||||
|             setIsCopied(true); | ||||
|         }, [code]); | ||||
|         const copyToClipboard = useCallback(async () => { | ||||
|             if (!navigator?.clipboard) { | ||||
|                 toast({ | ||||
|                     title: t('copy_to_clipboard_toast.unsupported.title'), | ||||
|                     variant: 'destructive', | ||||
|                     description: t( | ||||
|                         'copy_to_clipboard_toast.unsupported.description' | ||||
|                     ), | ||||
|                 }); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 await navigator.clipboard.writeText(code); | ||||
|                 setIsCopied(true); | ||||
|             } catch { | ||||
|                 setIsCopied(false); | ||||
|                 toast({ | ||||
|                     title: t('copy_to_clipboard_toast.failed.title'), | ||||
|                     variant: 'destructive', | ||||
|                     description: t( | ||||
|                         'copy_to_clipboard_toast.failed.description' | ||||
|                     ), | ||||
|                 }); | ||||
|             } | ||||
|         }, [code, t, toast]); | ||||
|  | ||||
|         return ( | ||||
|             <div | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import React from 'react'; | ||||
| import type { Diagram } from '@/lib/domain/diagram'; | ||||
| import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip/tooltip'; | ||||
| import type { DatabaseEdition } from '@/lib/domain/database-edition'; | ||||
| import { | ||||
|     databaseEditionToImageMap, | ||||
|     databaseEditionToLabelMap, | ||||
| @@ -9,39 +9,44 @@ import { | ||||
|     databaseSecondaryLogoMap, | ||||
|     databaseTypeToLabelMap, | ||||
| } from '@/lib/databases'; | ||||
| import type { DatabaseType } from '@/lib/domain/database-type'; | ||||
| import { cn } from '@/lib/utils'; | ||||
|  | ||||
| export interface DiagramIconProps { | ||||
|     diagram: Diagram; | ||||
| export interface DiagramIconProps | ||||
|     extends React.ComponentPropsWithoutRef<'div'> { | ||||
|     databaseType: DatabaseType; | ||||
|     databaseEdition?: DatabaseEdition; | ||||
|     imgClassName?: string; | ||||
| } | ||||
|  | ||||
| export const DiagramIcon = React.forwardRef< | ||||
|     React.ElementRef<typeof TooltipTrigger>, | ||||
|     DiagramIconProps | ||||
| >(({ diagram }, ref) => | ||||
|     diagram.databaseEdition ? ( | ||||
| >(({ databaseType, databaseEdition, className, imgClassName }, ref) => | ||||
|     databaseEdition ? ( | ||||
|         <Tooltip> | ||||
|             <TooltipTrigger className="mr-1" ref={ref}> | ||||
|             <TooltipTrigger className={cn('mr-1', className)} ref={ref} asChild> | ||||
|                 <img | ||||
|                     src={databaseEditionToImageMap[diagram.databaseEdition]} | ||||
|                     className="h-5 max-w-fit rounded-full" | ||||
|                     src={databaseEditionToImageMap[databaseEdition]} | ||||
|                     className={cn('h-5 max-w-fit rounded-full', imgClassName)} | ||||
|                     alt="database" | ||||
|                 /> | ||||
|             </TooltipTrigger> | ||||
|             <TooltipContent> | ||||
|                 {databaseEditionToLabelMap[diagram.databaseEdition]} | ||||
|                 {databaseEditionToLabelMap[databaseEdition]} | ||||
|             </TooltipContent> | ||||
|         </Tooltip> | ||||
|     ) : ( | ||||
|         <Tooltip> | ||||
|             <TooltipTrigger className="mr-2" ref={ref}> | ||||
|             <TooltipTrigger className={cn('mr-2', className)} ref={ref} asChild> | ||||
|                 <img | ||||
|                     src={databaseSecondaryLogoMap[diagram.databaseType]} | ||||
|                     className="h-5 max-w-fit" | ||||
|                     src={databaseSecondaryLogoMap[databaseType]} | ||||
|                     className={cn('h-5 max-w-fit', imgClassName)} | ||||
|                     alt="database" | ||||
|                 /> | ||||
|             </TooltipTrigger> | ||||
|             <TooltipContent> | ||||
|                 {databaseTypeToLabelMap[diagram.databaseType]} | ||||
|                 {databaseTypeToLabelMap[databaseType]} | ||||
|             </TooltipContent> | ||||
|         </Tooltip> | ||||
|     ) | ||||
|   | ||||
| @@ -117,7 +117,10 @@ const DialogInternalContent = React.forwardRef< | ||||
| >(({ className, ...props }, ref) => ( | ||||
|     <ScrollArea | ||||
|         ref={ref} | ||||
|         className={cn('flex max-h-screen flex-col overflow-y-auto', className)} | ||||
|         className={cn( | ||||
|             'flex flex-1 max-h-screen flex-col overflow-y-auto', | ||||
|             className | ||||
|         )} | ||||
|         {...props} | ||||
|     /> | ||||
| )); | ||||
|   | ||||
| @@ -14,6 +14,7 @@ type ToasterToast = ToastProps & { | ||||
|     layout?: 'row' | 'column'; | ||||
| }; | ||||
|  | ||||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
| const actionTypes = { | ||||
|     ADD_TOAST: 'ADD_TOAST', | ||||
|     UPDATE_TOAST: 'UPDATE_TOAST', | ||||
|   | ||||
							
								
								
									
										15
									
								
								src/context/alert-context/alert-context.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,15 @@ | ||||
| import { createContext, useContext } from 'react'; | ||||
| import { emptyFn } from '@/lib/utils'; | ||||
| import type { BaseAlertDialogProps } from '@/dialogs/base-alert-dialog/base-alert-dialog'; | ||||
|  | ||||
| export interface AlertContext { | ||||
|     showAlert: (params: BaseAlertDialogProps) => void; | ||||
|     closeAlert: () => void; | ||||
| } | ||||
|  | ||||
| export const alertContext = createContext<AlertContext>({ | ||||
|     closeAlert: emptyFn, | ||||
|     showAlert: emptyFn, | ||||
| }); | ||||
|  | ||||
| export const useAlert = () => useContext(alertContext); | ||||
							
								
								
									
										36
									
								
								src/context/alert-context/alert-provider.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,36 @@ | ||||
| import React, { useCallback, useState } from 'react'; | ||||
| import type { AlertContext } from './alert-context'; | ||||
| import { alertContext } from './alert-context'; | ||||
| import type { BaseAlertDialogProps } from '@/dialogs/base-alert-dialog/base-alert-dialog'; | ||||
| import { BaseAlertDialog } from '@/dialogs/base-alert-dialog/base-alert-dialog'; | ||||
|  | ||||
| export const AlertProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|     children, | ||||
| }) => { | ||||
|     const [showAlert, setShowAlert] = useState(false); | ||||
|     const [alertParams, setAlertParams] = useState<BaseAlertDialogProps>({ | ||||
|         title: '', | ||||
|     }); | ||||
|     const showAlertHandler: AlertContext['showAlert'] = useCallback( | ||||
|         (params) => { | ||||
|             setAlertParams(params); | ||||
|             setShowAlert(true); | ||||
|         }, | ||||
|         [setShowAlert, setAlertParams] | ||||
|     ); | ||||
|     const closeAlertHandler = useCallback(() => { | ||||
|         setShowAlert(false); | ||||
|     }, [setShowAlert]); | ||||
|  | ||||
|     return ( | ||||
|         <alertContext.Provider | ||||
|             value={{ | ||||
|                 showAlert: showAlertHandler, | ||||
|                 closeAlert: closeAlertHandler, | ||||
|             }} | ||||
|         > | ||||
|             {children} | ||||
|             <BaseAlertDialog dialog={{ open: showAlert }} {...alertParams} /> | ||||
|         </alertContext.Provider> | ||||
|     ); | ||||
| }; | ||||
| @@ -84,6 +84,7 @@ export interface ChartDBContext { | ||||
|         options?: { updateHistory: boolean } | ||||
|     ) => Promise<void>; | ||||
|     loadDiagram: (diagramId: string) => Promise<Diagram | undefined>; | ||||
|     loadDiagramFromData: (diagram: Diagram) => void; | ||||
|     updateDiagramUpdatedAt: () => Promise<void>; | ||||
|     clearDiagramData: () => Promise<void>; | ||||
|     deleteDiagram: () => Promise<void>; | ||||
| @@ -246,6 +247,7 @@ export const chartDBContext = createContext<ChartDBContext>({ | ||||
|     updateDiagramName: emptyFn, | ||||
|     updateDiagramUpdatedAt: emptyFn, | ||||
|     loadDiagram: emptyFn, | ||||
|     loadDiagramFromData: emptyFn, | ||||
|     clearDiagramData: emptyFn, | ||||
|     deleteDiagram: emptyFn, | ||||
|  | ||||
|   | ||||
| @@ -27,6 +27,7 @@ export interface ChartDBProviderProps { | ||||
|     diagram?: Diagram; | ||||
|     readonly?: boolean; | ||||
| } | ||||
|  | ||||
| export const ChartDBProvider: React.FC< | ||||
|     React.PropsWithChildren<ChartDBProviderProps> | ||||
| > = ({ children, diagram, readonly }) => { | ||||
| @@ -310,6 +311,7 @@ export const ChartDBProvider: React.FC< | ||||
|                 color: randomColor(), | ||||
|                 createdAt: Date.now(), | ||||
|                 isView: false, | ||||
|                 order: tables.length, | ||||
|                 ...attributes, | ||||
|             }; | ||||
|             await addTable(table); | ||||
| @@ -1334,15 +1336,9 @@ export const ChartDBProvider: React.FC< | ||||
|         ] | ||||
|     ); | ||||
|  | ||||
|     const loadDiagram: ChartDBContext['loadDiagram'] = useCallback( | ||||
|         async (diagramId: string) => { | ||||
|             const diagram = await db.getDiagram(diagramId, { | ||||
|                 includeRelationships: true, | ||||
|                 includeTables: true, | ||||
|                 includeDependencies: true, | ||||
|             }); | ||||
|  | ||||
|             if (diagram) { | ||||
|     const loadDiagramFromData: ChartDBContext['loadDiagramFromData'] = | ||||
|         useCallback( | ||||
|             async (diagram) => { | ||||
|                 setDiagramId(diagram.id); | ||||
|                 setDiagramName(diagram.name); | ||||
|                 setDatabaseType(diagram.databaseType); | ||||
| @@ -1354,23 +1350,36 @@ export const ChartDBProvider: React.FC< | ||||
|                 setDiagramUpdatedAt(diagram.updatedAt); | ||||
|  | ||||
|                 events.emit({ action: 'load_diagram', data: { diagram } }); | ||||
|             }, | ||||
|             [ | ||||
|                 setDiagramId, | ||||
|                 setDiagramName, | ||||
|                 setDatabaseType, | ||||
|                 setDatabaseEdition, | ||||
|                 setTables, | ||||
|                 setRelationships, | ||||
|                 setDependencies, | ||||
|                 setDiagramCreatedAt, | ||||
|                 setDiagramUpdatedAt, | ||||
|                 events, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|     const loadDiagram: ChartDBContext['loadDiagram'] = useCallback( | ||||
|         async (diagramId: string) => { | ||||
|             const diagram = await db.getDiagram(diagramId, { | ||||
|                 includeRelationships: true, | ||||
|                 includeTables: true, | ||||
|                 includeDependencies: true, | ||||
|             }); | ||||
|  | ||||
|             if (diagram) { | ||||
|                 loadDiagramFromData(diagram); | ||||
|             } | ||||
|  | ||||
|             return diagram; | ||||
|         }, | ||||
|         [ | ||||
|             db, | ||||
|             setDiagramId, | ||||
|             setDiagramName, | ||||
|             setDatabaseType, | ||||
|             setDatabaseEdition, | ||||
|             setTables, | ||||
|             setRelationships, | ||||
|             setDependencies, | ||||
|             setDiagramCreatedAt, | ||||
|             setDiagramUpdatedAt, | ||||
|             events, | ||||
|         ] | ||||
|         [db, loadDiagramFromData] | ||||
|     ); | ||||
|  | ||||
|     return ( | ||||
| @@ -1391,6 +1400,7 @@ export const ChartDBProvider: React.FC< | ||||
|                 updateDiagramId, | ||||
|                 updateDiagramName, | ||||
|                 loadDiagram, | ||||
|                 loadDiagramFromData, | ||||
|                 updateDatabaseType, | ||||
|                 updateDatabaseEdition, | ||||
|                 clearDiagramData, | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import { createContext } from 'react'; | ||||
| import { emptyFn } from '@/lib/utils'; | ||||
| import type { BaseAlertDialogProps } from '@/dialogs/base-alert-dialog/base-alert-dialog'; | ||||
| import type { TableSchemaDialogProps } from '@/dialogs/table-schema-dialog/table-schema-dialog'; | ||||
| import type { ImportDatabaseDialogProps } from '@/dialogs/import-database-dialog/import-database-dialog'; | ||||
| import type { ExportSQLDialogProps } from '@/dialogs/export-sql-dialog/export-sql-dialog'; | ||||
| @@ -21,10 +20,6 @@ export interface DialogContext { | ||||
|     openExportSQLDialog: (params: Omit<ExportSQLDialogProps, 'dialog'>) => void; | ||||
|     closeExportSQLDialog: () => void; | ||||
|  | ||||
|     // Alert dialog | ||||
|     showAlert: (params: BaseAlertDialogProps) => void; | ||||
|     closeAlert: () => void; | ||||
|  | ||||
|     // Create relationship dialog | ||||
|     openCreateRelationshipDialog: () => void; | ||||
|     closeCreateRelationshipDialog: () => void; | ||||
| @@ -45,6 +40,10 @@ export interface DialogContext { | ||||
|     openStarUsDialog: () => void; | ||||
|     closeStarUsDialog: () => void; | ||||
|  | ||||
|     // Buckle dialog | ||||
|     openBuckleDialog: () => void; | ||||
|     closeBuckleDialog: () => void; | ||||
|  | ||||
|     // Export image dialog | ||||
|     openExportImageDialog: ( | ||||
|         params: Omit<ExportImageDialogProps, 'dialog'> | ||||
| @@ -71,8 +70,6 @@ export const dialogContext = createContext<DialogContext>({ | ||||
|     closeOpenDiagramDialog: emptyFn, | ||||
|     openExportSQLDialog: emptyFn, | ||||
|     closeExportSQLDialog: emptyFn, | ||||
|     closeAlert: emptyFn, | ||||
|     showAlert: emptyFn, | ||||
|     closeCreateRelationshipDialog: emptyFn, | ||||
|     openCreateRelationshipDialog: emptyFn, | ||||
|     openImportDatabaseDialog: emptyFn, | ||||
| @@ -87,4 +84,6 @@ export const dialogContext = createContext<DialogContext>({ | ||||
|     closeExportDiagramDialog: emptyFn, | ||||
|     openImportDiagramDialog: emptyFn, | ||||
|     closeImportDiagramDialog: emptyFn, | ||||
|     openBuckleDialog: emptyFn, | ||||
|     closeBuckleDialog: emptyFn, | ||||
| }); | ||||
|   | ||||
| @@ -6,8 +6,6 @@ import { OpenDiagramDialog } from '@/dialogs/open-diagram-dialog/open-diagram-di | ||||
| import type { ExportSQLDialogProps } from '@/dialogs/export-sql-dialog/export-sql-dialog'; | ||||
| import { ExportSQLDialog } from '@/dialogs/export-sql-dialog/export-sql-dialog'; | ||||
| import { DatabaseType } from '@/lib/domain/database-type'; | ||||
| import type { BaseAlertDialogProps } from '@/dialogs/base-alert-dialog/base-alert-dialog'; | ||||
| import { BaseAlertDialog } from '@/dialogs/base-alert-dialog/base-alert-dialog'; | ||||
| import { CreateRelationshipDialog } from '@/dialogs/create-relationship-dialog/create-relationship-dialog'; | ||||
| import type { ImportDatabaseDialogProps } from '@/dialogs/import-database-dialog/import-database-dialog'; | ||||
| import { ImportDatabaseDialog } from '@/dialogs/import-database-dialog/import-database-dialog'; | ||||
| @@ -19,6 +17,7 @@ import type { ExportImageDialogProps } from '@/dialogs/export-image-dialog/expor | ||||
| import { ExportImageDialog } from '@/dialogs/export-image-dialog/export-image-dialog'; | ||||
| import { ExportDiagramDialog } from '@/dialogs/export-diagram-dialog/export-diagram-dialog'; | ||||
| import { ImportDiagramDialog } from '@/dialogs/import-diagram-dialog/import-diagram-dialog'; | ||||
| import { BuckleDialog } from '@/dialogs/buckle-dialog/buckle-dialog'; | ||||
|  | ||||
| export const DialogProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|     children, | ||||
| @@ -29,6 +28,7 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|     const [openCreateRelationshipDialog, setOpenCreateRelationshipDialog] = | ||||
|         useState(false); | ||||
|     const [openStarUsDialog, setOpenStarUsDialog] = useState(false); | ||||
|     const [openBuckleDialog, setOpenBuckleDialog] = useState(false); | ||||
|  | ||||
|     // Export image dialog | ||||
|     const [openExportImageDialog, setOpenExportImageDialog] = useState(false); | ||||
| @@ -96,22 +96,6 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|     const [openImportDiagramDialog, setOpenImportDiagramDialog] = | ||||
|         useState(false); | ||||
|  | ||||
|     // Alert dialog | ||||
|     const [showAlert, setShowAlert] = useState(false); | ||||
|     const [alertParams, setAlertParams] = useState<BaseAlertDialogProps>({ | ||||
|         title: '', | ||||
|     }); | ||||
|     const showAlertHandler: DialogContext['showAlert'] = useCallback( | ||||
|         (params) => { | ||||
|             setAlertParams(params); | ||||
|             setShowAlert(true); | ||||
|         }, | ||||
|         [setShowAlert, setAlertParams] | ||||
|     ); | ||||
|     const closeAlertHandler = useCallback(() => { | ||||
|         setShowAlert(false); | ||||
|     }, [setShowAlert]); | ||||
|  | ||||
|     return ( | ||||
|         <dialogContext.Provider | ||||
|             value={{ | ||||
| @@ -121,8 +105,6 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|                 closeOpenDiagramDialog: () => setOpenOpenDiagramDialog(false), | ||||
|                 openExportSQLDialog: openExportSQLDialogHandler, | ||||
|                 closeExportSQLDialog: () => setOpenExportSQLDialog(false), | ||||
|                 showAlert: showAlertHandler, | ||||
|                 closeAlert: closeAlertHandler, | ||||
|                 openCreateRelationshipDialog: () => | ||||
|                     setOpenCreateRelationshipDialog(true), | ||||
|                 closeCreateRelationshipDialog: () => | ||||
| @@ -134,6 +116,8 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|                 closeTableSchemaDialog: () => setOpenTableSchemaDialog(false), | ||||
|                 openStarUsDialog: () => setOpenStarUsDialog(true), | ||||
|                 closeStarUsDialog: () => setOpenStarUsDialog(false), | ||||
|                 closeBuckleDialog: () => setOpenBuckleDialog(false), | ||||
|                 openBuckleDialog: () => setOpenBuckleDialog(true), | ||||
|                 closeExportImageDialog: () => setOpenExportImageDialog(false), | ||||
|                 openExportImageDialog: openExportImageDialogHandler, | ||||
|                 openExportDiagramDialog: () => setOpenExportDiagramDialog(true), | ||||
| @@ -151,7 +135,6 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|                 dialog={{ open: openExportSQLDialog }} | ||||
|                 {...exportSQLDialogParams} | ||||
|             /> | ||||
|             <BaseAlertDialog dialog={{ open: showAlert }} {...alertParams} /> | ||||
|             <CreateRelationshipDialog | ||||
|                 dialog={{ open: openCreateRelationshipDialog }} | ||||
|             /> | ||||
| @@ -170,6 +153,7 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|             /> | ||||
|             <ExportDiagramDialog dialog={{ open: openExportDiagramDialog }} /> | ||||
|             <ImportDiagramDialog dialog={{ open: openImportDiagramDialog }} /> | ||||
|             <BuckleDialog dialog={{ open: openBuckleDialog }} /> | ||||
|         </dialogContext.Provider> | ||||
|     ); | ||||
| }; | ||||
|   | ||||
| @@ -30,8 +30,17 @@ export interface LocalConfigContext { | ||||
|     starUsDialogLastOpen: number; | ||||
|     setStarUsDialogLastOpen: (lastOpen: number) => void; | ||||
|  | ||||
|     buckleWaitlistOpened: boolean; | ||||
|     setBuckleWaitlistOpened: (githubRepoOpened: boolean) => void; | ||||
|  | ||||
|     buckleDialogLastOpen: number; | ||||
|     setBuckleDialogLastOpen: (lastOpen: number) => void; | ||||
|  | ||||
|     showDependenciesOnCanvas: boolean; | ||||
|     setShowDependenciesOnCanvas: (showDependenciesOnCanvas: boolean) => void; | ||||
|  | ||||
|     showMiniMapOnCanvas: boolean; | ||||
|     setShowMiniMapOnCanvas: (showMiniMapOnCanvas: boolean) => void; | ||||
| } | ||||
|  | ||||
| export const LocalConfigContext = createContext<LocalConfigContext>({ | ||||
| @@ -56,6 +65,15 @@ export const LocalConfigContext = createContext<LocalConfigContext>({ | ||||
|     starUsDialogLastOpen: 0, | ||||
|     setStarUsDialogLastOpen: emptyFn, | ||||
|  | ||||
|     buckleWaitlistOpened: false, | ||||
|     setBuckleWaitlistOpened: emptyFn, | ||||
|  | ||||
|     buckleDialogLastOpen: 0, | ||||
|     setBuckleDialogLastOpen: emptyFn, | ||||
|  | ||||
|     showDependenciesOnCanvas: false, | ||||
|     setShowDependenciesOnCanvas: emptyFn, | ||||
|  | ||||
|     showMiniMapOnCanvas: false, | ||||
|     setShowMiniMapOnCanvas: emptyFn, | ||||
| }); | ||||
|   | ||||
| @@ -10,7 +10,10 @@ const showCardinalityKey = 'show_cardinality'; | ||||
| const hideMultiSchemaNotificationKey = 'hide_multi_schema_notification'; | ||||
| const githubRepoOpenedKey = 'github_repo_opened'; | ||||
| const starUsDialogLastOpenKey = 'star_us_dialog_last_open'; | ||||
| const buckleWaitlistOpenedKey = 'buckle_waitlist_opened'; | ||||
| const buckleDialogLastOpenKey = 'buckle_dialog_last_open'; | ||||
| const showDependenciesOnCanvasKey = 'show_dependencies_on_canvas'; | ||||
| const showMiniMapOnCanvasKey = 'show_minimap_on_canvas'; | ||||
|  | ||||
| export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|     children, | ||||
| @@ -48,12 +51,28 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|             parseInt(localStorage.getItem(starUsDialogLastOpenKey) || '0') | ||||
|         ); | ||||
|  | ||||
|     const [buckleWaitlistOpened, setBuckleWaitlistOpened] = | ||||
|         React.useState<boolean>( | ||||
|             (localStorage.getItem(buckleWaitlistOpenedKey) || 'false') === | ||||
|                 'true' | ||||
|         ); | ||||
|  | ||||
|     const [buckleDialogLastOpen, setBuckleDialogLastOpen] = | ||||
|         React.useState<number>( | ||||
|             parseInt(localStorage.getItem(buckleDialogLastOpenKey) || '0') | ||||
|         ); | ||||
|  | ||||
|     const [showDependenciesOnCanvas, setShowDependenciesOnCanvas] = | ||||
|         React.useState<boolean>( | ||||
|             (localStorage.getItem(showDependenciesOnCanvasKey) || 'false') === | ||||
|                 'true' | ||||
|         ); | ||||
|  | ||||
|     const [showMiniMapOnCanvas, setShowMiniMapOnCanvas] = | ||||
|         React.useState<boolean>( | ||||
|             (localStorage.getItem(showMiniMapOnCanvasKey) || 'true') === 'true' | ||||
|         ); | ||||
|  | ||||
|     useEffect(() => { | ||||
|         localStorage.setItem( | ||||
|             starUsDialogLastOpenKey, | ||||
| @@ -65,6 +84,20 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|         localStorage.setItem(githubRepoOpenedKey, githubRepoOpened.toString()); | ||||
|     }, [githubRepoOpened]); | ||||
|  | ||||
|     useEffect(() => { | ||||
|         localStorage.setItem( | ||||
|             buckleDialogLastOpenKey, | ||||
|             buckleDialogLastOpen.toString() | ||||
|         ); | ||||
|     }, [buckleDialogLastOpen]); | ||||
|  | ||||
|     useEffect(() => { | ||||
|         localStorage.setItem( | ||||
|             buckleWaitlistOpenedKey, | ||||
|             buckleWaitlistOpened.toString() | ||||
|         ); | ||||
|     }, [buckleWaitlistOpened]); | ||||
|  | ||||
|     useEffect(() => { | ||||
|         localStorage.setItem( | ||||
|             hideMultiSchemaNotificationKey, | ||||
| @@ -95,6 +128,13 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|         ); | ||||
|     }, [showDependenciesOnCanvas]); | ||||
|  | ||||
|     useEffect(() => { | ||||
|         localStorage.setItem( | ||||
|             showMiniMapOnCanvasKey, | ||||
|             showMiniMapOnCanvas.toString() | ||||
|         ); | ||||
|     }, [showMiniMapOnCanvas]); | ||||
|  | ||||
|     return ( | ||||
|         <LocalConfigContext.Provider | ||||
|             value={{ | ||||
| @@ -114,6 +154,12 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|                 setStarUsDialogLastOpen, | ||||
|                 showDependenciesOnCanvas, | ||||
|                 setShowDependenciesOnCanvas, | ||||
|                 setBuckleDialogLastOpen, | ||||
|                 buckleDialogLastOpen, | ||||
|                 buckleWaitlistOpened, | ||||
|                 setBuckleWaitlistOpened, | ||||
|                 showMiniMapOnCanvas, | ||||
|                 setShowMiniMapOnCanvas, | ||||
|             }} | ||||
|         > | ||||
|             {children} | ||||
|   | ||||
| @@ -122,6 +122,32 @@ export const StorageProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|         config: '++id, defaultDiagramId', | ||||
|     }); | ||||
|  | ||||
|     db.version(8).stores({ | ||||
|         diagrams: | ||||
|             '++id, name, databaseType, databaseEdition, createdAt, updatedAt', | ||||
|         db_tables: | ||||
|             '++id, diagramId, name, schema, x, y, fields, indexes, color, createdAt, width, comment, isView, isMaterializedView, order', | ||||
|         db_relationships: | ||||
|             '++id, diagramId, name, sourceSchema, sourceTableId, targetSchema, targetTableId, sourceFieldId, targetFieldId, type, createdAt', | ||||
|         db_dependencies: | ||||
|             '++id, diagramId, schema, tableId, dependentSchema, dependentTableId, createdAt', | ||||
|         config: '++id, defaultDiagramId', | ||||
|     }); | ||||
|  | ||||
|     db.version(9).upgrade((tx) => | ||||
|         tx | ||||
|             .table<DBTable & { diagramId: string }>('db_tables') | ||||
|             .toCollection() | ||||
|             .modify((table) => { | ||||
|                 for (const field of table.fields) { | ||||
|                     if (typeof field.nullable === 'string') { | ||||
|                         field.nullable = | ||||
|                             (field.nullable as string).toLowerCase() === 'true'; | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|     ); | ||||
|  | ||||
|     db.on('ready', async () => { | ||||
|         const config = await getConfig(); | ||||
|  | ||||
| @@ -270,6 +296,23 @@ export const StorageProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|         attributes: Partial<Diagram>; | ||||
|     }) => { | ||||
|         await db.diagrams.update(id, attributes); | ||||
|  | ||||
|         if (attributes.id) { | ||||
|             await Promise.all([ | ||||
|                 db.db_tables | ||||
|                     .where('diagramId') | ||||
|                     .equals(id) | ||||
|                     .modify({ diagramId: attributes.id }), | ||||
|                 db.db_relationships | ||||
|                     .where('diagramId') | ||||
|                     .equals(id) | ||||
|                     .modify({ diagramId: attributes.id }), | ||||
|                 db.db_dependencies | ||||
|                     .where('diagramId') | ||||
|                     .equals(id) | ||||
|                     .modify({ diagramId: attributes.id }), | ||||
|             ]); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     const deleteDiagram: StorageContext['deleteDiagram'] = async ( | ||||
| @@ -345,15 +388,7 @@ export const StorageProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|             .equals(diagramId) | ||||
|             .toArray(); | ||||
|  | ||||
|         // Sort tables first alphabetically, then views alphabetically | ||||
|         return tables.sort((a, b) => { | ||||
|             if (a.isView === b.isView) { | ||||
|                 // Both are either tables or views, so sort alphabetically by name | ||||
|                 return a.name.localeCompare(b.name); | ||||
|             } | ||||
|             // If one is a view and the other is not, put tables first | ||||
|             return a.isView ? 1 : -1; | ||||
|         }); | ||||
|         return tables; | ||||
|     }; | ||||
|  | ||||
|     const addRelationship: StorageContext['addRelationship'] = async ({ | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import { | ||||
|     AlertDialogTitle, | ||||
| } from '@/components/alert-dialog/alert-dialog'; | ||||
| import type { AlertDialogProps } from '@radix-ui/react-alert-dialog'; | ||||
| import { useDialog } from '@/hooks/use-dialog'; | ||||
| import { useAlert } from '@/context/alert-context/alert-context'; | ||||
|  | ||||
| export interface BaseAlertDialogProps { | ||||
|     title: string; | ||||
| @@ -33,7 +33,7 @@ export const BaseAlertDialog: React.FC<BaseAlertDialogProps> = ({ | ||||
|     content, | ||||
|     onClose, | ||||
| }) => { | ||||
|     const { closeAlert } = useDialog(); | ||||
|     const { closeAlert } = useAlert(); | ||||
|  | ||||
|     const closeAlertHandler = useCallback(() => { | ||||
|         onClose?.(); | ||||
|   | ||||
							
								
								
									
										80
									
								
								src/dialogs/buckle-dialog/buckle-dialog.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,80 @@ | ||||
| import React, { useCallback, useEffect } from 'react'; | ||||
| import { useDialog } from '@/hooks/use-dialog'; | ||||
| import { | ||||
|     Dialog, | ||||
|     DialogClose, | ||||
|     DialogContent, | ||||
|     DialogDescription, | ||||
|     DialogFooter, | ||||
|     DialogHeader, | ||||
|     DialogTitle, | ||||
| } from '@/components/dialog/dialog'; | ||||
| import { Button } from '@/components/button/button'; | ||||
| import type { BaseDialogProps } from '../common/base-dialog-props'; | ||||
| import { useLocalConfig } from '@/hooks/use-local-config'; | ||||
| import { useTheme } from '@/hooks/use-theme'; | ||||
|  | ||||
| export interface BuckleDialogProps extends BaseDialogProps {} | ||||
|  | ||||
| export const BuckleDialog: React.FC<BuckleDialogProps> = ({ dialog }) => { | ||||
|     const { setBuckleWaitlistOpened } = useLocalConfig(); | ||||
|     const { effectiveTheme } = useTheme(); | ||||
|  | ||||
|     useEffect(() => { | ||||
|         if (!dialog.open) return; | ||||
|     }, [dialog.open]); | ||||
|     const { closeBuckleDialog } = useDialog(); | ||||
|  | ||||
|     const handleConfirm = useCallback(() => { | ||||
|         setBuckleWaitlistOpened(true); | ||||
|         window.open('https://waitlist.buckle.dev', '_blank'); | ||||
|     }, [setBuckleWaitlistOpened]); | ||||
|  | ||||
|     return ( | ||||
|         <Dialog | ||||
|             {...dialog} | ||||
|             onOpenChange={(open) => { | ||||
|                 if (!open) { | ||||
|                     closeBuckleDialog(); | ||||
|                 } | ||||
|             }} | ||||
|         > | ||||
|             <DialogContent | ||||
|                 className="flex flex-col" | ||||
|                 showClose={false} | ||||
|                 onInteractOutside={(e) => { | ||||
|                     e.preventDefault(); | ||||
|                 }} | ||||
|             > | ||||
|                 <DialogHeader> | ||||
|                     <DialogTitle className="hidden" /> | ||||
|                     <DialogDescription className="hidden" /> | ||||
|                 </DialogHeader> | ||||
|                 <div className="flex w-full flex-col items-center"> | ||||
|                     <img | ||||
|                         src={ | ||||
|                             effectiveTheme === 'light' | ||||
|                                 ? '/buckle-animated.gif' | ||||
|                                 : '/buckle.png' | ||||
|                         } | ||||
|                         className="h-16" | ||||
|                     /> | ||||
|                     <div className="mt-6 text-center text-base"> | ||||
|                         We've been working on something big -{' '} | ||||
|                         <span className="font-semibold">Ready to explore?</span> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <DialogFooter className="flex gap-1 md:justify-between"> | ||||
|                     <DialogClose asChild> | ||||
|                         <Button variant="secondary">Not now</Button> | ||||
|                     </DialogClose> | ||||
|                     <DialogClose asChild> | ||||
|                         <Button onClick={handleConfirm}> | ||||
|                             Try ChartDB v2.0! | ||||
|                         </Button> | ||||
|                     </DialogClose> | ||||
|                 </DialogFooter> | ||||
|             </DialogContent> | ||||
|         </Dialog> | ||||
|     ); | ||||
| }; | ||||
| @@ -8,10 +8,13 @@ export interface ExampleOptionProps {} | ||||
| export const ExampleOption: React.FC<ExampleOptionProps> = () => { | ||||
|     const { t } = useTranslation(); | ||||
|     return ( | ||||
|         <Link href="/examples" className="text-primary hover:text-primary"> | ||||
|             <div className="flex size-20 cursor-pointer flex-col items-center rounded-md border py-3 text-center md:size-32"> | ||||
|                 <div className="flex flex-1 items-center"> | ||||
|                     <LayoutGrid size={34} /> | ||||
|         <Link | ||||
|             href="/examples" | ||||
|             className="col-span-3 text-primary hover:text-primary" | ||||
|         > | ||||
|             <div className="flex h-8 w-full cursor-pointer flex-row items-center justify-center gap-2 rounded-md border py-3 text-center"> | ||||
|                 <div className="flex items-center"> | ||||
|                     <LayoutGrid className="size-4" /> | ||||
|                 </div> | ||||
|                 <div className="flex flex-col-reverse"> | ||||
|                     <div className="hidden text-sm text-primary md:flex"> | ||||
|   | ||||
| @@ -1,22 +1,61 @@ | ||||
| import React from 'react'; | ||||
| import React, { useMemo, useState } from 'react'; | ||||
| import { ToggleGroup } from '@/components/toggle/toggle-group'; | ||||
| import { DatabaseType } from '@/lib/domain/database-type'; | ||||
| import { DatabaseOption } from './database-option'; | ||||
| import { ExampleOption } from './example-option'; | ||||
|  | ||||
| import { Button } from '@/components/button/button'; | ||||
| import { ChevronDown, ChevronUp } from 'lucide-react'; | ||||
| export interface SelectDatabaseContentProps { | ||||
|     databaseType: DatabaseType; | ||||
|     setDatabaseType: React.Dispatch<React.SetStateAction<DatabaseType>>; | ||||
|     onContinue: () => void; | ||||
| } | ||||
|  | ||||
| const ROW_SIZE = 3; | ||||
| const ROWS = 2; | ||||
| const TOTAL_SLOTS = ROW_SIZE * ROWS; | ||||
| const SUPPORTED_DB_TYPES: DatabaseType[] = [ | ||||
|     DatabaseType.MYSQL, | ||||
|     DatabaseType.POSTGRESQL, | ||||
|     DatabaseType.MARIADB, | ||||
|     DatabaseType.SQLITE, | ||||
|     DatabaseType.SQL_SERVER, | ||||
|     DatabaseType.COCKROACHDB, | ||||
|     DatabaseType.CLICKHOUSE, | ||||
| ]; | ||||
|  | ||||
| export const SelectDatabaseContent: React.FC<SelectDatabaseContentProps> = ({ | ||||
|     databaseType, | ||||
|     setDatabaseType, | ||||
|     onContinue, | ||||
| }) => { | ||||
|     const [currentRow, setCurrentRow] = useState(0); | ||||
|     const currentDatabasesTypes = useMemo( | ||||
|         () => | ||||
|             SUPPORTED_DB_TYPES.slice( | ||||
|                 currentRow * ROW_SIZE, | ||||
|                 currentRow * ROW_SIZE + TOTAL_SLOTS | ||||
|             ), | ||||
|         [currentRow] | ||||
|     ); | ||||
|  | ||||
|     const hasNextRow = useMemo( | ||||
|         () => (currentRow + 1) * ROW_SIZE < SUPPORTED_DB_TYPES.length, | ||||
|         [currentRow] | ||||
|     ); | ||||
|  | ||||
|     const hasPreviousRow = useMemo(() => currentRow > 0, [currentRow]); | ||||
|  | ||||
|     const toggleRow = () => { | ||||
|         if (currentRow === 0 && hasNextRow) { | ||||
|             setCurrentRow(currentRow + 1); | ||||
|         } else if (currentRow > 0) { | ||||
|             setCurrentRow(currentRow - 1); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     return ( | ||||
|         <div className="flex flex-1 items-center justify-center"> | ||||
|         <div className="flex flex-1 flex-col items-center justify-center gap-4"> | ||||
|             <ToggleGroup | ||||
|                 value={databaseType} | ||||
|                 onValueChange={(value: DatabaseType) => { | ||||
| @@ -30,12 +69,41 @@ export const SelectDatabaseContent: React.FC<SelectDatabaseContentProps> = ({ | ||||
|                 type="single" | ||||
|                 className="grid grid-flow-row grid-cols-3 gap-6" | ||||
|             > | ||||
|                 <DatabaseOption type={DatabaseType.MYSQL} /> | ||||
|                 <DatabaseOption type={DatabaseType.POSTGRESQL} /> | ||||
|                 <DatabaseOption type={DatabaseType.MARIADB} /> | ||||
|                 <DatabaseOption type={DatabaseType.SQLITE} /> | ||||
|                 <DatabaseOption type={DatabaseType.SQL_SERVER} /> | ||||
|                 <ExampleOption /> | ||||
|                 {Array.from({ length: TOTAL_SLOTS }).map((_, index) => | ||||
|                     currentDatabasesTypes?.[index] ? ( | ||||
|                         <DatabaseOption | ||||
|                             key={currentDatabasesTypes[index]} | ||||
|                             type={currentDatabasesTypes[index]} | ||||
|                         /> | ||||
|                     ) : null | ||||
|                 )} | ||||
|  | ||||
|                 <div className="col-span-3 flex flex-1 flex-col gap-1"> | ||||
|                     {hasNextRow || hasPreviousRow ? ( | ||||
|                         <Button | ||||
|                             variant="ghost" | ||||
|                             onClick={toggleRow} | ||||
|                             className="col-span-3 h-8" | ||||
|                         > | ||||
|                             {currentRow === 0 ? ( | ||||
|                                 <div className="flex h-8 w-full cursor-pointer flex-row items-center justify-center gap-2 py-3 text-center md:h-12"> | ||||
|                                     <ChevronDown className="mr-2 size-3.5" /> | ||||
|                                     <span className="text-xs"> | ||||
|                                         More Databases | ||||
|                                     </span> | ||||
|                                 </div> | ||||
|                             ) : ( | ||||
|                                 <div className="flex h-8 w-full cursor-pointer flex-row items-center justify-center gap-2 py-3 text-center md:h-12"> | ||||
|                                     <ChevronUp className="mr-2 size-3.5" /> | ||||
|                                     <span className="text-xs"> | ||||
|                                         Primary Databases | ||||
|                                     </span> | ||||
|                                 </div> | ||||
|                             )} | ||||
|                         </Button> | ||||
|                     ) : null} | ||||
|                     <ExampleOption /> | ||||
|                 </div> | ||||
|             </ToggleGroup> | ||||
|         </div> | ||||
|     ); | ||||
|   | ||||
| @@ -70,7 +70,7 @@ export const ExportSQLDialog: React.FC<ExportSQLDialogProps> = ({ | ||||
|                 const script = await exportSQLScript(); | ||||
|                 setScript(script); | ||||
|                 setIsScriptLoading(false); | ||||
|             } catch (e) { | ||||
|             } catch { | ||||
|                 setError(true); | ||||
|             } | ||||
|         }; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { Dialog, DialogContent } from '@/components/dialog/dialog'; | ||||
| import { useDialog } from '@/hooks/use-dialog'; | ||||
| import type { DatabaseType } from '@/lib/domain/database-type'; | ||||
| import { DatabaseType } from '@/lib/domain/database-type'; | ||||
| import React, { useCallback, useEffect, useState } from 'react'; | ||||
| import { ImportDatabase } from '../common/import-database/import-database'; | ||||
| import type { DatabaseEdition } from '@/lib/domain/database-edition'; | ||||
| @@ -12,6 +12,7 @@ import { useRedoUndoStack } from '@/hooks/use-redo-undo-stack'; | ||||
| import { Trans, useTranslation } from 'react-i18next'; | ||||
| import { useReactFlow } from '@xyflow/react'; | ||||
| import type { BaseDialogProps } from '../common/base-dialog-props'; | ||||
| import { useAlert } from '@/context/alert-context/alert-context'; | ||||
|  | ||||
| export interface ImportDatabaseDialogProps extends BaseDialogProps { | ||||
|     databaseType: DatabaseType; | ||||
| @@ -21,7 +22,8 @@ export const ImportDatabaseDialog: React.FC<ImportDatabaseDialogProps> = ({ | ||||
|     dialog, | ||||
|     databaseType, | ||||
| }) => { | ||||
|     const { closeImportDatabaseDialog, showAlert } = useDialog(); | ||||
|     const { closeImportDatabaseDialog } = useDialog(); | ||||
|     const { showAlert } = useAlert(); | ||||
|     const { | ||||
|         tables, | ||||
|         relationships, | ||||
| @@ -30,6 +32,8 @@ export const ImportDatabaseDialog: React.FC<ImportDatabaseDialogProps> = ({ | ||||
|         addTables, | ||||
|         addRelationships, | ||||
|         diagramName, | ||||
|         databaseType: currentDatabaseType, | ||||
|         updateDatabaseType, | ||||
|     } = useChartDB(); | ||||
|     const [scriptResult, setScriptResult] = useState(''); | ||||
|     const { resetRedoStack, resetUndoStack } = useRedoUndoStack(); | ||||
| @@ -282,6 +286,10 @@ export const ImportDatabaseDialog: React.FC<ImportDatabaseDialogProps> = ({ | ||||
|             }), | ||||
|         ]); | ||||
|  | ||||
|         if (currentDatabaseType === DatabaseType.GENERIC) { | ||||
|             await updateDatabaseType(databaseType); | ||||
|         } | ||||
|  | ||||
|         setNodes((nodes) => | ||||
|             nodes.map((node) => ({ | ||||
|                 ...node, | ||||
| @@ -297,6 +305,8 @@ export const ImportDatabaseDialog: React.FC<ImportDatabaseDialogProps> = ({ | ||||
|         closeImportDatabaseDialog(); | ||||
|     }, [ | ||||
|         databaseEdition, | ||||
|         currentDatabaseType, | ||||
|         updateDatabaseType, | ||||
|         databaseType, | ||||
|         scriptResult, | ||||
|         tables, | ||||
|   | ||||
| @@ -74,7 +74,7 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({ | ||||
|             }} | ||||
|         > | ||||
|             <DialogContent | ||||
|                 className="flex h-[30rem] max-h-screen w-[90vw] flex-col overflow-y-auto md:w-screen xl:min-w-[55vw]" | ||||
|                 className="flex h-[30rem] max-h-screen flex-col overflow-y-auto md:min-w-[80vw] xl:min-w-[55vw]" | ||||
|                 showClose | ||||
|             > | ||||
|                 <DialogHeader> | ||||
| @@ -137,7 +137,12 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({ | ||||
|                                         <TableCell className="table-cell"> | ||||
|                                             <div className="flex justify-center"> | ||||
|                                                 <DiagramIcon | ||||
|                                                     diagram={diagram} | ||||
|                                                     databaseType={ | ||||
|                                                         diagram.databaseType | ||||
|                                                     } | ||||
|                                                     databaseEdition={ | ||||
|                                                         diagram.databaseEdition | ||||
|                                                     } | ||||
|                                                 /> | ||||
|                                             </div> | ||||
|                                         </TableCell> | ||||
|   | ||||
| @@ -73,3 +73,64 @@ | ||||
|         @apply dark:group-hover:bg-slate-900 group-hover:bg-slate-100 group-hover:ring-[0.5px] rounded-md cursor-pointer; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .gradient-background { | ||||
|     /* Fallback: Set a background color. */ | ||||
|     background-color: #f46b24; | ||||
|  | ||||
|     /* Create the gradient. */ | ||||
|     background-image: linear-gradient( | ||||
|         45deg, | ||||
|         #2e6579 20%, | ||||
|         #4fafca 20%, | ||||
|         #4fafca 40%, | ||||
|         #6dc630 40%, | ||||
|         #6dc630 60%, | ||||
|         #f9dc3a 60%, | ||||
|         #f9dc3a 80%, | ||||
|         #f46b24 80% | ||||
|     ); | ||||
|  | ||||
|     /* Set the background size and repeat properties. */ | ||||
|     background-size: 100%; | ||||
|     background-repeat: repeat; | ||||
|  | ||||
|     /* Use the text as a mask for the background. */ | ||||
|     /* This will show the gradient as a text color rather than element bg. */ | ||||
|     /* -webkit-background-clip: text; | ||||
|     -webkit-text-fill-color: transparent; */ | ||||
|  | ||||
|     /* Animate the text when loading the element. */ | ||||
|     /* This animates it on page load and when hovering out. */ | ||||
|     animation: rainbow-text-simple-animation-rev 0.75s ease forwards; | ||||
| } | ||||
|  | ||||
| .gradient-background:hover { | ||||
|     animation: rainbow-text-simple-animation 0.5s ease-in forwards; | ||||
| } | ||||
|  | ||||
| @keyframes rainbow-text-simple-animation-rev { | ||||
|     0% { | ||||
|         background-size: 650%; | ||||
|     } | ||||
|     40% { | ||||
|         background-size: 650%; | ||||
|     } | ||||
|     100% { | ||||
|         background-size: 100%; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Move the background and make it larger. */ | ||||
| /* Animation shown when hovering over the text. */ | ||||
| @keyframes rainbow-text-simple-animation { | ||||
|     0% { | ||||
|         background-size: 100%; | ||||
|     } | ||||
|     80% { | ||||
|         background-size: 650%; | ||||
|     } | ||||
|     100% { | ||||
|         background-size: 650%; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,8 +19,10 @@ import { mr, mrMetadata } from './locales/mr'; | ||||
| import { tr, trMetadata } from './locales/tr'; | ||||
| import { id_ID, id_IDMetadata } from './locales/id_ID'; | ||||
| import { te, teMetadata } from './locales/te'; | ||||
| import { bn, bnMetadata } from './locales/bn'; | ||||
| import { gu, guMetadata } from './locales/gu'; | ||||
| import { vi, viMetadata } from './locales/vi'; | ||||
| import { ar, arMetadata } from './locales/ar'; | ||||
|  | ||||
| export const languages: LanguageMetadata[] = [ | ||||
|     enMetadata, | ||||
| @@ -40,8 +42,10 @@ export const languages: LanguageMetadata[] = [ | ||||
|     trMetadata, | ||||
|     id_IDMetadata, | ||||
|     teMetadata, | ||||
|     bnMetadata, | ||||
|     guMetadata, | ||||
|     viMetadata, | ||||
|     arMetadata, | ||||
| ]; | ||||
|  | ||||
| const resources = { | ||||
| @@ -62,8 +66,10 @@ const resources = { | ||||
|     tr, | ||||
|     id_ID, | ||||
|     te, | ||||
|     bn, | ||||
|     gu, | ||||
|     vi, | ||||
|     ar, | ||||
| }; | ||||
|  | ||||
| i18n.use(LanguageDetector) | ||||
|   | ||||
							
								
								
									
										407
									
								
								src/i18n/locales/ar.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,407 @@ | ||||
| import type { LanguageMetadata, LanguageTranslation } from '../types'; | ||||
|  | ||||
| export const ar: LanguageTranslation = { | ||||
|     translation: { | ||||
|         menu: { | ||||
|             file: { | ||||
|                 file: 'ملف', | ||||
|                 new: 'جديد', | ||||
|                 open: 'فتح', | ||||
|                 save: 'حفظ', | ||||
|                 import_database: 'استيراد قاعدة بيانات', | ||||
|                 export_sql: 'SQL تصدير', | ||||
|                 export_as: 'تصدير كـ', | ||||
|                 delete_diagram: 'حذف الرسم البياني', | ||||
|                 exit: 'خروج', | ||||
|             }, | ||||
|             edit: { | ||||
|                 edit: 'تحرير', | ||||
|                 undo: 'تراجع', | ||||
|                 redo: 'إعادة', | ||||
|                 clear: 'مسح', | ||||
|             }, | ||||
|             view: { | ||||
|                 view: 'عرض', | ||||
|                 show_sidebar: 'إظهار الشريط الجانبي', | ||||
|                 hide_sidebar: 'إخفاء الشريط الجانبي', | ||||
|                 hide_cardinality: 'إخفاء الكاردينالية', | ||||
|                 show_cardinality: 'إظهار الكاردينالية', | ||||
|                 zoom_on_scroll: 'تكبير/تصغير عند التمرير', | ||||
|                 theme: 'المظهر', | ||||
|                 show_dependencies: 'إظهار الاعتمادات', | ||||
|                 hide_dependencies: 'إخفاء الاعتمادات', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: 'مشاركة', | ||||
|                 export_diagram: 'تصدير المخطط', | ||||
|                 import_diagram: 'استيراد المخطط', | ||||
|             }, | ||||
|             help: { | ||||
|                 help: 'مساعدة', | ||||
|                 visit_website: 'ChartDB قم بزيارة', | ||||
|                 join_discord: 'Discord انضم إلينا على', | ||||
|                 schedule_a_call: '!تحدث معنا', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         delete_diagram_alert: { | ||||
|             title: 'حذف المخطط', | ||||
|             description: | ||||
|                 '.لا يمكن التراجع عن هذا الإجراء. سيتم حذف الرسم البياني بشكل دائم', | ||||
|             cancel: 'إلغاء', | ||||
|             delete: 'حذف', | ||||
|         }, | ||||
|  | ||||
|         clear_diagram_alert: { | ||||
|             title: 'مسح الرسم البياني', | ||||
|             description: | ||||
|                 '.لا يمكن التراجع عن هذا الاجراء. سيتم حذف جميع البيانات في الرسم البياني بشكل دائم', | ||||
|             cancel: 'إلغاء', | ||||
|             clear: 'مسح', | ||||
|         }, | ||||
|  | ||||
|         reorder_diagram_alert: { | ||||
|             title: 'إعادة ترتيب الرسم البياني', | ||||
|             description: | ||||
|                 'هذا الإجراء سيقوم بإعادة ترتيب الجداول في المخطط بشكل تلقائي. هل تريد المتابعة؟', | ||||
|             reorder: 'إعادة ترتيب', | ||||
|             cancel: 'إلغاء', | ||||
|         }, | ||||
|  | ||||
|         multiple_schemas_alert: { | ||||
|             title: 'مخططات متعددة', | ||||
|             description: | ||||
|                 '{{formattedSchemas}} :مخططات في هذا الرسم البياني. يتم حاليا عرض {{schemasCount}} هناك', | ||||
|             dont_show_again: 'لا تظهره مجدداً', | ||||
|             change_schema: 'تغيير', | ||||
|             none: 'لا شيء', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'فشل النسخ', | ||||
|                 description: '.الحافظة غير مدعومة', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'فشل النسخ', | ||||
|                 description: 'حدث خطأ أثناء النسخ. حاول مجدداً', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'النظام', | ||||
|             light: 'فاتح', | ||||
|             dark: 'داكن', | ||||
|         }, | ||||
|  | ||||
|         zoom: { | ||||
|             on: 'تشغيل', | ||||
|             off: 'إيقاف', | ||||
|         }, | ||||
|  | ||||
|         last_saved: 'آخر حفظ', | ||||
|         saved: 'تم الحفظ', | ||||
|         loading_diagram: '...جارِ تحميل الرسم البياني', | ||||
|         deselect_all: 'إلغاء تحديد الكل', | ||||
|         select_all: 'تحديد الكل', | ||||
|         clear: 'مسح', | ||||
|         show_more: 'عرض المزيد', | ||||
|         show_less: 'عرض أقل', | ||||
|         copy_to_clipboard: 'نسخ إلى الحافظة', | ||||
|         copied: '!تم النسخ', | ||||
|  | ||||
|         side_panel: { | ||||
|             schema: ':المخطط', | ||||
|             filter_by_schema: 'تصفية حسب المخطط', | ||||
|             search_schema: '...بحث في المخطط', | ||||
|             no_schemas_found: '.لم يتم العثور على مخططات', | ||||
|             view_all_options: '...عرض جميع الخيارات', | ||||
|             tables_section: { | ||||
|                 tables: 'الجداول', | ||||
|                 add_table: 'إضافة جدول', | ||||
|                 filter: 'تصفية', | ||||
|                 collapse: 'طي الكل', | ||||
|  | ||||
|                 table: { | ||||
|                     fields: 'الحقول', | ||||
|                     nullable: 'يمكن ان يكون فارغاً؟', | ||||
|                     primary_key: 'المفتاح الأساسي', | ||||
|                     indexes: 'الفهارس', | ||||
|                     comments: 'تعليقات', | ||||
|                     no_comments: 'لا توجد تعليقات', | ||||
|                     add_field: 'إضافة حقل', | ||||
|                     add_index: 'إضافة فهرس', | ||||
|                     index_select_fields: 'حدد الحقول', | ||||
|                     no_types_found: 'لا يوجد أنواع', | ||||
|                     field_name: 'الإسم', | ||||
|                     field_type: 'النوع', | ||||
|                     field_actions: { | ||||
|                         title: 'خصائص الحقل', | ||||
|                         unique: 'فريد', | ||||
|                         comments: 'تعليقات', | ||||
|                         no_comments: 'لا يوجد تعليقات', | ||||
|                         delete_field: 'حذف الحقل', | ||||
|                     }, | ||||
|                     index_actions: { | ||||
|                         title: 'خصائص الفهرس', | ||||
|                         name: 'الإسم', | ||||
|                         unique: 'فريد', | ||||
|                         delete_index: 'حذف الفهرس', | ||||
|                     }, | ||||
|                     table_actions: { | ||||
|                         title: 'إجراءات الجدول', | ||||
|                         change_schema: 'تغيير المخطط', | ||||
|                         add_field: 'إضافة حقل', | ||||
|                         add_index: 'إضافة فهرس', | ||||
|                         duplicate_table: 'نسخ الجدول', | ||||
|                         delete_table: 'حذف الجدول', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'لا توجد جداول', | ||||
|                     description: 'أنشئ جدولاً للبدء', | ||||
|                 }, | ||||
|             }, | ||||
|             relationships_section: { | ||||
|                 relationships: 'العلاقات', | ||||
|                 filter: 'تصفية', | ||||
|                 add_relationship: 'إضافة علاقة', | ||||
|                 collapse: 'طي الكل', | ||||
|                 relationship: { | ||||
|                     primary: 'الجدول الأساسي', | ||||
|                     foreign: 'الجدول المرتبط', | ||||
|                     cardinality: 'الكاردينالية', | ||||
|                     delete_relationship: 'حذف', | ||||
|                     relationship_actions: { | ||||
|                         title: 'إجراءات', | ||||
|                         delete_relationship: 'حذف', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'لا توجد علاقات', | ||||
|                     description: 'إنشئ علاقة لربط الجداول', | ||||
|                 }, | ||||
|             }, | ||||
|             dependencies_section: { | ||||
|                 dependencies: 'الاعتمادات', | ||||
|                 filter: 'تصفية', | ||||
|                 collapse: 'طي الكل', | ||||
|                 dependency: { | ||||
|                     table: 'الجدول', | ||||
|                     dependent_table: 'عرض الاعتمادات', | ||||
|                     delete_dependency: 'حذف', | ||||
|                     dependency_actions: { | ||||
|                         title: 'إجراءات', | ||||
|                         delete_dependency: 'حذف', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'لا توجد اعتمادات', | ||||
|                     description: 'إنشاء اعتماد للبدء', | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         toolbar: { | ||||
|             zoom_in: 'تكبير', | ||||
|             zoom_out: 'تصغير', | ||||
|             save: 'حفظ', | ||||
|             show_all: 'عرض الكل', | ||||
|             undo: 'تراجع', | ||||
|             redo: 'إعادة', | ||||
|             reorder_diagram: 'إعادة ترتيب الرسم البياني', | ||||
|             highlight_overlapping_tables: 'تمييز الجداول المتداخلة', | ||||
|         }, | ||||
|  | ||||
|         new_diagram_dialog: { | ||||
|             database_selection: { | ||||
|                 title: 'ما هو نوع قاعدة البيانات الخاصة بك؟', | ||||
|                 description: | ||||
|                     'تتمتع كل قاعدة بيانات بمميزاتها وقدراتها الفريدة.', | ||||
|                 check_examples_long: 'ألقي نظرة على الأمثلة', | ||||
|                 check_examples_short: 'أمثلة', | ||||
|             }, | ||||
|  | ||||
|             import_database: { | ||||
|                 title: 'إسترد قاعدة بياناتك', | ||||
|                 database_edition: ':إصدار قاعدة البيانات', | ||||
|                 step_1: ':قم بتشغيل هذا البرنامج النصي في قاعدة بياناتك', | ||||
|                 step_2: ':إلصق نتيجة البرنامج النصي هنا', | ||||
|                 script_results_placeholder: '...نتيجة البرنامج النصي هنا', | ||||
|                 ssms_instructions: { | ||||
|                     button_text: 'SSMS تعليمات', | ||||
|                     title: 'تعليمات', | ||||
|                     step_1: 'SQL SERVER < انتقل إلى الأدوات > الخيارات > نتائح الاستعلام', | ||||
|                     step_2: '(اضبطها على 9999999) XML اذا كنت تستخدم "نتائج إلى الشبكة"، قم بتغيير الحد الاقصى للاحرف المستردة للبيانات غير', | ||||
|                 }, | ||||
|                 instructions_link: 'تحتاج مساعدة؟ شاهد الفيديو', | ||||
|                 check_script_result: 'تحقق من نتيجة البرنامج النصي', | ||||
|             }, | ||||
|  | ||||
|             cancel: 'إلغاء', | ||||
|             import_from_file: 'استيراد من ملف', | ||||
|             back: 'رجوع', | ||||
|             empty_diagram: 'مخطط فارغ', | ||||
|             continue: 'متابعة', | ||||
|             import: 'استيراد', | ||||
|         }, | ||||
|  | ||||
|         open_diagram_dialog: { | ||||
|             title: 'فتح مخطط', | ||||
|             description: 'اختر مخططًا لفتحه من القائمة ادناه', | ||||
|             table_columns: { | ||||
|                 name: 'الإسم', | ||||
|                 created_at: 'تاريخ الإنشاء', | ||||
|                 last_modified: 'آخر تعديل', | ||||
|                 tables_count: 'الجداول', | ||||
|             }, | ||||
|             cancel: 'إلغاء', | ||||
|             open: 'فتح', | ||||
|         }, | ||||
|  | ||||
|         export_sql_dialog: { | ||||
|             title: 'SQL تصدير', | ||||
|             description: | ||||
|                 '{{databaseType}} صدّر مخطط الرسم البياني إلى برنامج نصي لـ', | ||||
|             close: 'إغلاق', | ||||
|             loading: { | ||||
|                 text: '...{{databaseType}} ل SQL يقوم الذكاء الاصطناعي بإنشاء', | ||||
|                 description: 'هذا قد يستغرق 30 ثانية', | ||||
|             }, | ||||
|             error: { | ||||
|                 message: | ||||
|                     'النصي. يرجى المحاولة مرة اخرى لاحقاً او <0>اتصل بنا</0> SQL خطأ في إنشاء برنامج', | ||||
|                 description: | ||||
|                     ' الخاصة بك. راجع الدليل <0>هنا</0> OPENAI_TOKEN لا تتردد في استخدام', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         create_relationship_dialog: { | ||||
|             title: 'إنشاء علاقة', | ||||
|             primary_table: 'الجدول الأساسي', | ||||
|             primary_field: 'الحقل الأساسي', | ||||
|             referenced_table: 'الجدول المرتبط', | ||||
|             referenced_field: 'الحقل المرتبط', | ||||
|             primary_table_placeholder: 'حدد الجدول', | ||||
|             primary_field_placeholder: 'حدد الحقل', | ||||
|             referenced_table_placeholder: 'حدد الجدول', | ||||
|             referenced_field_placeholder: 'حدد الحقل', | ||||
|             no_tables_found: 'لم يتم العثور على جداول', | ||||
|             no_fields_found: 'لم يتم العثور على حقول', | ||||
|             create: 'إنشاء', | ||||
|             cancel: 'إلغاء', | ||||
|         }, | ||||
|  | ||||
|         import_database_dialog: { | ||||
|             title: 'استيراد إلى المخطط الحالي', | ||||
|             override_alert: { | ||||
|                 title: 'استيراد قاعدة بيانات', | ||||
|                 content: { | ||||
|                     alert: 'سيؤدي استيراد هذا المخطط إلى التأثير على الجداول والعلاقات الحالية.', | ||||
|                     new_tables: | ||||
|                         'جداول جديدة <bold>{{newTablesNumber}}</bold> سيتم إضافة', | ||||
|                     new_relationships: | ||||
|                         'علاقات جديدة <bold>{{newRelationshipsNumber}}</bold> سيتم إنشاء', | ||||
|                     tables_override: | ||||
|                         'جداول <bold>{{tablesOverrideNumber}}</bold> سيتم تعديل', | ||||
|                     proceed: 'هل تريد المتابعة؟', | ||||
|                 }, | ||||
|                 import: 'استيراد', | ||||
|                 cancel: 'إلغاء', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         export_image_dialog: { | ||||
|             title: 'تصدير الصورة', | ||||
|             description: ':اختر عامل المقياس للتصدير', | ||||
|             scale_1x: '1x عادي', | ||||
|             scale_2x: '2x (موصى به)', | ||||
|             scale_3x: '3x', | ||||
|             scale_4x: '4x', | ||||
|             cancel: 'إلغاء', | ||||
|             export: 'تصدير', | ||||
|         }, | ||||
|  | ||||
|         new_table_schema_dialog: { | ||||
|             title: 'اختر مخططاً', | ||||
|             description: | ||||
|                 '.يتم حالياً عرض مخططات متعددة. اختر واحداً للجدول الجديد', | ||||
|             cancel: 'إلغاء', | ||||
|             confirm: 'تأكيد', | ||||
|         }, | ||||
|  | ||||
|         update_table_schema_dialog: { | ||||
|             title: 'تغيير المخطط', | ||||
|             description: '"{{tableName}}" تحديث مخطط الجدول', | ||||
|             cancel: 'إلغاء', | ||||
|             confirm: 'تغيير', | ||||
|         }, | ||||
|  | ||||
|         star_us_dialog: { | ||||
|             title: '!ساعدنا على التحسن', | ||||
|             description: '؟! إنها مجرد نقرة واحدةGITHUB هل ترغب في تقييمنا على', | ||||
|             close: 'ليس الآن', | ||||
|             confirm: '!بالتأكيد', | ||||
|         }, | ||||
|         export_diagram_dialog: { | ||||
|             title: 'تصدير المخطط', | ||||
|             description: ':اختر التنسيق للتصدير', | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'إلغاء', | ||||
|             export: 'تصدير', | ||||
|             error: { | ||||
|                 title: 'حدث خطأ أثناء التصدير', | ||||
|                 description: | ||||
|                     'chartdb.io@gmail.com حدث خطأ ما. هل تحتاج إلى مساعدة؟', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         import_diagram_dialog: { | ||||
|             title: 'استيراد الرسم البياني', | ||||
|             description: ':للرسم البياني ادناه JSON قم بلصق', | ||||
|             cancel: 'إلغاء', | ||||
|             import: 'استيراد', | ||||
|             error: { | ||||
|                 title: 'حدث خطأ أثناء الاستيراد', | ||||
|                 description: | ||||
|                     'chartdb.io@gmail.com و المحاولة مرة اخرى. هل تحتاج إلى المساعدة؟ JSON غير صالح. يرجى التحقق من JSON الرسم البياني', | ||||
|             }, | ||||
|         }, | ||||
|         relationship_type: { | ||||
|             one_to_one: 'واحد إلى واحد', | ||||
|             one_to_many: 'واحد إلى متعدد', | ||||
|             many_to_one: 'متعدد إلى واحد', | ||||
|             many_to_many: 'متعدد إلى متعدد', | ||||
|         }, | ||||
|  | ||||
|         canvas_context_menu: { | ||||
|             new_table: 'جدول جديد', | ||||
|             new_relationship: 'علاقة جديدة', | ||||
|         }, | ||||
|  | ||||
|         table_node_context_menu: { | ||||
|             edit_table: 'تعديل الجدول', | ||||
|             duplicate_table: 'نسخ الجدول', | ||||
|             delete_table: 'حذف الجدول', | ||||
|         }, | ||||
|  | ||||
|         snap_to_grid_tooltip: '({{key}} مغنظة الشبكة (اضغط مع الاستمرار على', | ||||
|  | ||||
|         tool_tips: { | ||||
|             double_click_to_edit: 'انقر مرتين للتعديل', | ||||
|         }, | ||||
|  | ||||
|         language_select: { | ||||
|             change_language: 'اللغة', | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| export const arMetadata: LanguageMetadata = { | ||||
|     name: 'Arabic', | ||||
|     nativeName: 'العربية', | ||||
|     code: 'ar', | ||||
| }; | ||||
							
								
								
									
										410
									
								
								src/i18n/locales/bn.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,410 @@ | ||||
| import type { LanguageMetadata, LanguageTranslation } from '../types'; | ||||
|  | ||||
| export const bn: LanguageTranslation = { | ||||
|     translation: { | ||||
|         menu: { | ||||
|             file: { | ||||
|                 file: 'ফাইল', | ||||
|                 new: 'নতুন', | ||||
|                 open: 'খুলুন', | ||||
|                 save: 'সংরক্ষণ করুন', | ||||
|                 import_database: 'ডাটাবেস আমদানি করুন', | ||||
|                 export_sql: 'SQL রপ্তানি করুন', | ||||
|                 export_as: 'রূপে রপ্তানি করুন', | ||||
|                 delete_diagram: 'ডায়াগ্রাম মুছুন', | ||||
|                 exit: 'প্রস্থান করুন', | ||||
|             }, | ||||
|             edit: { | ||||
|                 edit: 'সম্পাদনা', | ||||
|                 undo: 'পূর্বাবস্থায় ফিরুন', | ||||
|                 redo: 'পুনরায় করুন', | ||||
|                 clear: 'পরিষ্কার করুন', | ||||
|             }, | ||||
|             view: { | ||||
|                 view: 'দেখুন', | ||||
|                 show_sidebar: 'সাইডবার দেখান', | ||||
|                 hide_sidebar: 'সাইডবার লুকান', | ||||
|                 hide_cardinality: 'কার্ডিনালিটি লুকান', | ||||
|                 show_cardinality: 'কার্ডিনালিটি দেখান', | ||||
|                 zoom_on_scroll: 'স্ক্রলে জুম করুন', | ||||
|                 theme: 'থিম', | ||||
|                 show_dependencies: 'নির্ভরতাগুলি দেখান', | ||||
|                 hide_dependencies: 'নির্ভরতাগুলি লুকান', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|  | ||||
|             share: { | ||||
|                 share: 'শেয়ার করুন', | ||||
|                 export_diagram: 'ডায়াগ্রাম রপ্তানি করুন', | ||||
|                 import_diagram: 'ডায়াগ্রাম আমদানি করুন', | ||||
|             }, | ||||
|             help: { | ||||
|                 help: 'সাহায্য', | ||||
|                 visit_website: 'ChartDB ওয়েবসাইটে যান', | ||||
|                 join_discord: 'আমাদের Discord-এ যোগ দিন', | ||||
|                 schedule_a_call: 'আমাদের সাথে কথা বলুন!', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         delete_diagram_alert: { | ||||
|             title: 'ডায়াগ্রাম মুছুন', | ||||
|             description: | ||||
|                 'এই কাজটি পূর্বাবস্থায় ফিরিয়ে আনা যাবে না। এই ডায়াগ্রাম স্থায়ীভাবে মুছে ফেলা হবে।', | ||||
|             cancel: 'বাতিল করুন', | ||||
|             delete: 'মুছুন', | ||||
|         }, | ||||
|  | ||||
|         clear_diagram_alert: { | ||||
|             title: 'ডায়াগ্রাম পরিষ্কার করুন', | ||||
|             description: | ||||
|                 'এই কাজটি পূর্বাবস্থায় ফিরিয়ে আনা যাবে না। এই ডায়াগ্রামের সমস্ত তথ্য স্থায়ীভাবে মুছে যাবে।', | ||||
|             cancel: 'বাতিল করুন', | ||||
|             clear: 'পরিষ্কার করুন', | ||||
|         }, | ||||
|  | ||||
|         reorder_diagram_alert: { | ||||
|             title: 'ডায়াগ্রাম পুনর্বিন্যাস করুন', | ||||
|             description: | ||||
|                 'এই কাজটি ডায়াগ্রামের সমস্ত টেবিল পুনর্বিন্যাস করবে। আপনি কি চালিয়ে যেতে চান?', | ||||
|             reorder: 'পুনর্বিন্যাস করুন', | ||||
|             cancel: 'বাতিল করুন', | ||||
|         }, | ||||
|  | ||||
|         multiple_schemas_alert: { | ||||
|             title: 'বহু স্কিমা', | ||||
|             description: | ||||
|                 '{{schemasCount}} স্কিমা এই ডায়াগ্রামে রয়েছে। বর্তমানে প্রদর্শিত: {{formattedSchemas}}।', | ||||
|             dont_show_again: 'পুনরায় দেখাবেন না', | ||||
|             change_schema: 'পরিবর্তন করুন', | ||||
|             none: 'কিছুই না', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'কপি ব্যর্থ হয়েছে', | ||||
|                 description: 'ক্লিপবোর্ড সমর্থিত নয়', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'কপি ব্যর্থ হয়েছে', | ||||
|                 description: 'কিছু ভুল হয়েছে। অনুগ্রহ করে আবার চেষ্টা করুন।', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'সিস্টেম', | ||||
|             light: 'হালকা', | ||||
|             dark: 'অন্ধকার', | ||||
|         }, | ||||
|  | ||||
|         zoom: { | ||||
|             on: 'চালু', | ||||
|             off: 'বন্ধ', | ||||
|         }, | ||||
|  | ||||
|         last_saved: 'সর্বশেষ সংরক্ষণ', | ||||
|         saved: 'সংরক্ষিত', | ||||
|         loading_diagram: 'ডায়াগ্রাম লোড হচ্ছে...', | ||||
|         deselect_all: 'সব নির্বাচন সরান', | ||||
|         select_all: 'সব নির্বাচন করুন', | ||||
|         clear: 'পরিষ্কার করুন', | ||||
|         show_more: 'আরও দেখুন', | ||||
|         show_less: 'কম দেখুন', | ||||
|         copy_to_clipboard: 'ক্লিপবোর্ডে অনুলিপি করুন', | ||||
|         copied: 'অনুলিপি সম্পন্ন!', | ||||
|  | ||||
|         side_panel: { | ||||
|             schema: 'স্কিমা:', | ||||
|             filter_by_schema: 'স্কিমা দ্বারা ফিল্টার করুন', | ||||
|             search_schema: 'স্কিমা খুঁজুন...', | ||||
|             no_schemas_found: 'কোনো স্কিমা পাওয়া যায়নি।', | ||||
|             view_all_options: 'সমস্ত বিকল্প দেখুন...', | ||||
|             tables_section: { | ||||
|                 tables: 'টেবিল', | ||||
|                 add_table: 'টেবিল যোগ করুন', | ||||
|                 filter: 'ফিল্টার', | ||||
|                 collapse: 'সব ভাঁজ করুন', | ||||
|  | ||||
|                 table: { | ||||
|                     fields: 'ফিল্ড', | ||||
|                     nullable: 'নালযোগ্য?', | ||||
|                     primary_key: 'প্রাথমিক কী', | ||||
|                     indexes: 'ইনডেক্স', | ||||
|                     comments: 'মন্তব্য', | ||||
|                     no_comments: 'কোনো মন্তব্য নেই', | ||||
|                     add_field: 'ফিল্ড যোগ করুন', | ||||
|                     add_index: 'ইনডেক্স যোগ করুন', | ||||
|                     index_select_fields: 'ফিল্ড নির্বাচন করুন', | ||||
|                     no_types_found: 'কোনো ধরন পাওয়া যায়নি', | ||||
|                     field_name: 'নাম', | ||||
|                     field_type: 'ধরন', | ||||
|                     field_actions: { | ||||
|                         title: 'ফিল্ড কর্ম', | ||||
|                         unique: 'অদ্বিতীয়', | ||||
|                         comments: 'মন্তব্য', | ||||
|                         no_comments: 'কোনো মন্তব্য নেই', | ||||
|                         delete_field: 'ফিল্ড মুছুন', | ||||
|                     }, | ||||
|                     index_actions: { | ||||
|                         title: 'ইনডেক্স কর্ম', | ||||
|                         name: 'নাম', | ||||
|                         unique: 'অদ্বিতীয়', | ||||
|                         delete_index: 'ইনডেক্স মুছুন', | ||||
|                     }, | ||||
|                     table_actions: { | ||||
|                         title: 'টেবিল কর্ম', | ||||
|                         change_schema: 'স্কিমা পরিবর্তন করুন', | ||||
|                         add_field: 'ফিল্ড যোগ করুন', | ||||
|                         add_index: 'ইনডেক্স যোগ করুন', | ||||
|                         duplicate_table: 'টেবিল নকল করুন', | ||||
|                         delete_table: 'টেবিল মুছুন', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'কোনো টেবিল নেই', | ||||
|                     description: 'শুরু করতে একটি টেবিল তৈরি করুন', | ||||
|                 }, | ||||
|             }, | ||||
|             relationships_section: { | ||||
|                 relationships: 'সম্পর্ক', | ||||
|                 filter: 'ফিল্টার', | ||||
|                 add_relationship: 'সম্পর্ক যোগ করুন', | ||||
|                 collapse: 'সব ভাঁজ করুন', | ||||
|                 relationship: { | ||||
|                     primary: 'প্রাথমিক টেবিল', | ||||
|                     foreign: 'বিদেশি টেবিল', | ||||
|                     cardinality: 'কার্ডিনালিটি', | ||||
|                     delete_relationship: 'মুছুন', | ||||
|                     relationship_actions: { | ||||
|                         title: 'কর্ম', | ||||
|                         delete_relationship: 'মুছুন', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'কোনো সম্পর্ক নেই', | ||||
|                     description: 'টেবিল সংযোগ করতে একটি সম্পর্ক তৈরি করুন', | ||||
|                 }, | ||||
|             }, | ||||
|             dependencies_section: { | ||||
|                 dependencies: 'নির্ভরতাগুলি', | ||||
|                 filter: 'ফিল্টার', | ||||
|                 collapse: 'ভাঁজ করুন', | ||||
|                 dependency: { | ||||
|                     table: 'টেবিল', | ||||
|                     dependent_table: 'নির্ভরশীল টেবিল', | ||||
|                     delete_dependency: 'নির্ভরতা মুছুন', | ||||
|                     dependency_actions: { | ||||
|                         title: 'কর্ম', | ||||
|                         delete_dependency: 'নির্ভরতা মুছুন', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'কোনো নির্ভরতাগুলি নেই', | ||||
|                     description: 'এই অংশে কোনো নির্ভরতা উপলব্ধ নেই।', | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         toolbar: { | ||||
|             zoom_in: 'জুম ইন', | ||||
|             zoom_out: 'জুম আউট', | ||||
|             save: 'সংরক্ষণ করুন', | ||||
|             show_all: 'সব দেখান', | ||||
|             undo: 'পূর্বাবস্থায় ফিরুন', | ||||
|             redo: 'পুনরায় করুন', | ||||
|             reorder_diagram: 'ডায়াগ্রাম পুনর্বিন্যাস করুন', | ||||
|             highlight_overlapping_tables: 'ওভারল্যাপিং টেবিল হাইলাইট করুন', | ||||
|         }, | ||||
|  | ||||
|         new_diagram_dialog: { | ||||
|             database_selection: { | ||||
|                 title: 'আপনার ডাটাবেস কী?', | ||||
|                 description: | ||||
|                     'প্রত্যেক ডাটাবেসের নিজস্ব বৈশিষ্ট্য এবং ক্ষমতা রয়েছে।', | ||||
|                 check_examples_long: 'উদাহরণ দেখুন', | ||||
|                 check_examples_short: 'উদাহরণ', | ||||
|             }, | ||||
|  | ||||
|             import_database: { | ||||
|                 title: 'আপনার ডাটাবেস আমদানি করুন', | ||||
|                 database_edition: 'ডাটাবেস সংস্করণ:', | ||||
|                 step_1: 'আপনার ডাটাবেসে এই স্ক্রিপ্ট চালান:', | ||||
|                 step_2: 'স্ক্রিপ্টের ফলাফল এখানে পেস্ট করুন:', | ||||
|                 script_results_placeholder: 'স্ক্রিপ্টের ফলাফল এখানে...', | ||||
|                 ssms_instructions: { | ||||
|                     button_text: 'SSMS নির্দেশনা', | ||||
|                     title: 'নির্দেশনা', | ||||
|                     step_1: 'টুলস > অপশন > কোয়েরি ফলাফল > SQL সার্ভারে যান।', | ||||
|                     step_2: 'যদি আপনি "গ্রিডে ফলাফল" ব্যবহার করেন, তাহলে নন-XML ডেটার জন্য সর্বাধিক চরিত্রগুলি 9999999-এ সেট করুন।', | ||||
|                 }, | ||||
|                 instructions_link: 'সাহায্যের প্রয়োজন? এখানে দেখুন', | ||||
|                 check_script_result: 'স্ক্রিপ্ট ফলাফল যাচাই করুন', | ||||
|             }, | ||||
|  | ||||
|             cancel: 'বাতিল করুন', | ||||
|             back: 'ফিরে যান', | ||||
|             import_from_file: 'ফাইল থেকে আমদানি করুন', | ||||
|             empty_diagram: 'ফাঁকা চিত্র', | ||||
|             continue: 'চালিয়ে যান', | ||||
|             import: 'আমদানি করুন', | ||||
|         }, | ||||
|  | ||||
|         open_diagram_dialog: { | ||||
|             title: 'চিত্র খুলুন', | ||||
|             description: 'নিচের তালিকা থেকে একটি চিত্র নির্বাচন করুন।', | ||||
|             table_columns: { | ||||
|                 name: 'নাম', | ||||
|                 created_at: 'তৈরির তারিখ', | ||||
|                 last_modified: 'সর্বশেষ পরিবর্তিত', | ||||
|                 tables_count: 'টেবিল', | ||||
|             }, | ||||
|             cancel: 'বাতিল করুন', | ||||
|             open: 'খুলুন', | ||||
|         }, | ||||
|  | ||||
|         export_sql_dialog: { | ||||
|             title: 'SQL রপ্তানি করুন', | ||||
|             description: | ||||
|                 '{{databaseType}} স্ক্রিপ্টের জন্য আপনার ডায়াগ্রাম স্কিমা রপ্তানি করুন', | ||||
|             close: 'বন্ধ করুন', | ||||
|             loading: { | ||||
|                 text: '{{databaseType}} এর জন্য AI SQL তৈরি হচ্ছে...', | ||||
|                 description: 'এতে ৩০ সেকেন্ড পর্যন্ত সময় লাগতে পারে।', | ||||
|             }, | ||||
|             error: { | ||||
|                 message: | ||||
|                     'SQL স্ক্রিপ্ট তৈরি করার সময় একটি ত্রুটি ঘটেছে। অনুগ্রহ করে পরে আবার চেষ্টা করুন বা <0>আমাদের সাথে যোগাযোগ করুন</0>।', | ||||
|                 description: | ||||
|                     'আপনার OPENAI_TOKEN ব্যবহার করার জন্য বিনামূল্যে অভিজ্ঞতা নিন, ম্যানুয়াল <0>এখানে দেখুন</0>।', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         create_relationship_dialog: { | ||||
|             title: 'সম্পর্ক তৈরি করুন', | ||||
|             primary_table: 'প্রাথমিক টেবিল', | ||||
|             primary_field: 'প্রাথমিক ক্ষেত্র', | ||||
|             referenced_table: 'রেফারেন্স করা টেবিল', | ||||
|             referenced_field: 'রেফারেন্স করা ক্ষেত্র', | ||||
|             primary_table_placeholder: 'টেবিল নির্বাচন করুন', | ||||
|             primary_field_placeholder: 'ক্ষেত্র নির্বাচন করুন', | ||||
|             referenced_table_placeholder: 'টেবিল নির্বাচন করুন', | ||||
|             referenced_field_placeholder: 'ক্ষেত্র নির্বাচন করুন', | ||||
|             no_tables_found: 'কোন টেবিল পাওয়া যায়নি', | ||||
|             no_fields_found: 'কোন ক্ষেত্র পাওয়া যায়নি', | ||||
|             create: 'তৈরি করুন', | ||||
|             cancel: 'বাতিল করুন', | ||||
|         }, | ||||
|  | ||||
|         import_database_dialog: { | ||||
|             title: 'বর্তমান চিত্রে আমদানি করুন', | ||||
|             override_alert: { | ||||
|                 title: 'ডাটাবেস আমদানি করুন', | ||||
|                 content: { | ||||
|                     alert: 'এই চিত্র আমদানির ফলে বিদ্যমান টেবিল ও সম্পর্ক প্রভাবিত হবে।', | ||||
|                     new_tables: | ||||
|                         '<bold>{{newTablesNumber}}</bold> নতুন টেবিল যোগ করা হবে।', | ||||
|                     new_relationships: | ||||
|                         '<bold>{{newRelationshipsNumber}}</bold> নতুন সম্পর্ক তৈরি করা হবে।', | ||||
|                     tables_override: | ||||
|                         '<bold>{{tablesOverrideNumber}}</bold> টেবিল ওভাররাইট করা হবে।', | ||||
|                     proceed: 'আপনি কি এগিয়ে যেতে চান?', | ||||
|                 }, | ||||
|                 import: 'আমদানি করুন', | ||||
|                 cancel: 'বাতিল করুন', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         export_image_dialog: { | ||||
|             title: 'চিত্র রপ্তানি করুন', | ||||
|             description: 'রপ্তানির জন্য স্কেল ফ্যাক্টর নির্বাচন করুন:', | ||||
|             scale_1x: '1x স্বাভাবিক', | ||||
|             scale_2x: '2x (প্রস্তাবিত)', | ||||
|             scale_3x: '3x', | ||||
|             scale_4x: '4x', | ||||
|             cancel: 'বাতিল করুন', | ||||
|             export: 'রপ্তানি করুন', | ||||
|         }, | ||||
|  | ||||
|         new_table_schema_dialog: { | ||||
|             title: 'স্কিমা নির্বাচন করুন', | ||||
|             description: | ||||
|                 'বর্তমানে অনেক স্কিমা প্রদর্শিত হচ্ছে। নতুন টেবিলের জন্য একটি নির্বাচন করুন।', | ||||
|             cancel: 'বাতিল করুন', | ||||
|             confirm: 'নিশ্চিত করুন', | ||||
|         }, | ||||
|  | ||||
|         update_table_schema_dialog: { | ||||
|             title: 'স্কিমা পরিবর্তন করুন', | ||||
|             description: 'টেবিল "{{tableName}}" এর জন্য স্কিমা আপডেট করুন', | ||||
|             cancel: 'বাতিল করুন', | ||||
|             confirm: 'পরিবর্তন করুন', | ||||
|         }, | ||||
|  | ||||
|         star_us_dialog: { | ||||
|             title: 'আমাদের উন্নত করতে সাহায্য করুন!', | ||||
|             description: | ||||
|                 'আপনি কি GitHub-এ আমাদের একটি স্টার দিতে পারবেন? এটি মাত্র এক ক্লিক দূরে!', | ||||
|             close: 'এখন নয়', | ||||
|             confirm: 'অবশ্যই!', | ||||
|         }, | ||||
|  | ||||
|         export_diagram_dialog: { | ||||
|             title: 'চিত্র রপ্তানি করুন', | ||||
|             description: 'রপ্তানির জন্য ফরম্যাট নির্বাচন করুন:', | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'বাতিল করুন', | ||||
|             export: 'রপ্তানি করুন', | ||||
|             error: { | ||||
|                 title: 'চিত্র রপ্তানিতে ত্রুটি', | ||||
|                 description: | ||||
|                     'কিছু ভুল হয়েছে। সাহায্যের প্রয়োজন? chartdb.io@gmail.com-এ যোগাযোগ করুন।', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         import_diagram_dialog: { | ||||
|             title: 'চিত্র আমদানি করুন', | ||||
|             description: 'নীচে ডায়াগ্রাম JSON পেস্ট করুন:', | ||||
|             cancel: 'বাতিল করুন', | ||||
|             import: 'আমদানি করুন', | ||||
|             error: { | ||||
|                 title: 'চিত্র আমদানিতে ত্রুটি', | ||||
|                 description: | ||||
|                     'ডায়াগ্রাম JSON অবৈধ। অনুগ্রহ করে JSON পরীক্ষা করুন এবং আবার চেষ্টা করুন। সাহায্যের প্রয়োজন? chartdb.io@gmail.com-এ যোগাযোগ করুন।', | ||||
|             }, | ||||
|         }, | ||||
|         relationship_type: { | ||||
|             one_to_one: 'এক থেকে এক', | ||||
|             one_to_many: 'এক থেকে অনেক', | ||||
|             many_to_one: 'অনেক থেকে এক', | ||||
|             many_to_many: 'অনেক থেকে অনেক', | ||||
|         }, | ||||
|  | ||||
|         canvas_context_menu: { | ||||
|             new_table: 'নতুন টেবিল', | ||||
|             new_relationship: 'নতুন সম্পর্ক', | ||||
|         }, | ||||
|  | ||||
|         table_node_context_menu: { | ||||
|             edit_table: 'টেবিল সম্পাদনা করুন', | ||||
|             duplicate_table: 'টেবিল নকল করুন', | ||||
|             delete_table: 'টেবিল মুছে ফেলুন', | ||||
|         }, | ||||
|  | ||||
|         snap_to_grid_tooltip: 'গ্রিডে স্ন্যাপ করুন (অবস্থান {{key}})', | ||||
|  | ||||
|         tool_tips: { | ||||
|             double_click_to_edit: 'সম্পাদনা করতে ডাবল-ক্লিক করুন', | ||||
|         }, | ||||
|  | ||||
|         language_select: { | ||||
|             change_language: 'ভাষা পরিবর্তন করুন', | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| export const bnMetadata: LanguageMetadata = { | ||||
|     name: 'Bengali', | ||||
|     nativeName: 'বাংলা', | ||||
|     code: 'bn', | ||||
| }; | ||||
| @@ -30,6 +30,9 @@ export const de: LanguageTranslation = { | ||||
|                 theme: 'Stil', | ||||
|                 show_dependencies: 'Abhängigkeiten anzeigen', | ||||
|                 hide_dependencies: 'Abhängigkeiten ausblenden', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
| @@ -78,6 +81,18 @@ export const de: LanguageTranslation = { | ||||
|             none: 'Keine', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Kopieren fehlgeschlagen', | ||||
|                 description: 'Zwischenablage nicht unterstützt', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Kopieren fehlgeschlagen', | ||||
|                 description: | ||||
|                     'Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'System', | ||||
|             light: 'Hell', | ||||
| @@ -91,7 +106,6 @@ export const de: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Zuletzt gespeichert', | ||||
|         saved: 'Gespeichert', | ||||
|         diagrams: 'Diagramme', | ||||
|         loading_diagram: 'Diagramm wird geladen...', | ||||
|         deselect_all: 'Alles abwählen', | ||||
|         select_all: 'Alles auswählen', | ||||
|   | ||||
| @@ -30,6 +30,8 @@ export const en = { | ||||
|                 theme: 'Theme', | ||||
|                 show_dependencies: 'Show Dependencies', | ||||
|                 hide_dependencies: 'Hide Dependencies', | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: 'Share', | ||||
| @@ -77,6 +79,17 @@ export const en = { | ||||
|             none: 'none', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Copy failed', | ||||
|                 description: 'Clipboard not supported.', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Copy failed', | ||||
|                 description: 'Something went wrong. Please try again.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'System', | ||||
|             light: 'Light', | ||||
| @@ -90,7 +103,6 @@ export const en = { | ||||
|  | ||||
|         last_saved: 'Last saved', | ||||
|         saved: 'Saved', | ||||
|         diagrams: 'Diagrams', | ||||
|         loading_diagram: 'Loading diagram...', | ||||
|         deselect_all: 'Deselect All', | ||||
|         select_all: 'Select All', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const es: LanguageTranslation = { | ||||
|                 theme: 'Tema', | ||||
|                 show_dependencies: 'Mostrar dependencias', | ||||
|                 hide_dependencies: 'Ocultar dependencias', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
| @@ -69,6 +72,17 @@ export const es: LanguageTranslation = { | ||||
|             cancel: 'Cancelar', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Copia fallida', | ||||
|                 description: 'Portapapeles no soportado', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Copia fallida', | ||||
|                 description: 'Algo salió mal. Por favor, inténtelo de nuevo.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Sistema', | ||||
|             light: 'Claro', | ||||
| @@ -82,7 +96,6 @@ export const es: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Último guardado', | ||||
|         saved: 'Guardado', | ||||
|         diagrams: 'Diagramas', | ||||
|         loading_diagram: 'Cargando diagrama...', | ||||
|         deselect_all: 'Deseleccionar todo', | ||||
|         select_all: 'Seleccionar todo', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const fr: LanguageTranslation = { | ||||
|                 theme: 'Thème', | ||||
|                 show_dependencies: 'Afficher les Dépendances', | ||||
|                 hide_dependencies: 'Masquer les Dépendances', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: 'Partage', | ||||
| @@ -68,6 +71,17 @@ export const fr: LanguageTranslation = { | ||||
|             cancel: 'Annuler', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Échec de la copie', | ||||
|                 description: 'Presse-papiers non pris en charge', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Échec de la copie', | ||||
|                 description: 'Quelque chose a mal tourné. Veuillez réessayer.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Système', | ||||
|             light: 'Clair', | ||||
| @@ -81,7 +95,6 @@ export const fr: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Dernière sauvegarde', | ||||
|         saved: 'Enregistré', | ||||
|         diagrams: 'Diagrammes', | ||||
|         loading_diagram: 'Chargement du diagramme...', | ||||
|         deselect_all: 'Tout désélectionner', | ||||
|         select_all: 'Tout sélectionner', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const gu: LanguageTranslation = { | ||||
|                 theme: 'થિમ', | ||||
|                 show_dependencies: 'નિર્ભરતાઓ બતાવો', | ||||
|                 hide_dependencies: 'નિર્ભરતાઓ છુપાવો', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|  | ||||
|             share: { | ||||
| @@ -78,6 +81,17 @@ export const gu: LanguageTranslation = { | ||||
|             none: 'કઈ નહીં', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'નકલ નિષ્ફળ', | ||||
|                 description: 'ક્લિપબોર્ડ આધારિત નથી', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'નકલ નિષ્ફળ', | ||||
|                 description: 'કંઈક ખોટું થયું છે. કૃપા કરીને ફરી પ્રયાસ કરો.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'સિસ્ટમ', | ||||
|             light: 'હલકો', | ||||
| @@ -91,7 +105,6 @@ export const gu: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'છેલ્લે સાચવ્યું', | ||||
|         saved: 'સાચવ્યું', | ||||
|         diagrams: 'ડાયાગ્રામ', | ||||
|         loading_diagram: 'ડાયાગ્રામ લોડ થઈ રહ્યું છે...', | ||||
|         deselect_all: 'બધાને ડીસેલેક્ટ કરો', | ||||
|         select_all: 'બધા પસંદ કરો', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const hi: LanguageTranslation = { | ||||
|                 theme: 'थीम', | ||||
|                 show_dependencies: 'निर्भरता दिखाएँ', | ||||
|                 hide_dependencies: 'निर्भरता छिपाएँ', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
| @@ -78,6 +81,17 @@ export const hi: LanguageTranslation = { | ||||
|             none: 'कोई नहीं', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'कॉपी असफल', | ||||
|                 description: 'क्लिपबोर्ड समर्थित नहीं है', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'कॉपी असफल', | ||||
|                 description: 'कुछ गलत हो गया। कृपया पुनः प्रयास करें।', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'सिस्टम', | ||||
|             light: 'हल्का', | ||||
| @@ -91,7 +105,6 @@ export const hi: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'अंतिम सहेजा गया', | ||||
|         saved: 'सहेजा गया', | ||||
|         diagrams: 'आरेख', | ||||
|         loading_diagram: 'आरेख लोड हो रहा है...', | ||||
|         deselect_all: 'सभी को अचयनित करें', | ||||
|         select_all: 'सभी को चुनें', | ||||
|   | ||||
| @@ -30,12 +30,14 @@ export const id_ID: LanguageTranslation = { | ||||
|                 theme: 'Tema', | ||||
|                 show_dependencies: 'Tampilkan Dependensi', | ||||
|                 hide_dependencies: 'Sembunyikan Dependensi', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
|                 share: 'Share', | ||||
|                 export_diagram: 'Export Diagram', | ||||
|                 import_diagram: 'Import Diagram', | ||||
|                 share: 'Bagikan', | ||||
|                 export_diagram: 'Ekspor Diagram', | ||||
|                 import_diagram: 'Impor Diagram', | ||||
|             }, | ||||
|             help: { | ||||
|                 help: 'Bantuan', | ||||
| @@ -78,6 +80,17 @@ export const id_ID: LanguageTranslation = { | ||||
|             none: 'Tidak ada', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Gagal menyalin', | ||||
|                 description: 'Clipboard tidak didukung', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Gagal menyalin', | ||||
|                 description: 'Ada yang salah. Silakan coba lagi.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Sistem', | ||||
|             light: 'Terang', | ||||
| @@ -91,7 +104,6 @@ export const id_ID: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Terakhir disimpan', | ||||
|         saved: 'Tersimpan', | ||||
|         diagrams: 'Diagram', | ||||
|         loading_diagram: 'Memuat diagram...', | ||||
|         deselect_all: 'Batalkan Semua', | ||||
|         select_all: 'Pilih Semua', | ||||
| @@ -335,30 +347,28 @@ export const id_ID: LanguageTranslation = { | ||||
|             confirm: 'Tentu saja!', | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         export_diagram_dialog: { | ||||
|             title: 'Export Diagram', | ||||
|             description: 'Choose the format for export:', | ||||
|             title: 'Ekspor Diagram', | ||||
|             description: 'Pilih format untuk ekspor:', | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             cancel: 'Batal', | ||||
|             export: 'Ekspor', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 title: 'Error ekspor diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|                     'Sesuatu yang salah. Butuh bantuan? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|             title: 'Import Diagram', | ||||
|             description: 'Paste the diagram JSON below:', | ||||
|             cancel: 'Cancel', | ||||
|             import: 'Import', | ||||
|             title: 'Impor Diagram', | ||||
|             description: 'Tempel diagram JSON di bawah:', | ||||
|             cancel: 'Batal', | ||||
|             import: 'Impor', | ||||
|             error: { | ||||
|                 title: 'Error importing diagram', | ||||
|                 title: 'Error impor diagram', | ||||
|                 description: | ||||
|                     'The diagram JSON is invalid. Please check the JSON and try again. Need help? chartdb.io@gmail.com', | ||||
|                     'Diagram JSON tidak valid. Silakan cek JSON dan coba lagi. Butuh bantuan? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
| @@ -377,16 +387,13 @@ export const id_ID: LanguageTranslation = { | ||||
|         table_node_context_menu: { | ||||
|             edit_table: 'Ubah Tabel', | ||||
|             delete_table: 'Hapus Tabel', | ||||
|             // TODO: Translate | ||||
|             duplicate_table: 'Duplicate Table', | ||||
|             duplicate_table: 'Duplikat Tabel', | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         snap_to_grid_tooltip: 'Snap to Grid (Hold {{key}})', | ||||
|         snap_to_grid_tooltip: 'Snap ke Kisi (Tahan {{key}})', | ||||
|  | ||||
|         // TODO: Translate | ||||
|         tool_tips: { | ||||
|             double_click_to_edit: 'Double-click to edit', | ||||
|             double_click_to_edit: 'Klik ganda untuk mengedit', | ||||
|         }, | ||||
|  | ||||
|         language_select: { | ||||
|   | ||||
| @@ -31,6 +31,9 @@ export const ja: LanguageTranslation = { | ||||
|                 // TODO: Translate | ||||
|                 show_dependencies: 'Show Dependencies', | ||||
|                 hide_dependencies: 'Hide Dependencies', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
| @@ -79,6 +82,18 @@ export const ja: LanguageTranslation = { | ||||
|             none: 'なし', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'コピー失敗', | ||||
|                 description: 'クリップボードがサポートされていません', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'コピー失敗', | ||||
|                 description: | ||||
|                     '何かがうまくいきませんでした。もう一度お試しください。', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'システム', | ||||
|             light: 'ライト', | ||||
| @@ -92,7 +107,6 @@ export const ja: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: '最後に保存された', | ||||
|         saved: '保存されました', | ||||
|         diagrams: 'ダイアグラム', | ||||
|         loading_diagram: 'ダイアグラムを読み込み中...', | ||||
|         deselect_all: 'すべての選択を解除', | ||||
|         select_all: 'すべてを選択', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const ko_KR: LanguageTranslation = { | ||||
|                 theme: '테마', | ||||
|                 show_dependencies: '종속성 보이기', | ||||
|                 hide_dependencies: '종속성 숨기기', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: '공유', | ||||
| @@ -77,6 +80,17 @@ export const ko_KR: LanguageTranslation = { | ||||
|             none: '없음', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: '복사 실패', | ||||
|                 description: '클립보드가 지원되지 않습니다"', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: '복사 실패', | ||||
|                 description: '문제가 발생했습니다. 다시 시도해주세요.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: '시스템 설정에 따름', | ||||
|             light: '밝게', | ||||
| @@ -90,7 +104,6 @@ export const ko_KR: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: '최근 저장일시: ', | ||||
|         saved: '저장됨', | ||||
|         diagrams: '다이어그램', | ||||
|         loading_diagram: '다이어그램 로딩중...', | ||||
|         deselect_all: '모두 선택 해제', | ||||
|         select_all: '모두 선택', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const mr: LanguageTranslation = { | ||||
|                 theme: 'थीम', | ||||
|                 show_dependencies: 'डिपेंडेन्सि दाखवा', | ||||
|                 hide_dependencies: 'डिपेंडेन्सि लपवा', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 // TODO: Add translations | ||||
| @@ -78,6 +81,17 @@ export const mr: LanguageTranslation = { | ||||
|             none: 'काहीही नाही', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'कॉपी अयशस्वी', | ||||
|                 description: 'क्लिपबोर्ड समर्थित नाही', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'कॉपी अयशस्वी', | ||||
|                 description: 'काहीतरी चूक झाली. कृपया पुन्हा प्रयत्न करा.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'सिस्टम', | ||||
|             light: 'लाईट', | ||||
| @@ -91,7 +105,6 @@ export const mr: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'शेवटचे जतन केले', | ||||
|         saved: 'जतन केले', | ||||
|         diagrams: 'आरेख', | ||||
|         loading_diagram: 'आरेख लोड करत आहे...', | ||||
|         deselect_all: 'सर्व निवड रद्द करा', | ||||
|         select_all: 'सर्व निवडा', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const ne: LanguageTranslation = { | ||||
|                 theme: 'थिम', | ||||
|                 show_dependencies: 'डिपेन्डेन्सीहरू देखाउनुहोस्', | ||||
|                 hide_dependencies: 'डिपेन्डेन्सीहरू लुकाउनुहोस्', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: 'शेयर गर्नुहोस्', | ||||
| @@ -77,6 +80,17 @@ export const ne: LanguageTranslation = { | ||||
|             none: 'कुनै पनि छैन', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'प्रतिलिपि असफल', | ||||
|                 description: 'क्लिपबोर्ड समर्थित छैन', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'प्रतिलिपि असफल', | ||||
|                 description: 'केही गडबड भयो। कृपया फेरि प्रयास गर्नुहोस्।', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'सिस्टम', | ||||
|             light: 'लाइट', | ||||
| @@ -90,7 +104,6 @@ export const ne: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'अन्तिम सुरक्षित', | ||||
|         saved: 'सुरक्षित', | ||||
|         diagrams: 'डायाग्रामहरू', | ||||
|         loading_diagram: 'डायाग्राम लोड हुँदैछ...', | ||||
|         deselect_all: 'सबै चयन हटाउनुहोस्', | ||||
|         select_all: 'सबै चयन गर्नुहोस्', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const pt_BR: LanguageTranslation = { | ||||
|                 theme: 'Tema', | ||||
|                 show_dependencies: 'Mostrar Dependências', | ||||
|                 hide_dependencies: 'Ocultar Dependências', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
| @@ -78,6 +81,17 @@ export const pt_BR: LanguageTranslation = { | ||||
|             none: 'nenhum', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Falha na cópia', | ||||
|                 description: 'Área de transferência não suportada', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Falha na cópia', | ||||
|                 description: 'Algo deu errado. Por favor, tente novamente.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Sistema', | ||||
|             light: 'Claro', | ||||
| @@ -91,7 +105,6 @@ export const pt_BR: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Última vez salvo', | ||||
|         saved: 'Salvo', | ||||
|         diagrams: 'Diagramas', | ||||
|         loading_diagram: 'Carregando diagrama...', | ||||
|         deselect_all: 'Desmarcar Todos', | ||||
|         select_all: 'Selecionar Todos', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const ru: LanguageTranslation = { | ||||
|                 theme: 'Тема', | ||||
|                 show_dependencies: 'Показать зависимости', | ||||
|                 hide_dependencies: 'Скрыть зависимости', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: 'Поделиться', | ||||
| @@ -77,6 +80,18 @@ export const ru: LanguageTranslation = { | ||||
|             none: 'никто', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Ошибка копирования', | ||||
|                 description: 'Буфер обмена не поддерживается', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Ошибка копирования', | ||||
|                 description: | ||||
|                     'Что-то пошло не так. Пожалуйста, попробуйте еще раз.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Системная', | ||||
|             light: 'Светлая', | ||||
| @@ -90,7 +105,6 @@ export const ru: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Последнее сохранение', | ||||
|         saved: 'Сохранено', | ||||
|         diagrams: 'Диаграммы', | ||||
|         loading_diagram: 'Загрузка диаграммы...', | ||||
|         deselect_all: 'Отменить выбор всех', | ||||
|         select_all: 'Выбрать все', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const te: LanguageTranslation = { | ||||
|                 theme: 'థీమ్', | ||||
|                 show_dependencies: 'ఆధారాలు చూపించండి', | ||||
|                 hide_dependencies: 'ఆధారాలను దాచండి', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
| @@ -78,6 +81,17 @@ export const te: LanguageTranslation = { | ||||
|             none: 'ఎదరికాదు', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'కాపీ విఫలమైంది', | ||||
|                 description: 'క్లిప్బోర్డ్ మద్దతు ఇవ్వదు', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'కాపీ విఫలమైంది', | ||||
|                 description: 'ఏదో తప్పు జరిగింది. దయచేసి మళ్లీ ప్రయత్నించండి.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'సిస్టమ్', | ||||
|             light: 'హালకా', | ||||
| @@ -91,7 +105,6 @@ export const te: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'చివరిగా సేవ్ చేయబడిన', | ||||
|         saved: 'సేవ్ చేయబడింది', | ||||
|         diagrams: 'చిత్రాలు', | ||||
|         loading_diagram: 'చిత్రం లోడ్ అవుతోంది...', | ||||
|         deselect_all: 'అన్ని ఎంచుకోకుండా ఉంచు', | ||||
|         select_all: 'అన్ని ఎంచుకోండి', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const tr: LanguageTranslation = { | ||||
|                 theme: 'Tema', | ||||
|                 show_dependencies: 'Bağımlılıkları Göster', | ||||
|                 hide_dependencies: 'Bağımlılıkları Gizle', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
| @@ -78,6 +81,17 @@ export const tr: LanguageTranslation = { | ||||
|             none: 'yok', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Kopyalama başarısız', | ||||
|                 description: 'Panoya desteklenmiyor', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Kopyalama başarısız', | ||||
|                 description: 'Bir şeyler ters gitti. Lütfen tekrar deneyin.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Sistem', | ||||
|             light: 'Açık', | ||||
| @@ -91,8 +105,6 @@ export const tr: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Son kaydedilen', | ||||
|         saved: 'Kaydedildi', | ||||
|         diagrams: 'Diyagramlar', | ||||
|  | ||||
|         loading_diagram: 'Diyagram yükleniyor...', | ||||
|         deselect_all: 'Hepsini Seçme', | ||||
|         select_all: 'Hepsini Seç', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const uk: LanguageTranslation = { | ||||
|                 theme: 'Тема', | ||||
|                 show_dependencies: 'Показати залежності', | ||||
|                 hide_dependencies: 'Приховати залежності', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
| @@ -78,6 +81,17 @@ export const uk: LanguageTranslation = { | ||||
|             none: 'немає', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Помилка копіювання', | ||||
|                 description: 'Буфер обміну не підтримується', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Помилка копіювання', | ||||
|                 description: 'Щось пішло не так. Будь ласка, спробуйте ще раз.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'система', | ||||
|             light: 'світлий', | ||||
| @@ -91,7 +105,6 @@ export const uk: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Востаннє збережено', | ||||
|         saved: 'Збережено', | ||||
|         diagrams: 'Діаграми', | ||||
|         loading_diagram: 'Діаграма завантаження...', | ||||
|         deselect_all: 'Зняти вибір із усіх', | ||||
|         select_all: 'Вибрати усі', | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const vi: LanguageTranslation = { | ||||
|                 theme: 'Chủ đề', | ||||
|                 show_dependencies: 'Hiển thị các phụ thuộc', | ||||
|                 hide_dependencies: 'Ẩn các phụ thuộc', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: 'Chia sẻ', | ||||
| @@ -77,6 +80,17 @@ export const vi: LanguageTranslation = { | ||||
|             none: 'không có', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: 'Sao chép thất bại', | ||||
|                 description: 'Không hỗ trợ bảng tạm', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: 'Sao chép thất bại', | ||||
|                 description: 'Đã xảy ra lỗi. Vui lòng thử lại.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Hệ thống', | ||||
|             light: 'Sáng', | ||||
| @@ -90,14 +104,13 @@ export const vi: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: 'Đã lưu lần cuối', | ||||
|         saved: 'Đã lưu', | ||||
|         diagrams: 'Sơ đồ', | ||||
|         loading_diagram: 'Đang tải sơ đồ...', | ||||
|         deselect_all: 'Bỏ chọn tất cả', | ||||
|         select_all: 'Chọn tất cả', | ||||
|         clear: 'Xóa', | ||||
|         show_more: 'Hiển thị thêm', | ||||
|         show_less: 'Hiển thị ít hơn', | ||||
|         copy_to_clipboard: 'Sao chép vào Clipboard', | ||||
|         copy_to_clipboard: 'Sao chép vào bảng tạm', | ||||
|         copied: 'Đã sao chép!', | ||||
|  | ||||
|         side_panel: { | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const zh_CN: LanguageTranslation = { | ||||
|                 theme: '主题', | ||||
|                 show_dependencies: '展示依赖', | ||||
|                 hide_dependencies: '隐藏依赖', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: '分享', | ||||
| @@ -74,6 +77,17 @@ export const zh_CN: LanguageTranslation = { | ||||
|             none: '无', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: '复制失败', | ||||
|                 description: '不支持剪贴板', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: '复制失败', | ||||
|                 description: '出现问题。请再试一次。', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: '系统', | ||||
|             light: '浅色', | ||||
| @@ -87,7 +101,6 @@ export const zh_CN: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: '上次保存时间:', | ||||
|         saved: '已保存', | ||||
|         diagrams: '关系图', | ||||
|         loading_diagram: '加载关系图...', | ||||
|         deselect_all: '取消全选', | ||||
|         select_all: '全选', | ||||
| @@ -384,7 +397,7 @@ export const zh_CN: LanguageTranslation = { | ||||
| }; | ||||
|  | ||||
| export const zh_CNMetadata: LanguageMetadata = { | ||||
|     name: 'Chinese', | ||||
|     name: 'Chinese (Simplified)', | ||||
|     nativeName: '简体中文', | ||||
|     code: 'zh_CN', | ||||
| }; | ||||
|   | ||||
| @@ -30,6 +30,9 @@ export const zh_TW: LanguageTranslation = { | ||||
|                 theme: '主題', | ||||
|                 show_dependencies: '顯示相依性', | ||||
|                 hide_dependencies: '隱藏相依性', | ||||
|                 // TODO: Translate | ||||
|                 show_minimap: 'Show Mini Map', | ||||
|                 hide_minimap: 'Hide Mini Map', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: '分享', | ||||
| @@ -74,6 +77,17 @@ export const zh_TW: LanguageTranslation = { | ||||
|             none: '無', | ||||
|         }, | ||||
|  | ||||
|         copy_to_clipboard_toast: { | ||||
|             unsupported: { | ||||
|                 title: '複製失敗', | ||||
|                 description: '不支援剪貼簿', | ||||
|             }, | ||||
|             failed: { | ||||
|                 title: '複製失敗', | ||||
|                 description: '出現問題。請再試一次。', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: '系統', | ||||
|             light: '淺色', | ||||
| @@ -87,7 +101,6 @@ export const zh_TW: LanguageTranslation = { | ||||
|  | ||||
|         last_saved: '上次儲存於', | ||||
|         saved: '已儲存', | ||||
|         diagrams: '圖表', | ||||
|         loading_diagram: '正在載入圖表...', | ||||
|         deselect_all: '取消所有選取', | ||||
|         select_all: '全選', | ||||
| @@ -384,6 +397,6 @@ export const zh_TW: LanguageTranslation = { | ||||
|  | ||||
| export const zh_TWMetadata: LanguageMetadata = { | ||||
|     nativeName: '繁體中文', | ||||
|     name: 'Traditional Chinese', | ||||
|     name: 'Chinese (Traditional)', | ||||
|     code: 'zh_TW', | ||||
| }; | ||||
|   | ||||
							
								
								
									
										117
									
								
								src/lib/data/data-types/clickhouse-data-types.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,117 @@ | ||||
| import type { DataType } from './data-types'; | ||||
|  | ||||
| export const clickhouseDataTypes: readonly DataType[] = [ | ||||
|     // Numeric Types | ||||
|     { name: 'uint8', id: 'uint8' }, | ||||
|     { name: 'uint16', id: 'uint16' }, | ||||
|     { name: 'uint32', id: 'uint32' }, | ||||
|     { name: 'uint64', id: 'uint64' }, | ||||
|     { name: 'uint128', id: 'uint128' }, | ||||
|     { name: 'uint256', id: 'uint256' }, | ||||
|     { name: 'int8', id: 'int8' }, | ||||
|     { name: 'int16', id: 'int16' }, | ||||
|     { name: 'int32', id: 'int32' }, | ||||
|     { name: 'int64', id: 'int64' }, | ||||
|     { name: 'int128', id: 'int128' }, | ||||
|     { name: 'int256', id: 'int256' }, | ||||
|     { name: 'float32', id: 'float32' }, | ||||
|     { name: 'float64', id: 'float64' }, | ||||
|     { name: 'tinyint', id: 'tinyint' }, | ||||
|     { name: 'int1', id: 'int1' }, | ||||
|     { name: 'byte', id: 'byte' }, | ||||
|     { name: 'tinyint signed', id: 'tinyint_signed' }, | ||||
|     { name: 'int1 signed', id: 'int1_signed' }, | ||||
|     { name: 'smallint', id: 'smallint' }, | ||||
|     { name: 'smallint signed', id: 'smallint_signed' }, | ||||
|     { name: 'int', id: 'int' }, | ||||
|     { name: 'integer', id: 'integer' }, | ||||
|     { name: 'mediumint', id: 'mediumint' }, | ||||
|     { name: 'mediumint signed', id: 'mediumint_signed' }, | ||||
|     { name: 'int signed', id: 'int_signed' }, | ||||
|     { name: 'integer signed', id: 'integer_signed' }, | ||||
|     { name: 'bigint', id: 'bigint' }, | ||||
|     { name: 'signed', id: 'signed' }, | ||||
|     { name: 'bigint signed', id: 'bigint_signed' }, | ||||
|     { name: 'time', id: 'time' }, | ||||
|     { name: 'float', id: 'float' }, | ||||
|     { name: 'double', id: 'double' }, | ||||
|     { name: 'real', id: 'real' }, | ||||
|     { name: 'single', id: 'single' }, | ||||
|     { name: 'double precision', id: 'double_precision' }, | ||||
|  | ||||
|     // string Types | ||||
|     { name: 'longtext', id: 'longtext' }, | ||||
|     { name: 'mediumtext', id: 'mediumtext' }, | ||||
|     { name: 'tinytext', id: 'tinytext' }, | ||||
|     { name: 'text', id: 'text' }, | ||||
|     { name: 'longblob', id: 'longblob' }, | ||||
|     { name: 'mediumblob', id: 'mediumblob' }, | ||||
|     { name: 'tinyblob', id: 'tinyblob' }, | ||||
|     { name: 'blob', id: 'blob' }, | ||||
|     { name: 'varchar', id: 'varchar' }, | ||||
|     { name: 'char', id: 'char' }, | ||||
|     { name: 'char large object', id: 'char_large_object' }, | ||||
|     { name: 'char varying', id: 'char_varying' }, | ||||
|     { name: 'character large object', id: 'character_large_object' }, | ||||
|     { name: 'character varying', id: 'character_varying' }, | ||||
|     { name: 'nchar large object', id: 'nchar_large_object' }, | ||||
|     { name: 'nchar varying', id: 'nchar_varying' }, | ||||
|     { | ||||
|         name: 'national character large object', | ||||
|         id: 'national_character_large_object', | ||||
|     }, | ||||
|     { name: 'national character varying', id: 'national_character_varying' }, | ||||
|     { name: 'national char varying', id: 'national_char_varying' }, | ||||
|     { name: 'national character', id: 'national_character' }, | ||||
|     { name: 'national char', id: 'national_char' }, | ||||
|     { name: 'binary large object', id: 'binary_large_object' }, | ||||
|     { name: 'binary varying', id: 'binary_varying' }, | ||||
|     { name: 'fixedstring', id: 'fixedstring' }, | ||||
|     { name: 'string', id: 'string' }, | ||||
|  | ||||
|     // Date Types | ||||
|     { name: 'date', id: 'date' }, | ||||
|     { name: 'date32', id: 'date32' }, | ||||
|     { name: 'datetime', id: 'datetime' }, | ||||
|     { name: 'datetime64', id: 'datetime64' }, | ||||
|  | ||||
|     // JSON Types | ||||
|     { name: 'object', id: 'object' }, | ||||
|     { name: 'json', id: 'json' }, | ||||
|  | ||||
|     // UUID Type | ||||
|     { name: 'uuid', id: 'uuid' }, | ||||
|  | ||||
|     // Boolean Type | ||||
|     { name: 'boolean', id: 'boolean' }, | ||||
|  | ||||
|     // Enum Type | ||||
|     { name: 'enum', id: 'enum' }, | ||||
|     { name: 'lowcardinality', id: 'lowcardinality' }, | ||||
|  | ||||
|     // Array Type | ||||
|     { name: 'array', id: 'array' }, | ||||
|  | ||||
|     // Tuple Type | ||||
|     { name: 'tuple', id: 'tuple' }, | ||||
|     { name: 'map', id: 'map' }, | ||||
|  | ||||
|     { name: 'simpleaggregatefunction', id: 'simpleaggregatefunction' }, | ||||
|     { name: 'aggregatefunction', id: 'aggregatefunction' }, | ||||
|  | ||||
|     { name: 'nested', id: 'nested' }, | ||||
|  | ||||
|     { name: 'ipv4', id: 'ipv4' }, | ||||
|     { name: 'ipv6', id: 'ipv6' }, | ||||
|  | ||||
|     // Geography Types | ||||
|     { name: 'point', id: 'point' }, | ||||
|     { name: 'ring', id: 'ring' }, | ||||
|     { name: 'polygon', id: 'polygon' }, | ||||
|     { name: 'multipolygon', id: 'multipolygon' }, | ||||
|  | ||||
|     { name: 'expression', id: 'expression' }, | ||||
|     { name: 'set', id: 'set' }, | ||||
|     { name: 'nothing', id: 'nothing' }, | ||||
|     { name: 'interval', id: 'interval' }, | ||||
| ] as const; | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { z } from 'zod'; | ||||
| import { DatabaseType } from '../../domain/database-type'; | ||||
| import { clickhouseDataTypes } from './clickhouse-data-types'; | ||||
| import { genericDataTypes } from './generic-data-types'; | ||||
| import { mariadbDataTypes } from './mariadb-data-types'; | ||||
| import { mysqlDataTypes } from './mysql-data-types'; | ||||
| @@ -24,6 +25,8 @@ export const dataTypeMap: Record<DatabaseType, readonly DataType[]> = { | ||||
|     [DatabaseType.SQL_SERVER]: sqlServerDataTypes, | ||||
|     [DatabaseType.MARIADB]: mariadbDataTypes, | ||||
|     [DatabaseType.SQLITE]: sqliteDataTypes, | ||||
|     [DatabaseType.CLICKHOUSE]: clickhouseDataTypes, | ||||
|     [DatabaseType.COCKROACHDB]: postgresDataTypes, | ||||
| } as const; | ||||
|  | ||||
| const compatibleTypes: Record<DatabaseType, Record<string, string[]>> = { | ||||
| @@ -39,6 +42,8 @@ const compatibleTypes: Record<DatabaseType, Record<string, string[]>> = { | ||||
|     [DatabaseType.SQL_SERVER]: {}, | ||||
|     [DatabaseType.MARIADB]: {}, | ||||
|     [DatabaseType.SQLITE]: {}, | ||||
|     [DatabaseType.CLICKHOUSE]: {}, | ||||
|     [DatabaseType.COCKROACHDB]: {}, | ||||
|     [DatabaseType.GENERIC]: {}, | ||||
| }; | ||||
|  | ||||
|   | ||||