d1s 0.2.10 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.next/.next/BUILD_ID +1 -1
- package/dist/.next/.next/app-build-manifest.json +33 -33
- package/dist/.next/.next/app-path-routes-manifest.json +1 -1
- package/dist/.next/.next/build-manifest.json +3 -3
- package/dist/.next/.next/cache/.rscinfo +1 -1
- package/dist/.next/.next/cache/.tsbuildinfo +1 -1
- package/dist/.next/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/1.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/10.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/11.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/12.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/2.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/3.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/4.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/5.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/6.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/7.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/8.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/9.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/dist/.next/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/0.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/1.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/dist/.next/.next/next-minimal-server.js.nft.json +1 -1
- package/dist/.next/.next/next-server.js.nft.json +1 -1
- package/dist/.next/.next/prerender-manifest.json +1 -1
- package/dist/.next/.next/required-server-files.json +1 -1
- package/dist/.next/.next/server/app/_not-found/page.js +1 -1
- package/dist/.next/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/.next/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/_not-found.html +1 -1
- package/dist/.next/.next/server/app/_not-found.rsc +4 -4
- package/dist/.next/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/databases/route.js +1 -1
- package/dist/.next/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync/route.js +5 -5
- package/dist/.next/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync-files/route.js +3 -3
- package/dist/.next/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pull-data/confirm/route.js +1 -1
- package/dist/.next/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js +2 -2
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/preview/route.js +4 -4
- package/dist/.next/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/push-remote/confirm/route.js +5 -5
- package/dist/.next/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/push-remote/preview/route.js +4 -4
- package/dist/.next/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/query/route.js +3 -3
- package/dist/.next/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/tables/[name]/route.js +5 -5
- package/dist/.next/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/tables/route.js +2 -2
- package/dist/.next/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/update/route.js +1 -1
- package/dist/.next/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/index.html +3 -3
- package/dist/.next/.next/server/app/index.rsc +5 -5
- package/dist/.next/.next/server/app/page.js +11 -13
- package/dist/.next/.next/server/app/page.js.nft.json +1 -1
- package/dist/.next/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app-paths-manifest.json +3 -3
- package/dist/.next/.next/server/chunks/226.js +12 -12
- package/dist/.next/.next/server/chunks/391.js +5 -5
- package/dist/.next/.next/server/chunks/452.js +1 -1
- package/dist/.next/.next/server/chunks/572.js +1 -0
- package/dist/.next/.next/server/chunks/627.js +3 -3
- package/dist/.next/.next/server/chunks/638.js +3 -3
- package/dist/.next/.next/server/chunks/992.js +3 -3
- package/dist/.next/.next/server/middleware-build-manifest.js +1 -1
- package/dist/.next/.next/server/next-font-manifest.js +1 -1
- package/dist/.next/.next/server/next-font-manifest.json +1 -1
- package/dist/.next/.next/server/pages/404.html +1 -1
- package/dist/.next/.next/server/pages/500.html +1 -1
- package/dist/.next/.next/server/pages/_app.js +1 -1
- package/dist/.next/.next/server/pages/_document.js +1 -1
- package/dist/.next/.next/server/pages/_error.js +1 -1
- package/dist/.next/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/.next/static/chunks/576-18a2209e1ed26aad.js +1 -0
- package/dist/.next/.next/static/chunks/{92-c4466e0f1ca8a3a8.js → 92-5f7522943fcb72a8.js} +1 -1
- package/dist/.next/.next/static/chunks/app/{layout-be6ee67cf0c92654.js → layout-40ec07d04681ba81.js} +1 -1
- package/dist/.next/.next/static/chunks/app/page-f05cd0fc436bf9bc.js +1 -0
- package/dist/.next/.next/static/chunks/{main-app-fa35024de9bd9284.js → main-app-4506e88db72db4b7.js} +1 -1
- package/dist/.next/.next/static/css/7c16f57d325d0d7d.css +3 -0
- package/dist/.next/.next/static/gABGrAoO8IPArDo_Ns_7g/_buildManifest.js +1 -0
- package/dist/.next/.next/static/gABGrAoO8IPArDo_Ns_7g/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/gh-QfIUVo4FTTduYCVKT6/_buildManifest.js +1 -0
- package/dist/.next/.next/static/gh-QfIUVo4FTTduYCVKT6/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/.next/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/.next/.next/static/ybCx6L6gHqtODbKmlhU-d/_buildManifest.js +1 -0
- package/dist/.next/.next/static/ybCx6L6gHqtODbKmlhU-d/_ssgManifest.js +1 -0
- package/dist/.next/.next/trace +3 -3
- package/dist/.next/.next/types/app/api/cloudflare/route.ts +1 -1
- package/dist/.next/.next/types/app/api/databases/route.ts +1 -1
- package/dist/.next/.next/types/app/api/migrations/sync/route.ts +1 -1
- package/dist/.next/.next/types/app/api/migrations/sync-files/route.ts +1 -1
- package/dist/.next/.next/types/app/api/pull-data/confirm/route.ts +1 -1
- package/dist/.next/.next/types/app/api/pull-remote/confirm/route.ts +1 -1
- package/dist/.next/.next/types/app/api/pull-remote/preview/route.ts +1 -1
- package/dist/.next/.next/types/app/api/push-remote/confirm/route.ts +1 -1
- package/dist/.next/.next/types/app/api/push-remote/preview/route.ts +1 -1
- package/dist/.next/.next/types/app/api/query/route.ts +1 -1
- package/dist/.next/.next/types/app/api/tables/[name]/route.ts +1 -1
- package/dist/.next/.next/types/app/api/tables/route.ts +1 -1
- package/dist/.next/.next/types/app/api/update/route.ts +1 -1
- package/dist/.next/.next/types/app/page.ts +1 -1
- package/dist/.next/BUILD_ID +1 -1
- package/dist/.next/app-build-manifest.json +32 -32
- package/dist/.next/app-path-routes-manifest.json +1 -1
- package/dist/.next/build-manifest.json +3 -3
- package/dist/.next/cache/.rscinfo +1 -1
- package/dist/.next/cache/.tsbuildinfo +1 -1
- package/dist/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/.next/cache/webpack/client-production/1.pack +0 -0
- package/dist/.next/cache/webpack/client-production/2.pack +0 -0
- package/dist/.next/cache/webpack/client-production/index.pack +0 -0
- package/dist/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/dist/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/dist/.next/cache/webpack/server-production/0.pack +0 -0
- package/dist/.next/cache/webpack/server-production/index.pack +0 -0
- package/dist/.next/next-minimal-server.js.nft.json +1 -1
- package/dist/.next/next-server.js.nft.json +1 -1
- package/dist/.next/prerender-manifest.json +1 -1
- package/dist/.next/required-server-files.json +1 -1
- package/dist/.next/server/app/_not-found/page.js +1 -1
- package/dist/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/_not-found.html +1 -1
- package/dist/.next/server/app/_not-found.rsc +4 -4
- package/dist/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/databases/route.js +1 -1
- package/dist/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/migrations/sync/route.js +5 -5
- package/dist/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/migrations/sync-files/route.js +3 -3
- package/dist/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-data/confirm/route.js +1 -1
- package/dist/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-remote/confirm/route.js +2 -2
- package/dist/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-remote/preview/route.js +4 -4
- package/dist/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/push-remote/confirm/route.js +5 -5
- package/dist/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/push-remote/preview/route.js +4 -4
- package/dist/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/query/route.js +3 -3
- package/dist/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/tables/[name]/route.js +5 -5
- package/dist/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/tables/route.js +2 -2
- package/dist/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/update/route.js +1 -1
- package/dist/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/index.html +3 -3
- package/dist/.next/server/app/index.rsc +5 -5
- package/dist/.next/server/app/page.js +11 -13
- package/dist/.next/server/app/page.js.nft.json +1 -1
- package/dist/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/.next/server/app-paths-manifest.json +2 -2
- package/dist/.next/server/chunks/226.js +12 -12
- package/dist/.next/server/chunks/391.js +5 -5
- package/dist/.next/server/chunks/452.js +1 -1
- package/dist/.next/server/chunks/572.js +1 -0
- package/dist/.next/server/chunks/627.js +3 -3
- package/dist/.next/server/chunks/638.js +3 -3
- package/dist/.next/server/chunks/992.js +3 -3
- package/dist/.next/server/middleware-build-manifest.js +1 -1
- package/dist/.next/server/next-font-manifest.js +1 -1
- package/dist/.next/server/next-font-manifest.json +1 -1
- package/dist/.next/server/pages/404.html +1 -1
- package/dist/.next/server/pages/500.html +1 -1
- package/dist/.next/server/pages/_app.js +1 -1
- package/dist/.next/server/pages/_document.js +1 -1
- package/dist/.next/server/pages/_error.js +1 -1
- package/dist/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/static/IX-QLbm7scYnyqWeeimal/_buildManifest.js +1 -0
- package/dist/.next/static/IX-QLbm7scYnyqWeeimal/_ssgManifest.js +1 -0
- package/dist/.next/static/chunks/576-18a2209e1ed26aad.js +1 -0
- package/dist/.next/static/chunks/{92-c4466e0f1ca8a3a8.js → 92-5f7522943fcb72a8.js} +1 -1
- package/dist/.next/static/chunks/app/{layout-be6ee67cf0c92654.js → layout-40ec07d04681ba81.js} +1 -1
- package/dist/.next/static/chunks/app/page-f05cd0fc436bf9bc.js +1 -0
- package/dist/.next/static/chunks/{main-app-fa35024de9bd9284.js → main-app-4506e88db72db4b7.js} +1 -1
- package/dist/.next/static/css/7c16f57d325d0d7d.css +3 -0
- package/dist/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/.next/trace +3 -16
- package/dist/.next/types/app/api/cloudflare/route.ts +1 -1
- package/dist/.next/types/app/api/databases/route.ts +1 -1
- package/dist/.next/types/app/api/migrations/sync/route.ts +1 -1
- package/dist/.next/types/app/api/migrations/sync-files/route.ts +1 -1
- package/dist/.next/types/app/api/pull-data/confirm/route.ts +1 -1
- package/dist/.next/types/app/api/pull-remote/confirm/route.ts +1 -1
- package/dist/.next/types/app/api/pull-remote/preview/route.ts +1 -1
- package/dist/.next/types/app/api/push-remote/confirm/route.ts +1 -1
- package/dist/.next/types/app/api/push-remote/preview/route.ts +1 -1
- package/dist/.next/types/app/api/query/route.ts +1 -1
- package/dist/.next/types/app/api/tables/[name]/route.ts +1 -1
- package/dist/.next/types/app/api/tables/route.ts +1 -1
- package/dist/.next/types/app/api/update/route.ts +1 -1
- package/dist/.next/types/app/page.ts +1 -1
- package/dist/app/api/tables/[name]/route.js +22 -10
- package/dist/app/globals.css +39 -0
- package/dist/app/page.jsx +13 -23
- package/dist/d1-studio.js +34 -4
- package/dist/lib/data-type-handlers.js +426 -0
- package/dist/lib/sql-operations.js +32 -8
- package/dist/lib/sql-sanitizer.js +233 -0
- package/package.json +3 -9
- package/dist/.next/.next/cache/webpack/server-production/2.pack +0 -0
- package/dist/.next/.next/server/chunks/90.js +0 -1
- package/dist/.next/.next/static/chunks/700-dc8f9f08b166c5e6.js +0 -1
- package/dist/.next/.next/static/chunks/app/page-16ec561fc8bebb5d.js +0 -1
- package/dist/.next/.next/static/css/0c512cea5f3d317a.css +0 -3
- package/dist/.next/server/chunks/90.js +0 -1
- package/dist/.next/static/chunks/700-dc8f9f08b166c5e6.js +0 -1
- package/dist/.next/static/chunks/app/page-16ec561fc8bebb5d.js +0 -1
- package/dist/.next/static/css/0c512cea5f3d317a.css +0 -3
- package/dist/app/app/api/cloudflare/route.js +0 -150
- package/dist/app/app/api/databases/route.js +0 -71
- package/dist/app/app/api/migrations/sync/route.js +0 -174
- package/dist/app/app/api/migrations/sync-files/route.js +0 -172
- package/dist/app/app/api/pull-data/confirm/route.js +0 -230
- package/dist/app/app/api/pull-remote/confirm/route.js +0 -278
- package/dist/app/app/api/pull-remote/preview/route.js +0 -144
- package/dist/app/app/api/push-remote/confirm/route.js +0 -196
- package/dist/app/app/api/push-remote/preview/route.js +0 -179
- package/dist/app/app/api/query/route.js +0 -168
- package/dist/app/app/api/tables/[name]/route.js +0 -174
- package/dist/app/app/api/tables/route.js +0 -178
- package/dist/app/app/api/update/route.js +0 -45
- package/dist/app/app/globals.css +0 -93
- package/dist/app/app/layout.jsx +0 -35
- package/dist/app/app/page.jsx +0 -44
- package/next.config.mjs +0 -18
- package/postcss.config.mjs +0 -8
- package/scripts/studio.js +0 -169
- package/scripts/test.js +0 -366
- package/src/app/api/cloudflare/route.js +0 -150
- package/src/app/api/databases/route.js +0 -71
- package/src/app/api/migrations/sync/route.js +0 -174
- package/src/app/api/migrations/sync-files/route.js +0 -172
- package/src/app/api/pull-data/confirm/route.js +0 -230
- package/src/app/api/pull-remote/confirm/route.js +0 -278
- package/src/app/api/pull-remote/preview/route.js +0 -144
- package/src/app/api/push-remote/confirm/route.js +0 -196
- package/src/app/api/push-remote/preview/route.js +0 -179
- package/src/app/api/query/route.js +0 -168
- package/src/app/api/tables/[name]/route.js +0 -174
- package/src/app/api/tables/route.js +0 -178
- package/src/app/api/update/route.js +0 -45
- package/src/app/globals.css +0 -93
- package/src/app/layout.jsx +0 -35
- package/src/app/page.jsx +0 -44
- package/src/components/cloudflare-credentials-modal.jsx +0 -94
- package/src/components/column-selector.jsx +0 -133
- package/src/components/column-sorting.jsx +0 -65
- package/src/components/delete-records-dialog.jsx +0 -64
- package/src/components/download-button.jsx +0 -205
- package/src/components/edit-error-alert.jsx +0 -30
- package/src/components/editable-cell.jsx +0 -163
- package/src/components/editable-row.jsx +0 -169
- package/src/components/environment-handler.jsx +0 -332
- package/src/components/environment-select.jsx +0 -62
- package/src/components/pull-preview-toast.jsx +0 -215
- package/src/components/push-error-alert.jsx +0 -72
- package/src/components/push-preview-toast.jsx +0 -183
- package/src/components/query-results.jsx +0 -112
- package/src/components/refresh-button.jsx +0 -61
- package/src/components/resize-columns.jsx +0 -101
- package/src/components/sidebar.jsx +0 -254
- package/src/components/sql-editor.jsx +0 -411
- package/src/components/sql-error-display.jsx +0 -167
- package/src/components/sync-migrations-button.jsx +0 -87
- package/src/components/table-error-dialog.jsx +0 -65
- package/src/components/table-toolbar.jsx +0 -285
- package/src/components/table-view.jsx +0 -843
- package/src/components/ui/alert.jsx +0 -47
- package/src/components/ui/button.jsx +0 -48
- package/src/components/ui/card.jsx +0 -50
- package/src/components/ui/checkbox.jsx +0 -24
- package/src/components/ui/collapsible.jsx +0 -11
- package/src/components/ui/dialog.jsx +0 -96
- package/src/components/ui/dropdown-menu.jsx +0 -158
- package/src/components/ui/input.jsx +0 -19
- package/src/components/ui/scroll-area.jsx +0 -40
- package/src/components/ui/select.jsx +0 -121
- package/src/components/ui/separator.jsx +0 -25
- package/src/components/ui/sheet.jsx +0 -109
- package/src/components/ui/sidebar.jsx +0 -620
- package/src/components/ui/skeleton.jsx +0 -14
- package/src/components/ui/table.jsx +0 -86
- package/src/components/ui/tabs.jsx +0 -43
- package/src/components/ui/toast.jsx +0 -86
- package/src/components/ui/toaster.jsx +0 -35
- package/src/components/ui/tooltip.jsx +0 -28
- package/src/components/update-banner.jsx +0 -93
- package/src/context/database-context.js +0 -510
- package/src/hooks/use-mobile.jsx +0 -19
- package/src/hooks/use-sql-error.ts +0 -23
- package/src/hooks/use-toast.js +0 -155
- package/src/lib/database-queue.js +0 -37
- package/src/lib/error.js +0 -20
- package/src/lib/find-wrangler-config.js +0 -74
- package/src/lib/license.js +0 -99
- package/src/lib/logger.js +0 -58
- package/src/lib/migrations.js +0 -415
- package/src/lib/parse-sql-error.js +0 -200
- package/src/lib/request-deduplication.js +0 -24
- package/src/lib/schema-operations.js +0 -106
- package/src/lib/sql-error-types.js +0 -14
- package/src/lib/sql-operations.js +0 -647
- package/src/lib/utils.js +0 -6
- package/src/lib/version-utils.js +0 -34
- /package/dist/.next/.next/static/{5dBGGUmK5q7of4h5Rahrg → Y9mYu4WBghepP5oT_3OdR}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{5dBGGUmK5q7of4h5Rahrg → Y9mYu4WBghepP5oT_3OdR}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{PflNFnmFsNegSqhzjI6lA → ae3gNmoSGm-R5LJC4UagI}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{PflNFnmFsNegSqhzjI6lA → ae3gNmoSGm-R5LJC4UagI}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{p8875OZM4iDNsPzmoyLe7 → bKfUJeuvAQlBmR3TjrfkH}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{p8875OZM4iDNsPzmoyLe7 → bKfUJeuvAQlBmR3TjrfkH}/_ssgManifest.js +0 -0
- /package/dist/.next/{static 2/5dBGGUmK5q7of4h5Rahrg → .next/static/ejYPqJ2kVicVp5EFWOZIC}/_buildManifest.js +0 -0
- /package/dist/.next/{static 2/5dBGGUmK5q7of4h5Rahrg → .next/static/ejYPqJ2kVicVp5EFWOZIC}/_ssgManifest.js +0 -0
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// app/api/update/route.js
|
|
2
|
-
import { NextResponse } from 'next/server';
|
|
3
|
-
import pkg from '../../../../package.json' assert { type: 'json' };
|
|
4
|
-
|
|
5
|
-
export async function GET() {
|
|
6
|
-
try {
|
|
7
|
-
// Get current version from package.json
|
|
8
|
-
const currentVersion = pkg.version;
|
|
9
|
-
|
|
10
|
-
// Fetch the latest version from npm registry
|
|
11
|
-
const response = await fetch('https://registry.npmjs.org/d1s/latest', {
|
|
12
|
-
headers: {
|
|
13
|
-
'Accept': 'application/json',
|
|
14
|
-
'User-Agent': 'd1-studio'
|
|
15
|
-
},
|
|
16
|
-
// Add cache control to prevent excessive requests
|
|
17
|
-
cache: 'no-cache'
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
if (!response.ok) {
|
|
21
|
-
throw new Error('Failed to check for updates');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const data = await response.json();
|
|
25
|
-
const latestVersion = data.version;
|
|
26
|
-
|
|
27
|
-
// Compare versions - only return update info if there's a newer version
|
|
28
|
-
if (latestVersion && currentVersion && latestVersion !== currentVersion) {
|
|
29
|
-
console.log(`Update available: ${currentVersion} → ${latestVersion}`);
|
|
30
|
-
return NextResponse.json({
|
|
31
|
-
update: {
|
|
32
|
-
latest: latestVersion,
|
|
33
|
-
current: currentVersion
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// No update available
|
|
39
|
-
return NextResponse.json({ update: null });
|
|
40
|
-
} catch (error) {
|
|
41
|
-
console.error('Error checking for updates:', error);
|
|
42
|
-
// Return null on error to prevent banner from showing
|
|
43
|
-
return NextResponse.json({ update: null });
|
|
44
|
-
}
|
|
45
|
-
}
|
package/src/app/globals.css
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
body {
|
|
6
|
-
font-family: Arial, Helvetica, sans-serif;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
@layer base {
|
|
10
|
-
:root {
|
|
11
|
-
--background: 0 0% 100%;
|
|
12
|
-
--foreground: 240 10% 3.9%;
|
|
13
|
-
--card: 0 0% 100%;
|
|
14
|
-
--card-foreground: 240 10% 3.9%;
|
|
15
|
-
--popover: 0 0% 100%;
|
|
16
|
-
--popover-foreground: 240 10% 3.9%;
|
|
17
|
-
--primary: 240 5.9% 10%;
|
|
18
|
-
--primary-foreground: 0 0% 98%;
|
|
19
|
-
--secondary: 240 4.8% 95.9%;
|
|
20
|
-
--secondary-foreground: 240 5.9% 10%;
|
|
21
|
-
--muted: 240 4.8% 95.9%;
|
|
22
|
-
--muted-foreground: 240 3.8% 46.1%;
|
|
23
|
-
--accent: 240 4.8% 95.9%;
|
|
24
|
-
--accent-foreground: 240 5.9% 10%;
|
|
25
|
-
--destructive: 0 84.2% 60.2%;
|
|
26
|
-
--destructive-foreground: 0 0% 98%;
|
|
27
|
-
--border: 240 5.9% 90%;
|
|
28
|
-
--input: 240 5.9% 90%;
|
|
29
|
-
--ring: 240 10% 3.9%;
|
|
30
|
-
--chart-1: 12 76% 61%;
|
|
31
|
-
--chart-2: 173 58% 39%;
|
|
32
|
-
--chart-3: 197 37% 24%;
|
|
33
|
-
--chart-4: 43 74% 66%;
|
|
34
|
-
--chart-5: 27 87% 67%;
|
|
35
|
-
--radius: 0.5rem;
|
|
36
|
-
--sidebar-background: 0 0% 98%;
|
|
37
|
-
--sidebar-foreground: 240 5.3% 26.1%;
|
|
38
|
-
--sidebar-primary: 240 5.9% 10%;
|
|
39
|
-
--sidebar-primary-foreground: 0 0% 98%;
|
|
40
|
-
--sidebar-accent: 240 4.8% 95.9%;
|
|
41
|
-
--sidebar-accent-foreground: 240 5.9% 10%;
|
|
42
|
-
--sidebar-border: 220 13% 91%;
|
|
43
|
-
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
44
|
-
}
|
|
45
|
-
.dark {
|
|
46
|
-
--background: 240 10% 3.9%;
|
|
47
|
-
--foreground: 0 0% 98%;
|
|
48
|
-
--card: 240 10% 3.9%;
|
|
49
|
-
--card-foreground: 0 0% 98%;
|
|
50
|
-
--popover: 240 10% 3.9%;
|
|
51
|
-
--popover-foreground: 0 0% 98%;
|
|
52
|
-
--primary: 0 0% 98%;
|
|
53
|
-
--primary-foreground: 240 5.9% 10%;
|
|
54
|
-
--secondary: 240 3.7% 15.9%;
|
|
55
|
-
--secondary-foreground: 0 0% 98%;
|
|
56
|
-
--muted: 240 3.7% 15.9%;
|
|
57
|
-
--muted-foreground: 240 5% 64.9%;
|
|
58
|
-
--accent: 240 3.7% 15.9%;
|
|
59
|
-
--accent-foreground: 0 0% 98%;
|
|
60
|
-
--destructive: 0 62.8% 30.6%;
|
|
61
|
-
--destructive-foreground: 0 0% 98%;
|
|
62
|
-
--border: 240 3.7% 15.9%;
|
|
63
|
-
--input: 240 3.7% 15.9%;
|
|
64
|
-
--ring: 240 4.9% 83.9%;
|
|
65
|
-
--chart-1: 220 70% 50%;
|
|
66
|
-
--chart-2: 160 60% 45%;
|
|
67
|
-
--chart-3: 30 80% 55%;
|
|
68
|
-
--chart-4: 280 65% 60%;
|
|
69
|
-
--chart-5: 340 75% 55%;
|
|
70
|
-
--sidebar-background: 240 5.9% 10%;
|
|
71
|
-
--sidebar-foreground: 240 4.8% 95.9%;
|
|
72
|
-
--sidebar-primary: 224.3 76.3% 48%;
|
|
73
|
-
--sidebar-primary-foreground: 0 0% 100%;
|
|
74
|
-
--sidebar-accent: 240 3.7% 15.9%;
|
|
75
|
-
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
|
76
|
-
--sidebar-border: 240 3.7% 15.9%;
|
|
77
|
-
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
@layer base {
|
|
82
|
-
* {
|
|
83
|
-
@apply border-border;
|
|
84
|
-
}
|
|
85
|
-
body {
|
|
86
|
-
@apply bg-background text-foreground;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.table-fixed {
|
|
91
|
-
table-layout: fixed;
|
|
92
|
-
width: 100%;
|
|
93
|
-
}
|
package/src/app/layout.jsx
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// app/layout.js
|
|
2
|
-
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
-
import "./globals.css";
|
|
4
|
-
import { DatabaseProvider } from '@/context/database-context';
|
|
5
|
-
import { Toaster } from '@/components/ui/toaster'; // Change this import
|
|
6
|
-
|
|
7
|
-
const geistSans = Geist({
|
|
8
|
-
variable: "--font-geist-sans",
|
|
9
|
-
subsets: ["latin"],
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const geistMono = Geist_Mono({
|
|
13
|
-
variable: "--font-geist-mono",
|
|
14
|
-
subsets: ["latin"],
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
export const metadata = {
|
|
18
|
-
title: "d1-studio",
|
|
19
|
-
description: "Native D1 database studio.",
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default function RootLayout({ children }) {
|
|
23
|
-
return (
|
|
24
|
-
<html lang="en">
|
|
25
|
-
<body
|
|
26
|
-
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
27
|
-
>
|
|
28
|
-
<DatabaseProvider>
|
|
29
|
-
{children}
|
|
30
|
-
<Toaster /> {/* Add this component */}
|
|
31
|
-
</DatabaseProvider>
|
|
32
|
-
</body>
|
|
33
|
-
</html>
|
|
34
|
-
);
|
|
35
|
-
}
|
package/src/app/page.jsx
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// app/page.js
|
|
2
|
-
'use client'
|
|
3
|
-
|
|
4
|
-
import { useState } from 'react';
|
|
5
|
-
import { AppSidebar } from '../components/sidebar';
|
|
6
|
-
import { SQLEditor } from '../components/sql-editor';
|
|
7
|
-
import { TableView } from '../components/table-view';
|
|
8
|
-
import UpdateBanner from '@/components/update-banner';
|
|
9
|
-
|
|
10
|
-
export default function StudioPage() {
|
|
11
|
-
const [currentView, setCurrentView] = useState('sql-editor');
|
|
12
|
-
const [selectedTable, setSelectedTable] = useState(null);
|
|
13
|
-
|
|
14
|
-
const handleTableSelect = (tableName) => {
|
|
15
|
-
setSelectedTable(tableName);
|
|
16
|
-
setCurrentView('table-view');
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<div className="flex flex-col min-h-screen bg-background">
|
|
21
|
-
{/* Banner */}
|
|
22
|
-
<UpdateBanner />
|
|
23
|
-
|
|
24
|
-
{/* Main layout with adjusted positioning for banner */}
|
|
25
|
-
<div className="flex flex-1 mt-[var(--banner-height,0px)]">
|
|
26
|
-
{/* Sidebar with adjusted height */}
|
|
27
|
-
<AppSidebar
|
|
28
|
-
className="w-64 border-r fixed top-[var(--banner-height,0px)] h-[calc(100vh-var(--banner-height,0px))]"
|
|
29
|
-
currentView={currentView}
|
|
30
|
-
onNavigate={setCurrentView}
|
|
31
|
-
onTableSelect={handleTableSelect}
|
|
32
|
-
/>
|
|
33
|
-
|
|
34
|
-
{/* Main content with adjusted margin-top and height */}
|
|
35
|
-
<main className="ml-64 flex-1 h-[calc(100vh-var(--banner-height,0px))]">
|
|
36
|
-
{currentView === 'sql-editor' && <SQLEditor />}
|
|
37
|
-
{currentView === 'table-view' && selectedTable && (
|
|
38
|
-
<TableView tableName={selectedTable} />
|
|
39
|
-
)}
|
|
40
|
-
</main>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
);
|
|
44
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
// components/cloudflare-credentials-modal.jsx
|
|
2
|
-
'use client';
|
|
3
|
-
|
|
4
|
-
import React, { useState } from 'react';
|
|
5
|
-
import {
|
|
6
|
-
Dialog,
|
|
7
|
-
DialogContent,
|
|
8
|
-
DialogDescription,
|
|
9
|
-
DialogHeader,
|
|
10
|
-
DialogTitle,
|
|
11
|
-
} from "@/components/ui/dialog";
|
|
12
|
-
import { Input } from "@/components/ui/input";
|
|
13
|
-
import { Button } from "@/components/ui/button";
|
|
14
|
-
import { Loader2 } from 'lucide-react';
|
|
15
|
-
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
16
|
-
|
|
17
|
-
export function CloudflareCredentialsModal({ open, onClose, onSubmit }) {
|
|
18
|
-
const [accountId, setAccountId] = useState('');
|
|
19
|
-
const [apiToken, setApiToken] = useState('');
|
|
20
|
-
const [error, setError] = useState('');
|
|
21
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
22
|
-
|
|
23
|
-
const handleSubmit = async (e) => {
|
|
24
|
-
e.preventDefault();
|
|
25
|
-
setError('');
|
|
26
|
-
setIsLoading(true);
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
await onSubmit({ accountId, apiToken });
|
|
30
|
-
// Store credentials in localStorage
|
|
31
|
-
localStorage.setItem('cf_credentials', JSON.stringify({
|
|
32
|
-
accountId,
|
|
33
|
-
apiToken
|
|
34
|
-
}));
|
|
35
|
-
onClose();
|
|
36
|
-
} catch (err) {
|
|
37
|
-
setError(err.message);
|
|
38
|
-
} finally {
|
|
39
|
-
setIsLoading(false);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<Dialog open={open} onOpenChange={onClose}>
|
|
45
|
-
<DialogContent className="sm:max-w-md">
|
|
46
|
-
<DialogHeader>
|
|
47
|
-
<DialogTitle>Connect to Cloudflare</DialogTitle>
|
|
48
|
-
<DialogDescription>
|
|
49
|
-
Enter your Cloudflare credentials to push your database to production.
|
|
50
|
-
</DialogDescription>
|
|
51
|
-
</DialogHeader>
|
|
52
|
-
|
|
53
|
-
<form onSubmit={handleSubmit} className="space-y-4 mt-4">
|
|
54
|
-
{error && (
|
|
55
|
-
<Alert variant="destructive">
|
|
56
|
-
<AlertDescription>{error}</AlertDescription>
|
|
57
|
-
</Alert>
|
|
58
|
-
)}
|
|
59
|
-
|
|
60
|
-
<div className="space-y-2">
|
|
61
|
-
<label className="text-sm font-medium">Account ID</label>
|
|
62
|
-
<Input
|
|
63
|
-
placeholder="Your Cloudflare Account ID"
|
|
64
|
-
value={accountId}
|
|
65
|
-
onChange={(e) => setAccountId(e.target.value)}
|
|
66
|
-
required
|
|
67
|
-
/>
|
|
68
|
-
</div>
|
|
69
|
-
|
|
70
|
-
<div className="space-y-2">
|
|
71
|
-
<label className="text-sm font-medium">API Token</label>
|
|
72
|
-
<Input
|
|
73
|
-
type="password"
|
|
74
|
-
placeholder="Your D1 Database API Token"
|
|
75
|
-
value={apiToken}
|
|
76
|
-
onChange={(e) => setApiToken(e.target.value)}
|
|
77
|
-
required
|
|
78
|
-
/>
|
|
79
|
-
</div>
|
|
80
|
-
|
|
81
|
-
<div className="flex justify-end gap-3">
|
|
82
|
-
<Button type="button" variant="outline" onClick={onClose}>
|
|
83
|
-
Cancel
|
|
84
|
-
</Button>
|
|
85
|
-
<Button type="submit" disabled={isLoading}>
|
|
86
|
-
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
|
87
|
-
Connect
|
|
88
|
-
</Button>
|
|
89
|
-
</div>
|
|
90
|
-
</form>
|
|
91
|
-
</DialogContent>
|
|
92
|
-
</Dialog>
|
|
93
|
-
);
|
|
94
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
// components/column-selector.jsx
|
|
2
|
-
import React, { useState, useEffect } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
DropdownMenu,
|
|
5
|
-
DropdownMenuContent,
|
|
6
|
-
DropdownMenuTrigger
|
|
7
|
-
} from "@/components/ui/dropdown-menu";
|
|
8
|
-
import { Button } from "@/components/ui/button";
|
|
9
|
-
import { Checkbox } from "@/components/ui/checkbox";
|
|
10
|
-
import { Input } from "@/components/ui/input";
|
|
11
|
-
import { Columns } from 'lucide-react';
|
|
12
|
-
|
|
13
|
-
export function ColumnSelector({ schema = [], visibleColumns = [], onColumnToggle }) {
|
|
14
|
-
const [searchTerm, setSearchTerm] = useState('');
|
|
15
|
-
|
|
16
|
-
// Initialize visible columns with all columns from schema
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
if (!schema || schema.length === 0) return;
|
|
19
|
-
|
|
20
|
-
// Get all column names from schema
|
|
21
|
-
const allColumns = schema.map(col => col.name);
|
|
22
|
-
|
|
23
|
-
// If visibleColumns is empty, make all columns visible
|
|
24
|
-
if (visibleColumns.length === 0) {
|
|
25
|
-
allColumns.forEach(col => onColumnToggle(col));
|
|
26
|
-
}
|
|
27
|
-
}, [schema, visibleColumns.length, onColumnToggle]);
|
|
28
|
-
|
|
29
|
-
// Filter columns based on search term
|
|
30
|
-
const filteredColumns = schema.filter(col =>
|
|
31
|
-
col.name.toLowerCase().includes(searchTerm.toLowerCase())
|
|
32
|
-
);
|
|
33
|
-
const filteredColumnNames = filteredColumns.map(col => col.name);
|
|
34
|
-
|
|
35
|
-
// Determine if all filtered columns are selected
|
|
36
|
-
const allFilteredSelected =
|
|
37
|
-
filteredColumnNames.length > 0 &&
|
|
38
|
-
filteredColumnNames.every(name => visibleColumns.includes(name));
|
|
39
|
-
|
|
40
|
-
// Handle individual checkbox change
|
|
41
|
-
const handleCheckboxChange = (columnName) => {
|
|
42
|
-
onColumnToggle(columnName);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// Handle the "Select All" checkbox change for the filtered list
|
|
46
|
-
const handleSelectAllChange = (checked) => {
|
|
47
|
-
if (checked) {
|
|
48
|
-
// For every filtered column that is not visible, toggle it on
|
|
49
|
-
filteredColumns.forEach(col => {
|
|
50
|
-
if (!visibleColumns.includes(col.name)) {
|
|
51
|
-
onColumnToggle(col.name);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
} else {
|
|
55
|
-
// For every filtered column that is visible, toggle it off
|
|
56
|
-
filteredColumns.forEach(col => {
|
|
57
|
-
if (visibleColumns.includes(col.name)) {
|
|
58
|
-
onColumnToggle(col.name);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
return (
|
|
65
|
-
<DropdownMenu>
|
|
66
|
-
<DropdownMenuTrigger asChild>
|
|
67
|
-
<Button
|
|
68
|
-
size="sm"
|
|
69
|
-
variant="outline"
|
|
70
|
-
className="font-semibold"
|
|
71
|
-
>
|
|
72
|
-
<Columns className="h-4 w-4" />
|
|
73
|
-
Columns ({visibleColumns.length})
|
|
74
|
-
</Button>
|
|
75
|
-
</DropdownMenuTrigger>
|
|
76
|
-
<DropdownMenuContent align="end" className="w-64 font-sans">
|
|
77
|
-
<div className="p-2">
|
|
78
|
-
<Input
|
|
79
|
-
placeholder="Search columns..."
|
|
80
|
-
value={searchTerm}
|
|
81
|
-
onChange={(e) => setSearchTerm(e.target.value)}
|
|
82
|
-
className="h-8"
|
|
83
|
-
/>
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
{/* Select All Option */}
|
|
87
|
-
<div className="flex items-center space-x-2 px-2 py-1.5 hover:bg-accent rounded-md">
|
|
88
|
-
<Checkbox
|
|
89
|
-
id="select-all-columns"
|
|
90
|
-
checked={allFilteredSelected}
|
|
91
|
-
onCheckedChange={handleSelectAllChange}
|
|
92
|
-
className="shrink-0"
|
|
93
|
-
/>
|
|
94
|
-
<label
|
|
95
|
-
htmlFor="select-all-columns"
|
|
96
|
-
className="flex-1 cursor-pointer text-sm font-medium"
|
|
97
|
-
>
|
|
98
|
-
Select All {searchTerm && '(Filtered)'}
|
|
99
|
-
</label>
|
|
100
|
-
</div>
|
|
101
|
-
|
|
102
|
-
<div className="max-h-[300px] overflow-y-auto">
|
|
103
|
-
{filteredColumns.map((column) => (
|
|
104
|
-
<div
|
|
105
|
-
key={column.name}
|
|
106
|
-
className="flex items-start space-x-2 px-2 py-1.5 hover:bg-accent rounded-md"
|
|
107
|
-
>
|
|
108
|
-
<Checkbox
|
|
109
|
-
id={`column-${column.name}`}
|
|
110
|
-
checked={visibleColumns.includes(column.name)}
|
|
111
|
-
onCheckedChange={() => handleCheckboxChange(column.name)}
|
|
112
|
-
className="mt-1"
|
|
113
|
-
/>
|
|
114
|
-
<label
|
|
115
|
-
htmlFor={`column-${column.name}`}
|
|
116
|
-
className="flex-1 cursor-pointer"
|
|
117
|
-
>
|
|
118
|
-
<div className="text-sm font-medium">
|
|
119
|
-
{column.name}
|
|
120
|
-
</div>
|
|
121
|
-
<div className="text-xs text-muted-foreground">
|
|
122
|
-
{column.type.toLowerCase()}
|
|
123
|
-
</div>
|
|
124
|
-
</label>
|
|
125
|
-
</div>
|
|
126
|
-
))}
|
|
127
|
-
</div>
|
|
128
|
-
</DropdownMenuContent>
|
|
129
|
-
</DropdownMenu>
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export default ColumnSelector;
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// components/column-sorting.jsx
|
|
2
|
-
'use client';
|
|
3
|
-
|
|
4
|
-
import { ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react';
|
|
5
|
-
import { Button } from "@/components/ui/button";
|
|
6
|
-
|
|
7
|
-
export function SortableHeader({
|
|
8
|
-
column,
|
|
9
|
-
sortConfig,
|
|
10
|
-
onSort,
|
|
11
|
-
children
|
|
12
|
-
}) {
|
|
13
|
-
const direction = sortConfig[column];
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<div className="flex items-center w-full">
|
|
17
|
-
<Button
|
|
18
|
-
variant="ghost"
|
|
19
|
-
size="sm"
|
|
20
|
-
className="h-8 hover:bg-neutral-100 w-full justify-between"
|
|
21
|
-
onClick={() => {
|
|
22
|
-
const nextDirection = !direction
|
|
23
|
-
? 'asc'
|
|
24
|
-
: direction === 'asc'
|
|
25
|
-
? 'desc'
|
|
26
|
-
: null;
|
|
27
|
-
onSort(column, nextDirection);
|
|
28
|
-
}}
|
|
29
|
-
>
|
|
30
|
-
<span className="flex items-center gap-1 font-mono">
|
|
31
|
-
{children}
|
|
32
|
-
</span>
|
|
33
|
-
<span className="shrink-0">
|
|
34
|
-
{direction === 'asc' && <ArrowUp className="h-4 w-4" />}
|
|
35
|
-
{direction === 'desc' && <ArrowDown className="h-4 w-4" />}
|
|
36
|
-
{!direction && <ArrowUpDown className="h-4 w-4" />}
|
|
37
|
-
</span>
|
|
38
|
-
</Button>
|
|
39
|
-
</div>
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function sortData(data, column, direction) {
|
|
44
|
-
if (!direction || !data.length) return data;
|
|
45
|
-
|
|
46
|
-
return [...data].sort((a, b) => {
|
|
47
|
-
const aVal = a[column];
|
|
48
|
-
const bVal = b[column];
|
|
49
|
-
|
|
50
|
-
// Handle null values
|
|
51
|
-
if (aVal == null && bVal == null) return 0;
|
|
52
|
-
if (aVal == null) return 1;
|
|
53
|
-
if (bVal == null) return -1;
|
|
54
|
-
|
|
55
|
-
// Compare based on type
|
|
56
|
-
if (typeof aVal === 'number' && typeof bVal === 'number') {
|
|
57
|
-
return direction === 'asc' ? aVal - bVal : bVal - aVal;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// String comparison for everything else
|
|
61
|
-
const aStr = String(aVal).toLowerCase();
|
|
62
|
-
const bStr = String(bVal).toLowerCase();
|
|
63
|
-
return direction === 'asc' ? aStr.localeCompare(bStr) : bStr.localeCompare(aStr);
|
|
64
|
-
});
|
|
65
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// components/delete-records-dialog.jsx
|
|
2
|
-
'use client';
|
|
3
|
-
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import { AlertCircle } from 'lucide-react';
|
|
6
|
-
import {
|
|
7
|
-
Dialog,
|
|
8
|
-
DialogContent,
|
|
9
|
-
DialogDescription,
|
|
10
|
-
DialogHeader,
|
|
11
|
-
DialogTitle,
|
|
12
|
-
DialogFooter,
|
|
13
|
-
} from "@/components/ui/dialog";
|
|
14
|
-
import { Button } from "@/components/ui/button";
|
|
15
|
-
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
16
|
-
|
|
17
|
-
export function DeleteRecordsDialog({
|
|
18
|
-
isOpen,
|
|
19
|
-
onClose,
|
|
20
|
-
onConfirm,
|
|
21
|
-
selectedCount,
|
|
22
|
-
tableName,
|
|
23
|
-
isDeleting,
|
|
24
|
-
error
|
|
25
|
-
}) {
|
|
26
|
-
return (
|
|
27
|
-
<Dialog open={isOpen} onOpenChange={onClose}>
|
|
28
|
-
<DialogContent className="sm:max-w-md font-sans">
|
|
29
|
-
<DialogHeader>
|
|
30
|
-
<DialogTitle className="mb-2">Delete {selectedCount} {selectedCount === 1 ? 'Record' : 'Records'}?</DialogTitle>
|
|
31
|
-
<DialogDescription className="text-neutral-600 font-medium">
|
|
32
|
-
You're about to delete {selectedCount} {selectedCount === 1 ? 'record' : 'records'} from <span className="font-sans font-bold text-neutral-900">{tableName}</span>.
|
|
33
|
-
</DialogDescription>
|
|
34
|
-
</DialogHeader>
|
|
35
|
-
|
|
36
|
-
{error && (
|
|
37
|
-
<Alert variant="destructive">
|
|
38
|
-
<AlertCircle className="h-4 w-4" />
|
|
39
|
-
<AlertDescription>{error}</AlertDescription>
|
|
40
|
-
</Alert>
|
|
41
|
-
)}
|
|
42
|
-
|
|
43
|
-
<DialogFooter className="flex gap-1 mt-2 sm:justify-end font-sans">
|
|
44
|
-
<Button
|
|
45
|
-
variant="outline"
|
|
46
|
-
onClick={onClose}
|
|
47
|
-
disabled={isDeleting}
|
|
48
|
-
>
|
|
49
|
-
Cancel
|
|
50
|
-
</Button>
|
|
51
|
-
<Button
|
|
52
|
-
variant="destructive"
|
|
53
|
-
onClick={onConfirm}
|
|
54
|
-
disabled={isDeleting}
|
|
55
|
-
>
|
|
56
|
-
{isDeleting ? 'Deleting...' : 'Delete'}
|
|
57
|
-
</Button>
|
|
58
|
-
</DialogFooter>
|
|
59
|
-
</DialogContent>
|
|
60
|
-
</Dialog>
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export default DeleteRecordsDialog;
|