Compare commits

...

651 Commits

Author SHA1 Message Date
Szilárd Dóró
b649f178e0 Merge pull request #1454 from nhost/changeset-release/main
chore: update versions
2023-01-04 14:43:52 +01:00
github-actions[bot]
1f5e1e3d42 chore: update versions 2023-01-03 18:20:01 +00:00
Nuno Pato
5727b0b0fe Merge pull request #1426 from nhost/feat/add-functions-to-logs-dashboard
feat(dashboard): add functions to logs
2023-01-03 17:18:24 -01:00
Pilou
2f38ed56f5 Merge pull request #1459 from nhost/fix/reuse-file-upload
fix: 🐛 allow useFileUpload to be reused
2023-01-03 13:41:20 +01:00
Guido Curcio
16502ea175 Merge pull request #1382 from nhost/feat/auth-management 2023-01-03 06:16:57 -05:00
Guido Curcio
beee0407df Merge branch 'main' into feat/auth-management 2023-01-03 05:13:46 -05:00
Guido Curcio
3990b1ffbb Update dashboard/src/components/users/CreateUserForm/CreateUserForm.tsx
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2023-01-03 06:12:22 -03:00
Guido Curcio
1fb03708e3 Update dashboard/src/components/users/EditUserPasswordForm/EditUserPasswordForm.tsx
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2023-01-03 06:12:15 -03:00
Szilárd Dóró
d42719ee65 Merge pull request #1453 from nhost/feat/custom-jwt-secret
feat(dashboard): add JWT secret editor modal
2023-01-03 09:30:09 +01:00
Guido Curcio
72ff489ea8 fix inconsistent padding in modals. 2023-01-03 03:43:11 -03:00
Pilou
c9bf2dde0e Merge pull request #1458 from nhost/refactor/do-not-over-export
Only export what is required by the user or `@nhost/nextjs`
2023-01-02 22:04:52 +01:00
Pierre-Louis Mercereau
613533d377 chore: do not cache documentation build 2023-01-02 21:22:54 +01:00
Pierre-Louis Mercereau
8568354718 fix: 🐛 allow useFileUpload to be reused 2023-01-02 21:03:58 +01:00
Pierre-Louis Mercereau
1be6d32455 Only export what is required by the user or @nhost/nextjs 2023-01-02 16:19:00 +01:00
Pilou
812a6e5005 Merge pull request #1452 from nhost/fix/improve-missing-react-provider-error
fix: improve missing React provider error
2023-01-02 15:54:48 +01:00
Szilárd Dóró
34cc230b61 fix(dashboard): improve responsive layout 2023-01-02 15:29:02 +01:00
Szilárd Dóró
898a7c835f chore(dashboard): improve JWT secret validation 2023-01-02 14:41:28 +01:00
Szilárd Dóró
7766624bc5 feat(dashboard): add JWT secret editor modal 2023-01-02 14:34:36 +01:00
Pierre-Louis Mercereau
2e8f73df38 chore: changeset 2023-01-02 14:25:29 +01:00
Pierre-Louis Mercereau
6a419e060e fix: improve missing React provider error 2023-01-02 14:23:49 +01:00
Guido Curcio
43480ca735 spacing on action buttons 2023-01-02 09:07:21 -03:00
Guido Curcio
efc42d77fd fix loading state on EditUserForm (drawer) 2023-01-02 08:42:45 -03:00
Guido Curcio
31e2523eca spacing on create user modal 2023-01-02 08:19:54 -03:00
Guido Curcio
fbf4f40ab7 Merge branch 'feat/auth-management' of https://github.com/nhost/nhost into feat/auth-management 2023-01-02 08:15:31 -03:00
Guido Curcio
cbe203e720 fix alt props and spacing on users table 2023-01-02 08:14:49 -03:00
Szilárd Dóró
378a6684b0 Merge pull request #1451 from nhost/changeset-release/main
chore: update versions
2023-01-02 11:33:20 +01:00
github-actions[bot]
1999ae09e6 chore: update versions 2023-01-02 09:47:28 +00:00
Szilárd Dóró
0fe48a0833 Merge pull request #1425 from nhost/fix/refresh-after-provisioning
fix(dashboard): provisioning status polling
2023-01-02 10:46:12 +01:00
Szilárd Dóró
7bbf6dbf1c Merge pull request #1387 from nhost/changeset-release/main
chore: update versions
2023-01-02 10:43:56 +01:00
Szilárd Dóró
689dc873b3 Update integrations/react-apollo/CHANGELOG.md
Co-authored-by: Pilou <24897252+plmercereau@users.noreply.github.com>
2023-01-02 10:07:28 +01:00
Szilárd Dóró
a0747d02e0 Update integrations/react-urql/CHANGELOG.md
Co-authored-by: Pilou <24897252+plmercereau@users.noreply.github.com>
2023-01-02 10:07:23 +01:00
Szilárd Dóró
be5bd1e446 Update integrations/apollo/CHANGELOG.md
Co-authored-by: Pilou <24897252+plmercereau@users.noreply.github.com>
2023-01-02 10:07:18 +01:00
Szilárd Dóró
52ccfdec89 Merge branch 'main' into fix/refresh-after-provisioning 2023-01-02 10:05:46 +01:00
Szilárd Dóró
2c60591580 fix(deps): revert major bumps 2023-01-02 10:02:12 +01:00
github-actions[bot]
6140bc5b3b chore: update versions 2022-12-27 13:49:10 +00:00
Pilou
9f7780ec91 Merge pull request #1438 from nhost/ci/renovate
ci: improve renovate configuration
2022-12-27 14:47:35 +01:00
Pilou
abc7d0c7a5 Merge pull request #1442 from nhost/chore/docgen-vite
chore: build docgen with vite
2022-12-27 09:44:03 +01:00
Pilou
074a36ea48 Merge pull request #1432 from nhost/fix/remove-accept-encoding-header
Fix/allow override of the accept-encoding header
2022-12-27 09:43:39 +01:00
Pierre-Louis Mercereau
64e806dc27 chore: build docgen with vite 2022-12-26 21:16:02 +01:00
Pilou
bd0e9748b6 Merge pull request #1440 from nhost/renovate-changesets
chore: create changesest from Renovate bumps
2022-12-26 21:04:45 +01:00
plmercereau
b21222b378 chore(deps): update dependency @types/node to v16 2022-12-26 20:01:13 +00:00
Pilou
7e217db128 Merge pull request #1294 from nhost/renovate/node-18.x
chore(deps): update dependency @types/node to v16
2022-12-26 20:59:25 +01:00
Pierre-Louis Mercereau
56c716d9fa Merge branch 'main' into renovate/node-18.x 2022-12-26 20:23:00 +01:00
Pilou
14ecbd1fb9 Merge pull request #1439 from nhost/renovate-changesets
chore: create changesest from Renovate bumps
2022-12-26 20:19:58 +01:00
plmercereau
a0242c4d6f chore(deps): update dependency tsup to v6 2022-12-26 19:13:36 +00:00
Pilou
4800b4a756 Merge pull request #1306 from nhost/renovate/tsup-6.x
chore(deps): update dependency tsup to v6
2022-12-26 20:12:14 +01:00
Pierre-Louis Mercereau
5b318d17d4 Merge branch 'main' into renovate/node-18.x 2022-12-26 20:08:46 +01:00
Pierre-Louis Mercereau
2f9be4f760 fix: @types/node v16 2022-12-26 20:06:00 +01:00
Pierre-Louis Mercereau
64777b6f30 ci: improve renovate configuration 2022-12-26 19:59:48 +01:00
Pilou
7e1489353e Merge pull request #1437 from nhost/ci/renovate-changeset-pr
ci: create renovate changeset pr
2022-12-26 19:44:20 +01:00
Pierre-Louis Mercereau
c53306a497 ci: correct PAT secret 2022-12-26 19:43:55 +01:00
Pierre-Louis Mercereau
83345579d0 ci: create renovate changeset pr 2022-12-26 19:41:08 +01:00
Pilou
2b4b9e0385 Merge pull request #1304 from nhost/renovate/graphql-16.x
chore(deps): update dependency graphql to v16
2022-12-26 19:08:25 +01:00
renovate[bot]
922349f550 chore(deps): update dependency graphql to v16 2022-12-26 17:47:32 +00:00
Pilou
d613f3fd04 Merge pull request #1434 from nhost/renovate/jsonwebtoken-9.x
ci: correct gh action
2022-12-26 18:41:24 +01:00
Pierre-Louis Mercereau
4d8a47777e ci: correct gh action 2022-12-26 18:40:44 +01:00
Pilou
229a7ab1f7 Merge pull request #1417 from nhost/renovate/jsonwebtoken-9.x
fix(deps): update dependency jsonwebtoken to v9
2022-12-26 18:38:09 +01:00
Pierre-Louis Mercereau
3dabb7b53a ci: adapt renovate action 2022-12-26 18:37:49 +01:00
renovate[bot]
abc3d6ce60 chore(deps): update dependency tsup to v6 2022-12-26 17:33:02 +00:00
Pilou
08d49bd1fd Merge pull request #1408 from nhost/renovate/vitest-monorepo
chore(deps): update dependency vitest to ^0.26.0
2022-12-26 18:24:07 +01:00
Pierre-Louis Mercereau
03435a2c66 chore: bump vitest to latest version 2022-12-26 14:55:39 +01:00
Pierre-Louis Mercereau
66208d6840 chore: allow custom values for Accept-Encoding 2022-12-26 13:15:04 +01:00
Pierre-Louis Mercereau
5be9abb0fa chore: changeset 2022-12-26 12:59:23 +01:00
Pierre-Louis Mercereau
8e504b5328 Merge branch 'main' into fix/remove-accept-encoding-header 2022-12-26 12:55:58 +01:00
renovate[bot]
0e3eb7204a fix(deps): update dependency jsonwebtoken to v9 2022-12-23 23:51:28 +00:00
Guido Curcio
70cfeb1fcf Update dashboard/src/components/users/UsersBody/UsersBody.tsx
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2022-12-23 12:38:12 -03:00
Guido Curcio
3116562b58 fix service urls; pagination props 2022-12-23 11:31:43 -03:00
Guido Curcio
693e40d385 Merge branch 'main' into feat/auth-management 2022-12-23 11:28:53 -03:00
Nuno Pato
9a1aa7bb2e changeset 2022-12-22 20:08:28 -01:00
Nuno Pato
98345f2e78 dashboard: add functions to the logs dashboard 2022-12-22 20:05:39 -01:00
Guido Curcio
f29abe6238 add changeset 2022-12-22 16:51:19 -03:00
Szilárd Dóró
8956d47bce fix(dashboard): start polling manually
reference issue: https://github.com/apollographql/apollo-client/issues/9819
2022-12-22 18:22:00 +01:00
Szilárd Dóró
dd0738d5f7 chore(dashboard): add changeset 2022-12-22 17:57:36 +01:00
Szilárd Dóró
11d77d6011 fix(dashboard): provisioning status polling 2022-12-22 17:53:07 +01:00
renovate[bot]
a78cd2f18f chore(deps): update dependency vitest to ^0.26.0 2022-12-22 16:01:51 +00:00
Pilou
6ef340daad Merge pull request #1424 from nhost/ci/retry-cli-install
ci: retry the Nhost CLI installation
2022-12-22 16:31:46 +01:00
Pierre-Louis Mercereau
a96e3c9163 ci: retry the Nhost CLI installation 2022-12-22 16:21:36 +01:00
Guido Curcio
229c47cf16 set up redirect from /users/<userId> -> users?userId=<userId> 2022-12-22 10:04:56 -03:00
Guido Curcio
e5e705350d fix: style inconsistencies in users page 2022-12-22 09:56:37 -03:00
Guido Curcio
4f81b0695d add responsive breakpoints to users's table, user's drawer 2022-12-22 09:51:47 -03:00
Szilárd Dóró
9c5b6532d3 Merge pull request #1422 from nhost/fix/persistent-drawer
fix(dashboard): close modals when navigating
2022-12-22 11:02:40 +01:00
Szilárd Dóró
889df8ca4d fix(dashboard): don't break unit tests 2022-12-22 10:54:02 +01:00
Pilou
b998e09e10 Merge pull request #1421 from nhost/chore/integrations-labeler
ci: label integrations
2022-12-22 10:48:33 +01:00
Szilárd Dóró
9e0486a362 chore(dashboard): add changeset 2022-12-22 10:01:12 +01:00
Szilárd Dóró
74037cec68 fix(dashboard): close modals when navigating 2022-12-22 10:00:21 +01:00
Guido Curcio
800db1b300 remove page query param from url if currentPage is equal to 1. 2022-12-22 03:02:53 -03:00
Guido Curcio
a40baa8c63 show up to 3 providers in users table, render a chip with remainder length 2022-12-22 02:23:17 -03:00
Guido Curcio
5cc06609c2 fix(EditUserForm): copy button. 2022-12-22 01:51:17 -03:00
Pierre-Louis Mercereau
819e68b501 ci: label integrations 2022-12-21 19:36:05 +01:00
Guido Curcio
efa68aab83 fix(roles): only show alert when editing role. 2022-12-21 14:15:48 -03:00
Guido Curcio
3a696d366a clicking on auth button of sidebar goes to page 1 2022-12-21 13:55:15 -03:00
Guido Curcio
e3e21b6164 upper bound on number of pages 2022-12-21 13:44:50 -03:00
Guido Curcio
9259663c76 missing key prop on providers 2022-12-21 13:43:28 -03:00
Guido Curcio
26dd7faf05 retrigger effect when nr of pages changes 2022-12-21 13:31:30 -03:00
Pilou
10cc213933 Merge pull request #1418 from nhost/renovate/mermaid-9.x
fix(deps): update dependency mermaid to v9
2022-12-21 16:50:53 +01:00
Guido Curcio
1b5cb93761 include alert when editing roles 2022-12-21 12:18:51 -03:00
Pilou
4157c012fd Merge pull request #1406 from nhost/chore/deprecate-axios
chore: deprecate axios
2022-12-21 16:02:26 +01:00
Pilou
9515096349 Update .changeset/kind-cycles-explain.md
Co-authored-by: Nuno Pato <nunopato@gmail.com>
2022-12-21 15:38:33 +01:00
Pilou
4dd5617855 Update .changeset/kind-cycles-explain.md
Co-authored-by: Nuno Pato <nunopato@gmail.com>
2022-12-21 15:37:29 +01:00
renovate[bot]
01dc358842 fix(deps): update dependency mermaid to v9 2022-12-21 13:22:15 +00:00
Pilou
925a1808e6 Merge pull request #1413 from nhost/renovate/vite-4.x
chore(deps): update dependency vite to v4
2022-12-21 14:10:23 +01:00
Pilou
ac80f88727 Merge pull request #1410 from nhost/chore/remove-query-string
chore: remove unused query-string dependency
2022-12-21 13:12:23 +01:00
Pilou
3078247629 Merge pull request #1412 from nhost/test/docker-compose
test(docker-compose): more retries
2022-12-21 13:12:05 +01:00
Pierre-Louis Mercereau
144c0084d2 chore: add Nhost prefix to client types 2022-12-21 12:27:19 +01:00
Pierre-Louis Mercereau
bbdfb77a07 refactor: types 2022-12-21 12:22:27 +01:00
Guido Curcio
b6df9e2e8c fix: correct onPageChange prop comments. 2022-12-21 08:21:39 -03:00
Guido Curcio
48f15eb849 remove unhelpful comments 2022-12-21 08:16:19 -03:00
Guido Curcio
141642d40d show only two providers in users table 2022-12-21 08:07:23 -03:00
Guido Curcio
def4a3a2ea fix: password change error handling, refetch, and closing dialog; createdAt in users body; use internal ban state for unbanning user; implement error handling for odd pages from URL & side-effect for user id queries; add comments to side-effects. 2022-12-21 08:02:50 -03:00
Pilou
b5a9c1be47 Update packages/nhost-js/src/clients/functions.ts
Co-authored-by: Nuno Pato <nunopato@gmail.com>
2022-12-20 18:45:36 +01:00
Pierre-Louis Mercereau
5b5e7d9640 chore: update vite-related libraries 2022-12-20 15:38:28 +01:00
Guido Curcio
b876a4ada1 handle pagination between pages (parse & mutate url) 2022-12-20 11:02:35 -03:00
Pierre-Louis Mercereau
c02e0c63f2 refactor: simplify 2022-12-20 14:48:47 +01:00
Guido Curcio
7e064355ba show banned users on users table 2022-12-20 10:47:27 -03:00
renovate[bot]
788482fab2 chore(deps): update dependency vite to v4 2022-12-20 13:40:30 +00:00
Pilou
16d94821b8 Merge pull request #1411 from nhost/renovate/tj-actions-changed-files-35.x
chore(deps): update tj-actions/changed-files action to v35
2022-12-20 14:30:16 +01:00
Guido Curcio
0f6ece6b8c remove pagination when there are no users from filter. 2022-12-20 10:28:46 -03:00
Pierre-Louis Mercereau
5c4ab54c90 test(docker-compose): more retries 2022-12-20 14:28:05 +01:00
Guido Curcio
793e7392da error handling for creating users 2022-12-20 10:24:53 -03:00
renovate[bot]
5941568bbb chore(deps): update tj-actions/changed-files action to v35 2022-12-20 13:15:40 +00:00
Pierre-Louis Mercereau
1a9e1fde1d chore: remove unused query-string dependency 2022-12-20 14:12:29 +01:00
Guido Curcio
a9bbd1303e close drawer after deleting user; track disabled state of an user. 2022-12-20 09:30:41 -03:00
Guido Curcio
b0ed2b6f14 button instead of IconButton for password change 2022-12-20 09:03:33 -03:00
Guido Curcio
3e951eab4f fix: don't hide the OAuth methods section; remove the active chip. 2022-12-20 08:42:13 -03:00
Guido Curcio
cd7a198715 fix: fix showing minutes instead of month; correct format. 2022-12-20 08:36:36 -03:00
Guido Curcio
7c4d05a25e fix: loading states, remove sign-in methods, fix default role, move handlers to specific component. 2022-12-20 07:15:43 -03:00
Pierre-Louis Mercereau
32c0632526 docs: correct changeset 2022-12-20 10:28:09 +01:00
Pierre-Louis Mercereau
19cca7f45d chore: changeset 2022-12-20 10:22:00 +01:00
Pierre-Louis Mercereau
191580a819 Merge branch 'main' into chore/deprecate-axios 2022-12-20 10:12:29 +01:00
Pilou
4a57861354 Merge pull request #1396 from nhost/integrations-iaubsd98hasd
Integrations and README updates
2022-12-20 10:11:48 +01:00
Pierre-Louis Mercereau
d96b817476 refactor: simplify 2022-12-20 10:04:19 +01:00
renovate[bot]
db6db8d860 chore(deps): update dependency @types/node to v18 2022-12-20 08:35:37 +00:00
Pierre-Louis Mercereau
fe405ba123 fix: docgen and tsconfig 2022-12-20 09:33:53 +01:00
Pilou
972a5f652f Merge pull request #1281 from nhost/renovate/typescript-4.x
chore(deps): update dependency typescript to v4.9.4
2022-12-20 09:32:34 +01:00
Pierre-Louis Mercereau
7a2c140524 Merge branch 'main' into chore/deprecate-axios 2022-12-20 09:26:41 +01:00
Pierre-Louis Mercereau
3d717d68a9 Merge branch 'main' into integrations-iaubsd98hasd 2022-12-20 09:22:29 +01:00
Pierre-Louis Mercereau
13b6a47bef fix: ignore duplicate type 2022-12-20 09:13:50 +01:00
Pierre-Louis Mercereau
2a6caa47bd chore: deprecate axios 2022-12-20 09:00:59 +01:00
Szilárd Dóró
dbbfaef451 Merge pull request #1373 from nhost/feat/rule-group-editor
feat(dashboard): Rule Group Editor
2022-12-19 11:52:16 +01:00
Szilárd Dóró
b4c07f1723 Merge branch 'main' into feat/rule-group-editor 2022-12-19 11:51:18 +01:00
Szilárd Dóró
e983eb53d9 chore(dashboard): remove "is" prefix 2022-12-19 11:09:18 +01:00
Szilárd Dóró
49867fdcf7 fix(dashboard): add missing inputValue for freeSolo input 2022-12-19 11:07:50 +01:00
Szilárd Dóró
cc428d73ee fix(dashboard): async initialization 2022-12-19 11:02:16 +01:00
Pilou
940a1db0fc Merge branch 'main' into integrations-iaubsd98hasd 2022-12-19 11:00:35 +01:00
Pilou
d70f29a408 Merge pull request #1400 from nhost/contributors-readme-action-PL6rn2c5lN
docs(contributor): contributors readme action update
2022-12-19 10:58:17 +01:00
Pilou
52cb055520 Merge pull request #1402 from nhost/contributors-readme-action-IrWb62uoZo
docs(contributor): contributors readme action update
2022-12-19 10:57:46 +01:00
github-actions[bot]
8c406237a2 docs(contributor): contrib-readme-action has updated readme 2022-12-19 09:57:07 +00:00
Pilou
d036e282e5 Merge pull request #1395 from nhost/fix-asu9hda0sd
revert code to previously working
2022-12-19 10:56:53 +01:00
Szilárd Dóró
39530cd8e8 feat(dashboard): support Hasura array operators 2022-12-19 10:16:36 +01:00
github-actions[bot]
8b58627608 docs(contributor): contrib-readme-action has updated readme 2022-12-19 08:06:33 +00:00
Calvin Lang
c4e2d87e5c Removed accept headers * in axios requests 2022-12-19 16:06:26 +08:00
Johan Eliasson
66b0378d38 Merge pull request #1397 from muttenzer/docs/event-trigger-env-var
Replace deprecated "NHOST_BACKEND_URL" in event trigger example
2022-12-19 09:06:09 +01:00
Timo M
22d7a36247 update hasura event trigger video using the correct env var 2022-12-17 17:48:36 +01:00
Timo M
7d2eb2de66 update webhook url format image 2022-12-17 17:45:09 +01:00
Timo M
4bba002c30 replace NHOST_BACKEND_URL with NHOST_FUNCTIONS_URL env var 2022-12-17 17:43:42 +01:00
Johan Eliasson
881a3344d4 update lock file 2022-12-17 11:00:45 +01:00
Johan Eliasson
d1562d33fb update 2022-12-17 10:57:06 +01:00
Johan Eliasson
21ced66f22 moved apollo and react-apollo to integrations/ folder 2022-12-17 10:50:13 +01:00
Johan Eliasson
2a2d86904d revert to previously working 2022-12-17 10:46:12 +01:00
Johan Eliasson
82d46f716b Merge pull request #1381 from nhost/docs-ui8asud9
docs update
2022-12-17 10:42:33 +01:00
Johan Eliasson
5e26810868 using authentication everywhere 2022-12-17 10:36:39 +01:00
Johan Eliasson
d590258371 correct query 2022-12-17 10:34:06 +01:00
Johan Eliasson
697ef57cb8 Update docs/docs/authentication/users.mdx
Co-authored-by: Guido Curcio <guidomaurocurcio@gmail.com>
2022-12-17 10:29:28 +01:00
Johan Eliasson
93002dc8c3 Update docs/docs/authentication/users.mdx
Co-authored-by: Guido Curcio <guidomaurocurcio@gmail.com>
2022-12-17 10:29:09 +01:00
Guido Curcio
357e0933ff pass roles with payload; handle adding and removing roles from user 2022-12-17 03:18:53 -03:00
Johan Eliasson
baa1937d06 Merge pull request #1228 from nhost/react-urql
urql
2022-12-16 22:11:29 +01:00
Johan Eliasson
03e5662df9 Merge branch 'main' into react-urql 2022-12-16 22:10:54 +01:00
Pilou
e0711bdfc8 Merge pull request #1372 from kematzy/docs-update-vue-quickstart
Update of Vue Quickstart documentation
2022-12-16 22:05:55 +01:00
Johan Eliasson
caca27fde3 Merge branch 'main' into docs-ui8asud9 2022-12-16 21:55:55 +01:00
Johan Eliasson
b0d51033c6 typo fix 2022-12-16 21:43:02 +01:00
Johan Eliasson
088f9394fc Update docs/docs/graphql/permissions.mdx
Co-authored-by: Siarhei Lipchyk <contact@siarhei.dev>
2022-12-16 21:42:07 +01:00
Szilárd Dóró
a91361f971 feat(dashboard): add support for Hasura permission object converter 2022-12-16 21:10:04 +01:00
Pilou
a4f5be6ab9 Merge pull request #1390 from nhost/fix/strict-mode
fix: React 18 strict mode and other improvements
2022-12-16 19:09:55 +01:00
Szilárd Dóró
dbbccbf1cd fix(dashboard): mobile responsive design 2022-12-16 13:50:22 +01:00
Guido Curcio
7d8f82b99d user.lastSeen fix 2022-12-16 09:36:22 -03:00
Szilárd Dóró
a70dc7b352 chore(dashboard): improve rule group editor design 2022-12-16 12:57:03 +01:00
Pierre-Louis Mercereau
54df0df42b fix: 🐛 React 18 strict mode and other improvements 2022-12-16 12:08:04 +01:00
Szilárd Dóró
0bbb2598fd feat(dashboard): finalize Hasura permission converter 2022-12-16 11:01:25 +01:00
Guido Curcio
e10480b761 missing refetch when deleting user. 2022-12-15 15:02:05 -03:00
Guido Curcio
1343abbe50 comments & types 2022-12-15 12:33:04 -03:00
Szilárd Dóró
4ba34cc827 feat(dashboard): working on Hasura converters 2022-12-15 16:00:11 +01:00
Guido Curcio
fa37546139 handle banning users 2022-12-15 11:22:55 -03:00
Szilárd Dóró
42ece48ce3 feat(dashboard): added support for text truncation 2022-12-15 15:05:24 +01:00
Guido Curcio
112526a984 render email & password only if email and no social oauth. 2022-12-15 11:04:40 -03:00
Szilárd Dóró
f97ab31f69 feat(dashboard): added support for _c* operators 2022-12-15 10:21:09 +01:00
Johan Eliasson
21dc1ecd6b image didn't exist 2022-12-15 10:01:24 +01:00
Szilárd Dóró
c11adbe3e2 chore(dashboard): improve initialization 2022-12-15 09:58:27 +01:00
Johan Eliasson
6078e9c207 new sys env vars 2022-12-15 09:22:00 +01:00
Johan Eliasson
450582dc43 update 2022-12-15 09:12:11 +01:00
Johan Eliasson
ddec0e1be1 update 2022-12-15 09:09:31 +01:00
Johan Eliasson
698154b24b permissions updated 2022-12-15 09:05:42 +01:00
Johan Eliasson
9c87b0f67b updates 2022-12-14 20:48:43 +01:00
Pilou
85afe3d216 Merge pull request #1368 from nhost/refactor/less-peer-dependencies
refactor: less peer dependencies
2022-12-14 19:19:09 +01:00
Pierre-Louis Mercereau
0773e5215f Merge branch 'main' into refactor/less-peer-dependencies 2022-12-14 19:01:31 +01:00
Pierre-Louis Mercereau
10f25fcc4e chore: remove needless paths 2022-12-14 18:59:57 +01:00
Johan Eliasson
2ee90d6ea3 removed unused files 2022-12-14 18:16:33 +01:00
Johan Eliasson
5db5323a1d updates 2022-12-14 18:14:40 +01:00
Guido Curcio
0c74806245 fix showing limit in pagination rather than total users. 2022-12-14 13:31:47 -03:00
Guido Curcio
5df84d7f50 fix remoteAppUser type 2022-12-14 13:08:39 -03:00
Guido Curcio
d58de8fcf8 join totalUsers query with main users query 2022-12-14 12:55:49 -03:00
Szilárd Dóró
ed93d4b583 feat(dashboard): add onInitialized to autocomplete 2022-12-14 16:15:40 +01:00
Szilárd Dóró
1ec1953eaa chore(dashboard): improve default value error tolerance 2022-12-14 15:41:17 +01:00
Szilárd Dóró
63e9c3933e chore(dashboard): improved column autocomplete value management 2022-12-14 15:33:29 +01:00
Guido Curcio
85674c4d90 handle users providers other than email (e.g. github); handle removed providers from a user. 2022-12-14 11:32:28 -03:00
Guido Curcio
5a1d3b9bfc handle anonymous users 2022-12-14 11:06:35 -03:00
Guido Curcio
942570ed29 show table header on not found search strings 2022-12-14 10:33:29 -03:00
Szilárd Dóró
1b1620f633 chore(dashboard): cleaned up default value functionality 2022-12-14 14:24:41 +01:00
Johan Eliasson
e8e8d661e1 small exchange refactor 2022-12-14 13:50:44 +01:00
Johan Eliasson
ba08ec7f5c comments 2022-12-14 13:44:39 +01:00
Johan Eliasson
fb0c98c21d moved react-urql to integrations 2022-12-14 13:37:20 +01:00
Johan Eliasson
c9f575c40c database settings update 2022-12-14 13:24:25 +01:00
Johan Eliasson
6c8bed7ecc Update packages/react-urql/src/provider.tsx
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2022-12-14 13:23:37 +01:00
Guido Curcio
3058eee48f 25 limit, loading screen 2022-12-14 09:21:14 -03:00
Szilárd Dóró
d5a712f7ef feat(dashboard): add support for default values 2022-12-14 13:07:11 +01:00
Johan Eliasson
83422f5ee6 updated README 2022-12-14 09:42:01 +01:00
Johan Eliasson
51909a6a8f remove 2022-12-14 09:34:05 +01:00
Johan Eliasson
2f30797556 update 2022-12-14 09:28:35 +01:00
Johan Eliasson
0b8f7d1661 Merge branch 'main' into react-urql 2022-12-14 09:27:54 +01:00
Johan Eliasson
52ee9d84b6 demo img 2022-12-14 09:11:17 +01:00
Szilárd Dóró
d9612b28b0 chore(dashboard): update pnpm-lock.yaml 2022-12-14 09:07:56 +01:00
Szilárd Dóró
0034791493 Merge remote-tracking branch 'origin/main' into feat/rule-group-editor 2022-12-14 09:06:15 +01:00
Johan Eliasson
80fed14a6b updated 2022-12-14 09:03:30 +01:00
Szilárd Dóró
d457ada435 Merge pull request #1380 from nhost/changeset-release/main
chore: update versions
2022-12-14 08:57:35 +01:00
github-actions[bot]
b41e5a9df5 chore: update versions 2022-12-14 07:46:43 +00:00
Szilárd Dóró
0c8ace1bd4 Merge pull request #1379 from nhost/fix/dashboard-urls
fix(dashboard): use correct service URLs
2022-12-14 08:45:12 +01:00
Johan Eliasson
3f800a068b update 2022-12-13 22:31:42 +01:00
Szilárd Dóró
7d490fe569 fix(dashboard): use correct GraphQL slug and admin secret 2022-12-13 21:34:11 +01:00
Szilárd Dóró
d6527122db fix(dashboard): use correct service URLs 2022-12-13 21:21:12 +01:00
Johan Eliasson
3211140dec remove changeset for now 2022-12-13 21:10:41 +01:00
Johan Eliasson
469352cd81 merge 2022-12-13 21:09:44 +01:00
Szilárd Dóró
88400f6b7c chore(dashboard): add delay to queries 2022-12-13 17:41:16 +01:00
Szilárd Dóró
f8c8a06d71 feat(dashboard): permission variable queries 2022-12-13 17:24:14 +01:00
Szilárd Dóró
ebc1730fce Merge pull request #1375 from nhost/changeset-release/main
chore: update versions
2022-12-13 16:55:15 +01:00
Pierre-Louis Mercereau
c1cd1e813c docs: update changelog 2022-12-13 16:34:41 +01:00
Pierre-Louis Mercereau
e08a074474 chore: un-bump major versions 2022-12-13 16:33:30 +01:00
Szilárd Dóró
2f819865bc chore(dashboard): move handlers to mocks folder 2022-12-13 16:32:01 +01:00
Szilárd Dóró
3888f3041f chore(dashboard): improve operator selectors 2022-12-13 16:15:01 +01:00
Guido Curcio
bacb1b9720 fix number of pages going to 0 on nextPageClick 2022-12-13 11:53:42 -03:00
Guido Curcio
e119e4fc18 styles on userBody 2022-12-13 11:19:23 -03:00
Pierre-Louis Mercereau
569c4004f6 Merge branch 'main' into refactor/less-peer-dependencies 2022-12-13 14:10:31 +01:00
github-actions[bot]
95932fa3f2 chore: update versions 2022-12-13 13:06:10 +00:00
Pilou
99402b77d1 Merge pull request #1376 from nhost/chore/docgen
chore: remove generated documentation from the repository
2022-12-13 14:04:48 +01:00
Szilárd Dóró
f6fb2cd8e6 Merge pull request #1377 from nhost/fix/local-development-region
fix(dashboard): don't break the UI when project is not loaded yet
2022-12-13 13:49:38 +01:00
Szilárd Dóró
5c2cf59b41 chore(dashboard): update CHANGELOG.md 2022-12-13 13:11:50 +01:00
Szilárd Dóró
a6d31dc260 fix(dashboard): don't break the UI when project is not loaded yet 2022-12-13 13:10:54 +01:00
Guido Curcio
b1fe2be963 users body loader, pagination elemnts; input fix for pages > 9 2022-12-13 09:07:36 -03:00
Szilárd Dóró
872e50b635 chore(dashboard): improve Chip in autocomplete 2022-12-13 13:01:44 +01:00
Pierre-Louis Mercereau
bd73557a47 Merge branch 'main' into chore/docgen 2022-12-13 12:01:04 +01:00
Guido Curcio
9b6e8ab3bc slotProps for pagination component 2022-12-13 07:50:43 -03:00
Pilou
c95bab70c2 Merge pull request #1366 from nhost/refactor/merge-core
refactor: decommission `@nhost/core`
2022-12-13 10:50:36 +01:00
Szilárd Dóró
52d4b5de45 Merge pull request #1347 from nhost/changeset-release/main
chore: update versions
2022-12-13 10:29:25 +01:00
Szilárd Dóró
fe0742e278 chore(dashboard): update pnpm-lock.yaml 2022-12-13 10:15:29 +01:00
Szilárd Dóró
ded57d3b24 Merge remote-tracking branch 'origin/main' into feat/rule-group-editor 2022-12-13 10:13:03 +01:00
Szilárd Dóró
c30abaea22 chore(dashboard): add reference to storybook to the README 2022-12-13 10:11:31 +01:00
Szilárd Dóró
6b4ab50f74 fix(packages): nextjs and react-apollo versions 2022-12-13 09:50:42 +01:00
github-actions[bot]
ceba605d0b chore: update versions 2022-12-13 08:47:12 +00:00
Szilárd Dóró
9249a85ee5 Merge pull request #1371 from nhost/fix/aws-name-null-reference
fix(dashboard): don't break UI when region is nullish
2022-12-13 09:45:32 +01:00
Guido Curcio
d2c4b7cad1 custom styles for pagination in users tab 2022-12-13 02:26:32 -03:00
Guido Curcio
59d737696a onChangePage handler for Pagination 2022-12-13 02:13:57 -03:00
Kematzy
22de3214f1 Minor typo & formatting changes to standardise 2022-12-13 11:52:08 +08:00
Kematzy
cf880f992f Update Vue Quickstart docs 2022-12-13 11:50:51 +08:00
Szilárd Dóró
f4d70f88e9 chore(dashboard): add changeset 2022-12-12 22:43:06 +01:00
Szilárd Dóró
0d09b80b12 fix(dashboard): fix nullish region in local mode 2022-12-12 22:42:09 +01:00
Pierre-Louis Mercereau
195adfb04a chore: remove generated documentation from the repository 2022-12-12 21:26:21 +01:00
Pilou
aee4cdcb72 Update .changeset/modern-days-eat.md
Co-authored-by: Johan Eliasson <johan@nhost.io>
2022-12-12 20:20:03 +01:00
Pilou
b09930c8a4 Merge pull request #1369 from nhost/contributors-readme-action-TvJAKaD1lO
docs(contributor): contributors readme action update
2022-12-12 19:06:31 +01:00
github-actions[bot]
687951281e docs(contributor): contrib-readme-action has updated readme 2022-12-12 18:05:20 +00:00
Pilou
c0f05acd9b Merge pull request #1365 from badgifter/patch-windowslive-url
Windows Live Provider displayed link updated to match backend url
2022-12-12 19:05:01 +01:00
Szilárd Dóró
87af60cc03 feat(dashboard): add experimental multiselect autocomplete 2022-12-12 17:30:09 +01:00
Pierre-Louis Mercereau
3d8dd39995 fix: dashboard tests 2022-12-12 17:00:41 +01:00
Pierre-Louis Mercereau
65687beecc chore: rewrite the pr so it fits with Nuno's mind 2022-12-12 16:41:16 +01:00
Szilárd Dóró
62aa859737 feat(dashboard): support for boolean input field 2022-12-12 15:53:50 +01:00
Pierre-Louis Mercereau
d8c2d369aa chore: changeset 2022-12-12 15:43:55 +01:00
Pierre-Louis Mercereau
a4e4926aeb Merge branch 'main' into refactor/merge-core 2022-12-12 15:28:26 +01:00
Guido Curcio
35cd76e562 UsersBodyProps types 2022-12-12 11:16:56 -03:00
Guido Curcio
266bbe837d type users, add comments UsersBodyProps, memo limit & offset. 2022-12-12 11:15:31 -03:00
Guido Curcio
caf785a938 feat: Pagination common component. 2022-12-12 10:48:06 -03:00
Szilárd Dóró
9bc3e755df feat(dashboard): add dynamic rule group editor input type 2022-12-12 14:43:22 +01:00
Pilou
4a9471cc16 Create rude-singers-carry.md 2022-12-12 14:42:55 +01:00
Szilárd Dóró
638a7ac11d feat(dashboard): finalize relationship discovery 2022-12-12 14:19:02 +01:00
Bad Gifter
567e370bdc microsoft changed to windowslive 2022-12-12 14:04:35 +03:00
Bad Gifter
a91f2db0e2 Windows Live Provider displayed link updated to match backend url 2022-12-12 13:49:08 +03:00
Szilárd Dóró
4e49c8db50 fix(dashboard): correct column autocomplete input value 2022-12-12 11:28:49 +01:00
Szilárd Dóró
210f65b4db feat(dashboard): added column autocomplete to rule group editor 2022-12-12 10:50:15 +01:00
Szilárd Dóró
1b6482126f feat(dashboard): add relationship discovery 2022-12-12 10:10:39 +01:00
Guido Curcio
96f9c1a55d handle pagination when searching for users 2022-12-12 06:08:35 -03:00
Guido Curcio
731460b20d handle pagination in users' table 2022-12-12 06:05:22 -03:00
Guido Curcio
1537d46b1d handle states of search: case insensitive query, preserve search query. 2022-12-12 04:29:12 -03:00
Guido Curcio
632def158d render activated providers from users. 2022-12-12 02:38:53 -03:00
Guido Curcio
39271a67e2 render all available roles from the app, check roles form user. 2022-12-12 02:11:43 -03:00
Guido Curcio
9e25c4f386 render verified checkbox as helpertext except when errors; disable prop on phoneNumberVerified when no phoneNumber. 2022-12-12 01:26:48 -03:00
Guido Curcio
dd58a4ac7f handle mutation of displayName, email, and avatarUrl; render avatar url if not default=blank. 2022-12-12 01:14:04 -03:00
Guido Curcio
b9c3567baa update gql query with locale, lastSeen, emailVerified, and phoneNumberVerified 2022-12-12 00:56:00 -03:00
Guido Curcio
108937789a EditUserForm: roles & sign-in methods styles. 2022-12-12 00:20:59 -03:00
Guido Curcio
e651745a7e no users found; default & allowed roles 2022-12-11 23:15:29 -03:00
Szilárd Dóró
699debb2b8 fix(dashboard): correct group rendering 2022-12-09 16:12:05 +01:00
Szilárd Dóró
3e08dc7f8c feat(dashboard): improve navigation in popover 2022-12-09 14:26:46 +01:00
Szilárd Dóró
6928b48781 fix(dashboard): custom autocomplete props 2022-12-09 14:14:58 +01:00
Szilárd Dóró
02886350ff chore(dashboard): use custom autocomplete for column selector 2022-12-09 14:11:32 +01:00
Szilárd Dóró
b3672f8246 feat(dashboard): column selector metadata support 2022-12-09 12:09:43 +01:00
Guido Curcio
6091b4a8e8 handle delete users & refetch main users query 2022-12-09 06:46:01 -03:00
Szilárd Dóró
aea99ad2c8 Merge pull request #1361 from nhost/fix/apple-sign-in-mutation
fix(dashboard): do not show error when submitting Apple provider settings
2022-12-09 09:45:33 +01:00
Szilárd Dóró
594488e435 chore(dashboard): add changeset 2022-12-09 09:29:32 +01:00
Szilárd Dóró
bb83b0f81a fix(dashboard): do not show error when submitting Apple provider settings 2022-12-09 09:18:46 +01:00
Guido Curcio
82ddcbd180 handle search strings, static UsersBodyHeader, nullish render on no users 2022-12-09 03:48:34 -03:00
Guido Curcio
8aa7aafa3b add form footer to EditUserForm 2022-12-09 03:10:23 -03:00
Guido Curcio
183cb4b26a EditUserPasswordForm: handle change password edits, remote gql client, toast on edit. 2022-12-09 03:00:20 -03:00
Guido Curcio
3a7377c6e2 EditUserForm: add avatar with letters, change password button & modal. 2022-12-08 23:15:05 -03:00
Guido Curcio
1529f58c33 fetch remote project users on page load 2022-12-08 23:00:26 -03:00
Guido Curcio
95af5421d1 UsersBody: render first two letters of displayname if no avatar 2022-12-08 22:51:11 -03:00
Guido Curcio
feb39404db first section of user's drawer 2022-12-08 22:26:54 -03:00
Pilou
0384d7c7c4 Merge pull request #1360 from nhost/contributors-readme-action-cDMbyYcNKN
docs(contributor): contributors readme action update
2022-12-08 19:40:40 +01:00
Pilou
7e356a9604 Merge pull request #1357 from nhost/contributors-readme-action-sNfze0TcKw
docs(contributor): contributors readme action update
2022-12-08 19:29:19 +01:00
github-actions[bot]
013e55a307 docs(contributor): contrib-readme-action has updated readme 2022-12-08 18:28:57 +00:00
Pilou
2a71257cde Merge pull request #1358 from nhost/fix/workspace-packages
fix: use workspace to resolve internal dependencies
2022-12-08 19:28:41 +01:00
Pierre-Louis Mercereau
583a4401d0 docs: add explanation to the CI workflow 2022-12-08 18:50:01 +01:00
Pierre-Louis Mercereau
914e91a0b0 ci: correct test 2022-12-08 18:40:49 +01:00
Pierre-Louis Mercereau
98698213e2 ci: run all e2e tests when lockfile changed 2022-12-08 18:29:54 +01:00
Pierre-Louis Mercereau
756daa97cd fix: use workspace to resolve internal dependencies 2022-12-08 16:58:47 +01:00
github-actions[bot]
ab5a2b119c docs(contributor): contrib-readme-action has updated readme 2022-12-08 15:18:12 +00:00
Johan Eliasson
ffdcce1463 Merge pull request #1352 from wollerman/patch-1
Add a section on managing local seed data
2022-12-08 16:17:54 +01:00
Guido Curcio
15b3100c63 pass on data from previously fetched users table 2022-12-08 12:17:22 -03:00
Guido Curcio
f7ef7d106d open drawer on edit user 2022-12-08 11:18:11 -03:00
Szilárd Dóró
0dbbcc5595 chore(dashboard): improve column autocomplete 2022-12-08 15:16:13 +01:00
Szilárd Dóró
a3dcb6106e Merge pull request #1355 from nhost/chore/revert-types-react-bump
chore(dashboard): revert `@types/react` bump
2022-12-08 15:03:24 +01:00
Szilárd Dóró
208d224763 chore(dashboard): revert @types/react bump 2022-12-08 14:46:36 +01:00
Szilárd Dóró
816f8d069d fix(dashboard): pnpm-lock file 2022-12-08 14:20:28 +01:00
Guido Curcio
72c31622cd render user's table with dropdown trigger 2022-12-08 09:25:07 -03:00
Guido Curcio
6959461e3f handle creating users (CreateUserForm) 2022-12-08 08:40:13 -03:00
Guido Curcio
103472ac77 empty state for new users page 2022-12-08 07:57:42 -03:00
Szilárd Dóró
2ebf99ff8f chore(dashboard): improved column autocomplete 2022-12-08 09:32:51 +01:00
renovate[bot]
c13e492bbf chore(deps): update dependency typescript to v4.9.4 2022-12-08 01:41:29 +00:00
Matt Wollerman
564d000bfc add link to overview description of seed data 2022-12-07 20:21:09 -05:00
Szilárd Dóró
63476a2351 feat(dashboard): start work on column autocomplete 2022-12-07 16:49:55 +01:00
Matt Wollerman
266fda07ab add a section on managing local seed data 2022-12-07 08:45:40 -05:00
Szilárd Dóró
782252c059 chore(dashboard): improved Rule Group editor 2022-12-07 14:42:20 +01:00
Szilárd Dóró
e86978a1ff chore(dashboard): upgrade storybook
- chore(dashboard): improve mobile layout of the rule group editor
2022-12-07 13:32:05 +01:00
Szilárd Dóró
84cfd11953 chore(dashboard): extend rule group editor story 2022-12-07 13:12:13 +01:00
Szilárd Dóró
9a43e136f6 fix(dashboard): fixed rule group editor form structure 2022-12-07 11:22:50 +01:00
Szilárd Dóró
e9cff26fa0 chore(dashboard): improve rule group editor layout 2022-12-07 10:11:54 +01:00
Szilárd Dóró
3d32bca2b3 fix(dashboard): fix rule group editor delete button 2022-12-06 16:11:08 +01:00
Szilárd Dóró
4021feaf38 feat(dashboard): rule editor implementation 2022-12-06 14:02:07 +01:00
Pilou
6174e1ddcc Merge pull request #1341 from nhost/refactor/nhost-react-providers
refactor: nhost react providers
2022-12-06 12:57:26 +01:00
Pierre-Louis Mercereau
af2e3eae37 chore: minor bump 2022-12-06 12:39:30 +01:00
Pilou
d2b4c126f3 Merge pull request #1346 from nhost/chore/prettier-ignore-lockfile
chore: prettier ignore pnpm-lock.yaml
2022-12-06 11:01:00 +01:00
Pierre-Louis Mercereau
7f2e182c47 chore: prettier ignore pnpm-lock.yaml 2022-12-06 10:54:16 +01:00
Szilárd Dóró
306ec74356 chore(dashboard): update import paths 2022-12-06 10:16:42 +01:00
Szilárd Dóró
ae40bd54d4 Merge pull request #1302 from nhost/renovate/react-18.x
chore(deps): update dependency @types/react to v18.0.26
2022-12-06 10:01:27 +01:00
Pilou
b5cc47078a Update .changeset/big-pumpkins-march.md
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2022-12-06 09:59:25 +01:00
Pierre-Louis Mercereau
7f251111e2 chore: 🤖 changeset 2022-12-06 09:41:40 +01:00
Pierre-Louis Mercereau
c03dacc3a3 refactor: use NhostProvider in React and Nextjs 2022-12-06 09:39:44 +01:00
Pilou
8b9e1a0ce8 Merge pull request #1339 from nhost/contributors-readme-action-oSzExU64y7
docs(contributor): contributors readme action update
2022-12-06 07:04:10 +01:00
github-actions[bot]
cf9cfec330 docs(contributor): contrib-readme-action has updated readme 2022-12-06 05:52:28 +00:00
Pilou
1c94f56c59 Merge pull request #1338 from iangabrielsanchez/patch-1
Fix typo
2022-12-06 06:52:14 +01:00
Ian Gabriel Sanchez
f06d5deba3 Fix typo 2022-12-06 10:15:59 +08:00
Nuno Pato
8ff58d7f23 Merge pull request #1330 from nhost/changeset-release/main
chore: update versions
2022-12-05 15:22:02 -01:00
github-actions[bot]
8dd1c7415b chore: update versions 2022-12-05 15:56:54 +00:00
Nuno Pato
ebd2749e38 Merge pull request #1329 from nhost/fix/hasura-duplicate-slug
fix(dashboard): use correct Hasura slug
2022-12-05 14:55:28 -01:00
Szilárd Dóró
80b604adda fix(dashboard): use correct Hasura slug 2022-12-05 16:35:35 +01:00
Nuno Pato
9d73050792 Merge pull request #1322 from nhost/changeset-release/main
chore: update versions
2022-12-05 14:20:47 -01:00
renovate[bot]
2a86b8876c chore(deps): update dependency @types/react to v18.0.26 2022-12-05 14:47:07 +00:00
github-actions[bot]
91a1a41f5d chore: update versions 2022-12-05 14:41:11 +00:00
Nuno Pato
22e9c27c81 Merge pull request #1328 from nhost/fix/graphiql-editor
fix(dashboard): prevent error on GraphQL page
2022-12-05 13:39:28 -01:00
Szilárd Dóró
2d2beb53d2 fix(dashboard): prevent error on GraphQL page 2022-12-05 15:26:37 +01:00
Pilou
b403b0d6a0 Merge pull request #1327 from nhost/ci/unambiguous-git-log
chore: don't use PAT in renovate post PR
2022-12-05 14:21:43 +01:00
Pierre-Louis Mercereau
4dbac55cb4 chore: don't use PAT in renovate post PR 2022-12-05 14:20:56 +01:00
Pilou
c6e31ac741 Merge pull request #1324 from nhost/renovate/xstate-vue-2.x
fix(deps): update dependency @xstate/vue to v2
2022-12-05 13:06:56 +01:00
Pilou
0d3e8b3992 Merge pull request #1325 from nhost/ci/unambiguous-git-log
chore(gh-actions): `git log` unabiguously
2022-12-05 12:58:15 +01:00
Pierre-Louis Mercereau
b2afd14d61 chore(gh-actions): git log unabiguously 2022-12-05 12:57:46 +01:00
renovate[bot]
f28f28b6ee fix(deps): update dependency @xstate/vue to v2 2022-12-05 11:52:06 +00:00
Pilou
834b959271 Merge pull request #1323 from nhost/renovate/vueuse-core-9.x
fix(deps): update dependency @vueuse/core to v9
2022-12-05 12:44:43 +01:00
renovate[bot]
4dbc9ccc87 fix(deps): update dependency @vueuse/core to v9 2022-12-05 11:23:06 +00:00
Pierre-Louis Mercereau
2764a1c4b6 Merge branch 'main' into refactor/merge-core 2022-12-05 12:17:21 +01:00
Nuno Pato
1666ca2ec5 Merge pull request #1250 from nhost/chore/deprecate-old-dns-name
chore(dashboard): deprecate old DNS name
2022-12-05 10:10:37 -01:00
Pilou
346791d4d5 Merge pull request #1321 from nhost/renovate/pnpm-find-workspace-dir-5.x
fix(deps): update dependency @pnpm/find-workspace-dir to v5
2022-12-05 11:55:33 +01:00
Pierre-Louis Mercereau
94bdafe22f chore: adapt sync-versions to find-workspace-dir 5 2022-12-05 11:51:44 +01:00
renovate[bot]
33782e9d41 fix(deps): update dependency @pnpm/find-workspace-dir to v5 2022-12-05 10:46:45 +00:00
Johan Eliasson
ea02e1e104 Merge pull request #1311 from nhost/example-serverless-functions-stripe-webhooks
example(serverless functions): Stripe Webhooks
2022-12-05 11:39:36 +01:00
Johan Eliasson
98bf6e3792 Update examples/serverless-functions/functions/stripe-webhook/index.ts
Co-authored-by: Nuno Pato <nunopato@gmail.com>
2022-12-05 11:39:26 +01:00
Johan Eliasson
d9dcafd643 Update examples/serverless-functions/functions/stripe-webhook/index.ts
Co-authored-by: Nuno Pato <nunopato@gmail.com>
2022-12-05 11:39:20 +01:00
Johan Eliasson
4f3d97b5ad Merge pull request #1316 from nhost/elitan-patch-3
docs clarifications
2022-12-05 11:38:51 +01:00
Nuno Pato
d1801ceae9 dashboard: fix link 2022-12-05 09:12:40 -01:00
Szilárd Dóró
b6f9fe6304 Merge pull request #1301 from nhost/changeset-release/main
chore: update versions
2022-12-05 11:02:10 +01:00
github-actions[bot]
15b652d7e0 chore: update versions 2022-12-05 09:14:59 +00:00
Szilárd Dóró
cdc0047cb7 Merge pull request #1284 from nhost/renovate/graphiql-react-0.x
fix(deps): update dependency @graphiql/react to ^0.15.0
2022-12-05 10:13:19 +01:00
Pilou
7c0e71e8be Merge pull request #1303 from nhost/renovate/eslint-plugin-vue-9.x
chore(deps): update dependency eslint-plugin-vue to v9
2022-12-05 09:38:23 +01:00
Pilou
175d6d8cbc Merge pull request #1315 from plmercereau/ci/nhost-cli-action
ci: generic Nhost CLI action
2022-12-05 09:30:31 +01:00
Pierre-Louis Mercereau
2ae277409a ci: action test cleanup 2022-12-05 09:14:58 +01:00
Pierre-Louis Mercereau
ada10170b7 ci: always checkout 2022-12-05 09:08:04 +01:00
Pierre-Louis Mercereau
0ed77cbe8b ci: add cli action tests 2022-12-05 09:05:51 +01:00
Johan Eliasson
1abc68992f Update users.mdx 2022-12-05 08:15:14 +01:00
Pilou
795962e3c2 Merge pull request #1313 from nhost/ci/e2e-matrix-job-name
ci: improve the names of the e2e matrix jobs
2022-12-05 01:28:13 +01:00
Pilou
ba998eb632 Update README.md 2022-12-05 01:18:13 +01:00
Pierre-Louis Mercereau
d3fc1bbeb9 ci: simplify config injection 2022-12-05 00:07:35 +01:00
Pierre-Louis Mercereau
7b9c2016d0 ci: default is: do not start the app 2022-12-04 23:44:51 +01:00
Pierre-Louis Mercereau
ebf4070be6 ci: final adjustments 2022-12-04 23:39:01 +01:00
Pierre-Louis Mercereau
59e3f6abc6 ci: cli version 2022-12-04 23:32:04 +01:00
Pierre-Louis Mercereau
0c9a03a7ff docs: add nhost-cli action readme 2022-12-04 23:00:24 +01:00
Pierre-Louis Mercereau
42cbe27914 ci: revert 2022-12-04 22:51:04 +01:00
Pierre-Louis Mercereau
d7e7b0e51b ci: cleanup 2022-12-04 22:50:11 +01:00
Pierre-Louis Mercereau
036181dd75 ci: clean 2022-12-04 22:48:19 +01:00
Pierre-Louis Mercereau
2828a9fe01 ci: silence curl 2022-12-04 22:41:16 +01:00
Pierre-Louis Mercereau
88bc71dffc ci: try another version 2022-12-04 22:39:49 +01:00
Pierre-Louis Mercereau
17699870a6 ci: correct curl 2022-12-04 22:34:41 +01:00
Pierre-Louis Mercereau
5c0304ab73 ci: remove sS 2022-12-04 22:30:41 +01:00
Pierre-Louis Mercereau
637265e3d9 ci: again 2022-12-04 22:29:34 +01:00
Pierre-Louis Mercereau
229604d8e1 ci: correct retry 2022-12-04 22:25:45 +01:00
Pierre-Louis Mercereau
1165a33079 ci: --retry-connrefused 2022-12-04 22:22:26 +01:00
Pierre-Louis Mercereau
82c0dd9d87 ci: retry again 2022-12-04 22:17:00 +01:00
Pierre-Louis Mercereau
a9bfab1778 ci: 16.1 2022-12-04 22:15:29 +01:00
Pierre-Louis Mercereau
60b7a664d2 ci: improve wait-for 2022-12-04 22:14:53 +01:00
Pierre-Louis Mercereau
4f708d04d6 ci: correct path 2022-12-04 21:56:24 +01:00
Pierre-Louis Mercereau
a02af56056 ci: config 2022-12-04 21:52:17 +01:00
Pierre-Louis Mercereau
575136dcfb ci: don't fail, and fail 2022-12-04 16:45:44 +01:00
Pierre-Louis Mercereau
2bc6346cbc ci: not siltent 2022-12-04 16:42:17 +01:00
Pierre-Louis Mercereau
91cd494a3d ci: correct nhost dev 2022-12-04 16:37:21 +01:00
Pierre-Louis Mercereau
d57e0a5287 ci: path 2022-12-04 16:36:02 +01:00
Pierre-Louis Mercereau
dd5e7093f0 ci: start 2022-12-04 16:34:47 +01:00
Pierre-Louis Mercereau
3e9bb84f07 ci: don't build packages 2022-12-04 16:34:05 +01:00
Pierre-Louis Mercereau
6665b58ec8 ci: dedicated wip action 2022-12-04 16:33:13 +01:00
Pierre-Louis Mercereau
456e893cd6 ci: change branch reference 2022-12-04 16:24:47 +01:00
Pierre-Louis Mercereau
fd76170ca6 ci: nhost-cli action 2022-12-04 16:23:52 +01:00
Pierre-Louis Mercereau
682aef2d94 ci: improve the names of the e2e matrix jobs 2022-12-03 23:01:46 +01:00
Pilou
cb53f71d4a Merge pull request #1312 from plmercereau/main
Chore(docker-compose): fix tests
2022-12-03 17:28:42 +01:00
Pierre-Louis Mercereau
4fc0b40cb4 chore(docker-compose): increase timeout 2022-12-03 17:20:48 +01:00
Pierre-Louis Mercereau
9da2d01c55 chore(docker-compose): describe 2022-12-03 17:16:11 +01:00
Pierre-Louis Mercereau
0d5e7850f8 chore(docker-compose): retry 2022-12-03 17:14:23 +01:00
Johan Eliasson
8ed965c669 keep migrations file here, otherwise nhost dev won't work 2022-12-03 14:44:22 +01:00
Pilou
cb284b40b1 Merge pull request #1308 from nhost/ci/docker-compose
chore: improve docker-compose example
2022-12-03 13:59:10 +01:00
Johan Eliasson
c59f622feb fix 2022-12-03 13:48:40 +01:00
Johan Eliasson
9a30edd038 example 2022-12-03 13:47:42 +01:00
Johan Eliasson
4b2d2a4f55 merge 2022-12-03 13:36:02 +01:00
Johan Eliasson
eba2bd05b8 update 2022-12-03 13:35:04 +01:00
Johan Eliasson
84a1b28261 Create breezy-donuts-try.md 2022-12-03 13:34:20 +01:00
Johan Eliasson
ff3b9df41e cleanup 2022-12-03 13:32:06 +01:00
Pilou
b8b4e36175 Merge pull request #1307 from nhost/renovate/uuid-9.x
chore(deps): update dependency uuid to v9
2022-12-03 11:33:51 +01:00
Pierre-Louis Mercereau
6e47ef68d5 Merge branch 'ci/docker-compose' of https://github.com/nhost/nhost into ci/docker-compose 2022-12-02 23:11:24 +01:00
Pilou
2697414637 Create fair-students-enjoy.md 2022-12-02 23:08:13 +01:00
Pierre-Louis Mercereau
e753b2faed chore: quiet docker pull 2022-12-02 23:01:55 +01:00
Pierre-Louis Mercereau
6f62ec7d2a fix: use docker-compose v2 syntax 2022-12-02 22:43:32 +01:00
Pierre-Louis Mercereau
d365ef1953 test: 💍 create e2e tests for the docker-compose example 2022-12-02 22:20:12 +01:00
Szilárd Dóró
99ee9fd10d fix(dashboard): move Brazilian flag 2022-12-02 20:29:58 +01:00
Nuno Pato
9608a327c9 dashboard: add brazilian flag 2022-12-02 18:27:14 -01:00
Szilárd Dóró
492b83ef58 fix(dashboard): correct GraphQL URL 2022-12-02 20:25:11 +01:00
renovate[bot]
09f53ae43f chore(deps): update dependency uuid to v9 2022-12-02 18:30:25 +00:00
renovate[bot]
7724ac7e06 chore(deps): update dependency eslint-plugin-vue to v9 2022-12-02 15:56:01 +00:00
renovate[bot]
02343fe171 fix(deps): update dependency @graphiql/react to ^0.15.0 2022-12-02 15:52:13 +00:00
Szilárd Dóró
98dd8d039c Merge pull request #1305 from nhost/fix/pnpm-lock
fix(deps): correct pnpm-lock.yaml
2022-12-02 16:35:13 +01:00
Szilárd Dóró
456e057497 Merge remote-tracking branch 'origin/main' into fix/pnpm-lock 2022-12-02 16:34:46 +01:00
Pilou
93e9b58a58 Merge pull request #1289 from nhost/renovate/faker-6.x
chore(deps): update dependency @types/faker to v6
2022-12-02 16:33:33 +01:00
Szilárd Dóró
019a7c2335 fix: correct pnpm-lock.yaml 2022-12-02 16:26:51 +01:00
Pierre-Louis Mercereau
a0901914ac Merge branch 'main' into refactor/merge-core 2022-12-02 16:09:32 +01:00
Pilou
64882a8e16 Merge pull request #1279 from nhost/renovate/prettier-plugin-tailwindcss-0.x
chore(deps): update dependency prettier-plugin-tailwindcss to ^0.2.0
2022-12-02 15:59:13 +01:00
Pilou
1ed572fe39 Merge pull request #1275 from nhost/renovate/msw-0.x
chore(deps): update dependency msw to ^0.49.0
2022-12-02 15:58:56 +01:00
Pilou
e06271a8ae Merge pull request #1282 from nhost/renovate/vitest-monorepo
chore(deps): update dependency vitest to ^0.25.0
2022-12-02 15:56:09 +01:00
Szilárd Dóró
bca239ebb2 Merge pull request #1296 from nhost/chore/cleanup-deps
chore(deps): remove unused deps, sync @types/react and @types/react-dom
2022-12-02 15:51:40 +01:00
Szilárd Dóró
e33caa046d Merge pull request #1273 from nhost/fix/settings-env-var-empty-list
fix(dashboard): correct section paddings when no env vars
2022-12-02 15:51:05 +01:00
renovate[bot]
cbbd331341 chore(deps): update dependency prettier-plugin-tailwindcss to ^0.2.0 2022-12-02 14:42:50 +00:00
Pierre-Louis Mercereau
c41bfaffdd chore: 🤖 remove unused @types/faker 2022-12-02 15:39:20 +01:00
renovate[bot]
f2596b0b14 chore(deps): update dependency msw to ^0.49.0 2022-12-02 14:31:58 +00:00
Pilou
4d0c3111d1 Merge pull request #1299 from nhost/chore/labeler
chore: don't remove existing labels
2022-12-02 15:29:18 +01:00
Pierre-Louis Mercereau
7ff9644ac7 chore: don't remove existing labels 2022-12-02 15:28:35 +01:00
renovate[bot]
87fdaa7144 chore(deps): update dependency @types/faker to v6 2022-12-02 13:56:59 +00:00
Szilárd Dóró
bc23d051ba Merge pull request #1274 from nhost/changeset-release/main
chore: update versions
2022-12-02 13:40:52 +01:00
Szilárd Dóró
132a4f4be9 chore(deps): synchronize @types/react-dom and @types/react versions 2022-12-02 13:36:26 +01:00
github-actions[bot]
c330dc1c00 chore: update versions 2022-12-02 12:34:54 +00:00
Pilou
4bebd9842b Merge pull request #1297 from nhost/chore/labeler
chore: rename labeler.yaml to .yml
2022-12-02 13:33:09 +01:00
Pierre-Louis Mercereau
541f2d250c chore: rename labeler.yaml to .yml 2022-12-02 13:32:02 +01:00
Szilárd Dóró
6b31e31430 Merge branch 'main' into chore/cleanup-deps 2022-12-02 13:31:09 +01:00
Szilárd Dóró
9ba2208dd7 chore(dashboard): remove unused dependencies 2022-12-02 13:30:02 +01:00
Szilárd Dóró
538541fc79 Merge pull request #1268 from nhost/renovate/netlify-functions-0.x
chore(deps): remove dependency @netlify/functions
2022-12-02 13:18:38 +01:00
Pilou
cb0aab48b3 Merge pull request #1292 from nhost/chore/labeler
chore: use correct PAT
2022-12-02 13:18:16 +01:00
Pierre-Louis Mercereau
dcc760b6bb chore: use correct PAT 2022-12-02 13:17:39 +01:00
Pilou
d2227be0d0 Merge pull request #1291 from nhost/chore/labeler
chore: add labeler workflow
2022-12-02 12:05:35 +01:00
Pierre-Louis Mercereau
93e807edc4 chore: add labeler workflow 2022-12-02 12:04:55 +01:00
Pilou
14738d4b58 Merge pull request #1283 from plmercereau/main
ci: create renovate changeset `after` the pull request is merged
2022-12-02 11:39:06 +01:00
Szilárd Dóró
6ac4cfa80c Merge branch 'main' into renovate/netlify-functions-0.x 2022-12-02 11:32:08 +01:00
Szilárd Dóró
295c6c9110 chore(dashboard): remove @netlify/functions 2022-12-02 11:31:58 +01:00
Szilárd Dóró
02911e4a54 Merge pull request #1267 from nhost/renovate/critters-0.x
chore(deps): update dependency critters to ^0.0.16
2022-12-02 11:19:39 +01:00
Szilárd Dóró
2be825de08 Merge pull request #1285 from nhost/renovate/docusaurus-monorepo
fix(deps): update docusaurus monorepo to v2.2.0
2022-12-02 11:19:14 +01:00
Szilárd Dóró
65afad1b91 fix(deps): pnpm-lock 2022-12-02 11:08:38 +01:00
Pilou
dbea13a1d2 Merge pull request #1287 from nhost/chore/labeler
chore: add labels to pull requests
2022-12-02 10:59:37 +01:00
Szilárd Dóró
5e2a419700 Merge branch 'main' into renovate/critters-0.x 2022-12-02 10:42:52 +01:00
Szilárd Dóró
f1272947dd chore(deps): update @types/react and @types/react-dom 2022-12-02 10:17:32 +01:00
Johan Eliasson
e5041bfd30 Merge branch 'main' into react-urql 2022-12-02 09:59:38 +01:00
Johan Eliasson
3d7cc74feb env vars 2022-12-02 09:42:38 +01:00
Johan Eliasson
d007202783 update 2022-12-02 09:40:26 +01:00
Johan Eliasson
38e92a705d works outside strict mode now 2022-12-02 09:38:16 +01:00
Pierre-Louis Mercereau
9e6660450c chore: add an examples label 2022-12-02 09:19:04 +01:00
Pierre-Louis Mercereau
2db9be03ff chore: 🤖 add labels to pull requests 2022-12-01 23:11:06 +01:00
renovate[bot]
1b8f505050 fix(deps): update docusaurus monorepo to v2.2.0 2022-12-01 21:41:57 +00:00
Pilou
6ab6bccded Merge pull request #1278 from nhost/ci/renovate-label
ci: add renovate label
2022-12-01 22:37:11 +01:00
Pilou
b12bc1c27f Merge pull request #1277 from nhost/chore/missing-version
chore: add missing version field to the vue-starter example
2022-12-01 22:31:55 +01:00
Pierre-Louis Mercereau
04d1641cf7 revert: initial versions 2022-12-01 22:22:06 +01:00
Pierre-Louis Mercereau
e91c09aa9c revert: initial versions 2022-12-01 22:20:46 +01:00
Pierre-Louis Mercereau
7c04aad870 revert: initial bumps 2022-12-01 22:19:13 +01:00
Pilou
520044c5ab Merge branch 'nhost:main' into main 2022-12-01 22:16:18 +01:00
plmercereau
22fed668d6 chore(deps): update dependency uuid to v9 2022-12-01 21:07:31 +00:00
Pilou
ae14fb1a2f Merge pull request #50 from plmercereau/renovate/uuid-9.x
chore(deps): update dependency uuid to v9
2022-12-01 22:06:13 +01:00
Johan Eliasson
74cc63833a package updates 2022-12-01 22:05:28 +01:00
Pilou
f4ca0aab42 Merge pull request #52 from plmercereau/ci/origin
test: 💍 origin
2022-12-01 22:04:55 +01:00
Pierre-Louis Mercereau
d8a0d196af test: 💍 origin 2022-12-01 22:04:23 +01:00
Pierre-Louis Mercereau
cd53718631 ci: origin 2022-12-01 22:03:49 +01:00
Pilou
1fcd3f1851 Merge pull request #49 from plmercereau/renovate/last-sha
test: 💍 last sha
2022-12-01 21:59:26 +01:00
Pierre-Louis Mercereau
67d370feaa test: 💍 last sha 2022-12-01 21:58:01 +01:00
Pierre-Louis Mercereau
0173ec356b ci: last sha 2022-12-01 21:56:45 +01:00
renovate[bot]
2fb43d417a chore(deps): update dependency uuid to v9 2022-12-01 20:41:02 +00:00
Pilou
966b8158c2 Merge pull request #48 from plmercereau/renovate/debug
test: 💍 debug
2022-12-01 21:33:56 +01:00
Pierre-Louis Mercereau
800fac6093 test: 💍 debug 2022-12-01 21:33:20 +01:00
Pierre-Louis Mercereau
20eb04cd46 ci: debug 2022-12-01 21:32:22 +01:00
Johan Eliasson
425320bbb5 lockfile update 2022-12-01 21:31:57 +01:00
Johan Eliasson
499352ad8a Merge branch 'main' into react-urql 2022-12-01 21:30:53 +01:00
Pilou
5d31a88556 Merge pull request #45 from plmercereau/renovate/base_ref
test: 💍 base_ref
2022-12-01 21:27:33 +01:00
Pierre-Louis Mercereau
06019ae7ba test: 💍 base_ref 2022-12-01 21:25:36 +01:00
Pierre-Louis Mercereau
523af2901f ci: base_ref 2022-12-01 21:24:52 +01:00
Pilou
1e0a2c0c43 Merge pull request #1264 from nhost/renovate/react-dom-18.x
chore(deps): update dependency @types/react-dom to v18.0.9
2022-12-01 21:06:41 +01:00
Pilou
9b60f9ca48 Merge pull request #1276 from nhost/renovate/nextjs-monorepo
chore(deps): update dependency next to v12.3.4
2022-12-01 21:06:01 +01:00
Pilou
90bc800c92 Update .github/renovate.json 2022-12-01 21:05:42 +01:00
renovate[bot]
023060cee6 chore(deps): update dependency vitest to ^0.25.0 2022-12-01 20:02:01 +00:00
Szilárd Dóró
0bb3b127d0 chore(dashboard): change local package versions 2022-12-01 20:53:30 +01:00
Pilou
cd914d30ed Merge pull request #44 from plmercereau/renovate/after
test: 💍 add changeset after renovate merge
2022-12-01 20:11:15 +01:00
Pilou
71dddccb9c Merge pull request #41 from plmercereau/renovate/dotenv-16.x
chore(deps): update dependency dotenv to v16
2022-12-01 19:59:03 +01:00
Pierre-Louis Mercereau
2a846040ef test: 💍 add changeset after renovate merge 2022-12-01 19:58:18 +01:00
Pierre-Louis Mercereau
8b580d05c4 ci: add changeset after the renovate pr is merged 2022-12-01 19:57:33 +01:00
Pilou
24d70e8ea8 Update .changeset/tenancy-smothering-cataleptic.md 2022-12-01 19:32:47 +01:00
renovate[bot]
8212432983 chore(deps): update dependency next to v12.3.4 2022-12-01 18:07:07 +00:00
Pierre-Louis Mercereau
7df00a3291 fix: 🐛 disable @antfu's lint rule 2022-12-01 19:04:47 +01:00
Pierre-Louis Mercereau
0186aa5c98 ci: add renovate label 2022-12-01 18:59:38 +01:00
Pierre-Louis Mercereau
67e5cc839c chore: add missing version field to the vue-starter example 2022-12-01 18:56:08 +01:00
Pilou
25c5bd1ccd Merge pull request #1269 from plmercereau/main
ci: improvements on the renovate changeset workflow
2022-12-01 18:51:39 +01:00
renovate[bot]
e5fa48d818 chore(deps): update dependency next to v12.3.4 2022-12-01 17:41:33 +00:00
Pilou
f34da3a715 Merge pull request #1270 from nhost/renovate/xstate-inspect-0.x
chore(deps): update dependency @xstate/inspect to ^0.7.0
2022-12-01 18:38:17 +01:00
Pilou
fab330ce55 Merge pull request #35 from plmercereau/renovate/glob-8.x
chore(deps): update dependency @types/glob to v8
2022-12-01 18:34:47 +01:00
renovate[bot]
3a76080e40 chore(deps): update dependency @types/glob to v8 2022-12-01 16:37:05 +00:00
Szilárd Dóró
db57572f38 fix(dashboard): correct section paddings when no env vars 2022-12-01 15:40:16 +01:00
renovate[bot]
b030eae999 chore(deps): update dependency @xstate/inspect to ^0.7.0 2022-12-01 14:13:16 +00:00
renovate[bot]
b10f4fa631 chore(deps): update dependency @xstate/inspect to ^0.7.0 2022-12-01 14:11:35 +00:00
Pilou
4a6e8c9945 Merge pull request #1263 from nhost/renovate/akhilmhdh-contributors-readme-action-2.x
chore(deps): update akhilmhdh/contributors-readme-action action to v2.3.6
2022-12-01 15:06:20 +01:00
Pierre-Louis Mercereau
3a4d087e6f chore: remove changeset 2022-12-01 15:04:52 +01:00
Pilou
c408b38f28 Merge branch 'nhost:main' into main 2022-12-01 14:54:02 +01:00
Pierre-Louis Mercereau
b2336b2b33 ci: clean 2022-12-01 14:53:49 +01:00
Pierre-Louis Mercereau
fcf68d5c32 ci: separate workflow 2022-12-01 14:48:54 +01:00
Pierre-Louis Mercereau
9e71677cd2 ci: use PAT 2022-12-01 14:36:48 +01:00
Pierre-Louis Mercereau
ce48ce0860 ci: amend 2022-12-01 14:30:57 +01:00
renovate[bot]
9b93cf95ec chore(deps): update dependency @netlify/functions to ^0.11.0 2022-12-01 13:21:48 +00:00
renovate[bot]
34d85e54d6 chore(deps): update dependency critters to ^0.0.16 2022-12-01 13:20:08 +00:00
renovate[bot]
6ae9d6dd01 chore(deps): update dependency @netlify/functions to ^0.11.0 2022-12-01 13:19:41 +00:00
renovate[bot]
1e8d8afe70 chore(deps): update dependency critters to ^0.0.16 2022-12-01 13:18:19 +00:00
Pierre-Louis Mercereau
80478e39e0 ci: put ifs back 2022-12-01 14:11:23 +01:00
Szilárd Dóró
ee7338cc12 Merge pull request #1266 from nhost/changeset-release/main
chore: update versions
2022-12-01 14:10:20 +01:00
renovate[bot]
3a39970d28 chore(deps): update dependency dotenv to v16 2022-12-01 13:09:28 +00:00
Pierre-Louis Mercereau
b0607673ed ci: remove more ifs 2022-12-01 13:57:27 +01:00
Pierre-Louis Mercereau
d9f27c6c65 ci: deactivate 2022-12-01 13:46:15 +01:00
github-actions[bot]
ea0b35fe84 chore: update versions 2022-12-01 12:30:09 +00:00
Szilárd Dóró
4fbd22f232 Merge pull request #1258 from nhost/fix/settings-env-var-character-limit
fix(dashboard): remove character limit from env var inputs
2022-12-01 13:28:30 +01:00
Pierre-Louis Mercereau
c92142845f ci: simplify syntax 2022-12-01 13:27:29 +01:00
Pierre-Louis Mercereau
c93f818315 ci: not the dependencies 2022-12-01 12:42:19 +01:00
Pierre-Louis Mercereau
d20ed86219 ci: don't create changeset if no package is impacted 2022-12-01 12:36:10 +01:00
renovate[bot]
e04390307c chore(deps): update dependency @types/react-dom to v18.0.9 2022-12-01 10:49:12 +00:00
renovate[bot]
5c931f14ae chore(deps): update dependency @types/react-dom to v18.0.9 2022-12-01 10:47:47 +00:00
renovate[bot]
a7ab1243a4 chore(deps): update akhilmhdh/contributors-readme-action action to v2.3.6 2022-12-01 10:43:54 +00:00
Pilou
5638b5e770 Merge pull request #1262 from nhost/ci/adjust-workflows
ci: adjust workflows
2022-12-01 11:43:09 +01:00
renovate[bot]
c5ce895c97 chore(deps): update akhilmhdh/contributors-readme-action action to v2.3.6 2022-12-01 10:42:20 +00:00
Pierre-Louis Mercereau
2be99c0e55 ci: adjust workflows 2022-12-01 11:34:59 +01:00
Pilou
f6299b537d Merge pull request #1261 from plmercereau/main
ci: set Renovate bot
2022-12-01 11:33:30 +01:00
Pilou
11d06cce4b Merge branch 'nhost:main' into main 2022-12-01 10:49:46 +01:00
Pierre-Louis Mercereau
e9e0ad6d3c ci: clean renovate 2022-12-01 10:46:28 +01:00
Pierre-Louis Mercereau
3ad2d5ced8 ci: clean-up 2022-12-01 10:44:47 +01:00
Szilárd Dóró
42bfa7c16d Merge pull request #1259 from nhost/chore/issue-templates
chore: create issue templates
2022-12-01 10:37:51 +01:00
Pierre-Louis Mercereau
0dea974a2e ci: fine-tune 2022-12-01 10:28:13 +01:00
Szilárd Dóró
8165b8f13e chore: create issue templates 2022-12-01 10:25:30 +01:00
Pierre-Louis Mercereau
1c8864c992 ci: debug ref_head 2022-12-01 10:22:40 +01:00
Pierre-Louis Mercereau
dd6921676f ci: correct sed 2022-12-01 10:12:54 +01:00
Szilárd Dóró
a1193da4fb fix(dashboard): remove character limit from env var inputs 2022-12-01 10:05:56 +01:00
Pierre-Louis Mercereau
ff83a29dcc ci: fix filter 2022-12-01 10:03:15 +01:00
Pierre-Louis Mercereau
4771bff65c ci: don't use ambiguous redirection 2022-12-01 09:56:57 +01:00
Pierre-Louis Mercereau
6106265d87 ci: install pnpm 2022-12-01 09:48:48 +01:00
Pierre-Louis Mercereau
3c2455b7e1 ci: echo 2022-12-01 09:39:59 +01:00
Pierre-Louis Mercereau
7bc8de103b ci: correct 2022-12-01 09:36:26 +01:00
Pierre-Louis Mercereau
e49ba4bd02 ci: don't use paste 2022-12-01 09:23:24 +01:00
Pierre-Louis Mercereau
44ac1a0095 ci: shuf 2022-12-01 09:10:41 +01:00
Pierre-Louis Mercereau
04ce686e7c Merge branch 'main' of https://github.com/plmercereau/nhost 2022-12-01 08:46:29 +01:00
Pierre-Louis Mercereau
ca01224083 ci: alway patch 2022-12-01 08:46:02 +01:00
Pilou
d489232cbc Update packages.yaml 2022-12-01 07:43:32 +01:00
Pierre-Louis Mercereau
9efc0522c3 fix(examples): rename test script to e2e:test 2022-11-30 23:54:57 +01:00
Pierre-Louis Mercereau
4c86ed787e ci: shorter job title 2022-11-30 23:50:28 +01:00
Pierre-Louis Mercereau
9a3c05f69b fix(examples): correct examples to pass the build step 2022-11-30 23:48:11 +01:00
Pierre-Louis Mercereau
2b03f80d59 ci: avoid double negative 2022-11-30 23:37:40 +01:00
Pierre-Louis Mercereau
baa3f0531d ci: typo 2022-11-30 23:35:49 +01:00
Pierre-Louis Mercereau
f9bbc78241 ci: correct test 2022-11-30 23:34:37 +01:00
Pierre-Louis Mercereau
7f62c8b7c2 refactor(examples): remove obsolete test 2022-11-30 23:31:04 +01:00
Pierre-Louis Mercereau
de2bcb6320 ci: fix 2022-11-30 23:18:42 +01:00
Pierre-Louis Mercereau
64a6d934e7 ci: dict 2022-11-30 23:17:26 +01:00
Pierre-Louis Mercereau
f455022e6d ci: debug 2022-11-30 23:15:26 +01:00
Pierre-Louis Mercereau
baac8a3605 ci: debug 2022-11-30 23:03:39 +01:00
Pierre-Louis Mercereau
be20cd5cdb ci: remove if 2022-11-30 22:58:17 +01:00
Pilou
1de4137369 Merge pull request #4 from plmercereau/renovate/configure
Configure Renovate
2022-11-30 22:54:17 +01:00
Pierre-Louis Mercereau
18fae1a891 ci(renovate): ignore node and pnpm 2022-11-30 22:54:04 +01:00
Pierre-Louis Mercereau
03c58613b8 ci: adapt renovate 2022-11-30 22:49:46 +01:00
Pierre-Louis Mercereau
fb23dd6b39 ci: prepare renovate 2022-11-30 22:45:33 +01:00
renovate[bot]
c12bd632fc chore(deps): add renovate.json 2022-11-30 20:11:34 +00:00
Pilou
a71eea09a9 Merge pull request #1254 from nhost/ci/create-cli-pr
ci: PR to the CLI with the new dashboard version
2022-11-30 18:25:47 +01:00
Szilárd Dóró
c9f88326b2 chore(dashboard): migrate app URLs to service URLs 2022-11-30 17:12:58 +01:00
Pierre-Louis Mercereau
d1f7842169 chore: set fetch-depth to 0 2022-11-30 16:50:32 +01:00
Pierre-Louis Mercereau
4566c2a202 chore: rephrase 2022-11-30 16:40:31 +01:00
Pierre-Louis Mercereau
c678918e73 ci: PR to the CLI with the new dashboard version 2022-11-30 16:38:03 +01:00
Szilárd Dóró
ac8efcbdd5 chore(dashboard): add changeset 2022-11-30 16:13:30 +01:00
Szilárd Dóró
9bc346e8d4 fix(dashboard): minor layout fixes in provider alert 2022-11-30 16:12:11 +01:00
Nuno Pato
efed987d31 fix linter 2022-11-30 12:12:48 -01:00
Szilárd Dóró
7e113bfb1f Merge pull request #1253 from nhost/changeset-release/main
chore: update versions
2022-11-30 14:11:45 +01:00
Nuno Pato
bdab7da7d3 fix linter 2022-11-30 12:02:10 -01:00
Nuno Pato
c2d9993968 asd 2022-11-30 11:53:30 -01:00
Nuno Pato
508ba62207 update copy 2022-11-30 11:52:41 -01:00
Nuno Pato
a3318de06e incorporate minor changes from comments 2022-11-30 11:49:25 -01:00
github-actions[bot]
f1d358d77c chore: update versions 2022-11-30 11:16:45 +00:00
Szilárd Dóró
d558ef9ecf Merge pull request #1249 from nhost/chore/dashboard-cleanup
chore(dashboard): cleanup unused files
2022-11-30 12:08:39 +01:00
Pierre-Louis Mercereau
26d577d7ae Merge branch 'main' into refactor/merge-core 2022-11-30 11:43:30 +01:00
Szilárd Dóró
75c7ba7f12 Merge pull request #1252 from nhost/changeset-release/main
chore: update versions
2022-11-30 08:29:25 +01:00
github-actions[bot]
d62dfe19a2 chore: update versions 2022-11-30 07:28:00 +00:00
Szilárd Dóró
0dbef188b1 Merge pull request #1247 from nhost/chore/sidebar-menu-item-height
chore(dashboard): update settings sidebar menu item density
2022-11-30 08:26:39 +01:00
Nuno Pato
fa9f7ca052 Deprecate old DNS name 2022-11-30 03:01:17 -01:00
Szilárd Dóró
44f13f6240 chore(dashboard): cleanup unused files 2022-11-29 20:29:25 +01:00
Szilárd Dóró
e01cb2ed49 chore(dashboard): add changeset 2022-11-29 17:18:48 +01:00
Szilárd Dóró
388eef041f chore(dashboard): change settings sidebar menu item density 2022-11-29 17:18:09 +01:00
Pierre-Louis Mercereau
622c48a94b chore: update changeset 2022-11-29 16:18:18 +01:00
Pierre-Louis Mercereau
e1a87a05b1 chore: update lock file 2022-11-29 16:15:49 +01:00
Pierre-Louis Mercereau
2148317282 Merge branch 'main' into refactor/merge-core 2022-11-29 16:15:05 +01:00
Pierre-Louis Mercereau
5f9c6c8346 Merge branch 'main' into refactor/merge-core 2022-11-28 21:16:06 +01:00
Johan Eliasson
2e30371086 Merge branch 'main' into react-urql 2022-11-28 17:04:51 +01:00
Pierre-Louis Mercereau
57db5b83d4 chore: 🤖 changeset 2022-11-28 15:39:21 +01:00
Johan Eliasson
66659bb293 update 2022-11-27 21:31:14 +01:00
Johan Eliasson
579d4f3170 update 2022-11-27 21:14:10 +01:00
Johan Eliasson
bb56548603 urql 2022-11-27 21:12:07 +01:00
Pierre-Louis Mercereau
3cab18713a Merge branch 'main' into refactor/merge-core 2022-11-24 17:33:18 +01:00
Pierre-Louis Mercereau
fb94dae43a chore: merge main 2022-11-24 17:17:04 +01:00
Pierre-Louis Mercereau
f694846eae chore: 🤖 remove hasura-storage-js to hasura-auth-js 2022-11-24 16:54:13 +01:00
Pierre-Louis Mercereau
322ab50138 Merge branch 'main' into refactor/merge-core 2022-11-22 09:52:45 +01:00
Pierre-Louis Mercereau
435efd2bc5 fix: 🐛 Set same-site cookie to lax 2022-11-21 15:22:05 +01:00
Szilárd Dóró
5501a5937e fix(docgen): complex types in markdown tables 2022-11-16 12:27:24 +01:00
Pierre-Louis Mercereau
80a6808a82 Merge branch 'main' into refactor/merge-core 2022-11-16 10:26:11 +01:00
Pierre-Louis Mercereau
987bd70312 Merge branch 'main' into refactor/merge-core 2022-11-15 14:14:58 +01:00
Pierre-Louis Mercereau
feb22e62c1 fix: add missing oauth provider: azuread 2022-11-14 23:48:45 +01:00
Pierre-Louis Mercereau
e7d4c77a6d refactor: 💡 restructure hasura-auth-js after the core merger 2022-11-14 23:20:49 +01:00
Pierre-Louis Mercereau
628e32464d Merge branch 'main' into refactor/merge-core 2022-11-14 21:45:05 +01:00
Pierre-Louis Mercereau
dc82043254 chore: only include the auth client typedoc 2022-11-09 22:13:20 +01:00
Pierre-Louis Mercereau
997e9d58a8 refactor: 💡 remove @nhost/core 2022-11-09 22:09:17 +01:00
Pierre-Louis Mercereau
8a3f1706fe chore: add auth as a dependency to storage 2022-11-09 22:01:11 +01:00
Pierre-Louis Mercereau
12cbe4d534 chore: lint 2022-11-09 21:52:15 +01:00
Pierre-Louis Mercereau
9f21931201 refactor: copy tests from core 2022-11-09 21:46:32 +01:00
Pierre-Louis Mercereau
09351e1910 Merge branch 'main' into refactor/merge-core 2022-11-09 20:49:33 +01:00
Pierre-Louis Mercereau
1c2ea5a407 refactor: 💡 merge @nhost/core 2022-11-09 20:49:13 +01:00
976 changed files with 22364 additions and 24364 deletions

View File

@@ -2,9 +2,22 @@
"$schema": "https://unpkg.com/@changesets/config@1.6.0/schema.json", "$schema": "https://unpkg.com/@changesets/config@1.6.0/schema.json",
"changelog": "@changesets/cli/changelog", "changelog": "@changesets/cli/changelog",
"commit": false, "commit": false,
"linked": [], "linked": [
[
"@nhost/nextjs",
"@nhost/react",
"@nhost/vue",
"@nhost/nhost-js",
"@nhost/hasura-auth-js",
"@nhost/hasura-storage-js"
],
[
"@nhost/react-apollo",
"@nhost/apollo"
]
],
"access": "restricted", "access": "restricted",
"baseBranch": "main", "baseBranch": "main",
"updateInternalDependencies": "patch", "updateInternalDependencies": "patch",
"ignore": [] "ignore": []
} }

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -5,6 +5,10 @@ inputs:
description: 'Turborepo token' description: 'Turborepo token'
TURBO_TEAM: TURBO_TEAM:
description: 'Turborepo team' description: 'Turborepo team'
BUILD:
description: 'Build packages'
default: 'default'
runs: runs:
using: 'composite' using: 'composite'
steps: steps:
@@ -35,6 +39,14 @@ runs:
# * They are reused through the Turborepo cache # * They are reused through the Turborepo cache
- shell: bash - shell: bash
name: Build packages name: Build packages
if: ${{ inputs.BUILD == 'all' }}
run: pnpm build:all
env:
TURBO_TOKEN: ${{ inputs.TURBO_TOKEN }}
TURBO_TEAM: ${{ inputs.TURBO_TEAM }}
- shell: bash
name: Build everything in the monorepo
if: ${{ inputs.BUILD == 'default' }}
run: pnpm build run: pnpm build
env: env:
TURBO_TOKEN: ${{ inputs.TURBO_TOKEN }} TURBO_TOKEN: ${{ inputs.TURBO_TOKEN }}

108
.github/actions/nhost-cli/README.md vendored Normal file
View File

@@ -0,0 +1,108 @@
# Nhost CLI GitHub Action
## Usage
```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install the Nhost CLI
uses: ./.github/actions/nhost-cli
```
### Install the CLI and start the app
```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Nhost CLI and start the application
uses: ./.github/actions/nhost-cli
with:
start: true
```
### Set another working directory
```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Nhost CLI
uses: ./.github/actions/nhost-cli
with:
path: examples/react-apollo
start: true
```
### Don't wait for the app to be ready
```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Nhost CLI and start app
uses: ./.github/actions/nhost-cli
with:
start: true
wait: false
```
### Stop the app
```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Start app
uses: ./.github/actions/nhost-cli
with:
start: true
- name: Do something
cmd: echo "do something"
- name: Stop
uses: ./.github/actions/nhost-cli
with:
stop: true
```
### Install a given value of the CLI
```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Nhost CLI
uses: ./.github/actions/nhost-cli
with:
version: v0.8.10
```
### Inject values into nhost/config.yaml
```yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Nhost CLI
uses: ./.github/actions/nhost-cli
with:
config: |
services:
auth:
image: nhost/hasura-auth:0.16.1
```

78
.github/actions/nhost-cli/action.yaml vendored Normal file
View File

@@ -0,0 +1,78 @@
name: Nhost CLI
description: 'Action to install the Nhost CLI and to run an application'
inputs:
start:
description: "Start the application. If false, the application won't be started"
default: 'false'
wait:
description: 'If starting the application, wait until it is ready'
default: 'true'
stop:
description: 'Stop the application'
default: 'false'
path:
description: 'Path to the application'
default: '.'
version:
description: 'Version of the Nhost CLI'
default: 'latest'
config:
description: 'Values to be injected into nhost/config.yaml'
runs:
using: 'composite'
steps:
- name: Check if Nhost CLI is already installed
id: check-nhost-cli
shell: bash
# TODO check if the version is the same
run: |
if [ -z "$(which nhost)" ]
then
echo "installed=false" >> $GITHUB_OUTPUT
else
echo "installed=true" >> $GITHUB_OUTPUT
fi
- name: Install Nhost CLI
if: ${{ steps.check-nhost-cli.outputs.installed == 'false' }}
uses: nick-fields/retry@v2
with:
timeout_minutes: 3
max_attempts: 3
command: bash <(curl --silent -L https://raw.githubusercontent.com/nhost/cli/main/get.sh) ${{ inputs.version }}
- name: Set custom configuration
if: ${{ inputs.config }}
shell: bash
working-directory: ${{ inputs.path }}
run: config="${{ inputs.config }}" yq -i '. *= env(config)' nhost/config.yaml
- name: Start the application
if: ${{ inputs.start == 'true' }}
shell: bash
working-directory: ${{ inputs.path }}
run: nhost dev --no-browser &
- name: Wait for the app to be ready
id: wait
if: ${{ inputs.start == 'true' && inputs.wait == 'true' }}
shell: bash
working-directory: ${{ inputs.path }}
continue-on-error: true
run: |
curl -sSf --connect-timeout 3 \
--max-time 5 \
--retry 300 \
--retry-delay 1 \
--retry-max-time 300 \
--retry-connrefused \
'http://localhost:9695' > /dev/null
- name: Log on failure
if: steps.wait.outcome == 'failure'
shell: bash
working-directory: ${{ inputs.path }}
run: |
nhost logs
exit 1
- name: Stop the application
if: ${{ inputs.stop == 'true' }}
shell: bash
working-directory: ${{ inputs.path }}
run: nhost down

25
.github/labeler.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
dashboard:
- dashboard/**/*
documentation:
- any:
- docs/**/*
- '!docs/docs/reference/docgen/**/*'
examples:
- examples/**/*
sdk:
- packages/**/*
integrations:
- integrations/**/*
react:
- '{packages,examples,integrations}/*react*/**/*'
nextjs:
- '{packages,examples}/*next*/**/*'
vue:
- '{packages,examples,integrations}/*vue*/**/*'

23
.github/renovate.json vendored Normal file
View File

@@ -0,0 +1,23 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
],
"docker-compose": {
"enabled": true
},
"ignoreDeps": [
"pnpm",
"node",
"@types/node"
],
"labels": [
"dependencies"
],
"enabledManagers": [
"npm",
"dockerfile",
"docker-compose",
"github-actions"
]
}

View File

@@ -148,3 +148,33 @@ jobs:
vercel pull --environment=production --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }} vercel pull --environment=production --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
vercel build --prod --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }} vercel build --prod --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
vercel deploy --prebuilt --prod --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }} vercel deploy --prebuilt --prod --token=${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
bump-cli:
name: Bump Dashboard version in the Nhost CLI
runs-on: ubuntu-latest
needs:
- version
- publish-docker
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
repository: nhost/cli
token: ${{ secrets.GH_PAT }}
fetch-depth: 0
- name: Bump version in source code
run: |
IMAGE=$(echo ${{ env.DASHBOARD_PACKAGE }} | sed 's/@\(.\+\)\/\(.\+\)/\1\\\/\2/g')
VERSION="${{ needs.version.outputs.dashboardVersion }}"
EXPRESSION='s/"'$IMAGE':[0-9]\+\.[0-9]\+\.[0-9]\+"/"'$IMAGE':'$VERSION'"/g'
find ./ -type f -exec sed -i -e $EXPRESSION {} \;
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.GH_PAT }}
commit-message: 'chore: bump nhost/dashboard to ${{ needs.version.outputs.dashboardVersion }}'
branch: bump-dashboard-version
delete-branch: true
title: 'chore: bump nhost/dashboard to ${{ needs.version.outputs.dashboardVersion }}'
body: |
This PR bumps the Nhost Dashboard Docker image to version ${{ needs.version.outputs.dashboardVersion }}.

View File

@@ -1,11 +1,9 @@
name: Packages name: Continuous Integration
on: on:
push: push:
branches: [main] branches: [main]
paths-ignore: paths-ignore:
- 'dashboard/**'
- 'docs/**'
- 'assets/**' - 'assets/**'
- '**.md' - '**.md'
- 'LICENSE' - 'LICENSE'
@@ -13,15 +11,16 @@ on:
branches: [main] branches: [main]
types: [opened, synchronize] types: [opened, synchronize]
paths-ignore: paths-ignore:
- 'dashboard/**'
- 'docs/**'
- 'assets/**' - 'assets/**'
- '**.md' - '**.md'
- 'LICENSE' - 'LICENSE'
env: env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: nhost TURBO_TEAM: nhost
NEXT_PUBLIC_ENV: dev
NEXT_TELEMETRY_DISABLED: 1
NEXT_PUBLIC_NHOST_BACKEND_URL: http://localhost:1337
jobs: jobs:
build: build:
name: Build @nhost packages name: Build @nhost packages
@@ -36,21 +35,34 @@ jobs:
with: with:
TURBO_TOKEN: ${{ env.TURBO_TOKEN }} TURBO_TOKEN: ${{ env.TURBO_TOKEN }}
TURBO_TEAM: ${{ env.TURBO_TEAM }} TURBO_TEAM: ${{ env.TURBO_TEAM }}
BUILD: 'all'
- name: Check if the pnpm lockfile changed
id: changed-lockfile
uses: tj-actions/changed-files@v35
with:
files: pnpm-lock.yaml
# * Determine a pnpm filter argument for packages that have been modified.
# * If the lockfile has changed, we don't filter anything in order to run all the e2e tests.
- name: filter packages
id: filter-packages
if: steps.changed-lockfile.outputs.any_changed != 'true' && github.event_name == 'pull_request'
run: echo "filter=${{ format('--filter=...[origin/{0}]', github.base_ref) }}" >> $GITHUB_OUTPUT
# * List packagesthat has an `e2e` script, except the root, and return an array of their name and path # * List packagesthat has an `e2e` script, except the root, and return an array of their name and path
# * In a PR, only include packages that have been modified, and their dependencies # * In a PR, only include packages that have been modified, and their dependencies
- name: List examples with an e2e script - name: List examples with an e2e script
id: set-matrix id: set-matrix
run: | run: |
FILTER_MODIFIED="${{ github.event_name == 'pull_request' && format('--filter=...[origin/{0}]', github.base_ref) || '' }}" PACKAGES=$(pnpm recursive list --depth -1 --parseable --filter='!nhost-root' ${{ steps.filter-packages.outputs.filter }} \
PACKAGES=$(pnpm recursive list --depth -1 --parseable --filter='!nhost-root' $FILTER_MODIFIED \ | xargs -I@ realpath --relative-to=$PWD @ \
| xargs -I@ jq "if (.scripts.e2e | length) != 0 then {name: .name, path: \"@\"} else null end" @/package.json \ | xargs -I@ jq "if (.scripts.e2e | length) != 0 then {name: .name, path: \"@\"} else null end" @/package.json \
| awk "!/null/" \ | awk "!/null/" \
| jq -c --slurp) | jq -c --slurp)
echo "matrix=$PACKAGES" >> $GITHUB_OUTPUT echo "matrix=$PACKAGES" >> $GITHUB_OUTPUT
outputs: outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }} matrix: ${{ steps.set-matrix.outputs.matrix }}
e2e: e2e:
name: 'e2e: ${{ matrix.package.name }}' name: 'e2e (${{ matrix.package.path }})'
needs: build needs: build
if: ${{ needs.build.outputs.matrix != '[]' && needs.build.outputs.matrix != '' }} if: ${{ needs.build.outputs.matrix != '[]' && needs.build.outputs.matrix != '' }}
strategy: strategy:
@@ -70,7 +82,7 @@ jobs:
# * Install Nhost CLI if a `nhost/config.yaml` file is found # * Install Nhost CLI if a `nhost/config.yaml` file is found
- name: Install Nhost CLI - name: Install Nhost CLI
if: hashFiles(format('{0}/nhost/config.yaml', matrix.package.path)) != '' if: hashFiles(format('{0}/nhost/config.yaml', matrix.package.path)) != ''
run: curl -L https://raw.githubusercontent.com/nhost/cli/main/get.sh | bash uses: ./.github/actions/nhost-cli
# * Run the `ci` script of the current package of the matrix. Dependencies build is cached by Turborepo # * Run the `ci` script of the current package of the matrix. Dependencies build is cached by Turborepo
- name: Run e2e test - name: Run e2e test
run: pnpm --filter="${{ matrix.package.name }}" run e2e run: pnpm --filter="${{ matrix.package.name }}" run e2e
@@ -89,6 +101,7 @@ jobs:
path: | path: |
${{format('{0}/cypress/screenshots/**', matrix.package.path)}} ${{format('{0}/cypress/screenshots/**', matrix.package.path)}}
${{format('{0}/cypress/videos/**', matrix.package.path)}} ${{format('{0}/cypress/videos/**', matrix.package.path)}}
unit: unit:
name: Unit tests name: Unit tests
needs: build needs: build
@@ -103,7 +116,7 @@ jobs:
TURBO_TEAM: ${{ env.TURBO_TEAM }} TURBO_TEAM: ${{ env.TURBO_TEAM }}
# * Run every `test` script in the workspace . Dependencies build is cached by Turborepo # * Run every `test` script in the workspace . Dependencies build is cached by Turborepo
- name: Run unit tests - name: Run unit tests
run: pnpm run test run: pnpm run test:all
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v3
with: with:
@@ -113,6 +126,7 @@ jobs:
run: | run: |
echo '### Code coverage' >> $GITHUB_STEP_SUMMARY echo '### Code coverage' >> $GITHUB_STEP_SUMMARY
echo 'Visit [codecov](https://app.codecov.io/gh/nhost/nhost/) to see the code coverage reports' >> $GITHUB_STEP_SUMMARY echo 'Visit [codecov](https://app.codecov.io/gh/nhost/nhost/) to see the code coverage reports' >> $GITHUB_STEP_SUMMARY
lint: lint:
name: Lint name: Lint
needs: build needs: build
@@ -127,4 +141,4 @@ jobs:
TURBO_TEAM: ${{ env.TURBO_TEAM }} TURBO_TEAM: ${{ env.TURBO_TEAM }}
# * Run every `lint` script in the workspace . Dependencies build is cached by Turborepo # * Run every `lint` script in the workspace . Dependencies build is cached by Turborepo
- name: Lint - name: Lint
run: pnpm run lint run: pnpm run lint:all

View File

@@ -1,15 +0,0 @@
name: Add contributors
on:
push:
branches:
- main
jobs:
contrib-readme-job:
runs-on: ubuntu-latest
name: A job to automate contrib in readme
steps:
- name: Contribute List
uses: akhilmhdh/contributors-readme-action@v2.3.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -2,24 +2,17 @@ name: 'Dashboard'
on: on:
workflow_call: workflow_call:
pull_request:
branches: [main]
types: [opened, synchronize]
paths:
- 'packages/**'
- 'dashboard/**'
env: env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: nhost TURBO_TEAM: nhost
NEXT_PUBLIC_ENV: dev
NEXT_TELEMETRY_DISABLED: 1
NEXT_PUBLIC_NHOST_BACKEND_URL: http://localhost:1337
jobs: jobs:
build: build:
name: Build name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
NEXT_PUBLIC_ENV: dev
NEXT_TELEMETRY_DISABLED: 1
NEXT_PUBLIC_NHOST_BACKEND_URL: http://localhost:1337
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install Node and dependencies - name: Install Node and dependencies
@@ -33,10 +26,6 @@ jobs:
tests: tests:
name: Tests name: Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
NEXT_PUBLIC_ENV: dev
NEXT_TELEMETRY_DISABLED: 1
NEXT_PUBLIC_NHOST_BACKEND_URL: http://localhost:1337
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install Node and dependencies - name: Install Node and dependencies
@@ -50,10 +39,6 @@ jobs:
lint: lint:
name: Lint name: Lint
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
NEXT_PUBLIC_ENV: dev
NEXT_TELEMETRY_DISABLED: 1
NEXT_PUBLIC_NHOST_BACKEND_URL: http://localhost:1337
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install Node and dependencies - name: Install Node and dependencies

15
.github/workflows/labeler.yaml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: 'Pull Request Labeler'
on:
- pull_request_target
jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
with:
repo-token: '${{ secrets.GH_PAT }}'
sync-labels: ''

89
.github/workflows/renovate.yaml vendored Normal file
View File

@@ -0,0 +1,89 @@
name: Renovate
on:
pull_request:
branches: [main]
types: [closed]
paths-ignore:
- 'assets/**'
- '**.md'
- 'LICENSE'
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: nhost
jobs:
renovate-changeset:
name: Add changeset
if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'renovate/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.GH_PAT }}
# * Install Node and dependencies. Package downloads will be cached for the next jobs.
- name: Install Node and dependencies
uses: ./.github/actions/install-dependencies
with:
TURBO_TOKEN: ${{ env.TURBO_TOKEN }}
TURBO_TEAM: ${{ env.TURBO_TEAM }}
BUILD: 'none'
- name: Determine bumps
id: bumps
run: |
LAST_NON_PR_SHA=$(git log --no-merges main origin/${{ github.head_ref }} --format=format:%h -- | head -2 | tail -1)
echo "result<<EOF" >> $GITHUB_OUTPUT
pnpm recursive list --depth -1 --parseable \
--filter='!nhost-root' \
--filter=[$LAST_NON_PR_SHA] \
| xargs -I@ jq ".name" @/package.json \
| sort \
| uniq -u \
| awk '$0=$0": patch"' \
>> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT
- name: Install dictionary
if: steps.bumps.outputs.result != ''
run: sudo apt-get install wbritish
- name: Generate changeset file name
id: file_name
if: steps.bumps.outputs.result != ''
run: |
FILE_NAME=$(shuf -n 3 /usr/share/dict/words | tr '\n' '-' | sed 's/-$//' | sed 's/'"'"'s//g' | tr '[:upper:]' '[:lower:]')
echo "result=./.changeset/${FILE_NAME}.md" >> $GITHUB_OUTPUT
- name: Create changeset file
if: steps.bumps.outputs.result != ''
run: |
cat <<EOF > ${{ steps.file_name.outputs.result }}
---
${{ steps.bumps.outputs.result }}
---
${{ github.event.pull_request.title }}
EOF
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.GH_PAT }}
commit-message: ${{ github.event.pull_request.title }}
branch: renovate-changesets
delete-branch: true
title: 'chore: create changesest from Renovate bumps'
labels: |
dependencies
body: |
This PR creates the changesets from the Renovate dependencies that have been merged to main.
- name: Enable Pull Request Automerge
if: steps.cpr.outputs.pull-request-operation == 'created'
uses: peter-evans/enable-pull-request-automerge@v2
with:
token: ${{ secrets.GH_PAT }}
pull-request-number: ${{ steps.cpr.outputs.pull-request-number }}
- name: Auto approve
if: steps.cpr.outputs.pull-request-operation == 'created'
uses: juliangruber/approve-pull-request-action@v2
with:
github-token: ${{ secrets.GH_PAT }}
number: ${{ steps.cpr.outputs.pull-request-number }}

View File

@@ -0,0 +1,104 @@
name: Test Nhost CLI action
on:
pull_request:
branches: [main]
types: [opened, synchronize]
paths:
- '.github/actions/nhost-cli/**'
- '!.github/actions/nhost-cli/**/*.md'
jobs:
install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install the Nhost CLI
uses: ./.github/actions/nhost-cli
- name: should succeed running the nhost command
run: nhost
start:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install the Nhost CLI and start the application
uses: ./.github/actions/nhost-cli
with:
path: packages/nhost-js
start: true
- name: should be running
run: curl -sSf 'http://localhost:9695' > /dev/null
stop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install the Nhost CLI, start and stop the application
uses: ./.github/actions/nhost-cli
with:
path: packages/nhost-js
start: true
stop: true
- name: should have no live docker container
run: |
if [ -z "docker ps -q" ]; then
echo "Some docker containers are still running"
docker ps
exit 1
fi
wait:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install the Nhost CLI and start the application
uses: ./.github/actions/nhost-cli
with:
path: packages/nhost-js
start: true
wait: false
- name: should not be ready
run: curl -sSf -o /dev/null 'http://localhost:9695' > /dev/null && exit 1 || true
- name: should eventually be ready
run: |
curl -sSf --connect-timeout 3 \
--max-time 5 \
--retry 300 \
--retry-delay 1 \
--retry-max-time 300 \
--retry-connrefused \
'http://localhost:9695' > /dev/null
config:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install the Nhost CLI and run the application
uses: ./.github/actions/nhost-cli
with:
path: packages/nhost-js
start: true
config: |
services:
auth:
image: nhost/hasura-auth:0.15.0
- name: should find the injected hasura-auth version
run: |
VERSION=$(curl -sSf 'http://localhost:1337/v1/auth/version')
EXPECTED_VERSION='{"version":"v0.15.0"}'
if [ "$VERSION" != "$EXPECTED_VERSION" ]; then
echo "Expected version $EXPECTED_VERSION but got $VERSION"
exit 1
fi
version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install the Nhost CLI
uses: ./.github/actions/nhost-cli
with:
version: v0.8.10
- name: should find the correct version
run: nhost version | head -n 1 | grep v0.8.10 || exit 1

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
prefer-workspace-packages = true

View File

@@ -14,4 +14,5 @@ package.json
tsconfig.json tsconfig.json
tsconfig.*.json tsconfig.*.json
*.d.ts *.d.ts
.next .next
**/pnpm-lock.yaml

435
README.md
View File

@@ -101,14 +101,17 @@ Nhost is frontend agnostic, which means Nhost works with all frontend frameworks
## Nhost Clients ## Nhost Clients
- [JavaScript/TypeScript SDK](https://docs.nhost.io/reference/javascript) - [JavaScript/TypeScript](https://docs.nhost.io/reference/javascript)
- [Dart and Flutter SDK](https://github.com/nhost/nhost-dart) - [Dart and Flutter](https://github.com/nhost/nhost-dart)
- [Nhost React](https://docs.nhost.io/reference/react) - [React](https://docs.nhost.io/reference/react)
- [Nhost Next.js](https://docs.nhost.io/reference/nextjs) - [Next.js](https://docs.nhost.io/reference/nextjs)
- [Nhost Vue](https://docs.nhost.io/reference/vue) - [Vue](https://docs.nhost.io/reference/vue)
## Integrations ## Integrations
- [Apollo](./integrations/apollo#nhostapollo)
- [React Apollo](./integrations/react-apollo#nhostreact-apollo)
- [React URQL](./integrations/react-urql#nhostreact-urql)
- [Stripe GraphQL API](./integrations/stripe-graphql-js#nhoststripe-graphql-js) - [Stripe GraphQL API](./integrations/stripe-graphql-js#nhoststripe-graphql-js)
- [Google Translation GraphQL API](./integrations/google-translation#nhostgoogle-translation) - [Google Translation GraphQL API](./integrations/google-translation#nhostgoogle-translation)
@@ -127,8 +130,8 @@ Also, follow Nhost on [GitHub Discussions](https://github.com/nhost/nhost/discus
This repository, and most of our other open source projects, are licensed under the MIT license. This repository, and most of our other open source projects, are licensed under the MIT license.
<a href="https://runacap.com/ross-index/q1-2022/" target="_blank" rel="noopener"> <a href="https://runacap.com/ross-index/" target="_blank" rel="noopener" >
<img style="width: 260px; height: 56px" src="https://runacap.com/wp-content/uploads/2022/06/ROSS_badge_black_Q1_2022.svg" alt="ROSS Index - Fastest Growing Open-Source Startups in Q1 2022 | Runa Capital" width="260" height="56" /> <img style="width: 260px; height: 56px" src="https://runacap.com/wp-content/uploads/2022/06/ROSS_black_edition_badge.svg" alt="ROSS Index - Fastest Growing Open-Source Startups | Runa Capital" width="260" height="56" />
</a> </a>
### How to contribute ### How to contribute
@@ -141,416 +144,8 @@ Here are some ways of contributing to making Nhost better:
### Contributors ### Contributors
<!-- readme: contributors -start --> <a href="https://github.com/nhost/nhost/graphs/contributors">
<table> <p align="center">
<tr> <img width="720" src="https://contrib.rocks/image?repo=nhost/nhost" alt="A table of avatars from the project's contributors" />
<td align="center"> </p>
<a href="https://github.com/plmercereau"> </a>
<img src="https://avatars.githubusercontent.com/u/24897252?v=4" width="100;" alt="plmercereau"/>
<br />
<sub><b>Pilou</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/elitan">
<img src="https://avatars.githubusercontent.com/u/331818?v=4" width="100;" alt="elitan"/>
<br />
<sub><b>Johan Eliasson</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/szilarddoro">
<img src="https://avatars.githubusercontent.com/u/310881?v=4" width="100;" alt="szilarddoro"/>
<br />
<sub><b>Szilárd Dóró</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/nunopato">
<img src="https://avatars.githubusercontent.com/u/1523504?v=4" width="100;" alt="nunopato"/>
<br />
<sub><b>Nuno Pato</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gdangelo">
<img src="https://avatars.githubusercontent.com/u/4352286?v=4" width="100;" alt="gdangelo"/>
<br />
<sub><b>Grégory D'Angelo</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ejkkan">
<img src="https://avatars.githubusercontent.com/u/32518962?v=4" width="100;" alt="ejkkan"/>
<br />
<sub><b>Erik Magnusson</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/guicurcio">
<img src="https://avatars.githubusercontent.com/u/20285232?v=4" width="100;" alt="guicurcio"/>
<br />
<sub><b>Guido Curcio</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/subatuba21">
<img src="https://avatars.githubusercontent.com/u/34824571?v=4" width="100;" alt="subatuba21"/>
<br />
<sub><b>Subha Das</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/sebagudelo">
<img src="https://avatars.githubusercontent.com/u/43288271?v=4" width="100;" alt="sebagudelo"/>
<br />
<sub><b>Sebagudelo</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/mrinalwahal">
<img src="https://avatars.githubusercontent.com/u/9859731?v=4" width="100;" alt="mrinalwahal"/>
<br />
<sub><b>Mrinal Wahal</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/timpratim">
<img src="https://avatars.githubusercontent.com/u/32492961?v=4" width="100;" alt="timpratim"/>
<br />
<sub><b>Pratim</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/chrtze">
<img src="https://avatars.githubusercontent.com/u/3797215?v=4" width="100;" alt="chrtze"/>
<br />
<sub><b>Christopher Möller</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/GavanWilhite">
<img src="https://avatars.githubusercontent.com/u/2085119?v=4" width="100;" alt="GavanWilhite"/>
<br />
<sub><b>Gavan Wilhite</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/FuzzyReason">
<img src="https://avatars.githubusercontent.com/u/62517920?v=4" width="100;" alt="FuzzyReason"/>
<br />
<sub><b>Vadim Smirnov</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/macmac49">
<img src="https://avatars.githubusercontent.com/u/831190?v=4" width="100;" alt="macmac49"/>
<br />
<sub><b>Macmac49</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/subhendukundu">
<img src="https://avatars.githubusercontent.com/u/20059141?v=4" width="100;" alt="subhendukundu"/>
<br />
<sub><b>Subhendu Kundu</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/heygambo">
<img src="https://avatars.githubusercontent.com/u/449438?v=4" width="100;" alt="heygambo"/>
<br />
<sub><b>Christian Gambardella</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/dbarrosop">
<img src="https://avatars.githubusercontent.com/u/6246622?v=4" width="100;" alt="dbarrosop"/>
<br />
<sub><b>David Barroso</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/hajek-raven">
<img src="https://avatars.githubusercontent.com/u/7288737?v=4" width="100;" alt="hajek-raven"/>
<br />
<sub><b>Filip Hájek</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/MelodicCrypter">
<img src="https://avatars.githubusercontent.com/u/18341500?v=4" width="100;" alt="MelodicCrypter"/>
<br />
<sub><b>Hugh Caluscusin</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jerryjappinen">
<img src="https://avatars.githubusercontent.com/u/1101002?v=4" width="100;" alt="jerryjappinen"/>
<br />
<sub><b>Jerry Jäppinen</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/mdp18">
<img src="https://avatars.githubusercontent.com/u/11698527?v=4" width="100;" alt="mdp18"/>
<br />
<sub><b>Max</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/mustafa-hanif">
<img src="https://avatars.githubusercontent.com/u/30019262?v=4" width="100;" alt="mustafa-hanif"/>
<br />
<sub><b>Mustafa Hanif</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/nbourdin">
<img src="https://avatars.githubusercontent.com/u/5602476?v=4" width="100;" alt="nbourdin"/>
<br />
<sub><b>Nicolas Bourdin</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/piromsurang">
<img src="https://avatars.githubusercontent.com/u/17776837?v=4" width="100;" alt="piromsurang"/>
<br />
<sub><b>Piromsurang Rungserichai</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Savinvadim1312">
<img src="https://avatars.githubusercontent.com/u/16936043?v=4" width="100;" alt="Savinvadim1312"/>
<br />
<sub><b>Savin Vadim</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Svarto">
<img src="https://avatars.githubusercontent.com/u/24279217?v=4" width="100;" alt="Svarto"/>
<br />
<sub><b>Svarto</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/muttenzer">
<img src="https://avatars.githubusercontent.com/u/49474412?v=4" width="100;" alt="muttenzer"/>
<br />
<sub><b>Muttenzer</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/alexander-mart">
<img src="https://avatars.githubusercontent.com/u/14993551?v=4" width="100;" alt="alexander-mart"/>
<br />
<sub><b>Alexander Mart</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ahmic">
<img src="https://avatars.githubusercontent.com/u/13452362?v=4" width="100;" alt="ahmic"/>
<br />
<sub><b>Amir Ahmic</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/akd-io">
<img src="https://avatars.githubusercontent.com/u/30059155?v=4" width="100;" alt="akd-io"/>
<br />
<sub><b>Anders Kjær Damgaard</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Sonichigo">
<img src="https://avatars.githubusercontent.com/u/53110238?v=4" width="100;" alt="Sonichigo"/>
<br />
<sub><b>Animesh Pathak</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/chrisli-03">
<img src="https://avatars.githubusercontent.com/u/11177048?v=4" width="100;" alt="chrisli-03"/>
<br />
<sub><b>Chris</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/massless">
<img src="https://avatars.githubusercontent.com/u/44389?v=4" width="100;" alt="massless"/>
<br />
<sub><b>Chris Wetherell</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/rustyb">
<img src="https://avatars.githubusercontent.com/u/53086?v=4" width="100;" alt="rustyb"/>
<br />
<sub><b>Colin Broderick</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/daguitosama">
<img src="https://avatars.githubusercontent.com/u/34744883?v=4" width="100;" alt="daguitosama"/>
<br />
<sub><b>Dago</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/dminkovsky">
<img src="https://avatars.githubusercontent.com/u/218725?v=4" width="100;" alt="dminkovsky"/>
<br />
<sub><b>Dmitry Minkovsky</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/dohomi">
<img src="https://avatars.githubusercontent.com/u/489221?v=4" width="100;" alt="dohomi"/>
<br />
<sub><b>Dominic Garms</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gaurav1999">
<img src="https://avatars.githubusercontent.com/u/20752142?v=4" width="100;" alt="gaurav1999"/>
<br />
<sub><b>Gaurav Agrawal</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/alveshelio">
<img src="https://avatars.githubusercontent.com/u/8176422?v=4" width="100;" alt="alveshelio"/>
<br />
<sub><b>Helio Alves</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/nkhdo">
<img src="https://avatars.githubusercontent.com/u/26102306?v=4" width="100;" alt="nkhdo"/>
<br />
<sub><b>Hoang Do</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/eltociear">
<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="100;" alt="eltociear"/>
<br />
<sub><b>Ikko Ashimine</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/jladuval">
<img src="https://avatars.githubusercontent.com/u/1935359?v=4" width="100;" alt="jladuval"/>
<br />
<sub><b>Jacob Duval</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/leothorp">
<img src="https://avatars.githubusercontent.com/u/12928449?v=4" width="100;" alt="leothorp"/>
<br />
<sub><b>Leo Thorp</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/LucasBois1">
<img src="https://avatars.githubusercontent.com/u/44686060?v=4" width="100;" alt="LucasBois1"/>
<br />
<sub><b>Lucas Bois</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/MarcelloTheArcane">
<img src="https://avatars.githubusercontent.com/u/21159570?v=4" width="100;" alt="MarcelloTheArcane"/>
<br />
<sub><b>Max Reynolds</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/nachoaldamav">
<img src="https://avatars.githubusercontent.com/u/22749943?v=4" width="100;" alt="nachoaldamav"/>
<br />
<sub><b>Nacho Aldama</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ghoshnirmalya">
<img src="https://avatars.githubusercontent.com/u/6391763?v=4" width="100;" alt="ghoshnirmalya"/>
<br />
<sub><b>Nirmalya Ghosh</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/quentin-decre">
<img src="https://avatars.githubusercontent.com/u/1137511?v=4" width="100;" alt="quentin-decre"/>
<br />
<sub><b>Quentin Decré</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/elephant3">
<img src="https://avatars.githubusercontent.com/u/48279149?v=4" width="100;" alt="elephant3"/>
<br />
<sub><b>Siarhei Lipchyk</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/altschuler">
<img src="https://avatars.githubusercontent.com/u/956928?v=4" width="100;" alt="altschuler"/>
<br />
<sub><b>Simon Altschuler</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/atapas">
<img src="https://avatars.githubusercontent.com/u/3633137?v=4" width="100;" alt="atapas"/>
<br />
<sub><b>Tapas Adhikary</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/uulwake">
<img src="https://avatars.githubusercontent.com/u/22399181?v=4" width="100;" alt="uulwake"/>
<br />
<sub><b>Ulrich Wake</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/kwarabei">
<img src="https://avatars.githubusercontent.com/u/102731455?v=4" width="100;" alt="kwarabei"/>
<br />
<sub><b>Vadim</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/TheRedLancer">
<img src="https://avatars.githubusercontent.com/u/58493767?v=4" width="100;" alt="TheRedLancer"/>
<br />
<sub><b>Zach Burnaby</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/komninoschat">
<img src="https://avatars.githubusercontent.com/u/29049104?v=4" width="100;" alt="komninoschat"/>
<br />
<sub><b>Komninos</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/meesvandongen">
<img src="https://avatars.githubusercontent.com/u/35409045?v=4" width="100;" alt="meesvandongen"/>
<br />
<sub><b>Meesvandongen</b></sub>
</a>
</td></tr>
</table>
<!-- readme: contributors -end -->

View File

@@ -19,7 +19,9 @@ module.exports = {
'*.spec.ts', '*.spec.ts',
'*.spec.tsx', '*.spec.tsx',
'tests/**/*.ts', 'tests/**/*.ts',
'tests/**/*.d.ts' 'tests/**/*.d.ts',
'e2e/**/*.ts',
'e2e/**/*.d.ts'
], ],
plugins: ['@typescript-eslint', 'cypress'], plugins: ['@typescript-eslint', 'cypress'],
extends: ['plugin:cypress/recommended'], extends: ['plugin:cypress/recommended'],

View File

@@ -1,6 +1,4 @@
module.exports = { module.exports = {
'(packages|integrations)/(docgen|hasura-auth-js|hasura-storage-js|nextjs|nhost-js|react|core|vue)/src/**/*.{js,ts,jsx,tsx}':
['pnpm docgen', 'git add docs'],
'(nhost-cloud.yaml|**/nhost/config.yaml)': () => [ '(nhost-cloud.yaml|**/nhost/config.yaml)': () => [
'pnpm sync-versions', 'pnpm sync-versions',
"git add ':(glob)**/nhost/config.yaml'" "git add ':(glob)**/nhost/config.yaml'"

View File

@@ -28,22 +28,44 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true, "esModuleInterop": true,
"sourceMap": true, "sourceMap": true,
"types": ["node"], "types": [
"node"
],
"typeRoots": [ "typeRoots": [
"./node_modules/@types", "**/*/dist", "**/*/build", "**/*/.next", "**/*/umd" "./node_modules/@types",
"**/*/dist",
"**/*/build",
"**/*/.next",
"**/*/umd"
], ],
"paths": { "paths": {
"@nhost/apollo": ["../packages/apollo/src/index.ts"], "@nhost/apollo": [
"@nhost/core": ["../packages/core/src/index.ts"], "../integrations/apollo/src/index.ts"
"@nhost/docgen": ["../packages/docgen/src/index.ts"], ],
"@nhost/hasura-auth-js": ["../packages/hasura-auth-js/src/index.ts"], "@nhost/docgen": [
"@nhost/hasura-storage-js": ["../packages/hasura-storage-js/src/index.ts"], "../packages/docgen/src/index.ts"
"@nhost/nextjs": ["../packages/nextjs/src/index.ts"], ],
"@nhost/nhost-js": ["../packages/nhost-js/src/index.ts"], "@nhost/hasura-auth-js": [
"@nhost/react": ["../packages/react/src/index.ts"], "../packages/hasura-auth-js/src/index.ts"
"@nhost/react-apollo": ["../packages/react-apollo/src/index.ts"], ],
"@nhost/react-auth": ["../packages/react-auth/src/index.ts"], "@nhost/hasura-storage-js": [
"@nhost/vue": ["../packages/vue/src/index.ts"] "../packages/hasura-storage-js/src/index.ts"
],
"@nhost/nextjs": [
"../packages/nextjs/src/index.ts"
],
"@nhost/nhost-js": [
"../packages/nhost-js/src/index.ts"
],
"@nhost/react": [
"../packages/react/src/index.ts"
],
"@nhost/react-apollo": [
"../integrations/react-apollo/src/index.ts"
],
"@nhost/vue": [
"../packages/vue/src/index.ts"
]
} }
}, },
"exclude": [ "exclude": [

View File

@@ -1,3 +1,4 @@
import replace from '@rollup/plugin-replace'
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
@@ -18,7 +19,9 @@ export default defineConfig({
tsconfigPaths(), tsconfigPaths(),
dts({ dts({
exclude: ['**/*.spec.ts', '**/*.test.ts', '**/tests/**'], exclude: ['**/*.spec.ts', '**/*.test.ts', '**/tests/**'],
entryRoot: 'src' entryRoot: 'src',
// Was defaulting to true until version 1.7
skipDiagnostics: true
}) })
], ],
test: { test: {
@@ -41,6 +44,12 @@ export default defineConfig({
}, },
rollupOptions: { rollupOptions: {
external: (id) => deps.some((dep) => id.startsWith(dep)), external: (id) => deps.some((dep) => id.startsWith(dep)),
plugins: [
replace({
preventAssignment: true,
'exports.hasOwnProperty(': 'Object.prototype.hasOwnProperty.call(exports,'
})
],
output: { output: {
globals: { globals: {
graphql: 'graphql', graphql: 'graphql',

View File

@@ -6,6 +6,7 @@ module.exports = {
'@storybook/addon-links', '@storybook/addon-links',
'@storybook/addon-essentials', '@storybook/addon-essentials',
'@storybook/addon-interactions', '@storybook/addon-interactions',
'storybook-addon-next-router',
{ {
/** /**
* Fix Storybook issue with PostCSS@8 * Fix Storybook issue with PostCSS@8
@@ -38,4 +39,10 @@ module.exports = {
}, },
}; };
}, },
env: (config) => ({
...config,
NEXT_PUBLIC_ENV: 'dev',
NEXT_PUBLIC_NHOST_BACKEND_URL: 'http://localhost:1337',
NEXT_PUBLIC_NHOST_PLATFORM: 'false',
}),
}; };

View File

@@ -2,9 +2,25 @@ import '@fontsource/inter';
import '@fontsource/inter/500.css'; import '@fontsource/inter/500.css';
import '@fontsource/inter/700.css'; import '@fontsource/inter/700.css';
import { CssBaseline, ThemeProvider } from '@mui/material'; import { CssBaseline, ThemeProvider } from '@mui/material';
import { NhostApolloProvider } from '@nhost/react-apollo';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Buffer } from 'buffer';
import { initialize, mswDecorator } from 'msw-storybook-addon';
import { RouterContext } from 'next/dist/shared/lib/router-context';
import '../src/styles/globals.css';
import defaultTheme from '../src/theme/default'; import defaultTheme from '../src/theme/default';
global.Buffer = Buffer;
initialize({ onUnhandledRequest: 'bypass' });
const queryClient = new QueryClient();
export const parameters = { export const parameters = {
nextRouter: {
Provider: RouterContext.Provider,
isReady: true,
},
actions: { argTypesRegex: '^on[A-Z].*' }, actions: { argTypesRegex: '^on[A-Z].*' },
controls: { controls: {
matchers: { matchers: {
@@ -14,11 +30,25 @@ export const parameters = {
}, },
}; };
export const withMuiTheme = (Story) => ( export const decorators = [
<ThemeProvider theme={defaultTheme}> (Story) => (
<CssBaseline /> <ThemeProvider theme={defaultTheme}>
<Story /> <CssBaseline />
</ThemeProvider> <Story />
); </ThemeProvider>
),
export const decorators = [withMuiTheme]; (Story) => (
<QueryClientProvider client={queryClient}>
<Story />
</QueryClientProvider>
),
(Story) => (
<NhostApolloProvider
fetchPolicy="cache-first"
graphqlUrl="http://localhost:1337/v1/graphql"
>
<Story />
</NhostApolloProvider>
),
mswDecorator,
];

View File

@@ -1,5 +1,127 @@
# @nhost/dashboard # @nhost/dashboard
## 0.8.0
### Minor Changes
- 9a1aa7bb: add functions to the log dashboard
- f29abe62: feat(dashboard): Users Management v2
### Patch Changes
- 7766624b: feat(dashboard): add JWT secret editor modal
- @nhost/react-apollo@4.12.1
- @nhost/nextjs@1.12.1
## 0.7.13
### Patch Changes
- dd0738d5: fix(dashboard): provisioning status polling
## 0.7.12
### Patch Changes
- b21222b3: chore(deps): update dependency @types/node to v16
- 9e0486a3: fix(dashboard): close modals when navigating
- Updated dependencies [b21222b3]
- Updated dependencies [65687bee]
- Updated dependencies [54df0df4]
- @nhost/nextjs@1.12.0
- @nhost/react-apollo@4.12.0
## 0.7.11
### Patch Changes
- d6527122: fix(dashboard): use correct service URLs
## 0.7.10
### Patch Changes
- Updated dependencies [57db5b83]
- @nhost/nextjs@1.11.0
- @nhost/nhost-js@1.7.0
- @nhost/react@0.17.0
- @nhost/react-apollo@4.11.0
## 0.7.9
### Patch Changes
- a6d31dc2: fix(dashboard): don't break the UI when project is not loaded yet
## 0.7.8
### Patch Changes
- 7f251111: Use `NhostProvider` instead of `NhostReactProvider` and `NhostNextProvider`
`NhostReactProvider` and `NhostNextProvider` are now deprecated
- f4d70f88: fix(dashboard): do not break when region is nullish
- 4a9471cc: Windows Live Provider displayed link updated to match backend url
- 594488e4: fix(dashboard): do not show error when submitting Apple provider settings
- Updated dependencies [7f251111]
- @nhost/nextjs@1.10.0
- @nhost/react@0.16.0
- @nhost/react-apollo@4.10.0
## 0.7.7
### Patch Changes
- 80b604ad: fix(dashboard): use correct Hasura slug
## 0.7.6
### Patch Changes
- 2d2beb53: fix(dashboard): prevent error on GraphQL page
- ac8efcbd: chore(dashboard): deprecate old DNS name
## 0.7.5
### Patch Changes
- 132a4f4b: chore(dashboard): remove unused dependencies
- 132a4f4b: chore(deps): synchronize @types/react-dom and @types/react versions
- db57572f: fix(dashboard): correct section paddings when no env vars
- Updated dependencies [132a4f4b]
- @nhost/react@0.15.2
- @nhost/react-apollo@4.9.2
- @nhost/nextjs@1.9.3
## 0.7.4
### Patch Changes
- 34d85e54: chore(deps): update dependency critters to ^0.0.16
- 9b93cf95: chore(deps): update dependency @netlify/functions to ^0.11.0
- e0439030: chore(deps): update dependency @types/react-dom to v18.0.9
- Updated dependencies [82124329]
- @nhost/nextjs@1.9.2
## 0.7.3
### Patch Changes
- a1193da4: fix(dashboard): remove character limit from env var inputs
## 0.7.2
### Patch Changes
- 44f13f62: chore(dashboard): cleanup unused files
## 0.7.1
### Patch Changes
- e01cb2ed: chore(dashboard): change settings sidebar menu item density
## 0.7.0 ## 0.7.0
### Minor Changes ### Minor Changes

View File

@@ -37,6 +37,14 @@ NEXT_PUBLIC_ENV=dev
NEXT_PUBLIC_NHOST_PLATFORM=false NEXT_PUBLIC_NHOST_PLATFORM=false
``` ```
### Storybook
Components are documented using [Storybook](https://storybook.js.org/). To run Storybook, run the following command:
```bash
pnpm storybook
```
### Full list of environment variables ### Full list of environment variables
| Name | Description | | Name | Description |

View File

@@ -66,6 +66,11 @@ module.exports = withBundleAnalyzer({
destination: '/:workspaceSlug/:appSlug/settings/environment-variables', destination: '/:workspaceSlug/:appSlug/settings/environment-variables',
permanent: true, permanent: true,
}, },
{
source: '/:workspaceSlug/:appSlug/users/:userId',
destination: '/:workspaceSlug/:appSlug/users?userId=:userId',
permanent: true,
},
]; ];
}, },
}); });

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nhost/dashboard", "name": "@nhost/dashboard",
"version": "0.7.0", "version": "0.8.0",
"private": true, "private": true,
"scripts": { "scripts": {
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
@@ -13,11 +13,11 @@
"codegen": "graphql-codegen --config graphql.config.yaml --errors-only", "codegen": "graphql-codegen --config graphql.config.yaml --errors-only",
"nhost:dev": "nhost dev -d", "nhost:dev": "nhost dev -d",
"format": "prettier --write \"src/**/*.{js,ts,tsx,jsx,json,md}\" --plugin-search-dir=.", "format": "prettier --write \"src/**/*.{js,ts,tsx,jsx,json,md}\" --plugin-search-dir=.",
"storybook": "start-storybook -p 6006", "storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook" "build-storybook": "build-storybook"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.6.2", "@apollo/client": "^3.7.3",
"@codemirror/language": "^6.3.0", "@codemirror/language": "^6.3.0",
"@emotion/cache": "^11.10.5", "@emotion/cache": "^11.10.5",
"@emotion/react": "^11.10.5", "@emotion/react": "^11.10.5",
@@ -25,7 +25,7 @@
"@emotion/styled": "^11.10.5", "@emotion/styled": "^11.10.5",
"@fontsource/inter": "^4.5.14", "@fontsource/inter": "^4.5.14",
"@fontsource/roboto-mono": "^4.5.8", "@fontsource/roboto-mono": "^4.5.8",
"@graphiql/react": "^0.14.0", "@graphiql/react": "^0.15.0",
"@graphiql/toolkit": "^0.8.0", "@graphiql/toolkit": "^0.8.0",
"@headlessui/react": "^1.6.5", "@headlessui/react": "^1.6.5",
"@heroicons/react": "^1.0.6", "@heroicons/react": "^1.0.6",
@@ -34,12 +34,11 @@
"@mui/material": "^5.10.14", "@mui/material": "^5.10.14",
"@mui/system": "^5.10.14", "@mui/system": "^5.10.14",
"@mui/x-date-pickers": "^5.0.8", "@mui/x-date-pickers": "^5.0.8",
"@nhost/core": "^0.9.4", "@nhost/nextjs": "workspace:*",
"@nhost/nextjs": "^1.9.1", "@nhost/react-apollo": "workspace:*",
"@nhost/nhost-js": "^1.6.2",
"@nhost/react": "^0.15.1",
"@nhost/react-apollo": "^4.9.1",
"@segment/snippet": "^4.15.3", "@segment/snippet": "^4.15.3",
"@stripe/react-stripe-js": "^1.10.0",
"@stripe/stripe-js": "^1.35.0",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",
"@tanstack/react-query": "^4.16.1", "@tanstack/react-query": "^4.16.1",
"@tanstack/react-table": "^8.5.30", "@tanstack/react-table": "^8.5.30",
@@ -51,21 +50,20 @@
"cross-fetch": "^3.1.5", "cross-fetch": "^3.1.5",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"generate-password": "^1.7.0", "generate-password": "^1.7.0",
"graphiql": "^2.1.0", "graphiql": "^2.2.0",
"graphql": "^16.6.0", "graphql": "^16.6.0",
"graphql-request": "^4.3.0", "graphql-request": "^4.3.0",
"graphql-tag": "^2.12.6", "graphql-tag": "^2.12.6",
"graphql-ws": "^5.11.2", "graphql-ws": "^5.11.2",
"jsonwebtoken": "^8.5.1",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"next": "^12.3.1", "next": "^12.3.1",
"next-seo": "^5.14.1", "next-seo": "^5.14.1",
"node-pg-format": "^1.3.5", "node-pg-format": "^1.3.5",
"pluralize": "^8.0.0", "pluralize": "^8.0.0",
"prettysize": "^2.0.0", "prettysize": "^2.0.0",
"randomstring": "^1.2.3",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-error-boundary": "^3.1.4",
"react-hook-form": "^7.39.5", "react-hook-form": "^7.39.5",
"react-hot-toast": "^2.4.0", "react-hot-toast": "^2.4.0",
"react-is": "17.0.2", "react-is": "17.0.2",
@@ -75,7 +73,6 @@
"react-table": "^7.8.0", "react-table": "^7.8.0",
"sharp": "^0.31.2", "sharp": "^0.31.2",
"slugify": "^1.6.5", "slugify": "^1.6.5",
"smartlook-client": "^6.0.0",
"stripe": "^10.17.0", "stripe": "^10.17.0",
"tailwind-merge": "^1.8.0", "tailwind-merge": "^1.8.0",
"utility-types": "^3.10.0", "utility-types": "^3.10.0",
@@ -90,43 +87,36 @@
"@graphql-codegen/typescript-graphql-request": "^4.5.1", "@graphql-codegen/typescript-graphql-request": "^4.5.1",
"@graphql-codegen/typescript-operations": "^2.5.1", "@graphql-codegen/typescript-operations": "^2.5.1",
"@graphql-codegen/typescript-react-apollo": "^3.3.1", "@graphql-codegen/typescript-react-apollo": "^3.3.1",
"@netlify/functions": "^0.7.2",
"@next/bundle-analyzer": "^12.3.1", "@next/bundle-analyzer": "^12.3.1",
"@storybook/addon-actions": "^6.5.13", "@storybook/addon-actions": "^6.5.14",
"@storybook/addon-essentials": "^6.5.13", "@storybook/addon-essentials": "^6.5.14",
"@storybook/addon-interactions": "^6.5.13", "@storybook/addon-interactions": "^6.5.14",
"@storybook/addon-links": "^6.5.13", "@storybook/addon-links": "^6.5.14",
"@storybook/addon-postcss": "^2.0.0", "@storybook/addon-postcss": "^2.0.0",
"@storybook/builder-webpack5": "^6.5.13", "@storybook/builder-webpack5": "^6.5.14",
"@storybook/manager-webpack5": "^6.5.13", "@storybook/manager-webpack5": "^6.5.14",
"@storybook/react": "^6.5.13", "@storybook/react": "^6.5.14",
"@storybook/testing-library": "^0.0.13", "@storybook/testing-library": "^0.0.13",
"@stripe/react-stripe-js": "^1.10.0",
"@stripe/stripe-js": "^1.35.0",
"@testing-library/dom": "^8.19.0", "@testing-library/dom": "^8.19.0",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3", "@testing-library/user-event": "^14.4.3",
"@types/express": "^4.17.14",
"@types/lodash.debounce": "^4.0.7", "@types/lodash.debounce": "^4.0.7",
"@types/node": "^18.11.9", "@types/node": "^16.11.7",
"@types/pluralize": "^0.0.29", "@types/pluralize": "^0.0.29",
"@types/react": "18.0.25", "@types/react": "18.0.25",
"@types/react-dom": "18.0.8", "@types/react-dom": "18.0.9",
"@types/react-table": "^7.7.12", "@types/react-table": "^7.7.12",
"@types/testing-library__jest-dom": "^5.14.5", "@types/testing-library__jest-dom": "^5.14.5",
"@types/validator": "^13.7.10", "@types/validator": "^13.7.10",
"@typescript-eslint/eslint-plugin": "^5.43.0", "@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.43.0", "@typescript-eslint/parser": "^5.43.0",
"@vitejs/plugin-react": "^2.2.0", "@vitejs/plugin-react": "^3.0.0",
"@vitest/coverage-c8": "^0.25.2", "@vitest/coverage-c8": "^0.26.0",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"babel-loader": "^8.3.0", "babel-loader": "^8.3.0",
"babel-plugin-transform-remove-console": "^6.9.4", "babel-plugin-transform-remove-console": "^6.9.4",
"concurrently": "^6.3.0",
"critters": "^0.0.10",
"csstype": "^3.0.10", "csstype": "^3.0.10",
"dotenv": "^10.0.0",
"eslint": "^8.28.0", "eslint": "^8.28.0",
"eslint-config-airbnb": "19.0.4", "eslint-config-airbnb": "19.0.4",
"eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-airbnb-typescript": "^17.0.0",
@@ -136,25 +126,24 @@
"eslint-plugin-jsx-a11y": "^6.6.1", "eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-react": "^7.31.11", "eslint-plugin-react": "^7.31.11",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"express": "^4.18.2",
"express-validator": "^6.14.2",
"jsdom": "^20.0.3", "jsdom": "^20.0.3",
"lint-staged": ">=13", "lint-staged": ">=13",
"msw": "^0.49.0", "msw": "^0.49.0",
"msw-storybook-addon": "^1.6.3",
"postcss": "^8.4.19", "postcss": "^8.4.19",
"postmark": "^2.7.8",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"prettier-plugin-organize-imports": "^3.2.0", "prettier-plugin-organize-imports": "^3.2.0",
"prettier-plugin-tailwindcss": "^0.1.13", "prettier-plugin-tailwindcss": "^0.2.0",
"react-date-fns-hooks": "^0.9.4", "react-date-fns-hooks": "^0.9.4",
"react-error-boundary": "^3.1.4",
"require-from-string": "^2.0.2", "require-from-string": "^2.0.2",
"storybook-addon-next-router": "^4.0.1",
"tailwindcss": "^3.1.2", "tailwindcss": "^3.1.2",
"ts-node": "^10.9.1",
"tsconfig-paths-webpack-plugin": "^4.0.0", "tsconfig-paths-webpack-plugin": "^4.0.0",
"typescript": "^4.8.4", "typescript": "^4.8.4",
"vite": "^3.2.4", "vite": "^4.0.2",
"vite-tsconfig-paths": "^3.6.0", "vite-tsconfig-paths": "^4.0.3",
"vitest": "^0.25.2", "vitest": "^0.26.2",
"webpack": "^5.75.0" "webpack": "^5.75.0"
}, },
"browserslist": { "browserslist": {
@@ -168,5 +157,8 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
},
"msw": {
"workerDirectory": "public"
} }
} }

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,303 @@
/* eslint-disable */
/* tslint:disable */
/**
* Mock Service Worker (0.49.0).
* @see https://github.com/mswjs/msw
* - Please do NOT modify this file.
* - Please do NOT serve this file on production.
*/
const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70'
const activeClientIds = new Set()
self.addEventListener('install', function () {
self.skipWaiting()
})
self.addEventListener('activate', function (event) {
event.waitUntil(self.clients.claim())
})
self.addEventListener('message', async function (event) {
const clientId = event.source.id
if (!clientId || !self.clients) {
return
}
const client = await self.clients.get(clientId)
if (!client) {
return
}
const allClients = await self.clients.matchAll({
type: 'window',
})
switch (event.data) {
case 'KEEPALIVE_REQUEST': {
sendToClient(client, {
type: 'KEEPALIVE_RESPONSE',
})
break
}
case 'INTEGRITY_CHECK_REQUEST': {
sendToClient(client, {
type: 'INTEGRITY_CHECK_RESPONSE',
payload: INTEGRITY_CHECKSUM,
})
break
}
case 'MOCK_ACTIVATE': {
activeClientIds.add(clientId)
sendToClient(client, {
type: 'MOCKING_ENABLED',
payload: true,
})
break
}
case 'MOCK_DEACTIVATE': {
activeClientIds.delete(clientId)
break
}
case 'CLIENT_CLOSED': {
activeClientIds.delete(clientId)
const remainingClients = allClients.filter((client) => {
return client.id !== clientId
})
// Unregister itself when there are no more clients
if (remainingClients.length === 0) {
self.registration.unregister()
}
break
}
}
})
self.addEventListener('fetch', function (event) {
const { request } = event
const accept = request.headers.get('accept') || ''
// Bypass server-sent events.
if (accept.includes('text/event-stream')) {
return
}
// Bypass navigation requests.
if (request.mode === 'navigate') {
return
}
// Opening the DevTools triggers the "only-if-cached" request
// that cannot be handled by the worker. Bypass such requests.
if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') {
return
}
// Bypass all requests when there are no active clients.
// Prevents the self-unregistered worked from handling requests
// after it's been deleted (still remains active until the next reload).
if (activeClientIds.size === 0) {
return
}
// Generate unique request ID.
const requestId = Math.random().toString(16).slice(2)
event.respondWith(
handleRequest(event, requestId).catch((error) => {
if (error.name === 'NetworkError') {
console.warn(
'[MSW] Successfully emulated a network error for the "%s %s" request.',
request.method,
request.url,
)
return
}
// At this point, any exception indicates an issue with the original request/response.
console.error(
`\
[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`,
request.method,
request.url,
`${error.name}: ${error.message}`,
)
}),
)
})
async function handleRequest(event, requestId) {
const client = await resolveMainClient(event)
const response = await getResponse(event, client, requestId)
// Send back the response clone for the "response:*" life-cycle events.
// Ensure MSW is active and ready to handle the message, otherwise
// this message will pend indefinitely.
if (client && activeClientIds.has(client.id)) {
;(async function () {
const clonedResponse = response.clone()
sendToClient(client, {
type: 'RESPONSE',
payload: {
requestId,
type: clonedResponse.type,
ok: clonedResponse.ok,
status: clonedResponse.status,
statusText: clonedResponse.statusText,
body:
clonedResponse.body === null ? null : await clonedResponse.text(),
headers: Object.fromEntries(clonedResponse.headers.entries()),
redirected: clonedResponse.redirected,
},
})
})()
}
return response
}
// Resolve the main client for the given event.
// Client that issues a request doesn't necessarily equal the client
// that registered the worker. It's with the latter the worker should
// communicate with during the response resolving phase.
async function resolveMainClient(event) {
const client = await self.clients.get(event.clientId)
if (client?.frameType === 'top-level') {
return client
}
const allClients = await self.clients.matchAll({
type: 'window',
})
return allClients
.filter((client) => {
// Get only those clients that are currently visible.
return client.visibilityState === 'visible'
})
.find((client) => {
// Find the client ID that's recorded in the
// set of clients that have registered the worker.
return activeClientIds.has(client.id)
})
}
async function getResponse(event, client, requestId) {
const { request } = event
const clonedRequest = request.clone()
function passthrough() {
// Clone the request because it might've been already used
// (i.e. its body has been read and sent to the client).
const headers = Object.fromEntries(clonedRequest.headers.entries())
// Remove MSW-specific request headers so the bypassed requests
// comply with the server's CORS preflight check.
// Operate with the headers as an object because request "Headers"
// are immutable.
delete headers['x-msw-bypass']
return fetch(clonedRequest, { headers })
}
// Bypass mocking when the client is not active.
if (!client) {
return passthrough()
}
// Bypass initial page load requests (i.e. static assets).
// The absence of the immediate/parent client in the map of the active clients
// means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
// and is not ready to handle requests.
if (!activeClientIds.has(client.id)) {
return passthrough()
}
// Bypass requests with the explicit bypass header.
// Such requests can be issued by "ctx.fetch()".
if (request.headers.get('x-msw-bypass') === 'true') {
return passthrough()
}
// Notify the client that a request has been intercepted.
const clientMessage = await sendToClient(client, {
type: 'REQUEST',
payload: {
id: requestId,
url: request.url,
method: request.method,
headers: Object.fromEntries(request.headers.entries()),
cache: request.cache,
mode: request.mode,
credentials: request.credentials,
destination: request.destination,
integrity: request.integrity,
redirect: request.redirect,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
body: await request.text(),
bodyUsed: request.bodyUsed,
keepalive: request.keepalive,
},
})
switch (clientMessage.type) {
case 'MOCK_RESPONSE': {
return respondWithMock(clientMessage.data)
}
case 'MOCK_NOT_FOUND': {
return passthrough()
}
case 'NETWORK_ERROR': {
const { name, message } = clientMessage.data
const networkError = new Error(message)
networkError.name = name
// Rejecting a "respondWith" promise emulates a network error.
throw networkError
}
}
return passthrough()
}
function sendToClient(client, message) {
return new Promise((resolve, reject) => {
const channel = new MessageChannel()
channel.port1.onmessage = (event) => {
if (event.data && event.data.error) {
return reject(event.data.error)
}
resolve(event.data)
}
client.postMessage(message, [channel.port2])
})
}
function sleep(timeMs) {
return new Promise((resolve) => {
setTimeout(resolve, timeMs)
})
}
async function respondWithMock(response) {
await sleep(response.delay)
return new Response(response.body, response)
}

View File

@@ -15,7 +15,7 @@ import {
useInsertFeatureFlagMutation, useInsertFeatureFlagMutation,
useUpdateApplicationMutation, useUpdateApplicationMutation,
} from '@/utils/__generated__/graphql'; } from '@/utils/__generated__/graphql';
import { useUserEmail } from '@nhost/react'; import { useUserEmail } from '@nhost/nextjs';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
/** /**

View File

@@ -11,7 +11,7 @@ import Text from '@/ui/v2/Text';
import { discordAnnounce } from '@/utils/discordAnnounce'; import { discordAnnounce } from '@/utils/discordAnnounce';
import { triggerToast } from '@/utils/toast'; import { triggerToast } from '@/utils/toast';
import { updateOwnCache } from '@/utils/updateOwnCache'; import { updateOwnCache } from '@/utils/updateOwnCache';
import { useUserData } from '@nhost/react'; import { useUserData } from '@nhost/nextjs';
import Image from 'next/image'; import Image from 'next/image';
import { useState } from 'react'; import { useState } from 'react';
import { RemoveApplicationModal } from './RemoveApplicationModal'; import { RemoveApplicationModal } from './RemoveApplicationModal';

View File

@@ -5,7 +5,7 @@ import { Modal } from '@/ui/Modal';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import { Dropdown } from '@/ui/v2/Dropdown'; import { Dropdown } from '@/ui/v2/Dropdown';
import Text from '@/ui/v2/Text'; import Text from '@/ui/v2/Text';
import { useUserData } from '@nhost/react'; import { useUserData } from '@nhost/nextjs';
import Image from 'next/image'; import Image from 'next/image';
import { useState } from 'react'; import { useState } from 'react';
import ApplicationInfo from './ApplicationInfo'; import ApplicationInfo from './ApplicationInfo';

View File

@@ -1,107 +0,0 @@
import { useWorkspaceContext } from '@/context/workspace-context';
import { useCurrentWorkspaceAndApplication } from '@/hooks/useCurrentWorkspaceAndApplication';
import { Alert } from '@/ui/Alert';
import Button from '@/ui/v2/Button';
import Input from '@/ui/v2/Input';
import Text from '@/ui/v2/Text';
import { discordAnnounce } from '@/utils/discordAnnounce';
import { inputErrorMessages } from '@/utils/getErrorMessage';
import { slugifyString } from '@/utils/helpers';
import { triggerToast } from '@/utils/toast';
import { updateOwnCache } from '@/utils/updateOwnCache';
import { useUpdateApplicationMutation } from '@/utils/__generated__/graphql';
import { useRouter } from 'next/router';
import React, { useState } from 'react';
export function ChangeApplicationName({ close }: any) {
const [updateAppName, { client }] = useUpdateApplicationMutation({});
const { workspaceContext } = useWorkspaceContext();
const [name, setName] = useState(workspaceContext.appName);
const [applicationError, setApplicationError] = useState<any>('');
const { currentWorkspace, currentApplication } =
useCurrentWorkspaceAndApplication();
const router = useRouter();
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const slug = slugifyString(name);
if (slug.length < 4 || slug.length > 32) {
setApplicationError('Slug should be within 4 and 32 characters.');
return;
}
if (!inputErrorMessages(name, setName, setApplicationError, 'project')) {
return;
}
try {
await updateAppName({
variables: {
appId: currentApplication.id,
app: {
name,
slug,
},
},
});
triggerToast('Project name changed');
} catch (error) {
await discordAnnounce(
`Error trying to delete project: ${currentApplication.name}`,
);
}
await updateOwnCache(client);
await router.push(`/${currentWorkspace.slug}/${slug}`);
}
return (
<div className="w-modal px-6 py-6 text-left">
<div className="flex flex-col">
<Text variant="h3" component="h2">
Change Project Name
</Text>
<form onSubmit={handleSubmit}>
<div className="mt-4 grid grid-flow-row gap-2">
<Input
label="New Project Name"
id="projectName"
value={name}
onChange={(e) => {
setName(e.target.value);
setApplicationError('');
}}
fullWidth
autoFocus
helperText={`https://app.nhost.io/${
currentWorkspace.slug
}/${slugifyString(name)}`}
/>
{applicationError && (
<Alert severity="error">{applicationError}</Alert>
)}
</div>
<div className="mt-4 grid grid-flow-row gap-2">
<Button type="submit" disabled={applicationError}>
Save
</Button>
<Button
type="button"
variant="outlined"
color="secondary"
onClick={close}
>
Close
</Button>
</div>
</form>
</div>
</div>
);
}
export default ChangeApplicationName;

View File

@@ -32,9 +32,12 @@ export default function ConnectGithubModal({ close }: ConnectGithubModalProps) {
useState<ConnectGithubModalState>('CONNECTING'); useState<ConnectGithubModalState>('CONNECTING');
const [selectedRepoId, setSelectedRepoId] = useState<string | null>(null); const [selectedRepoId, setSelectedRepoId] = useState<string | null>(null);
const { data, loading, error } = useGetGithubRepositoriesQuery({ const { data, loading, error, startPolling } =
pollInterval: 2000, useGetGithubRepositoriesQuery();
});
useEffect(() => {
startPolling(2000);
}, [startPolling]);
const handleSelectAnotherRepository = () => { const handleSelectAnotherRepository = () => {
setSelectedRepoId(null); setSelectedRepoId(null);

View File

@@ -1,327 +0,0 @@
import ErrorBoundaryFallback from '@/components/common/ErrorBoundaryFallback';
import TwilioIcon from '@/components/icons/TwilioIcon';
import {
useGetSmsSettingsQuery,
useUpdateAppMutation,
} from '@/generated/graphql';
import { useCurrentWorkspaceAndApplication } from '@/hooks/useCurrentWorkspaceAndApplication';
import { Button, Input } from '@/ui';
import { Alert } from '@/ui/Alert';
import DelayedLoading from '@/ui/DelayedLoading';
import { Text } from '@/ui/Text';
import { showLoadingToast, triggerToast } from '@/utils/toast';
import { useApolloClient } from '@apollo/client';
import { useEffect } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import {
Controller,
FormProvider,
useForm,
useFormContext,
} from 'react-hook-form';
import toast from 'react-hot-toast';
export function EditSMSSettingsForm({
close,
isAlreadyEnabled,
}: {
close: () => void;
isAlreadyEnabled: boolean;
}) {
const { currentApplication } = useCurrentWorkspaceAndApplication();
const {
handleSubmit,
watch,
formState: { isSubmitting, errors },
} = useFormContext<EditSMSSettingsFormData>();
const { control } = useFormContext<EditSMSSettingsFormData>();
const [updateApp] = useUpdateAppMutation();
let toastId: string;
const client = useApolloClient();
const isNotCompleted =
!watch('accountSID') ||
!watch('authToken') ||
!watch('messagingServiceSID');
const handleEditSMSSettings = async (data: EditSMSSettingsFormData) => {
try {
toastId = showLoadingToast('Updating SMS settings...');
await updateApp({
variables: {
id: currentApplication.id,
app: {
authSmsTwilioAccountSid: data.accountSID,
authSmsTwilioAuthToken: data.authToken,
authSmsTwilioMessagingServiceId: data.messagingServiceSID,
authSmsPasswordlessEnabled: true,
},
},
});
await client.refetchQueries({ include: ['getSMSSettings'] });
toast.remove(toastId);
triggerToast('SMS settings updated successfully.');
close();
} catch (error) {
if (toastId) {
toast.remove(toastId);
}
throw error;
}
};
return (
<form
onSubmit={handleSubmit(handleEditSMSSettings)}
className="flex w-full flex-col pb-1"
autoComplete="off"
>
{errors &&
Object.entries(errors).map(([type, error]) => (
<Alert key={type} className="mb-4" severity="error">
{error.message}
</Alert>
))}
<div>
<div className="flex flex-row place-content-between border-t border-b px-2 py-2.5">
<div className="flex w-full flex-row">
<Text
color="greyscaleDark"
className="self-center font-medium"
size="normal"
>
Account SID
</Text>
</div>
<div className="flex w-full">
<Controller
name="accountSID"
control={control}
rules={{
required: true,
pattern: {
value: /^[a-zA-Z0-9-_]+$/,
message:
'The Account SID must contain only letters, hyphens, and numbers.',
},
}}
render={({ field }) => (
<Input
{...field}
id="accountSID"
placeholder="Account SID"
required
value={field.value || ''}
onChange={(value: string) => {
if (value && !/^[a-zA-Z0-9-_]+$/gi.test(value)) {
// prevent the user from entering invalid characters
return;
}
field.onChange(value);
}}
/>
)}
/>
</div>
</div>
<div className="flex flex-row place-content-between border-b px-2 py-2.5">
<div className="flex w-full flex-row">
<Text
color="greyscaleDark"
className="self-center font-medium"
size="normal"
>
Auth Token
</Text>
</div>
<div className="flex w-full">
<Controller
name="authToken"
control={control}
rules={{
required: true,
pattern: {
value: /^[a-zA-Z0-9-_]+$/,
message:
'The Auth Token must contain only letters, hyphens, and numbers.',
},
}}
render={({ field }) => (
<Input
{...field}
id="authToken"
placeholder="Auth Token"
required
value={field.value || ''}
onChange={(value: string) => {
if (value && !/^[a-zA-Z0-9-_/.]+$/gi.test(value)) {
return;
}
field.onChange(value);
}}
/>
)}
/>
</div>
</div>
<div className="flex flex-row place-content-between border-b px-2 py-2.5">
<div className="flex w-full flex-row">
<Text
color="greyscaleDark"
className="self-center font-medium"
size="normal"
>
Messaging Service SID
</Text>
</div>
<div className="flex w-full">
<Controller
name="messagingServiceSID"
control={control}
rules={{
required: true,
pattern: {
value: /^[+a-zA-Z0-9-_/.]+$/,
message:
'The Messaging Service SID must either be a valid phone number or contain only letters, hyphens, and numbers.',
},
}}
render={({ field }) => (
<Input
{...field}
id="messagingServiceSID"
required
placeholder="Messaging Service SID"
value={field.value || ''}
onChange={(value: string) => {
if (value && !/^[+a-zA-Z0-9-_/.]+$/gi.test(value)) {
return;
}
field.onChange(value);
}}
/>
)}
/>
</div>
</div>
</div>
<div className="flex flex-col">
<Button
variant="primary"
type="submit"
className="text-grayscaleDark mt-2 border text-sm+ font-normal"
loading={isSubmitting}
disabled={isSubmitting || isNotCompleted}
>
{isAlreadyEnabled ? 'Update SMS Settings' : 'Enable SMS'}
</Button>
</div>
</form>
);
}
export function EditSMSSettingsModal({
close,
isAlreadyEnabled,
}: {
close: () => void;
isAlreadyEnabled: boolean;
}) {
return (
<div className="w-modal px-6 py-4 text-left">
<div className="flex flex-col">
<div className="mx-auto mt-2.5">
<TwilioIcon className=" text-greyscaleDark" />
</div>
<Text
variant="subHeading"
color="greyscaleDark"
size="large"
className="mt-3 text-center"
>
Set up Twilio SMS Service
</Text>
<Text
variant="body"
color="greyscaleDark"
size="small"
className="mt-0.5 mb-6 text-center font-normal"
>
SMS messages are sent through Twilio. Create an account and a
messaging service at https://console.twilio.com.
</Text>
<div>
<ErrorBoundary fallbackRender={ErrorBoundaryFallback}>
<EditSMSSettingsForm
close={close}
isAlreadyEnabled={isAlreadyEnabled}
/>
</ErrorBoundary>
</div>
</div>
</div>
);
}
export interface EditSMSSettingsProps {
close: () => void;
}
export interface EditSMSSettingsFormData {
accountSID: string;
authToken: string;
messagingServiceSID: string;
}
export function EditSMSSettings({ close }: EditSMSSettingsProps) {
const { currentApplication } = useCurrentWorkspaceAndApplication();
const form = useForm<EditSMSSettingsFormData>({
reValidateMode: 'onSubmit',
defaultValues: {
accountSID: '',
authToken: '',
messagingServiceSID: '',
},
});
const { data, loading, error } = useGetSmsSettingsQuery({
variables: {
id: currentApplication.id,
},
});
useEffect(() => {
if (!data) {
return;
}
form.setValue('accountSID', data.app.authSmsTwilioAccountSid);
form.setValue('authToken', data.app.authSmsTwilioAuthToken);
form.setValue(
'messagingServiceSID',
data.app.authSmsTwilioMessagingServiceId,
);
}, [data, form]);
if (loading) {
return <DelayedLoading delay={500} />;
}
if (error) {
throw error;
}
return (
<FormProvider {...form}>
<EditSMSSettingsModal
close={close}
isAlreadyEnabled={data.app.authSmsPasswordlessEnabled}
/>
</FormProvider>
);
}

View File

@@ -1,134 +0,0 @@
import {
useGetSmsSettingsQuery,
useUpdateAppMutation,
} from '@/generated/graphql';
import { useCurrentWorkspaceAndApplication } from '@/hooks/useCurrentWorkspaceAndApplication';
import { Text, Toggle } from '@/ui';
import DelayedLoading from '@/ui/DelayedLoading';
import { showLoadingToast, triggerToast } from '@/utils/toast';
import { useApolloClient } from '@apollo/client';
import clsx from 'clsx';
import Image from 'next/image';
import { useEffect, useState } from 'react';
import toast from 'react-hot-toast';
export function EnableSMSSignIn({ openSMSSettingsModal }: any) {
const { currentApplication } = useCurrentWorkspaceAndApplication();
const [updateApp] = useUpdateAppMutation();
const { data, loading, error } = useGetSmsSettingsQuery({
variables: {
id: currentApplication.id,
},
});
const [enableSMSLoginMethod, setEnableSMSLoginMethod] = useState(false);
const client = useApolloClient();
let toastId: string;
useEffect(() => {
if (!data) {
return;
}
setEnableSMSLoginMethod(data.app.authSmsPasswordlessEnabled);
}, [data]);
if (loading) {
return <DelayedLoading delay={500} />;
}
if (error) {
throw error;
}
const handleDisable = async () => {
try {
toastId = showLoadingToast('Disabling SMS login...');
await updateApp({
variables: {
id: currentApplication.id,
app: {
authSmsPasswordlessEnabled: false,
},
},
});
setEnableSMSLoginMethod(false);
await client.refetchQueries({ include: ['getSMSSettings'] });
toast.remove(toastId);
triggerToast('Passwordless SMS disabled.');
} catch (updateError) {
if (toastId) {
toast.remove(toastId);
}
throw updateError;
}
};
return (
<div className="mt-20">
<div className="mx-auto font-display">
<div className="flex flex-col place-content-between">
<div className="">
<div className="flex flex-row place-content-between">
<div className="relative flex flex-row">
<Image
src="/assets/SMS.svg"
width={24}
height={24}
alt="Phone Number (SMS)"
/>
<Text
variant="body"
size="large"
className="ml-2 font-medium"
color="greyscaleDark"
>
Phone Number (SMS)
</Text>
<div>
<button
type="button"
className={clsx(
'ml-2 align-bottom text-sm- font-medium text-blue transition-opacity duration-300',
!enableSMSLoginMethod && 'invisible opacity-0',
enableSMSLoginMethod && 'opacity-100',
)}
onClick={() => openSMSSettingsModal()}
>
Edit SMS settings
</button>
</div>
</div>
<div className="flex flex-row">
<Toggle
checked={enableSMSLoginMethod}
onChange={async () => {
if (enableSMSLoginMethod) {
await handleDisable();
} else {
openSMSSettingsModal();
}
}}
/>
</div>
</div>
<div className="mt-3 flex flex-row self-center align-middle">
<Text
variant="body"
size="normal"
color="greyscaleDark"
className="self-center"
>
Sign in users with Phone Number (SMS).
</Text>
</div>
</div>
</div>
</div>
</div>
);
}
export default EnableSMSSignIn;

View File

@@ -1,12 +1,16 @@
import { ConnectionDetail } from '@/components/applications/ConnectionDetail'; import { ConnectionDetail } from '@/components/applications/ConnectionDetail';
import { LoadingScreen } from '@/components/common/LoadingScreen'; import { LoadingScreen } from '@/components/common/LoadingScreen';
import useIsPlatform from '@/hooks/common/useIsPlatform';
import { useCurrentWorkspaceAndApplication } from '@/hooks/useCurrentWorkspaceAndApplication'; import { useCurrentWorkspaceAndApplication } from '@/hooks/useCurrentWorkspaceAndApplication';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import ArrowSquareOutIcon from '@/ui/v2/icons/ArrowSquareOutIcon'; import ArrowSquareOutIcon from '@/ui/v2/icons/ArrowSquareOutIcon';
import Link from '@/ui/v2/Link'; import Link from '@/ui/v2/Link';
import Text from '@/ui/v2/Text'; import Text from '@/ui/v2/Text';
import generateAppServiceUrl, {
defaultLocalBackendSlugs,
defaultRemoteBackendSlugs,
} from '@/utils/common/generateAppServiceUrl';
import { LOCAL_HASURA_URL } from '@/utils/env'; import { LOCAL_HASURA_URL } from '@/utils/env';
import { generateRemoteAppUrl } from '@/utils/helpers';
import Image from 'next/image'; import Image from 'next/image';
interface HasuraDataProps { interface HasuraDataProps {
@@ -15,6 +19,7 @@ interface HasuraDataProps {
export function HasuraData({ close }: HasuraDataProps) { export function HasuraData({ close }: HasuraDataProps) {
const { currentApplication } = useCurrentWorkspaceAndApplication(); const { currentApplication } = useCurrentWorkspaceAndApplication();
const isPlatform = useIsPlatform();
if ( if (
!currentApplication?.subdomain || !currentApplication?.subdomain ||
@@ -24,9 +29,15 @@ export function HasuraData({ close }: HasuraDataProps) {
} }
const hasuraUrl = const hasuraUrl =
process.env.NEXT_PUBLIC_ENV === 'dev' process.env.NEXT_PUBLIC_ENV === 'dev' || !isPlatform
? LOCAL_HASURA_URL ? `${LOCAL_HASURA_URL}/console`
: generateRemoteAppUrl(currentApplication.subdomain); : generateAppServiceUrl(
currentApplication?.subdomain,
currentApplication?.region.awsName,
'hasura',
defaultLocalBackendSlugs,
{ ...defaultRemoteBackendSlugs, hasura: '/console' },
);
return ( return (
<div className="mx-auto w-full max-w-md px-6 py-4 text-left"> <div className="mx-auto w-full max-w-md px-6 py-4 text-left">
@@ -60,7 +71,7 @@ export function HasuraData({ close }: HasuraDataProps) {
<div className="mt-6 grid grid-flow-row gap-2"> <div className="mt-6 grid grid-flow-row gap-2">
<Link <Link
href={`${hasuraUrl}/console`} href={hasuraUrl}
target="_blank" target="_blank"
rel="noreferrer noopener" rel="noreferrer noopener"
className="grid grid-flow-col items-center justify-center gap-1 rounded-[4px] bg-btn p-2 text-sm+ font-medium text-white hover:ring-2 motion-safe:transition-all" className="grid grid-flow-col items-center justify-center gap-1 rounded-[4px] bg-btn p-2 text-sm+ font-medium text-white hover:ring-2 motion-safe:transition-all"

View File

@@ -1,224 +0,0 @@
import { useCurrentWorkspaceAndApplication } from '@/hooks/useCurrentWorkspaceAndApplication';
import { useSubmitState } from '@/hooks/useSubmitState';
import { Alert } from '@/ui/Alert';
import Button from '@/ui/v2/Button';
import Input from '@/ui/v2/Input';
import Text from '@/ui/v2/Text';
import { triggerToast } from '@/utils/toast';
import {
refetchGetAppInjectedVariablesQuery,
useUpdateApplicationMutation,
} from '@/utils/__generated__/graphql';
import { useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
export interface EditCustomUserJWTTokenData {
customUserJWTToken: string;
}
export type JWTSecretModalState = 'SHOW' | 'EDIT';
export interface JWTSecretModalProps {
close: () => void;
data?: any;
jwtSecret: string;
initialModalState?: JWTSecretModalState;
}
export function EditJWTSecretModal({ close }: any) {
const { currentApplication } = useCurrentWorkspaceAndApplication();
const { submitState, setSubmitState } = useSubmitState();
const [updateApplication] = useUpdateApplicationMutation({
refetchQueries: [
refetchGetAppInjectedVariablesQuery({ id: currentApplication.id }),
],
});
const {
handleSubmit,
control,
formState: { isSubmitting },
} = useForm<EditCustomUserJWTTokenData>({
reValidateMode: 'onSubmit',
defaultValues: {
customUserJWTToken: '',
},
});
const handleEditJWTSecret = async (data: EditCustomUserJWTTokenData) => {
setSubmitState({
error: null,
loading: false,
fieldsWithError: [],
});
try {
JSON.parse(data.customUserJWTToken);
} catch (error) {
setSubmitState({
error: new Error('The custom JWT token should be valid json.'),
loading: false,
fieldsWithError: [],
});
return;
}
try {
await updateApplication({
variables: {
appId: currentApplication.id,
app: {
hasuraGraphqlJwtSecret: data.customUserJWTToken,
},
},
});
triggerToast(
`Successfully added custom JWT token to ${currentApplication.name}.`,
);
close();
} catch (error) {
triggerToast(
`Error adding custom JWT token to ${currentApplication.name}`,
);
setSubmitState({ error, loading: false, fieldsWithError: [] });
}
};
return (
<form
className="w-modal px-6 py-4"
onSubmit={handleSubmit(handleEditJWTSecret)}
>
<div className="grid grid-flow-row gap-2">
<div className="grid grid-flow-row text-left">
<Text variant="h3" component="h2">
Add Custom JWT Secret
</Text>
<Text variant="subtitle2">
You can add your custom JWT key here. Hasura will use this key to
validate the identity of your users.
</Text>
</div>
{submitState.error && (
<Alert severity="error">{submitState.error.message}</Alert>
)}
<Controller
name="customUserJWTToken"
control={control}
rules={{
required: true,
}}
render={({ field }) => (
<Input
{...field}
placeholder="Paste your custom JWT token here..."
componentsProps={{
inputRoot: {
className: 'font-mono bg-header',
},
}}
aria-label="Custom JWT token"
type="text"
value={field.value}
onBlur={() =>
setSubmitState({
error: null,
loading: false,
fieldsWithError: [],
})
}
multiline
rows={6}
fullWidth
hideEmptyHelperText
/>
)}
/>
<div className="grid grid-flow-row gap-2">
<Button type="submit" loading={isSubmitting}>
Save Changes
</Button>
<Button variant="outlined" color="secondary" onClick={close}>
Cancel
</Button>
</div>
</div>
</form>
);
}
export function ShowJWTTokenModal({ JWTKey, editJWTSecret }: any) {
return (
<div className="w-modal px-6 py-4">
<div className="grid grid-flow-row gap-2">
<div className="grid grid-flow-row text-left">
<Text variant="h3" component="h2">
Auth JWT Secret
</Text>
<Text variant="subtitle2">
This is the key used for generating JWTs. It&apos;s HMAC-SHA-based
and the same as configured in Hasura.
</Text>
</div>
<div>
<Input
defaultValue={JWTKey}
multiline
disabled
fullWidth
hideEmptyHelperText
rows={6}
componentsProps={{
inputRoot: { className: 'font-mono' },
}}
/>
</div>
<div className="mx-auto max-w-sm text-center">
<Text variant="subtitle2">
Already using a third party auth service? <br />
<button
type="button"
className="mt-0.5 ml-0.5 text-xs font-medium text-blue"
onClick={() => {
editJWTSecret();
}}
>
Add your custom JWT token
</button>
</Text>
</div>
</div>
</div>
);
}
export function JWTSecretModal({
close,
data,
jwtSecret,
initialModalState,
}: any) {
const [jwtSecretModalState, setJwtSecretModalState] =
useState<JWTSecretModalState>(initialModalState || 'SHOW');
const editJWTSecret = () => {
setJwtSecretModalState('EDIT');
};
if (jwtSecretModalState === 'EDIT') {
return <EditJWTSecretModal close={close} />;
}
return (
<ShowJWTTokenModal
JWTKey={jwtSecret || data}
editJWTSecret={editJWTSecret}
/>
);
}

View File

@@ -1,28 +0,0 @@
import { Avatar } from '@/ui/Avatar';
import { Text } from '@/ui/Text';
import { nhost } from '@/utils/nhost';
import Image from 'next/image';
export function SelectedWorkspaceOnNewApp({ current }: any) {
const user = nhost.auth.getUser();
return (
<div className="flex flex-row space-x-2 self-center">
{current.name === 'Default Workspace' ? (
<Avatar
className="h-5 w-5 self-center rounded-full"
name={user?.displayName}
avatarUrl={user?.avatarUrl}
/>
) : (
<div className="h-5 w-5 overflow-hidden rounded-md">
<Image src="/logos/new.svg" alt="Nhost Logo" width={20} height={20} />
</div>
)}
<Text size="small" color="greyscaleDark" className="font-normal">
{current.name}
</Text>
</div>
);
}
export default SelectedWorkspaceOnNewApp;

View File

@@ -13,14 +13,17 @@ export function FunctionsLogsTerminalPage({ functionName }: any) {
const { currentApplication } = useCurrentWorkspaceAndApplication(); const { currentApplication } = useCurrentWorkspaceAndApplication();
const [normalizedFunctionData, setNormalizedFunctionData] = useState(null); const [normalizedFunctionData, setNormalizedFunctionData] = useState(null);
const { data } = useGetFunctionLogQuery({ const { data, startPolling } = useGetFunctionLogQuery({
variables: { variables: {
subdomain: currentApplication.subdomain, subdomain: currentApplication.subdomain,
functionPaths: [functionName?.split('/').slice(1, 3).join('/')], functionPaths: [functionName?.split('/').slice(1, 3).join('/')],
}, },
pollInterval: 3000,
}); });
useEffect(() => {
startPolling(3000);
}, [startPolling]);
useEffect(() => { useEffect(() => {
if (!data || data.getFunctionLogs.length === 0) { if (!data || data.getFunctionLogs.length === 0) {
return; return;

View File

@@ -2,7 +2,7 @@ import { useRemoteApplicationGQLClient } from '@/hooks/useRemoteApplicationGQLCl
import ActivityIndicator from '@/ui/v2/ActivityIndicator'; import ActivityIndicator from '@/ui/v2/ActivityIndicator';
import Option from '@/ui/v2/Option'; import Option from '@/ui/v2/Option';
import Select from '@/ui/v2/Select'; import Select from '@/ui/v2/Select';
import type { RemoteAppGetUsersQuery } from '@/utils/__generated__/graphql'; import type { RemoteAppGetUsersCustomQuery } from '@/utils/__generated__/graphql';
import { useRemoteAppGetUsersCustomQuery } from '@/utils/__generated__/graphql'; import { useRemoteAppGetUsersCustomQuery } from '@/utils/__generated__/graphql';
import { DEFAULT_ROLES } from './utils'; import { DEFAULT_ROLES } from './utils';
@@ -57,7 +57,7 @@ export function UserSelect({ onUserChange, ...props }: UserSelectProps) {
return; return;
} }
const user: RemoteAppGetUsersQuery['users'][number] = users.find( const user: RemoteAppGetUsersCustomQuery['users'][0] = users.find(
({ id }) => id === userId, ({ id }) => id === userId,
); );

View File

@@ -1 +0,0 @@
export { default } from './AppDeployments';

View File

@@ -37,20 +37,27 @@ function ControlledAutocomplete(
}: ControlledAutocompleteProps<AutocompleteOption>, }: ControlledAutocompleteProps<AutocompleteOption>,
ref: ForwardedRef<HTMLInputElement>, ref: ForwardedRef<HTMLInputElement>,
) { ) {
const { setValue } = useFormContext(); const form = useFormContext();
const { field } = useController({ const { field } = useController({
...controllerProps, ...(controllerProps || {}),
name: controllerProps?.name || name || '', name: controllerProps?.name || name || '',
control: controllerProps?.control || control, control: controllerProps?.control || control,
}); });
if (!form) {
throw new Error('ControlledAutocomplete must be used in a FormContext.');
}
const { setValue } = form || {};
return ( return (
<Autocomplete <Autocomplete
{...props} {...props}
{...field} {...field}
inputValue={typeof field.value === 'string' ? field.value : undefined}
ref={mergeRefs([field.ref, ref])} ref={mergeRefs([field.ref, ref])}
onChange={(event, options, reason, details) => { onChange={(event, options, reason, details) => {
setValue(controllerProps?.name || name, options); setValue?.(controllerProps?.name || name, options);
if (props.onChange) { if (props.onChange) {
props.onChange(event, options, reason, details); props.onChange(event, options, reason, details);

View File

@@ -2,11 +2,11 @@ import DataGridBody from '@/components/common/DataGridBody';
import DataGridFrame from '@/components/common/DataGridFrame'; import DataGridFrame from '@/components/common/DataGridFrame';
import type { DataGridHeaderProps } from '@/components/common/DataGridHeader'; import type { DataGridHeaderProps } from '@/components/common/DataGridHeader';
import DataGridHeader from '@/components/common/DataGridHeader'; import DataGridHeader from '@/components/common/DataGridHeader';
import DataBrowserEmptyState from '@/components/data-browser/DataBrowserEmptyState'; import DataBrowserEmptyState from '@/components/dataBrowser/DataBrowserEmptyState';
import { DataGridProvider } from '@/context/DataGridContext'; import { DataGridProvider } from '@/context/DataGridContext';
import type { UseDataGridOptions } from '@/hooks/useDataGrid'; import type { UseDataGridOptions } from '@/hooks/useDataGrid';
import useDataGrid from '@/hooks/useDataGrid'; import useDataGrid from '@/hooks/useDataGrid';
import type { DataBrowserGridColumn } from '@/types/data-browser'; import type { DataBrowserGridColumn } from '@/types/dataBrowser';
import ActivityIndicator from '@/ui/v2/ActivityIndicator'; import ActivityIndicator from '@/ui/v2/ActivityIndicator';
import type { ForwardedRef } from 'react'; import type { ForwardedRef } from 'react';
import { forwardRef, useEffect, useRef } from 'react'; import { forwardRef, useEffect, useRef } from 'react';

View File

@@ -1,7 +1,7 @@
import type { DataGridProps } from '@/components/common/DataGrid'; import type { DataGridProps } from '@/components/common/DataGrid';
import DataGridCell from '@/components/common/DataGridCell'; import DataGridCell from '@/components/common/DataGridCell';
import useDataGridConfig from '@/hooks/useDataGridConfig'; import useDataGridConfig from '@/hooks/useDataGridConfig';
import type { DataBrowserGridColumn } from '@/types/data-browser'; import type { DataBrowserGridColumn } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import PlusIcon from '@/ui/v2/icons/PlusIcon'; import PlusIcon from '@/ui/v2/icons/PlusIcon';
import type { DetailedHTMLProps, HTMLProps, KeyboardEvent } from 'react'; import type { DetailedHTMLProps, HTMLProps, KeyboardEvent } from 'react';
@@ -35,15 +35,15 @@ function InsertPlaceholderTableRow({
}: InsertPlaceholderTableRowProps) { }: InsertPlaceholderTableRowProps) {
return ( return (
<div <div
className="h-12 border-r-1 border-b-1 border-gray-200 bg-white" className="h-12 bg-white border-gray-200 border-r-1 border-b-1"
{...props} {...props}
> >
<Button <Button
onClick={onInsertRow} onClick={onInsertRow}
variant="borderless" variant="borderless"
color="secondary" color="secondary"
className="h-full w-full justify-start rounded-none px-2 py-3 text-xs font-normal hover:shadow-none focus:shadow-none focus:outline-none" className="justify-start w-full h-full px-2 py-3 text-xs font-normal rounded-none hover:shadow-none focus:shadow-none focus:outline-none"
startIcon={<PlusIcon className="h-4 w-4 text-greyscaleGrey" />} startIcon={<PlusIcon className="w-4 h-4 text-greyscaleGrey" />}
> >
Insert New Row Insert New Row
</Button> </Button>
@@ -181,7 +181,7 @@ export default function DataGridBody<T extends object>({
return ( return (
<div {...getTableBodyProps()} ref={bodyRef} {...props}> <div {...getTableBodyProps()} ref={bodyRef} {...props}>
{rows.length === 0 && !loading && ( {rows.length === 0 && !loading && (
<div className="flex flex-nowrap pr-5"> <div className="flex pr-5 flex-nowrap">
{onInsertRow ? ( {onInsertRow ? (
<InsertPlaceholderTableRow <InsertPlaceholderTableRow
style={{ style={{
@@ -279,7 +279,7 @@ export default function DataGridBody<T extends object>({
})} })}
{allowInsertColumn && ( {allowInsertColumn && (
<div className="h-12 w-25 border-r-1 border-b-1 border-gray-200 bg-white" /> <div className="h-12 bg-white border-gray-200 w-25 border-r-1 border-b-1" />
)} )}
</div> </div>

View File

@@ -3,7 +3,7 @@ import type {
ColumnType, ColumnType,
DataBrowserGridCell, DataBrowserGridCell,
DataBrowserGridCellProps, DataBrowserGridCellProps,
} from '@/types/data-browser'; } from '@/types/dataBrowser';
import Tooltip, { useTooltip } from '@/ui/v2/Tooltip'; import Tooltip, { useTooltip } from '@/ui/v2/Tooltip';
import { triggerToast } from '@/utils/toast'; import { triggerToast } from '@/utils/toast';
import type { import type {

View File

@@ -1,6 +1,6 @@
import type { DataGridProps } from '@/components/common/DataGrid'; import type { DataGridProps } from '@/components/common/DataGrid';
import useDataGridConfig from '@/hooks/useDataGridConfig'; import useDataGridConfig from '@/hooks/useDataGridConfig';
import type { DataBrowserGridColumn } from '@/types/data-browser'; import type { DataBrowserGridColumn } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import Divider from '@/ui/v2/Divider'; import Divider from '@/ui/v2/Divider';
import { Dropdown } from '@/ui/v2/Dropdown'; import { Dropdown } from '@/ui/v2/Dropdown';

View File

@@ -15,10 +15,14 @@ export type DialogType =
| 'EDIT_FOREIGN_KEY' | 'EDIT_FOREIGN_KEY'
| 'CREATE_ROLE' | 'CREATE_ROLE'
| 'EDIT_ROLE' | 'EDIT_ROLE'
| 'CREATE_USER'
| 'CREATE_PERMISSION_VARIABLE' | 'CREATE_PERMISSION_VARIABLE'
| 'EDIT_PERMISSION_VARIABLE' | 'EDIT_PERMISSION_VARIABLE'
| 'CREATE_ENVIRONMENT_VARIABLE' | 'CREATE_ENVIRONMENT_VARIABLE'
| 'EDIT_ENVIRONMENT_VARIABLE'; | 'EDIT_ENVIRONMENT_VARIABLE'
| 'EDIT_USER'
| 'EDIT_USER_PASSWORD'
| 'EDIT_JWT_SECRET';
export interface DialogConfig<TPayload = unknown> { export interface DialogConfig<TPayload = unknown> {
/** /**

View File

@@ -1,24 +1,36 @@
import RetryableErrorBoundary from '@/components/common/RetryableErrorBoundary'; import RetryableErrorBoundary from '@/components/common/RetryableErrorBoundary';
import CreateForeignKeyForm from '@/components/data-browser/CreateForeignKeyForm'; import CreateForeignKeyForm from '@/components/dataBrowser/CreateForeignKeyForm';
import EditForeignKeyForm from '@/components/data-browser/EditForeignKeyForm'; import EditForeignKeyForm from '@/components/dataBrowser/EditForeignKeyForm';
import CreateEnvironmentVariableForm from '@/components/settings/environmentVariables/CreateEnvironmentVariableForm'; import CreateEnvironmentVariableForm from '@/components/settings/environmentVariables/CreateEnvironmentVariableForm';
import EditEnvironmentVariableForm from '@/components/settings/environmentVariables/EditEnvironmentVariableForm'; import EditEnvironmentVariableForm from '@/components/settings/environmentVariables/EditEnvironmentVariableForm';
import EditJwtSecretForm from '@/components/settings/environmentVariables/EditJwtSecretForm';
import CreatePermissionVariableForm from '@/components/settings/permissions/CreatePermissionVariableForm'; import CreatePermissionVariableForm from '@/components/settings/permissions/CreatePermissionVariableForm';
import EditPermissionVariableForm from '@/components/settings/permissions/EditPermissionVariableForm'; import EditPermissionVariableForm from '@/components/settings/permissions/EditPermissionVariableForm';
import CreateRoleForm from '@/components/settings/roles/CreateRoleForm'; import CreateRoleForm from '@/components/settings/roles/CreateRoleForm';
import EditRoleForm from '@/components/settings/roles/EditRoleForm'; import EditRoleForm from '@/components/settings/roles/EditRoleForm';
import CreateUserForm from '@/components/users/CreateUserForm';
import EditUserForm from '@/components/users/EditUserForm';
import EditUserPasswordForm from '@/components/users/EditUserPasswordForm';
import ActivityIndicator from '@/ui/v2/ActivityIndicator'; import ActivityIndicator from '@/ui/v2/ActivityIndicator';
import AlertDialog from '@/ui/v2/AlertDialog'; import AlertDialog from '@/ui/v2/AlertDialog';
import { BaseDialog } from '@/ui/v2/Dialog'; import { BaseDialog } from '@/ui/v2/Dialog';
import Drawer from '@/ui/v2/Drawer'; import Drawer from '@/ui/v2/Drawer';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { useRouter } from 'next/router';
import type { import type {
BaseSyntheticEvent, BaseSyntheticEvent,
DetailedHTMLProps, DetailedHTMLProps,
HTMLProps, HTMLProps,
PropsWithChildren, PropsWithChildren,
} from 'react'; } from 'react';
import { useCallback, useMemo, useReducer, useRef, useState } from 'react'; import {
useCallback,
useEffect,
useMemo,
useReducer,
useRef,
useState,
} from 'react';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
import type { DialogConfig, DialogType } from './DialogContext'; import type { DialogConfig, DialogType } from './DialogContext';
import DialogContext from './DialogContext'; import DialogContext from './DialogContext';
@@ -49,31 +61,33 @@ function LoadingComponent({
} }
const CreateRecordForm = dynamic( const CreateRecordForm = dynamic(
() => import('@/components/data-browser/CreateRecordForm'), () => import('@/components/dataBrowser/CreateRecordForm'),
{ ssr: false, loading: () => LoadingComponent() }, { ssr: false, loading: () => LoadingComponent() },
); );
const CreateColumnForm = dynamic( const CreateColumnForm = dynamic(
() => import('@/components/data-browser/CreateColumnForm'), () => import('@/components/dataBrowser/CreateColumnForm'),
{ ssr: false, loading: () => LoadingComponent() }, { ssr: false, loading: () => LoadingComponent() },
); );
const EditColumnForm = dynamic( const EditColumnForm = dynamic(
() => import('@/components/data-browser/EditColumnForm'), () => import('@/components/dataBrowser/EditColumnForm'),
{ ssr: false, loading: () => LoadingComponent() }, { ssr: false, loading: () => LoadingComponent() },
); );
const CreateTableForm = dynamic( const CreateTableForm = dynamic(
() => import('@/components/data-browser/CreateTableForm'), () => import('@/components/dataBrowser/CreateTableForm'),
{ ssr: false, loading: () => LoadingComponent() }, { ssr: false, loading: () => LoadingComponent() },
); );
const EditTableForm = dynamic( const EditTableForm = dynamic(
() => import('@/components/data-browser/EditTableForm'), () => import('@/components/dataBrowser/EditTableForm'),
{ ssr: false, loading: () => LoadingComponent() }, { ssr: false, loading: () => LoadingComponent() },
); );
function DialogProvider({ children }: PropsWithChildren<unknown>) { function DialogProvider({ children }: PropsWithChildren<unknown>) {
const router = useRouter();
const [ const [
{ {
open: dialogOpen, open: dialogOpen,
@@ -161,26 +175,29 @@ function DialogProvider({ children }: PropsWithChildren<unknown>) {
alertDialogDispatch({ type: 'CLEAR_ALERT_CONTENT' }); alertDialogDispatch({ type: 'CLEAR_ALERT_CONTENT' });
} }
function openDirtyConfirmation(config?: Partial<DialogConfig<string>>) { const openDirtyConfirmation = useCallback(
const { props, ...restConfig } = config || {}; (config?: Partial<DialogConfig<string>>) => {
const { props, ...restConfig } = config || {};
openAlertDialog({ setShowDirtyConfirmation(true);
...config, openAlertDialog({
title: 'Unsaved changes', ...config,
payload: title: 'Unsaved changes',
'You have unsaved local changes. Are you sure you want to discard them?', payload:
props: { 'You have unsaved local changes. Are you sure you want to discard them?',
...props, props: {
primaryButtonText: 'Discard', ...props,
primaryButtonColor: 'error', primaryButtonText: 'Discard',
}, primaryButtonColor: 'error',
...restConfig, },
}); ...restConfig,
} });
},
[],
);
function closeDrawerWithDirtyGuard(event?: BaseSyntheticEvent) { function closeDrawerWithDirtyGuard(event?: BaseSyntheticEvent) {
if (isDrawerDirty.current && event?.type !== 'submit') { if (isDrawerDirty.current && event?.type !== 'submit') {
setShowDirtyConfirmation(true);
openDirtyConfirmation({ props: { onPrimaryAction: closeDrawer } }); openDirtyConfirmation({ props: { onPrimaryAction: closeDrawer } });
return; return;
} }
@@ -190,7 +207,6 @@ function DialogProvider({ children }: PropsWithChildren<unknown>) {
function closeDialogWithDirtyGuard(event?: BaseSyntheticEvent) { function closeDialogWithDirtyGuard(event?: BaseSyntheticEvent) {
if (isDialogDirty.current && event?.type !== 'submit') { if (isDialogDirty.current && event?.type !== 'submit') {
setShowDirtyConfirmation(true);
openDirtyConfirmation({ props: { onPrimaryAction: closeDialog } }); openDirtyConfirmation({ props: { onPrimaryAction: closeDialog } });
return; return;
} }
@@ -248,6 +264,32 @@ function DialogProvider({ children }: PropsWithChildren<unknown>) {
onCancel: closeDrawerWithDirtyGuard, onCancel: closeDrawerWithDirtyGuard,
}; };
useEffect(() => {
function handleCloseDrawerAndDialog() {
if (isDrawerDirty.current || isDialogDirty.current) {
openDirtyConfirmation({
props: {
onPrimaryAction: () => {
closeDialog();
closeDrawer();
},
},
});
throw new Error('Unsaved changes');
}
closeDrawer();
closeDialog();
}
router?.events?.on?.('routeChangeStart', handleCloseDrawerAndDialog);
return () => {
router?.events?.off?.('routeChangeStart', handleCloseDrawerAndDialog);
};
}, [closeDialog, closeDrawer, openDirtyConfirmation, router.events]);
return ( return (
<DialogContext.Provider value={contextValue}> <DialogContext.Provider value={contextValue}>
<AlertDialog <AlertDialog
@@ -315,6 +357,10 @@ function DialogProvider({ children }: PropsWithChildren<unknown>) {
<EditRoleForm {...sharedDialogProps} /> <EditRoleForm {...sharedDialogProps} />
)} )}
{activeDialogType === 'CREATE_USER' && (
<CreateUserForm {...sharedDialogProps} />
)}
{activeDialogType === 'CREATE_PERMISSION_VARIABLE' && ( {activeDialogType === 'CREATE_PERMISSION_VARIABLE' && (
<CreatePermissionVariableForm {...sharedDialogProps} /> <CreatePermissionVariableForm {...sharedDialogProps} />
)} )}
@@ -330,6 +376,17 @@ function DialogProvider({ children }: PropsWithChildren<unknown>) {
{activeDialogType === 'EDIT_ENVIRONMENT_VARIABLE' && ( {activeDialogType === 'EDIT_ENVIRONMENT_VARIABLE' && (
<EditEnvironmentVariableForm {...sharedDialogProps} /> <EditEnvironmentVariableForm {...sharedDialogProps} />
)} )}
{activeDialogType === 'EDIT_USER_PASSWORD' && (
<EditUserPasswordForm
{...sharedDialogProps}
user={sharedDialogProps?.user}
/>
)}
{activeDialogType === 'EDIT_JWT_SECRET' && (
<EditJwtSecretForm {...sharedDialogProps} />
)}
</RetryableErrorBoundary> </RetryableErrorBoundary>
</BaseDialog> </BaseDialog>
@@ -375,6 +432,10 @@ function DialogProvider({ children }: PropsWithChildren<unknown>) {
schema={drawerPayload?.schema} schema={drawerPayload?.schema}
/> />
)} )}
{activeDrawerType === 'EDIT_USER' && (
<EditUserForm {...sharedDrawerProps} {...drawerPayload} />
)}
</RetryableErrorBoundary> </RetryableErrorBoundary>
</Drawer> </Drawer>

View File

@@ -0,0 +1,138 @@
import type { ButtonProps } from '@/ui/v2/Button';
import Button from '@/ui/v2/Button';
import Input from '@/ui/v2/Input';
import Text from '@/ui/v2/Text';
import ChevronLeftIcon from '@/ui/v2/icons/ChevronLeftIcon';
import ChevronRightIcon from '@/ui/v2/icons/ChevronRightIcon';
import type { DetailedHTMLProps, HTMLProps } from 'react';
import { twMerge } from 'tailwind-merge';
export type PaginationProps = DetailedHTMLProps<
HTMLProps<HTMLDivElement>,
HTMLDivElement
> & {
/**
* Total number of pages.
*/
totalNrOfPages: number;
/**
* Number of total elements per page.
*/
elementsPerPage?: number;
/**
* Total number of elements.
*/
totalNrOfElements: number;
/**
* Current page number.
*/
currentPageNumber: number;
/**
* Function to be called when navigating to the previous page.
*/
onPrevPageClick: VoidFunction;
/**
* Function to be called when navigating to the next page.
*/
onNextPageClick: VoidFunction;
/**
* Function to be called when a new page number is submitted.
*/
onPageChange: (page: number) => void;
/**
* Props for component slots.
*/
slotProps?: {
/**
* Props to be passed to the next button component.
*/
nextButton?: Partial<ButtonProps>;
/**
* Props to be passed to the previous button component.
*/
prevButton?: Partial<ButtonProps>;
};
};
export default function Pagination({
className,
totalNrOfPages,
currentPageNumber,
onPrevPageClick,
onNextPageClick,
slotProps,
elementsPerPage,
onPageChange,
totalNrOfElements,
...props
}: PaginationProps) {
return (
<div
className={twMerge('grid grid-flow-col items-center gap-2', className)}
{...props}
>
<div className="grid justify-start grid-flow-col gap-2">
<Button
variant="outlined"
color="secondary"
className="block text-xs"
disabled={currentPageNumber === 1}
aria-label="Previous page"
onClick={onPrevPageClick}
>
<ChevronLeftIcon className="w-4 h-4" />
Back
</Button>
<div className="grid items-center grid-cols-3 gap-1 text-center grid-col !text-greyscaleGreyDark">
<Text className="text-xs align-middle ">Page</Text>
<Input
value={currentPageNumber}
onChange={(e) => {
const page = parseInt(e.target.value, 10);
if (page > 0 && page <= totalNrOfPages) {
onPageChange(page);
}
}}
disabled={totalNrOfPages === 1}
color="secondary"
slotProps={{
inputRoot: {
className: 'w-4 h-2.5 text-center !text-[11.5px]',
},
}}
/>
<Text className="self-center text-xs align-middle text-greyscaleGreyDark">
of {totalNrOfPages}
</Text>
</div>
<Button
variant="outlined"
color="secondary"
className="text-xs"
aria-label="Next page"
disabled={currentPageNumber === totalNrOfPages}
onClick={onNextPageClick}
{...slotProps?.nextButton}
>
Next
<ChevronRightIcon className="w-4 h-4" />
</Button>
</div>
<div className="flex flex-row items-center justify-end text-center gap-x-1">
<Text className="text-xs text-greyscaleGreyDark">
{currentPageNumber === 1 && currentPageNumber}
{currentPageNumber === 2 && elementsPerPage + currentPageNumber - 1}
{currentPageNumber > 2 &&
(currentPageNumber - 1) * elementsPerPage + 1}{' '}
-{' '}
{totalNrOfElements < currentPageNumber * elementsPerPage
? totalNrOfElements
: currentPageNumber * elementsPerPage}{' '}
of {totalNrOfElements} users
</Text>
</div>
</div>
);
}

View File

@@ -0,0 +1,3 @@
export * from './Pagination';
export { default } from './Pagination';

View File

@@ -0,0 +1,48 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react';
import type { PropsWithoutRef } from 'react';
import type { ReadOnlyToggleProps } from './ReadOnlyToggle';
import ReadOnlyToggle from './ReadOnlyToggle';
export default {
title: 'Common Components / ReadOnlyToggle',
component: ReadOnlyToggle,
argTypes: {
checked: {
options: [null, true, false],
control: { type: 'radio' },
},
},
} as ComponentMeta<typeof ReadOnlyToggle>;
const Template: ComponentStory<typeof ReadOnlyToggle> = function Template(
args: PropsWithoutRef<ReadOnlyToggleProps>,
) {
return <ReadOnlyToggle {...args} />;
};
export const Null = Template.bind({});
Null.args = {
checked: null,
};
export const True = Template.bind({});
True.args = {
checked: true,
};
export const False = Template.bind({});
False.args = {
checked: false,
};
export const CustomClasses = Template.bind({});
CustomClasses.args = {
checked: true,
className: '!bg-red',
slotProps: {
label: {
className: '!text-sm !text-white',
},
},
};

View File

@@ -1,39 +1,79 @@
import type { ForwardedRef } from 'react'; import type { TextProps } from '@/ui/v2/Text';
import Text from '@/ui/v2/Text';
import type { DetailedHTMLProps, ForwardedRef, HTMLProps } from 'react';
import { forwardRef } from 'react'; import { forwardRef } from 'react';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
const ReadOnlyToggle = forwardRef( export interface ReadOnlyToggleProps
( extends DetailedHTMLProps<HTMLProps<HTMLSpanElement>, HTMLSpanElement> {
{ checked }: { checked: boolean | null }, /**
ref: ForwardedRef<HTMLSpanElement>, * Determines whether the toggle is checked or not.
) => ( */
checked?: boolean | null;
/**
* Props passed to specific component slots.
*/
slotProps?: {
/**
* Props passed to the root `<span />` element.
*/
root?: DetailedHTMLProps<HTMLProps<HTMLSpanElement>, HTMLSpanElement>;
/**
* Props passed to the label.
*/
label?: TextProps;
};
}
function ReadOnlyToggle(
{ checked, className, slotProps = {}, ...props }: ReadOnlyToggleProps,
ref: ForwardedRef<HTMLSpanElement>,
) {
return (
<span <span
className="inline-grid h-full w-full grid-flow-col items-center justify-start gap-1.5" {...props}
{...(slotProps?.root || {})}
className={twMerge(
'inline-grid h-full w-full grid-flow-col items-center justify-start gap-1.5',
slotProps?.root?.className,
className,
)}
ref={ref} ref={ref}
> >
<span <span
className={twMerge( className={twMerge(
'box-border inline-grid h-3 w-5 items-center rounded-full px-0.5', 'box-border inline-grid h-3 w-5 items-center rounded-full px-0.5',
checked === true && 'justify-end bg-greyscaleDark', checked === true &&
'border-1 border-transparent justify-end bg-greyscaleDark',
checked === false && 'border-1 border-greyscaleDark', checked === false && 'border-1 border-greyscaleDark',
checked === null && 'border-1 border-greyscaleDark', checked === null && 'border-1 border-greyscaleDark',
)} )}
> >
<span <span
className={twMerge( className={twMerge(
'inline rounded-full', 'inline-block rounded-full',
checked === true && 'h-2 w-2 bg-white', checked === true && 'h-2 w-2 bg-white',
checked === false && 'h-2 w-2 bg-greyscaleDark', checked === false && 'h-2 w-2 bg-greyscaleDark',
checked === null && 'h-px w-2 justify-self-center bg-greyscaleDark', checked === null &&
'h-px my-px w-2 justify-self-center bg-greyscaleDark',
)} )}
/> />
</span> </span>
<span className="truncate text-xs font-normal">{String(checked)}</span> <Text
{...(slotProps?.label || {})}
component="span"
className={twMerge(
'truncate !text-xs font-normal',
slotProps?.label?.className,
)}
>
{String(checked)}
</Text>
</span> </span>
), );
); }
ReadOnlyToggle.displayName = 'NhostReadOnlyToggle'; ReadOnlyToggle.displayName = 'NhostReadOnlyToggle';
export default ReadOnlyToggle; export default forwardRef(ReadOnlyToggle);

View File

@@ -3,7 +3,7 @@ import ControlledCheckbox from '@/components/common/ControlledCheckbox';
import { useDialog } from '@/components/common/DialogProvider'; import { useDialog } from '@/components/common/DialogProvider';
import Form from '@/components/common/Form'; import Form from '@/components/common/Form';
import InlineCode from '@/components/common/InlineCode'; import InlineCode from '@/components/common/InlineCode';
import type { ColumnType, DatabaseColumn } from '@/types/data-browser'; import type { ColumnType, DatabaseColumn } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import Input from '@/ui/v2/Input'; import Input from '@/ui/v2/Input';
import { OptionBase } from '@/ui/v2/Option'; import { OptionBase } from '@/ui/v2/Option';

View File

@@ -1,6 +1,6 @@
import { useDialog } from '@/components/common/DialogProvider'; import { useDialog } from '@/components/common/DialogProvider';
import type { BaseForeignKeyFormValues } from '@/components/data-browser/BaseForeignKeyForm'; import type { BaseForeignKeyFormValues } from '@/components/dataBrowser/BaseForeignKeyForm';
import type { DatabaseColumn } from '@/types/data-browser'; import type { DatabaseColumn } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import ArrowRightIcon from '@/ui/v2/icons/ArrowRightIcon'; import ArrowRightIcon from '@/ui/v2/icons/ArrowRightIcon';
import LinkIcon from '@/ui/v2/icons/LinkIcon'; import LinkIcon from '@/ui/v2/icons/LinkIcon';

View File

@@ -2,7 +2,7 @@ import ControlledSelect from '@/components/common/ControlledSelect';
import { useDialog } from '@/components/common/DialogProvider'; import { useDialog } from '@/components/common/DialogProvider';
import Form from '@/components/common/Form'; import Form from '@/components/common/Form';
import useDatabaseQuery from '@/hooks/dataBrowser/useDatabaseQuery'; import useDatabaseQuery from '@/hooks/dataBrowser/useDatabaseQuery';
import type { DatabaseColumn, ForeignKeyRelation } from '@/types/data-browser'; import type { DatabaseColumn, ForeignKeyRelation } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import Divider from '@/ui/v2/Divider'; import Divider from '@/ui/v2/Divider';
import Option from '@/ui/v2/Option'; import Option from '@/ui/v2/Option';

View File

@@ -1,6 +1,6 @@
import type { ControlledSelectProps } from '@/components/common/ControlledSelect'; import type { ControlledSelectProps } from '@/components/common/ControlledSelect';
import ControlledSelect from '@/components/common/ControlledSelect'; import ControlledSelect from '@/components/common/ControlledSelect';
import type { NormalizedQueryDataRow } from '@/types/data-browser'; import type { NormalizedQueryDataRow } from '@/types/dataBrowser';
import Option from '@/ui/v2/Option'; import Option from '@/ui/v2/Option';
import type { ForwardedRef, PropsWithoutRef } from 'react'; import type { ForwardedRef, PropsWithoutRef } from 'react';
import { forwardRef } from 'react'; import { forwardRef } from 'react';

View File

@@ -1,5 +1,5 @@
import ControlledSelect from '@/components/common/ControlledSelect'; import ControlledSelect from '@/components/common/ControlledSelect';
import type { NormalizedQueryDataRow } from '@/types/data-browser'; import type { NormalizedQueryDataRow } from '@/types/dataBrowser';
import Option from '@/ui/v2/Option'; import Option from '@/ui/v2/Option';
import { useFormContext, useFormState, useWatch } from 'react-hook-form'; import { useFormContext, useFormState, useWatch } from 'react-hook-form';
import type { BaseForeignKeyFormValues } from './BaseForeignKeyForm'; import type { BaseForeignKeyFormValues } from './BaseForeignKeyForm';

View File

@@ -1,10 +1,10 @@
import { useDialog } from '@/components/common/DialogProvider'; import { useDialog } from '@/components/common/DialogProvider';
import Form from '@/components/common/Form'; import Form from '@/components/common/Form';
import DatabaseRecordInputGroup from '@/components/data-browser/DatabaseRecordInputGroup'; import DatabaseRecordInputGroup from '@/components/dataBrowser/DatabaseRecordInputGroup';
import type { import type {
ColumnInsertOptions, ColumnInsertOptions,
DataBrowserGridColumn, DataBrowserGridColumn,
} from '@/types/data-browser'; } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';

View File

@@ -1,7 +1,7 @@
import { useDialog } from '@/components/common/DialogProvider'; import { useDialog } from '@/components/common/DialogProvider';
import Form from '@/components/common/Form'; import Form from '@/components/common/Form';
import { baseColumnValidationSchema } from '@/components/data-browser/BaseColumnForm'; import { baseColumnValidationSchema } from '@/components/dataBrowser/BaseColumnForm';
import type { DatabaseTable, ForeignKeyRelation } from '@/types/data-browser'; import type { DatabaseTable, ForeignKeyRelation } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import Input from '@/ui/v2/Input'; import Input from '@/ui/v2/Input';
import { useEffect } from 'react'; import { useEffect } from 'react';

View File

@@ -1,7 +1,7 @@
import ControlledAutocomplete from '@/components/common/ControlledAutocomplete'; import ControlledAutocomplete from '@/components/common/ControlledAutocomplete';
import ControlledCheckbox from '@/components/common/ControlledCheckbox'; import ControlledCheckbox from '@/components/common/ControlledCheckbox';
import InlineCode from '@/components/common/InlineCode'; import InlineCode from '@/components/common/InlineCode';
import type { ColumnType, ForeignKeyRelation } from '@/types/data-browser'; import type { ColumnType, ForeignKeyRelation } from '@/types/dataBrowser';
import type { ButtonProps } from '@/ui/v2/Button'; import type { ButtonProps } from '@/ui/v2/Button';
import type { CheckboxProps } from '@/ui/v2/Checkbox'; import type { CheckboxProps } from '@/ui/v2/Checkbox';
import IconButton from '@/ui/v2/IconButton'; import IconButton from '@/ui/v2/IconButton';

View File

@@ -1,4 +1,4 @@
import type { ForeignKeyRelation } from '@/types/data-browser'; import type { ForeignKeyRelation } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import ArrowRightIcon from '@/ui/v2/icons/ArrowRightIcon'; import ArrowRightIcon from '@/ui/v2/icons/ArrowRightIcon';
import LinkIcon from '@/ui/v2/icons/LinkIcon'; import LinkIcon from '@/ui/v2/icons/LinkIcon';

View File

@@ -1,6 +1,6 @@
import { useDialog } from '@/components/common/DialogProvider'; import { useDialog } from '@/components/common/DialogProvider';
import type { BaseForeignKeyFormValues } from '@/components/data-browser/BaseForeignKeyForm'; import type { BaseForeignKeyFormValues } from '@/components/dataBrowser/BaseForeignKeyForm';
import type { DatabaseColumn, ForeignKeyRelation } from '@/types/data-browser'; import type { DatabaseColumn, ForeignKeyRelation } from '@/types/dataBrowser';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import PlusIcon from '@/ui/v2/icons/PlusIcon'; import PlusIcon from '@/ui/v2/icons/PlusIcon';
import InputLabel from '@/ui/v2/InputLabel'; import InputLabel from '@/ui/v2/InputLabel';

View File

@@ -1,5 +1,5 @@
import ControlledSelect from '@/components/common/ControlledSelect'; import ControlledSelect from '@/components/common/ControlledSelect';
import type { ColumnType, DatabaseColumn } from '@/types/data-browser'; import type { ColumnType, DatabaseColumn } from '@/types/dataBrowser';
import Option from '@/ui/v2/Option'; import Option from '@/ui/v2/Option';
import { identityTypes } from '@/utils/dataBrowser/postgresqlConstants'; import { identityTypes } from '@/utils/dataBrowser/postgresqlConstants';
import { useMemo } from 'react'; import { useMemo } from 'react';

View File

@@ -1,5 +1,5 @@
import ControlledSelect from '@/components/common/ControlledSelect'; import ControlledSelect from '@/components/common/ControlledSelect';
import type { DatabaseColumn } from '@/types/data-browser'; import type { DatabaseColumn } from '@/types/dataBrowser';
import Option from '@/ui/v2/Option'; import Option from '@/ui/v2/Option';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useFormState, useWatch } from 'react-hook-form'; import { useFormState, useWatch } from 'react-hook-form';

View File

@@ -0,0 +1,129 @@
import Form from '@/components/common/Form';
import Button from '@/ui/v2/Button';
import Text from '@/ui/v2/Text';
import hasuraMetadataQuery from '@/utils/msw/mocks/rest/hasuraMetadataQuery';
import tableQuery from '@/utils/msw/mocks/rest/tableQuery';
import type { ComponentMeta, ComponentStory } from '@storybook/react';
import { useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import type { ColumnAutocompleteProps } from './ColumnAutocomplete';
import ColumnAutocomplete from './ColumnAutocomplete';
export default {
title: 'Data Browser / ColumnAutocomplete',
component: ColumnAutocomplete,
parameters: {
docs: {
source: {
type: 'code',
},
},
},
} as ComponentMeta<typeof ColumnAutocomplete>;
const defaultParameters = {
nextRouter: {
path: '/[workspaceSlug]/[appSlug]/database/browser/[dataSourceSlug]/[schemaSlug]/[tableSlug]',
asPath: '/workspace/app/database/browser/default/public/users',
query: {
workspaceSlug: 'workspace',
appSlug: 'app',
dataSourceSlug: 'default',
schemaSlug: 'public',
tableSlug: 'books',
},
},
msw: {
handlers: [tableQuery, hasuraMetadataQuery],
},
};
const Template: ComponentStory<typeof ColumnAutocomplete> = function Template(
args: ColumnAutocompleteProps,
) {
const [submittedValues, setSubmittedValues] = useState<string>('');
const form = useForm<{ firstReference: string; secondReference: string }>({
defaultValues: {
firstReference: null,
secondReference: null,
},
});
function handleSubmit(values: {
firstReference: string;
secondReference: string;
}) {
setSubmittedValues(JSON.stringify(values, null, 2));
}
return (
<div className="grid grid-flow-row gap-2">
<FormProvider {...form}>
<Form onSubmit={handleSubmit} className="grid grid-flow-row gap-2">
<ColumnAutocomplete
{...args}
name="firstReference"
label="First Reference"
onChange={(_event, newValue) =>
form.setValue('firstReference', newValue.value, {
shouldDirty: true,
})
}
onInitialized={(newValue) => {
form.setValue('firstReference', newValue.value, {
shouldDirty: true,
});
}}
/>
<ColumnAutocomplete
{...args}
name="secondReference"
label="Second Reference"
onChange={(_event, newValue) =>
form.setValue('secondReference', newValue.value, {
shouldDirty: true,
})
}
onInitialized={(newValue) => {
form.setValue('secondReference', newValue.value, {
shouldDirty: true,
});
}}
/>
<Button type="submit" className="justify-self-start">
Submit
</Button>
</Form>
</FormProvider>
<Text component="pre" className="!font-mono !text-gray-700">
{submittedValues || 'The form has not been submitted yet.'}
</Text>
</div>
);
};
export const Basic = Template.bind({});
Basic.args = {
schema: 'public',
table: 'books',
};
Basic.parameters = defaultParameters;
export const DefaultValue = Template.bind({});
DefaultValue.args = {
schema: 'public',
table: 'books',
value: 'author.id',
};
DefaultValue.parameters = defaultParameters;
export const DisabledRelationships = Template.bind({});
DisabledRelationships.args = {
schema: 'public',
table: 'books',
disableRelationships: true,
};
DisabledRelationships.parameters = defaultParameters;

View File

@@ -0,0 +1,33 @@
import customClaimsQuery from '@/utils/msw/mocks/graphql/customClaimsQuery';
import hasuraMetadataQuery from '@/utils/msw/mocks/rest/hasuraMetadataQuery';
import tableQuery from '@/utils/msw/mocks/rest/tableQuery';
import { render, screen } from '@/utils/testUtils';
import { setupServer } from 'msw/node';
import { test, vi } from 'vitest';
import ColumnAutocomplete from './ColumnAutocomplete';
const server = setupServer(tableQuery, hasuraMetadataQuery, customClaimsQuery);
beforeAll(() => server.listen({ onUnhandledRequest: 'warn' }));
afterEach(() => server.resetHandlers());
afterAll(() => {
server.close();
vi.restoreAllMocks();
});
test('should render a combobox', () => {
render(
<ColumnAutocomplete
schema="public"
table="books"
label="Column Autocomplete"
/>,
);
expect(
screen.getByRole('combobox', { name: /column autocomplete/i }),
).toBeInTheDocument();
});
// Note: Network requests don't go through in tests, so we can't test the
// autocomplete functionality for now.

View File

@@ -0,0 +1,382 @@
import InlineCode from '@/components/common/InlineCode';
import useMetadataQuery from '@/hooks/dataBrowser/useMetadataQuery';
import useTableQuery from '@/hooks/dataBrowser/useTableQuery';
import ActivityIndicator from '@/ui/v2/ActivityIndicator';
import type { AutocompleteOption } from '@/ui/v2/Autocomplete';
import { AutocompletePopper } from '@/ui/v2/Autocomplete';
import IconButton from '@/ui/v2/IconButton';
import ArrowLeftIcon from '@/ui/v2/icons/ArrowLeftIcon';
import type { InputProps } from '@/ui/v2/Input';
import Input from '@/ui/v2/Input';
import List from '@/ui/v2/List';
import { OptionBase } from '@/ui/v2/Option';
import { OptionGroupBase } from '@/ui/v2/OptionGroup';
import Text from '@/ui/v2/Text';
import getTruncatedText from '@/utils/common/getTruncatedText';
import type { AutocompleteGroupedOption } from '@mui/base/AutocompleteUnstyled';
import { useAutocomplete } from '@mui/base/AutocompleteUnstyled';
import type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';
import { autocompleteClasses } from '@mui/material/Autocomplete';
import type {
ForwardedRef,
HTMLAttributes,
PropsWithoutRef,
SyntheticEvent,
} from 'react';
import { forwardRef, useEffect, useState } from 'react';
import { twMerge } from 'tailwind-merge';
import type { UseAsyncInitialValueOptions } from './useAsyncInitialValue';
import useAsyncInitialValue from './useAsyncInitialValue';
import type { UseColumnGroupsOptions } from './useColumnGroups';
import useColumnGroups from './useColumnGroups';
export interface ColumnAutocompleteProps
extends Omit<PropsWithoutRef<InputProps>, 'onChange'> {
/**
* Schema where the `table` is located.
*/
schema: string;
/**
* Table to get the columns from.
*/
table: string;
/**
* Function to be called when the value changes.
*/
onChange?: (
event: SyntheticEvent,
value: {
value: string;
columnMetadata?: Record<string, any>;
disableReset?: boolean;
},
) => void;
/**
* Function to be called when the input is asynchronously initialized.
*/
onInitialized?: UseAsyncInitialValueOptions['onInitialized'];
/**
* Class name to be applied to the root element.
*/
rootClassName?: string;
/**
* Determines if the autocomplete should allow relationships.
*/
disableRelationships?: UseColumnGroupsOptions['disableRelationships'];
}
function renderGroup(params: AutocompleteRenderGroupParams) {
return (
<li key={params.key}>
<OptionGroupBase>{params.group}</OptionGroupBase>
<List>{params.children}</List>
</li>
);
}
function renderOption(
option: AutocompleteOption<string>,
optionProps: HTMLAttributes<HTMLLIElement>,
) {
return (
<OptionBase
{...optionProps}
className="grid grid-flow-col items-baseline justify-start justify-items-start gap-1.5"
>
<span>{option.label}</span>
{option.group === 'columns' && (
<InlineCode>{option.metadata?.type || option.value}</InlineCode>
)}
</OptionBase>
);
}
function ColumnAutocomplete(
{
rootClassName,
schema: defaultSchema,
table: defaultTable,
value: externalValue,
disableRelationships,
onChange,
onInitialized,
...props
}: ColumnAutocompleteProps,
ref: ForwardedRef<HTMLInputElement>,
) {
const [open, setOpen] = useState(false);
const [activeRelationship, setActiveRelationship] = useState<any>();
const selectedSchema = activeRelationship?.schema || defaultSchema;
const selectedTable = activeRelationship?.table || defaultTable;
const {
data: tableData,
status: tableStatus,
error: tableError,
isFetching: isTableFetching,
} = useTableQuery([`default.${selectedSchema}.${selectedTable}`], {
schema: selectedSchema,
table: selectedTable,
queryOptions: { refetchOnWindowFocus: false },
});
const {
data: metadata,
status: metadataStatus,
error: metadataError,
isFetching: isMetadataFetching,
} = useMetadataQuery([`default.metadata`], {
queryOptions: { refetchOnWindowFocus: false },
});
const {
initialized,
inputValue,
setInputValue,
selectedColumn,
setSelectedColumn,
selectedRelationships,
setSelectedRelationships,
relationshipDotNotation,
activeRelationship: asyncActiveRelationship,
} = useAsyncInitialValue({
selectedSchema,
selectedTable,
initialValue: externalValue as string,
isTableLoading: tableStatus === 'loading' || isTableFetching,
isMetadataLoading: metadataStatus === 'loading' || isMetadataFetching,
tableData,
metadata,
onInitialized,
});
useEffect(() => {
setActiveRelationship(asyncActiveRelationship);
}, [asyncActiveRelationship]);
function isOptionEqualToValue(
option: AutocompleteOption,
value: NonNullable<string | AutocompleteOption>,
) {
if (!value) {
return false;
}
if (typeof value === 'string') {
return option.value === value;
}
return option.value === value.value && option.custom === value.custom;
}
function handleChange(
event: SyntheticEvent,
value: NonNullable<string | AutocompleteOption>,
) {
if (typeof value === 'string' || Array.isArray(value) || !value) {
return;
}
if ('group' in value && value.group === 'columns') {
setSelectedColumn(value);
setOpen(false);
setInputValue(value.value);
onChange?.(event, {
value:
selectedRelationships.length > 0
? [relationshipDotNotation, value.value].join('.')
: value.value,
columnMetadata: value.metadata,
});
return;
}
setInputValue('');
setSelectedColumn(null);
setSelectedRelationships((currentRelationships) => [
...currentRelationships,
value.metadata?.target,
]);
}
const options = useColumnGroups({
selectedSchema,
selectedTable,
tableData,
metadata,
disableRelationships,
});
const {
popupOpen,
anchorEl,
setAnchorEl,
getRootProps,
getInputLabelProps,
getInputProps,
getListboxProps,
getOptionProps,
groupedOptions,
} = useAutocomplete({
open,
inputValue,
options,
id: props?.name,
openOnFocus: true,
disableCloseOnSelect: true,
value: selectedColumn,
onClose: () => setOpen(false),
groupBy: (option) => option.group,
isOptionEqualToValue,
onChange: handleChange,
});
return (
<>
<div {...getRootProps()} className={rootClassName}>
<Input
{...props}
ref={ref}
fullWidth
slotProps={{
...(props.slotProps || {}),
label: getInputLabelProps(),
input: { ...(props.slotProps?.input || {}), ref: setAnchorEl },
inputRoot: {
...getInputProps(),
className: twMerge(
Boolean(selectedColumn) || Boolean(relationshipDotNotation)
? '!pl-0'
: null,
props.slotProps?.inputRoot?.className,
),
},
}}
onFocus={() => setOpen(true)}
onClick={() => setOpen(true)}
error={Boolean(tableError || metadataError)}
helperText={String(tableError || metadataError || '')}
onChange={(event) => setInputValue(event.target.value)}
value={inputValue}
startAdornment={
selectedColumn || relationshipDotNotation ? (
<Text className="!ml-2 lg:max-w-[200px] flex-shrink-0 truncate">
<span className="text-greyscaleGrey">{defaultTable}</span>.
{relationshipDotNotation && (
<>
<span className="hidden lg:inline">
{getTruncatedText(relationshipDotNotation, 15, 'start')}.
</span>
<span className="inline lg:hidden">
{relationshipDotNotation}.
</span>
</>
)}
</Text>
) : null
}
endAdornment={
tableStatus === 'loading' ||
metadataStatus === 'loading' ||
!initialized ? (
<ActivityIndicator className="mr-2" delay={500} />
) : null
}
/>
</div>
<AutocompletePopper
onMouseDown={(event) => event.preventDefault()}
modifiers={[{ name: 'offset', options: { offset: [0, 10] } }]}
placement="bottom-start"
open={popupOpen}
anchorEl={anchorEl}
style={{ width: anchorEl?.parentElement?.clientWidth }}
>
<div className={autocompleteClasses.paper}>
<div className="px-3 py-2.5 border-b-1 border-greyscale-100 grid grid-flow-col gap-2 justify-start items-center">
{selectedRelationships.length > 0 && (
<IconButton
variant="borderless"
color="secondary"
onClick={(event) => {
event.stopPropagation();
setInputValue('');
setSelectedColumn(null);
setSelectedRelationships((activeRelationships) =>
activeRelationships.slice(0, -1),
);
}}
>
<ArrowLeftIcon className="w-4 h-4" />
</IconButton>
)}
<Text className="truncate direction-rtl text-left">
<span className="!text-greyscaleMedium">{defaultTable}</span>
{relationshipDotNotation && (
<>
<span className="hidden lg:inline">
.{getTruncatedText(relationshipDotNotation, 20, 'start')}
</span>
<span className="inline lg:hidden">
.{relationshipDotNotation}
</span>
</>
)}
</Text>
</div>
{(tableStatus === 'loading' ||
metadataStatus === 'loading' ||
!initialized) && (
<div className="p-2">
<ActivityIndicator label="Loading..." />
</div>
)}
{groupedOptions.length > 0 && (
<List
{...getListboxProps()}
className={autocompleteClasses.listbox}
>
{(
groupedOptions as AutocompleteGroupedOption<
typeof options[number]
>[]
).map((optionGroup) =>
renderGroup({
key: `${optionGroup.key}`,
group: optionGroup.group,
children: optionGroup.options.map((option, index) =>
renderOption(
option,
getOptionProps({
option,
index: optionGroup.index + index,
}),
),
),
}),
)}
</List>
)}
{groupedOptions.length === 0 && Boolean(anchorEl) && (
<Text className={autocompleteClasses.noOptions}>No options</Text>
)}
</div>
</AutocompletePopper>
</>
);
}
export default forwardRef(ColumnAutocomplete);

View File

@@ -0,0 +1,2 @@
export * from './ColumnAutocomplete';
export { default } from './ColumnAutocomplete';

View File

@@ -0,0 +1,263 @@
import type { FetchMetadataReturnType } from '@/hooks/dataBrowser/useMetadataQuery';
import type { FetchTableReturnType } from '@/hooks/dataBrowser/useTableQuery';
import type { HasuraMetadataTable } from '@/types/dataBrowser';
import type { AutocompleteOption } from '@/ui/v2/Autocomplete';
import { useEffect, useState } from 'react';
export interface UseAsyncInitialValueOptions {
/**
* Selected schema to be used to determine the initial value.
*/
selectedSchema?: string;
/**
* Selected table to be used to determine the initial value.
*/
selectedTable?: string;
/**
* Initial value to be used before the async value is loaded.
*/
initialValue?: string;
/**
* Determines whether or not the table data is loading.
*/
isTableLoading?: boolean;
/**
* Determines whether or not the metadata is loading.
*/
isMetadataLoading?: boolean;
/**
* Table data to be used to determine the initial value.
*/
tableData?: FetchTableReturnType;
/**
* Metadata to be used to determine the initial value.
*/
metadata?: FetchMetadataReturnType;
/**
* Function to be called when the input is asynchronously initialized.
*/
onInitialized?: (value: {
value: string;
columnMetadata?: Record<string, any>;
}) => void;
}
export default function useAsyncInitialValue({
selectedSchema,
selectedTable,
initialValue,
isTableLoading,
isMetadataLoading,
tableData,
metadata,
onInitialized,
}: UseAsyncInitialValueOptions) {
const currentTablePath = `${selectedSchema}.${selectedTable}`;
const [inputValue, setInputValue] = useState('');
const [initialized, setInitialized] = useState(false);
// We might not going to have the most up-to-date table data because the
// relationship is loaded asynchronously, so we need to make sure we don't
// look for the column in a stale table when initializing
const [asyncTablePath, setAsyncTablePath] = useState(currentTablePath);
const [remainingColumnPath, setRemainingColumnPath] = useState(
initialValue?.split('.') || [],
);
const [selectedRelationships, setSelectedRelationships] = useState<
{ schema: string; table: string; name: string }[]
>([]);
const relationshipDotNotation =
initialized && selectedRelationships?.length > 0
? selectedRelationships.map((relationship) => relationship.name).join('.')
: '';
const [selectedColumn, setSelectedColumn] =
useState<AutocompleteOption>(null);
const activeRelationship =
selectedRelationships[selectedRelationships.length - 1];
useEffect(() => {
if (remainingColumnPath?.length > 0 || initialized) {
return;
}
setInitialized(true);
if (!selectedColumn) {
return;
}
onInitialized?.({
value:
selectedRelationships.length > 0
? [relationshipDotNotation, selectedColumn.value].join('.')
: selectedColumn.value,
columnMetadata: selectedColumn.metadata,
});
}, [
initialized,
onInitialized,
relationshipDotNotation,
remainingColumnPath?.length,
selectedColumn,
selectedRelationships.length,
]);
useEffect(() => {
if (
remainingColumnPath?.length !== 1 ||
isTableLoading ||
!tableData?.columns ||
asyncTablePath !== currentTablePath
) {
return;
}
const [activeColumn] = remainingColumnPath;
// If there is a single column in the path, it means that we can look for it
// in the table columns
if (
!tableData?.columns.some((column) => column.column_name === activeColumn)
) {
setRemainingColumnPath([]);
return;
}
setSelectedColumn({
value: activeColumn,
label: activeColumn,
group: 'columns',
metadata: tableData.columns.find(
(column) => column.column_name === activeColumn,
),
});
setRemainingColumnPath((columnPath) => columnPath.slice(1));
setInputValue(activeColumn);
}, [
remainingColumnPath,
isTableLoading,
tableData?.columns,
asyncTablePath,
currentTablePath,
]);
useEffect(() => {
if (
remainingColumnPath.length < 2 ||
isTableLoading ||
isMetadataLoading ||
!tableData?.columns
) {
return;
}
const metadataMap = metadata.tables.reduce(
(map, metadataTable) =>
map.set(
`${metadataTable.table.schema}.${metadataTable.table.name}`,
metadataTable,
),
new Map<string, HasuraMetadataTable>(),
);
const [nextPath] = remainingColumnPath.slice(
0,
remainingColumnPath.length - 1,
);
const tableMetadata = metadataMap.get(`${selectedSchema}.${selectedTable}`);
const currentRelationship = [
...(tableMetadata.object_relationships || []),
...(tableMetadata.array_relationships || []),
].find(({ name }) => name === nextPath);
if (!currentRelationship) {
setRemainingColumnPath([]);
return;
}
const { foreign_key_constraint_on: metadataConstraint } =
currentRelationship.using || {};
// In some cases the metadata already contains the schema and table name
if (typeof metadataConstraint !== 'string') {
setAsyncTablePath(
`${metadataConstraint.table.schema || 'public'}.${
metadataConstraint.table.name
}`,
);
setSelectedRelationships((currentRelationships) => [
...currentRelationships,
{
schema: metadataConstraint.table.schema || 'public',
table: metadataConstraint.table.name,
name: nextPath,
},
]);
setRemainingColumnPath((columnPath) => columnPath.slice(1));
return;
}
const foreignKeyRelation = tableData?.foreignKeyRelations?.find(
({ columnName }) => {
const { foreign_key_constraint_on } = currentRelationship.using || {};
if (!foreign_key_constraint_on) {
return false;
}
if (typeof foreign_key_constraint_on === 'string') {
return foreign_key_constraint_on === columnName;
}
return foreign_key_constraint_on.column === columnName;
},
);
if (!foreignKeyRelation) {
setRemainingColumnPath([]);
return;
}
setAsyncTablePath(
`${foreignKeyRelation.referencedSchema || 'public'}.${
foreignKeyRelation.referencedTable
}`,
);
setSelectedRelationships((currentRelationships) => [
...currentRelationships,
{
schema: foreignKeyRelation.referencedSchema || 'public',
table: foreignKeyRelation.referencedTable,
name: nextPath,
},
]);
setRemainingColumnPath((columnPath) => columnPath.slice(1));
}, [
selectedSchema,
selectedTable,
metadata?.tables,
tableData?.columns,
tableData?.foreignKeyRelations,
remainingColumnPath,
isTableLoading,
isMetadataLoading,
]);
return {
initialized,
inputValue,
setInputValue,
activeRelationship,
selectedRelationships: initialized ? selectedRelationships : [],
selectedColumn: initialized ? selectedColumn : null,
setSelectedRelationships,
setSelectedColumn,
relationshipDotNotation,
};
}

View File

@@ -0,0 +1,102 @@
import type { FetchMetadataReturnType } from '@/hooks/dataBrowser/useMetadataQuery';
import type { FetchTableReturnType } from '@/hooks/dataBrowser/useTableQuery';
import type { AutocompleteOption } from '@/ui/v2/Autocomplete';
export interface UseColumnGroupsOptions {
/**
* Selected schema to be used to determines the column groups.
*/
selectedSchema?: string;
/**
* Selected table to be used to determine the column groups.
*/
selectedTable?: string;
/**
* Table data to be used to determine the column groups.
*/
tableData?: FetchTableReturnType;
/**
* Metadata to be used to determine the column groups.
*/
metadata?: FetchMetadataReturnType;
/**
* Determines whether or not to disable column groups.
*/
disableRelationships?: boolean;
}
export default function useColumnGroups({
selectedTable,
selectedSchema,
tableData,
metadata,
disableRelationships,
}: UseColumnGroupsOptions) {
const { columns, foreignKeyRelations } = tableData || {};
const columnTargetMap = foreignKeyRelations?.reduce(
(map, currentRelation) =>
map.set(currentRelation.columnName, {
schema: currentRelation.referencedSchema || 'public',
table: currentRelation.referencedTable,
}),
new Map<string, { schema: string; table: string }>(),
);
const columnOptions: AutocompleteOption[] =
columns?.map((column) => ({
label: column.column_name,
value: column.column_name,
group: 'columns',
metadata: column,
})) || [];
if (disableRelationships) {
return columnOptions;
}
const { object_relationships, array_relationships } =
metadata?.tables?.find(
({ table: metadataTable }) =>
metadataTable.name === selectedTable &&
metadataTable.schema === selectedSchema,
) || {};
const objectAndArrayRelationships = [
...(object_relationships || []),
...(array_relationships || []),
].map((relationship) => {
const { foreign_key_constraint_on } = relationship?.using || {};
if (typeof foreign_key_constraint_on === 'string') {
return {
schema: selectedSchema,
table: selectedTable,
column: foreign_key_constraint_on,
name: relationship.name,
};
}
return {
schema: foreign_key_constraint_on.table.schema,
table: foreign_key_constraint_on.table.name,
column: foreign_key_constraint_on.column,
name: relationship.name,
};
});
return [
...columnOptions,
...objectAndArrayRelationships.map((relationship) => ({
label: relationship.name,
value: relationship.name,
group: 'relationships',
metadata: {
target: {
...(columnTargetMap?.get(relationship.column) || {}),
name: relationship.name,
},
},
})),
];
}

View File

@@ -1,10 +1,10 @@
import type { import type {
BaseColumnFormProps, BaseColumnFormProps,
BaseColumnFormValues, BaseColumnFormValues,
} from '@/components/data-browser/BaseColumnForm'; } from '@/components/dataBrowser/BaseColumnForm';
import BaseColumnForm, { import BaseColumnForm, {
baseColumnValidationSchema, baseColumnValidationSchema,
} from '@/components/data-browser/BaseColumnForm'; } from '@/components/dataBrowser/BaseColumnForm';
import useCreateColumnMutation from '@/hooks/dataBrowser/useCreateColumnMutation'; import useCreateColumnMutation from '@/hooks/dataBrowser/useCreateColumnMutation';
import useTrackForeignKeyRelationsMutation from '@/hooks/dataBrowser/useTrackForeignKeyRelationsMutation'; import useTrackForeignKeyRelationsMutation from '@/hooks/dataBrowser/useTrackForeignKeyRelationsMutation';
import { Alert } from '@/ui/Alert'; import { Alert } from '@/ui/Alert';

View File

@@ -1,11 +1,11 @@
import type { import type {
BaseForeignKeyFormProps, BaseForeignKeyFormProps,
BaseForeignKeyFormValues, BaseForeignKeyFormValues,
} from '@/components/data-browser/BaseForeignKeyForm'; } from '@/components/dataBrowser/BaseForeignKeyForm';
import { import {
BaseForeignKeyForm, BaseForeignKeyForm,
baseForeignKeyValidationSchema, baseForeignKeyValidationSchema,
} from '@/components/data-browser/BaseForeignKeyForm'; } from '@/components/dataBrowser/BaseForeignKeyForm';
import { Alert } from '@/ui/Alert'; import { Alert } from '@/ui/Alert';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import { yupResolver } from '@hookform/resolvers/yup'; import { yupResolver } from '@hookform/resolvers/yup';

View File

@@ -1,7 +1,7 @@
import type { BaseRecordFormProps } from '@/components/data-browser/BaseRecordForm'; import type { BaseRecordFormProps } from '@/components/dataBrowser/BaseRecordForm';
import BaseRecordForm from '@/components/data-browser/BaseRecordForm'; import BaseRecordForm from '@/components/dataBrowser/BaseRecordForm';
import useCreateRecordMutation from '@/hooks/dataBrowser/useCreateRecordMutation'; import useCreateRecordMutation from '@/hooks/dataBrowser/useCreateRecordMutation';
import type { ColumnInsertOptions } from '@/types/data-browser'; import type { ColumnInsertOptions } from '@/types/dataBrowser';
import { Alert } from '@/ui/Alert'; import { Alert } from '@/ui/Alert';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import { createDynamicValidationSchema } from '@/utils/dataBrowser/validationSchemaHelpers'; import { createDynamicValidationSchema } from '@/utils/dataBrowser/validationSchemaHelpers';

View File

@@ -1,14 +1,14 @@
import type { import type {
BaseTableFormProps, BaseTableFormProps,
BaseTableFormValues, BaseTableFormValues,
} from '@/components/data-browser/BaseTableForm'; } from '@/components/dataBrowser/BaseTableForm';
import BaseTableForm, { import BaseTableForm, {
baseTableValidationSchema, baseTableValidationSchema,
} from '@/components/data-browser/BaseTableForm'; } from '@/components/dataBrowser/BaseTableForm';
import useCreateTableMutation from '@/hooks/dataBrowser/useCreateTableMutation'; import useCreateTableMutation from '@/hooks/dataBrowser/useCreateTableMutation';
import useTrackForeignKeyRelationMutation from '@/hooks/dataBrowser/useTrackForeignKeyRelationsMutation'; import useTrackForeignKeyRelationMutation from '@/hooks/dataBrowser/useTrackForeignKeyRelationsMutation';
import useTrackTableMutation from '@/hooks/dataBrowser/useTrackTableMutation'; import useTrackTableMutation from '@/hooks/dataBrowser/useTrackTableMutation';
import type { DatabaseTable } from '@/types/data-browser'; import type { DatabaseTable } from '@/types/dataBrowser';
import { Alert } from '@/ui/Alert'; import { Alert } from '@/ui/Alert';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import { triggerToast } from '@/utils/toast'; import { triggerToast } from '@/utils/toast';

View File

@@ -6,8 +6,8 @@ import DataGridNumericCell from '@/components/common/DataGridNumericCell';
import DataGridTextCell from '@/components/common/DataGridTextCell'; import DataGridTextCell from '@/components/common/DataGridTextCell';
import { useDialog } from '@/components/common/DialogProvider'; import { useDialog } from '@/components/common/DialogProvider';
import InlineCode from '@/components/common/InlineCode'; import InlineCode from '@/components/common/InlineCode';
import DataBrowserEmptyState from '@/components/data-browser/DataBrowserEmptyState'; import DataBrowserEmptyState from '@/components/dataBrowser/DataBrowserEmptyState';
import DataBrowserGridControls from '@/components/data-browser/DataBrowserGridControls'; import DataBrowserGridControls from '@/components/dataBrowser/DataBrowserGridControls';
import useDeleteColumnWithToastMutation from '@/hooks/dataBrowser/useDeleteColumnMutation/useDeleteColumnWithToastMutation'; import useDeleteColumnWithToastMutation from '@/hooks/dataBrowser/useDeleteColumnMutation/useDeleteColumnWithToastMutation';
import useTableQuery from '@/hooks/dataBrowser/useTableQuery'; import useTableQuery from '@/hooks/dataBrowser/useTableQuery';
import type { UpdateRecordVariables } from '@/hooks/dataBrowser/useUpdateRecordMutation'; import type { UpdateRecordVariables } from '@/hooks/dataBrowser/useUpdateRecordMutation';
@@ -17,7 +17,7 @@ import useTablePath from '@/hooks/useTablePath';
import type { import type {
DataBrowserGridColumn, DataBrowserGridColumn,
NormalizedQueryDataRow, NormalizedQueryDataRow,
} from '@/types/data-browser'; } from '@/types/dataBrowser';
import KeyIcon from '@/ui/v2/icons/KeyIcon'; import KeyIcon from '@/ui/v2/icons/KeyIcon';
import normalizeDefaultValue from '@/utils/dataBrowser/normalizeDefaultValue'; import normalizeDefaultValue from '@/utils/dataBrowser/normalizeDefaultValue';
import { import {

View File

@@ -4,7 +4,7 @@ import { useDialog } from '@/components/common/DialogProvider';
import useDeleteRecordMutation from '@/hooks/dataBrowser/useDeleteRecordMutation'; import useDeleteRecordMutation from '@/hooks/dataBrowser/useDeleteRecordMutation';
import { useCurrentWorkspaceAndApplication } from '@/hooks/useCurrentWorkspaceAndApplication'; import { useCurrentWorkspaceAndApplication } from '@/hooks/useCurrentWorkspaceAndApplication';
import useDataGridConfig from '@/hooks/useDataGridConfig'; import useDataGridConfig from '@/hooks/useDataGridConfig';
import type { DataBrowserGridColumn } from '@/types/data-browser'; import type { DataBrowserGridColumn } from '@/types/dataBrowser';
import Chip from '@/ui/Chip'; import Chip from '@/ui/Chip';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';
import { Dropdown } from '@/ui/v2/Dropdown'; import { Dropdown } from '@/ui/v2/Dropdown';

View File

@@ -1,5 +1,5 @@
import type { DataBrowserSidebarProps } from '@/components/data-browser/DataBrowserSidebar'; import type { DataBrowserSidebarProps } from '@/components/dataBrowser/DataBrowserSidebar';
import DataBrowserSidebar from '@/components/data-browser/DataBrowserSidebar'; import DataBrowserSidebar from '@/components/dataBrowser/DataBrowserSidebar';
import type { ProjectLayoutProps } from '@/components/layout/ProjectLayout'; import type { ProjectLayoutProps } from '@/components/layout/ProjectLayout';
import ProjectLayout from '@/components/layout/ProjectLayout'; import ProjectLayout from '@/components/layout/ProjectLayout';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';

View File

@@ -1,6 +1,6 @@
import InlineCode from '@/components/common/InlineCode'; import InlineCode from '@/components/common/InlineCode';
import ReadOnlyToggle from '@/components/common/ReadOnlyToggle'; import ReadOnlyToggle from '@/components/common/ReadOnlyToggle';
import type { DataBrowserGridColumn } from '@/types/data-browser'; import type { DataBrowserGridColumn } from '@/types/dataBrowser';
import KeyIcon from '@/ui/v2/icons/KeyIcon'; import KeyIcon from '@/ui/v2/icons/KeyIcon';
import Input from '@/ui/v2/Input'; import Input from '@/ui/v2/Input';
import Option from '@/ui/v2/Option'; import Option from '@/ui/v2/Option';
@@ -204,7 +204,7 @@ export default function DatabaseRecordInputGroup({
multiline={isMultiline} multiline={isMultiline}
rows={5} rows={5}
autoFocus={index === 0 && autoFocusFirstInput} autoFocus={index === 0 && autoFocusFirstInput}
componentsProps={{ slotProps={{
label: commonLabelProps, label: commonLabelProps,
inputRoot: { step: 1 }, inputRoot: { step: 1 },
}} }}

View File

@@ -1,13 +1,13 @@
import type { import type {
BaseColumnFormProps, BaseColumnFormProps,
BaseColumnFormValues, BaseColumnFormValues,
} from '@/components/data-browser/BaseColumnForm'; } from '@/components/dataBrowser/BaseColumnForm';
import BaseColumnForm, { import BaseColumnForm, {
baseColumnValidationSchema, baseColumnValidationSchema,
} from '@/components/data-browser/BaseColumnForm'; } from '@/components/dataBrowser/BaseColumnForm';
import useTrackForeignKeyRelationMutation from '@/hooks/dataBrowser/useTrackForeignKeyRelationsMutation'; import useTrackForeignKeyRelationMutation from '@/hooks/dataBrowser/useTrackForeignKeyRelationsMutation';
import useUpdateColumnMutation from '@/hooks/dataBrowser/useUpdateColumnMutation'; import useUpdateColumnMutation from '@/hooks/dataBrowser/useUpdateColumnMutation';
import type { DataBrowserGridColumn } from '@/types/data-browser'; import type { DataBrowserGridColumn } from '@/types/dataBrowser';
import { Alert } from '@/ui/Alert'; import { Alert } from '@/ui/Alert';
import type { AutocompleteOption } from '@/ui/v2/Autocomplete'; import type { AutocompleteOption } from '@/ui/v2/Autocomplete';
import Button from '@/ui/v2/Button'; import Button from '@/ui/v2/Button';

Some files were not shown because too many files have changed in this diff Show More