Compare commits
7 Commits
@nhost/das
...
@nhost/rea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdc50b32d8 | ||
|
|
3cdca8d4b3 | ||
|
|
c425c9f265 | ||
|
|
3b8473b168 | ||
|
|
8d91f7103f | ||
|
|
11ce93d64b | ||
|
|
3ff1c2b531 |
@@ -14,7 +14,7 @@ runs:
|
||||
steps:
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
with:
|
||||
version: 8.6.2
|
||||
version: 8.10.5
|
||||
run_install: false
|
||||
- name: Get pnpm cache directory
|
||||
id: pnpm-cache-dir
|
||||
|
||||
23
.github/renovate.json
vendored
23
.github/renovate.json
vendored
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"$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"
|
||||
]
|
||||
}
|
||||
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -106,6 +106,8 @@ jobs:
|
||||
# * Run every `lint` script in the workspace . Dependencies build is cached by Turborepo
|
||||
- name: Lint
|
||||
run: pnpm run lint:all
|
||||
- name: Audit for vulnerabilities
|
||||
run: pnpx audit-ci --config ./audit-ci.jsonc
|
||||
|
||||
e2e:
|
||||
name: 'E2E (Package: ${{ matrix.package.path }})'
|
||||
|
||||
3
.npmrc
3
.npmrc
@@ -1 +1,2 @@
|
||||
prefer-workspace-packages = true
|
||||
prefer-workspace-packages = true
|
||||
auto-install-peers = false
|
||||
6
audit-ci.jsonc
Normal file
6
audit-ci.jsonc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
// $schema provides code completion hints to IDEs.
|
||||
"$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json",
|
||||
"moderate": true,
|
||||
"allowlist": ["trim-newlines"]
|
||||
}
|
||||
@@ -1,5 +1,21 @@
|
||||
# @nhost/dashboard
|
||||
|
||||
## 1.6.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- 3b8473b: chore: update turbo to `1.11.3` and pnpm to `8.10.5` in Dockerfile
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/react-apollo@7.0.2
|
||||
- @nhost/nextjs@2.0.2
|
||||
|
||||
## 1.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3ff1c2b53: fix: show upgrade option for pro projects
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -3,7 +3,7 @@ RUN apk add --no-cache libc6-compat
|
||||
RUN apk update
|
||||
WORKDIR /app
|
||||
|
||||
RUN yarn global add turbo@1.10.11
|
||||
RUN yarn global add turbo@1.11.3
|
||||
COPY . .
|
||||
RUN turbo prune --scope="@nhost/dashboard" --docker
|
||||
|
||||
@@ -29,7 +29,7 @@ ENV NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL __NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL_
|
||||
ENV NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL __NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL__
|
||||
ENV NEXT_PUBLIC_NHOST_HASURA_API_URL __NEXT_PUBLIC_NHOST_HASURA_API_URL__
|
||||
|
||||
RUN yarn global add pnpm@8.6.2
|
||||
RUN yarn global add pnpm@8.10.5
|
||||
COPY .gitignore .gitignore
|
||||
COPY --from=pruner /app/out/json/ .
|
||||
COPY --from=pruner /app/out/pnpm-*.yaml .
|
||||
|
||||
@@ -27,7 +27,7 @@ test('should be able to create then delete a personal access token', async () =>
|
||||
const patName = faker.lorem.slug(3);
|
||||
|
||||
await page.getByRole('textbox', { name: /name/i }).fill(patName);
|
||||
await page.getByRole('button', { name: /expiration/i }).click();
|
||||
await page.getByLabel('Expiration').click();
|
||||
await page.getByRole('option', { name: /7 days/i }).click();
|
||||
await page.getByRole('button', { name: /create/i }).click();
|
||||
|
||||
|
||||
@@ -138,7 +138,8 @@ test('should create a table with an identity column', async () => {
|
||||
],
|
||||
});
|
||||
|
||||
await page.getByRole('button', { name: /identity/i }).click();
|
||||
// await page.getByRole('button', { name: /identity/i }).click();
|
||||
await page.getByLabel('Identity').click();
|
||||
await page.getByRole('option', { name: /id/i }).click();
|
||||
|
||||
// create table
|
||||
@@ -194,26 +195,18 @@ test('should create table with foreign key constraint', async () => {
|
||||
|
||||
await page.getByRole('button', { name: /add foreign key/i }).click();
|
||||
|
||||
// select column in current table
|
||||
await page
|
||||
.getByRole('button', { name: /column/i })
|
||||
.first()
|
||||
.click();
|
||||
await page.locator('#columnName').click();
|
||||
await page.getByRole('option', { name: /author_id/i }).click();
|
||||
|
||||
// select reference schema
|
||||
await page.getByRole('button', { name: /schema/i }).click();
|
||||
await page.getByLabel('Schema').click();
|
||||
await page.getByRole('option', { name: /public/i }).click();
|
||||
|
||||
// select reference table
|
||||
await page.getByRole('button', { name: /table/i }).click();
|
||||
await page.getByLabel('Table').click();
|
||||
await page.getByRole('option', { name: firstTableName, exact: true }).click();
|
||||
|
||||
// select reference column
|
||||
await page
|
||||
.getByRole('button', { name: /column/i })
|
||||
.nth(1)
|
||||
.click();
|
||||
await page.locator('#referencedColumn').click();
|
||||
await page.getByRole('option', { name: /id/i }).click();
|
||||
|
||||
await page.getByRole('button', { name: /add/i }).click();
|
||||
|
||||
@@ -113,27 +113,21 @@ test('should not be able to delete a table if other tables have foreign keys ref
|
||||
await page.getByRole('button', { name: /add foreign key/i }).click();
|
||||
|
||||
// select column in current table
|
||||
await page
|
||||
.getByRole('button', { name: /column/i })
|
||||
.first()
|
||||
.click();
|
||||
await page.locator('#columnName').click();
|
||||
|
||||
await page.getByRole('option', { name: /author_id/i }).click();
|
||||
|
||||
// select reference schema
|
||||
await page.getByRole('button', { name: /schema/i }).click();
|
||||
await page.getByLabel('Schema').click();
|
||||
await page.getByRole('option', { name: /public/i }).click();
|
||||
|
||||
// select reference table
|
||||
await page.getByRole('button', { name: /table/i }).click();
|
||||
await page.getByLabel('Table').click();
|
||||
await page.getByRole('option', { name: firstTableName, exact: true }).click();
|
||||
|
||||
// select reference column
|
||||
await page
|
||||
.getByRole('button', { name: /column/i })
|
||||
.nth(1)
|
||||
.click();
|
||||
await page.locator('#referencedColumn').click();
|
||||
await page.getByRole('option', { name: /id/i }).click();
|
||||
|
||||
await page.getByRole('button', { name: /add/i }).click();
|
||||
|
||||
await expect(
|
||||
|
||||
@@ -93,7 +93,7 @@ test("should show the project's region and subdomain", async () => {
|
||||
|
||||
test('should not have a GitHub repository connected', async () => {
|
||||
await expect(
|
||||
page.getByRole('button', { name: /connect to github/i }),
|
||||
page.getByRole('button', { name: /connect to github/i }).first(),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
|
||||
@@ -116,7 +116,8 @@ export async function prepareTable({
|
||||
);
|
||||
|
||||
// select the first column as primary key
|
||||
await page.getByRole('button', { name: /primary key/i }).click();
|
||||
// await page.getByRole('button', { name: /primary key/i }).click();
|
||||
await page.getByLabel('Primary Key').click();
|
||||
await page.getByRole('option', { name: primaryKey, exact: true }).click();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
query InitQuery {
|
||||
root {
|
||||
enableServices
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"projectId": 2596,
|
||||
"token": "U2FsdGVkX19+V8BJnVR0xLEC+42OW5qZl/A0i6beAaRmJoIhFh5Yf6eIKBzLbV9h",
|
||||
"outputDirectoryPath": "src/hypertune"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/dashboard",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
@@ -15,62 +15,61 @@
|
||||
"format": "prettier --write \"src/**/*.{js,ts,tsx,jsx,json,md}\" --plugin-search-dir=.",
|
||||
"storybook": "start-storybook -p 6006 -s public",
|
||||
"build-storybook": "build-storybook",
|
||||
"install-browsers": "pnpm dlx playwright@1.31.0 install --with-deps",
|
||||
"e2e": "pnpm install-browsers && pnpm dlx playwright@1.31.0 test"
|
||||
"install-browsers": "pnpm playwright install && pnpm playwright install-deps",
|
||||
"e2e": "pnpm install-browsers && pnpm playwright test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.7.10",
|
||||
"@codemirror/lang-sql": "^6.5.4",
|
||||
"@emotion/cache": "^11.10.5",
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/server": "^11.4.0",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
"@fontsource/inter": "^5.0.0",
|
||||
"@fontsource/roboto-mono": "^5.0.0",
|
||||
"@graphiql/react": "^0.18.0",
|
||||
"@graphiql/toolkit": "^0.8.2",
|
||||
"@headlessui/react": "^1.6.5",
|
||||
"@apollo/client": "^3.8.9",
|
||||
"@codemirror/lang-sql": "^6.5.5",
|
||||
"@emotion/cache": "^11.11.0",
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/server": "^11.11.0",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@fontsource/inter": "^5.0.16",
|
||||
"@fontsource/roboto-mono": "^5.0.16",
|
||||
"@graphiql/react": "^0.20.2",
|
||||
"@graphiql/toolkit": "^0.9.1",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@hookform/resolvers": "^3.0.0",
|
||||
"@mui/base": "^5.0.0-alpha.106",
|
||||
"@mui/material": "^5.10.14",
|
||||
"@mui/system": "^5.10.14",
|
||||
"@mui/x-date-pickers": "^5.0.8",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@mui/base": "5.0.0-beta.31",
|
||||
"@mui/material": "^5.15.4",
|
||||
"@mui/system": "^5.15.4",
|
||||
"@mui/x-date-pickers": "^5.0.20",
|
||||
"@nhost/nextjs": "workspace:*",
|
||||
"@nhost/react-apollo": "workspace:*",
|
||||
"@segment/snippet": "^4.15.3",
|
||||
"@stripe/react-stripe-js": "^2.0.0",
|
||||
"@stripe/stripe-js": "^1.35.0",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@tanstack/react-query": "^4.16.1",
|
||||
"@tanstack/react-table": "^8.5.30",
|
||||
"@tanstack/react-virtual": "^3.0.0-beta.23",
|
||||
"@uiw/codemirror-theme-github": "^4.21.20",
|
||||
"@uiw/react-codemirror": "^4.21.20",
|
||||
"@segment/snippet": "^4.16.2",
|
||||
"@stripe/react-stripe-js": "^2.4.0",
|
||||
"@stripe/stripe-js": "^1.54.2",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@tanstack/react-query": "^4.36.1",
|
||||
"@tanstack/react-table": "^8.11.6",
|
||||
"@tanstack/react-virtual": "^3.0.1",
|
||||
"@uiw/codemirror-theme-github": "^4.21.21",
|
||||
"@uiw/react-codemirror": "^4.21.21",
|
||||
"analytics-node": "^6.2.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"clsx": "^1.2.1",
|
||||
"date-fns": "^2.29.3",
|
||||
"generate-password": "^1.7.0",
|
||||
"graphiql": "^3.0.0",
|
||||
"graphql": "^16.6.0",
|
||||
"graphql-request": "^6.0.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"generate-password": "^1.7.1",
|
||||
"graphiql": "^3.1.0",
|
||||
"graphql": "16.8.1",
|
||||
"graphql-request": "^6.1.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"graphql-ws": "^5.11.2",
|
||||
"hypertune": "^1.4.4",
|
||||
"just-kebab-case": "^4.1.1",
|
||||
"graphql-ws": "^5.14.3",
|
||||
"just-kebab-case": "^4.2.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"next": "^12.3.1",
|
||||
"next-seo": "^6.0.0",
|
||||
"next": "^14.0.4",
|
||||
"next-seo": "^6.4.0",
|
||||
"node-pg-format": "^1.3.5",
|
||||
"pluralize": "^8.0.0",
|
||||
"react": "18.2.0",
|
||||
"react-children-utilities": "^2.9.0",
|
||||
"react-children-utilities": "^2.10.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-error-boundary": "^4.0.0",
|
||||
"react-hook-form": "^7.42.1",
|
||||
"react-hot-toast": "^2.4.0",
|
||||
"react-intersection-observer": "^9.5.2",
|
||||
"react-error-boundary": "^4.0.12",
|
||||
"react-hook-form": "^7.49.3",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"react-intersection-observer": "^9.5.3",
|
||||
"react-is": "18.2.0",
|
||||
"react-loading-skeleton": "^2.2.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
@@ -82,87 +81,87 @@
|
||||
"rehype-highlight": "^7.0.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"shell-quote": "^1.8.1",
|
||||
"slugify": "^1.6.5",
|
||||
"slugify": "^1.6.6",
|
||||
"stripe": "^10.17.0",
|
||||
"tailwind-merge": "^1.8.0",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"utility-types": "^3.10.0",
|
||||
"validator": "^13.7.0",
|
||||
"yup": "^1.0.2",
|
||||
"validator": "^13.11.0",
|
||||
"yup": "^1.3.3",
|
||||
"yup-password": "^0.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.2",
|
||||
"@babel/core": "^7.23.7",
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@graphql-codegen/cli": "^3.0.0",
|
||||
"@graphql-codegen/typescript": "^3.0.0",
|
||||
"@graphql-codegen/typescript-operations": "^3.0.0",
|
||||
"@graphql-codegen/typescript-react-apollo": "^3.3.1",
|
||||
"@next/bundle-analyzer": "^12.3.1",
|
||||
"@playwright/test": "1.31.0",
|
||||
"@storybook/addon-actions": "^6.5.14",
|
||||
"@storybook/addon-essentials": "^6.5.14",
|
||||
"@storybook/addon-interactions": "^6.5.14",
|
||||
"@storybook/addon-links": "^6.5.14",
|
||||
"@graphql-codegen/cli": "^3.3.1",
|
||||
"@graphql-codegen/typescript": "^3.0.4",
|
||||
"@graphql-codegen/typescript-operations": "^3.0.4",
|
||||
"@graphql-codegen/typescript-react-apollo": "^3.3.7",
|
||||
"@next/bundle-analyzer": "^12.3.4",
|
||||
"@playwright/test": "1.41.0",
|
||||
"@storybook/addon-actions": "^6.5.16",
|
||||
"@storybook/addon-essentials": "^6.5.16",
|
||||
"@storybook/addon-interactions": "^6.5.16",
|
||||
"@storybook/addon-links": "^6.5.16",
|
||||
"@storybook/addon-postcss": "^2.0.0",
|
||||
"@storybook/builder-webpack5": "^6.5.14",
|
||||
"@storybook/manager-webpack5": "^6.5.14",
|
||||
"@storybook/react": "^6.5.14",
|
||||
"@storybook/testing-library": "^0.2.0",
|
||||
"@storybook/builder-webpack5": "^6.5.16",
|
||||
"@storybook/manager-webpack5": "^6.5.16",
|
||||
"@storybook/react": "^6.5.16",
|
||||
"@storybook/testing-library": "^0.2.2",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@testing-library/dom": "^9.0.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/ace": "^0.0.48",
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
"@types/jest": "^29.5.3",
|
||||
"@types/lodash.debounce": "^4.0.7",
|
||||
"@types/node": "^16.11.7",
|
||||
"@types/bcryptjs": "^2.4.6",
|
||||
"@types/jest": "^29.5.11",
|
||||
"@types/lodash.debounce": "^4.0.9",
|
||||
"@types/node": "^16.18.70",
|
||||
"@types/pluralize": "^0.0.30",
|
||||
"@types/react": "^18.2.14",
|
||||
"@types/react-dom": "^18.2.6",
|
||||
"@types/react-table": "^7.7.12",
|
||||
"@types/shell-quote": "^1.7.1",
|
||||
"@types/testing-library__jest-dom": "^5.14.5",
|
||||
"@types/validator": "^13.7.10",
|
||||
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
||||
"@typescript-eslint/parser": "^6.15.0",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"@vitest/coverage-v8": "^0.32.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"@types/react": "^18.2.47",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@types/react-table": "^7.7.19",
|
||||
"@types/shell-quote": "^1.7.5",
|
||||
"@types/testing-library__jest-dom": "^5.14.9",
|
||||
"@types/validator": "^13.11.8",
|
||||
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
||||
"@typescript-eslint/parser": "^6.18.1",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@vitest/coverage-v8": "^0.32.4",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"babel-loader": "^8.3.0",
|
||||
"babel-plugin-transform-remove-console": "^6.9.4",
|
||||
"csstype": "^3.0.10",
|
||||
"dotenv": "^16.0.3",
|
||||
"csstype": "^3.1.3",
|
||||
"dotenv": "^16.3.1",
|
||||
"encoding": "^0.1.13",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-airbnb": "19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
"eslint-config-next": "^13.0.2",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
||||
"eslint-plugin-react": "^7.31.11",
|
||||
"eslint-config-airbnb-typescript": "^17.1.0",
|
||||
"eslint-config-next": "^13.5.6",
|
||||
"eslint-config-prettier": "^8.10.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"jsdom": "^22.0.0",
|
||||
"lint-staged": ">=13",
|
||||
"msw": "^1.0.1",
|
||||
"msw-storybook-addon": "^1.6.3",
|
||||
"node-fetch": "^3.3.0",
|
||||
"postcss": "^8.4.19",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier-plugin-organize-imports": "^3.2.0",
|
||||
"prettier-plugin-tailwindcss": "^0.4.0",
|
||||
"jsdom": "^22.1.0",
|
||||
"lint-staged": "^15.2.0",
|
||||
"msw": "^1.3.2",
|
||||
"msw-storybook-addon": "^1.10.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"postcss": "^8.4.33",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"prettier-plugin-tailwindcss": "^0.4.1",
|
||||
"react-date-fns-hooks": "^0.9.4",
|
||||
"require-from-string": "^2.0.2",
|
||||
"snake-case": "^3.0.4",
|
||||
"storybook-addon-next-router": "^4.0.1",
|
||||
"tailwindcss": "^3.1.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths-webpack-plugin": "^4.0.0",
|
||||
"vite": "^4.0.2",
|
||||
"vite-tsconfig-paths": "^4.0.3",
|
||||
"vitest": "^0.32.0"
|
||||
"storybook-addon-next-router": "^4.0.2",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths-webpack-plugin": "^4.1.0",
|
||||
"vite": "^5.0.12",
|
||||
"vite-tsconfig-paths": "^4.2.3",
|
||||
"vitest": "^0.32.4"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -17,7 +17,7 @@ function NavLink(
|
||||
ref: ForwardedRef<HTMLAnchorElement>,
|
||||
) {
|
||||
return (
|
||||
<NextLink href={href} passHref>
|
||||
<NextLink href={href} passHref legacyBehavior>
|
||||
<Link className={twMerge('font-display', className)} ref={ref} {...props}>
|
||||
{children}
|
||||
</Link>
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function ThemeSwitcher({
|
||||
listbox: { className: 'min-w-0 w-full' },
|
||||
popper: {
|
||||
disablePortal: false,
|
||||
className: 'z-[10000] w-[270px] w-full',
|
||||
className: 'z-[10000] w-[270px]',
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function UpgradeToProBanner({
|
||||
return (
|
||||
<Box
|
||||
sx={{ backgroundColor: 'primary.light' }}
|
||||
className="flex flex-col justify-between space-y-4 rounded-md p-4 lg:flex-row lg:items-center lg:space-y-0"
|
||||
className="flex flex-col justify-between p-4 space-y-4 rounded-md lg:flex-row lg:items-center lg:space-y-0"
|
||||
>
|
||||
<div className="flex flex-col justify-between space-y-4">
|
||||
<div className="space-y-2">
|
||||
@@ -81,13 +81,13 @@ export default function UpgradeToProBanner({
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
underline="hover"
|
||||
className="text-center font-medium"
|
||||
className="font-medium text-center"
|
||||
sx={{
|
||||
color: 'text.secondary',
|
||||
}}
|
||||
>
|
||||
See all features
|
||||
<ArrowSquareOutIcon className="ml-1 h-4 w-4" />
|
||||
<ArrowSquareOutIcon className="w-4 h-4 ml-1" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -97,6 +97,7 @@ export default function UpgradeToProBanner({
|
||||
width={300}
|
||||
height={140}
|
||||
objectFit="contain"
|
||||
alt='Upgrade to Pro illustration'
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
DataBrowserGridCellProps,
|
||||
} from '@/features/database/dataGrid/types/dataBrowser';
|
||||
import { triggerToast } from '@/utils/toast';
|
||||
import type { FocusEvent, KeyboardEvent, MouseEvent } from 'react';
|
||||
import type { FocusEvent, JSXElementConstructor, KeyboardEvent, MouseEvent, ReactElement, ReactNode, ReactPortal } from 'react';
|
||||
import {
|
||||
Children,
|
||||
cloneElement,
|
||||
@@ -320,7 +320,7 @@ function DataGridCellContent<TData extends object = {}, TValue = unknown>({
|
||||
sx={{ backgroundColor: 'transparent' }}
|
||||
{...props}
|
||||
>
|
||||
{Children.map(children, (child) => {
|
||||
{Children.map(children, (child: ReactNode | ReactPortal | ReactElement<unknown, string | JSXElementConstructor<any>>) => {
|
||||
if (!isValidElement(child)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import { Input, inputClasses } from '@/components/ui/v2/Input';
|
||||
import { OptionBase } from '@/components/ui/v2/Option';
|
||||
import { OptionGroupBase } from '@/components/ui/v2/OptionGroup';
|
||||
import type { StyledComponent } from '@emotion/styled';
|
||||
import type { UseAutocompleteProps } from '@mui/base/AutocompleteUnstyled';
|
||||
import { createFilterOptions } from '@mui/base/AutocompleteUnstyled';
|
||||
import PopperUnstyled from '@mui/base/PopperUnstyled';
|
||||
import type { UseAutocompleteProps } from '@mui/base/useAutocomplete';
|
||||
import { createFilterOptions } from '@mui/base/useAutocomplete';
|
||||
import { Popper } from '@mui/base'
|
||||
import { styled } from '@mui/material';
|
||||
import type { AutocompleteProps as MaterialAutocompleteProps } from '@mui/material/Autocomplete';
|
||||
import MaterialAutocomplete, {
|
||||
@@ -142,7 +142,7 @@ const StyledOptionBase = styled(OptionBase)(({ theme }) => ({
|
||||
gap: theme.spacing(0.5),
|
||||
}));
|
||||
|
||||
export const AutocompletePopper = styled(PopperUnstyled)(({ theme }) => ({
|
||||
export const AutocompletePopper = styled(Popper)(({ theme }) => ({
|
||||
zIndex: theme.zIndex.modal + 1,
|
||||
boxShadow: 'none',
|
||||
minWidth: 320,
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { styled } from '@mui/material';
|
||||
import type {
|
||||
BoxProps as MaterialBoxProps,
|
||||
BoxTypeMap,
|
||||
} from '@mui/material/Box';
|
||||
import type { BoxProps as MaterialBoxProps } from '@mui/material/Box';
|
||||
import MaterialBox from '@mui/material/Box';
|
||||
import { type BoxTypeMap } from '@mui/system';
|
||||
import type { ForwardedRef, PropsWithoutRef } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface ChipProps extends MaterialChipProps {
|
||||
/**
|
||||
* Custom component for the root node.
|
||||
*/
|
||||
component?: string | ElementType;
|
||||
component?: ElementType;
|
||||
}
|
||||
|
||||
const Chip = styled(MaterialChip)<ChipProps>(({ theme }) => ({
|
||||
|
||||
@@ -7,7 +7,7 @@ export interface HelperTextProps extends MaterialFormHelperTextProps {
|
||||
/**
|
||||
* Custom component for the root node.
|
||||
*/
|
||||
component?: string | ElementType;
|
||||
component?: ElementType;
|
||||
}
|
||||
|
||||
const HelperText = styled(MaterialFormHelperText)<HelperTextProps>({
|
||||
|
||||
@@ -1,41 +1,42 @@
|
||||
import type { OptionUnstyledProps } from '@mui/base/OptionUnstyled';
|
||||
import OptionUnstyled, {
|
||||
optionUnstyledClasses,
|
||||
} from '@mui/base/OptionUnstyled';
|
||||
import {
|
||||
Option as BaseOption,
|
||||
optionClasses as baseOptionClasses,
|
||||
type OptionProps as BaseOptionProps,
|
||||
} from '@mui/base';
|
||||
import { darken, styled } from '@mui/material';
|
||||
import type { ForwardedRef } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
import OptionBase from './OptionBase';
|
||||
|
||||
export interface OptionProps<TValue extends {}>
|
||||
extends OptionUnstyledProps<TValue> {}
|
||||
extends BaseOptionProps<TValue> {}
|
||||
|
||||
const StyledOption = styled(OptionUnstyled)(({ theme }) => ({
|
||||
const StyledOption = styled(BaseOption)(({ theme }) => ({
|
||||
transition: theme.transitions.create(['background-color']),
|
||||
color: theme.palette.text.primary,
|
||||
[`&.${optionUnstyledClasses.selected}`]: {
|
||||
[`&.${baseOptionClasses.selected}`]: {
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'dark'
|
||||
? `${darken(theme.palette.action.hover, 0.1)} !important`
|
||||
: `${darken(theme.palette.action.hover, 0.05)} !important`,
|
||||
},
|
||||
[`&.${optionUnstyledClasses.selected}:hover, &.${optionUnstyledClasses.selected}.${optionUnstyledClasses.highlighted}`]:
|
||||
[`&.${baseOptionClasses.selected}:hover, &.${baseOptionClasses.selected}.${baseOptionClasses.highlighted}`]:
|
||||
{
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'dark'
|
||||
? `${darken(theme.palette.action.hover, 0.25)} !important`
|
||||
: `${darken(theme.palette.action.hover, 0.075)} !important`,
|
||||
},
|
||||
[`&.${optionUnstyledClasses.highlighted}, &:hover`]: {
|
||||
[`&.${baseOptionClasses.highlighted}, &:hover`]: {
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'dark'
|
||||
? `${darken(theme.palette.action.hover, 0.15)} !important`
|
||||
: `${theme.palette.action.hover} !important`,
|
||||
},
|
||||
[`&.${optionUnstyledClasses.disabled}`]: {
|
||||
[`&.${baseOptionClasses.disabled}`]: {
|
||||
color: theme.palette.text.disabled,
|
||||
},
|
||||
[`&.${optionUnstyledClasses.disabled}:hover`]: {
|
||||
[`&.${baseOptionClasses.disabled}:hover`]: {
|
||||
backgroundColor: 'transparent !important',
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import type { OptionGroupUnstyledProps } from '@mui/base/OptionGroupUnstyled';
|
||||
import OptionGroupUnstyled from '@mui/base/OptionGroupUnstyled';
|
||||
import {
|
||||
OptionGroup as BaseOptionGroup,
|
||||
type OptionGroupProps as BaseOptionGroupProps,
|
||||
} from '@mui/base';
|
||||
import { styled } from '@mui/material';
|
||||
import type { ForwardedRef } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
import OptionGroupBase from './OptionGroupBase';
|
||||
|
||||
export interface OptionGroupProps extends OptionGroupUnstyledProps {}
|
||||
export interface OptionGroupProps extends BaseOptionGroupProps {}
|
||||
|
||||
const StyledGroupRoot = styled('li')(({ theme }) => ({
|
||||
listStyle: 'none',
|
||||
@@ -25,7 +27,7 @@ function OptionGroup(
|
||||
...externalSlots,
|
||||
};
|
||||
|
||||
return <OptionGroupUnstyled {...props} ref={ref} slots={slots} />;
|
||||
return <BaseOptionGroup {...props} ref={ref} slots={slots} />;
|
||||
}
|
||||
|
||||
OptionGroup.displayName = 'NhostOptionGroup';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { FormControlProps } from '@/components/ui/v2/FormControl';
|
||||
import { FormControl } from '@/components/ui/v2/FormControl';
|
||||
import PopperUnstyled from '@mui/base/PopperUnstyled';
|
||||
import type { SelectUnstyledProps } from '@mui/base/SelectUnstyled';
|
||||
import SelectUnstyled from '@mui/base/SelectUnstyled';
|
||||
import { styled } from '@mui/material';
|
||||
import { Popper as BasePopper } from '@mui/base/Popper';
|
||||
import type { SelectProps as BaseSelectProps } from '@mui/base/Select';
|
||||
import { Select as BaseSelect } from '@mui/base/Select';
|
||||
import { styled } from '@mui/system';
|
||||
import clsx from 'clsx';
|
||||
import type { ForwardedRef, PropsWithoutRef } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
@@ -11,7 +11,7 @@ import type { ToggleButtonProps } from './ToggleButton';
|
||||
import ToggleButton from './ToggleButton';
|
||||
|
||||
export interface SelectProps<TValue extends {}>
|
||||
extends SelectUnstyledProps<TValue>,
|
||||
extends BaseSelectProps<TValue, false>,
|
||||
Pick<
|
||||
FormControlProps,
|
||||
| 'fullWidth'
|
||||
@@ -25,7 +25,7 @@ export interface SelectProps<TValue extends {}>
|
||||
/**
|
||||
* Props for component slots.
|
||||
*/
|
||||
slotProps?: SelectUnstyledProps<TValue>['slotProps'] & {
|
||||
slotProps?: BaseSelectProps<TValue, false>['slotProps'] & {
|
||||
root?: Partial<PropsWithoutRef<ToggleButtonProps>>;
|
||||
label?: Partial<FormControlProps['labelProps']>;
|
||||
formControl?: Partial<FormControlProps>;
|
||||
@@ -59,8 +59,8 @@ const StyledListbox = styled('ul')(({ theme }) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledPopper = styled(PopperUnstyled)`
|
||||
z-index: 10;
|
||||
const StyledPopper = styled(BasePopper)`
|
||||
z-index: 9999;
|
||||
`;
|
||||
|
||||
function Select<TValue>(
|
||||
@@ -80,7 +80,7 @@ function Select<TValue>(
|
||||
}: SelectProps<TValue>,
|
||||
ref: ForwardedRef<HTMLButtonElement>,
|
||||
) {
|
||||
const slots: SelectUnstyledProps<TValue>['slots'] = {
|
||||
const slots: BaseSelectProps<TValue, false>['slots'] = {
|
||||
root: ToggleButton,
|
||||
popper: StyledPopper,
|
||||
listbox: StyledListbox,
|
||||
@@ -107,7 +107,7 @@ function Select<TValue>(
|
||||
htmlFor: props.id,
|
||||
}}
|
||||
>
|
||||
<SelectUnstyled
|
||||
<BaseSelect
|
||||
aria-label={typeof label === 'string' ? label : undefined}
|
||||
{...props}
|
||||
className={clsx(error && 'error')}
|
||||
@@ -117,7 +117,6 @@ function Select<TValue>(
|
||||
...slotProps,
|
||||
root: {
|
||||
...slotProps?.root,
|
||||
placeholder,
|
||||
},
|
||||
listbox: {
|
||||
...slotProps?.listbox,
|
||||
@@ -132,7 +131,7 @@ function Select<TValue>(
|
||||
placeholder={placeholder}
|
||||
>
|
||||
{children}
|
||||
</SelectUnstyled>
|
||||
</BaseSelect>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { ChevronDownIcon } from '@/components/ui/v2/icons/ChevronDownIcon';
|
||||
import { ChevronUpIcon } from '@/components/ui/v2/icons/ChevronUpIcon';
|
||||
import type { ButtonUnstyledProps } from '@mui/base/ButtonUnstyled';
|
||||
import ButtonUnstyled from '@mui/base/ButtonUnstyled';
|
||||
import { selectUnstyledClasses } from '@mui/base/SelectUnstyled';
|
||||
import {
|
||||
Button as ButtonUnstyled,
|
||||
type ButtonProps as ButtonUnstyledProps,
|
||||
} from '@mui/base';
|
||||
import { selectClasses as selectUnstyledClasses } from '@mui/base/Select';
|
||||
import type { SxProps } from '@mui/material';
|
||||
import { styled } from '@mui/material';
|
||||
import type { Theme } from '@mui/system';
|
||||
@@ -24,6 +26,7 @@ export interface ToggleButtonProps
|
||||
Omit<DetailedHTMLProps<HTMLProps<HTMLSpanElement>, HTMLSpanElement>, 'as'>
|
||||
>;
|
||||
};
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const StyledButton = styled(ButtonUnstyled)(({ theme }) => ({
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import type { FormControlLabelProps } from '@/components/ui/v2/FormControlLabel';
|
||||
import { FormControlLabel } from '@/components/ui/v2/FormControlLabel';
|
||||
import SwitchUnstyled, {
|
||||
switchUnstyledClasses,
|
||||
} from '@mui/base/SwitchUnstyled';
|
||||
import type { SwitchUnstyledProps } from '@mui/base/SwitchUnstyled/SwitchUnstyled.types';
|
||||
import {
|
||||
Switch as BaseSwitch,
|
||||
switchClasses as baseSwitchClasses,
|
||||
} from '@mui/base';
|
||||
import type { SwitchProps as BaseSwitchProps } from '@mui/base/Switch';
|
||||
import { styled } from '@mui/material';
|
||||
import type { ForwardedRef, PropsWithoutRef } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
export interface SwitchProps extends SwitchUnstyledProps {
|
||||
export interface SwitchProps extends BaseSwitchProps {
|
||||
/**
|
||||
* Label to be displayed next to the checkbox.
|
||||
*/
|
||||
@@ -16,11 +17,11 @@ export interface SwitchProps extends SwitchUnstyledProps {
|
||||
/**
|
||||
* Props to be passed to the internal components.
|
||||
*/
|
||||
slotProps?: SwitchUnstyledProps['slotProps'] & {
|
||||
slotProps?: BaseSwitchProps['slotProps'] & {
|
||||
/**
|
||||
* Props to be passed to the `Switch` component.
|
||||
*/
|
||||
root?: Partial<SwitchUnstyledProps>;
|
||||
root?: Partial<BaseSwitchProps>;
|
||||
/**
|
||||
* Props to be passed to the `FormControlLabel` component.
|
||||
*/
|
||||
@@ -35,23 +36,23 @@ const StyledFormControlLabel = styled(FormControlLabel)(({ theme }) => ({
|
||||
justifyContent: 'start',
|
||||
}));
|
||||
|
||||
const StyledSwitch = styled(SwitchUnstyled)(({ theme }) => ({
|
||||
const StyledSwitch = styled(BaseSwitch)(({ theme }) => ({
|
||||
position: 'relative',
|
||||
display: 'inline-block',
|
||||
width: '40px',
|
||||
height: '24px',
|
||||
cursor: 'pointer',
|
||||
|
||||
[`&.${switchUnstyledClasses.disabled}`]: {
|
||||
[`&.${baseSwitchClasses.disabled}`]: {
|
||||
cursor: 'not-allowed',
|
||||
|
||||
[`& .${switchUnstyledClasses.track}`]: {
|
||||
[`& .${baseSwitchClasses.track}`]: {
|
||||
backgroundColor: theme.palette.grey[200],
|
||||
color: theme.palette.grey[200],
|
||||
},
|
||||
},
|
||||
|
||||
[`& .${switchUnstyledClasses.track}`]: {
|
||||
[`& .${baseSwitchClasses.track}`]: {
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'dark'
|
||||
? theme.palette.grey[500]
|
||||
@@ -63,7 +64,7 @@ const StyledSwitch = styled(SwitchUnstyled)(({ theme }) => ({
|
||||
position: 'absolute',
|
||||
},
|
||||
|
||||
[` & .${switchUnstyledClasses.thumb}`]: {
|
||||
[` & .${baseSwitchClasses.thumb}`]: {
|
||||
display: 'block',
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
@@ -77,24 +78,24 @@ const StyledSwitch = styled(SwitchUnstyled)(({ theme }) => ({
|
||||
transitionDuration: '120ms',
|
||||
},
|
||||
|
||||
[`&.${switchUnstyledClasses.focusVisible} .${switchUnstyledClasses.thumb}`]: {
|
||||
[`&.${baseSwitchClasses.focusVisible} .${baseSwitchClasses.thumb}`]: {
|
||||
backgroundColor: theme.palette.action.focus,
|
||||
boxShadow: '0 0 1px 8px rgba(0, 0, 0, 0.25)',
|
||||
},
|
||||
|
||||
[`&.${switchUnstyledClasses.checked}`]: {
|
||||
[`.${switchUnstyledClasses.thumb}`]: {
|
||||
[`&.${baseSwitchClasses.checked}`]: {
|
||||
[`.${baseSwitchClasses.thumb}`]: {
|
||||
left: '19px',
|
||||
top: '3px',
|
||||
backgroundColor: theme.palette.common.white,
|
||||
},
|
||||
|
||||
[`.${switchUnstyledClasses.track}`]: {
|
||||
[`.${baseSwitchClasses.track}`]: {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
|
||||
[`&.${switchUnstyledClasses.disabled}`]: {
|
||||
[`.${switchUnstyledClasses.track}`]: {
|
||||
[`&.${baseSwitchClasses.disabled}`]: {
|
||||
[`.${baseSwitchClasses.track}`]: {
|
||||
opacity: 0.5,
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'dark'
|
||||
@@ -104,7 +105,7 @@ const StyledSwitch = styled(SwitchUnstyled)(({ theme }) => ({
|
||||
},
|
||||
},
|
||||
|
||||
[`& .${switchUnstyledClasses.input}`]: {
|
||||
[`& .${baseSwitchClasses.input}`]: {
|
||||
cursor: 'inherit',
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
messagesState,
|
||||
import messagesState, {
|
||||
type ProjectMessage,
|
||||
} from '@/features/ai/DevAssistant/state';
|
||||
} from '@/features/ai/DevAssistant/state/messages';
|
||||
import { selectorFamily } from 'recoil';
|
||||
|
||||
const projectMessagesState = selectorFamily<ProjectMessage[], string>({
|
||||
|
||||
@@ -196,14 +196,14 @@ export default function EditUserForm({
|
||||
className="flex flex-col overflow-hidden border-t-1 lg:flex-auto lg:content-between"
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<Box className="flex-auto divide-y overflow-y-auto">
|
||||
<Box className="flex-auto overflow-y-auto divide-y">
|
||||
<Box
|
||||
component="section"
|
||||
className="grid grid-flow-col p-6 lg:grid-cols-7"
|
||||
>
|
||||
<div className="col-span-6 grid grid-flow-col place-content-start items-center gap-4">
|
||||
<Avatar className="h-12 w-12" src={user.avatarUrl} />
|
||||
<div className="grid grid-flow-row items-center">
|
||||
<div className="grid items-center grid-flow-col col-span-6 gap-4 place-content-start">
|
||||
<Avatar className="w-12 h-12" src={user.avatarUrl} />
|
||||
<div className="grid items-center grid-flow-row">
|
||||
<Text className="text-lg font-medium">{user.displayName}</Text>
|
||||
<Text className="text-sm+ font-normal" color="secondary">
|
||||
{user.email}
|
||||
@@ -225,7 +225,7 @@ export default function EditUserForm({
|
||||
Actions
|
||||
</Button>
|
||||
</Dropdown.Trigger>
|
||||
<Dropdown.Content menu className="h-full w-full">
|
||||
<Dropdown.Content menu className="w-full h-full">
|
||||
<Dropdown.Item
|
||||
className="font-medium"
|
||||
sx={{ color: 'error.main' }}
|
||||
@@ -253,11 +253,11 @@ export default function EditUserForm({
|
||||
component="section"
|
||||
className="grid grid-flow-row grid-cols-4 gap-8 p-6"
|
||||
>
|
||||
<InputLabel as="h3" className="col-span-1 self-center">
|
||||
<InputLabel as="h3" className="self-center col-span-1">
|
||||
User ID
|
||||
</InputLabel>
|
||||
<div className="col-span-3 grid grid-flow-col items-center justify-start gap-2">
|
||||
<Text className="truncate font-medium">{user.id}</Text>
|
||||
<div className="grid items-center justify-start grid-flow-col col-span-3 gap-2">
|
||||
<Text className="font-medium truncate">{user.id}</Text>
|
||||
<IconButton
|
||||
variant="borderless"
|
||||
color="secondary"
|
||||
@@ -267,18 +267,18 @@ export default function EditUserForm({
|
||||
copy(user.id, 'User ID');
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="h-4 w-4" />
|
||||
<CopyIcon className="w-4 h-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
|
||||
<InputLabel as="h3" className="col-span-1 self-center ">
|
||||
<InputLabel as="h3" className="self-center col-span-1 ">
|
||||
Created At
|
||||
</InputLabel>
|
||||
<Text className="col-span-3 font-medium">
|
||||
{format(new Date(user.createdAt), 'yyyy-MM-dd HH:mm:ss')}
|
||||
</Text>
|
||||
|
||||
<InputLabel as="h3" className="col-span-1 self-center ">
|
||||
<InputLabel as="h3" className="self-center col-span-1 ">
|
||||
Last Seen
|
||||
</InputLabel>
|
||||
<Text className="col-span-3 font-medium">
|
||||
@@ -336,14 +336,14 @@ export default function EditUserForm({
|
||||
autoComplete="off"
|
||||
/>
|
||||
|
||||
<div className="col-span-1 my-1 grid grid-flow-col grid-cols-8 items-center">
|
||||
<div className="grid items-center grid-flow-col grid-cols-8 col-span-1 my-1">
|
||||
<div className="col-span-2 ">
|
||||
<InputLabel as="h3">Password</InputLabel>
|
||||
</div>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="borderless"
|
||||
className="col-span-6 place-self-start px-2"
|
||||
className="col-span-6 px-2 place-self-start"
|
||||
onClick={handleChangeUserPassword}
|
||||
>
|
||||
Change
|
||||
@@ -392,12 +392,12 @@ export default function EditUserForm({
|
||||
</Box>
|
||||
<Box
|
||||
component="section"
|
||||
className="grid place-content-start gap-4 p-6 lg:grid-cols-4"
|
||||
className="grid gap-4 p-6 place-content-start lg:grid-cols-4"
|
||||
>
|
||||
<div className="col-span-1 items-center self-center align-middle">
|
||||
<div className="items-center self-center col-span-1 align-middle">
|
||||
<InputLabel as="h3">OAuth Providers</InputLabel>
|
||||
</div>
|
||||
<div className="col-span-3 grid w-full grid-flow-row gap-y-6">
|
||||
<div className="grid w-full grid-flow-row col-span-3 gap-y-6">
|
||||
{user.userProviders.length === 0 && (
|
||||
<div className="grid grid-flow-col place-content-between gap-x-1">
|
||||
<Text className="font-normal" color="disabled">
|
||||
@@ -408,10 +408,10 @@ export default function EditUserForm({
|
||||
|
||||
{user.userProviders.map((provider) => (
|
||||
<div
|
||||
className="grid grid-flow-col place-content-between gap-3"
|
||||
className="grid grid-flow-col gap-3 place-content-between"
|
||||
key={provider.id}
|
||||
>
|
||||
<div className="span-cols-1 grid grid-flow-col gap-2">
|
||||
<div className="grid grid-flow-col gap-2 span-cols-1">
|
||||
<Image
|
||||
src={
|
||||
theme.palette.mode === 'dark'
|
||||
@@ -424,6 +424,7 @@ export default function EditUserForm({
|
||||
}
|
||||
width={25}
|
||||
height={25}
|
||||
alt='Oauth provider logo'
|
||||
/>
|
||||
<Text className="font-medium capitalize">
|
||||
{getReadableProviderName(provider.providerId)}
|
||||
@@ -436,7 +437,7 @@ export default function EditUserForm({
|
||||
{!isAnonymous && (
|
||||
<Box
|
||||
component="section"
|
||||
className="grid grid-flow-row gap-y-10 p-6"
|
||||
className="grid grid-flow-row p-6 gap-y-10"
|
||||
>
|
||||
<ControlledSelect
|
||||
{...register('defaultRole')}
|
||||
@@ -456,11 +457,11 @@ export default function EditUserForm({
|
||||
</Option>
|
||||
))}
|
||||
</ControlledSelect>
|
||||
<div className="grid grid-flow-row place-content-start gap-6 lg:grid-flow-col lg:grid-cols-8">
|
||||
<div className="grid grid-flow-row gap-6 place-content-start lg:grid-flow-col lg:grid-cols-8">
|
||||
<InputLabel as="h3" className="col-span-2">
|
||||
Allowed Roles
|
||||
</InputLabel>
|
||||
<div className="col-span-3 grid grid-flow-row gap-6">
|
||||
<div className="grid grid-flow-row col-span-3 gap-6">
|
||||
{roles.map((role, i) => (
|
||||
<ControlledCheckbox
|
||||
id={`roles.${i}`}
|
||||
@@ -476,7 +477,7 @@ export default function EditUserForm({
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box className="grid w-full flex-shrink-0 snap-end grid-flow-col justify-between gap-3 place-self-end border-t-1 p-2">
|
||||
<Box className="grid justify-between flex-shrink-0 w-full grid-flow-col gap-3 p-2 snap-end place-self-end border-t-1">
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
|
||||
@@ -226,12 +226,12 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
|
||||
if (!users) {
|
||||
return (
|
||||
<div className="h-screen w-screen overflow-hidden">
|
||||
<div className="absolute top-0 left-0 z-50 block h-full w-full">
|
||||
<span className="top50percent relative top-1/2 mx-auto my-0 block">
|
||||
<div className="w-screen h-screen overflow-hidden">
|
||||
<div className="absolute top-0 left-0 z-50 block w-full h-full">
|
||||
<span className="relative block mx-auto my-0 top50percent top-1/2">
|
||||
<ActivityIndicator
|
||||
label="Loading users..."
|
||||
className="my-auto flex items-center justify-center"
|
||||
className="flex items-center justify-center my-auto"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
@@ -269,7 +269,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
}}
|
||||
className="grid grid-flow-col items-center gap-2 p-2 text-sm+ font-medium"
|
||||
>
|
||||
<UserIcon className="h-4 w-4" />
|
||||
<UserIcon className="w-4 h-4" />
|
||||
<Text className="font-medium">View User</Text>
|
||||
</Dropdown.Item>
|
||||
|
||||
@@ -280,7 +280,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
sx={{ color: 'error.main' }}
|
||||
onClick={() => handleDeleteUser(user)}
|
||||
>
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
<TrashIcon className="w-4 h-4" />
|
||||
<Text className="font-medium" color="error">
|
||||
Delete User
|
||||
</Text>
|
||||
@@ -294,14 +294,14 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
onClick={() => handleViewUser(user)}
|
||||
aria-label={`View ${user.displayName}`}
|
||||
>
|
||||
<div className="col-span-2 grid grid-flow-col place-content-start gap-4">
|
||||
<div className="grid grid-flow-col col-span-2 gap-4 place-content-start">
|
||||
<Avatar
|
||||
src={user.avatarUrl}
|
||||
alt={`Avatar of ${user.displayName}`}
|
||||
/>
|
||||
<div className="grid grid-flow-row items-center">
|
||||
<div className="grid grid-flow-col items-center gap-2">
|
||||
<Text className="truncate font-medium leading-5">
|
||||
<div className="grid items-center grid-flow-row">
|
||||
<div className="grid items-center grid-flow-col gap-2">
|
||||
<Text className="font-medium leading-5 truncate">
|
||||
{user.displayName}
|
||||
</Text>
|
||||
{user.disabled && (
|
||||
@@ -314,7 +314,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Text className="truncate font-normal" color="secondary">
|
||||
<Text className="font-normal truncate" color="secondary">
|
||||
{user.email}
|
||||
</Text>
|
||||
</div>
|
||||
@@ -334,7 +334,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
: '-'}
|
||||
</Text>
|
||||
|
||||
<div className="col-span-2 hidden grid-flow-col place-content-start gap-3 px-4 lg:grid">
|
||||
<div className="hidden grid-flow-col col-span-2 gap-3 px-4 place-content-start lg:grid">
|
||||
{user.userProviders.length === 0 && (
|
||||
<Text className="col-span-3 font-medium">-</Text>
|
||||
)}
|
||||
@@ -362,6 +362,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
}
|
||||
width={16}
|
||||
height={16}
|
||||
alt='Oauth provider logo'
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -102,10 +102,10 @@ export default function BaseColumnForm({
|
||||
return (
|
||||
<Form
|
||||
onSubmit={handleExternalSubmit}
|
||||
className="flex flex-auto flex-col content-between overflow-hidden border-t-1"
|
||||
className="flex flex-col content-between flex-auto overflow-hidden border-t-1"
|
||||
>
|
||||
<div className="flex-auto overflow-y-auto">
|
||||
<section className="grid grid-cols-8 py-3 px-6">
|
||||
<section className="grid grid-cols-8 px-6 py-3">
|
||||
<Input
|
||||
{...register('name', {
|
||||
onChange: (event) => {
|
||||
@@ -184,7 +184,7 @@ export default function BaseColumnForm({
|
||||
</Text>
|
||||
</span>
|
||||
}
|
||||
className="col-span-8 m-0 w-full py-3 sm:col-span-6 sm:col-start-3 sm:ml-1"
|
||||
className="w-full col-span-8 py-3 m-0 sm:col-span-6 sm:col-start-3 sm:ml-1"
|
||||
onChange={(_event, checked) => {
|
||||
if (checked) {
|
||||
setDefaultValueInputText('');
|
||||
@@ -197,7 +197,7 @@ export default function BaseColumnForm({
|
||||
|
||||
<Box
|
||||
component="section"
|
||||
className="grid grid-cols-8 border-t-1 py-3 px-6"
|
||||
className="grid grid-cols-8 px-6 py-3 border-t-1"
|
||||
>
|
||||
<ControlledAutocomplete
|
||||
id="defaultValue"
|
||||
@@ -249,7 +249,7 @@ export default function BaseColumnForm({
|
||||
/>
|
||||
|
||||
<ControlledCheckbox
|
||||
className="col-span-8 m-0 w-full py-3 sm:col-span-6 sm:col-start-3 sm:ml-1"
|
||||
className="w-full col-span-8 py-3 m-0 sm:col-span-6 sm:col-start-3 sm:ml-1"
|
||||
name="isNullable"
|
||||
label={
|
||||
<span className="inline-grid grid-flow-row">
|
||||
@@ -269,7 +269,7 @@ export default function BaseColumnForm({
|
||||
/>
|
||||
|
||||
<ControlledCheckbox
|
||||
className="col-span-8 m-0 w-full py-3 sm:col-span-6 sm:col-start-3 sm:ml-1"
|
||||
className="w-full col-span-8 py-3 m-0 sm:col-span-6 sm:col-start-3 sm:ml-1"
|
||||
name="isUnique"
|
||||
label={
|
||||
<span className="inline-grid grid-flow-row">
|
||||
@@ -306,7 +306,7 @@ export default function BaseColumnForm({
|
||||
</Box>
|
||||
</div>
|
||||
|
||||
<Box className="grid flex-shrink-0 grid-flow-col justify-between gap-3 border-t-1 p-2">
|
||||
<Box className="grid justify-between flex-shrink-0 grid-flow-col gap-3 p-2 border-t-1">
|
||||
<Button
|
||||
variant="borderless"
|
||||
color="secondary"
|
||||
|
||||
@@ -107,9 +107,9 @@ export default function BaseForeignKeyForm({
|
||||
selectedColumn?.isPrimary || selectedColumn?.isUnique || false,
|
||||
});
|
||||
}}
|
||||
className="flex flex-auto flex-col content-between overflow-hidden pb-4"
|
||||
className="flex flex-col content-between flex-auto pb-4 overflow-hidden"
|
||||
>
|
||||
<Box className="grid flex-auto grid-flow-row gap-4 overflow-y-auto border-t-1 py-4">
|
||||
<Box className="grid flex-auto grid-flow-row gap-4 py-4 overflow-y-auto border-t-1">
|
||||
<Box component="section" className="grid grid-flow-row gap-4 px-6">
|
||||
<Text variant="h3">From</Text>
|
||||
|
||||
@@ -185,7 +185,7 @@ export default function BaseForeignKeyForm({
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box className="grid flex-shrink-0 grid-flow-row gap-2 border-t-1 px-6 pt-4">
|
||||
<Box className="grid flex-shrink-0 grid-flow-row gap-2 px-6 pt-4 border-t-1">
|
||||
<Button loading={isSubmitting} disabled={isSubmitting} type="submit">
|
||||
{submitButtonText}
|
||||
</Button>
|
||||
|
||||
@@ -14,8 +14,8 @@ import { Text } from '@/components/ui/v2/Text';
|
||||
import { useMetadataQuery } from '@/features/database/dataGrid/hooks/useMetadataQuery';
|
||||
import { useTableQuery } from '@/features/database/dataGrid/hooks/useTableQuery';
|
||||
import { getTruncatedText } from '@/utils/getTruncatedText';
|
||||
import type { AutocompleteGroupedOption } from '@mui/base/AutocompleteUnstyled';
|
||||
import { useAutocomplete } from '@mui/base/AutocompleteUnstyled';
|
||||
import type { AutocompleteGroupedOption } from '@mui/base/useAutocomplete';
|
||||
import { useAutocomplete } from '@mui/base/useAutocomplete';
|
||||
import type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';
|
||||
import { autocompleteClasses } from '@mui/material/Autocomplete';
|
||||
import type {
|
||||
@@ -366,11 +366,11 @@ function ColumnAutocomplete(
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ArrowLeftIcon className="h-4 w-4" />
|
||||
<ArrowLeftIcon className="w-4 h-4" />
|
||||
</IconButton>
|
||||
)}
|
||||
|
||||
<Text className="direction-rtl truncate text-left">
|
||||
<Text className="text-left truncate direction-rtl">
|
||||
<Text component="span" color="disabled">
|
||||
{defaultTable}
|
||||
</Text>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { triggerToast } from '@/utils/toast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useRouter } from 'next/router';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type * as Yup from 'yup';
|
||||
|
||||
export interface CreateColumnFormProps
|
||||
extends Pick<BaseColumnFormProps, 'onCancel' | 'location'> {
|
||||
@@ -50,7 +51,9 @@ export default function CreateColumnForm({
|
||||
resetForeignKeyError();
|
||||
}
|
||||
|
||||
const form = useForm<BaseColumnFormValues>({
|
||||
const form = useForm<
|
||||
BaseColumnFormValues | Yup.InferType<typeof baseColumnValidationSchema>
|
||||
>({
|
||||
defaultValues: {
|
||||
name: '',
|
||||
type: null,
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type * as Yup from 'yup';
|
||||
|
||||
export interface CreateForeignKeyFormProps
|
||||
extends Pick<
|
||||
@@ -34,7 +35,10 @@ export default function CreateForeignKeyForm({
|
||||
}: CreateForeignKeyFormProps) {
|
||||
const [error, setError] = useState<Error>(null);
|
||||
|
||||
const form = useForm<BaseForeignKeyFormValues>({
|
||||
const form = useForm<
|
||||
| BaseForeignKeyFormValues
|
||||
| Yup.InferType<typeof baseForeignKeyValidationSchema>
|
||||
>({
|
||||
defaultValues: {
|
||||
id: null,
|
||||
name: '',
|
||||
|
||||
@@ -16,6 +16,7 @@ import { triggerToast } from '@/utils/toast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useRouter } from 'next/router';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type * as Yup from 'yup';
|
||||
|
||||
export interface CreateTableFormProps
|
||||
extends Pick<BaseTableFormProps, 'onCancel' | 'location'> {
|
||||
@@ -53,7 +54,9 @@ export default function CreateTableForm({
|
||||
|
||||
const error = createTableError || trackTableError || foreignKeyError;
|
||||
|
||||
const form = useForm<BaseTableFormValues>({
|
||||
const form = useForm<
|
||||
BaseTableFormValues | Yup.InferType<typeof baseTableValidationSchema>
|
||||
>({
|
||||
defaultValues: {
|
||||
columns: [
|
||||
{
|
||||
|
||||
@@ -241,7 +241,7 @@ function DataBrowserSidebarContent({
|
||||
) {
|
||||
openDrawer({
|
||||
title: (
|
||||
<span className="inline-grid grid-flow-col items-center gap-2">
|
||||
<span className="inline-grid items-center grid-flow-col gap-2">
|
||||
Permissions
|
||||
<InlineCode className="!text-sm+ font-normal">{table}</InlineCode>
|
||||
<Chip label="Preview" size="small" color="info" component="span" />
|
||||
@@ -263,12 +263,12 @@ function DataBrowserSidebarContent({
|
||||
}
|
||||
|
||||
return (
|
||||
<Box className="flex h-full flex-col justify-between">
|
||||
<Box className="flex flex-col justify-between h-full">
|
||||
<Box className="flex flex-col px-2">
|
||||
{schemas && schemas.length > 0 && (
|
||||
<Select
|
||||
renderValue={(option) => (
|
||||
<span className="grid grid-flow-col items-center gap-1">
|
||||
<span className="grid items-center grid-flow-col gap-1">
|
||||
{option?.label}
|
||||
</span>
|
||||
)}
|
||||
@@ -281,7 +281,7 @@ function DataBrowserSidebarContent({
|
||||
>
|
||||
{schemas.map((schema) => (
|
||||
<Option
|
||||
className="grid grid-flow-col items-center gap-1"
|
||||
className="grid items-center grid-flow-col gap-1"
|
||||
value={schema.schema_name}
|
||||
key={schema.schema_name}
|
||||
>
|
||||
@@ -295,7 +295,7 @@ function DataBrowserSidebarContent({
|
||||
</Text>
|
||||
{(isSchemaLocked(schema.schema_name) || isGitHubConnected) && (
|
||||
<LockIcon
|
||||
className="h-3 w-3"
|
||||
className="w-3 h-3"
|
||||
sx={{ color: 'text.secondary' }}
|
||||
/>
|
||||
)}
|
||||
@@ -317,7 +317,7 @@ function DataBrowserSidebarContent({
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
underline="hover"
|
||||
className="grid grid-flow-col items-center justify-start gap-1"
|
||||
className="grid items-center justify-start grid-flow-col gap-1"
|
||||
>
|
||||
Learn More <ArrowRightIcon />
|
||||
</Link>
|
||||
@@ -327,7 +327,7 @@ function DataBrowserSidebarContent({
|
||||
<Button
|
||||
variant="borderless"
|
||||
endIcon={<PlusIcon />}
|
||||
className="mt-1 w-full justify-between px-2"
|
||||
className="justify-between w-full px-2 mt-1"
|
||||
onClick={() => {
|
||||
openDrawer({
|
||||
title: 'Create a New Table',
|
||||
@@ -396,7 +396,7 @@ function DataBrowserSidebarContent({
|
||||
}
|
||||
>
|
||||
<UsersIcon
|
||||
className="h-4 w-4"
|
||||
className="w-4 h-4"
|
||||
sx={{ color: 'text.secondary' }}
|
||||
/>
|
||||
<span>View Permissions</span>
|
||||
@@ -426,7 +426,7 @@ function DataBrowserSidebarContent({
|
||||
}
|
||||
>
|
||||
<PencilIcon
|
||||
className="h-4 w-4"
|
||||
className="w-4 h-4"
|
||||
sx={{ color: 'text.secondary' }}
|
||||
/>
|
||||
<span>Edit Table</span>
|
||||
@@ -449,7 +449,7 @@ function DataBrowserSidebarContent({
|
||||
}
|
||||
>
|
||||
<UsersIcon
|
||||
className="h-4 w-4"
|
||||
className="w-4 h-4"
|
||||
sx={{ color: 'text.secondary' }}
|
||||
/>
|
||||
<span>Edit Permissions</span>
|
||||
@@ -473,7 +473,7 @@ function DataBrowserSidebarContent({
|
||||
}
|
||||
>
|
||||
<TrashIcon
|
||||
className="h-4 w-4"
|
||||
className="w-4 h-4"
|
||||
sx={{ color: 'error.main' }}
|
||||
/>
|
||||
<span>Delete Table</span>
|
||||
@@ -521,7 +521,7 @@ function DataBrowserSidebarContent({
|
||||
component={NavLink}
|
||||
href={sqlEditorHref}
|
||||
>
|
||||
<div className="flex w-full flex-row items-center justify-center space-x-4">
|
||||
<div className="flex flex-row items-center justify-center w-full space-x-4">
|
||||
<TerminalIcon />
|
||||
<span className="flex">SQL Editor</span>
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,7 @@ import { triggerToast } from '@/utils/toast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useRouter } from 'next/router';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type * as Yup from 'yup';
|
||||
|
||||
export interface EditColumnFormProps
|
||||
extends Pick<BaseColumnFormProps, 'onCancel' | 'location'> {
|
||||
@@ -78,7 +79,9 @@ export default function EditColumnForm({
|
||||
comment: originalColumn.comment || null,
|
||||
};
|
||||
|
||||
const form = useForm<BaseColumnFormValues>({
|
||||
const form = useForm<
|
||||
BaseColumnFormValues | Yup.InferType<typeof baseColumnValidationSchema>
|
||||
>({
|
||||
defaultValues: columnValues,
|
||||
reValidateMode: 'onSubmit',
|
||||
resolver: yupResolver(baseColumnValidationSchema),
|
||||
|
||||
@@ -12,6 +12,7 @@ import type { ForeignKeyRelation } from '@/features/database/dataGrid/types/data
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type * as Yup from 'yup';
|
||||
|
||||
export interface EditForeignKeyFormProps
|
||||
extends Pick<
|
||||
@@ -40,7 +41,10 @@ export default function EditForeignKeyForm({
|
||||
}: EditForeignKeyFormProps) {
|
||||
const [error, setError] = useState<Error>(null);
|
||||
|
||||
const form = useForm<BaseForeignKeyFormValues>({
|
||||
const form = useForm<
|
||||
| BaseForeignKeyFormValues
|
||||
| Yup.InferType<typeof baseForeignKeyValidationSchema>
|
||||
>({
|
||||
defaultValues: {
|
||||
id: foreignKeyRelation.id,
|
||||
name: foreignKeyRelation.name,
|
||||
|
||||
@@ -22,6 +22,7 @@ import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type * as Yup from 'yup';
|
||||
|
||||
export interface EditTableFormProps
|
||||
extends Pick<BaseTableFormProps, 'onCancel' | 'location'> {
|
||||
@@ -85,7 +86,9 @@ export default function EditTableForm({
|
||||
resetUpdateError();
|
||||
}
|
||||
|
||||
const form = useForm<BaseTableFormValues>({
|
||||
const form = useForm<
|
||||
BaseTableFormValues | Yup.InferType<typeof baseTableValidationSchema>
|
||||
>({
|
||||
defaultValues: {
|
||||
name: originalTable.table_name,
|
||||
columns: [],
|
||||
|
||||
@@ -45,7 +45,7 @@ export default function AuthDomain() {
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation();
|
||||
|
||||
const form = useForm<{ capacity: number }>({
|
||||
const form = useForm<Yup.InferType<typeof validationSchema>>({
|
||||
reValidateMode: 'onSubmit',
|
||||
defaultValues: { capacity },
|
||||
resolver: yupResolver(validationSchema),
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Box } from '@/components/ui/v2/Box';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Checkbox } from '@/components/ui/v2/Checkbox';
|
||||
import { BaseDialog } from '@/components/ui/v2/Dialog';
|
||||
import { Link } from '@/components/ui/v2/Link';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { useAppState } from '@/features/projects/common/hooks/useAppState';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
@@ -85,6 +84,7 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
|
||||
const currentPlan = plans.find((plan) => plan.id === app.plan.id);
|
||||
const selectedPlan = plans.find((plan) => plan.id === selectedPlanId);
|
||||
const higherPlans = plans.filter((plan) => plan.price > currentPlan.price);
|
||||
|
||||
useEffect(() => {
|
||||
if (!pollingCurrentProject || state === ApplicationStatus.Paused) {
|
||||
@@ -201,53 +201,6 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
);
|
||||
}
|
||||
|
||||
if (app.plan.id !== plans.find((plan) => plan.isFree)?.id) {
|
||||
return (
|
||||
<Box className="mx-auto w-full max-w-xl rounded-lg p-6 text-left">
|
||||
<div className="flex flex-col">
|
||||
<div className="mx-auto">
|
||||
<Image
|
||||
src="/assets/upgrade.svg"
|
||||
alt="Nhost Logo"
|
||||
width={72}
|
||||
height={72}
|
||||
/>
|
||||
</div>
|
||||
<Text variant="h3" component="h2" className="mt-2 text-center">
|
||||
Downgrade is not available
|
||||
</Text>
|
||||
|
||||
<Text className="mt-1 text-center">
|
||||
You can't downgrade from a paid plan to a free plan here.
|
||||
</Text>
|
||||
|
||||
<Text className="text-center">
|
||||
Please contact us at{' '}
|
||||
<Link href="mailto:info@nhost.io">info@nhost.io</Link> if you want
|
||||
to downgrade.
|
||||
</Text>
|
||||
|
||||
<div className="mt-6 grid grid-flow-row gap-2">
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
className="mx-auto w-full max-w-sm"
|
||||
onClick={() => {
|
||||
if (close) {
|
||||
close();
|
||||
}
|
||||
|
||||
closeAlertDialog();
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box className="w-full max-w-xl rounded-lg p-6 text-left">
|
||||
<BaseDialog
|
||||
@@ -277,7 +230,7 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
</Text>
|
||||
|
||||
<div className="mt-2">
|
||||
{plans
|
||||
{higherPlans
|
||||
.filter((plan) => plan.id !== app.plan.id)
|
||||
.map((plan) => (
|
||||
<div className="mt-4" key={plan.id}>
|
||||
|
||||
@@ -102,7 +102,7 @@ export default function WorkspaceAndProjectList({
|
||||
placeholder="Find Project"
|
||||
startAdornment={
|
||||
<SearchIcon
|
||||
className="ml-2 -mr-1 h-4 w-4 shrink-0"
|
||||
className="w-4 h-4 ml-2 -mr-1 shrink-0"
|
||||
sx={{ color: 'text.disabled' }}
|
||||
/>
|
||||
}
|
||||
@@ -123,7 +123,7 @@ export default function WorkspaceAndProjectList({
|
||||
</NavLink>
|
||||
</Box>
|
||||
|
||||
<Box className="my-8 grid grid-flow-row gap-8">
|
||||
<Box className="grid grid-flow-row gap-8 my-8">
|
||||
{filteredWorkspaces.map((workspace) => (
|
||||
<div key={workspace.slug}>
|
||||
<NavLink href={`/${workspace.slug}`} passHref>
|
||||
@@ -147,7 +147,7 @@ export default function WorkspaceAndProjectList({
|
||||
secondaryAction={
|
||||
<div className="grid grid-flow-col gap-px">
|
||||
{latestDeployment && (
|
||||
<div className="mr-2 flex self-center align-middle">
|
||||
<div className="flex self-center mr-2 align-middle">
|
||||
<StatusCircle
|
||||
status={
|
||||
latestDeployment.deploymentStatus as DeploymentStatus
|
||||
@@ -171,10 +171,11 @@ export default function WorkspaceAndProjectList({
|
||||
<NavLink
|
||||
href={`${workspace?.slug}/${project.slug}`}
|
||||
passHref
|
||||
className='w-full'
|
||||
>
|
||||
<ListItem.Button className="rounded-none">
|
||||
<ListItem.Avatar>
|
||||
<div className="h-10 w-10 overflow-hidden rounded-lg">
|
||||
<div className="w-10 h-10 overflow-hidden rounded-lg">
|
||||
<Image
|
||||
src="/logos/new.svg"
|
||||
alt="Nhost Logo"
|
||||
|
||||
@@ -48,14 +48,14 @@ export default function WorkspaceSidebar({
|
||||
<List className="grid grid-flow-row gap-2">
|
||||
{workspaces.map(({ id, name, slug }) => (
|
||||
<ListItem.Root key={id}>
|
||||
<NavLink href={`/${slug}`} passHref>
|
||||
<NavLink href={`/${slug}`} passHref className='w-full'>
|
||||
<ListItem.Button
|
||||
dense
|
||||
aria-label={`View ${name}`}
|
||||
className="!p-1"
|
||||
>
|
||||
<ListItem.Avatar className="h-8 w-8">
|
||||
<div className="inline-block h-8 w-8 overflow-hidden rounded-lg">
|
||||
<ListItem.Avatar className="w-8 h-8">
|
||||
<div className="inline-block w-8 h-8 overflow-hidden rounded-lg">
|
||||
<Image
|
||||
src="/logos/new.svg"
|
||||
alt="Nhost Logo"
|
||||
@@ -131,7 +131,7 @@ export default function WorkspaceSidebar({
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
<Button
|
||||
className="grid grid-flow-col gap-1"
|
||||
className="grid w-full grid-flow-col gap-1"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
startIcon={<GitHubIcon />}
|
||||
@@ -147,7 +147,7 @@ export default function WorkspaceSidebar({
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
<Button
|
||||
className="grid grid-flow-col gap-1"
|
||||
className="grid w-full grid-flow-col gap-1"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
aria-labelledby="discord-button-label"
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function AuthDomain() {
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation();
|
||||
|
||||
const form = useForm<{ auth_fqdn: string }>({
|
||||
const form = useForm<Yup.InferType<typeof validationSchema>>({
|
||||
reValidateMode: 'onSubmit',
|
||||
defaultValues: { auth_fqdn: null },
|
||||
resolver: yupResolver(validationSchema),
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function HasuraDomain() {
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation();
|
||||
|
||||
const form = useForm<{ hasura_fqdn: string }>({
|
||||
const form = useForm<Yup.InferType<typeof validationSchema>>({
|
||||
reValidateMode: 'onSubmit',
|
||||
defaultValues: { hasura_fqdn: null },
|
||||
resolver: yupResolver(validationSchema),
|
||||
|
||||
@@ -40,7 +40,7 @@ export default function RunServicePortDomain({
|
||||
const runServicePort = service.config.ports.find((p) => p.port === port);
|
||||
const initialValue = runServicePort?.ingresses?.[0]?.fqdn?.[0];
|
||||
|
||||
const form = useForm<{ runServicePortFQDN: string }>({
|
||||
const form = useForm<RunServicePortFormValues>({
|
||||
reValidateMode: 'onSubmit',
|
||||
defaultValues: {
|
||||
runServicePortFQDN: initialValue,
|
||||
|
||||
@@ -34,7 +34,7 @@ export default function ServerlessFunctionsDomain() {
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation();
|
||||
|
||||
const form = useForm<{ functions_fqdn: string }>({
|
||||
const form = useForm<ServerlessFunctionsDomainFormValues>({
|
||||
reValidateMode: 'onSubmit',
|
||||
defaultValues: { functions_fqdn: null },
|
||||
resolver: yupResolver(validationSchema),
|
||||
|
||||
@@ -17,6 +17,7 @@ export default function OverviewTopBar() {
|
||||
const { currentWorkspace, currentProject } = useCurrentWorkspaceAndProject();
|
||||
const isOwner = useIsCurrentUserOwner();
|
||||
const isStarter = currentProject?.plan?.name === 'Starter';
|
||||
const isPro = currentProject?.plan?.name === 'Pro';
|
||||
const { openDialog } = useDialog();
|
||||
const { maintenanceActive } = useUI();
|
||||
|
||||
@@ -87,7 +88,7 @@ export default function OverviewTopBar() {
|
||||
color={!isStarter ? 'primary' : 'default'}
|
||||
/>
|
||||
|
||||
{isStarter && isOwner && (
|
||||
{(isStarter || isPro) && isOwner && (
|
||||
<Button
|
||||
variant="borderless"
|
||||
className="mr-2"
|
||||
|
||||
@@ -27,7 +27,7 @@ function AllWorkspaceApps() {
|
||||
|
||||
if (currentWorkspace?.projects?.length === 0) {
|
||||
return (
|
||||
<Box className="flex flex-row border-y py-4">
|
||||
<Box className="flex flex-row py-4 border-y">
|
||||
<Text className="text-xs" color="secondary">
|
||||
No projects on this workspace.
|
||||
</Text>
|
||||
@@ -45,11 +45,12 @@ function AllWorkspaceApps() {
|
||||
<NavLink
|
||||
href={`${currentWorkspace?.slug}/${project.slug}`}
|
||||
passHref
|
||||
className='w-full'
|
||||
>
|
||||
<ListItem.Button className="grid grid-flow-col items-center justify-between gap-2">
|
||||
<div className="grid grid-flow-col items-center justify-start gap-2">
|
||||
<ListItem.Button className="grid items-center justify-between grid-flow-col gap-2">
|
||||
<div className="grid items-center justify-start grid-flow-col gap-2">
|
||||
<ListItem.Avatar>
|
||||
<div className="h-8 w-8 overflow-hidden rounded-lg">
|
||||
<div className="w-8 h-8 overflow-hidden rounded-lg">
|
||||
<Image
|
||||
src="/logos/new.svg"
|
||||
alt="Nhost Logo"
|
||||
@@ -99,8 +100,8 @@ export default function WorkspaceApps() {
|
||||
|
||||
return (
|
||||
<div className="mt-9">
|
||||
<div className="mx-auto max-w-3xl font-display">
|
||||
<div className="mb-4 grid grid-flow-col items-center justify-between gap-2">
|
||||
<div className="max-w-3xl mx-auto font-display">
|
||||
<div className="grid items-center justify-between grid-flow-col gap-2 mb-4">
|
||||
<Text className="text-lg font-medium">Projects</Text>
|
||||
|
||||
{!loading && (
|
||||
|
||||
@@ -13,20 +13,18 @@ import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useHostName } from '@/features/projects/common/hooks/useHostName';
|
||||
import { InfoCard } from '@/features/projects/overview/components/InfoCard';
|
||||
import {
|
||||
COST_PER_VCPU,
|
||||
MAX_SERVICES_CPU,
|
||||
MAX_SERVICES_MEM,
|
||||
MAX_SERVICE_REPLICAS,
|
||||
MIN_SERVICES_CPU,
|
||||
MIN_SERVICES_MEM,
|
||||
} from '@/features/projects/resources/settings/utils/resourceSettingsValidationSchema';
|
||||
import { COST_PER_VCPU } from '@/features/projects/resources/settings/utils/resourceSettingsValidationSchema';
|
||||
import { ComputeFormSection } from '@/features/services/components/ServiceForm/components/ComputeFormSection';
|
||||
import { EnvironmentFormSection } from '@/features/services/components/ServiceForm/components/EnvironmentFormSection';
|
||||
import { PortsFormSection } from '@/features/services/components/ServiceForm/components/PortsFormSection';
|
||||
import { ReplicasFormSection } from '@/features/services/components/ServiceForm/components/ReplicasFormSection';
|
||||
import { StorageFormSection } from '@/features/services/components/ServiceForm/components/StorageFormSection';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
|
||||
import {
|
||||
validationSchema,
|
||||
type ServiceFormProps,
|
||||
type ServiceFormValues,
|
||||
} from '@/features/services/components/ServiceForm/ServiceFormTypes';
|
||||
import { RESOURCE_VCPU_MULTIPLIER } from '@/utils/constants/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
@@ -42,72 +40,9 @@ import { useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { parse } from 'shell-quote';
|
||||
import * as Yup from 'yup';
|
||||
import { ServiceConfirmationDialog } from './components/ServiceConfirmationDialog';
|
||||
import { ServiceDetailsDialog } from './components/ServiceDetailsDialog';
|
||||
|
||||
export enum PortTypes {
|
||||
HTTP = 'http',
|
||||
TCP = 'tcp',
|
||||
UDP = 'udp',
|
||||
}
|
||||
|
||||
export const validationSchema = Yup.object({
|
||||
name: Yup.string().required('The name is required.'),
|
||||
image: Yup.string().label('Image to run'),
|
||||
command: Yup.string(),
|
||||
environment: Yup.array().of(
|
||||
Yup.object().shape({
|
||||
name: Yup.string().required(),
|
||||
value: Yup.string().required(),
|
||||
}),
|
||||
),
|
||||
compute: Yup.object({
|
||||
cpu: Yup.number().min(MIN_SERVICES_CPU).max(MAX_SERVICES_CPU).required(),
|
||||
memory: Yup.number().min(MIN_SERVICES_MEM).max(MAX_SERVICES_MEM).required(),
|
||||
}),
|
||||
replicas: Yup.number().min(0).max(MAX_SERVICE_REPLICAS).required(),
|
||||
ports: Yup.array().of(
|
||||
Yup.object().shape({
|
||||
port: Yup.number().required(),
|
||||
type: Yup.mixed<PortTypes>().oneOf(Object.values(PortTypes)).required(),
|
||||
publish: Yup.boolean().default(false),
|
||||
}),
|
||||
),
|
||||
storage: Yup.array().of(
|
||||
Yup.object()
|
||||
.shape({
|
||||
name: Yup.string().required(),
|
||||
path: Yup.string().required(),
|
||||
capacity: Yup.number().nonNullable().required(),
|
||||
})
|
||||
.required(),
|
||||
),
|
||||
});
|
||||
|
||||
export type ServiceFormValues = Yup.InferType<typeof validationSchema>;
|
||||
|
||||
export interface ServiceFormProps extends DialogFormProps {
|
||||
/**
|
||||
* To use in conjunction with initialData to allow for updating the service
|
||||
*/
|
||||
serviceID?: string;
|
||||
|
||||
/**
|
||||
* if there is initialData then it's an update operation
|
||||
*/
|
||||
initialData?: ServiceFormValues & { subdomain?: string }; // subdomain is only set on the backend
|
||||
|
||||
/**
|
||||
* Function to be called when the operation is cancelled.
|
||||
*/
|
||||
onCancel?: VoidFunction;
|
||||
/**
|
||||
* Function to be called when the submit is successful.
|
||||
*/
|
||||
onSubmit?: VoidFunction | ((args?: any) => Promise<any>);
|
||||
}
|
||||
|
||||
export default function ServiceForm({
|
||||
serviceID,
|
||||
initialData,
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { PortTypes } from '@/features/services/components/ServiceForm/components/PortsFormSection/PortsFormSectionTypes';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
import {
|
||||
MAX_SERVICES_CPU,
|
||||
MAX_SERVICES_MEM,
|
||||
MAX_SERVICE_REPLICAS,
|
||||
MIN_SERVICES_CPU,
|
||||
MIN_SERVICES_MEM,
|
||||
} from '@/features/projects/resources/settings/utils/resourceSettingsValidationSchema';
|
||||
|
||||
export const validationSchema = Yup.object({
|
||||
name: Yup.string().required('The name is required.'),
|
||||
image: Yup.string().label('Image to run'),
|
||||
command: Yup.string(),
|
||||
environment: Yup.array().of(
|
||||
Yup.object().shape({
|
||||
name: Yup.string().required(),
|
||||
value: Yup.string().required(),
|
||||
}),
|
||||
),
|
||||
compute: Yup.object({
|
||||
cpu: Yup.number().min(MIN_SERVICES_CPU).max(MAX_SERVICES_CPU).required(),
|
||||
memory: Yup.number().min(MIN_SERVICES_MEM).max(MAX_SERVICES_MEM).required(),
|
||||
}),
|
||||
replicas: Yup.number().min(0).max(MAX_SERVICE_REPLICAS).required(),
|
||||
ports: Yup.array().of(
|
||||
Yup.object().shape({
|
||||
port: Yup.number().required(),
|
||||
type: Yup.mixed<PortTypes>().oneOf(Object.values(PortTypes)).required(),
|
||||
publish: Yup.boolean().default(false),
|
||||
}),
|
||||
),
|
||||
storage: Yup.array().of(
|
||||
Yup.object()
|
||||
.shape({
|
||||
name: Yup.string().required(),
|
||||
path: Yup.string().required(),
|
||||
capacity: Yup.number().nonNullable().required(),
|
||||
})
|
||||
.required(),
|
||||
),
|
||||
});
|
||||
|
||||
export type ServiceFormValues = Yup.InferType<typeof validationSchema>;
|
||||
|
||||
export interface ServiceFormProps extends DialogFormProps {
|
||||
/**
|
||||
* To use in conjunction with initialData to allow for updating the service
|
||||
*/
|
||||
serviceID?: string;
|
||||
|
||||
/**
|
||||
* if there is initialData then it's an update operation
|
||||
*/
|
||||
initialData?: ServiceFormValues & { subdomain?: string }; // subdomain is only set on the backend
|
||||
|
||||
/**
|
||||
* Function to be called when the operation is cancelled.
|
||||
*/
|
||||
onCancel?: VoidFunction;
|
||||
/**
|
||||
* Function to be called when the submit is successful.
|
||||
*/
|
||||
onSubmit?: VoidFunction | ((args?: any) => Promise<any>);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
MEM_CPU_RATIO,
|
||||
MIN_SERVICES_MEM,
|
||||
} from '@/features/projects/resources/settings/utils/resourceSettingsValidationSchema';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm/ServiceFormTypes';
|
||||
import { useFormContext, useWatch } from 'react-hook-form';
|
||||
|
||||
interface ComputeFormSectionProps {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { TrashIcon } from '@/components/ui/v2/icons/TrashIcon';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm/ServiceFormTypes';
|
||||
import { useState } from 'react';
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
|
||||
|
||||
@@ -11,10 +11,8 @@ import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { InfoCard } from '@/features/projects/overview/components/InfoCard';
|
||||
import {
|
||||
PortTypes,
|
||||
type ServiceFormValues,
|
||||
} from '@/features/services/components/ServiceForm';
|
||||
import { PortTypes } from '@/features/services/components/ServiceForm/components/PortsFormSection/PortsFormSectionTypes';
|
||||
import { type ServiceFormValues } from '@/features/services/components/ServiceForm/ServiceFormTypes';
|
||||
import { useFieldArray, useFormContext, useWatch } from 'react-hook-form';
|
||||
|
||||
export default function PortsFormSection() {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum PortTypes {
|
||||
HTTP = 'http',
|
||||
TCP = 'tcp',
|
||||
UDP = 'udp',
|
||||
}
|
||||
@@ -1,2 +1 @@
|
||||
/* eslint-disable import/no-cycle */
|
||||
export { default as PortsFormSection } from './PortsFormSection';
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Slider } from '@/components/ui/v2/Slider';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { MAX_SERVICE_REPLICAS } from '@/features/projects/resources/settings/utils/resourceSettingsValidationSchema';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm/ServiceFormTypes';
|
||||
import { useFormContext, useWatch } from 'react-hook-form';
|
||||
|
||||
export default function ReplicasFormSection() {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { InfoIcon } from '@/components/ui/v2/icons/InfoIcon';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { COST_PER_VCPU } from '@/features/projects/resources/settings/utils/resourceSettingsValidationSchema';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm/ServiceFormTypes';
|
||||
import { RESOURCE_VCPU_MULTIPLIER } from '@/utils/constants/common';
|
||||
|
||||
export interface ServiceConfirmationDialogProps {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
MAX_STORAGE_CAPACITY,
|
||||
MIN_STORAGE_CAPACITY,
|
||||
} from '@/features/projects/resources/settings/utils/resourceSettingsValidationSchema';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm';
|
||||
import type { ServiceFormValues } from '@/features/services/components/ServiceForm/ServiceFormTypes';
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
|
||||
export default function StorageFormSection() {
|
||||
@@ -53,7 +53,8 @@ export default function StorageFormSection() {
|
||||
<span>
|
||||
By default, services do not have persistent storage. You can add
|
||||
SSD disks to the service here. It is important to note that
|
||||
capacity can not be decreased after creation, only expanded. Refer to{' '}
|
||||
capacity can not be decreased after creation, only expanded.
|
||||
Refer to{' '}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
@@ -82,7 +83,7 @@ export default function StorageFormSection() {
|
||||
{fields.map((field, index) => (
|
||||
<Box
|
||||
key={field.id}
|
||||
className="flex w-full flex-col space-y-2 xs+:flex-row xs+:space-y-0 xs+:space-x-2"
|
||||
className="flex w-full flex-col space-y-2 xs+:flex-row xs+:space-x-2 xs+:space-y-0"
|
||||
>
|
||||
<Input
|
||||
{...register(`storage.${index}.name`)}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from './ServiceForm';
|
||||
export { default as ServiceForm } from './ServiceForm';
|
||||
|
||||
@@ -11,10 +11,8 @@ import { UserIcon } from '@/components/ui/v2/icons/UserIcon';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { DeleteServiceModal } from '@/features/projects/common/components/DeleteServiceModal';
|
||||
import {
|
||||
ServiceForm,
|
||||
type PortTypes,
|
||||
} from '@/features/services/components/ServiceForm';
|
||||
import { ServiceForm } from '@/features/services/components/ServiceForm';
|
||||
import { type PortTypes } from '@/features/services/components/ServiceForm/components/PortsFormSection/PortsFormSectionTypes';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import type { RunService } from 'pages/[workspaceSlug]/[appSlug]/services';
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { default as useHypertune } from './useHypertune';
|
||||
@@ -1,14 +0,0 @@
|
||||
import hypertune from '@/hypertune/hypertune';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function useHypertune() {
|
||||
const [, setIsInitialized] = useState<boolean>(hypertune.isInitialized());
|
||||
|
||||
useEffect(() => {
|
||||
hypertune.waitForInitialization().then(() => {
|
||||
setIsInitialized(true);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return hypertune;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import { initializeHypertune } from './project_2596';
|
||||
|
||||
const hypertune = initializeHypertune({});
|
||||
|
||||
export default hypertune;
|
||||
@@ -1,107 +0,0 @@
|
||||
/* eslint-disable */
|
||||
|
||||
import * as sdk from "hypertune";
|
||||
|
||||
const projectId = 2596;
|
||||
|
||||
const businessToken = `U2FsdGVkX19+V8BJnVR0xLEC+42OW5qZl/A0i6beAaRmJoIhFh5Yf6eIKBzLbV9h`;
|
||||
|
||||
const queryCode = `query InitQuery {
|
||||
root {
|
||||
enableServices
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const query = {"Query":{"objectTypeName":"Query","selection":{"root":{"fieldArguments":{"__isPartialObject__":true},"fieldQuery":{"Root":{"objectTypeName":"Root","selection":{"enableServices":{"fieldArguments":{},"fieldQuery":null}}}}}}}};
|
||||
|
||||
const fallbackInitData: sdk.FallbackInitData & { [key: string]: unknown } = {"commitId":3297,"reducedExpression":{"id":"caxyeQqTKX3UGOXClvbnW","logs":{"events":{},"exposures":{},"evaluations":{}},"type":"ObjectExpression","fields":{"root":{"id":"PoMWxsy7KbW9fCq5XXvx4","body":{"id":"IUICRjZ7iSnh9k0cWBmnd","logs":{"events":{},"exposures":{},"evaluations":{}},"type":"ObjectExpression","fields":{"enableServices":{"id":"7WZWy2AIy_q9Vbz4cn9KB","logs":{"evaluations":{"XNOtHkUBpglrY1nkYa_bf":1},"events":{},"exposures":{}},"type":"BooleanExpression","value":true,"valueType":{"type":"BooleanValueType"}}},"valueType":{"type":"ObjectValueType","objectTypeName":"Root"},"objectTypeName":"Root"},"logs":{"events":{},"exposures":{},"evaluations":{}},"type":"FunctionExpression","valueType":{"type":"FunctionValueType","returnValueType":{"type":"ObjectValueType","objectTypeName":"Root"},"parameterValueTypes":[{"type":"ObjectValueType","objectTypeName":"Query_root_args"}]},"parameters":[{"id":"Ygjhl2LqjiwcousTABFQz","name":"rootArgs"}]}},"metadata":{"permissions":{"user":{},"group":{"team":{"write":"allow"}}}},"valueType":{"type":"ObjectValueType","objectTypeName":"Query"},"objectTypeName":"Query"},"splits":{},"eventTypes":{},"commitConfig":{"splitConfig":{}},"initLogId":0,"commitHash":"4178461588049503","sdkConfig":{"hashPollInterval":1000,"flushLogsInterval":1000,"maxLogsPerFlush":1},"query":{"Query":{"objectTypeName":"Query","selection":{"root":{"fieldArguments":{"__isPartialObject__":true},"fieldQuery":{"Root":{"objectTypeName":"Root","selection":{"enableServices":{"fieldArguments":{},"fieldQuery":null}}}}}}}}};
|
||||
|
||||
export function initializeHypertune(
|
||||
variableValues: Rec,
|
||||
options: sdk.InitializeOptions = {}
|
||||
): QueryNode {
|
||||
const defaultOptions = { businessToken, query, fallbackInitData };
|
||||
|
||||
return sdk.initialize(
|
||||
QueryNode,
|
||||
projectId,
|
||||
queryCode,
|
||||
variableValues,
|
||||
{ ...defaultOptions, ...options }
|
||||
);
|
||||
}
|
||||
|
||||
// Enum types
|
||||
|
||||
|
||||
|
||||
// Input object types
|
||||
|
||||
export type Rec = {
|
||||
|
||||
//
|
||||
};
|
||||
|
||||
export type Rec2 = {
|
||||
context: Rec3;
|
||||
//
|
||||
};
|
||||
|
||||
export type Rec3 = {
|
||||
workSpace: Rec4;
|
||||
//
|
||||
};
|
||||
|
||||
export type Rec4 = {
|
||||
id: string;
|
||||
//
|
||||
};
|
||||
|
||||
// Enum node classes
|
||||
|
||||
|
||||
|
||||
// Fragment node classes
|
||||
|
||||
export class QueryNode extends sdk.Node {
|
||||
typeName = "Query" as const;
|
||||
|
||||
root(args: Rec2): RootNode {
|
||||
const props0 = this.getField("root", args);
|
||||
const expression0 = props0.expression;
|
||||
|
||||
if (
|
||||
expression0 &&
|
||||
expression0.type === "ObjectExpression"
|
||||
&& expression0.objectTypeName === "Root"
|
||||
) {
|
||||
return new RootNode(props0);
|
||||
}
|
||||
|
||||
const node = new RootNode(props0);
|
||||
node._logUnexpectedTypeError();
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
export class RootNode extends sdk.Node {
|
||||
typeName = "Root" as const;
|
||||
|
||||
enableServices(args: Rec): sdk.BooleanNode {
|
||||
const props0 = this.getField("enableServices", args);
|
||||
const expression0 = props0.expression;
|
||||
|
||||
if (
|
||||
expression0 &&
|
||||
expression0.type === "BooleanExpression"
|
||||
|
||||
) {
|
||||
return new sdk.BooleanNode(props0);
|
||||
}
|
||||
|
||||
const node = new sdk.BooleanNode(props0);
|
||||
node._logUnexpectedTypeError();
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ function GraphiQLHeader({ onUserChange, onRoleChange }: GraphiQLHeaderProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="grid grid-flow-row items-end gap-2 p-2 md:grid-flow-col md:justify-between">
|
||||
<header className="grid items-end grid-flow-row gap-2 p-2 md:grid-flow-col md:justify-between">
|
||||
<div className="grid grid-flow-row gap-2 md:grid-flow-col md:items-end">
|
||||
<div className="grid grid-cols-2 gap-2 md:grid-flow-col md:grid-cols-[initial]">
|
||||
<UserSelect
|
||||
|
||||
@@ -13,10 +13,8 @@ import type { GetRunServicesQuery } from '@/utils/__generated__/graphql';
|
||||
import { useGetRunServicesQuery } from '@/utils/__generated__/graphql';
|
||||
|
||||
import { UpgradeNotification } from '@/features/projects/common/components/UpgradeNotification';
|
||||
import {
|
||||
ServiceForm,
|
||||
type PortTypes,
|
||||
} from '@/features/services/components/ServiceForm';
|
||||
import { ServiceForm } from '@/features/services/components/ServiceForm';
|
||||
import { type PortTypes } from '@/features/services/components/ServiceForm/components/PortsFormSection/PortsFormSectionTypes';
|
||||
import ServicesList from '@/features/services/components/ServicesList/ServicesList';
|
||||
import { useRouter } from 'next/router';
|
||||
import {
|
||||
|
||||
@@ -11,7 +11,6 @@ import { Option } from '@/components/ui/v2/Option';
|
||||
import { Radio } from '@/components/ui/v2/Radio';
|
||||
import { RadioGroup } from '@/components/ui/v2/RadioGroup';
|
||||
import { Select } from '@/components/ui/v2/Select';
|
||||
import type { TextProps } from '@/components/ui/v2/Text';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { planDescriptions } from '@/features/projects/common/utils/planDescriptions';
|
||||
@@ -37,7 +36,7 @@ import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import type { FormEvent, ReactElement } from 'react';
|
||||
import { cloneElement, isValidElement, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import slugify from 'slugify';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
@@ -321,22 +320,22 @@ export function NewProjectPageContent({
|
||||
});
|
||||
}}
|
||||
value={selectedRegion.id}
|
||||
renderValue={(option) => {
|
||||
const [flag, , country] = (option?.label as any[]) || [];
|
||||
|
||||
return (
|
||||
<span className="inline-grid grid-flow-col grid-rows-none items-center gap-x-2">
|
||||
{flag}
|
||||
|
||||
{isValidElement<TextProps>(country)
|
||||
? cloneElement(country, {
|
||||
...country.props,
|
||||
variant: 'body1',
|
||||
})
|
||||
: null}
|
||||
renderValue={() => (
|
||||
<div className="relative grid grid-flow-col items-center justify-start gap-x-3">
|
||||
<span className="row-span-2 flex">
|
||||
<Image
|
||||
src={`/assets/flags/${selectedRegion.code}.svg`}
|
||||
alt={`${selectedRegion.name} country flag`}
|
||||
width={16}
|
||||
height={12}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}}
|
||||
|
||||
<Text variant="body1" className="row-span-1">
|
||||
{selectedRegion.name}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
{regionOptions.map((option) => (
|
||||
<Option
|
||||
@@ -366,7 +365,7 @@ export function NewProjectPageContent({
|
||||
{option.disabled && (
|
||||
<Text
|
||||
variant="subtitle2"
|
||||
className="absolute top-1/2 right-4 -translate-y-1/2"
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2"
|
||||
>
|
||||
Disabled
|
||||
</Text>
|
||||
|
||||
@@ -40,6 +40,7 @@ export const mockRouter: NextRouter = {
|
||||
emit: vi.fn(),
|
||||
},
|
||||
isFallback: false,
|
||||
forward: vi.fn(),
|
||||
};
|
||||
|
||||
export const mockApplication: Project = {
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
render as rtlRender,
|
||||
waitForElementToBeRemoved as rtlWaitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
import { RouterContext } from 'next/dist/shared/lib/router-context';
|
||||
import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime';
|
||||
import type { PropsWithChildren, ReactElement } from 'react';
|
||||
import { Toaster } from 'react-hot-toast';
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/cli
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/nhost-js@3.0.2
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"name": "@nhost-examples/cli",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"main": "src/index.mjs",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node src/index.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nhost/nhost-js": "*",
|
||||
"commander": "^10.0.0",
|
||||
"dotenv": "^16.0.3",
|
||||
"graphql": "16.6.0",
|
||||
"@nhost/nhost-js": "^3.0.2",
|
||||
"commander": "^10.0.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"graphql": "16.8.1",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"pino": "^8.14.1"
|
||||
"pino": "^8.17.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @nhost-examples/codegen-react-apollo
|
||||
|
||||
## 0.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/react-apollo@7.0.2
|
||||
- @nhost/react@3.0.2
|
||||
|
||||
## 0.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/codegen-react-apollo",
|
||||
"version": "0.1.10",
|
||||
"version": "0.1.11",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"codegen": "graphql-codegen",
|
||||
@@ -15,27 +15,27 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.7.3",
|
||||
"@nhost/react": "*",
|
||||
"@nhost/react-apollo": "*",
|
||||
"@apollo/client": "^3.8.9",
|
||||
"@nhost/react": "^3.0.2",
|
||||
"@nhost/react-apollo": "^7.0.2",
|
||||
"clsx": "^1.2.1",
|
||||
"graphql": "15.7.2",
|
||||
"graphql": "16.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/cli": "^2.14.1",
|
||||
"@graphql-codegen/client-preset": "^1.1.5",
|
||||
"@graphql-typed-document-node/core": "^3.1.1",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/react": "^18.2.14",
|
||||
"@types/react-dom": "^18.2.6",
|
||||
"@vitejs/plugin-react": "^3.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"postcss": "^8.4.19",
|
||||
"tailwindcss": "^3.2.1",
|
||||
"typescript": "^4.6.4",
|
||||
"vite": "^4.0.2"
|
||||
"@graphql-codegen/cli": "^2.16.5",
|
||||
"@graphql-codegen/client-preset": "^1.3.0",
|
||||
"@graphql-typed-document-node/core": "^3.2.0",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@types/node": "^18.19.6",
|
||||
"@types/react": "^18.2.47",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"postcss": "^8.4.33",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^4.9.5",
|
||||
"vite": "^5.0.12"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/codegen-react-query
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/react@3.0.2
|
||||
|
||||
## 0.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/codegen-react-query",
|
||||
"version": "0.1.11",
|
||||
"version": "0.1.12",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"codegen": "graphql-codegen",
|
||||
@@ -15,28 +15,28 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@nhost/react": "*",
|
||||
"@tanstack/react-query": "^4.2.3",
|
||||
"@tanstack/react-query-devtools": "^4.2.3",
|
||||
"@nhost/react": "^3.0.2",
|
||||
"@tanstack/react-query": "^4.36.1",
|
||||
"@tanstack/react-query-devtools": "^4.36.1",
|
||||
"clsx": "^1.2.1",
|
||||
"graphql": "15.7.2",
|
||||
"graphql-request": "^6.0.0",
|
||||
"graphql": "16.8.1",
|
||||
"graphql-request": "^6.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/cli": "^2.14.1",
|
||||
"@graphql-codegen/client-preset": "^1.1.5",
|
||||
"@graphql-typed-document-node/core": "^3.1.1",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@types/node": "^16.11.56",
|
||||
"@types/react": "^18.2.14",
|
||||
"@types/react-dom": "^18.2.6",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "^8.23.0",
|
||||
"postcss": "^8.4.20",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"typescript": "^4.8.2",
|
||||
"vite": "^4.0.2"
|
||||
"@graphql-codegen/cli": "^2.16.5",
|
||||
"@graphql-codegen/client-preset": "^1.3.0",
|
||||
"@graphql-typed-document-node/core": "^3.2.0",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@types/node": "^16.18.70",
|
||||
"@types/react": "^18.2.47",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"eslint": "^8.56.0",
|
||||
"postcss": "^8.4.33",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^4.9.5",
|
||||
"vite": "^5.0.12"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @nhost-examples/react-urql
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/react-urql@4.0.2
|
||||
- @nhost/react@3.0.2
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@nhost-examples/codegen-react-urql",
|
||||
"private": true,
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.8",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
@@ -9,27 +9,27 @@
|
||||
"codegen": "graphql-codegen"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nhost/react": "*",
|
||||
"@nhost/react-urql": "*",
|
||||
"@nhost/react": "^3.0.2",
|
||||
"@nhost/react-urql": "^4.0.2",
|
||||
"clsx": "^1.2.1",
|
||||
"graphql": "15.7.2",
|
||||
"graphql": "16.8.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"urql": "^3.0.3"
|
||||
"urql": "^3.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/cli": "^2.14.1",
|
||||
"@graphql-codegen/client-preset": "^1.1.5",
|
||||
"@graphql-typed-document-node/core": "^3.1.1",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@types/node": "^16.11.7",
|
||||
"@types/react": "^18.2.14",
|
||||
"@types/react-dom": "^18.2.6",
|
||||
"@vitejs/plugin-react": "^3.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"postcss": "^8.4.19",
|
||||
"tailwindcss": "^3.2.1",
|
||||
"typescript": "^4.6.4",
|
||||
"vite": "^4.0.2"
|
||||
"@graphql-codegen/cli": "^2.16.5",
|
||||
"@graphql-codegen/client-preset": "^1.3.0",
|
||||
"@graphql-typed-document-node/core": "^3.2.0",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@types/node": "^16.18.70",
|
||||
"@types/react": "^18.2.47",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"postcss": "^8.4.33",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^4.9.5",
|
||||
"vite": "^5.0.12"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @nhost-examples/docker-compose
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
|
||||
## 0.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
{
|
||||
"name": "@nhost-examples/docker-compose",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"e2e": "vitest run"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-fetch": "^3.1.5"
|
||||
"cross-fetch": "^3.1.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"graphql": "16.8.1"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/multi-tenant-one-to-many
|
||||
|
||||
## 2.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/nhost-js@3.0.2
|
||||
|
||||
## 2.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@nhost-examples/multi-tenant-one-to-many",
|
||||
"private": true,
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {},
|
||||
@@ -9,11 +9,11 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.13",
|
||||
"express": "^4.18.1",
|
||||
"typescript": "^4.8.2"
|
||||
"@types/express": "^4.17.21",
|
||||
"express": "^4.18.2",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nhost/nhost-js": "*"
|
||||
"@nhost/nhost-js": "^3.0.2"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,15 @@
|
||||
# @nhost-examples/nextjs
|
||||
|
||||
## 0.1.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/react-apollo@7.0.2
|
||||
- @nhost/nextjs@2.0.2
|
||||
- @nhost/react@3.0.2
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/nextjs",
|
||||
"version": "0.1.12",
|
||||
"version": "0.1.13",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -15,28 +15,28 @@
|
||||
"verify:fix": "run-p prettier:fix lint:fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.6.9",
|
||||
"@apollo/client": "^3.8.9",
|
||||
"@mantine/core": "^4.2.12",
|
||||
"@mantine/hooks": "^4.2.12",
|
||||
"@mantine/next": "^4.2.12",
|
||||
"@mantine/notifications": "^4.2.12",
|
||||
"@nhost/nextjs": "*",
|
||||
"@nhost/react": "*",
|
||||
"@nhost/react-apollo": "*",
|
||||
"graphql": "15.7.2",
|
||||
"next": "12.1.6",
|
||||
"@nhost/nextjs": "^2.0.2",
|
||||
"@nhost/react": "^3.0.2",
|
||||
"@nhost/react-apollo": "^7.0.2",
|
||||
"graphql": "16.8.1",
|
||||
"next": "^14.0.4",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-icons": "^4.4.0"
|
||||
"react-icons": "^4.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "^12.2.5",
|
||||
"@types/node": "^16.11.7",
|
||||
"@types/react": "^18.2.14",
|
||||
"@xstate/inspect": "^0.6.2",
|
||||
"@next/bundle-analyzer": "^12.3.4",
|
||||
"@types/node": "^16.18.70",
|
||||
"@types/react": "^18.2.47",
|
||||
"@xstate/inspect": "^0.6.5",
|
||||
"eslint-config-next": "12.0.10",
|
||||
"typescript": "^4.8.2",
|
||||
"ws": "^8.8.1",
|
||||
"xstate": "^4.33.5"
|
||||
"typescript": "^4.9.5",
|
||||
"ws": "^8.16.0",
|
||||
"xstate": "^4.38.3"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/node-storage
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/nhost-js@3.0.2
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/node-storage",
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"private": true,
|
||||
"description": "This is an example of how to use the Storage with Node.js",
|
||||
"main": "src/index.mjs",
|
||||
@@ -11,15 +11,15 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@nhost/nhost-js": "*",
|
||||
"dotenv": "^16.1.3",
|
||||
"@nhost/nhost-js": "^3.0.2",
|
||||
"dotenv": "^16.3.1",
|
||||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^11.1.1",
|
||||
"node-fetch": "^3.3.0",
|
||||
"uuid": "^9.0.0"
|
||||
"fs-extra": "^11.2.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.15.11",
|
||||
"@types/uuid": "^9.0.1"
|
||||
"@types/node": "^18.19.6",
|
||||
"@types/uuid": "^9.0.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @nhost-examples/nextjs-server-components
|
||||
|
||||
## 0.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
- Updated dependencies [8d91f71]
|
||||
- @nhost/nhost-js@3.0.2
|
||||
|
||||
## 0.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
experimental: {
|
||||
serverActions: true
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = nextConfig
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/nextjs-server-components",
|
||||
"version": "0.1.4",
|
||||
"version": "0.1.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -9,28 +9,28 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.8.2",
|
||||
"@apollo/client": "^3.8.9",
|
||||
"@nhost/nhost-js": "workspace:^",
|
||||
"autoprefixer": "10.4.15",
|
||||
"cookies-next": "^3.0.0",
|
||||
"eslint": "8.48.0",
|
||||
"eslint-config-next": "13.4.19",
|
||||
"form-data": "^4.0.0",
|
||||
"graphql": "16.7.1",
|
||||
"graphql": "16.8.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"next": "13.4.19",
|
||||
"postcss": "8.4.29",
|
||||
"next": "^14.0.4",
|
||||
"postcss": "^8.4.33",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"tailwind-merge": "^1.8.0",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwindcss": "3.3.3",
|
||||
"typescript": "5.2.2",
|
||||
"xstate": "^4.38.2"
|
||||
"xstate": "^4.38.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "20.5.6",
|
||||
"@types/react": "18.2.21",
|
||||
"@types/react": "18.2.47",
|
||||
"@types/react-dom": "18.2.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { NhostClient } from '@nhost/nhost-js'
|
||||
import { useState, type FormEvent } from 'react'
|
||||
|
||||
const nhost = new NhostClient({
|
||||
subdomain: process.env.NEXT_PUBLIC_NHOST_SUBDOMAIN,
|
||||
subdomain: process.env.NEXT_PUBLIC_NHOST_SUBDOMAIN || 'local',
|
||||
region: process.env.NEXT_PUBLIC_NHOST_REGION
|
||||
})
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useState, type FormEvent } from 'react'
|
||||
const NHOST_SESSION_KEY = 'nhostSession'
|
||||
|
||||
const nhost = new NhostClient({
|
||||
subdomain: process.env.NEXT_PUBLIC_NHOST_SUBDOMAIN,
|
||||
subdomain: process.env.NEXT_PUBLIC_NHOST_SUBDOMAIN || 'local',
|
||||
region: process.env.NEXT_PUBLIC_NHOST_REGION
|
||||
})
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useState, type FormEvent } from 'react'
|
||||
const NHOST_SESSION_KEY = 'nhostSession'
|
||||
|
||||
const nhost = new NhostClient({
|
||||
subdomain: process.env.NEXT_PUBLIC_NHOST_SUBDOMAIN,
|
||||
subdomain: process.env.NEXT_PUBLIC_NHOST_SUBDOMAIN || 'local',
|
||||
region: process.env.NEXT_PUBLIC_NHOST_REGION
|
||||
})
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ export default function Input({
|
||||
}: DetailedHTMLProps<HTMLProps<HTMLInputElement>, HTMLInputElement>) {
|
||||
const { pending } = useFormStatus()
|
||||
|
||||
const { children, ...restOfInputProps } = rest
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{label && (
|
||||
@@ -29,7 +31,7 @@ export default function Input({
|
||||
required={required}
|
||||
disabled={pending}
|
||||
className="block w-full p-3 border rounded-md border-slate-300 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
{...rest}
|
||||
{...restOfInputProps}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -6,17 +6,17 @@ import { experimental_useFormStatus as useFormStatus } from 'react-dom'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
type ButtonProps = {
|
||||
type?: 'button' | 'submit' | 'reset' | undefined
|
||||
} & DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
|
||||
type?: 'button' | 'submit' | 'reset' | undefined;
|
||||
} & DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>;
|
||||
|
||||
export default function SubmitButton({
|
||||
disabled,
|
||||
type,
|
||||
children,
|
||||
className,
|
||||
children,
|
||||
...rest
|
||||
}: ButtonProps) {
|
||||
const { pending } = useFormStatus()
|
||||
const { pending } = useFormStatus();
|
||||
|
||||
return (
|
||||
<button
|
||||
@@ -33,5 +33,5 @@ export default function SubmitButton({
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"baseUrl": "./",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
@@ -24,6 +25,7 @@
|
||||
"@actions": ["./src/app/actions"],
|
||||
"@server-actions/*": ["./src/app/server-actions/*"],
|
||||
"@types": ["./src/types"],
|
||||
"react": ["./node_modules/@types/react"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
---
|
||||
|
||||
## 0.2.2
|
||||
### Patch Changes
|
||||
|
||||
- 8d91f71: chore: update deps and enable pnpm audit
|
||||
|
||||
## 0.2.1
|
||||
### Patch Changes
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost-examples/sveltekit",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@@ -8,39 +8,38 @@
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
|
||||
"install-browsers": "pnpm dlx playwright@1.31.0 install --with-deps",
|
||||
"add-nhost-js": "pnpm add @nhost/nhost-js@2.2.18 --ignore-workspace",
|
||||
"test": "pnpm install-browsers && pnpm add-nhost-js && pnpm dlx playwright@1.31.0 test",
|
||||
"install-browsers": "pnpm playwright install && pnpm playwright install-deps",
|
||||
"test": "pnpm add-nhost-js && pnpm install-browsers && pnpm playwright test",
|
||||
"lint": "eslint .",
|
||||
"postinstall": "pnpm add-nhost-js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nhost/nhost-js": "2.2.18",
|
||||
"@playwright/test": "^1.31.0",
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/kit": "^1.5.0",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte": "^2.26.0",
|
||||
"postcss": "^8.4.23",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-svelte": "^2.8.1",
|
||||
"svelte": "^3.54.0",
|
||||
"svelte-check": "^3.0.1",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^4.3.8",
|
||||
"vitest": "^0.25.3"
|
||||
"@playwright/test": "^1.41.0",
|
||||
"@sveltejs/adapter-auto": "^2.1.1",
|
||||
"@sveltejs/kit": "^1.30.3",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^8.10.0",
|
||||
"eslint-plugin-svelte": "^2.35.1",
|
||||
"postcss": "^8.4.33",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-svelte": "^2.10.1",
|
||||
"svelte": "^3.59.2",
|
||||
"svelte-check": "^3.6.3",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.12",
|
||||
"vitest": "^0.25.8"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"graphql": "^16.7.1",
|
||||
"graphql": "16.8.1",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"js-cookie": "^3.0.5",
|
||||
"playwright": "^1.37.1",
|
||||
"uuid": "^9.0.0",
|
||||
"xstate": "^4.38.2"
|
||||
"uuid": "^9.0.1",
|
||||
"xstate": "^4.38.3"
|
||||
}
|
||||
}
|
||||
|
||||
26
examples/quickstarts/sveltekit/pnpm-lock.yaml
generated
26
examples/quickstarts/sveltekit/pnpm-lock.yaml
generated
@@ -6,31 +6,31 @@ settings:
|
||||
|
||||
dependencies:
|
||||
graphql:
|
||||
specifier: ^16.7.1
|
||||
version: 16.8.0
|
||||
specifier: 16.8.1
|
||||
version: 16.8.1
|
||||
|
||||
devDependencies:
|
||||
'@nhost/nhost-js':
|
||||
specifier: 2.2.18
|
||||
version: 2.2.18(graphql@16.8.0)
|
||||
version: 2.2.18(graphql@16.8.1)
|
||||
|
||||
packages:
|
||||
|
||||
/@graphql-typed-document-node/core@3.2.0(graphql@16.8.0):
|
||||
/@graphql-typed-document-node/core@3.2.0(graphql@16.8.1):
|
||||
resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==}
|
||||
peerDependencies:
|
||||
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
dependencies:
|
||||
graphql: 16.8.0
|
||||
graphql: 16.8.1
|
||||
dev: true
|
||||
|
||||
/@nhost/graphql-js@0.1.4(graphql@16.8.0):
|
||||
/@nhost/graphql-js@0.1.4(graphql@16.8.1):
|
||||
resolution: {integrity: sha512-IPHuGOf4iQrFsxG7Rh5jCCZzPCN9JkvldFww4Fz1lCVi9ZQNEaGaawIP5gBuBHeYIuALeaK1wVYKPc7vJ/euCA==}
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0
|
||||
dependencies:
|
||||
'@graphql-typed-document-node/core': 3.2.0(graphql@16.8.0)
|
||||
graphql: 16.8.0
|
||||
'@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1)
|
||||
graphql: 16.8.1
|
||||
isomorphic-unfetch: 3.1.0
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
@@ -58,15 +58,15 @@ packages:
|
||||
- encoding
|
||||
dev: true
|
||||
|
||||
/@nhost/nhost-js@2.2.18(graphql@16.8.0):
|
||||
/@nhost/nhost-js@2.2.18(graphql@16.8.1):
|
||||
resolution: {integrity: sha512-aHn6p75fuG7SEUyB/yfX5TXtVTqwCT88zdN9Mmgo/8hnFOGV1XM7B4fxuGpNQCz18tG6kjM24tWx8EGXAEZ1sw==}
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0
|
||||
dependencies:
|
||||
'@nhost/graphql-js': 0.1.4(graphql@16.8.0)
|
||||
'@nhost/graphql-js': 0.1.4(graphql@16.8.1)
|
||||
'@nhost/hasura-auth-js': 2.1.9
|
||||
'@nhost/hasura-storage-js': 2.2.5
|
||||
graphql: 16.8.0
|
||||
graphql: 16.8.1
|
||||
isomorphic-unfetch: 3.1.0
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
@@ -109,8 +109,8 @@ packages:
|
||||
mime-types: 2.1.35
|
||||
dev: true
|
||||
|
||||
/graphql@16.8.0:
|
||||
resolution: {integrity: sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg==}
|
||||
/graphql@16.8.1:
|
||||
resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==}
|
||||
engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
|
||||
|
||||
/isomorphic-unfetch@3.1.0:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user