Compare commits
	
		
			23 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 24db32369a | ||
|  | e77ee60a5b | ||
|  | 6c65c2e9cc | ||
|  | 70f545f78b | ||
|  | fb702c87ce | ||
|  | eaa067814f | ||
|  | 667685ed0f | ||
|  | 2940431efa | ||
|  | 94ec43b608 | ||
|  | a2efed803f | ||
|  | 8749591be0 | ||
|  | c5e0ea6fa4 | ||
|  | ab07da0b03 | ||
|  | 8397bef392 | ||
|  | 7c3c62860e | ||
|  | 76ba4ce4c5 | ||
|  | 0c0fad719f | ||
|  | b75c6fe4e7 | ||
|  | d9fcbeec72 | ||
|  | 5d79721b6d | ||
|  | 4be3592cf4 | ||
|  | b4cdcbbbd7 | ||
|  | e9c7f4be06 | 
							
								
								
									
										26
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						| @@ -1,5 +1,31 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## [1.3.0](https://github.com/chartdb/chartdb/compare/v1.2.0...v1.3.0) (2024-11-25) | ||||
|  | ||||
|  | ||||
| ### Features | ||||
|  | ||||
| * **side panel:** collapsible side panel on desktop view + keyboard shortcut ([#439](https://github.com/chartdb/chartdb/issues/439)) ([70f545f](https://github.com/chartdb/chartdb/commit/70f545f78bab9c510a6e5936fa5b259b806b6c69)) | ||||
|  | ||||
|  | ||||
| ### Bug Fixes | ||||
|  | ||||
| * **dialogs:** fix height of dialogs for small screens ([#440](https://github.com/chartdb/chartdb/issues/440)) ([667685e](https://github.com/chartdb/chartdb/commit/667685ed0f6a8cc61ae86b3ba60e052fbe6a9e1a)) | ||||
| * **drawer:** set fix min size ([#429](https://github.com/chartdb/chartdb/issues/429)) ([c5e0ea6](https://github.com/chartdb/chartdb/commit/c5e0ea6fa4017666ff3bc1e3071c487df48afd3d)) | ||||
| * **export-sql:** add unique to export script ([#422](https://github.com/chartdb/chartdb/issues/422)) ([b75c6fe](https://github.com/chartdb/chartdb/commit/b75c6fe4e78f3e2058be680f2fa0442db3b4a6bd)) | ||||
| * fix layout warnings ([#434](https://github.com/chartdb/chartdb/issues/434)) ([94ec43b](https://github.com/chartdb/chartdb/commit/94ec43b60845bb8c3592ce1b1450ca0171a53f99)) | ||||
| * **i18n:** add bahasa indonesia translation ([#331](https://github.com/chartdb/chartdb/issues/331)) ([ab07da0](https://github.com/chartdb/chartdb/commit/ab07da0b031f0d4050ff6b44ddcb94cb6c0010b6)) | ||||
| * **i18n:** add missing type to vi.ts ([#444](https://github.com/chartdb/chartdb/issues/444)) ([e77ee60](https://github.com/chartdb/chartdb/commit/e77ee60a5b47e0854d11b0ee2f16d6956737d0ff)) | ||||
| * **i18n:** Add Telugu Language ([#352](https://github.com/chartdb/chartdb/issues/352)) ([8749591](https://github.com/chartdb/chartdb/commit/8749591be036e131de4bfeed1e6eece8d62980dd)) | ||||
| * **i18n:** add Turkish translations ([#315](https://github.com/chartdb/chartdb/issues/315)) ([d9fcbee](https://github.com/chartdb/chartdb/commit/d9fcbeec726b7bde9f7d202bf09dc6b617e3ad80)) | ||||
| * **i18n:** add Vietnamese translations ([#435](https://github.com/chartdb/chartdb/issues/435)) ([6c65c2e](https://github.com/chartdb/chartdb/commit/6c65c2e9cce600b9778b84ce5b5f1625dc6f1a58)) | ||||
| * **i18n:** Translating to Gujarati language ([#433](https://github.com/chartdb/chartdb/issues/433)) ([2940431](https://github.com/chartdb/chartdb/commit/2940431efa1a6aa54d80c61d5e05f0ad47cd67ba)) | ||||
| * **i18n:** Translation of the export error into Russian ([#418](https://github.com/chartdb/chartdb/issues/418)) ([7c3c628](https://github.com/chartdb/chartdb/commit/7c3c62860efc98d3aabf2132a79ac945ffc8315a)) | ||||
| * **i18n:** update korean for 1.2.0 ([#419](https://github.com/chartdb/chartdb/issues/419)) ([8397bef](https://github.com/chartdb/chartdb/commit/8397bef3924610d94661aae99c55ba4fa376a186)) | ||||
| * **import script:** remove double quotes ([#442](https://github.com/chartdb/chartdb/issues/442)) ([fb702c8](https://github.com/chartdb/chartdb/commit/fb702c87ce5254bf6e0209c692305f5086956090)) | ||||
| * **share:** fix export to handle broken indexes & relationships ([#416](https://github.com/chartdb/chartdb/issues/416)) ([4be3592](https://github.com/chartdb/chartdb/commit/4be3592cf4d160be83ddf1db01ffe9afdef119fa)) | ||||
| * **templates:** add Five more templates (bouncer, cabot, feedbin, Pythonic, flarum, freescout) ([#441](https://github.com/chartdb/chartdb/issues/441)) ([eaa0678](https://github.com/chartdb/chartdb/commit/eaa067814fd96fcc1ee10488ee747a71a8e8ec7a)) | ||||
|  | ||||
| ## [1.2.0](https://github.com/chartdb/chartdb/compare/v1.1.0...v1.2.0) (2024-11-17) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
| <h3 align="center"> | ||||
|   <a href="https://discord.gg/QeFwyWSKwC">Community</a>  • | ||||
|   <a href="https://www.chartdb.io?ref=github_readme">Website</a>  • | ||||
|   <a href="https://chartdb.io/templates?ref=github_readme">Examples</a>  • | ||||
|   <a href="https://app.chartdb.io?ref=github_readme">Demo</a> | ||||
| </h3> | ||||
|  | ||||
|   | ||||
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						| @@ -1,12 +1,12 @@ | ||||
| { | ||||
|   "name": "chartdb", | ||||
|   "version": "1.2.0", | ||||
|   "version": "1.3.0", | ||||
|   "lockfileVersion": 3, | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "chartdb", | ||||
|       "version": "1.2.0", | ||||
|       "version": "1.3.0", | ||||
|       "dependencies": { | ||||
|         "@ai-sdk/openai": "^0.0.51", | ||||
|         "@dnd-kit/sortable": "^8.0.0", | ||||
|   | ||||
							
								
								
									
										190
									
								
								package.json
									
									
									
									
									
								
							
							
						
						| @@ -1,97 +1,97 @@ | ||||
| { | ||||
|   "name": "chartdb", | ||||
|   "private": true, | ||||
|   "version": "1.2.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:fix": "npm run lint -- --fix", | ||||
|     "preview": "vite preview", | ||||
|     "prepare": "husky" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@ai-sdk/openai": "^0.0.51", | ||||
|     "@dnd-kit/sortable": "^8.0.0", | ||||
|     "@monaco-editor/react": "^4.6.0", | ||||
|     "@radix-ui/react-accordion": "^1.2.0", | ||||
|     "@radix-ui/react-alert-dialog": "^1.1.1", | ||||
|     "@radix-ui/react-avatar": "^1.1.0", | ||||
|     "@radix-ui/react-checkbox": "^1.1.1", | ||||
|     "@radix-ui/react-collapsible": "^1.1.0", | ||||
|     "@radix-ui/react-context-menu": "^2.2.1", | ||||
|     "@radix-ui/react-dialog": "^1.1.1", | ||||
|     "@radix-ui/react-dropdown-menu": "^2.1.1", | ||||
|     "@radix-ui/react-hover-card": "^1.1.1", | ||||
|     "@radix-ui/react-icons": "^1.3.0", | ||||
|     "@radix-ui/react-label": "^2.1.0", | ||||
|     "@radix-ui/react-menubar": "^1.1.1", | ||||
|     "@radix-ui/react-popover": "^1.1.1", | ||||
|     "@radix-ui/react-scroll-area": "^1.1.0", | ||||
|     "@radix-ui/react-select": "^2.1.1", | ||||
|     "@radix-ui/react-separator": "^1.1.0", | ||||
|     "@radix-ui/react-slot": "^1.1.0", | ||||
|     "@radix-ui/react-tabs": "^1.1.0", | ||||
|     "@radix-ui/react-toast": "^1.2.1", | ||||
|     "@radix-ui/react-toggle": "^1.1.0", | ||||
|     "@radix-ui/react-toggle-group": "^1.1.0", | ||||
|     "@radix-ui/react-tooltip": "^1.1.2", | ||||
|     "@uidotdev/usehooks": "^2.4.1", | ||||
|     "@xyflow/react": "^12.3.1", | ||||
|     "ahooks": "^3.8.1", | ||||
|     "ai": "^3.3.14", | ||||
|     "class-variance-authority": "^0.7.0", | ||||
|     "clsx": "^2.1.1", | ||||
|     "cmdk": "^1.0.0", | ||||
|     "dexie": "^4.0.8", | ||||
|     "fast-deep-equal": "^3.1.3", | ||||
|     "html-to-image": "^1.11.11", | ||||
|     "i18next": "^23.14.0", | ||||
|     "i18next-browser-languagedetector": "^8.0.0", | ||||
|     "lucide-react": "^0.441.0", | ||||
|     "monaco-editor": "^0.52.0", | ||||
|     "nanoid": "^5.0.7", | ||||
|     "node-sql-parser": "^5.3.2", | ||||
|     "react": "^18.3.1", | ||||
|     "react-dom": "^18.3.1", | ||||
|     "react-helmet-async": "^2.0.5", | ||||
|     "react-hotkeys-hook": "^4.5.0", | ||||
|     "react-i18next": "^15.0.1", | ||||
|     "react-resizable-panels": "^2.0.22", | ||||
|     "react-responsive": "^10.0.0", | ||||
|     "react-router-dom": "^6.26.0", | ||||
|     "react-use": "^17.5.1", | ||||
|     "tailwind-merge": "^2.4.0", | ||||
|     "tailwindcss-animate": "^1.0.7", | ||||
|     "timeago-react": "^3.0.6", | ||||
|     "vaul": "^0.9.1", | ||||
|     "zod": "^3.23.8" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@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", | ||||
|     "@vitejs/plugin-react": "^4.3.1", | ||||
|     "autoprefixer": "^10.4.20", | ||||
|     "eslint": "^8.57.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-refresh": "^0.4.7", | ||||
|     "eslint-plugin-tailwindcss": "^3.17.4", | ||||
|     "husky": "^9.1.5", | ||||
|     "postcss": "^8.4.40", | ||||
|     "prettier": "^3.3.3", | ||||
|     "rollup-plugin-visualizer": "^5.12.0", | ||||
|     "tailwindcss": "^3.4.7", | ||||
|     "typescript": "^5.2.2", | ||||
|     "unplugin-inject-preload": "^3.0.0", | ||||
|     "vite": "^5.3.4" | ||||
|   } | ||||
|     "name": "chartdb", | ||||
|     "private": true, | ||||
|     "version": "1.3.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:fix": "npm run lint -- --fix", | ||||
|         "preview": "vite preview", | ||||
|         "prepare": "husky" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@ai-sdk/openai": "^0.0.51", | ||||
|         "@dnd-kit/sortable": "^8.0.0", | ||||
|         "@monaco-editor/react": "^4.6.0", | ||||
|         "@radix-ui/react-accordion": "^1.2.0", | ||||
|         "@radix-ui/react-alert-dialog": "^1.1.1", | ||||
|         "@radix-ui/react-avatar": "^1.1.0", | ||||
|         "@radix-ui/react-checkbox": "^1.1.1", | ||||
|         "@radix-ui/react-collapsible": "^1.1.0", | ||||
|         "@radix-ui/react-context-menu": "^2.2.1", | ||||
|         "@radix-ui/react-dialog": "^1.1.1", | ||||
|         "@radix-ui/react-dropdown-menu": "^2.1.1", | ||||
|         "@radix-ui/react-hover-card": "^1.1.1", | ||||
|         "@radix-ui/react-icons": "^1.3.0", | ||||
|         "@radix-ui/react-label": "^2.1.0", | ||||
|         "@radix-ui/react-menubar": "^1.1.1", | ||||
|         "@radix-ui/react-popover": "^1.1.1", | ||||
|         "@radix-ui/react-scroll-area": "^1.1.0", | ||||
|         "@radix-ui/react-select": "^2.1.1", | ||||
|         "@radix-ui/react-separator": "^1.1.0", | ||||
|         "@radix-ui/react-slot": "^1.1.0", | ||||
|         "@radix-ui/react-tabs": "^1.1.0", | ||||
|         "@radix-ui/react-toast": "^1.2.1", | ||||
|         "@radix-ui/react-toggle": "^1.1.0", | ||||
|         "@radix-ui/react-toggle-group": "^1.1.0", | ||||
|         "@radix-ui/react-tooltip": "^1.1.2", | ||||
|         "@uidotdev/usehooks": "^2.4.1", | ||||
|         "@xyflow/react": "^12.3.1", | ||||
|         "ahooks": "^3.8.1", | ||||
|         "ai": "^3.3.14", | ||||
|         "class-variance-authority": "^0.7.0", | ||||
|         "clsx": "^2.1.1", | ||||
|         "cmdk": "^1.0.0", | ||||
|         "dexie": "^4.0.8", | ||||
|         "fast-deep-equal": "^3.1.3", | ||||
|         "html-to-image": "^1.11.11", | ||||
|         "i18next": "^23.14.0", | ||||
|         "i18next-browser-languagedetector": "^8.0.0", | ||||
|         "lucide-react": "^0.441.0", | ||||
|         "monaco-editor": "^0.52.0", | ||||
|         "nanoid": "^5.0.7", | ||||
|         "node-sql-parser": "^5.3.2", | ||||
|         "react": "^18.3.1", | ||||
|         "react-dom": "^18.3.1", | ||||
|         "react-helmet-async": "^2.0.5", | ||||
|         "react-hotkeys-hook": "^4.5.0", | ||||
|         "react-i18next": "^15.0.1", | ||||
|         "react-resizable-panels": "^2.0.22", | ||||
|         "react-responsive": "^10.0.0", | ||||
|         "react-router-dom": "^6.26.0", | ||||
|         "react-use": "^17.5.1", | ||||
|         "tailwind-merge": "^2.4.0", | ||||
|         "tailwindcss-animate": "^1.0.7", | ||||
|         "timeago-react": "^3.0.6", | ||||
|         "vaul": "^0.9.1", | ||||
|         "zod": "^3.23.8" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@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", | ||||
|         "@vitejs/plugin-react": "^4.3.1", | ||||
|         "autoprefixer": "^10.4.20", | ||||
|         "eslint": "^8.57.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-refresh": "^0.4.7", | ||||
|         "eslint-plugin-tailwindcss": "^3.17.4", | ||||
|         "husky": "^9.1.5", | ||||
|         "postcss": "^8.4.40", | ||||
|         "prettier": "^3.3.3", | ||||
|         "rollup-plugin-visualizer": "^5.12.0", | ||||
|         "tailwindcss": "^3.4.7", | ||||
|         "typescript": "^5.2.2", | ||||
|         "unplugin-inject-preload": "^3.0.0", | ||||
|         "vite": "^5.3.4" | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/bouncer-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 323 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/bouncer-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 348 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/cabot-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 420 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/cabot-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 498 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/feedbin-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 498 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/feedbin-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 583 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/flarum-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 412 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/flarum-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 499 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/freescout-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 441 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/freescout-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 502 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/hacker-news-db-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 427 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/templates/hacker-news-db.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 472 KiB | 
| @@ -3,6 +3,7 @@ import * as DialogPrimitive from '@radix-ui/react-dialog'; | ||||
| import { Cross2Icon } from '@radix-ui/react-icons'; | ||||
|  | ||||
| import { cn } from '@/lib/utils'; | ||||
| import { ScrollArea } from '../scroll-area/scroll-area'; | ||||
|  | ||||
| const Dialog = DialogPrimitive.Root; | ||||
|  | ||||
| @@ -110,6 +111,18 @@ const DialogDescription = React.forwardRef< | ||||
| )); | ||||
| DialogDescription.displayName = DialogPrimitive.Description.displayName; | ||||
|  | ||||
| const DialogInternalContent = React.forwardRef< | ||||
|     React.ElementRef<typeof ScrollArea>, | ||||
|     React.ComponentPropsWithoutRef<typeof ScrollArea> | ||||
| >(({ className, ...props }, ref) => ( | ||||
|     <ScrollArea | ||||
|         ref={ref} | ||||
|         className={cn('flex max-h-screen flex-col overflow-y-auto', className)} | ||||
|         {...props} | ||||
|     /> | ||||
| )); | ||||
| DialogInternalContent.displayName = 'DialogInternalContent'; | ||||
|  | ||||
| export { | ||||
|     Dialog, | ||||
|     DialogPortal, | ||||
| @@ -121,4 +134,5 @@ export { | ||||
|     DialogFooter, | ||||
|     DialogTitle, | ||||
|     DialogDescription, | ||||
|     DialogInternalContent, | ||||
| }; | ||||
|   | ||||
| @@ -12,7 +12,7 @@ const ScrollArea = React.forwardRef< | ||||
|         className={cn('relative overflow-hidden', className)} | ||||
|         {...props} | ||||
|     > | ||||
|         <ScrollAreaPrimitive.Viewport className="scrollable-flex size-full rounded-[inherit]"> | ||||
|         <ScrollAreaPrimitive.Viewport className="size-full rounded-[inherit]"> | ||||
|             {children} | ||||
|         </ScrollAreaPrimitive.Viewport> | ||||
|         <ScrollBar /> | ||||
| @@ -40,7 +40,7 @@ const ScrollBar = React.forwardRef< | ||||
|         )} | ||||
|         {...props} | ||||
|     > | ||||
|         <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" /> | ||||
|         <ScrollAreaPrimitive.ScrollAreaThumb className="relative z-20 flex-1 rounded-full bg-border" /> | ||||
|     </ScrollAreaPrimitive.ScrollAreaScrollbar> | ||||
| )); | ||||
| ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import { | ||||
| import { useHistory } from '@/hooks/use-history'; | ||||
| import { useDialog } from '@/hooks/use-dialog'; | ||||
| import { useChartDB } from '@/hooks/use-chartdb'; | ||||
| import { useLayout } from '@/hooks/use-layout'; | ||||
|  | ||||
| export const KeyboardShortcutsProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|     children, | ||||
| @@ -15,6 +16,8 @@ export const KeyboardShortcutsProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|     const { redo, undo } = useHistory(); | ||||
|     const { openOpenDiagramDialog } = useDialog(); | ||||
|     const { updateDiagramUpdatedAt } = useChartDB(); | ||||
|     const { toggleSidePanel } = useLayout(); | ||||
|  | ||||
|     useHotkeys( | ||||
|         keyboardShortcutsForOS[KeyboardShortcutAction.REDO].keyCombination, | ||||
|         redo, | ||||
| @@ -49,6 +52,15 @@ export const KeyboardShortcutsProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|         }, | ||||
|         [updateDiagramUpdatedAt] | ||||
|     ); | ||||
|     useHotkeys( | ||||
|         keyboardShortcutsForOS[KeyboardShortcutAction.TOGGLE_SIDE_PANEL] | ||||
|             .keyCombination, | ||||
|         toggleSidePanel, | ||||
|         { | ||||
|             preventDefault: true, | ||||
|         }, | ||||
|         [toggleSidePanel] | ||||
|     ); | ||||
|  | ||||
|     return ( | ||||
|         <keyboardShortcutsContext.Provider value={{}}> | ||||
|   | ||||
| @@ -5,6 +5,7 @@ export enum KeyboardShortcutAction { | ||||
|     UNDO = 'undo', | ||||
|     OPEN_DIAGRAM = 'open_diagram', | ||||
|     SAVE_DIAGRAM = 'save_diagram', | ||||
|     TOGGLE_SIDE_PANEL = 'toggle_side_panel', | ||||
| } | ||||
|  | ||||
| export interface KeyboardShortcut { | ||||
| @@ -47,6 +48,13 @@ export const keyboardShortcuts: Record< | ||||
|         keyCombinationMac: 'meta+s', | ||||
|         keyCombinationWin: 'ctrl+s', | ||||
|     }, | ||||
|     [KeyboardShortcutAction.TOGGLE_SIDE_PANEL]: { | ||||
|         action: KeyboardShortcutAction.TOGGLE_SIDE_PANEL, | ||||
|         keyCombinationLabelMac: '⌘B', | ||||
|         keyCombinationLabelWin: 'Ctrl+B', | ||||
|         keyCombinationMac: 'meta+b', | ||||
|         keyCombinationWin: 'ctrl+b', | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| export interface KeyboardShortcutForOS { | ||||
|   | ||||
| @@ -22,6 +22,7 @@ export interface LayoutContext { | ||||
|     isSidePanelShowed: boolean; | ||||
|     hideSidePanel: () => void; | ||||
|     showSidePanel: () => void; | ||||
|     toggleSidePanel: () => void; | ||||
|  | ||||
|     isSelectSchemaOpen: boolean; | ||||
|     openSelectSchema: () => void; | ||||
| @@ -47,6 +48,7 @@ export const layoutContext = createContext<LayoutContext>({ | ||||
|     isSidePanelShowed: false, | ||||
|     hideSidePanel: emptyFn, | ||||
|     showSidePanel: emptyFn, | ||||
|     toggleSidePanel: emptyFn, | ||||
|  | ||||
|     isSelectSchemaOpen: false, | ||||
|     openSelectSchema: emptyFn, | ||||
|   | ||||
| @@ -36,6 +36,10 @@ export const LayoutProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|     const showSidePanel: LayoutContext['showSidePanel'] = () => | ||||
|         setIsSidePanelShowed(true); | ||||
|  | ||||
|     const toggleSidePanel: LayoutContext['toggleSidePanel'] = () => { | ||||
|         setIsSidePanelShowed((prevIsSidePanelShowed) => !prevIsSidePanelShowed); | ||||
|     }; | ||||
|  | ||||
|     const openTableFromSidebar: LayoutContext['openTableFromSidebar'] = ( | ||||
|         tableId | ||||
|     ) => { | ||||
| @@ -77,6 +81,7 @@ export const LayoutProvider: React.FC<React.PropsWithChildren> = ({ | ||||
|                 isSidePanelShowed, | ||||
|                 hideSidePanel, | ||||
|                 showSidePanel, | ||||
|                 toggleSidePanel, | ||||
|                 isSelectSchemaOpen, | ||||
|                 openSelectSchema, | ||||
|                 closeSelectSchema, | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import { | ||||
|     DialogDescription, | ||||
|     DialogFooter, | ||||
|     DialogHeader, | ||||
|     DialogInternalContent, | ||||
|     DialogTitle, | ||||
| } from '@/components/dialog/dialog'; | ||||
| import { ToggleGroup, ToggleGroupItem } from '@/components/toggle/toggle-group'; | ||||
| @@ -139,6 +140,7 @@ export const ImportDatabase: React.FC<ImportDatabaseProps> = ({ | ||||
|             setScriptResult(fixedJson); | ||||
|             setErrorMessage(''); | ||||
|         } else { | ||||
|             setScriptResult(fixedJson); | ||||
|             setErrorMessage(errorScriptOutputMessage); | ||||
|         } | ||||
|  | ||||
| @@ -157,188 +159,201 @@ export const ImportDatabase: React.FC<ImportDatabaseProps> = ({ | ||||
|  | ||||
|     const renderContent = useCallback(() => { | ||||
|         return ( | ||||
|             <div className="flex w-full flex-1 flex-col gap-6"> | ||||
|                 {databaseTypeToEditionMap[databaseType].length > 0 ? ( | ||||
|                     <div className="flex flex-col gap-1 md:flex-row"> | ||||
|                         <p className="text-sm leading-6 text-muted-foreground"> | ||||
|                             {t( | ||||
|                                 'new_diagram_dialog.import_database.database_edition' | ||||
|                             )} | ||||
|                         </p> | ||||
|                         <ToggleGroup | ||||
|                             type="single" | ||||
|                             className="ml-1 flex-wrap gap-2" | ||||
|                             value={ | ||||
|                                 !databaseEdition ? 'regular' : databaseEdition | ||||
|                             } | ||||
|                             onValueChange={(value) => { | ||||
|                                 setDatabaseEdition( | ||||
|                                     value === 'regular' | ||||
|                                         ? undefined | ||||
|                                         : (value as DatabaseEdition) | ||||
|                                 ); | ||||
|                             }} | ||||
|                         > | ||||
|                             <ToggleGroupItem | ||||
|                                 value="regular" | ||||
|                                 variant="outline" | ||||
|                                 className="h-6 gap-1 p-0 px-2 shadow-none" | ||||
|             <DialogInternalContent> | ||||
|                 <div className="flex w-full flex-1 flex-col gap-6"> | ||||
|                     {databaseTypeToEditionMap[databaseType].length > 0 ? ( | ||||
|                         <div className="flex flex-col gap-1 md:flex-row"> | ||||
|                             <p className="text-sm leading-6 text-muted-foreground"> | ||||
|                                 {t( | ||||
|                                     'new_diagram_dialog.import_database.database_edition' | ||||
|                                 )} | ||||
|                             </p> | ||||
|                             <ToggleGroup | ||||
|                                 type="single" | ||||
|                                 className="ml-1 flex-wrap gap-2" | ||||
|                                 value={ | ||||
|                                     !databaseEdition | ||||
|                                         ? 'regular' | ||||
|                                         : databaseEdition | ||||
|                                 } | ||||
|                                 onValueChange={(value) => { | ||||
|                                     setDatabaseEdition( | ||||
|                                         value === 'regular' | ||||
|                                             ? undefined | ||||
|                                             : (value as DatabaseEdition) | ||||
|                                     ); | ||||
|                                 }} | ||||
|                             > | ||||
|                                 <Avatar className="size-4 rounded-none"> | ||||
|                                     <AvatarImage | ||||
|                                         src={ | ||||
|                                             databaseSecondaryLogoMap[ | ||||
|                                                 databaseType | ||||
|                                             ] | ||||
|                                         } | ||||
|                                         alt="Regular" | ||||
|                                     /> | ||||
|                                     <AvatarFallback>Regular</AvatarFallback> | ||||
|                                 </Avatar> | ||||
|                                 Regular | ||||
|                             </ToggleGroupItem> | ||||
|                             {databaseTypeToEditionMap[databaseType].map( | ||||
|                                 (edition) => ( | ||||
|                                     <ToggleGroupItem | ||||
|                                         value={edition} | ||||
|                                         key={edition} | ||||
|                                         variant="outline" | ||||
|                                         className="h-6 gap-1 p-0 px-2 shadow-none" | ||||
|                                     > | ||||
|                                         <Avatar className="size-4"> | ||||
|                                             <AvatarImage | ||||
|                                                 src={ | ||||
|                                                     databaseEditionToImageMap[ | ||||
|                                                         edition | ||||
|                                                     ] | ||||
|                                                 } | ||||
|                                                 alt={ | ||||
|                                                     databaseEditionToLabelMap[ | ||||
|                                                         edition | ||||
|                                                     ] | ||||
|                                                 } | ||||
|                                             /> | ||||
|                                             <AvatarFallback> | ||||
|                                                 { | ||||
|                                                     databaseEditionToLabelMap[ | ||||
|                                                         edition | ||||
|                                                     ] | ||||
|                                                 } | ||||
|                                             </AvatarFallback> | ||||
|                                         </Avatar> | ||||
|                                         {databaseEditionToLabelMap[edition]} | ||||
|                                     </ToggleGroupItem> | ||||
|                                 ) | ||||
|                             )} | ||||
|                         </ToggleGroup> | ||||
|                     </div> | ||||
|                 ) : null} | ||||
|                 <div className="flex flex-col gap-1"> | ||||
|                     <div className="flex flex-col gap-1 text-sm text-muted-foreground md:flex-row md:justify-between"> | ||||
|                         <div> | ||||
|                             1. {t('new_diagram_dialog.import_database.step_1')} | ||||
|                         </div> | ||||
|                         {databaseType === DatabaseType.SQL_SERVER && ( | ||||
|                             <SSMSInfo /> | ||||
|                         )} | ||||
|                     </div> | ||||
|                     {databaseTypeToClientsMap[databaseType].length > 0 ? ( | ||||
|                         <Tabs | ||||
|                             value={ | ||||
|                                 !databaseClient ? 'dbclient' : databaseClient | ||||
|                             } | ||||
|                             onValueChange={(value) => { | ||||
|                                 setDatabaseClient( | ||||
|                                     value === 'dbclient' | ||||
|                                         ? undefined | ||||
|                                         : (value as DatabaseClient) | ||||
|                                 ); | ||||
|                             }} | ||||
|                         > | ||||
|                             <div className="flex flex-1"> | ||||
|                                 <TabsList className="h-8 justify-start rounded-none rounded-t-sm "> | ||||
|                                     <TabsTrigger | ||||
|                                         value="dbclient" | ||||
|                                         className="h-6 w-20" | ||||
|                                     > | ||||
|                                         DB Client | ||||
|                                     </TabsTrigger> | ||||
|  | ||||
|                                     {databaseClients?.map((client) => ( | ||||
|                                         <TabsTrigger | ||||
|                                             key={client} | ||||
|                                             value={client} | ||||
|                                             className="h-6 !w-20" | ||||
|                                 <ToggleGroupItem | ||||
|                                     value="regular" | ||||
|                                     variant="outline" | ||||
|                                     className="h-6 gap-1 p-0 px-2 shadow-none" | ||||
|                                 > | ||||
|                                     <Avatar className="size-4 rounded-none"> | ||||
|                                         <AvatarImage | ||||
|                                             src={ | ||||
|                                                 databaseSecondaryLogoMap[ | ||||
|                                                     databaseType | ||||
|                                                 ] | ||||
|                                             } | ||||
|                                             alt="Regular" | ||||
|                                         /> | ||||
|                                         <AvatarFallback>Regular</AvatarFallback> | ||||
|                                     </Avatar> | ||||
|                                     Regular | ||||
|                                 </ToggleGroupItem> | ||||
|                                 {databaseTypeToEditionMap[databaseType].map( | ||||
|                                     (edition) => ( | ||||
|                                         <ToggleGroupItem | ||||
|                                             value={edition} | ||||
|                                             key={edition} | ||||
|                                             variant="outline" | ||||
|                                             className="h-6 gap-1 p-0 px-2 shadow-none" | ||||
|                                         > | ||||
|                                             {databaseClientToLabelMap[client]} | ||||
|                                         </TabsTrigger> | ||||
|                                     )) ?? []} | ||||
|                                 </TabsList> | ||||
|                                             <Avatar className="size-4"> | ||||
|                                                 <AvatarImage | ||||
|                                                     src={ | ||||
|                                                         databaseEditionToImageMap[ | ||||
|                                                             edition | ||||
|                                                         ] | ||||
|                                                     } | ||||
|                                                     alt={ | ||||
|                                                         databaseEditionToLabelMap[ | ||||
|                                                             edition | ||||
|                                                         ] | ||||
|                                                     } | ||||
|                                                 /> | ||||
|                                                 <AvatarFallback> | ||||
|                                                     { | ||||
|                                                         databaseEditionToLabelMap[ | ||||
|                                                             edition | ||||
|                                                         ] | ||||
|                                                     } | ||||
|                                                 </AvatarFallback> | ||||
|                                             </Avatar> | ||||
|                                             {databaseEditionToLabelMap[edition]} | ||||
|                                         </ToggleGroupItem> | ||||
|                                     ) | ||||
|                                 )} | ||||
|                             </ToggleGroup> | ||||
|                         </div> | ||||
|                     ) : null} | ||||
|                     <div className="flex flex-col gap-1"> | ||||
|                         <div className="flex flex-col gap-1 text-sm text-muted-foreground md:flex-row md:justify-between"> | ||||
|                             <div> | ||||
|                                 1.{' '} | ||||
|                                 {t('new_diagram_dialog.import_database.step_1')} | ||||
|                             </div> | ||||
|                             {databaseType === DatabaseType.SQL_SERVER && ( | ||||
|                                 <SSMSInfo /> | ||||
|                             )} | ||||
|                         </div> | ||||
|                         {databaseTypeToClientsMap[databaseType].length > 0 ? ( | ||||
|                             <Tabs | ||||
|                                 value={ | ||||
|                                     !databaseClient | ||||
|                                         ? 'dbclient' | ||||
|                                         : databaseClient | ||||
|                                 } | ||||
|                                 onValueChange={(value) => { | ||||
|                                     setDatabaseClient( | ||||
|                                         value === 'dbclient' | ||||
|                                             ? undefined | ||||
|                                             : (value as DatabaseClient) | ||||
|                                     ); | ||||
|                                 }} | ||||
|                             > | ||||
|                                 <div className="flex flex-1"> | ||||
|                                     <TabsList className="h-8 justify-start rounded-none rounded-t-sm "> | ||||
|                                         <TabsTrigger | ||||
|                                             value="dbclient" | ||||
|                                             className="h-6 w-20" | ||||
|                                         > | ||||
|                                             DB Client | ||||
|                                         </TabsTrigger> | ||||
|  | ||||
|                                         {databaseClients?.map((client) => ( | ||||
|                                             <TabsTrigger | ||||
|                                                 key={client} | ||||
|                                                 value={client} | ||||
|                                                 className="h-6 !w-20" | ||||
|                                             > | ||||
|                                                 { | ||||
|                                                     databaseClientToLabelMap[ | ||||
|                                                         client | ||||
|                                                     ] | ||||
|                                                 } | ||||
|                                             </TabsTrigger> | ||||
|                                         )) ?? []} | ||||
|                                     </TabsList> | ||||
|                                 </div> | ||||
|                                 <CodeSnippet | ||||
|                                     className="h-40 w-full" | ||||
|                                     loading={!importMetadataScripts} | ||||
|                                     code={ | ||||
|                                         importMetadataScripts?.[databaseType]?.( | ||||
|                                             { | ||||
|                                                 databaseEdition, | ||||
|                                                 databaseClient, | ||||
|                                             } | ||||
|                                         ) ?? '' | ||||
|                                     } | ||||
|                                     language={databaseClient ? 'shell' : 'sql'} | ||||
|                                 /> | ||||
|                             </Tabs> | ||||
|                         ) : ( | ||||
|                             <CodeSnippet | ||||
|                                 className="h-40 w-full" | ||||
|                                 className="h-40 w-full flex-auto" | ||||
|                                 loading={!importMetadataScripts} | ||||
|                                 code={ | ||||
|                                     importMetadataScripts?.[databaseType]?.({ | ||||
|                                         databaseEdition, | ||||
|                                         databaseClient, | ||||
|                                     }) ?? '' | ||||
|                                 } | ||||
|                                 language={databaseClient ? 'shell' : 'sql'} | ||||
|                                 language="sql" | ||||
|                             /> | ||||
|                         </Tabs> | ||||
|                     ) : ( | ||||
|                         <CodeSnippet | ||||
|                             className="h-40 w-full flex-auto" | ||||
|                             loading={!importMetadataScripts} | ||||
|                             code={ | ||||
|                                 importMetadataScripts?.[databaseType]?.({ | ||||
|                                     databaseEdition, | ||||
|                                 }) ?? '' | ||||
|                             } | ||||
|                             language="sql" | ||||
|                         /> | ||||
|                     )} | ||||
|                 </div> | ||||
|                 <div className="flex h-48 flex-col gap-1"> | ||||
|                     <p className="text-sm text-muted-foreground"> | ||||
|                         2. {t('new_diagram_dialog.import_database.step_2')} | ||||
|                     </p> | ||||
|                     <Textarea | ||||
|                         className="w-full flex-1 rounded-md bg-muted p-2 text-sm" | ||||
|                         placeholder={t( | ||||
|                             'new_diagram_dialog.import_database.script_results_placeholder' | ||||
|                         )} | ||||
|                         value={scriptResult} | ||||
|                         onChange={handleInputChange} | ||||
|                     /> | ||||
|                     {showCheckJsonButton || errorMessage ? ( | ||||
|                         <div className="mt-2 flex items-center gap-2"> | ||||
|                             {showCheckJsonButton ? ( | ||||
|                                 <Button | ||||
|                                     type="button" | ||||
|                                     variant="outline" | ||||
|                                     size="sm" | ||||
|                                     onClick={handleCheckJson} | ||||
|                                     disabled={isCheckingJson} | ||||
|                                 > | ||||
|                                     {isCheckingJson ? ( | ||||
|                                         <Spinner size="small" /> | ||||
|                                     ) : ( | ||||
|                                         t( | ||||
|                                             'new_diagram_dialog.import_database.check_script_result' | ||||
|                                         ) | ||||
|                                     )} | ||||
|                                 </Button> | ||||
|                             ) : ( | ||||
|                                 <p className="text-sm text-red-700"> | ||||
|                                     {errorMessage} | ||||
|                                 </p> | ||||
|                     </div> | ||||
|                     <div className="flex h-48 flex-col gap-1"> | ||||
|                         <p className="text-sm text-muted-foreground"> | ||||
|                             2. {t('new_diagram_dialog.import_database.step_2')} | ||||
|                         </p> | ||||
|                         <Textarea | ||||
|                             className="w-full flex-1 rounded-md bg-muted p-2 text-sm" | ||||
|                             placeholder={t( | ||||
|                                 'new_diagram_dialog.import_database.script_results_placeholder' | ||||
|                             )} | ||||
|                         </div> | ||||
|                     ) : null} | ||||
|                             value={scriptResult} | ||||
|                             onChange={handleInputChange} | ||||
|                         /> | ||||
|                         {showCheckJsonButton || errorMessage ? ( | ||||
|                             <div className="mt-2 flex items-center gap-2"> | ||||
|                                 {showCheckJsonButton ? ( | ||||
|                                     <Button | ||||
|                                         type="button" | ||||
|                                         variant="outline" | ||||
|                                         size="sm" | ||||
|                                         onClick={handleCheckJson} | ||||
|                                         disabled={isCheckingJson} | ||||
|                                     > | ||||
|                                         {isCheckingJson ? ( | ||||
|                                             <Spinner size="small" /> | ||||
|                                         ) : ( | ||||
|                                             t( | ||||
|                                                 'new_diagram_dialog.import_database.check_script_result' | ||||
|                                             ) | ||||
|                                         )} | ||||
|                                     </Button> | ||||
|                                 ) : ( | ||||
|                                     <p className="text-sm text-red-700"> | ||||
|                                         {errorMessage} | ||||
|                                     </p> | ||||
|                                 )} | ||||
|                             </div> | ||||
|                         ) : null} | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             </DialogInternalContent> | ||||
|         ); | ||||
|     }, [ | ||||
|         databaseEdition, | ||||
|   | ||||
| @@ -128,7 +128,7 @@ export const CreateDiagramDialog: React.FC<CreateDiagramDialogProps> = ({ | ||||
|             }} | ||||
|         > | ||||
|             <DialogContent | ||||
|                 className="flex w-[90vw] max-w-[90vw] flex-col overflow-y-auto md:overflow-visible lg:max-w-[60vw] xl:lg:max-w-lg xl:min-w-[45vw]" | ||||
|                 className="flex max-h-screen w-[90vw] max-w-[90vw] flex-col overflow-y-auto md:overflow-visible lg:max-w-[60vw] xl:lg:max-w-lg xl:min-w-[45vw]" | ||||
|                 showClose={hasExistingDiagram} | ||||
|             > | ||||
|                 {step === CreateDiagramDialogStep.SELECT_DATABASE ? ( | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import { | ||||
|     DialogDescription, | ||||
|     DialogFooter, | ||||
|     DialogHeader, | ||||
|     DialogInternalContent, | ||||
|     DialogTitle, | ||||
| } from '@/components/dialog/dialog'; | ||||
| import { DatabaseType } from '@/lib/domain/database-type'; | ||||
| @@ -40,11 +41,13 @@ export const SelectDatabase: React.FC<SelectDatabaseProps> = ({ | ||||
|                     {t('new_diagram_dialog.database_selection.description')} | ||||
|                 </DialogDescription> | ||||
|             </DialogHeader> | ||||
|             <SelectDatabaseContent | ||||
|                 databaseType={databaseType} | ||||
|                 onContinue={onContinue} | ||||
|                 setDatabaseType={setDatabaseType} | ||||
|             /> | ||||
|             <DialogInternalContent> | ||||
|                 <SelectDatabaseContent | ||||
|                     databaseType={databaseType} | ||||
|                     onContinue={onContinue} | ||||
|                     setDatabaseType={setDatabaseType} | ||||
|                 /> | ||||
|             </DialogInternalContent> | ||||
|             <DialogFooter className="mt-4 flex !justify-between gap-2"> | ||||
|                 {hasExistingDiagram ? ( | ||||
|                     <DialogClose asChild> | ||||
|   | ||||
| @@ -18,6 +18,8 @@ import { useChartDB } from '@/hooks/use-chartdb'; | ||||
| import { diagramToJSONOutput } from '@/lib/export-import-utils'; | ||||
| import { Spinner } from '@/components/spinner/spinner'; | ||||
| import { waitFor } from '@/lib/utils'; | ||||
| import { AlertCircle } from 'lucide-react'; | ||||
| import { Alert, AlertDescription, AlertTitle } from '@/components/alert/alert'; | ||||
|  | ||||
| export interface ExportDiagramDialogProps extends BaseDialogProps {} | ||||
|  | ||||
| @@ -28,10 +30,12 @@ export const ExportDiagramDialog: React.FC<ExportDiagramDialogProps> = ({ | ||||
|     const { diagramName, currentDiagram } = useChartDB(); | ||||
|     const [isLoading, setIsLoading] = useState(false); | ||||
|     const { closeExportDiagramDialog } = useDialog(); | ||||
|     const [error, setError] = useState(false); | ||||
|  | ||||
|     useEffect(() => { | ||||
|         if (!dialog.open) return; | ||||
|         setIsLoading(false); | ||||
|         setError(false); | ||||
|     }, [dialog.open]); | ||||
|  | ||||
|     const downloadOutput = useCallback( | ||||
| @@ -47,12 +51,19 @@ export const ExportDiagramDialog: React.FC<ExportDiagramDialogProps> = ({ | ||||
|     const handleExport = useCallback(async () => { | ||||
|         setIsLoading(true); | ||||
|         await waitFor(1000); | ||||
|         const json = diagramToJSONOutput(currentDiagram); | ||||
|         const blob = new Blob([json], { type: 'application/json' }); | ||||
|         const dataUrl = URL.createObjectURL(blob); | ||||
|         downloadOutput(dataUrl); | ||||
|         setIsLoading(false); | ||||
|         closeExportDiagramDialog(); | ||||
|         try { | ||||
|             const json = diagramToJSONOutput(currentDiagram); | ||||
|             const blob = new Blob([json], { type: 'application/json' }); | ||||
|             const dataUrl = URL.createObjectURL(blob); | ||||
|             downloadOutput(dataUrl); | ||||
|             setIsLoading(false); | ||||
|             closeExportDiagramDialog(); | ||||
|         } catch (e) { | ||||
|             setError(true); | ||||
|             setIsLoading(false); | ||||
|  | ||||
|             throw e; | ||||
|         } | ||||
|     }, [downloadOutput, currentDiagram, closeExportDiagramDialog]); | ||||
|  | ||||
|     const outputTypeOptions: SelectBoxOption[] = useMemo( | ||||
| @@ -90,6 +101,17 @@ export const ExportDiagramDialog: React.FC<ExportDiagramDialogProps> = ({ | ||||
|                             value="json" | ||||
|                         /> | ||||
|                     </div> | ||||
|                     {error ? ( | ||||
|                         <Alert variant="destructive"> | ||||
|                             <AlertCircle className="size-4" /> | ||||
|                             <AlertTitle> | ||||
|                                 {t('export_diagram_dialog.error.title')} | ||||
|                             </AlertTitle> | ||||
|                             <AlertDescription> | ||||
|                                 {t('export_diagram_dialog.error.description')} | ||||
|                             </AlertDescription> | ||||
|                         </Alert> | ||||
|                     ) : null} | ||||
|                 </div> | ||||
|                 <DialogFooter className="flex gap-1 md:justify-between"> | ||||
|                     <DialogClose asChild> | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import { | ||||
|     DialogDescription, | ||||
|     DialogFooter, | ||||
|     DialogHeader, | ||||
|     DialogInternalContent, | ||||
|     DialogTitle, | ||||
| } from '@/components/dialog/dialog'; | ||||
| import { Label } from '@/components/label/label'; | ||||
| @@ -151,7 +152,7 @@ export const ExportSQLDialog: React.FC<ExportSQLDialogProps> = ({ | ||||
|             }} | ||||
|         > | ||||
|             <DialogContent | ||||
|                 className="flex max-h-[80vh] flex-col overflow-y-auto xl:min-w-[75vw]" | ||||
|                 className="flex max-h-screen flex-col overflow-y-auto xl:min-w-[75vw]" | ||||
|                 showClose | ||||
|             > | ||||
|                 <DialogHeader> | ||||
| @@ -167,23 +168,24 @@ export const ExportSQLDialog: React.FC<ExportSQLDialogProps> = ({ | ||||
|                         })} | ||||
|                     </DialogDescription> | ||||
|                 </DialogHeader> | ||||
|                 <div className="flex flex-1 items-center justify-center"> | ||||
|                     {error ? ( | ||||
|                         renderError() | ||||
|                     ) : script === undefined ? ( | ||||
|                         renderLoader() | ||||
|                     ) : script.length === 0 ? ( | ||||
|                         renderError() | ||||
|                     ) : ( | ||||
|                         <CodeSnippet | ||||
|                             className="h-96 w-full" | ||||
|                             code={script!} | ||||
|                             autoScroll={true} | ||||
|                             isComplete={!isScriptLoading} | ||||
|                         /> | ||||
|                     )} | ||||
|                 </div> | ||||
|  | ||||
|                 <DialogInternalContent> | ||||
|                     <div className="flex flex-1 items-center justify-center"> | ||||
|                         {error ? ( | ||||
|                             renderError() | ||||
|                         ) : script === undefined ? ( | ||||
|                             renderLoader() | ||||
|                         ) : script.length === 0 ? ( | ||||
|                             renderError() | ||||
|                         ) : ( | ||||
|                             <CodeSnippet | ||||
|                                 className="h-96 w-full" | ||||
|                                 code={script!} | ||||
|                                 autoScroll={true} | ||||
|                                 isComplete={!isScriptLoading} | ||||
|                             /> | ||||
|                         )} | ||||
|                     </div> | ||||
|                 </DialogInternalContent> | ||||
|                 <DialogFooter className="flex !justify-between gap-2"> | ||||
|                     <div /> | ||||
|                     <DialogClose asChild> | ||||
|   | ||||
| @@ -323,7 +323,7 @@ export const ImportDatabaseDialog: React.FC<ImportDatabaseDialogProps> = ({ | ||||
|             }} | ||||
|         > | ||||
|             <DialogContent | ||||
|                 className="flex w-[90vw] flex-col overflow-y-auto md:overflow-visible xl:min-w-[45vw]" | ||||
|                 className="flex max-h-screen w-[90vw] flex-col overflow-y-auto md:overflow-visible xl:min-w-[45vw]" | ||||
|                 showClose | ||||
|             > | ||||
|                 <ImportDatabase | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import { | ||||
|     DialogDescription, | ||||
|     DialogFooter, | ||||
|     DialogHeader, | ||||
|     DialogInternalContent, | ||||
|     DialogTitle, | ||||
| } from '@/components/dialog/dialog'; | ||||
| import { Button } from '@/components/button/button'; | ||||
| @@ -87,7 +88,7 @@ export const ImportDiagramDialog: React.FC<ImportDiagramDialogProps> = ({ | ||||
|                 } | ||||
|             }} | ||||
|         > | ||||
|             <DialogContent className="flex flex-col" showClose> | ||||
|             <DialogContent className="flex max-h-screen flex-col" showClose> | ||||
|                 <DialogHeader> | ||||
|                     <DialogTitle> | ||||
|                         {t('import_diagram_dialog.title')} | ||||
| @@ -96,23 +97,27 @@ export const ImportDiagramDialog: React.FC<ImportDiagramDialogProps> = ({ | ||||
|                         {t('import_diagram_dialog.description')} | ||||
|                     </DialogDescription> | ||||
|                 </DialogHeader> | ||||
|                 <div className="flex flex-col p-1"> | ||||
|                     <FileUploader | ||||
|                         supportedExtensions={['.json']} | ||||
|                         onFilesChange={onFileChange} | ||||
|                     /> | ||||
|                     {error ? ( | ||||
|                         <Alert variant="destructive" className="mt-2"> | ||||
|                             <AlertCircle className="size-4" /> | ||||
|                             <AlertTitle> | ||||
|                                 {t('import_diagram_dialog.error.title')} | ||||
|                             </AlertTitle> | ||||
|                             <AlertDescription> | ||||
|                                 {t('import_diagram_dialog.error.description')} | ||||
|                             </AlertDescription> | ||||
|                         </Alert> | ||||
|                     ) : null} | ||||
|                 </div> | ||||
|                 <DialogInternalContent> | ||||
|                     <div className="flex flex-col p-1"> | ||||
|                         <FileUploader | ||||
|                             supportedExtensions={['.json']} | ||||
|                             onFilesChange={onFileChange} | ||||
|                         /> | ||||
|                         {error ? ( | ||||
|                             <Alert variant="destructive" className="mt-2"> | ||||
|                                 <AlertCircle className="size-4" /> | ||||
|                                 <AlertTitle> | ||||
|                                     {t('import_diagram_dialog.error.title')} | ||||
|                                 </AlertTitle> | ||||
|                                 <AlertDescription> | ||||
|                                     {t( | ||||
|                                         'import_diagram_dialog.error.description' | ||||
|                                     )} | ||||
|                                 </AlertDescription> | ||||
|                             </Alert> | ||||
|                         ) : null} | ||||
|                     </div> | ||||
|                 </DialogInternalContent> | ||||
|                 <DialogFooter className="flex gap-1 md:justify-between"> | ||||
|                     <DialogClose asChild> | ||||
|                         <Button variant="secondary"> | ||||
|   | ||||
| @@ -7,9 +7,9 @@ import { | ||||
|     DialogDescription, | ||||
|     DialogFooter, | ||||
|     DialogHeader, | ||||
|     DialogInternalContent, | ||||
|     DialogTitle, | ||||
| } from '@/components/dialog/dialog'; | ||||
| import { ScrollArea } from '@/components/scroll-area/scroll-area'; | ||||
| import { | ||||
|     Table, | ||||
|     TableBody, | ||||
| @@ -74,7 +74,7 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({ | ||||
|             }} | ||||
|         > | ||||
|             <DialogContent | ||||
|                 className="flex w-[90vw] flex-col overflow-y-auto md:w-screen xl:min-w-[55vw]" | ||||
|                 className="flex h-[30rem] max-h-screen w-[90vw] flex-col overflow-y-auto md:w-screen xl:min-w-[55vw]" | ||||
|                 showClose | ||||
|             > | ||||
|                 <DialogHeader> | ||||
| @@ -83,9 +83,9 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({ | ||||
|                         {t('open_diagram_dialog.description')} | ||||
|                     </DialogDescription> | ||||
|                 </DialogHeader> | ||||
|                 <div className="flex flex-1 items-center justify-center"> | ||||
|                     <ScrollArea className="h-80 w-full"> | ||||
|                         <Table className="h-fit"> | ||||
|                 <DialogInternalContent> | ||||
|                     <div className="flex flex-1 items-center justify-center"> | ||||
|                         <Table> | ||||
|                             <TableHeader className="sticky top-0 bg-background"> | ||||
|                                 <TableRow> | ||||
|                                     <TableHead /> | ||||
| @@ -155,8 +155,8 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({ | ||||
|                                 ))} | ||||
|                             </TableBody> | ||||
|                         </Table> | ||||
|                     </ScrollArea> | ||||
|                 </div> | ||||
|                     </div> | ||||
|                 </DialogInternalContent> | ||||
|  | ||||
|                 <DialogFooter className="flex !justify-between gap-2"> | ||||
|                     <DialogClose asChild> | ||||
|   | ||||
| @@ -16,6 +16,11 @@ import { zh_CN, zh_CNMetadata } from './locales/zh_CN'; | ||||
| import { zh_TW, zh_TWMetadata } from './locales/zh_TW'; | ||||
| import { ne, neMetadata } from './locales/ne'; | ||||
| 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 { gu, guMetadata } from './locales/gu'; | ||||
| import { vi, viMetadata } from './locales/vi'; | ||||
|  | ||||
| export const languages: LanguageMetadata[] = [ | ||||
|     enMetadata, | ||||
| @@ -32,6 +37,11 @@ export const languages: LanguageMetadata[] = [ | ||||
|     zh_TWMetadata, | ||||
|     neMetadata, | ||||
|     mrMetadata, | ||||
|     trMetadata, | ||||
|     id_IDMetadata, | ||||
|     teMetadata, | ||||
|     guMetadata, | ||||
|     viMetadata, | ||||
| ]; | ||||
|  | ||||
| const resources = { | ||||
| @@ -49,6 +59,11 @@ const resources = { | ||||
|     zh_TW, | ||||
|     ne, | ||||
|     mr, | ||||
|     tr, | ||||
|     id_ID, | ||||
|     te, | ||||
|     gu, | ||||
|     vi, | ||||
| }; | ||||
|  | ||||
| i18n.use(LanguageDetector) | ||||
|   | ||||
| @@ -344,6 +344,11 @@ export const de: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
| @@ -340,6 +340,11 @@ export const en = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
| @@ -344,6 +344,11 @@ export const es: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
| @@ -346,6 +346,11 @@ export const fr: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
							
								
								
									
										397
									
								
								src/i18n/locales/gu.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,397 @@ | ||||
| import type { LanguageMetadata, LanguageTranslation } from '../types'; | ||||
|  | ||||
| export const gu: 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: 'નિર્ભરતાઓ છુપાવો', | ||||
|             }, | ||||
|  | ||||
|             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: 'કઈ નહીં', | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'સિસ્ટમ', | ||||
|             light: 'હલકો', | ||||
|             dark: 'ઘાટો', | ||||
|         }, | ||||
|  | ||||
|         zoom: { | ||||
|             on: 'ચાલુ', | ||||
|             off: 'બંધ', | ||||
|         }, | ||||
|  | ||||
|         last_saved: 'છેલ્લે સાચવ્યું', | ||||
|         saved: 'સાચવ્યું', | ||||
|         diagrams: 'ડાયાગ્રામ', | ||||
|         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: 'ફીલ્ડ્સ', | ||||
|                     //TODO translate | ||||
|                     nullable: '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: 'તેને 30 સેકંડ સુધીનો સમય લાગી શકે છે.', | ||||
|             }, | ||||
|             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 guMetadata: LanguageMetadata = { | ||||
|     name: 'Gujarati', | ||||
|     nativeName: 'ગુજરાતી', | ||||
|     code: 'gu', | ||||
| }; | ||||
| @@ -346,6 +346,11 @@ export const hi: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
							
								
								
									
										402
									
								
								src/i18n/locales/id_ID.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,402 @@ | ||||
| import type { LanguageMetadata, LanguageTranslation } from '../types'; | ||||
|  | ||||
| export const id_ID: LanguageTranslation = { | ||||
|     translation: { | ||||
|         menu: { | ||||
|             file: { | ||||
|                 file: 'Berkas', | ||||
|                 new: 'Buat Baru', | ||||
|                 open: 'Buka', | ||||
|                 save: 'Simpan', | ||||
|                 import_database: 'Impor Database', | ||||
|                 export_sql: 'Ekspor SQL', | ||||
|                 export_as: 'Ekspor Sebagai', | ||||
|                 delete_diagram: 'Hapus Diagram', | ||||
|                 exit: 'Keluar', | ||||
|             }, | ||||
|             edit: { | ||||
|                 edit: 'Ubah', | ||||
|                 undo: 'Undo', | ||||
|                 redo: 'Redo', | ||||
|                 clear: 'Bersihkan', | ||||
|             }, | ||||
|             view: { | ||||
|                 view: 'Tampilan', | ||||
|                 show_sidebar: 'Tampilkan Sidebar', | ||||
|                 hide_sidebar: 'Sembunyikan Sidebar', | ||||
|                 hide_cardinality: 'Sembunyikan Kardinalitas', | ||||
|                 show_cardinality: 'Tampilkan Kardinalitas', | ||||
|                 zoom_on_scroll: 'Perbesar saat Scroll', | ||||
|                 theme: 'Tema', | ||||
|                 show_dependencies: 'Tampilkan Dependensi', | ||||
|                 hide_dependencies: 'Sembunyikan Dependensi', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
|                 share: 'Share', | ||||
|                 export_diagram: 'Export Diagram', | ||||
|                 import_diagram: 'Import Diagram', | ||||
|             }, | ||||
|             help: { | ||||
|                 help: 'Bantuan', | ||||
|                 visit_website: 'Kunjungi ChartDB', | ||||
|                 join_discord: 'Bergabunglah di Discord kami', | ||||
|                 schedule_a_call: 'Berbicara dengan kami!', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         delete_diagram_alert: { | ||||
|             title: 'Hapus Diagram', | ||||
|             description: | ||||
|                 'Tindakan ini tidak dapat dibatalkan. Diagram akan dihapus secara permanen.', | ||||
|             cancel: 'Batal', | ||||
|             delete: 'Hapus', | ||||
|         }, | ||||
|  | ||||
|         clear_diagram_alert: { | ||||
|             title: 'Bersihkan Diagram', | ||||
|             description: | ||||
|                 'Tindakan ini tidak dapat dibatalkan. Semua data di diagram akan dihapus secara permanen.', | ||||
|             cancel: 'Batal', | ||||
|             clear: 'Bersihkan', | ||||
|         }, | ||||
|  | ||||
|         reorder_diagram_alert: { | ||||
|             title: 'Atur Ulang Diagram', | ||||
|             description: | ||||
|                 'Tindakan ini akan mengatur ulang semua tabel di diagram. Apakah Anda ingin melanjutkan?', | ||||
|             reorder: 'Atur Ulang', | ||||
|             cancel: 'Batal', | ||||
|         }, | ||||
|  | ||||
|         multiple_schemas_alert: { | ||||
|             title: 'Schema Lebih dari satu', | ||||
|             description: | ||||
|                 '{{schemasCount}} schema di diagram ini. Sedang ditampilkan: {{formattedSchemas}}.', | ||||
|             dont_show_again: 'Jangan tampilkan lagi', | ||||
|             change_schema: 'Ubah', | ||||
|             none: 'Tidak ada', | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Sistem', | ||||
|             light: 'Terang', | ||||
|             dark: 'Gelap', | ||||
|         }, | ||||
|  | ||||
|         zoom: { | ||||
|             on: 'Aktif', | ||||
|             off: 'Nonaktif', | ||||
|         }, | ||||
|  | ||||
|         last_saved: 'Terakhir disimpan', | ||||
|         saved: 'Tersimpan', | ||||
|         diagrams: 'Diagram', | ||||
|         loading_diagram: 'Memuat diagram...', | ||||
|         deselect_all: 'Batalkan Semua', | ||||
|         select_all: 'Pilih Semua', | ||||
|         clear: 'Bersihkan', | ||||
|         show_more: 'Tampilkan Lebih Banyak', | ||||
|         show_less: 'Tampilkan Lebih Sedikit', | ||||
|         copy_to_clipboard: 'Salin ke Clipboard', | ||||
|         copied: 'Tersalin!', | ||||
|  | ||||
|         side_panel: { | ||||
|             schema: 'Skema:', | ||||
|             filter_by_schema: 'Saring berdasarkan skema', | ||||
|             search_schema: 'Cari skema...', | ||||
|             no_schemas_found: 'Tidak ada skema yang ditemukan.', | ||||
|             view_all_options: 'Tampilkan Semua Pilihan...', | ||||
|             tables_section: { | ||||
|                 tables: 'Tabel', | ||||
|                 add_table: 'Tambah Tabel', | ||||
|                 filter: 'Saring', | ||||
|                 collapse: 'Lipat Semua', | ||||
|  | ||||
|                 table: { | ||||
|                     fields: 'Kolom', | ||||
|                     nullable: 'Bisa Kosong?', | ||||
|                     primary_key: 'Kunci Utama', | ||||
|                     indexes: 'Indeks', | ||||
|                     comments: 'Komentar', | ||||
|                     no_comments: 'Tidak ada komentar', | ||||
|                     add_field: 'Tambah Kolom', | ||||
|                     add_index: 'Tambah Indeks', | ||||
|                     index_select_fields: 'Pilih kolom', | ||||
|                     no_types_found: 'Tidak ada tipe yang ditemukan', | ||||
|                     field_name: 'Nama', | ||||
|                     field_type: 'Tipe', | ||||
|                     field_actions: { | ||||
|                         title: 'Atribut Kolom', | ||||
|                         unique: 'Unik', | ||||
|                         comments: 'Komentar', | ||||
|                         no_comments: 'Tidak ada komentar', | ||||
|                         delete_field: 'Hapus Kolom', | ||||
|                     }, | ||||
|                     index_actions: { | ||||
|                         title: 'Atribut Indeks', | ||||
|                         name: 'Nama', | ||||
|                         unique: 'Unik', | ||||
|                         delete_index: 'Hapus Indeks', | ||||
|                     }, | ||||
|                     table_actions: { | ||||
|                         title: 'Aksi Tabel', | ||||
|                         change_schema: 'Ubah Skema', | ||||
|                         add_field: 'Tambah Kolom', | ||||
|                         add_index: 'Tambah Indeks', | ||||
|                         duplicate_table: 'Duplikat Tabel', | ||||
|                         delete_table: 'Hapus Tabel', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'Tidak ada tabel', | ||||
|                     description: 'Buat tabel untuk memulai', | ||||
|                 }, | ||||
|             }, | ||||
|             relationships_section: { | ||||
|                 relationships: 'Hubungan', | ||||
|                 filter: 'Saring', | ||||
|                 add_relationship: 'Tambah Hubungan', | ||||
|                 collapse: 'Lipat Semua', | ||||
|                 relationship: { | ||||
|                     primary: 'Tabel Primer', | ||||
|                     foreign: 'Tabel Referensi', | ||||
|                     cardinality: 'Kardinalitas', | ||||
|                     delete_relationship: 'Hapus', | ||||
|                     relationship_actions: { | ||||
|                         title: 'Aksi', | ||||
|                         delete_relationship: 'Hapus', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'Tidak ada hubungan', | ||||
|                     description: 'Buat hubungan untuk menghubungkan tabel', | ||||
|                 }, | ||||
|             }, | ||||
|             dependencies_section: { | ||||
|                 dependencies: 'Dependensi', | ||||
|                 filter: 'Saring', | ||||
|                 collapse: 'Lipat Semua', | ||||
|                 dependency: { | ||||
|                     table: 'Tabel', | ||||
|                     dependent_table: 'Tampilan Dependen', | ||||
|                     delete_dependency: 'Hapus', | ||||
|                     dependency_actions: { | ||||
|                         title: 'Aksi', | ||||
|                         delete_dependency: 'Hapus', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'Tidak ada dependensi', | ||||
|                     description: 'Buat tampilan untuk memulai', | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         toolbar: { | ||||
|             zoom_in: 'Perbesar', | ||||
|             zoom_out: 'Perkecil', | ||||
|             save: 'Simpan', | ||||
|             show_all: 'Tampilkan Semua', | ||||
|             undo: 'Undo', | ||||
|             redo: 'Redo', | ||||
|             reorder_diagram: 'Atur Ulang Diagram', | ||||
|             highlight_overlapping_tables: 'Sorot Tabel yang Tumpang Tindih', | ||||
|         }, | ||||
|  | ||||
|         new_diagram_dialog: { | ||||
|             database_selection: { | ||||
|                 title: 'Apakah Database Anda?', | ||||
|                 description: | ||||
|                     'Setiap database memiliki fitur dan kemampuan unik.', | ||||
|                 check_examples_long: 'Lihat Contoh', | ||||
|                 check_examples_short: 'Contoh', | ||||
|             }, | ||||
|  | ||||
|             import_database: { | ||||
|                 title: 'Impor Database Anda', | ||||
|                 database_edition: 'Edisi Database:', | ||||
|                 step_1: 'Jalankan skrip ini di database Anda:', | ||||
|                 step_2: 'Tempel hasil skrip di sini:', | ||||
|                 script_results_placeholder: 'Hasil skrip di sini...', | ||||
|                 ssms_instructions: { | ||||
|                     button_text: 'Instruksi SSMS', | ||||
|                     title: 'Instruksi', | ||||
|                     step_1: 'Pergi ke Alat > Opsi > Hasil Kueri > SQL Server.', | ||||
|                     step_2: 'Jika Anda menggunakan "Hasil ke Grid," ubah Jumlah Karakter yang Diterima untuk Data Non-XML (disetel ke 9999999).', | ||||
|                 }, | ||||
|                 instructions_link: 'Butuh Bantuan? Tonton caranya', | ||||
|                 check_script_result: 'Periksa Hasil Skrip', | ||||
|             }, | ||||
|  | ||||
|             cancel: 'Batal', | ||||
|             import_from_file: 'Impor dari file', | ||||
|             back: 'Kembali', | ||||
|             empty_diagram: 'Diagram Kosong', | ||||
|             continue: 'Lanjutkan', | ||||
|             import: 'Impor', | ||||
|         }, | ||||
|  | ||||
|         open_diagram_dialog: { | ||||
|             title: 'Buka Diagram', | ||||
|             description: 'Pilih diagram untuk dibuka dari daftar di bawah.', | ||||
|             table_columns: { | ||||
|                 name: 'Name', | ||||
|                 created_at: 'Dibuat pada', | ||||
|                 last_modified: 'Terakhir diubah', | ||||
|                 tables_count: 'Tabel', | ||||
|             }, | ||||
|             cancel: 'Batal', | ||||
|             open: 'Buka', | ||||
|         }, | ||||
|  | ||||
|         export_sql_dialog: { | ||||
|             title: 'Ekspor SQL', | ||||
|             description: 'Ekspor skema diagram Anda ke skrip {{databaseType}}', | ||||
|             close: 'Tutup', | ||||
|             loading: { | ||||
|                 text: 'AI sedang membuat SQL untuk {{databaseType}}...', | ||||
|                 description: 'Ini akan memakan waktu hingga 30 detik.', | ||||
|             }, | ||||
|             error: { | ||||
|                 message: | ||||
|                     'Kesalahan saat menghasilkan skrip SQL. Silakan coba lagi nanti atau <0>hubungi kami</0>.', | ||||
|                 description: | ||||
|                     'Silakan gunakan OPENAI_TOKEN Anda, lihat petunjuk <0>di sini</0>.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         create_relationship_dialog: { | ||||
|             title: 'Buat Hubungan', | ||||
|             primary_table: 'Tabel Primer', | ||||
|             primary_field: 'Kolom Primer', | ||||
|             referenced_table: 'Tabel Referensi', | ||||
|             referenced_field: 'Kolom Referensi', | ||||
|             primary_table_placeholder: 'Pilih tabel', | ||||
|             primary_field_placeholder: 'Pilih kolom', | ||||
|             referenced_table_placeholder: 'Pilih tabel', | ||||
|             referenced_field_placeholder: 'Pilih kolom', | ||||
|             no_tables_found: 'Tidak ada tabel yang ditemukan', | ||||
|             no_fields_found: 'Tidak ada kolom yang ditemukan', | ||||
|             create: 'Buat', | ||||
|             cancel: 'Batal', | ||||
|         }, | ||||
|  | ||||
|         import_database_dialog: { | ||||
|             title: 'Impor ke Diagram Saat Ini', | ||||
|             override_alert: { | ||||
|                 title: 'Impor Database', | ||||
|                 content: { | ||||
|                     alert: 'Mengimpor diagram ini akan memengaruhi tabel dan hubungan yang ada.', | ||||
|                     new_tables: | ||||
|                         '<bold>{{newTablesNumber}}</bold> tabel baru akan ditambahkan.', | ||||
|                     new_relationships: | ||||
|                         '<bold>{{newRelationshipsNumber}}</bold> hubungan baru akan dibuat.', | ||||
|                     tables_override: | ||||
|                         '<bold>{{tablesOverrideNumber}}</bold> tabel akan ditimpa.', | ||||
|                     proceed: 'Apakah Anda ingin melanjutkan?', | ||||
|                 }, | ||||
|                 import: 'Impor', | ||||
|                 cancel: 'Batal', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         export_image_dialog: { | ||||
|             title: 'Ekspor Gambar', | ||||
|             description: 'Pilih faktor skala untuk ekspor:', | ||||
|             scale_1x: '1x Biasa', | ||||
|             scale_2x: '2x (Disarankan)', | ||||
|             scale_3x: '3x', | ||||
|             scale_4x: '4x', | ||||
|             cancel: 'Batal', | ||||
|             export: 'Ekspor', | ||||
|         }, | ||||
|  | ||||
|         new_table_schema_dialog: { | ||||
|             title: 'Pilih Skema', | ||||
|             description: | ||||
|                 'Skema yang sedang ditampilkan. Pilih salah satu untuk tabel baru.', | ||||
|             cancel: 'Batal', | ||||
|             confirm: 'Konfirmasi', | ||||
|         }, | ||||
|  | ||||
|         update_table_schema_dialog: { | ||||
|             title: 'Ubah Skema', | ||||
|             description: 'Perbarui skema tabel "{{tableName}}"', | ||||
|             cancel: 'Batal', | ||||
|             confirm: 'Ubah', | ||||
|         }, | ||||
|  | ||||
|         star_us_dialog: { | ||||
|             title: 'Bantu kami meningkatkan!', | ||||
|             description: | ||||
|                 'Apakah Anda ingin menambahkan bintang di GitHub? Cukup klik!', | ||||
|             close: 'Tidak sekarang', | ||||
|             confirm: 'Tentu saja!', | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         export_diagram_dialog: { | ||||
|             title: 'Export Diagram', | ||||
|             description: 'Choose the format for export:', | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|             title: 'Import Diagram', | ||||
|             description: 'Paste the diagram JSON below:', | ||||
|             cancel: 'Cancel', | ||||
|             import: 'Import', | ||||
|             error: { | ||||
|                 title: 'Error importing diagram', | ||||
|                 description: | ||||
|                     'The diagram JSON is invalid. Please check the JSON and try again. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         relationship_type: { | ||||
|             one_to_one: 'Satu ke Satu', | ||||
|             one_to_many: 'Satu ke Banyak', | ||||
|             many_to_one: 'Banyak ke Satu', | ||||
|             many_to_many: 'Banyak ke Banyak', | ||||
|         }, | ||||
|  | ||||
|         canvas_context_menu: { | ||||
|             new_table: 'Tabel Baru', | ||||
|             new_relationship: 'Hubungan Baru', | ||||
|         }, | ||||
|  | ||||
|         table_node_context_menu: { | ||||
|             edit_table: 'Ubah Tabel', | ||||
|             delete_table: 'Hapus Tabel', | ||||
|             // TODO: Translate | ||||
|             duplicate_table: 'Duplicate Table', | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         snap_to_grid_tooltip: 'Snap to Grid (Hold {{key}})', | ||||
|  | ||||
|         // TODO: Translate | ||||
|         tool_tips: { | ||||
|             double_click_to_edit: 'Double-click to edit', | ||||
|         }, | ||||
|  | ||||
|         language_select: { | ||||
|             change_language: 'Bahasa', | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| export const id_IDMetadata: LanguageMetadata = { | ||||
|     name: 'Indonesian', | ||||
|     nativeName: 'Indonesia', | ||||
|     code: 'id_ID', | ||||
| }; | ||||
| @@ -348,6 +348,11 @@ export const ja: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
| @@ -31,11 +31,10 @@ export const ko_KR: LanguageTranslation = { | ||||
|                 show_dependencies: '종속성 보이기', | ||||
|                 hide_dependencies: '종속성 숨기기', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
|                 share: 'Share', | ||||
|                 export_diagram: 'Export Diagram', | ||||
|                 import_diagram: 'Import Diagram', | ||||
|                 share: '공유', | ||||
|                 export_diagram: '다이어그램 내보내기', | ||||
|                 import_diagram: '다이어그램 가져오기', | ||||
|             }, | ||||
|             help: { | ||||
|                 help: '도움말', | ||||
| @@ -144,7 +143,7 @@ export const ko_KR: LanguageTranslation = { | ||||
|                         change_schema: '스키마 변경', | ||||
|                         add_field: '필드 추가', | ||||
|                         add_index: '인덱스 추가', | ||||
|                         duplicate_table: 'Duplicate Table', // TODO: Translate | ||||
|                         duplicate_table: '테이블 복제', | ||||
|                         delete_table: '테이블 삭제', | ||||
|                     }, | ||||
|                 }, | ||||
| @@ -231,8 +230,7 @@ export const ko_KR: LanguageTranslation = { | ||||
|  | ||||
|             cancel: '취소', | ||||
|             back: '뒤로가기', | ||||
|             // TODO: Translate | ||||
|             import_from_file: 'Import from File', | ||||
|             import_from_file: '파일에서 가져오기', | ||||
|             empty_diagram: '빈 다이어그램으로 시작', | ||||
|             continue: '계속', | ||||
|             import: '가져오기', | ||||
| @@ -335,24 +333,27 @@ export const ko_KR: LanguageTranslation = { | ||||
|             close: '아직은 괜찮아요', | ||||
|             confirm: '당연하죠!', | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         export_diagram_dialog: { | ||||
|             title: 'Export Diagram', | ||||
|             description: 'Choose the format for export:', | ||||
|             title: '다이어그램 내보내기', | ||||
|             description: '내보낼 형식을 선택해주세요:', | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|             title: 'Import Diagram', | ||||
|             description: 'Paste the diagram JSON below:', | ||||
|             cancel: 'Cancel', | ||||
|             import: 'Import', | ||||
|             cancel: '취소', | ||||
|             export: '내보내기', | ||||
|             error: { | ||||
|                 title: 'Error importing diagram', | ||||
|                 title: '다이어그램 내보내기 오류', | ||||
|                 description: | ||||
|                     'The diagram JSON is invalid. Please check the JSON and try again. Need help? chartdb.io@gmail.com', | ||||
|                     '무언가 문제가 발생하였습니다. 도움이 필요하신 경우 chartdb.io@gmail.com으로 연락해주세요.', | ||||
|             }, | ||||
|         }, | ||||
|         import_diagram_dialog: { | ||||
|             title: '다이어그램 가져오기', | ||||
|             description: '아래에 다이어그램 JSON을 첨부해주세요:', | ||||
|             cancel: '취소', | ||||
|             import: '가져오기', | ||||
|             error: { | ||||
|                 title: '다이어그램 가져오기 오류', | ||||
|                 description: | ||||
|                     '다이어그램 JSON이 유효하지 않습니다. JSON이 올바른 형식인지 확인해주세요. 도움이 필요하신 경우 chartdb.io@gmail.com으로 연락해주세요.', | ||||
|             }, | ||||
|         }, | ||||
|         relationship_type: { | ||||
| @@ -369,12 +370,11 @@ export const ko_KR: LanguageTranslation = { | ||||
|  | ||||
|         table_node_context_menu: { | ||||
|             edit_table: '테이블 수정', | ||||
|             duplicate_table: 'Duplicate Table', // TODO: Translate | ||||
|             duplicate_table: '테이블 복제', | ||||
|             delete_table: '테이블 삭제', | ||||
|         }, | ||||
|  | ||||
|         // TODO: Add translations | ||||
|         snap_to_grid_tooltip: 'Snap to Grid (Hold {{key}})', | ||||
|         snap_to_grid_tooltip: '그리드에 맞추기 ({{key}}를 누른채 유지)', | ||||
|  | ||||
|         tool_tips: { | ||||
|             double_click_to_edit: '더블클릭하여 편집', | ||||
|   | ||||
| @@ -349,6 +349,11 @@ export const mr: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         // TO | ||||
|   | ||||
| @@ -343,6 +343,11 @@ export const ne: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'रद्द गर्नुहोस्', | ||||
|             export: 'निर्यात गर्नुहोस्', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
| @@ -343,6 +343,11 @@ export const pt_BR: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
| @@ -339,6 +339,11 @@ export const ru: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Отменить', | ||||
|             export: 'Экспортировать', | ||||
|             error: { | ||||
|                 title: 'Ошибка экспортирования диаграммы', | ||||
|                 description: | ||||
|                     'Что-то пошло не так. Если вам нужна помощь, напишите нам: chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         import_diagram_dialog: { | ||||
|             title: 'Импорт кода диаграммы', | ||||
|   | ||||
							
								
								
									
										405
									
								
								src/i18n/locales/te.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,405 @@ | ||||
| import type { LanguageMetadata, LanguageTranslation } from '../types'; | ||||
|  | ||||
| export const te: 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 | ||||
|             share: { | ||||
|                 share: 'Share', | ||||
|                 export_diagram: 'Export Diagram', | ||||
|                 import_diagram: 'Import Diagram', | ||||
|             }, | ||||
|             help: { | ||||
|                 help: 'సహాయం', | ||||
|                 visit_website: 'ChartDB సందర్శించండి', | ||||
|                 join_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: 'ఎదరికాదు', | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'సిస్టమ్', | ||||
|             light: 'హালకా', | ||||
|             dark: 'నలుపు', | ||||
|         }, | ||||
|  | ||||
|         zoom: { | ||||
|             on: 'ఆన్', | ||||
|             off: 'ఆఫ్', | ||||
|         }, | ||||
|  | ||||
|         last_saved: 'చివరిగా సేవ్ చేయబడిన', | ||||
|         saved: 'సేవ్ చేయబడింది', | ||||
|         diagrams: 'చిత్రాలు', | ||||
|         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: 'ఇండెక్స్ జోడించు', | ||||
|                         // TODO: Translate | ||||
|                         duplicate_table: '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: 'Tools > Options > Query Results > SQL Server కు వెళ్ళండి.', | ||||
|                     step_2: 'మీరు "Results to Grid" ఉపయోగిస్తే, Maximum Characters Retrieved for Non-XML డేటా (9999999 కు సెట్ చేయండి) మార్చండి.', | ||||
|                 }, | ||||
|                 instructions_link: 'సహాయం కావాలి? ఎలా చూడండి', | ||||
|                 check_script_result: 'స్క్రిప్ట్ ఫలితం తనిఖీ చేయండి', | ||||
|             }, | ||||
|  | ||||
|             cancel: 'రద్దు', | ||||
|             // TODO: Translate | ||||
|             import_from_file: '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 ను ఉత్పత్తి చేయడంలో AI', | ||||
|                 description: 'ఇది 30 సెకన్లు పడుతుంది.', | ||||
|             }, | ||||
|             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: 'ఖచ్చితంగా!', | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         export_diagram_dialog: { | ||||
|             title: 'Export Diagram', | ||||
|             description: 'Choose the format for export:', | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|             title: 'Import Diagram', | ||||
|             description: 'Paste the diagram JSON below:', | ||||
|             cancel: 'Cancel', | ||||
|             import: 'Import', | ||||
|             error: { | ||||
|                 title: 'Error importing diagram', | ||||
|                 description: | ||||
|                     'The diagram JSON is invalid. Please check the JSON and try again. Need help? 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: 'పట్టికను సవరించు', | ||||
|             // TODO: Translate | ||||
|             duplicate_table: 'Duplicate Table', | ||||
|             delete_table: 'పట్టికను తొలగించు', | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         snap_to_grid_tooltip: 'Snap to Grid (Hold {{key}})', | ||||
|  | ||||
|         // TODO: Translate | ||||
|         tool_tips: { | ||||
|             double_click_to_edit: 'Double-click to edit', | ||||
|         }, | ||||
|  | ||||
|         language_select: { | ||||
|             change_language: 'భాష మార్చు', | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| export const teMetadata: LanguageMetadata = { | ||||
|     name: 'Telugu', | ||||
|     nativeName: 'తెలుగు', | ||||
|     code: 'te', | ||||
| }; | ||||
							
								
								
									
										389
									
								
								src/i18n/locales/tr.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,389 @@ | ||||
| import type { LanguageMetadata, LanguageTranslation } from '../types'; | ||||
|  | ||||
| export const tr: LanguageTranslation = { | ||||
|     translation: { | ||||
|         menu: { | ||||
|             file: { | ||||
|                 file: 'Dosya', | ||||
|                 new: 'Yeni', | ||||
|                 open: 'Aç', | ||||
|                 save: 'Kaydet', | ||||
|                 import_database: 'Veritabanı İçe Aktar', | ||||
|                 export_sql: 'SQL Olarak Dışa Aktar', | ||||
|                 export_as: 'Olarak Dışa Aktar', | ||||
|                 delete_diagram: 'Diyagramı Sil', | ||||
|                 exit: 'Çıkış', | ||||
|             }, | ||||
|             edit: { | ||||
|                 edit: 'Düzenle', | ||||
|                 undo: 'Geri Al', | ||||
|                 redo: 'Yinele', | ||||
|                 clear: 'Temizle', | ||||
|             }, | ||||
|             view: { | ||||
|                 view: 'Görünüm', | ||||
|                 show_sidebar: 'Kenar Çubuğunu Göster', | ||||
|                 hide_sidebar: 'Kenar Çubuğunu Gizle', | ||||
|                 hide_cardinality: 'Kardinaliteyi Gizle', | ||||
|                 show_cardinality: 'Kardinaliteyi Göster', | ||||
|                 zoom_on_scroll: 'Kaydırarak Yakınlaştır', | ||||
|                 theme: 'Tema', | ||||
|                 show_dependencies: 'Bağımlılıkları Göster', | ||||
|                 hide_dependencies: 'Bağımlılıkları Gizle', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             share: { | ||||
|                 share: 'Share', | ||||
|                 export_diagram: 'Export Diagram', | ||||
|                 import_diagram: 'Import Diagram', | ||||
|             }, | ||||
|             help: { | ||||
|                 help: 'Yardım', | ||||
|                 visit_website: "ChartDB'yi Ziyaret Et", | ||||
|                 join_discord: "Discord'a Katıl", | ||||
|                 schedule_a_call: 'Bize Ulaş!', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         delete_diagram_alert: { | ||||
|             title: 'Diyagramı Sil', | ||||
|             description: | ||||
|                 'Bu işlem geri alınamaz. Diyagram kalıcı olarak silinecektir.', | ||||
|             cancel: 'İptal', | ||||
|             delete: 'Sil', | ||||
|         }, | ||||
|  | ||||
|         clear_diagram_alert: { | ||||
|             title: 'Diyagramı Temizle', | ||||
|             description: | ||||
|                 'Bu işlem geri alınamaz. Diyagramdaki tüm veriler kalıcı olarak silinecektir.', | ||||
|             cancel: 'İptal', | ||||
|             clear: 'Temizle', | ||||
|         }, | ||||
|  | ||||
|         reorder_diagram_alert: { | ||||
|             title: 'Diyagramı Yeniden Sırala', | ||||
|             description: | ||||
|                 'Bu işlem tüm tabloları yeniden düzenleyecektir. Devam etmek istiyor musunuz?', | ||||
|             reorder: 'Yeniden Sırala', | ||||
|             cancel: 'İptal', | ||||
|         }, | ||||
|  | ||||
|         multiple_schemas_alert: { | ||||
|             title: 'Birden Fazla Şema', | ||||
|             description: | ||||
|                 'Bu diyagramda {{schemasCount}} şema var. Şu anda görüntülenen: {{formattedSchemas}}.', | ||||
|             dont_show_again: 'Tekrar gösterme', | ||||
|             change_schema: 'Değiştir', | ||||
|             none: 'yok', | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Sistem', | ||||
|             light: 'Açık', | ||||
|             dark: 'Koyu', | ||||
|         }, | ||||
|  | ||||
|         zoom: { | ||||
|             on: 'Açık', | ||||
|             off: 'Kapalı', | ||||
|         }, | ||||
|  | ||||
|         last_saved: 'Son kaydedilen', | ||||
|         saved: 'Kaydedildi', | ||||
|         diagrams: 'Diyagramlar', | ||||
|  | ||||
|         loading_diagram: 'Diyagram yükleniyor...', | ||||
|         deselect_all: 'Hepsini Seçme', | ||||
|         select_all: 'Hepsini Seç', | ||||
|         clear: 'Temizle', | ||||
|         show_more: 'Daha Fazla Göster', | ||||
|         show_less: 'Daha Az Göster', | ||||
|         copy_to_clipboard: 'Panoya Kopyala', | ||||
|         copied: 'Kopyalandı!', | ||||
|         side_panel: { | ||||
|             schema: 'Şema:', | ||||
|             filter_by_schema: 'Şemaya Göre Filtrele', | ||||
|             search_schema: 'Şema ara...', | ||||
|             no_schemas_found: 'Şema bulunamadı.', | ||||
|             view_all_options: 'Tüm Seçenekleri Gör...', | ||||
|             tables_section: { | ||||
|                 tables: 'Tablolar', | ||||
|                 add_table: 'Tablo Ekle', | ||||
|                 filter: 'Filtrele', | ||||
|                 collapse: 'Hepsini Daralt', | ||||
|                 table: { | ||||
|                     fields: 'Alanlar', | ||||
|                     nullable: 'Boş Bırakılabilir?', | ||||
|                     primary_key: 'Birincil Anahtar', | ||||
|                     indexes: 'İndeksler', | ||||
|                     comments: 'Yorumlar', | ||||
|                     no_comments: 'Yorum yok', | ||||
|                     add_field: 'Alan Ekle', | ||||
|                     add_index: 'İndeks Ekle', | ||||
|                     index_select_fields: 'Alanları Seç', | ||||
|                     no_types_found: 'Tür bulunamadı', | ||||
|                     field_name: 'Ad', | ||||
|                     field_type: 'Tür', | ||||
|                     field_actions: { | ||||
|                         title: 'Alan Özellikleri', | ||||
|                         unique: 'Tekil', | ||||
|                         comments: 'Yorumlar', | ||||
|                         no_comments: 'Yorum yok', | ||||
|                         delete_field: 'Alanı Sil', | ||||
|                     }, | ||||
|                     index_actions: { | ||||
|                         title: 'İndeks Özellikleri', | ||||
|                         name: 'Ad', | ||||
|                         unique: 'Tekil', | ||||
|                         delete_index: 'İndeksi Sil', | ||||
|                     }, | ||||
|                     table_actions: { | ||||
|                         title: 'Tablo İşlemleri', | ||||
|                         change_schema: 'Şemayı Değiştir', | ||||
|                         add_field: 'Alan Ekle', | ||||
|                         add_index: 'İndeks Ekle', | ||||
|                         // TODO: Translate | ||||
|                         duplicate_table: 'Duplicate Table', | ||||
|                         delete_table: 'Tabloyu Sil', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'Tablo yok', | ||||
|                     description: 'Başlamak için bir tablo oluşturun', | ||||
|                 }, | ||||
|             }, | ||||
|             relationships_section: { | ||||
|                 relationships: 'İlişkiler', | ||||
|                 filter: 'Filtrele', | ||||
|                 add_relationship: 'İlişki Ekle', | ||||
|                 collapse: 'Hepsini Daralt', | ||||
|                 relationship: { | ||||
|                     primary: 'Birincil Tablo', | ||||
|                     foreign: 'Referans Tablo', | ||||
|                     cardinality: 'Kardinalite', | ||||
|                     delete_relationship: 'Sil', | ||||
|                     relationship_actions: { | ||||
|                         title: 'İşlemler', | ||||
|                         delete_relationship: 'Sil', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'İlişki yok', | ||||
|                     description: 'Tabloları bağlamak için bir ilişki oluşturun', | ||||
|                 }, | ||||
|             }, | ||||
|             dependencies_section: { | ||||
|                 dependencies: 'Bağımlılıklar', | ||||
|                 filter: 'Filtrele', | ||||
|                 collapse: 'Hepsini Daralt', | ||||
|                 dependency: { | ||||
|                     table: 'Tablo', | ||||
|                     dependent_table: 'Bağımlı Görünüm', | ||||
|                     delete_dependency: 'Sil', | ||||
|                     dependency_actions: { | ||||
|                         title: 'İşlemler', | ||||
|                         delete_dependency: 'Sil', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'Bağımlılık yok', | ||||
|                     description: 'Başlamak için bir görünüm oluşturun', | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         toolbar: { | ||||
|             zoom_in: 'Yakınlaştır', | ||||
|             zoom_out: 'Uzaklaştır', | ||||
|             save: 'Kaydet', | ||||
|             show_all: 'Hepsini Gör', | ||||
|             undo: 'Geri Al', | ||||
|             redo: 'Yinele', | ||||
|             reorder_diagram: 'Diyagramı Yeniden Sırala', | ||||
|             highlight_overlapping_tables: 'Çakışan Tabloları Vurgula', | ||||
|         }, | ||||
|         new_diagram_dialog: { | ||||
|             database_selection: { | ||||
|                 title: 'Veritabanınız nedir?', | ||||
|                 description: | ||||
|                     'Her veritabanının kendine özgü özellikleri ve yetenekleri vardır.', | ||||
|                 check_examples_long: 'Örnekleri Kontrol Et', | ||||
|                 check_examples_short: 'Örnekler', | ||||
|             }, | ||||
|             import_database: { | ||||
|                 title: 'Veritabanını İçe Aktar', | ||||
|                 database_edition: 'Veritabanı Sürümü:', | ||||
|                 step_1: 'Bu komut dosyasını veritabanınızda çalıştırın:', | ||||
|                 step_2: 'Komut dosyası sonucunu buraya yapıştırın:', | ||||
|                 script_results_placeholder: 'Komut dosyası sonuçları burada...', | ||||
|                 ssms_instructions: { | ||||
|                     button_text: 'SSMS Talimatları', | ||||
|                     title: 'Talimatlar', | ||||
|                     step_1: "Araçlar > Seçenekler > Sorgu Sonuçları > SQL Server'a gidin.", | ||||
|                     step_2: 'Eğer "Sonuçlar Izgaraya" kullanıyorsanız, Maksimum Karakterlerin Alınması için XML olmayan veriler (9999999 olarak ayarlanmış) değiştirin.', | ||||
|                 }, | ||||
|                 instructions_link: | ||||
|                     'Yardıma mı ihtiyacınız var? İzlemek için tıklayın', | ||||
|                 check_script_result: 'Komut Dosyası Sonucunu Kontrol Et', | ||||
|             }, | ||||
|             // TODO: Translate | ||||
|             import_from_file: 'Import from File', | ||||
|             cancel: 'İptal', | ||||
|             back: 'Geri', | ||||
|             empty_diagram: 'Boş diyagram', | ||||
|             continue: 'Devam', | ||||
|             import: 'İçe Aktar', | ||||
|         }, | ||||
|         open_diagram_dialog: { | ||||
|             title: 'Diyagramı Aç', | ||||
|             description: 'Aşağıdaki listeden açmak için bir diyagram seçin.', | ||||
|             table_columns: { | ||||
|                 name: 'Ad', | ||||
|                 created_at: 'Oluşturulma Tarihi', | ||||
|                 last_modified: 'Son Değiştirme', | ||||
|                 tables_count: 'Tablolar', | ||||
|             }, | ||||
|             cancel: 'İptal', | ||||
|             open: 'Aç', | ||||
|         }, | ||||
|  | ||||
|         export_sql_dialog: { | ||||
|             title: 'SQL Olarak Dışa Aktar', | ||||
|             description: | ||||
|                 'Diyagram şemanızı {{databaseType}} betiğine dışa aktarın', | ||||
|             close: 'Kapat', | ||||
|             loading: { | ||||
|                 text: 'AI, SQL oluşturuyor {{databaseType}}...', | ||||
|                 description: 'Bu işlem en fazla 30 saniye sürecektir.', | ||||
|             }, | ||||
|             error: { | ||||
|                 message: | ||||
|                     'SQL betiği oluşturulurken hata oluştu. Lütfen daha sonra tekrar deneyin veya <0>bize ulaşın</0>.', | ||||
|                 description: | ||||
|                     "OPENAI_TOKEN'ınızı kullanabilirsiniz, kılavuzu <0>buradan</0> görebilirsiniz.", | ||||
|             }, | ||||
|         }, | ||||
|         create_relationship_dialog: { | ||||
|             title: 'İlişki Oluştur', | ||||
|             primary_table: 'Birincil Tablo', | ||||
|             primary_field: 'Birincil Alan', | ||||
|             referenced_table: 'Referans Tablo', | ||||
|             referenced_field: 'Referans Alan', | ||||
|             primary_table_placeholder: 'Tablo seç', | ||||
|             primary_field_placeholder: 'Alan seç', | ||||
|             referenced_table_placeholder: 'Tablo seç', | ||||
|             referenced_field_placeholder: 'Alan seç', | ||||
|             no_tables_found: 'Tablo bulunamadı', | ||||
|             no_fields_found: 'Alan bulunamadı', | ||||
|             create: 'Oluştur', | ||||
|             cancel: 'İptal', | ||||
|         }, | ||||
|         import_database_dialog: { | ||||
|             title: 'Mevcut Diyagrama İçe Aktar', | ||||
|             override_alert: { | ||||
|                 title: 'Veritabanını İçe Aktar', | ||||
|                 content: { | ||||
|                     alert: 'Bu diyagramı içe aktarmak mevcut tabloları ve ilişkileri etkileyecektir.', | ||||
|                     new_tables: | ||||
|                         '<bold>{{newTablesNumber}}</bold> yeni tablo eklenecek.', | ||||
|                     new_relationships: | ||||
|                         '<bold>{{newRelationshipsNumber}}</bold> yeni ilişki oluşturulacak.', | ||||
|                     tables_override: | ||||
|                         '<bold>{{tablesOverrideNumber}}</bold> tablo üzerine yazılacak.', | ||||
|                     proceed: 'Devam etmek istiyor musunuz?', | ||||
|                 }, | ||||
|                 import: 'İçe Aktar', | ||||
|                 cancel: 'İptal', | ||||
|             }, | ||||
|         }, | ||||
|         export_image_dialog: { | ||||
|             title: 'Resmi Dışa Aktar', | ||||
|             description: 'Dışa aktarım için ölçek faktörünü seçin:', | ||||
|             scale_1x: '1x Normal', | ||||
|             scale_2x: '2x (Önerilen)', | ||||
|             scale_3x: '3x', | ||||
|             scale_4x: '4x', | ||||
|             cancel: 'İptal', | ||||
|             export: 'Dışa Aktar', | ||||
|         }, | ||||
|         new_table_schema_dialog: { | ||||
|             title: 'Şema Seç', | ||||
|             description: | ||||
|                 'Şu anda birden fazla şema görüntülenmektedir. Yeni tablo için birini seçin.', | ||||
|             cancel: 'İptal', | ||||
|             confirm: 'Onayla', | ||||
|         }, | ||||
|         update_table_schema_dialog: { | ||||
|             title: 'Şemayı Değiştir', | ||||
|             description: 'Tablo "{{tableName}}" şemasını güncelle', | ||||
|             cancel: 'İptal', | ||||
|             confirm: 'Değiştir', | ||||
|         }, | ||||
|         star_us_dialog: { | ||||
|             title: 'Bize yardım et!', | ||||
|             description: | ||||
|                 "Bizi GitHub'da yıldızlamak ister misiniz? Sadece bir tık uzakta!", | ||||
|             close: 'Şimdi Değil', | ||||
|             confirm: 'Tabii ki!', | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         export_diagram_dialog: { | ||||
|             title: 'Export Diagram', | ||||
|             description: 'Choose the format for export:', | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|             title: 'Import Diagram', | ||||
|             description: 'Paste the diagram JSON below:', | ||||
|             cancel: 'Cancel', | ||||
|             import: 'Import', | ||||
|             error: { | ||||
|                 title: 'Error importing diagram', | ||||
|                 description: | ||||
|                     'The diagram JSON is invalid. Please check the JSON and try again. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         relationship_type: { | ||||
|             one_to_one: 'Bir Bir', | ||||
|             one_to_many: 'Bir Çok', | ||||
|             many_to_one: 'Çok Bir', | ||||
|             many_to_many: 'Çok Çok', | ||||
|         }, | ||||
|         canvas_context_menu: { | ||||
|             new_table: 'Yeni Tablo', | ||||
|             new_relationship: 'Yeni İlişki', | ||||
|         }, | ||||
|         table_node_context_menu: { | ||||
|             edit_table: 'Tabloyu Düzenle', | ||||
|             delete_table: 'Tabloyu Sil', | ||||
|             // TODO: Translate | ||||
|             duplicate_table: 'Duplicate Table', | ||||
|         }, | ||||
|  | ||||
|         // TODO: Translate | ||||
|         snap_to_grid_tooltip: 'Snap to Grid (Hold {{key}})', | ||||
|  | ||||
|         // TODO: Translate | ||||
|         tool_tips: { | ||||
|             double_click_to_edit: 'Double-click to edit', | ||||
|         }, | ||||
|  | ||||
|         language_select: { | ||||
|             change_language: 'Dil', | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| export const trMetadata: LanguageMetadata = { | ||||
|     nativeName: 'Türkçe', | ||||
|     name: 'Turkish', | ||||
|     code: 'tr', | ||||
| }; | ||||
| @@ -343,6 +343,11 @@ export const uk: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Cancel', | ||||
|             export: 'Export', | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         // TODO: Translate | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
							
								
								
									
										394
									
								
								src/i18n/locales/vi.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,394 @@ | ||||
| import type { LanguageMetadata, LanguageTranslation } from '../types'; | ||||
|  | ||||
| export const vi: LanguageTranslation = { | ||||
|     translation: { | ||||
|         menu: { | ||||
|             file: { | ||||
|                 file: 'Tệp', | ||||
|                 new: 'Tạo mới', | ||||
|                 open: 'Mở', | ||||
|                 save: 'Lưu', | ||||
|                 import_database: 'Nhập cơ sở dữ liệu', | ||||
|                 export_sql: 'Xuất SQL', | ||||
|                 export_as: 'Xuất thành', | ||||
|                 delete_diagram: 'Xóa sơ đồ', | ||||
|                 exit: 'Thoát', | ||||
|             }, | ||||
|             edit: { | ||||
|                 edit: 'Sửa', | ||||
|                 undo: 'Hoàn tác', | ||||
|                 redo: 'Làm lại', | ||||
|                 clear: 'Xóa', | ||||
|             }, | ||||
|             view: { | ||||
|                 view: 'Xem', | ||||
|                 show_sidebar: 'Hiển thị thanh bên', | ||||
|                 hide_sidebar: 'Ẩn thanh bên', | ||||
|                 hide_cardinality: 'Ẩn số lượng', | ||||
|                 show_cardinality: 'Hiển thị số lượng', | ||||
|                 zoom_on_scroll: 'Thu phóng khi cuộn', | ||||
|                 theme: 'Chủ đề', | ||||
|                 show_dependencies: 'Hiển thị các phụ thuộc', | ||||
|                 hide_dependencies: 'Ẩn các phụ thuộc', | ||||
|             }, | ||||
|             share: { | ||||
|                 share: 'Chia sẻ', | ||||
|                 export_diagram: 'Xuất sơ đồ', | ||||
|                 import_diagram: 'Nhập sơ đồ', | ||||
|             }, | ||||
|             help: { | ||||
|                 help: 'Trợ giúp', | ||||
|                 visit_website: 'Truy cập ChartDB', | ||||
|                 join_discord: 'Tham gia Discord', | ||||
|                 schedule_a_call: 'Trò chuyện cùng chúng tôi!', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         delete_diagram_alert: { | ||||
|             title: 'Xóa sơ đồ', | ||||
|             description: | ||||
|                 'Không thể hoàn tác hành động này. Thao tác này sẽ xóa vĩnh viễn sơ đồ.', | ||||
|             cancel: 'Hủy', | ||||
|             delete: 'Xóa', | ||||
|         }, | ||||
|  | ||||
|         clear_diagram_alert: { | ||||
|             title: 'Xóa dữ liệu trong sơ đồ', | ||||
|             description: | ||||
|                 'Không thể hoàn tác hành động này. Thao tác này sẽ xóa vĩnh viễn mọi dữ liệu trong sơ đồ.', | ||||
|             cancel: 'Hủy', | ||||
|             clear: 'Xóa', | ||||
|         }, | ||||
|  | ||||
|         reorder_diagram_alert: { | ||||
|             title: 'Sắp xếp lại sơ đồ', | ||||
|             description: | ||||
|                 'Hành động này sẽ sắp xếp lại tất cả các bảng trong sơ đồ. Bạn có muốn tiếp tục không?', | ||||
|             reorder: 'Sắp xếp', | ||||
|             cancel: 'Hủy', | ||||
|         }, | ||||
|  | ||||
|         multiple_schemas_alert: { | ||||
|             title: 'Có nhiều lược đồ', | ||||
|             description: | ||||
|                 'Có {{schemasCount}} lược đồ trong sơ đồ này. Hiện đang hiển thị: {{formattedSchemas}}.', | ||||
|             dont_show_again: 'Không hiển thị lại', | ||||
|             change_schema: 'Thay đổi', | ||||
|             none: 'không có', | ||||
|         }, | ||||
|  | ||||
|         theme: { | ||||
|             system: 'Hệ thống', | ||||
|             light: 'Sáng', | ||||
|             dark: 'Tối', | ||||
|         }, | ||||
|  | ||||
|         zoom: { | ||||
|             on: 'Bật', | ||||
|             off: 'Tất', | ||||
|         }, | ||||
|  | ||||
|         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', | ||||
|         copied: 'Đã sao chép!', | ||||
|  | ||||
|         side_panel: { | ||||
|             schema: 'Lược đồ:', | ||||
|             filter_by_schema: 'Lọc bởi lược đồ', | ||||
|             search_schema: 'Tìm kiếm lược đồ...', | ||||
|             no_schemas_found: 'Không tìm thấy lược đồ.', | ||||
|             view_all_options: 'Xem tất cả tùy chọn...', | ||||
|             tables_section: { | ||||
|                 tables: 'Bảng', | ||||
|                 add_table: 'Thêm bảng', | ||||
|                 filter: 'Lọc', | ||||
|                 collapse: 'Thu gọn tất cả', | ||||
|  | ||||
|                 table: { | ||||
|                     fields: 'Trường', | ||||
|                     nullable: 'Có thể NULL?', | ||||
|                     primary_key: 'Khóa chính', | ||||
|                     indexes: 'Chỉ mục', | ||||
|                     comments: 'Bình luận', | ||||
|                     no_comments: 'Không có bình luận', | ||||
|                     add_field: 'Thêm trường', | ||||
|                     add_index: 'Thêm chỉ mục', | ||||
|                     index_select_fields: 'Chọn trường', | ||||
|                     no_types_found: 'Không tìm thấy', | ||||
|                     field_name: 'Tên trường', | ||||
|                     field_type: 'Loại trường', | ||||
|                     field_actions: { | ||||
|                         title: 'Thuộc tính trường', | ||||
|                         unique: 'Giá trị duy nhất', | ||||
|                         comments: 'Bình luận', | ||||
|                         no_comments: 'Không có bình luận', | ||||
|                         delete_field: 'Xóa trường', | ||||
|                     }, | ||||
|                     index_actions: { | ||||
|                         title: 'Thuộc tính chỉ mục', | ||||
|                         name: 'Tên', | ||||
|                         unique: 'Giá trị duy nhất', | ||||
|                         delete_index: 'Xóa chỉ mục', | ||||
|                     }, | ||||
|                     table_actions: { | ||||
|                         title: 'Hành động', | ||||
|                         change_schema: 'Thay đổi lược đồ', | ||||
|                         add_field: 'Thêm trường', | ||||
|                         add_index: 'Thêm chỉ mục', | ||||
|                         duplicate_table: 'Nhân đôi bảng', | ||||
|                         delete_table: 'Xóa bảng', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'Không có bảng', | ||||
|                     description: 'Tạo một bảng để bắt đầu', | ||||
|                 }, | ||||
|             }, | ||||
|             relationships_section: { | ||||
|                 relationships: 'Quan hệ', | ||||
|                 filter: 'Lọc', | ||||
|                 add_relationship: 'Thêm quan hệ', | ||||
|                 collapse: 'Thu gọn tất cả', | ||||
|                 relationship: { | ||||
|                     primary: 'Bảng khóa chính', | ||||
|                     foreign: 'Bảng khóa ngoại', | ||||
|                     cardinality: 'Quan hệ', | ||||
|                     delete_relationship: 'Xóa', | ||||
|                     relationship_actions: { | ||||
|                         title: 'Hành động', | ||||
|                         delete_relationship: 'Xóa', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'Không có quan hệ', | ||||
|                     description: 'Tạo quan hệ để kết nối các bảng', | ||||
|                 }, | ||||
|             }, | ||||
|             dependencies_section: { | ||||
|                 dependencies: 'Phụ thuộc', | ||||
|                 filter: 'Lọc', | ||||
|                 collapse: 'Thu gọn tất cả', | ||||
|                 dependency: { | ||||
|                     table: 'Bảng', | ||||
|                     dependent_table: 'Bảng xem phụ thuộc', | ||||
|                     delete_dependency: 'Xóa', | ||||
|                     dependency_actions: { | ||||
|                         title: 'Hành động', | ||||
|                         delete_dependency: 'Xóa', | ||||
|                     }, | ||||
|                 }, | ||||
|                 empty_state: { | ||||
|                     title: 'Không có phụ thuộc', | ||||
|                     description: 'Tạo bảng xem phụ thuộc để bắt đầu', | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         toolbar: { | ||||
|             zoom_in: 'Phóng to', | ||||
|             zoom_out: 'Thu nhỏ', | ||||
|             save: 'Lưu', | ||||
|             show_all: 'Hiển thị tất cả', | ||||
|             undo: 'Hoàn tác', | ||||
|             redo: 'Làm lại', | ||||
|             reorder_diagram: 'Sắp xếp lại sơ đồ', | ||||
|             highlight_overlapping_tables: 'Làm nổi bật các bảng chồng chéo', | ||||
|         }, | ||||
|  | ||||
|         new_diagram_dialog: { | ||||
|             database_selection: { | ||||
|                 title: 'Cơ sở dữ liệu của bạn là gì?', | ||||
|                 description: | ||||
|                     'Mỗi cơ sở dữ liệu có những tính năng và khả năng riêng biệt.', | ||||
|                 check_examples_long: 'Xem ví dụ', | ||||
|                 check_examples_short: 'Ví dụ', | ||||
|             }, | ||||
|  | ||||
|             import_database: { | ||||
|                 title: 'Nhập cơ sở dữ liệu của bạn', | ||||
|                 database_edition: 'Loại:', | ||||
|                 step_1: 'Chạy lệnh này trong cơ sở dữ liệu của bạn:', | ||||
|                 step_2: 'Dán kết quả vào đây:', | ||||
|                 script_results_placeholder: 'Kết quả...', | ||||
|                 ssms_instructions: { | ||||
|                     button_text: 'Hướng dẫn SSMS', | ||||
|                     title: 'Hướng dẫn', | ||||
|                     step_1: 'Đi đến Tools > Options > Query Results > SQL Server.', | ||||
|                     step_2: 'Nếu bạn đang sử dụng "Results to Grid," thay đổi Maximum Characters Retrieved cho Non-XML (đặt thành 9999999).', | ||||
|                 }, | ||||
|                 instructions_link: 'Cần trợ giúp? Xem ngay', | ||||
|                 check_script_result: 'Xem kết quả', | ||||
|             }, | ||||
|  | ||||
|             cancel: 'Hủy', | ||||
|             import_from_file: 'Nhập từ tệp', | ||||
|             back: 'Trở lại', | ||||
|             empty_diagram: 'Sơ đồ trống', | ||||
|             continue: 'Tiếp tục', | ||||
|             import: 'Nhập', | ||||
|         }, | ||||
|  | ||||
|         open_diagram_dialog: { | ||||
|             title: 'Mở sơ đồ', | ||||
|             description: 'Chọn sơ đồ để mở từ danh sách bên dưới.', | ||||
|             table_columns: { | ||||
|                 name: 'Tên', | ||||
|                 created_at: 'Tạo vào lúc', | ||||
|                 last_modified: 'Lần cuối chỉnh sửa', | ||||
|                 tables_count: 'Số bảng', | ||||
|             }, | ||||
|             cancel: 'Hủy', | ||||
|             open: 'Mở', | ||||
|         }, | ||||
|  | ||||
|         export_sql_dialog: { | ||||
|             title: 'Xuất SQL', | ||||
|             description: 'Xuất sơ đồ của bạn sang {{databaseType}}', | ||||
|             close: 'Đóng', | ||||
|             loading: { | ||||
|                 text: 'AI đang tạo SQL cho {{databaseType}}...', | ||||
|                 description: 'Việc này có thể mất khoảng 30 giây.', | ||||
|             }, | ||||
|             error: { | ||||
|                 message: | ||||
|                     'Lỗi khi tạo SQL. Vui lòng thử lại sau hoặc <0>liên hệ với chúng tôi</0>.', | ||||
|                 description: | ||||
|                     'Bạn có thể sử dụng OPENAI_TOKEN, xem hướng dẫn <0>tại đây</0>.', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         create_relationship_dialog: { | ||||
|             title: 'Tạo quan hệ', | ||||
|             primary_table: 'Bảng chính', | ||||
|             primary_field: 'Khóa chính', | ||||
|             referenced_table: 'Bảng tham chiếu', | ||||
|             referenced_field: 'Khóa tham chiếu', | ||||
|             primary_table_placeholder: 'Chọn bảng', | ||||
|             primary_field_placeholder: 'Chọn trường', | ||||
|             referenced_table_placeholder: 'Chọn bảng', | ||||
|             referenced_field_placeholder: 'Chọn trường', | ||||
|             no_tables_found: 'Không tìm thấy bảng', | ||||
|             no_fields_found: 'Không tìm thấy trường', | ||||
|             create: 'Tạo', | ||||
|             cancel: 'Hủy', | ||||
|         }, | ||||
|  | ||||
|         import_database_dialog: { | ||||
|             title: 'Nhập vào sơ đồ hiện tại', | ||||
|             override_alert: { | ||||
|                 title: 'Nhập cơ sở dữ liệu', | ||||
|                 content: { | ||||
|                     alert: 'Việc nhập sơ đồ này sẽ ảnh hưởng đến các bảng và mối quan hệ hiện có.', | ||||
|                     new_tables: | ||||
|                         '<bold>{{newTablesNumber}}</bold> bảng mới sẽ được thêm vào.', | ||||
|                     new_relationships: | ||||
|                         '<bold>{{newRelationshipsNumber}}</bold> quan hệ mới sẽ được tạo.', | ||||
|                     tables_override: | ||||
|                         '<bold>{{tablesOverrideNumber}}</bold> bảng sẽ bị ghi đè.', | ||||
|                     proceed: 'Bạn có muốn tiếp tục không?', | ||||
|                 }, | ||||
|                 import: 'Nhập', | ||||
|                 cancel: 'Hủy', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         export_image_dialog: { | ||||
|             title: 'Xuất ảnh', | ||||
|             description: 'Chọn tỉ lệ để xuất:', | ||||
|             scale_1x: '1x Thông thường', | ||||
|             scale_2x: '2x (Khuyến khích)', | ||||
|             scale_3x: '3x', | ||||
|             scale_4x: '4x', | ||||
|             cancel: 'Hủy', | ||||
|             export: 'Xuất', | ||||
|         }, | ||||
|  | ||||
|         new_table_schema_dialog: { | ||||
|             title: 'Chọn lược đồ', | ||||
|             description: | ||||
|                 'Nhiều lược đồ hiện đang được hiển thị. Chọn một lược đồ cho bảng mới.', | ||||
|             cancel: 'Hủy', | ||||
|             confirm: 'Xác nhận', | ||||
|         }, | ||||
|  | ||||
|         update_table_schema_dialog: { | ||||
|             title: 'Thay đổi lược đồ', | ||||
|             description: 'Cập nhật lược đồ bảng "{{tableName}}"', | ||||
|             cancel: 'Hủy', | ||||
|             confirm: 'Xác nhận', | ||||
|         }, | ||||
|  | ||||
|         star_us_dialog: { | ||||
|             title: 'Hãy giúp chúng tôi cải thiện!', | ||||
|             description: | ||||
|                 'Bạn có muốn ủng hộ chúng tôi bằng cách gắn sao trên GitHub không? Chỉ cần một cú nhấp chuột là được!', | ||||
|             close: 'Chưa phải bây giờ', | ||||
|             confirm: 'Dĩ nhiên rồi!', | ||||
|         }, | ||||
|         export_diagram_dialog: { | ||||
|             title: 'Xuất sơ đồ', | ||||
|             description: 'Chọn định dạng để xuất:', | ||||
|             format_json: 'JSON', | ||||
|             cancel: 'Hủy', | ||||
|             export: 'Xuất', | ||||
|             error: { | ||||
|                 title: 'Lỗi khi xuất sơ đồ', | ||||
|                 description: | ||||
|                     'Có gì đó không ổn. Cần trợ giúp? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         import_diagram_dialog: { | ||||
|             title: 'Nhập sơ đồ', | ||||
|             description: 'Dán sơ đồ ở dạng JSON bên dưới:', | ||||
|             cancel: 'Hủy', | ||||
|             import: 'Nhập', | ||||
|             error: { | ||||
|                 title: 'Lỗi khi nhập sơ đồ', | ||||
|                 description: | ||||
|                     'Sơ đồ ở dạng JSON không hợp lệ. Vui lòng kiểm tra JSON và thử lại. Bạn cần trợ giúp? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|         relationship_type: { | ||||
|             one_to_one: 'Quan hệ một-một', | ||||
|             one_to_many: 'Quan hệ một-nhiều', | ||||
|             many_to_one: 'Quan hệ nhiều-một', | ||||
|             many_to_many: 'Quan hệ nhiều-nhiều', | ||||
|         }, | ||||
|  | ||||
|         canvas_context_menu: { | ||||
|             new_table: 'Tạo bảng mới', | ||||
|             new_relationship: 'Tạo quan hệ mới', | ||||
|         }, | ||||
|  | ||||
|         table_node_context_menu: { | ||||
|             edit_table: 'Sửa bảng', | ||||
|             duplicate_table: 'Nhân đôi bảng', | ||||
|             delete_table: 'Xóa bảng', | ||||
|         }, | ||||
|  | ||||
|         snap_to_grid_tooltip: 'Căn lưới (Giữ phím {{key}})', | ||||
|  | ||||
|         tool_tips: { | ||||
|             double_click_to_edit: 'Nhấp đúp để chỉnh sửa', | ||||
|         }, | ||||
|  | ||||
|         language_select: { | ||||
|             change_language: 'Ngôn ngữ', | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| export const viMetadata: LanguageMetadata = { | ||||
|     name: 'Vietnamese', | ||||
|     nativeName: 'Tiếng Việt', | ||||
|     code: 'vi', | ||||
| }; | ||||
| @@ -334,6 +334,12 @@ export const zh_CN: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: '取消', | ||||
|             export: '导出', | ||||
|             // TODO: translate | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
| @@ -333,6 +333,12 @@ export const zh_TW: LanguageTranslation = { | ||||
|             format_json: 'JSON', | ||||
|             cancel: '取消', | ||||
|             export: '匯出', | ||||
|             // TODO: Translate | ||||
|             error: { | ||||
|                 title: 'Error exporting diagram', | ||||
|                 description: | ||||
|                     'Something went wrong. Need help? chartdb.io@gmail.com', | ||||
|             }, | ||||
|         }, | ||||
|  | ||||
|         import_diagram_dialog: { | ||||
|   | ||||
| @@ -16,10 +16,6 @@ | ||||
|         @apply hidden !important; | ||||
|     } | ||||
|  | ||||
|     .scrollable-flex > div { | ||||
|         @apply !flex; | ||||
|     } | ||||
|  | ||||
|     .marker-definitions { | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										120
									
								
								src/lib/clone.ts
									
									
									
									
									
								
							
							
						
						| @@ -63,28 +63,51 @@ export const cloneTable = ( | ||||
|         ...options.idsMap, | ||||
|     ]); | ||||
|  | ||||
|     const getNewId = (id: string) => { | ||||
|     const getNewId = (id: string): string | null => { | ||||
|         const newId = idsMap.get(id); | ||||
|         if (!newId) { | ||||
|             throw new Error(`Id not found for ${id}`); | ||||
|             return null; | ||||
|         } | ||||
|         return newId; | ||||
|     }; | ||||
|  | ||||
|     const newTable: DBTable = { ...table, id: getNewId(table.id) }; | ||||
|     newTable.fields = table.fields.map( | ||||
|         (field): DBField => ({ | ||||
|             ...field, | ||||
|             id: getNewId(field.id), | ||||
|     const tableId = getNewId(table.id); | ||||
|     if (!tableId) { | ||||
|         throw new Error('Table id not found'); | ||||
|     } | ||||
|  | ||||
|     const newTable: DBTable = { ...table, id: tableId }; | ||||
|     newTable.fields = table.fields | ||||
|         .map((field): DBField | null => { | ||||
|             const id = getNewId(field.id); | ||||
|  | ||||
|             if (!id) { | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 ...field, | ||||
|                 id, | ||||
|             }; | ||||
|         }) | ||||
|     ); | ||||
|     newTable.indexes = table.indexes.map( | ||||
|         (index): DBIndex => ({ | ||||
|             ...index, | ||||
|             fieldIds: index.fieldIds.map((id) => getNewId(id)), | ||||
|             id: getNewId(index.id), | ||||
|         .filter((field): field is DBField => field !== null); | ||||
|     newTable.indexes = table.indexes | ||||
|         .map((index): DBIndex | null => { | ||||
|             const id = getNewId(index.id); | ||||
|  | ||||
|             if (!id) { | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 ...index, | ||||
|                 fieldIds: index.fieldIds | ||||
|                     .map((id) => getNewId(id)) | ||||
|                     .filter((fieldId): fieldId is string => fieldId !== null), | ||||
|                 id, | ||||
|             }; | ||||
|         }) | ||||
|     ); | ||||
|         .filter((index): index is DBIndex => index !== null); | ||||
|  | ||||
|     return newTable; | ||||
| }; | ||||
| @@ -102,10 +125,10 @@ export const cloneDiagram = ( | ||||
|  | ||||
|     const idsMap = generateIdsMapFromDiagram(diagram, generateId); | ||||
|  | ||||
|     const getNewId = (id: string) => { | ||||
|     const getNewId = (id: string): string | null => { | ||||
|         const newId = idsMap.get(id); | ||||
|         if (!newId) { | ||||
|             throw new Error(`Id not found for ${id}`); | ||||
|             return null; | ||||
|         } | ||||
|         return newId; | ||||
|     }; | ||||
| @@ -116,26 +139,59 @@ export const cloneDiagram = ( | ||||
|         ) ?? []; | ||||
|  | ||||
|     const relationships: DBRelationship[] = | ||||
|         diagram.relationships?.map( | ||||
|             (relationship): DBRelationship => ({ | ||||
|                 ...relationship, | ||||
|                 id: getNewId(relationship.id), | ||||
|                 sourceTableId: getNewId(relationship.sourceTableId), | ||||
|                 targetTableId: getNewId(relationship.targetTableId), | ||||
|                 sourceFieldId: getNewId(relationship.sourceFieldId), | ||||
|                 targetFieldId: getNewId(relationship.targetFieldId), | ||||
|         diagram.relationships | ||||
|             ?.map((relationship): DBRelationship | null => { | ||||
|                 const id = getNewId(relationship.id); | ||||
|                 const sourceTableId = getNewId(relationship.sourceTableId); | ||||
|                 const targetTableId = getNewId(relationship.targetTableId); | ||||
|                 const sourceFieldId = getNewId(relationship.sourceFieldId); | ||||
|                 const targetFieldId = getNewId(relationship.targetFieldId); | ||||
|  | ||||
|                 if ( | ||||
|                     !id || | ||||
|                     !sourceTableId || | ||||
|                     !targetTableId || | ||||
|                     !sourceFieldId || | ||||
|                     !targetFieldId | ||||
|                 ) { | ||||
|                     return null; | ||||
|                 } | ||||
|  | ||||
|                 return { | ||||
|                     ...relationship, | ||||
|                     id, | ||||
|                     sourceTableId, | ||||
|                     targetTableId, | ||||
|                     sourceFieldId, | ||||
|                     targetFieldId, | ||||
|                 }; | ||||
|             }) | ||||
|         ) ?? []; | ||||
|             .filter( | ||||
|                 (relationship): relationship is DBRelationship => | ||||
|                     relationship !== null | ||||
|             ) ?? []; | ||||
|  | ||||
|     const dependencies: DBDependency[] = | ||||
|         diagram.dependencies?.map( | ||||
|             (dependency): DBDependency => ({ | ||||
|                 ...dependency, | ||||
|                 id: getNewId(dependency.id), | ||||
|                 dependentTableId: getNewId(dependency.dependentTableId), | ||||
|                 tableId: getNewId(dependency.tableId), | ||||
|         diagram.dependencies | ||||
|             ?.map((dependency): DBDependency | null => { | ||||
|                 const id = getNewId(dependency.id); | ||||
|                 const dependentTableId = getNewId(dependency.dependentTableId); | ||||
|                 const tableId = getNewId(dependency.tableId); | ||||
|  | ||||
|                 if (!id || !dependentTableId || !tableId) { | ||||
|                     return null; | ||||
|                 } | ||||
|  | ||||
|                 return { | ||||
|                     ...dependency, | ||||
|                     id, | ||||
|                     dependentTableId, | ||||
|                     tableId, | ||||
|                 }; | ||||
|             }) | ||||
|         ) ?? []; | ||||
|             .filter( | ||||
|                 (dependency): dependency is DBDependency => dependency !== null | ||||
|             ) ?? []; | ||||
|  | ||||
|     return { | ||||
|         ...diagram, | ||||
|   | ||||
| @@ -82,6 +82,8 @@ export const exportBaseSQL = (diagram: Diagram): string => { | ||||
|             // Add size for character types | ||||
|             if (field.characterMaximumLength) { | ||||
|                 sqlScript += `(${field.characterMaximumLength})`; | ||||
|             } else if (field.type.name.toLowerCase().includes('varchar')) { | ||||
|                 sqlScript += `(500)`; | ||||
|             } | ||||
|  | ||||
|             // Add precision and scale for numeric types | ||||
| @@ -96,6 +98,11 @@ export const exportBaseSQL = (diagram: Diagram): string => { | ||||
|                 sqlScript += ' NOT NULL'; | ||||
|             } | ||||
|  | ||||
|             // Handle UNIQUE value | ||||
|             if (!field.primaryKey && field.unique) { | ||||
|                 sqlScript += ` UNIQUE`; | ||||
|             } | ||||
|  | ||||
|             // Handle DEFAULT value | ||||
|             if (field.default) { | ||||
|                 // Temp remove default user-define value when it have it | ||||
|   | ||||
| @@ -15,6 +15,9 @@ export const fixMetadataJson = async ( | ||||
|             .replace(/^\s+|\s+$/g, '') | ||||
|             .replace(/^"|"$/g, '') | ||||
|             .replace(/^'|'$/g, '') | ||||
|             .replace(/""""/g, '""') // Remove Quadruple quotes from keys | ||||
|             .replace(/"""([^",}]+)"""/g, '"$1"') // Remove tripple quotes from keys | ||||
|             .replace(/""([^",}]+)""/g, '"$1"') // Remove double quotes from keys | ||||
|             /* eslint-disable-next-line no-useless-escape */ | ||||
|             .replace(/\"/g, '___ESCAPED_QUOTE___') // Temporarily replace empty strings | ||||
|             .replace(/(?<=:\s*)""(?=\s*[,}])/g, '___EMPTY___') // Temporarily replace empty strings | ||||
|   | ||||
| @@ -6,9 +6,9 @@ import { | ||||
| } from '@/components/resizable/resizable'; | ||||
| import { SidePanel } from './side-panel/side-panel'; | ||||
| import { Canvas } from './canvas/canvas'; | ||||
| import { useBreakpoint } from '@/hooks/use-breakpoint'; | ||||
| import { useLayout } from '@/hooks/use-layout'; | ||||
| import type { Diagram } from '@/lib/domain/diagram'; | ||||
| import { cn } from '@/lib/utils'; | ||||
|  | ||||
| export interface EditorDesktopLayoutProps { | ||||
|     initialDiagram?: Diagram; | ||||
| @@ -17,22 +17,21 @@ export const EditorDesktopLayout: React.FC<EditorDesktopLayoutProps> = ({ | ||||
|     initialDiagram, | ||||
| }) => { | ||||
|     const { isSidePanelShowed } = useLayout(); | ||||
|     const { isLg } = useBreakpoint('lg'); | ||||
|     const { isXl } = useBreakpoint('xl'); | ||||
|  | ||||
|     return ( | ||||
|         <ResizablePanelGroup direction="horizontal"> | ||||
|             <ResizablePanel | ||||
|                 defaultSize={isXl ? 25 : isLg ? 35 : 50} | ||||
|                 minSize={isXl ? 25 : isLg ? 35 : 50} | ||||
|                 defaultSize={25} | ||||
|                 minSize={25} | ||||
|                 maxSize={isSidePanelShowed ? 99 : 0} | ||||
|                 // eslint-disable-next-line | ||||
|                 className="transition-[flex-grow] duration-200" | ||||
|                 className={cn('transition-[flex-grow] duration-200', { | ||||
|                     'min-w-[350px]': isSidePanelShowed, | ||||
|                 })} | ||||
|             > | ||||
|                 <SidePanel /> | ||||
|             </ResizablePanel> | ||||
|             <ResizableHandle /> | ||||
|             <ResizablePanel defaultSize={isXl ? 75 : isLg ? 65 : 50}> | ||||
|             <ResizableHandle disabled={!isSidePanelShowed} /> | ||||
|             <ResizablePanel defaultSize={75}> | ||||
|                 <Canvas initialTables={initialDiagram?.tables ?? []} /> | ||||
|             </ResizablePanel> | ||||
|         </ResizablePanelGroup> | ||||
|   | ||||
| @@ -467,6 +467,14 @@ export const TopNavbar: React.FC<TopNavbarProps> = () => { | ||||
|                                 {isSidePanelShowed | ||||
|                                     ? t('menu.view.hide_sidebar') | ||||
|                                     : t('menu.view.show_sidebar')} | ||||
|                                 <MenubarShortcut> | ||||
|                                     { | ||||
|                                         keyboardShortcutsForOS[ | ||||
|                                             KeyboardShortcutAction | ||||
|                                                 .TOGGLE_SIDE_PANEL | ||||
|                                         ].keyCombinationLabel | ||||
|                                     } | ||||
|                                 </MenubarShortcut> | ||||
|                             </MenubarItem> | ||||
|                             <MenubarSeparator /> | ||||
|                             <MenubarItem onClick={showOrHideCardinality}> | ||||
|   | ||||
							
								
								
									
										141
									
								
								src/pages/templates-page/templates-page-helmet.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,141 @@ | ||||
| import React, { useMemo } from 'react'; | ||||
| import { useParams } from 'react-router-dom'; | ||||
| import { Helmet } from 'react-helmet-async'; | ||||
| import { HOST_URL } from '@/lib/env'; | ||||
|  | ||||
| export interface TemplatesPageHelmetProps { | ||||
|     tag?: string; | ||||
|     isFeatured: boolean; | ||||
| } | ||||
|  | ||||
| const CHARTDB_HOST_URL = 'https://chartdb.io'; | ||||
| export const TemplatesPageHelmet: React.FC<TemplatesPageHelmetProps> = ({ | ||||
|     tag, | ||||
|     isFeatured, | ||||
| }) => { | ||||
|     const { tag: tagParam } = useParams<{ tag: string }>(); | ||||
|  | ||||
|     const formattedUrlTag = useMemo( | ||||
|         () => tag?.toLowerCase().replace(/ /g, '-'), | ||||
|         [tag] | ||||
|     ); | ||||
|  | ||||
|     const canonicalUrl = useMemo(() => { | ||||
|         let suffix = '/templates'; | ||||
|         if (formattedUrlTag) { | ||||
|             suffix += `/tags/${formattedUrlTag}`; | ||||
|         } else if (isFeatured) { | ||||
|             suffix += '/featured'; | ||||
|         } | ||||
|  | ||||
|         return `${CHARTDB_HOST_URL}${suffix}`; | ||||
|     }, [isFeatured, formattedUrlTag]); | ||||
|  | ||||
|     const needCanonical = | ||||
|         HOST_URL !== CHARTDB_HOST_URL || (tag && formattedUrlTag !== tagParam); | ||||
|  | ||||
|     return ( | ||||
|         <Helmet> | ||||
|             {needCanonical ? ( | ||||
|                 <link rel="canonical" href={canonicalUrl} /> | ||||
|             ) : null} | ||||
|  | ||||
|             {tag ? ( | ||||
|                 <title>{`${tag} database schema diagram templates | ChartDB`}</title> | ||||
|             ) : isFeatured ? ( | ||||
|                 <title> | ||||
|                     Featured database schema diagram templates | ChartDB | ||||
|                 </title> | ||||
|             ) : ( | ||||
|                 <title>Database schema diagram templates | ChartDB</title> | ||||
|             )} | ||||
|  | ||||
|             {tag ? ( | ||||
|                 <meta | ||||
|                     name="description" | ||||
|                     content={`Discover a collection of real-world database schema diagrams for ${tag}, featuring example applications and popular open-source projects.`} | ||||
|                 /> | ||||
|             ) : ( | ||||
|                 <meta | ||||
|                     name="description" | ||||
|                     content="Discover a collection of real-world database schema diagrams, featuring example applications and popular open-source projects." | ||||
|                 /> | ||||
|             )} | ||||
|  | ||||
|             {tag ? ( | ||||
|                 <meta | ||||
|                     property="og:title" | ||||
|                     content={`${tag} database schema diagram templates | ChartDB`} | ||||
|                 /> | ||||
|             ) : isFeatured ? ( | ||||
|                 <meta | ||||
|                     property="og:title" | ||||
|                     content="Featured database schema diagram templates | ChartDB" | ||||
|                 /> | ||||
|             ) : ( | ||||
|                 <meta | ||||
|                     property="og:title" | ||||
|                     content="Database schema diagram templates | ChartDB" | ||||
|                 /> | ||||
|             )} | ||||
|  | ||||
|             {tag ? ( | ||||
|                 <meta | ||||
|                     property="og:url" | ||||
|                     content={`${HOST_URL}/templates/${tagParam}`} | ||||
|                 /> | ||||
|             ) : isFeatured ? ( | ||||
|                 <meta | ||||
|                     property="og:url" | ||||
|                     content={`${HOST_URL}/templates/featured`} | ||||
|                 /> | ||||
|             ) : ( | ||||
|                 <meta property="og:url" content={`${HOST_URL}/templates`} /> | ||||
|             )} | ||||
|  | ||||
|             {tag ? ( | ||||
|                 <meta | ||||
|                     property="og:description" | ||||
|                     content={`Discover a collection of real-world database schema diagrams for ${tag}, featuring example applications and popular open-source projects.`} | ||||
|                 /> | ||||
|             ) : ( | ||||
|                 <meta | ||||
|                     property="og:description" | ||||
|                     content="Discover a collection of real-world database schema diagrams, featuring example applications and popular open-source projects." | ||||
|                 /> | ||||
|             )} | ||||
|             <meta property="og:image" content={`${HOST_URL}/chartdb.png`} /> | ||||
|             <meta property="og:type" content="website" /> | ||||
|             <meta property="og:site_name" content="ChartDB" /> | ||||
|  | ||||
|             {tag ? ( | ||||
|                 <meta | ||||
|                     name="twitter:title" | ||||
|                     content={`${tag} database schema diagram templates | ChartDB`} | ||||
|                 /> | ||||
|             ) : ( | ||||
|                 <meta | ||||
|                     name="twitter:title" | ||||
|                     content="Database schema diagram templates | ChartDB" | ||||
|                 /> | ||||
|             )} | ||||
|  | ||||
|             {tag ? ( | ||||
|                 <meta | ||||
|                     name="twitter:description" | ||||
|                     content={`Discover a collection of real-world database schema diagrams for ${tag}, featuring example applications and popular open-source projects.`} | ||||
|                 /> | ||||
|             ) : ( | ||||
|                 <meta | ||||
|                     name="twitter:description" | ||||
|                     content="Discover a collection of real-world database schema diagrams, featuring example applications and popular open-source projects." | ||||
|                 /> | ||||
|             )} | ||||
|  | ||||
|             <meta name="twitter:image" content={`${HOST_URL}/chartdb.png`} /> | ||||
|             <meta name="twitter:card" content="summary_large_image" /> | ||||
|             <meta name="twitter:site" content="@ChartDB_io" /> | ||||
|             <meta name="twitter:creator" content="@ChartDB_io" /> | ||||
|         </Helmet> | ||||
|     ); | ||||
| }; | ||||
| @@ -10,8 +10,7 @@ import { TemplateCard } from './template-card/template-card'; | ||||
| import { useLoaderData, useMatches, useParams } from 'react-router-dom'; | ||||
| import type { Template } from '@/templates-data/templates-data'; | ||||
| import { Spinner } from '@/components/spinner/spinner'; | ||||
| import { Helmet } from 'react-helmet-async'; | ||||
| import { HOST_URL } from '@/lib/env'; | ||||
| import { TemplatesPageHelmet } from './templates-page-helmet'; | ||||
|  | ||||
| export interface TemplatesPageLoaderData { | ||||
|     templates: Template[] | undefined; | ||||
| @@ -23,53 +22,21 @@ const TemplatesPageComponent: React.FC = () => { | ||||
|     const data = useLoaderData() as TemplatesPageLoaderData; | ||||
|  | ||||
|     const { templates, allTags } = data ?? {}; | ||||
|     const { tag } = useParams<{ tag: string }>(); | ||||
|     const { tag: tagParam } = useParams<{ tag: string }>(); | ||||
|     const matches = useMatches(); | ||||
|     const isFeatured = matches.some( | ||||
|         (match) => match.id === 'templates_featured' | ||||
|     ); | ||||
|     const isAllTemplates = matches.some((match) => match.id === 'templates'); | ||||
|     const tag = allTags?.find( | ||||
|         (currentTag) => | ||||
|             tagParam?.toLowerCase().replace(/-/g, ' ') === | ||||
|             currentTag.toLowerCase() | ||||
|     ); | ||||
|  | ||||
|     return ( | ||||
|         <> | ||||
|             <Helmet> | ||||
|                 {HOST_URL !== 'https://chartdb.io' ? ( | ||||
|                     <link rel="canonical" href="https://chartdb.io/templates" /> | ||||
|                 ) : null} | ||||
|                 <title>Database Schema Diagram Templates | ChartDB</title> | ||||
|                 <meta | ||||
|                     name="description" | ||||
|                     content="Discover a collection of real-world database schema diagrams, featuring example applications and popular open-source projects." | ||||
|                 /> | ||||
|                 <meta | ||||
|                     property="og:title" | ||||
|                     content="Database Schema Diagram Templates | ChartDB" | ||||
|                 /> | ||||
|                 <meta property="og:url" content={`${HOST_URL}/templates`} /> | ||||
|                 <meta | ||||
|                     property="og:description" | ||||
|                     content="Discover a collection of real-world database schema diagrams, featuring example applications and popular open-source projects." | ||||
|                 /> | ||||
|                 <meta property="og:image" content={`${HOST_URL}/chartdb.png`} /> | ||||
|                 <meta property="og:type" content="website" /> | ||||
|                 <meta property="og:site_name" content="ChartDB" /> | ||||
|                 <meta | ||||
|                     name="twitter:title" | ||||
|                     content="Database Schema Diagram Templates | ChartDB" | ||||
|                 /> | ||||
|                 <meta | ||||
|                     name="twitter:description" | ||||
|                     content="Discover a collection of real-world database schema diagrams, featuring example applications and popular open-source projects." | ||||
|                 /> | ||||
|                 <meta | ||||
|                     name="twitter:image" | ||||
|                     content={`${HOST_URL}/chartdb.png`} | ||||
|                 /> | ||||
|                 <meta name="twitter:card" content="summary_large_image" /> | ||||
|                 <meta name="twitter:site" content="@ChartDB_io" /> | ||||
|                 <meta name="twitter:creator" content="@ChartDB_io" /> | ||||
|             </Helmet> | ||||
|  | ||||
|             <TemplatesPageHelmet tag={tag} isFeatured={isFeatured} /> | ||||
|             <section className="flex w-screen flex-col bg-background"> | ||||
|                 <nav className="flex h-12 shrink-0 flex-row items-center justify-between border-b px-4"> | ||||
|                     <div className="flex flex-1 justify-start gap-x-3"> | ||||
| @@ -102,12 +69,25 @@ const TemplatesPageComponent: React.FC = () => { | ||||
|                 </nav> | ||||
|                 <div className="flex flex-col p-3 text-center md:px-28 md:text-left"> | ||||
|                     <h1 className="font-primary text-2xl font-bold"> | ||||
|                         Database Schema Templates | ||||
|                         {isFeatured | ||||
|                             ? 'Featured database schema templates' | ||||
|                             : tag | ||||
|                               ? `Database schema templates for ${tag}` | ||||
|                               : 'Database schema templates'} | ||||
|                     </h1> | ||||
|                     <h2 className="mt-1 font-primary text-base text-muted-foreground"> | ||||
|                         Discover a collection of real-world database schema | ||||
|                         diagrams, featuring example applications and popular | ||||
|                         open-source projects. | ||||
|                         diagrams | ||||
|                         {tag ? ( | ||||
|                             <> | ||||
|                                 {' for '} | ||||
|                                 <span className="font-semibold">{tag}</span> | ||||
|                             </> | ||||
|                         ) : ( | ||||
|                             '' | ||||
|                         )} | ||||
|                         , featuring example applications and popular open-source | ||||
|                         projects. | ||||
|                     </h2> | ||||
|                     {!templates ? ( | ||||
|                         <Spinner | ||||
| @@ -143,11 +123,7 @@ const TemplatesPageComponent: React.FC = () => { | ||||
|                                         items={allTags.map((currentTag) => ({ | ||||
|                                             title: currentTag, | ||||
|                                             href: `/templates/tags/${currentTag.toLowerCase().replace(/ /g, '-')}`, | ||||
|                                             selected: | ||||
|                                                 tag | ||||
|                                                     ?.toLowerCase() | ||||
|                                                     .replace(/-/g, ' ') === | ||||
|                                                 currentTag.toLowerCase(), | ||||
|                                             selected: tag === currentTag, | ||||
|                                         }))} | ||||
|                                     /> | ||||
|                                 ) : null} | ||||
|   | ||||
| @@ -25,6 +25,12 @@ import { monicaDb } from './templates/monica-db'; | ||||
| import { attendizeDb } from './templates/attendize-db'; | ||||
| import { saasPegasusDb } from './templates/saas-pegasus-db'; | ||||
| import { bookstackDb } from './templates/bookstack-db'; | ||||
| import { bouncerDb } from './templates/bouncer-db'; | ||||
| import { cabotDb } from './templates/cabot-db'; | ||||
| import { feedbinDb } from './templates/feedbin-db'; | ||||
| import { freescoutDb } from './templates/freescout-db'; | ||||
| import { hackerNewsDb } from './templates/hacker-news-db'; | ||||
| import { flarumDb } from './templates/flarum-db'; | ||||
| export interface Template { | ||||
|     slug: string; | ||||
|     name: string; | ||||
| @@ -65,4 +71,10 @@ export const templates: Template[] = [ | ||||
|     attendizeDb, | ||||
|     saasPegasusDb, | ||||
|     bookstackDb, | ||||
|     bouncerDb, | ||||
|     cabotDb, | ||||
|     feedbinDb, | ||||
|     freescoutDb, | ||||
|     hackerNewsDb, | ||||
|     flarumDb, | ||||
| ]; | ||||
|   | ||||
							
								
								
									
										983
									
								
								src/templates-data/templates/bouncer-db.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,983 @@ | ||||
| import { DatabaseType } from '@/lib/domain/database-type'; | ||||
| import type { Template } from '../templates-data'; | ||||
| import image from '@/assets/templates/bouncer-db.png'; | ||||
| import imageDark from '@/assets/templates/bouncer-db-dark.png'; | ||||
|  | ||||
| export const bouncerDb: Template = { | ||||
|     slug: 'bouncer-database', | ||||
|     name: 'Bouncer', | ||||
|     shortDescription: 'Laravel Eloquent roles and abilities', | ||||
|     description: | ||||
|         'framework-agnostic approach to managing roles and abilities for any app using Eloquent models.', | ||||
|     image, | ||||
|     imageDark, | ||||
|     tags: ['Postgres', 'Laravel', 'PHP'], | ||||
|     featured: false, | ||||
|     url: 'https://github.com/JosephSilber/bouncer', | ||||
|     diagram: { | ||||
|         id: 'bouncer_db', | ||||
|         name: 'bouncer-database', | ||||
|         createdAt: new Date(), | ||||
|         updatedAt: new Date(), | ||||
|         databaseType: DatabaseType.POSTGRESQL, | ||||
|         tables: [ | ||||
|             { | ||||
|                 id: '1ecviq82pwny6e5qsftqqv85t', | ||||
|                 name: 'roles', | ||||
|                 schema: 'public', | ||||
|                 x: 900, | ||||
|                 y: 100, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: '6dgpy48ulwwj4la0v9qyasacn', | ||||
|                         name: 'id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: true, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'g8j0s94za7lstfgqpu0rjv30q', | ||||
|                         name: 'name', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'mt51mbyv77zhhlxo6aoqtdrvb', | ||||
|                         name: 'title', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'r0kdjfscr4qrxug9lltz8ff05', | ||||
|                         name: 'level', | ||||
|                         type: { | ||||
|                             id: 'integer', | ||||
|                             name: 'integer', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '8pc8xntbm3ie0to59grej0hi0', | ||||
|                         name: 'scope', | ||||
|                         type: { | ||||
|                             id: 'integer', | ||||
|                             name: 'integer', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'r1bpa7kr06tlijcc5g6ozhyi1', | ||||
|                         name: 'created_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'fcghi02e6v8ituzvhxcqvry5s', | ||||
|                         name: 'updated_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: '5ozix6ibq6b8ifaqvpazqsd4e', | ||||
|                         name: 'roles_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: ['6dgpy48ulwwj4la0v9qyasacn'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'vb8w5m8rtwigvffo0hza1cnq5', | ||||
|                         name: 'roles_name_scope_unique', | ||||
|                         unique: true, | ||||
|                         fieldIds: [ | ||||
|                             'g8j0s94za7lstfgqpu0rjv30q', | ||||
|                             '8pc8xntbm3ie0to59grej0hi0', | ||||
|                         ], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'us1nbhilpzrzzdz20ee8b2yz5', | ||||
|                         name: 'roles_scope_index', | ||||
|                         unique: false, | ||||
|                         fieldIds: ['8pc8xntbm3ie0to59grej0hi0'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#ff6b8a', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: '2dk2y86w5uwob2walqmzpvd38', | ||||
|                 name: 'permissions', | ||||
|                 schema: 'public', | ||||
|                 x: 500, | ||||
|                 y: 100, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: 'dw9wefm90272eqrtdzc0kija2', | ||||
|                         name: 'id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: true, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'dln78b8156xss9vmtzufiyq89', | ||||
|                         name: 'ability_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'aybk9y71s2rkghsn2fpze24bc', | ||||
|                         name: 'entity_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '6jy0ziy0307k43itxl9syi36d', | ||||
|                         name: 'entity_type', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'os6d10ohhct1tftf3ddpzplgl', | ||||
|                         name: 'forbidden', | ||||
|                         type: { | ||||
|                             id: 'smallint', | ||||
|                             name: 'smallint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'o6zy8fbod1pojyclv43hpnzyq', | ||||
|                         name: 'scope', | ||||
|                         type: { | ||||
|                             id: 'integer', | ||||
|                             name: 'integer', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: 'dmuc2cgc1fsf7ex8848yfvf51', | ||||
|                         name: 'permissions_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: ['dw9wefm90272eqrtdzc0kija2'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'zauknvtjvcvv8s9kzmpcbidmq', | ||||
|                         name: 'permissions_entity_id_entity_type_scope_index', | ||||
|                         unique: false, | ||||
|                         fieldIds: [ | ||||
|                             'aybk9y71s2rkghsn2fpze24bc', | ||||
|                             '6jy0ziy0307k43itxl9syi36d', | ||||
|                             'o6zy8fbod1pojyclv43hpnzyq', | ||||
|                         ], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'm9h7f90dxevidzoel423z84pq', | ||||
|                         name: 'permissions_ability_id_index', | ||||
|                         unique: false, | ||||
|                         fieldIds: ['dln78b8156xss9vmtzufiyq89'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'e25jukkbmmmgtbux5mprd5c2t', | ||||
|                         name: 'permissions_scope_index', | ||||
|                         unique: false, | ||||
|                         fieldIds: ['o6zy8fbod1pojyclv43hpnzyq'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#ff6363', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: 'cv6gzut9xl6vi18h1uipfszse', | ||||
|                 name: 'abilities', | ||||
|                 schema: 'public', | ||||
|                 x: 100, | ||||
|                 y: 100, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: '5klow3heh0h4wyysvvlolrd3k', | ||||
|                         name: 'id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: true, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'b5fkxgkqocrav6gdjw5u8qna9', | ||||
|                         name: 'name', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'p9ein9lspzmrtrcgxnwcu4jtr', | ||||
|                         name: 'title', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'o7iqp8jvekbqmufkriravzd14', | ||||
|                         name: 'entity_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'z6347t0nenn6l7zfckobbkwky', | ||||
|                         name: 'entity_type', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'a42we94njfh5wfe40tzshz7yy', | ||||
|                         name: 'only_owned', | ||||
|                         type: { | ||||
|                             id: 'smallint', | ||||
|                             name: 'smallint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'ot976a09yh5xjnidymxl4bvx7', | ||||
|                         name: 'options', | ||||
|                         type: { | ||||
|                             id: 'json', | ||||
|                             name: 'json', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'sd6tn5b4dhrezroc5deefct22', | ||||
|                         name: 'scope', | ||||
|                         type: { | ||||
|                             id: 'integer', | ||||
|                             name: 'integer', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '7ei2ayl775rt4anar8we426b7', | ||||
|                         name: 'created_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '9frp78uwm48o3rehdgi8zfgwe', | ||||
|                         name: 'updated_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: '3tgypga0ix9jhfn7bed3lg3zf', | ||||
|                         name: 'abilities_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: ['5klow3heh0h4wyysvvlolrd3k'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'd4sskhldtbn57htxwc3qobpwp', | ||||
|                         name: 'abilities_scope_index', | ||||
|                         unique: false, | ||||
|                         fieldIds: ['sd6tn5b4dhrezroc5deefct22'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#9ef07a', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: 'e5a0uhiuu982vjhbujvd40klh', | ||||
|                 name: 'model_has_abilities', | ||||
|                 schema: 'public', | ||||
|                 x: 583.14307105074, | ||||
|                 y: 757.4824496551473, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: '7wir8w7knt9jwjkc4ttsl0vn6', | ||||
|                         name: 'ability_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'ojer4wzhyne7fdrgw9qy47x12', | ||||
|                         name: 'model_type', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'dzak2cn4sxwh0i85qpxxwnkz9', | ||||
|                         name: 'model_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 's6asnly67otxpgpvsfu0u4du5', | ||||
|                         name: 'scope', | ||||
|                         type: { | ||||
|                             id: 'integer', | ||||
|                             name: 'integer', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: 'lrsg01t8cmwyaezp5uamrjoto', | ||||
|                         name: 'model_has_abilities_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: [ | ||||
|                             '7wir8w7knt9jwjkc4ttsl0vn6', | ||||
|                             'ojer4wzhyne7fdrgw9qy47x12', | ||||
|                             'dzak2cn4sxwh0i85qpxxwnkz9', | ||||
|                         ], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#42e0c0', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: 'ftblbz8shvhibeyenqw2j66og', | ||||
|                 name: 'tenants', | ||||
|                 schema: 'public', | ||||
|                 x: 900, | ||||
|                 y: 600, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: 'rilheq75e61ukzvoovax5dww5', | ||||
|                         name: 'id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: true, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'hdvep6n3x5mpyize0poffmi8x', | ||||
|                         name: 'name', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '2zvadpju6k7472brqxnjwc25y', | ||||
|                         name: 'created_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '0a7ypts0qu8p8xdgmx973r0j2', | ||||
|                         name: 'updated_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: 'k6kmwfu8adxag9bzlvk0rfihc', | ||||
|                         name: 'tenants_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: ['rilheq75e61ukzvoovax5dww5'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#7175fa', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: 'lyw5j25p9jijopmxeg9wh21wt', | ||||
|                 name: 'assigned_roles', | ||||
|                 schema: 'public', | ||||
|                 x: 1300, | ||||
|                 y: 100, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: 'md1pv885295zlruqjf3bc2cn4', | ||||
|                         name: 'id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: true, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'wg9z61qv2m6gmqulnfrozpp0f', | ||||
|                         name: 'role_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'mr6hxkrpypz2vdsfidw3ilvzh', | ||||
|                         name: 'entity_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'g7u6a5onmfgzgm7qb528koa6w', | ||||
|                         name: 'entity_type', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'gvlv2hj10lgelg9cn3366sslu', | ||||
|                         name: 'restricted_to_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '1devmagh0xrj16ynyxvas28b4', | ||||
|                         name: 'restricted_to_type', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '27rz618ufyo31x2v9tqmv7bf9', | ||||
|                         name: 'scope', | ||||
|                         type: { | ||||
|                             id: 'integer', | ||||
|                             name: 'integer', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: 'v5jrok6ayblrkll3rj4opwb0v', | ||||
|                         name: 'assigned_roles_entity_id_entity_type_scope_index', | ||||
|                         unique: false, | ||||
|                         fieldIds: [ | ||||
|                             'mr6hxkrpypz2vdsfidw3ilvzh', | ||||
|                             'g7u6a5onmfgzgm7qb528koa6w', | ||||
|                             '27rz618ufyo31x2v9tqmv7bf9', | ||||
|                         ], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'ngfkhhz8p8qd1in8jfp3m33dh', | ||||
|                         name: 'assigned_roles_role_id_index', | ||||
|                         unique: false, | ||||
|                         fieldIds: ['wg9z61qv2m6gmqulnfrozpp0f'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'dmqwn02z4vxbyajgx9a85o9z4', | ||||
|                         name: 'assigned_roles_scope_index', | ||||
|                         unique: false, | ||||
|                         fieldIds: ['27rz618ufyo31x2v9tqmv7bf9'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'eanj0487n1x5r3kbf3asm1sgg', | ||||
|                         name: 'assigned_roles_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: ['md1pv885295zlruqjf3bc2cn4'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#8eb7ff', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: 'mcsql3yipul3bvoa8zp2z6xhm', | ||||
|                 name: 'model_has_roles', | ||||
|                 schema: 'public', | ||||
|                 x: 1192.3806696641184, | ||||
|                 y: 462.2441187492435, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: 'nmzyqbvbie1q6u0qdj2bx0ejk', | ||||
|                         name: 'role_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'dv9059syivzdb1lq2ibqhu0rf', | ||||
|                         name: 'model_type', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'tg1p3nusig09vpso36nv4cqsm', | ||||
|                         name: 'model_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '1ak37xnicelk5z4tpekrdhrcn', | ||||
|                         name: 'scope', | ||||
|                         type: { | ||||
|                             id: 'integer', | ||||
|                             name: 'integer', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: true, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: '1pnpzmyhlhs32qwtcwz1po9ja', | ||||
|                         name: 'model_has_roles_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: [ | ||||
|                             'nmzyqbvbie1q6u0qdj2bx0ejk', | ||||
|                             'dv9059syivzdb1lq2ibqhu0rf', | ||||
|                             'tg1p3nusig09vpso36nv4cqsm', | ||||
|                         ], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#ff6b8a', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: 'oy09nzysvqt9q38z38qdop5ky', | ||||
|                 name: 'users', | ||||
|                 schema: 'public', | ||||
|                 x: 598.0705987070124, | ||||
|                 y: 389.1233352248536, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: 'y13z863nrqq2jx88humld1c8l', | ||||
|                         name: 'id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: true, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'ki90zf8yhg9cr4qa58hoi4mhh', | ||||
|                         name: 'name', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '8qm8ms9bgwz5hhlaq5l36hnm1', | ||||
|                         name: 'email', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'vyso7h7t0wc441lj7zo51n5wd', | ||||
|                         name: 'password', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '8tmf7j5sga201ll66tufvruiu', | ||||
|                         name: 'created_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '5l5z4tzttk5f1xff7cot9aoxl', | ||||
|                         name: 'updated_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: 'nzc8rmf6y2cz9xjqnc90c4klf', | ||||
|                         name: 'users_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: ['y13z863nrqq2jx88humld1c8l'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#ff6b8a', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: 'rk4mh3tnvjgx2olpm5nu317g9', | ||||
|                 name: 'activity_logs', | ||||
|                 schema: 'public', | ||||
|                 x: 225.9858576165807, | ||||
|                 y: 561.8413654216401, | ||||
|                 fields: [ | ||||
|                     { | ||||
|                         id: '78k97fv3zqmnhqlygy10lq7oy', | ||||
|                         name: 'id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: true, | ||||
|                         unique: true, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'ulzkft5ohumvi9faj4ha0r1rn', | ||||
|                         name: 'loggable_type', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'r7utet2eq51fiqks56uird3ut', | ||||
|                         name: 'loggable_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: '73nnegxjwq3fpccbqzxhmhgfp', | ||||
|                         name: 'action', | ||||
|                         type: { | ||||
|                             id: 'character_varying', | ||||
|                             name: 'character varying', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'vav8txgj5835e0w3g86be4ozi', | ||||
|                         name: 'user_id', | ||||
|                         type: { | ||||
|                             id: 'bigint', | ||||
|                             name: 'bigint', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                     { | ||||
|                         id: 'nopldofnpy5yhlx2qcy92j3ix', | ||||
|                         name: 'created_at', | ||||
|                         type: { | ||||
|                             id: 'timestamp_without_time_zone', | ||||
|                             name: 'timestamp without time zone', | ||||
|                         }, | ||||
|                         primaryKey: false, | ||||
|                         unique: false, | ||||
|                         nullable: false, | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 indexes: [ | ||||
|                     { | ||||
|                         id: 'izfr3v00bqcrzcac5d745eztx', | ||||
|                         name: 'activity_logs_pkey', | ||||
|                         unique: true, | ||||
|                         fieldIds: ['78k97fv3zqmnhqlygy10lq7oy'], | ||||
|                         createdAt: Date.now(), | ||||
|                     }, | ||||
|                 ], | ||||
|                 color: '#ff6b8a', | ||||
|                 isView: false, | ||||
|                 isMaterializedView: false, | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|         ], | ||||
|         relationships: [ | ||||
|             { | ||||
|                 id: 'ikg1ovyjpye234c8zfhumhr6h', | ||||
|                 name: 'permissions_ability_id_foreign', | ||||
|                 sourceSchema: 'public', | ||||
|                 targetSchema: 'public', | ||||
|                 sourceTableId: '2dk2y86w5uwob2walqmzpvd38', | ||||
|                 targetTableId: 'cv6gzut9xl6vi18h1uipfszse', | ||||
|                 sourceFieldId: 'dln78b8156xss9vmtzufiyq89', | ||||
|                 targetFieldId: '5klow3heh0h4wyysvvlolrd3k', | ||||
|                 sourceCardinality: 'many', | ||||
|                 targetCardinality: 'one', | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|             { | ||||
|                 id: 'wkembgjtz8w9fau09ngjlxa8v', | ||||
|                 name: 'assigned_roles_role_id_foreign', | ||||
|                 sourceSchema: 'public', | ||||
|                 targetSchema: 'public', | ||||
|                 sourceTableId: 'lyw5j25p9jijopmxeg9wh21wt', | ||||
|                 targetTableId: '1ecviq82pwny6e5qsftqqv85t', | ||||
|                 sourceFieldId: 'wg9z61qv2m6gmqulnfrozpp0f', | ||||
|                 targetFieldId: '6dgpy48ulwwj4la0v9qyasacn', | ||||
|                 sourceCardinality: 'many', | ||||
|                 targetCardinality: 'one', | ||||
|                 createdAt: Date.now(), | ||||
|             }, | ||||
|         ], | ||||
|         dependencies: [], | ||||
|     }, | ||||
| }; | ||||
							
								
								
									
										2891
									
								
								src/templates-data/templates/cabot-db.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										4882
									
								
								src/templates-data/templates/feedbin-db.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										3163
									
								
								src/templates-data/templates/flarum-db.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										3869
									
								
								src/templates-data/templates/freescout-db.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										2737
									
								
								src/templates-data/templates/hacker-news-db.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -10,7 +10,7 @@ export const monicaDb: Template = { | ||||
|     description: 'Open Source eCommerce Framework on Symfony', | ||||
|     image, | ||||
|     imageDark, | ||||
|     tags: ['MySQL', 'Open Source', 'Laravel', 'Monica'], | ||||
|     tags: ['MySQL', 'Open Source', 'Laravel'], | ||||
|     featured: true, | ||||
|     url: 'https://github.com/monicahq/monica', | ||||
|     diagram: { | ||||
|   | ||||