Compare commits

..

23 Commits

Author SHA1 Message Date
Guy Ben-Aharon
24db32369a chore(main): release 1.3.0 (#417) 2024-11-25 19:14:51 +02:00
Guy Ben-Aharon
e77ee60a5b fix(i18n): add missing type to vi.ts (#444) 2024-11-25 14:42:14 +02:00
Huy Bui
6c65c2e9cc fix(i18n): add Vietnamese translations (#435) 2024-11-25 13:34:15 +02:00
Huy Bui
70f545f78b feat(side panel): collapsible side panel on desktop view + keyboard shortcut (#439)
* feat: collapsible sidebar on desktop view

* fix: remove unused wrapper

* feat: add toggle side panel hotkey
2024-11-25 13:14:48 +02:00
Jonathan Fishner
fb702c87ce fix(import script): remove double quotes (#442) 2024-11-24 18:25:14 +02:00
Jonathan Fishner
eaa067814f fix(templates): add Five more templates (bouncer, cabot, feedbin, Pythonic, flarum, freescout) (#441)
* feat(add templates): add three more templates (bouncer, cabot, feedbin)

* feat(add templates): add three more templates (Pythonic, flarum, freescout)

* fix build

* fix build
2024-11-24 18:22:50 +02:00
Guy Ben-Aharon
667685ed0f fix(dialogs): fix height of dialogs for small screens (#440)
* fix(dialogs): fix height of dialogs on small screens

* fix type
2024-11-24 12:21:15 +02:00
PRIYANSHI SHARMA
2940431efa fix(i18n): Translating to Gujarati language (#433)
* Translating to gujarati language good first issue #130

* fix build

---------

Co-authored-by: Guy Ben-Aharon <baguy3@gmail.com>
2024-11-23 19:39:13 +02:00
Guy Ben-Aharon
94ec43b608 fix: fix layout warnings (#434) 2024-11-21 20:30:00 +02:00
Guy Ben-Aharon
a2efed803f lint (#431) 2024-11-21 13:44:30 +02:00
VallabhaE
8749591be0 fix(i18n): Add Telugu Language (#352)
* Adding Telugu Language

* Adding Telugu Language

* revert package.json & package-lock.json

* fix build

---------

Co-authored-by: Guy Ben-Aharon <guybenah@gmail.com>
Co-authored-by: Guy Ben-Aharon <baguy3@gmail.com>
2024-11-21 11:35:35 +02:00
Guy Ben-Aharon
c5e0ea6fa4 fix(drawer): set fix min size (#429) 2024-11-20 18:45:32 +02:00
Wisnu Wicaksono
ab07da0b03 fix(i18n): add bahasa indonesia translation (#331)
* feat(i18n): add bahasa indonesia translation

* fix(i18n): update Indonesia name to Bahasa Indonesia in metadata

* fix(i18n): adjust top-navbar & add `id_ID` in `i18n`

* fix build

---------

Co-authored-by: Guy Ben-Aharon <baguy3@gmail.com>
2024-11-20 12:11:57 +02:00
☁️dungsil
8397bef392 fix(i18n): update korean for 1.2.0 (#419) 2024-11-19 11:53:06 +02:00
Zer0S2m
7c3c62860e fix(i18n): Translation of the export error into Russian (#418) 2024-11-19 11:45:48 +02:00
Guy Ben-Aharon
76ba4ce4c5 update canonical behavior on templates (#424) 2024-11-19 00:52:48 +02:00
Guy Ben-Aharon
0c0fad719f update canonical behavior on templates (#423) 2024-11-19 00:29:39 +02:00
Jonathan Fishner
b75c6fe4e7 fix(export-sql): add unique to export script (#422) 2024-11-18 21:28:14 +02:00
emircanakpinar
d9fcbeec72 fix(i18n): add Turkish translations (#315)
* fix(i18n): add missing Turkish translations

* fix translation build

---------

Co-authored-by: Guy Ben-Aharon <guybenah@gmail.com>
2024-11-18 16:00:30 +02:00
Guy Ben-Aharon
5d79721b6d update templates tag title (#420) 2024-11-18 14:30:12 +02:00
Guy Ben-Aharon
4be3592cf4 fix(share): fix export to handle broken indexes & relationships (#416) 2024-11-18 13:22:10 +02:00
Guy Ben-Aharon
b4cdcbbbd7 refactor template page - remove helmet data to a new component (#415)
* refactor template page - remove helmet data to a new component

* change texts

---------

Co-authored-by: johnnyfish <jonathanfishner11@gmail.com>
2024-11-18 12:28:04 +02:00
Jonathan Fishner
e9c7f4be06 Update README.md (#413)
* Update README.md

* Update README.md

* Update README.md
2024-11-17 14:14:50 +02:00
66 changed files with 21349 additions and 442 deletions

View File

@@ -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)

View File

@@ -16,6 +16,7 @@
<h3 align="center">
<a href="https://discord.gg/QeFwyWSKwC">Community</a> &bull;
<a href="https://www.chartdb.io?ref=github_readme">Website</a> &bull;
<a href="https://chartdb.io/templates?ref=github_readme">Examples</a> &bull;
<a href="https://app.chartdb.io?ref=github_readme">Demo</a>
</h3>

4
package-lock.json generated
View File

@@ -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",

View File

@@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 KiB

View File

@@ -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,
};

View File

@@ -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;

View File

@@ -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={{}}>

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 ? (

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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">

View File

@@ -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>

View File

@@ -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)

View File

@@ -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: {

View File

@@ -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: {

View File

@@ -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: {

View File

@@ -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
View 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',
};

View File

@@ -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
View 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',
};

View File

@@ -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: {

View File

@@ -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: '더블클릭하여 편집',

View File

@@ -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

View File

@@ -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: {

View File

@@ -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: {

View File

@@ -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
View 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
View 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',
};

View File

@@ -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
View 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',
};

View File

@@ -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: {

View File

@@ -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: {

View File

@@ -16,10 +16,6 @@
@apply hidden !important;
}
.scrollable-flex > div {
@apply !flex;
}
.marker-definitions {
}
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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}>

View 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>
);
};

View File

@@ -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}

View File

@@ -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,
];

View 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: [],
},
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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: {