Compare commits
25 Commits
@nhost/rea
...
@nhost/apo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25bc4b7fd6 | ||
|
|
da20159ec5 | ||
|
|
2ae5ea8bc1 | ||
|
|
3ba485e582 | ||
|
|
e5bab6a061 | ||
|
|
be64353145 | ||
|
|
2f5913c78d | ||
|
|
757ddd901c | ||
|
|
1a61c658a7 | ||
|
|
d3d14245c7 | ||
|
|
53d2f9d3e0 | ||
|
|
8c34c69e79 | ||
|
|
b19ffed273 | ||
|
|
859efa988a | ||
|
|
3202b6b897 | ||
|
|
ba73bb4003 | ||
|
|
d5337ff5bd | ||
|
|
511ab19755 | ||
|
|
7c2a1c29fd | ||
|
|
5c9b8f0a3f | ||
|
|
b3f1f5f6ea | ||
|
|
6b8aad5c84 | ||
|
|
c36132c9bb | ||
|
|
b18edc0532 | ||
|
|
1d55d3ea38 |
82
.github/workflows/gen_schedule_update_deps.yaml
vendored
Normal file
82
.github/workflows/gen_schedule_update_deps.yaml
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
name: "gen: update depenendencies"
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 1 * *'
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}:role/github-actions-nhost-be
|
||||
aws-region: eu-central-1
|
||||
|
||||
- uses: nixbuild/nix-quick-install-action@v26
|
||||
with:
|
||||
nix_version: 2.16.2
|
||||
nix_conf: |
|
||||
experimental-features = nix-command flakes
|
||||
sandbox = false
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
substituters = https://cache.nixos.org/?priority=40 s3://nhost-nix-cache?region=eu-central-1&priority=50
|
||||
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
|
||||
- name: Cache nix store
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /nix
|
||||
key: nix-update-deps-${{ hashFiles('flakes.nix', 'flake.lock') }}
|
||||
|
||||
- name: Update nix flakes
|
||||
run: nix flake update
|
||||
|
||||
- name: Update dependencies
|
||||
run: |
|
||||
nix develop -c bash -c "
|
||||
pnpm dedupe
|
||||
pnpm update -r
|
||||
pnpm dedupe
|
||||
"
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Update dependencies
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
signoff: false
|
||||
branch: automated/update-deps
|
||||
delete-branch: true
|
||||
title: '[Scheduled] Update dependencies'
|
||||
body: |
|
||||
Dependencies updated
|
||||
|
||||
Note - If you see this PR and the checks haven't run, close and reopen the PR. See https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs
|
||||
labels: |
|
||||
dependencies
|
||||
draft: false
|
||||
|
||||
- name: "Cache nix store on s3"
|
||||
run: |
|
||||
echo ${{ secrets.NIX_CACHE_PRIV_KEY }} > cache-priv-key.pem
|
||||
nix build .\#devShells.x86_64-linux.default
|
||||
nix store sign --key-file cache-priv-key.pem --all
|
||||
nix copy --to s3://nhost-nix-cache\?region=eu-central-1 .\#devShells.x86_64-linux.default
|
||||
|
||||
- run: rm cache-priv-key.pem
|
||||
if: always()
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -19,7 +19,7 @@ logs/
|
||||
coverage/
|
||||
dist/
|
||||
umd/
|
||||
node_modules/
|
||||
node_modules
|
||||
tmp/
|
||||
.pnpm-store
|
||||
.turbo
|
||||
|
||||
7
SECURITY.md
Normal file
7
SECURITY.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
At Nhost, we take security vulnerabilities seriously and appreciate the assistance of the community in bringing any issues to our attention. If you discover a security vulnerability, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/nhost/nhost/security/advisories/new) tab.
|
||||
|
||||
Once you have submitted the report, we will promptly conduct a thorough investigation within 72 hours. In case we need further information, we may contact you for additional details. Rest assured that addressing the reported vulnerability in a timely manner is our top priority.
|
||||
@@ -1,5 +1,41 @@
|
||||
# @nhost/dashboard
|
||||
|
||||
## 1.6.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 3ba485e: fix: added discord.com to connect-src
|
||||
- e5bab6a: chore: update dependencies
|
||||
- Updated dependencies [b19ffed]
|
||||
- Updated dependencies [e5bab6a]
|
||||
- @nhost/nextjs@2.1.0
|
||||
- @nhost/react-apollo@8.0.0
|
||||
|
||||
## 1.6.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ba73bb4: fix: update ErrorToast component to show the internal graphql error
|
||||
- d5337ff: fix: utilize accumulator in the creation of validation schema within data grid utils
|
||||
|
||||
## 1.6.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 7c2a1c2: feat: show error and debug info in the error toast
|
||||
|
||||
## 1.6.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 6b8aad5: fix: add bare nhost.run to CSP
|
||||
|
||||
## 1.6.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- b18edc0: feat: added CSP and X-Frame-Options
|
||||
|
||||
## 1.6.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -4,6 +4,23 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||
});
|
||||
const { version } = require('./package.json');
|
||||
|
||||
|
||||
const cspHeader = `
|
||||
default-src 'self' *.nhost.run ws://*.nhost.run nhost.run ws://nhost.run;
|
||||
script-src 'self' 'unsafe-eval' 'unsafe-inline' cdn.segment.com js.stripe.com;
|
||||
connect-src 'self' *.nhost.run ws://*.nhost.run nhost.run ws://nhost.run discord.com;
|
||||
style-src 'self' 'unsafe-inline';
|
||||
img-src 'self' blob: data: avatars.githubusercontent.com s.gravatar.com *.nhost.run nhost.run;
|
||||
font-src 'self' data:;
|
||||
object-src 'none';
|
||||
base-uri 'self';
|
||||
form-action 'self';
|
||||
frame-ancestors 'none';
|
||||
frame-src 'self' js.stripe.com;
|
||||
block-all-mixed-content;
|
||||
upgrade-insecure-requests;
|
||||
`
|
||||
|
||||
module.exports = withBundleAnalyzer({
|
||||
reactStrictMode: true,
|
||||
swcMinify: false,
|
||||
@@ -17,6 +34,23 @@ module.exports = withBundleAnalyzer({
|
||||
eslint: {
|
||||
dirs: ['src'],
|
||||
},
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
source: '/(.*)',
|
||||
headers: [
|
||||
{
|
||||
key: 'X-Frame-Options',
|
||||
value: 'SAMEORIGIN'
|
||||
},
|
||||
{
|
||||
key: 'Content-Security-Policy',
|
||||
value: cspHeader.replace(/\n/g, ''),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
async redirects() {
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/dashboard",
|
||||
"version": "1.6.1",
|
||||
"version": "1.6.6",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
@@ -19,7 +19,7 @@
|
||||
"e2e": "pnpm install-browsers && pnpm playwright test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.8.9",
|
||||
"@apollo/client": "^3.9.1",
|
||||
"@codemirror/lang-sql": "^6.5.5",
|
||||
"@emotion/cache": "^11.11.0",
|
||||
"@emotion/react": "^11.11.3",
|
||||
@@ -33,8 +33,8 @@
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@mui/base": "5.0.0-beta.31",
|
||||
"@mui/material": "^5.15.4",
|
||||
"@mui/system": "^5.15.4",
|
||||
"@mui/material": "^5.15.7",
|
||||
"@mui/system": "^5.15.7",
|
||||
"@mui/x-date-pickers": "^5.0.20",
|
||||
"@nhost/nextjs": "workspace:*",
|
||||
"@nhost/react-apollo": "workspace:*",
|
||||
@@ -43,14 +43,15 @@
|
||||
"@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",
|
||||
"@tanstack/react-table": "^8.11.7",
|
||||
"@tanstack/react-virtual": "^3.0.2",
|
||||
"@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.30.0",
|
||||
"framer-motion": "^10.18.0",
|
||||
"generate-password": "^1.7.1",
|
||||
"graphiql": "^3.1.0",
|
||||
"graphql": "16.8.1",
|
||||
@@ -59,7 +60,7 @@
|
||||
"graphql-ws": "^5.14.3",
|
||||
"just-kebab-case": "^4.2.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"next": "^14.0.4",
|
||||
"next": "^14.1.0",
|
||||
"next-seo": "^6.4.0",
|
||||
"node-pg-format": "^1.3.5",
|
||||
"pluralize": "^8.0.0",
|
||||
@@ -67,9 +68,9 @@
|
||||
"react-children-utilities": "^2.10.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-error-boundary": "^4.0.12",
|
||||
"react-hook-form": "^7.49.3",
|
||||
"react-hook-form": "^7.50.0",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"react-intersection-observer": "^9.5.3",
|
||||
"react-intersection-observer": "^9.5.4",
|
||||
"react-is": "18.2.0",
|
||||
"react-loading-skeleton": "^2.2.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
@@ -84,13 +85,13 @@
|
||||
"slugify": "^1.6.6",
|
||||
"stripe": "^10.17.0",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"utility-types": "^3.10.0",
|
||||
"utility-types": "^3.11.0",
|
||||
"validator": "^13.11.0",
|
||||
"yup": "^1.3.3",
|
||||
"yup-password": "^0.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.7",
|
||||
"@babel/core": "^7.23.9",
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@graphql-codegen/cli": "^3.3.1",
|
||||
"@graphql-codegen/typescript": "^3.0.4",
|
||||
@@ -110,29 +111,29 @@
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@testing-library/react": "^14.2.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/ace": "^0.0.48",
|
||||
"@types/bcryptjs": "^2.4.6",
|
||||
"@types/jest": "^29.5.11",
|
||||
"@types/lodash.debounce": "^4.0.9",
|
||||
"@types/node": "^16.18.70",
|
||||
"@types/node": "^16.18.78",
|
||||
"@types/pluralize": "^0.0.30",
|
||||
"@types/react": "^18.2.47",
|
||||
"@types/react": "^18.2.50",
|
||||
"@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",
|
||||
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
||||
"@typescript-eslint/parser": "^6.20.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@vitest/coverage-v8": "^0.32.4",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"babel-loader": "^8.3.0",
|
||||
"babel-plugin-transform-remove-console": "^6.9.4",
|
||||
"csstype": "^3.1.3",
|
||||
"dotenv": "^16.3.1",
|
||||
"dotenv": "^16.4.1",
|
||||
"encoding": "^0.1.13",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-airbnb": "19.0.4",
|
||||
@@ -144,7 +145,7 @@
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"jsdom": "^22.1.0",
|
||||
"lint-staged": "^15.2.0",
|
||||
"lint-staged": "^15.2.1",
|
||||
"msw": "^1.3.2",
|
||||
"msw-storybook-addon": "^1.10.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
@@ -160,7 +161,7 @@
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths-webpack-plugin": "^4.1.0",
|
||||
"vite": "^5.0.12",
|
||||
"vite-tsconfig-paths": "^4.2.3",
|
||||
"vite-tsconfig-paths": "^4.3.1",
|
||||
"vitest": "^0.32.4"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
135
dashboard/src/components/ui/v2/ErrorToast/ErrorToast.tsx
Normal file
135
dashboard/src/components/ui/v2/ErrorToast/ErrorToast.tsx
Normal file
@@ -0,0 +1,135 @@
|
||||
import { ChevronDownIcon } from '@/components/ui/v2/icons/ChevronDownIcon';
|
||||
import { ChevronUpIcon } from '@/components/ui/v2/icons/ChevronUpIcon';
|
||||
import { CopyIcon } from '@/components/ui/v2/icons/CopyIcon';
|
||||
import { XIcon } from '@/components/ui/v2/icons/XIcon';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { getToastBackgroundColor } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { type ApolloError } from '@apollo/client';
|
||||
import { useUserData } from '@nhost/nextjs';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useState } from 'react';
|
||||
|
||||
interface ErrorDetails {
|
||||
info: {
|
||||
projectId: string;
|
||||
userId: string;
|
||||
url?: string;
|
||||
};
|
||||
error: any;
|
||||
}
|
||||
|
||||
export default function ErrorToast({
|
||||
isVisible,
|
||||
errorMessage,
|
||||
error,
|
||||
close,
|
||||
}: {
|
||||
isVisible: boolean;
|
||||
errorMessage: string;
|
||||
error: ApolloError;
|
||||
close: () => void;
|
||||
}) {
|
||||
const userData = useUserData();
|
||||
const { asPath } = useRouter();
|
||||
|
||||
const [showInfo, setShowInfo] = useState(false);
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const errorDetails: ErrorDetails = {
|
||||
info: {
|
||||
projectId: currentProject?.id,
|
||||
userId: userData?.id || 'local',
|
||||
url: asPath,
|
||||
},
|
||||
error,
|
||||
};
|
||||
|
||||
const internalError = error?.graphQLErrors?.at(0)?.extensions?.internal as {
|
||||
error: {
|
||||
message: string;
|
||||
};
|
||||
};
|
||||
|
||||
const msg =
|
||||
internalError?.error?.message ||
|
||||
error?.graphQLErrors?.at(0).message ||
|
||||
errorMessage;
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isVisible && (
|
||||
<motion.div
|
||||
style={{
|
||||
backgroundColor: getToastBackgroundColor(),
|
||||
}}
|
||||
className="flex w-full max-w-xl flex-col space-y-4 rounded-lg p-4 text-white"
|
||||
initial={{
|
||||
opacity: 0,
|
||||
y: 100,
|
||||
}}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
y: 0,
|
||||
}}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
scale: 0,
|
||||
y: 100,
|
||||
}}
|
||||
transition={{
|
||||
bounce: 0.1,
|
||||
}}
|
||||
>
|
||||
<div className="flex w-full flex-row items-center justify-between space-x-4">
|
||||
<button onClick={close} type="button" aria-label="Close">
|
||||
<XIcon className="h-4 w-4 text-white" />
|
||||
</button>
|
||||
<span>
|
||||
{msg ?? 'An unkown error has occured, please try again later!'}
|
||||
</span>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowInfo(!showInfo)}
|
||||
className="flex flex-row items-center justify-center space-x-2 text-white"
|
||||
>
|
||||
<span>Info</span>
|
||||
{showInfo ? (
|
||||
<ChevronUpIcon className="h-3 w-3 text-white" />
|
||||
) : (
|
||||
<ChevronDownIcon className="h-3 w-3 text-white" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{showInfo && (
|
||||
<div className="flex flex-col space-y-4">
|
||||
<div className="relative flex flex-col">
|
||||
<div className="relative flex max-h-[400px] w-full max-w-xl flex-row justify-between overflow-x-auto rounded-lg bg-black p-4">
|
||||
<pre>{JSON.stringify(errorDetails, null, 2)}</pre>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Copy error details"
|
||||
className="absolute right-2 top-2"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
copy(
|
||||
JSON.stringify(errorDetails, null, 2),
|
||||
'Error details',
|
||||
);
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
1
dashboard/src/components/ui/v2/ErrorToast/index.ts
Normal file
1
dashboard/src/components/ui/v2/ErrorToast/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as ErrorToast } from './ErrorToast';
|
||||
@@ -4,16 +4,14 @@ import { Box } from '@/components/ui/v2/Box';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Checkbox } from '@/components/ui/v2/Checkbox';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
useDeleteUserAccountMutation,
|
||||
useGetAllWorkspacesAndProjectsQuery,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { type ApolloError } from '@apollo/client';
|
||||
import { useSignOut, useUserData } from '@nhost/nextjs';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
function ConfirmDeleteAccountModal({
|
||||
@@ -44,30 +42,19 @@ function ConfirmDeleteAccountModal({
|
||||
const onClickConfirm = async () => {
|
||||
setLoadingRemove(true);
|
||||
|
||||
await toast.promise(
|
||||
deleteUserAccount(),
|
||||
{
|
||||
loading: 'Deleting your account...',
|
||||
success: `The account has been deleted successfully.`,
|
||||
error: (arg: ApolloError) => {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } = (internal as Record<string, any>)?.error || {};
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
'An error occurred while deleting your account. Please try again.'
|
||||
);
|
||||
},
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await deleteUserAccount();
|
||||
onDelete?.();
|
||||
close();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Deleting your account...',
|
||||
successMessage: 'The account has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while deleting your account. Please try again.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onDelete?.();
|
||||
close();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -15,15 +15,13 @@ import { ListItem } from '@/components/ui/v2/ListItem';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { CreatePATForm } from '@/features/account/settings/components/CreatePATForm';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetPersonalAccessTokensDocument,
|
||||
useDeletePersonalAccessTokenMutation,
|
||||
useGetPersonalAccessTokensQuery,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { Fragment } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function PATSettings() {
|
||||
@@ -59,28 +57,20 @@ export default function PATSettings() {
|
||||
|
||||
async function handleDeletePAT({
|
||||
id,
|
||||
}: typeof availablePersonalAccessTokens[0]) {
|
||||
const deletePATPromise = deletePAT({ variables: { patId: id } });
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
deletePATPromise,
|
||||
{
|
||||
loading: 'Deleting personal access token...',
|
||||
success: 'Personal access token has been deleted successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while deleting the personal access token.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
}: (typeof availablePersonalAccessTokens)[0]) {
|
||||
await execPromiseWithErrorToast(
|
||||
() => deletePAT({ variables: { patId: id } }),
|
||||
{
|
||||
loadingMessage: 'Deleting personal access token...',
|
||||
successMessage: 'Personal access token has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while deleting the personal access token.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function handleConfirmDelete(
|
||||
originalPAT: typeof availablePersonalAccessTokens[0],
|
||||
originalPAT: (typeof availablePersonalAccessTokens)[0],
|
||||
) {
|
||||
openAlertDialog({
|
||||
title: 'Delete Personal Access Token',
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { Form } from '@/components/form/Form';
|
||||
import { SettingsContainer } from '@/components/layout/SettingsContainer';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useChangePassword } from '@nhost/nextjs';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -38,25 +36,19 @@ export default function PasswordSettings() {
|
||||
const isDirty = Object.keys(formState.dirtyFields).length > 0;
|
||||
|
||||
async function handleSubmit(formValues: PasswordSettingsFormValues) {
|
||||
try {
|
||||
const changePasswordPromise = changePassword(formValues.newPassword);
|
||||
|
||||
await toast.promise(
|
||||
changePasswordPromise,
|
||||
{
|
||||
loading: 'Changing password...',
|
||||
success: 'The password has been changed successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while trying to update the password. Please try again.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset();
|
||||
} catch {
|
||||
// Note: The error is handled by the toast.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
// TODO fix changePassword should throw an error if something happens
|
||||
await changePassword(formValues.newPassword);
|
||||
form.reset();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Changing password...',
|
||||
successMessage: 'The password has been changed successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the password. Please try again.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -10,26 +10,17 @@ import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { GraphqlDataSourcesFormSection } from '@/features/ai/AssistantForm/components/GraphqlDataSourcesFormSection';
|
||||
import { WebhooksDataSourcesFormSection } from '@/features/ai/AssistantForm/components/WebhooksDataSourcesFormSection';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||
import { useAdminApolloClient } from '@/features/projects/common/hooks/useAdminApolloClient';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getHasuraAdminSecret } from '@/utils/env';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { removeTypename, type DeepRequired } from '@/utils/helpers';
|
||||
import {
|
||||
useInsertAssistantMutation,
|
||||
useUpdateAssistantMutation,
|
||||
} from '@/utils/__generated__/graphite.graphql';
|
||||
import {
|
||||
ApolloClient,
|
||||
HttpLink,
|
||||
InMemoryCache,
|
||||
type ApolloError,
|
||||
} from '@apollo/client';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export const validationSchema = Yup.object({
|
||||
@@ -101,32 +92,15 @@ export default function AssistantForm({
|
||||
}: AssistantFormProps) {
|
||||
const { onDirtyStateChange } = useDialog();
|
||||
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const serviceUrl = generateAppServiceUrl(
|
||||
currentProject?.subdomain,
|
||||
currentProject?.region,
|
||||
'graphql',
|
||||
);
|
||||
|
||||
const client = new ApolloClient({
|
||||
cache: new InMemoryCache(),
|
||||
link: new HttpLink({
|
||||
uri: serviceUrl,
|
||||
headers: {
|
||||
'x-hasura-admin-secret':
|
||||
process.env.NEXT_PUBLIC_ENV === 'dev'
|
||||
? getHasuraAdminSecret()
|
||||
: currentProject?.config?.hasura.adminSecret,
|
||||
},
|
||||
}),
|
||||
});
|
||||
const { adminClient } = useAdminApolloClient();
|
||||
|
||||
const [insertAssistantMutation] = useInsertAssistantMutation({
|
||||
client,
|
||||
client: adminClient,
|
||||
});
|
||||
|
||||
const [updateAssistantMutation] = useUpdateAssistantMutation({ client });
|
||||
const [updateAssistantMutation] = useUpdateAssistantMutation({
|
||||
client: adminClient,
|
||||
});
|
||||
|
||||
const form = useForm<AssistantFormValues>({
|
||||
defaultValues: initialData,
|
||||
@@ -186,33 +160,18 @@ export default function AssistantForm({
|
||||
const handleSubmit = async (
|
||||
values: DeepRequired<AssistantFormValues> & { assistantID: string },
|
||||
) => {
|
||||
try {
|
||||
await toast.promise(
|
||||
createOrUpdateAutoEmbeddings(values),
|
||||
{
|
||||
loading: 'Configuring the Assistant...',
|
||||
success: `The Assistant has been configured successfully.`,
|
||||
error: (arg: ApolloError) => {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } = (internal as Record<string, any>)?.error || {};
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
'An error occurred while configuring the Assistant. Please try again.'
|
||||
);
|
||||
},
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await createOrUpdateAutoEmbeddings(values);
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Configuring the Assistant...',
|
||||
successMessage: 'The Assistant has been configured successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while configuring the Assistant. Please try again.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -8,25 +8,16 @@ import { PlusIcon } from '@/components/ui/v2/icons/PlusIcon';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||
import { useAdminApolloClient } from '@/features/projects/common/hooks/useAdminApolloClient';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getHasuraAdminSecret } from '@/utils/env';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
useInsertGraphiteAutoEmbeddingsConfigurationMutation,
|
||||
useUpdateGraphiteAutoEmbeddingsConfigurationMutation,
|
||||
} from '@/utils/__generated__/graphite.graphql';
|
||||
import {
|
||||
ApolloClient,
|
||||
HttpLink,
|
||||
InMemoryCache,
|
||||
type ApolloError,
|
||||
} from '@apollo/client';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export const validationSchema = Yup.object({
|
||||
@@ -70,34 +61,17 @@ export default function AutoEmbeddingsForm({
|
||||
}: AutoEmbeddingsFormProps) {
|
||||
const { onDirtyStateChange } = useDialog();
|
||||
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const serviceUrl = generateAppServiceUrl(
|
||||
currentProject?.subdomain,
|
||||
currentProject?.region,
|
||||
'graphql',
|
||||
);
|
||||
|
||||
const client = new ApolloClient({
|
||||
cache: new InMemoryCache(),
|
||||
link: new HttpLink({
|
||||
uri: serviceUrl,
|
||||
headers: {
|
||||
'x-hasura-admin-secret':
|
||||
process.env.NEXT_PUBLIC_ENV === 'dev'
|
||||
? getHasuraAdminSecret()
|
||||
: currentProject?.config?.hasura.adminSecret,
|
||||
},
|
||||
}),
|
||||
});
|
||||
const { adminClient } = useAdminApolloClient();
|
||||
|
||||
const [insertGraphiteAutoEmbeddingsConfiguration] =
|
||||
useInsertGraphiteAutoEmbeddingsConfigurationMutation({
|
||||
client,
|
||||
client: adminClient,
|
||||
});
|
||||
|
||||
const [updateGraphiteAutoEmbeddingsConfiguration] =
|
||||
useUpdateGraphiteAutoEmbeddingsConfigurationMutation({ client });
|
||||
useUpdateGraphiteAutoEmbeddingsConfigurationMutation({
|
||||
client: adminClient,
|
||||
});
|
||||
|
||||
const form = useForm<AutoEmbeddingsFormValues>({
|
||||
defaultValues: initialData,
|
||||
@@ -137,33 +111,18 @@ export default function AutoEmbeddingsForm({
|
||||
};
|
||||
|
||||
const handleSubmit = async (values: AutoEmbeddingsFormValues) => {
|
||||
try {
|
||||
await toast.promise(
|
||||
createOrUpdateAutoEmbeddings(values),
|
||||
{
|
||||
loading: 'Configuring the Auto-Embeddings...',
|
||||
success: `The Auto-Embeddings has been configured successfully.`,
|
||||
error: (arg: ApolloError) => {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } = (internal as Record<string, any>)?.error || {};
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
'An error occurred while configuring the Auto-Embeddings. Please try again.'
|
||||
);
|
||||
},
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await createOrUpdateAutoEmbeddings(values);
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Configuring the Auto-Embeddings...',
|
||||
successMessage: 'The Auto-Embeddings has been configured successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while configuring the Auto-Embeddings. Please try again.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,20 +2,11 @@ import { Box } from '@/components/ui/v2/Box';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Checkbox } from '@/components/ui/v2/Checkbox';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getHasuraAdminSecret } from '@/utils/env';
|
||||
import { useAdminApolloClient } from '@/features/projects/common/hooks/useAdminApolloClient';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { useDeleteAssistantMutation } from '@/utils/__generated__/graphite.graphql';
|
||||
import {
|
||||
ApolloClient,
|
||||
HttpLink,
|
||||
InMemoryCache,
|
||||
type ApolloError,
|
||||
} from '@apollo/client';
|
||||
import { type Assistant } from 'pages/[workspaceSlug]/[appSlug]/ai/assistants';
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export interface DeleteAssistantModalProps {
|
||||
@@ -32,29 +23,10 @@ export default function DeleteAssistantModal({
|
||||
const [remove, setRemove] = useState(false);
|
||||
const [loadingRemove, setLoadingRemove] = useState(false);
|
||||
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const serviceUrl = generateAppServiceUrl(
|
||||
currentProject?.subdomain,
|
||||
currentProject?.region,
|
||||
'graphql',
|
||||
);
|
||||
|
||||
const client = new ApolloClient({
|
||||
cache: new InMemoryCache(),
|
||||
link: new HttpLink({
|
||||
uri: serviceUrl,
|
||||
headers: {
|
||||
'x-hasura-admin-secret':
|
||||
process.env.NEXT_PUBLIC_ENV === 'dev'
|
||||
? getHasuraAdminSecret()
|
||||
: currentProject?.config?.hasura.adminSecret,
|
||||
},
|
||||
}),
|
||||
});
|
||||
const { adminClient } = useAdminApolloClient();
|
||||
|
||||
const [deleteAssistantMutation] = useDeleteAssistantMutation({
|
||||
client,
|
||||
client: adminClient,
|
||||
});
|
||||
|
||||
const deleteAssistant = async () => {
|
||||
@@ -70,27 +42,12 @@ export default function DeleteAssistantModal({
|
||||
async function handleClick() {
|
||||
setLoadingRemove(true);
|
||||
|
||||
await toast.promise(
|
||||
deleteAssistant(),
|
||||
{
|
||||
loading: 'Deleting the assistant...',
|
||||
success: `The Assistant has been deleted successfully.`,
|
||||
error: (arg: ApolloError) => {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } = (internal as Record<string, any>)?.error || {};
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
'An error occurred while deleting the Assistant. Please try again.'
|
||||
);
|
||||
},
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
await execPromiseWithErrorToast(deleteAssistant, {
|
||||
loadingMessage: 'Deleting the assistant...',
|
||||
successMessage: 'The Assistant has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while deleting the Assistant. Please try again.',
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -4,18 +4,12 @@ import { Checkbox } from '@/components/ui/v2/Checkbox';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getHasuraAdminSecret } from '@/utils/env';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { useDeleteGraphiteAutoEmbeddingsConfigurationMutation } from '@/utils/__generated__/graphite.graphql';
|
||||
import {
|
||||
ApolloClient,
|
||||
HttpLink,
|
||||
InMemoryCache,
|
||||
type ApolloError,
|
||||
} from '@apollo/client';
|
||||
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client';
|
||||
import { type AutoEmbeddingsConfiguration } from 'pages/[workspaceSlug]/[appSlug]/ai/auto-embeddings';
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export interface DeleteAutoEmbeddingsModalProps {
|
||||
@@ -71,27 +65,13 @@ export default function DeleteAutoEmbeddingsModal({
|
||||
async function handleClick() {
|
||||
setLoadingRemove(true);
|
||||
|
||||
await toast.promise(
|
||||
deleteAutoEmbeddingsConfig(),
|
||||
{
|
||||
loading: 'Deleting Auto-Embeddings Configuration...',
|
||||
success: `The Auto-Embeddings Configuration has been deleted successfully.`,
|
||||
error: (arg: ApolloError) => {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } = (internal as Record<string, any>)?.error || {};
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
'An error occurred while deleting the Auto-Embeddings Configuration. Please try again.'
|
||||
);
|
||||
},
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
await execPromiseWithErrorToast(deleteAutoEmbeddingsConfig, {
|
||||
loadingMessage: 'Deleting Auto-Embeddings Configuration...',
|
||||
successMessage:
|
||||
'The Auto-Embeddings Configuration has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while deleting the Auto-Embeddings Configuration. Please try again.',
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,7 @@ import { UpgradeToProBanner } from '@/components/common/UpgradeToProBanner';
|
||||
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
|
||||
import { Alert } from '@/components/ui/v2/Alert';
|
||||
import { Box } from '@/components/ui/v2/Box';
|
||||
import { ErrorToast } from '@/components/ui/v2/ErrorToast';
|
||||
import { IconButton } from '@/components/ui/v2/IconButton';
|
||||
import { ArrowUpIcon } from '@/components/ui/v2/icons/ArrowUpIcon';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
@@ -17,7 +18,6 @@ import { useAdminApolloClient } from '@/features/projects/common/hooks/useAdminA
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useIsGraphiteEnabled } from '@/features/projects/common/hooks/useIsGraphiteEnabled';
|
||||
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import {
|
||||
useSendDevMessageMutation,
|
||||
useStartDevSessionMutation,
|
||||
@@ -122,11 +122,17 @@ export default function DevAssistant() {
|
||||
|
||||
setMessages(thread);
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
'Failed to send the message to graphite. Please try again later.',
|
||||
toast.custom(
|
||||
(t) => (
|
||||
<ErrorToast
|
||||
isVisible={t.visible}
|
||||
errorMessage="Failed to send the message. Please try again later."
|
||||
error={error}
|
||||
close={() => toast.dismiss()}
|
||||
/>
|
||||
),
|
||||
{
|
||||
style: getToastStyleProps().style,
|
||||
...getToastStyleProps().error,
|
||||
duration: Number.POSITIVE_INFINITY,
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
|
||||
@@ -24,7 +24,7 @@ function PreComponent(
|
||||
const { children } = props;
|
||||
|
||||
return (
|
||||
<div className="group relative">
|
||||
<div className="relative group">
|
||||
<pre>{children}</pre>
|
||||
<IconButton
|
||||
sx={{
|
||||
@@ -34,13 +34,13 @@ function PreComponent(
|
||||
}}
|
||||
color="warning"
|
||||
variant="contained"
|
||||
className="absolute top-2 right-2 hidden group-hover:flex"
|
||||
className="absolute hidden top-2 right-2 group-hover:flex"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copy(onlyText(children), 'Snippet');
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="h-5 w-5" />
|
||||
<CopyIcon className="w-5 h-5" />
|
||||
</IconButton>
|
||||
</div>
|
||||
);
|
||||
@@ -53,7 +53,7 @@ export default function MessageBox({ message }: { message: Message }) {
|
||||
|
||||
return (
|
||||
<Box
|
||||
className="flex flex-col space-y-4 border-t p-4 first:border-t-0"
|
||||
className="flex flex-col p-4 space-y-4 border-t first:border-t-0"
|
||||
sx={{
|
||||
backgroundColor: isUserMessage && 'background.default',
|
||||
}}
|
||||
@@ -67,7 +67,7 @@ export default function MessageBox({ message }: { message: Message }) {
|
||||
) : (
|
||||
<>
|
||||
<Avatar
|
||||
className="h-7 w-7 rounded-full"
|
||||
className="rounded-full h-7 w-7"
|
||||
alt={user?.displayName}
|
||||
src={user?.avatarUrl}
|
||||
>
|
||||
|
||||
@@ -21,12 +21,10 @@ import {
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { RESOURCE_VCPU_MULTIPLIER } from '@/utils/constants/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
import { DisableAIServiceConfirmationDialog } from './DisableAIServiceConfirmationDialog';
|
||||
|
||||
@@ -182,9 +180,9 @@ export default function AISettings() {
|
||||
}
|
||||
|
||||
async function handleSubmit(formValues: AISettingsFormValues) {
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfig({
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
@@ -207,21 +205,17 @@ export default function AISettings() {
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: `AI settings are being updated...`,
|
||||
success: `AI settings has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the AI settings!`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
});
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'AI settings are being updated...',
|
||||
successMessage: 'AI settings has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the AI settings!',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const getAIResourcesCost = () => {
|
||||
|
||||
@@ -3,11 +3,9 @@ import { Box } from '@/components/ui/v2/Box';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { useUpdateConfigMutation } from '@/utils/__generated__/graphql';
|
||||
import type { ApolloError } from '@apollo/client';
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export interface DisableAIServiceConfirmationDialogProps {
|
||||
@@ -34,37 +32,26 @@ export default function DisableAIServiceConfirmationDialog({
|
||||
async function handleClick() {
|
||||
setLoading(true);
|
||||
|
||||
await toast.promise(
|
||||
updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
ai: null,
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
ai: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Disabling the AI service...',
|
||||
success: () => {
|
||||
onServiceDisabled();
|
||||
closeDialog();
|
||||
return `The service has been disabled.`;
|
||||
},
|
||||
error: (arg: ApolloError) => {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } = (internal as Record<string, any>)?.error || {};
|
||||
});
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
'An error occurred while disabling the AI service. Please try again later.'
|
||||
);
|
||||
},
|
||||
onServiceDisabled();
|
||||
closeDialog();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Disabling the AI service...',
|
||||
successMessage: 'The service has been disabled.',
|
||||
errorMessage:
|
||||
'An error occurred while disabling the AI service. Please try again later.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetAuthenticationSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -103,21 +101,19 @@ export default function AllowedEmailDomainsSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Allowed email settings are being updated...`,
|
||||
success: `Allowed email settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's allowed email settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
} catch {
|
||||
// Note: The toast will handle the error
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Allowed email settings are being updated...',
|
||||
successMessage:
|
||||
'Allowed email settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's allowed email settings.",
|
||||
},
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
};
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetAuthenticationSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -80,23 +78,19 @@ export default function AllowedRedirectURLsSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Allowed redirect URL settings are being updated...`,
|
||||
success: `Allowed redirect URL settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's allowed redirect URL settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Allowed redirect URL settings are being updated...',
|
||||
successMessage:
|
||||
'Allowed redirect URL settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's allowed redirect URL settings.",
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -8,11 +8,9 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -73,23 +71,19 @@ export default function AnonymousSignInSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Anonymous sign-in settings are being updated...`,
|
||||
success: `Anonymous sign-in settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update Anonymous sign-in settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Anonymous sign-in settings are being updated...',
|
||||
successMessage:
|
||||
'Anonymous sign-in settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update Anonymous sign-in settings.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -13,13 +13,11 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useTheme } from '@mui/material';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -117,23 +115,18 @@ export default function AppleProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Apple settings are being updated...`,
|
||||
success: `Apple settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Apple settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Apple settings are being updated...',
|
||||
successMessage: 'Apple settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Apple settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -158,7 +151,7 @@ export default function AppleProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -11,11 +11,9 @@ import {
|
||||
useGetSoftwareVersionsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -95,23 +93,17 @@ export default function AuthServiceVersionSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Auth version is being updated...`,
|
||||
success: `Auth version has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update Auth version.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Auth version is being updated...',
|
||||
successMessage: 'Auth version has been updated successfully.',
|
||||
errorMessage: 'An error occurred while trying to update Auth version.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -128,7 +120,7 @@ export default function AuthServiceVersionSettings() {
|
||||
}}
|
||||
docsLink="https://github.com/nhost/hasura-auth/releases"
|
||||
docsTitle="the latest releases"
|
||||
className="grid grid-flow-row gap-y-2 gap-x-4 px-4 lg:grid-cols-5"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-2 px-4 lg:grid-cols-5"
|
||||
>
|
||||
<ControlledAutocomplete
|
||||
id="version"
|
||||
|
||||
@@ -14,12 +14,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -106,23 +104,18 @@ export default function AzureADProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Azure AD settings are being updated...`,
|
||||
success: `Azure AD settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Azure AD settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Azure AD settings are being updated...',
|
||||
successMessage: 'Azure AD settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Azure AD settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -141,7 +134,7 @@ export default function AzureADProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid grid-flow-row grid-cols-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid grid-flow-row grid-cols-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function BitbucketProviderSettings() {
|
||||
@@ -84,23 +82,18 @@ export default function BitbucketProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Bitbucket settings are being updated...`,
|
||||
success: `Bitbucket settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Bitbucket settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Bitbucket settings are being updated...',
|
||||
successMessage: 'Bitbucket settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Bitbucket settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -119,7 +112,7 @@ export default function BitbucketProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetAuthenticationSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -110,23 +108,20 @@ export default function BlockedEmailSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Blocked email and domain settings are being updated...`,
|
||||
success: `Blocked email and domain settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's blocked email and domain settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage:
|
||||
'Blocked email and domain settings are being updated...',
|
||||
successMessage:
|
||||
'Blocked email and domain settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's blocked email and domain settings.",
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetAuthenticationSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -75,23 +73,18 @@ export default function ClientURLSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Client URL is being updated...`,
|
||||
success: `Client URL has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Client URL.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Client URL is being updated...',
|
||||
successMessage: 'Client URL has been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Client URL.",
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -3,15 +3,13 @@ import { Form } from '@/components/form/Form';
|
||||
import { SettingsContainer } from '@/components/layout/SettingsContainer';
|
||||
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetAuthenticationSettingsDocument,
|
||||
useGetAuthenticationSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -71,23 +69,18 @@ export default function DisableNewUsersSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Disabling new user sign ups...`,
|
||||
success: `New user sign ups have been disabled successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to disable new user sign ups.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Disabling new user sign ups...',
|
||||
successMessage: 'New user sign ups have been disabled successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to disable new user sign ups.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function DiscordProviderSettings() {
|
||||
@@ -87,23 +85,18 @@ export default function DiscordProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Discord settings are being updated...`,
|
||||
success: `Discord settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Discrod settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Discord settings are being updated...',
|
||||
successMessage: 'Discord settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Discrod settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -124,7 +117,7 @@ export default function DiscordProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -11,11 +11,9 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -85,23 +83,19 @@ export default function EmailAndPasswordSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Email and password sign-in settings are being updated...`,
|
||||
success: `Email and password sign-in settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update email sign-in settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: `Email and password sign-in settings are being updated...`,
|
||||
successMessage:
|
||||
'Email and password sign-in settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update email sign-in settings.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function FacebookProviderSettings() {
|
||||
@@ -87,23 +85,18 @@ export default function FacebookProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Facebook settings are being updated...`,
|
||||
success: `Facebook settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Facebook settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Facebook settings are being updated...',
|
||||
successMessage: 'Facebook settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Facebook settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -124,7 +117,7 @@ export default function FacebookProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -18,13 +18,11 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useTheme } from '@mui/material';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function GitHubProviderSettings() {
|
||||
@@ -89,23 +87,18 @@ export default function GitHubProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `GitHub settings are being updated...`,
|
||||
success: `GitHub settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's GitHub settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'GitHub settings are being updated...',
|
||||
successMessage: 'GitHub settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's GitHub settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -130,7 +123,7 @@ export default function GitHubProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function GitLabProviderSettings() {
|
||||
@@ -87,23 +85,18 @@ export default function GitLabProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `GitLab settings are being updated...`,
|
||||
success: `GitLab settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's GitLab settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'GitLab settings are being updated...',
|
||||
successMessage: 'GitLab settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's GitLab settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -122,7 +115,7 @@ export default function GitLabProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function GoogleProviderSettings() {
|
||||
@@ -87,23 +85,18 @@ export default function GoogleProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Google settings are being updated...`,
|
||||
success: `Google settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Google settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Google settings are being updated...',
|
||||
successMessage: 'Google settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Google settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -124,7 +117,7 @@ export default function GoogleProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -13,12 +13,10 @@ import {
|
||||
import {
|
||||
AUTH_GRAVATAR_DEFAULT,
|
||||
AUTH_GRAVATAR_RATING,
|
||||
getToastStyleProps,
|
||||
} from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -89,23 +87,18 @@ export default function GravatarSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Gravatar settings are being updated...`,
|
||||
success: `Gravatar settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Gravatar settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Gravatar settings are being updated...',
|
||||
successMessage: 'Gravatar settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Gravatar settings.",
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function LinkedInProviderSettings() {
|
||||
@@ -87,23 +85,18 @@ export default function LinkedInProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `LinkedIn settings are being updated...`,
|
||||
success: `LinkedIn settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's LinkedIn settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'LinkedIn settings are being updated...',
|
||||
successMessage: 'LinkedIn settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's LinkedIn settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -124,7 +117,7 @@ export default function LinkedInProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetAuthenticationSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -76,23 +74,20 @@ export default function MFASettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Multi-factor authentication settings are being updated...`,
|
||||
success: `Multi-factor authentication settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's multi-factor authentication settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage:
|
||||
'Multi-factor authentication settings are being updated...',
|
||||
successMessage:
|
||||
'Multi-factor authentication settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's multi-factor authentication settings.",
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -8,11 +8,9 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -73,23 +71,18 @@ export default function MagicLinkSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Magic Link settings are being updated...`,
|
||||
success: `Magic Link settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Magic Link settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Magic Link settings are being updated...',
|
||||
successMessage: 'Magic Link settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Magic Link settings.",
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -12,12 +12,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import Image from 'next/image';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -112,23 +110,17 @@ export default function SMSSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `SMS settings are being updated...`,
|
||||
success: `SMS settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update SMS settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'SMS settings are being updated...',
|
||||
successMessage: 'SMS settings have been updated successfully.',
|
||||
errorMessage: 'An error occurred while trying to update SMS settings.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -148,7 +140,7 @@ export default function SMSSettings() {
|
||||
docsLink="https://docs.nhost.io/authentication/sign-in-with-phone-number-sms"
|
||||
docsTitle="how to sign in users with a phone number (SMS)"
|
||||
className={twMerge(
|
||||
'grid grid-flow-col grid-cols-2 grid-rows-4 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid grid-flow-col grid-cols-2 grid-rows-4 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authSmsPasswordlessEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetAuthenticationSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -84,23 +82,18 @@ export default function SessionSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Session settings are being updated...`,
|
||||
success: `Session settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's session settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Session settings are being updated...',
|
||||
successMessage: 'Session settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's session settings.",
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function SpotifyProviderSettings() {
|
||||
@@ -87,23 +85,18 @@ export default function SpotifyProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Spotify settings are being updated...`,
|
||||
success: `Spotify settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Spotify settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Spotify settings are being updated...',
|
||||
successMessage: 'Spotify settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Spotify settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -124,7 +117,7 @@ export default function SpotifyProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function StravaProviderSettings() {
|
||||
@@ -87,23 +85,18 @@ export default function StravaProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Strava settings are being updated...`,
|
||||
success: `Strava settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Strava settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Strava settings are being updated...',
|
||||
successMessage: 'Strava settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Strava settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -122,7 +115,7 @@ export default function StravaProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -18,13 +18,11 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useTheme } from '@mui/material';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function TwitchProviderSettings() {
|
||||
@@ -89,23 +87,18 @@ export default function TwitchProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Twitch settings are being updated...`,
|
||||
success: `Twitch settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Twitch settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Twitch settings are being updated...',
|
||||
successMessage: 'Twitch settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's Twitch settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -130,7 +123,7 @@ export default function TwitchProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -13,12 +13,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -98,23 +96,17 @@ export default function TwitterProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Twitter settings are being updated...`,
|
||||
success: `Twitter settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Twitter settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Twitter settings are being updated...',
|
||||
successMessage: 'Twitter settings have been updated successfully.',
|
||||
errorMessage: `An error occurred while trying to update the project's Twitter settings.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -134,7 +126,7 @@ export default function TwitterProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -8,11 +8,9 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -66,33 +64,29 @@ export default function WebAuthnSettings() {
|
||||
config: {
|
||||
auth: {
|
||||
method: {
|
||||
webauthn: {...values,
|
||||
relyingParty: {
|
||||
name: currentProject.name,
|
||||
}},
|
||||
webauthn: {
|
||||
...values,
|
||||
relyingParty: {
|
||||
name: currentProject.name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `WebAuthn settings are being updated...`,
|
||||
success: `WebAuthn settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's WebAuthn settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'WebAuthn settings are being updated...',
|
||||
successMessage: 'WebAuthn settings have been updated successfully.',
|
||||
errorMessage: `An error occurred while trying to update the project's WebAuthn settings.`,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function WindowsLiveProviderSettings() {
|
||||
@@ -87,23 +85,17 @@ export default function WindowsLiveProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Windows Live settings are being updated...`,
|
||||
success: `Windows Live settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's Windows Live settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Windows Live settings are being updated...',
|
||||
successMessage: 'Windows Live settings have been updated successfully.',
|
||||
errorMessage: `An error occurred while trying to update the project's Windows Live settings.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -123,7 +115,7 @@ export default function WindowsLiveProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid-flow-rows grid grid-cols-2 grid-rows-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -14,12 +14,10 @@ import {
|
||||
useGetSignInMethodsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -113,23 +111,18 @@ export default function WorkOsProviderSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `WorkOS settings are being updated...`,
|
||||
success: `WorkOS settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's WorkOS settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'WorkOS settings are being updated...',
|
||||
successMessage: 'WorkOS settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's WorkOS settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -150,7 +143,7 @@ export default function WorkOsProviderSettings() {
|
||||
switchId="enabled"
|
||||
showSwitch
|
||||
className={twMerge(
|
||||
'grid grid-flow-row grid-cols-2 gap-y-4 gap-x-3 px-4 py-2',
|
||||
'grid grid-flow-row grid-cols-2 gap-x-3 gap-y-4 px-4 py-2',
|
||||
!authEnabled && 'hidden',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -6,12 +6,10 @@ import { Input } from '@/components/ui/v2/Input';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export interface CreateUserFormProps extends DialogFormProps {
|
||||
@@ -77,9 +75,9 @@ export default function CreateUserForm({
|
||||
async function handleCreateUser({ email, password }: CreateUserFormValues) {
|
||||
setCreateUserFormError(null);
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
fetch(signUpUrl, {
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await fetch(signUpUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, password }),
|
||||
@@ -95,21 +93,16 @@ export default function CreateUserForm({
|
||||
}
|
||||
|
||||
throw new Error(data?.message || 'Something went wrong.');
|
||||
}),
|
||||
{
|
||||
loading: 'Creating user...',
|
||||
success: 'User has been created successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while trying to create the user.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
});
|
||||
|
||||
onSubmit?.();
|
||||
} catch (error) {
|
||||
// Note: The error is already handled by the toast promise.
|
||||
}
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Creating user...',
|
||||
successMessage: 'User has been created successfully.',
|
||||
errorMessage: 'An error occurred while trying to create the user.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -19,9 +19,8 @@ import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/
|
||||
import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRoles';
|
||||
import { useRemoteApplicationGQLClient } from '@/hooks/useRemoteApplicationGQLClient';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
RemoteAppGetUsersDocument,
|
||||
useGetProjectLocalesQuery,
|
||||
@@ -36,7 +35,6 @@ import Image from 'next/image';
|
||||
import type { RemoteAppUser } from 'pages/[workspaceSlug]/[appSlug]/users';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export interface EditUserFormProps extends DialogFormProps {
|
||||
@@ -173,21 +171,15 @@ export default function EditUserForm({
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
banUser,
|
||||
{
|
||||
loading: shouldBan ? 'Banning user...' : 'Unbanning user...',
|
||||
success: shouldBan
|
||||
? 'User has been banned successfully.'
|
||||
: 'User has been unbanned successfully.',
|
||||
error: getServerError(
|
||||
shouldBan
|
||||
? 'An error occurred while trying to ban the user.'
|
||||
: 'An error occurred while trying to unban the user.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
await execPromiseWithErrorToast(() => banUser, {
|
||||
loadingMessage: shouldBan ? 'Banning user...' : 'Unbanning user...',
|
||||
successMessage: shouldBan
|
||||
? 'User has been banned successfully.'
|
||||
: 'User has been unbanned successfully.',
|
||||
errorMessage: shouldBan
|
||||
? 'An error occurred while trying to ban the user.'
|
||||
: 'An error occurred while trying to unban the user.',
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -196,14 +188,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 overflow-y-auto divide-y">
|
||||
<Box className="flex-auto divide-y overflow-y-auto">
|
||||
<Box
|
||||
component="section"
|
||||
className="grid grid-flow-col p-6 lg:grid-cols-7"
|
||||
>
|
||||
<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">
|
||||
<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">
|
||||
<Text className="text-lg font-medium">{user.displayName}</Text>
|
||||
<Text className="text-sm+ font-normal" color="secondary">
|
||||
{user.email}
|
||||
@@ -225,7 +217,7 @@ export default function EditUserForm({
|
||||
Actions
|
||||
</Button>
|
||||
</Dropdown.Trigger>
|
||||
<Dropdown.Content menu className="w-full h-full">
|
||||
<Dropdown.Content menu className="h-full w-full">
|
||||
<Dropdown.Item
|
||||
className="font-medium"
|
||||
sx={{ color: 'error.main' }}
|
||||
@@ -253,11 +245,11 @@ export default function EditUserForm({
|
||||
component="section"
|
||||
className="grid grid-flow-row grid-cols-4 gap-8 p-6"
|
||||
>
|
||||
<InputLabel as="h3" className="self-center col-span-1">
|
||||
<InputLabel as="h3" className="col-span-1 self-center">
|
||||
User ID
|
||||
</InputLabel>
|
||||
<div className="grid items-center justify-start grid-flow-col col-span-3 gap-2">
|
||||
<Text className="font-medium truncate">{user.id}</Text>
|
||||
<div className="col-span-3 grid grid-flow-col items-center justify-start gap-2">
|
||||
<Text className="truncate font-medium">{user.id}</Text>
|
||||
<IconButton
|
||||
variant="borderless"
|
||||
color="secondary"
|
||||
@@ -267,18 +259,18 @@ export default function EditUserForm({
|
||||
copy(user.id, 'User ID');
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="w-4 h-4" />
|
||||
<CopyIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
|
||||
<InputLabel as="h3" className="self-center col-span-1 ">
|
||||
<InputLabel as="h3" className="col-span-1 self-center ">
|
||||
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="self-center col-span-1 ">
|
||||
<InputLabel as="h3" className="col-span-1 self-center ">
|
||||
Last Seen
|
||||
</InputLabel>
|
||||
<Text className="col-span-3 font-medium">
|
||||
@@ -336,14 +328,14 @@ export default function EditUserForm({
|
||||
autoComplete="off"
|
||||
/>
|
||||
|
||||
<div className="grid items-center grid-flow-col grid-cols-8 col-span-1 my-1">
|
||||
<div className="col-span-1 my-1 grid grid-flow-col grid-cols-8 items-center">
|
||||
<div className="col-span-2 ">
|
||||
<InputLabel as="h3">Password</InputLabel>
|
||||
</div>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="borderless"
|
||||
className="col-span-6 px-2 place-self-start"
|
||||
className="col-span-6 place-self-start px-2"
|
||||
onClick={handleChangeUserPassword}
|
||||
>
|
||||
Change
|
||||
@@ -392,12 +384,12 @@ export default function EditUserForm({
|
||||
</Box>
|
||||
<Box
|
||||
component="section"
|
||||
className="grid gap-4 p-6 place-content-start lg:grid-cols-4"
|
||||
className="grid place-content-start gap-4 p-6 lg:grid-cols-4"
|
||||
>
|
||||
<div className="items-center self-center col-span-1 align-middle">
|
||||
<div className="col-span-1 items-center self-center align-middle">
|
||||
<InputLabel as="h3">OAuth Providers</InputLabel>
|
||||
</div>
|
||||
<div className="grid w-full grid-flow-row col-span-3 gap-y-6">
|
||||
<div className="col-span-3 grid w-full grid-flow-row 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 +400,10 @@ export default function EditUserForm({
|
||||
|
||||
{user.userProviders.map((provider) => (
|
||||
<div
|
||||
className="grid grid-flow-col gap-3 place-content-between"
|
||||
className="grid grid-flow-col place-content-between gap-3"
|
||||
key={provider.id}
|
||||
>
|
||||
<div className="grid grid-flow-col gap-2 span-cols-1">
|
||||
<div className="span-cols-1 grid grid-flow-col gap-2">
|
||||
<Image
|
||||
src={
|
||||
theme.palette.mode === 'dark'
|
||||
@@ -424,7 +416,7 @@ export default function EditUserForm({
|
||||
}
|
||||
width={25}
|
||||
height={25}
|
||||
alt='Oauth provider logo'
|
||||
alt="Oauth provider logo"
|
||||
/>
|
||||
<Text className="font-medium capitalize">
|
||||
{getReadableProviderName(provider.providerId)}
|
||||
@@ -437,7 +429,7 @@ export default function EditUserForm({
|
||||
{!isAnonymous && (
|
||||
<Box
|
||||
component="section"
|
||||
className="grid grid-flow-row p-6 gap-y-10"
|
||||
className="grid grid-flow-row gap-y-10 p-6"
|
||||
>
|
||||
<ControlledSelect
|
||||
{...register('defaultRole')}
|
||||
@@ -457,11 +449,11 @@ export default function EditUserForm({
|
||||
</Option>
|
||||
))}
|
||||
</ControlledSelect>
|
||||
<div className="grid grid-flow-row gap-6 place-content-start lg:grid-flow-col lg:grid-cols-8">
|
||||
<div className="grid grid-flow-row place-content-start gap-6 lg:grid-flow-col lg:grid-cols-8">
|
||||
<InputLabel as="h3" className="col-span-2">
|
||||
Allowed Roles
|
||||
</InputLabel>
|
||||
<div className="grid grid-flow-row col-span-3 gap-6">
|
||||
<div className="col-span-3 grid grid-flow-row gap-6">
|
||||
{roles.map((role, i) => (
|
||||
<ControlledCheckbox
|
||||
id={`roles.${i}`}
|
||||
@@ -477,7 +469,7 @@ export default function EditUserForm({
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<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">
|
||||
<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">
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
|
||||
@@ -6,8 +6,7 @@ import { Input } from '@/components/ui/v2/Input';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useRemoteApplicationGQLClient } from '@/hooks/useRemoteApplicationGQLClient';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import type { RemoteAppGetUsersQuery } from '@/utils/__generated__/graphql';
|
||||
import {
|
||||
useGetSignInMethodsQuery,
|
||||
@@ -17,7 +16,6 @@ import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import { useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export interface EditUserPasswordFormProps extends DialogFormProps {
|
||||
@@ -90,23 +88,23 @@ export default function EditUserPasswordForm({
|
||||
client: remoteProjectGQLClient,
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateUserPasswordPromise,
|
||||
{
|
||||
loading: 'Updating user password...',
|
||||
success: 'User password updated successfully.',
|
||||
error: getServerError('Failed to update user password.'),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateUserPasswordPromise;
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating user password...',
|
||||
successMessage: 'User password updated successfully.',
|
||||
errorMessage: 'Failed to update user password.',
|
||||
onError: (error) => {
|
||||
setEditUserPasswordFormError(
|
||||
new Error(error.message || 'Something went wrong.'),
|
||||
);
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
} catch (error) {
|
||||
setEditUserPasswordFormError(
|
||||
new Error(error.message || 'Something went wrong.'),
|
||||
);
|
||||
} finally {
|
||||
closeDialog();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
const {
|
||||
|
||||
@@ -17,8 +17,7 @@ import { getReadableProviderName } from '@/features/authentication/users/utils/g
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRoles';
|
||||
import { useRemoteApplicationGQLClient } from '@/hooks/useRemoteApplicationGQLClient';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
useDeleteRemoteAppUserRolesMutation,
|
||||
useGetRolesPermissionsQuery,
|
||||
@@ -33,7 +32,6 @@ import dynamic from 'next/dynamic';
|
||||
import Image from 'next/image';
|
||||
import type { RemoteAppUser } from 'pages/[workspaceSlug]/[appSlug]/users';
|
||||
import { Fragment, useMemo } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
const EditUserForm = dynamic(
|
||||
() =>
|
||||
@@ -153,20 +151,18 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
});
|
||||
}
|
||||
|
||||
await toast.promise(
|
||||
updateUserMutationPromise,
|
||||
{
|
||||
loading: `Updating user's settings...`,
|
||||
success: 'User settings have been updated successfully.',
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update this user's settings.`,
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateUserMutationPromise;
|
||||
},
|
||||
{
|
||||
loadingMessage: `Updating user's settings...`,
|
||||
successMessage: 'User settings have been updated successfully.',
|
||||
errorMessage: `An error occurred while trying to update this user's settings.`,
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
await onSubmit?.();
|
||||
|
||||
closeDrawer();
|
||||
}
|
||||
|
||||
@@ -181,20 +177,20 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
),
|
||||
props: {
|
||||
onPrimaryAction: async () => {
|
||||
await toast.promise(
|
||||
deleteUser({
|
||||
variables: {
|
||||
id: user.id,
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Deleting user...',
|
||||
success: 'User deleted successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while trying to delete this user.',
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await deleteUser({
|
||||
variables: {
|
||||
id: user.id,
|
||||
},
|
||||
});
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Deleting user...',
|
||||
successMessage: 'User deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to delete this user.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
await onSubmit();
|
||||
@@ -226,12 +222,12 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
|
||||
if (!users) {
|
||||
return (
|
||||
<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">
|
||||
<div className="h-screen w-screen overflow-hidden">
|
||||
<div className="absolute left-0 top-0 z-50 block h-full w-full">
|
||||
<span className="top50percent relative top-1/2 mx-auto my-0 block">
|
||||
<ActivityIndicator
|
||||
label="Loading users..."
|
||||
className="flex items-center justify-center my-auto"
|
||||
className="my-auto flex items-center justify-center"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
@@ -269,7 +265,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="w-4 h-4" />
|
||||
<UserIcon className="h-4 w-4" />
|
||||
<Text className="font-medium">View User</Text>
|
||||
</Dropdown.Item>
|
||||
|
||||
@@ -280,7 +276,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
sx={{ color: 'error.main' }}
|
||||
onClick={() => handleDeleteUser(user)}
|
||||
>
|
||||
<TrashIcon className="w-4 h-4" />
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
<Text className="font-medium" color="error">
|
||||
Delete User
|
||||
</Text>
|
||||
@@ -294,14 +290,14 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
onClick={() => handleViewUser(user)}
|
||||
aria-label={`View ${user.displayName}`}
|
||||
>
|
||||
<div className="grid grid-flow-col col-span-2 gap-4 place-content-start">
|
||||
<div className="col-span-2 grid grid-flow-col place-content-start gap-4">
|
||||
<Avatar
|
||||
src={user.avatarUrl}
|
||||
alt={`Avatar of ${user.displayName}`}
|
||||
/>
|
||||
<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">
|
||||
<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">
|
||||
{user.displayName}
|
||||
</Text>
|
||||
{user.disabled && (
|
||||
@@ -314,7 +310,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Text className="font-normal truncate" color="secondary">
|
||||
<Text className="truncate font-normal" color="secondary">
|
||||
{user.email}
|
||||
</Text>
|
||||
</div>
|
||||
@@ -334,7 +330,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
: '-'}
|
||||
</Text>
|
||||
|
||||
<div className="hidden grid-flow-col col-span-2 gap-3 px-4 place-content-start lg:grid">
|
||||
<div className="col-span-2 hidden grid-flow-col place-content-start gap-3 px-4 lg:grid">
|
||||
{user.userProviders.length === 0 && (
|
||||
<Text className="col-span-3 font-medium">-</Text>
|
||||
)}
|
||||
@@ -362,7 +358,7 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
}
|
||||
width={16}
|
||||
height={16}
|
||||
alt='Oauth provider logo'
|
||||
alt="Oauth provider logo"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -331,7 +331,7 @@ export default function EditPermissionsForm({
|
||||
<NavLink
|
||||
href={`/${currentWorkspace.slug}/${currentProject.slug}/settings/roles-and-permissions`}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<Link
|
||||
href="settings/roles-and-permissions"
|
||||
underline="hover"
|
||||
|
||||
@@ -14,13 +14,11 @@ import type {
|
||||
import { convertToHasuraPermissions } from '@/features/database/dataGrid/utils/convertToHasuraPermissions';
|
||||
import { convertToRuleGroup } from '@/features/database/dataGrid/utils/convertToRuleGroup';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useEffect } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import AggregationQuerySection from './sections/AggregationQuerySection';
|
||||
import BackendOnlySection from './sections/BackendOnlySection';
|
||||
import ColumnPermissionsSection from './sections/ColumnPermissionsSection';
|
||||
@@ -254,18 +252,18 @@ export default function RolePermissionEditorForm({
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
managePermissionPromise,
|
||||
{
|
||||
loading: 'Saving permission...',
|
||||
success: 'Permission has been saved successfully.',
|
||||
error: getServerError('An error occurred while saving the permission.'),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await managePermissionPromise;
|
||||
onDirtyStateChange(false, location);
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Saving permission...',
|
||||
successMessage: 'Permission has been saved successfully.',
|
||||
errorMessage: 'An error occurred while saving the permission.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onDirtyStateChange(false, location);
|
||||
onSubmit?.();
|
||||
}
|
||||
|
||||
function handleCancelClick() {
|
||||
@@ -293,20 +291,18 @@ export default function RolePermissionEditorForm({
|
||||
mode: 'delete',
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
deletePermissionPromise,
|
||||
{
|
||||
loading: 'Deleting permission...',
|
||||
success: 'Permission has been deleted successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while deleting the permission.',
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await deletePermissionPromise;
|
||||
onDirtyStateChange(false, location);
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Deleting permission...',
|
||||
successMessage: 'Permission has been deleted successfully.',
|
||||
errorMessage: 'An error occurred while deleting the permission.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onDirtyStateChange(false, location);
|
||||
onSubmit?.();
|
||||
}
|
||||
|
||||
function handleDeleteClick() {
|
||||
|
||||
@@ -114,7 +114,7 @@ export function createDynamicValidationSchema(
|
||||
['time', 'timetz', 'interval'].includes(column.specificType)
|
||||
) {
|
||||
return {
|
||||
...schema,
|
||||
...currentSchema,
|
||||
[column.id]: createTextValidationSchema(details).matches(
|
||||
/^\d{2}:\d{2}(:\d{2})?$/,
|
||||
'This is not a valid time (e.g: HH:MM:SS / HH:MM).',
|
||||
@@ -124,14 +124,14 @@ export function createDynamicValidationSchema(
|
||||
|
||||
if (column.type === 'date') {
|
||||
return {
|
||||
...schema,
|
||||
...currentSchema,
|
||||
[column.id]: createDateValidationSchema(details),
|
||||
};
|
||||
}
|
||||
|
||||
if (column.type === 'boolean') {
|
||||
return {
|
||||
...schema,
|
||||
...currentSchema,
|
||||
[column.id]: createBooleanValidationSchema(details),
|
||||
};
|
||||
}
|
||||
@@ -141,13 +141,13 @@ export function createDynamicValidationSchema(
|
||||
(column.specificType === 'jsonb' || column.specificType === 'json')
|
||||
) {
|
||||
return {
|
||||
...schema,
|
||||
...currentSchema,
|
||||
[column.id]: createJSONValidationSchema(details),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...schema,
|
||||
...currentSchema,
|
||||
[column.id]: createTextValidationSchema(details),
|
||||
};
|
||||
}, {});
|
||||
|
||||
@@ -11,11 +11,9 @@ import {
|
||||
useGetSoftwareVersionsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -97,23 +95,18 @@ export default function DatabaseServiceVersionSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Postgres version is being updated...`,
|
||||
success: `Postgres version has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update Postgres version.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Postgres version is being updated...',
|
||||
successMessage: 'Postgres version has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update Postgres version.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -130,7 +123,7 @@ export default function DatabaseServiceVersionSettings() {
|
||||
}}
|
||||
docsLink="https://hub.docker.com/r/nhost/postgres/tags"
|
||||
docsTitle="the latest releases"
|
||||
className="grid grid-flow-row gap-y-2 gap-x-4 px-4 lg:grid-cols-5"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-2 px-4 lg:grid-cols-5"
|
||||
>
|
||||
<ControlledAutocomplete
|
||||
id="version"
|
||||
|
||||
@@ -11,12 +11,10 @@ import {
|
||||
useGetPostgresSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -75,9 +73,9 @@ export default function AuthDomain() {
|
||||
}
|
||||
|
||||
async function handleSubmit(formValues: AuthDomainFormValues) {
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfig({
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
@@ -90,22 +88,19 @@ export default function AuthDomain() {
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: `Database storage capacity is being updated...`,
|
||||
success: `Database storage capacity has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the database storage capacity.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
});
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchPostgresSettings();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
form.reset(formValues);
|
||||
await refetchPostgresSettings();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Database storage capacity is being updated...',
|
||||
successMessage:
|
||||
'Database storage capacity has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the database storage capacity.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -8,11 +8,9 @@ import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -72,24 +70,19 @@ export default function HasuraAllowListSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Allow list settings are being updated...`,
|
||||
success: `Allow list settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update allow list settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Allow list settings are being updated...',
|
||||
successMessage: 'Allow list settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update allow list settings.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -8,11 +8,9 @@ import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -72,24 +70,20 @@ export default function HasuraConsoleSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Hasura Console settings are being updated...`,
|
||||
success: `Hasura Console settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update Hasura Console settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Hasura Console settings are being updated...',
|
||||
successMessage:
|
||||
'Hasura Console settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update Hasura Console settings.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -95,24 +93,18 @@ export default function HasuraCorsDomainSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `CORS domain settings are being updated...`,
|
||||
success: `CORS domain settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's CORS domain settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'CORS domain settings are being updated...',
|
||||
successMessage: 'CORS domain settings have been updated successfully.',
|
||||
errorMessage: `An error occurred while trying to update the project's CORS domain settings.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -8,11 +8,9 @@ import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -72,24 +70,19 @@ export default function HasuraDevModeSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Dev Mode settings are being updated...`,
|
||||
success: `Dev Mode settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update Dev Mode settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Dev Mode settings are being updated...',
|
||||
successMessage: 'Dev Mode settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update Dev Mode settings.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -93,24 +91,18 @@ export default function HasuraEnabledAPISettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Enabled APIs are being updated...`,
|
||||
success: `Enabled APIs have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update enabled APIs.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Enabled APIs are being updated...',
|
||||
successMessage: 'Enabled APIs have been updated successfully.',
|
||||
errorMessage: 'An error occurred while trying to update enabled APIs.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -125,7 +117,7 @@ export default function HasuraEnabledAPISettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
className="grid grid-flow-row gap-y-2 gap-x-4 px-4 lg:grid-cols-6"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-2 px-4 lg:grid-cols-6"
|
||||
>
|
||||
<ControlledAutocomplete
|
||||
id="enabledAPIs"
|
||||
|
||||
@@ -10,11 +10,9 @@ import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -94,24 +92,18 @@ export default function HasuraLogLevelSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Log level is being updated...`,
|
||||
success: `Log level has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update log level.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Log level is being updated...',
|
||||
successMessage: 'Log level has been updated successfully.',
|
||||
errorMessage: 'An error occurred while trying to update log level.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -136,7 +128,7 @@ export default function HasuraLogLevelSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
className="grid grid-flow-row gap-y-2 gap-x-4 px-4 lg:grid-cols-5"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-2 px-4 lg:grid-cols-5"
|
||||
>
|
||||
<ControlledAutocomplete
|
||||
id="logLevel"
|
||||
|
||||
@@ -9,11 +9,9 @@ import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -79,24 +77,18 @@ export default function HasuraPoolSizeSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Pool size is being updated...`,
|
||||
success: `Pool size has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the pool size.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Pool size is being updated...',
|
||||
successMessage: 'Pool size has been updated successfully.',
|
||||
errorMessage: 'An error occurred while trying to update the pool size.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -112,7 +104,7 @@ export default function HasuraPoolSizeSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
className="grid grid-flow-row gap-y-2 gap-x-4 px-4 lg:grid-cols-5"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-2 px-4 lg:grid-cols-5"
|
||||
>
|
||||
<Input
|
||||
{...register('httpPoolSize')}
|
||||
|
||||
@@ -8,11 +8,9 @@ import {
|
||||
useGetHasuraSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -76,24 +74,21 @@ export default function HasuraRemoteSchemaPermissionsSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Remote schema permission settings are being updated...`,
|
||||
success: `Remote schema permission settings have been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update remote schema permission settings.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage:
|
||||
'Remote schema permission settings are being updated...',
|
||||
successMessage:
|
||||
'Remote schema permission settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update remote schema permission settings.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -11,11 +11,9 @@ import {
|
||||
useGetSoftwareVersionsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -96,24 +94,19 @@ export default function HasuraServiceVersionSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Hasura version is being updated...`,
|
||||
success: `Hasura version has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update Hasura version.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Hasura version is being updated...',
|
||||
successMessage: 'Hasura version has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update Hasura version.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -130,7 +123,7 @@ export default function HasuraServiceVersionSettings() {
|
||||
}}
|
||||
docsLink="https://hub.docker.com/r/nhost/graphql-engine/tags"
|
||||
docsTitle="the latest releases"
|
||||
className="grid grid-flow-row gap-y-2 gap-x-4 px-4 lg:grid-cols-5"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-2 px-4 lg:grid-cols-5"
|
||||
>
|
||||
<ControlledAutocomplete
|
||||
id="version"
|
||||
|
||||
@@ -7,13 +7,11 @@ import {
|
||||
GetAllWorkspacesAndProjectsDocument,
|
||||
useDeleteApplicationMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { getApplicationStatusString } from '@/utils/helpers';
|
||||
import { formatDistance } from 'date-fns';
|
||||
import { useRouter } from 'next/router';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
export default function ApplicationInfo() {
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
@@ -23,23 +21,18 @@ export default function ApplicationInfo() {
|
||||
const router = useRouter();
|
||||
|
||||
async function handleClickRemove() {
|
||||
try {
|
||||
await toast.promise(
|
||||
deleteApplication({ variables: { appId: currentProject.id } }),
|
||||
{
|
||||
loading: 'Deleting project...',
|
||||
success: 'The project has been deleted successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while deleting the project. Please try again.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
await router.push('/');
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await deleteApplication({ variables: { appId: currentProject.id } });
|
||||
await router.push('/');
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Deleting project...',
|
||||
successMessage: 'The project has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while deleting the project. Please try again.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (!currentProject) {
|
||||
|
||||
@@ -18,12 +18,10 @@ import {
|
||||
useUnpauseApplicationMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { MAX_FREE_PROJECTS } from '@/utils/constants/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import type { ApolloError } from '@apollo/client';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { useUserData } from '@nhost/nextjs';
|
||||
import Image from 'next/image';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
export default function ApplicationPaused() {
|
||||
const { openDialog } = useDialog();
|
||||
@@ -47,33 +45,18 @@ export default function ApplicationPaused() {
|
||||
const wakeUpDisabled = numberOfFreeAndLiveProjects >= MAX_FREE_PROJECTS;
|
||||
|
||||
async function handleTriggerUnpausing() {
|
||||
try {
|
||||
await toast.promise(
|
||||
unpauseApplication({ variables: { appId: currentProject.id } }),
|
||||
{
|
||||
loading: 'Starting the project...',
|
||||
success: `The project has been started successfully.`,
|
||||
error: (arg: ApolloError) => {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } = (internal as Record<string, any>)?.error || {};
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
'An error occurred while waking up the project. Please try again.'
|
||||
);
|
||||
},
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
unpauseApplication({ variables: { appId: currentProject.id } });
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Starting the project...',
|
||||
successMessage: 'The project has been started successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while waking up the project. Please try again.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
|
||||
@@ -16,12 +16,10 @@ import {
|
||||
useUpdateApplicationMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { ApplicationStatus } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import Image from 'next/image';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
function Plan({ planName, price, setPlan, planId, selectedPlanId }: any) {
|
||||
return (
|
||||
@@ -119,8 +117,8 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
});
|
||||
|
||||
const handleUpdateAppPlan = async () => {
|
||||
try {
|
||||
await toast.promise(
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
updateApp({
|
||||
variables: {
|
||||
appId: app.id,
|
||||
@@ -129,21 +127,17 @@ export function ChangePlanModalWithData({ app, plans, close }: any) {
|
||||
desiredState: 5,
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Updating plan...',
|
||||
success: `Plan has been updated successfully to ${selectedPlan.name}.`,
|
||||
error: getServerError(
|
||||
'An error occurred while updating the plan. Please try again.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
});
|
||||
|
||||
setPollingCurrentProject(true);
|
||||
} catch (error) {
|
||||
// Note: Error is handled by the toast.
|
||||
}
|
||||
setPollingCurrentProject(true);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating plan...',
|
||||
successMessage: `Plan has been updated successfully to ${selectedPlan.name}.`,
|
||||
errorMessage:
|
||||
'An error occurred while updating the plan. Please try again.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const handleChangePlanClick = async () => {
|
||||
|
||||
@@ -3,15 +3,13 @@ import { Button } from '@/components/ui/v2/Button';
|
||||
import { Checkbox } from '@/components/ui/v2/Checkbox';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
useDeleteRunServiceConfigMutation,
|
||||
useDeleteRunServiceMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import type { ApolloError } from '@apollo/client';
|
||||
import { type RunService } from 'pages/[workspaceSlug]/[appSlug]/services';
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export interface DeleteServiceModalProps {
|
||||
@@ -43,27 +41,12 @@ export default function DeleteServiceModal({
|
||||
async function handleClick() {
|
||||
setLoadingRemove(true);
|
||||
|
||||
await toast.promise(
|
||||
deleteServiceAndConfig(),
|
||||
{
|
||||
loading: 'Deleting the service...',
|
||||
success: `The service has been deleted successfully.`,
|
||||
error: (arg: ApolloError) => {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } = (internal as Record<string, any>)?.error || {};
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
'An error occurred while deleting the service. Please try again.'
|
||||
);
|
||||
},
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
await execPromiseWithErrorToast(() => deleteServiceAndConfig(), {
|
||||
loadingMessage: 'Deleting the service...',
|
||||
successMessage: 'The service has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while deleting the service. Please try again.',
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -110,7 +110,7 @@ export default function WorkspaceAndProjectList({
|
||||
onChange={handleQueryChange}
|
||||
/>
|
||||
|
||||
<NavLink href="/new" passHref>
|
||||
<NavLink href="/new" passHref legacyBehavior>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
@@ -126,7 +126,7 @@ export default function WorkspaceAndProjectList({
|
||||
<Box className="grid grid-flow-row gap-8 my-8">
|
||||
{filteredWorkspaces.map((workspace) => (
|
||||
<div key={workspace.slug}>
|
||||
<NavLink href={`/${workspace.slug}`} passHref>
|
||||
<NavLink href={`/${workspace.slug}`} passHref legacyBehavior>
|
||||
<Link
|
||||
href={`${workspace.slug}`}
|
||||
className="mb-1.5 block font-medium"
|
||||
@@ -172,7 +172,7 @@ export default function WorkspaceAndProjectList({
|
||||
href={`${workspace?.slug}/${project.slug}`}
|
||||
passHref
|
||||
className='w-full'
|
||||
>
|
||||
legacyBehavior>
|
||||
<ListItem.Button className="rounded-none">
|
||||
<ListItem.Avatar>
|
||||
<div className="w-10 h-10 overflow-hidden rounded-lg">
|
||||
|
||||
@@ -48,7 +48,7 @@ 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 className='w-full'>
|
||||
<NavLink href={`/${slug}`} passHref className='w-full' legacyBehavior>
|
||||
<ListItem.Button
|
||||
dense
|
||||
aria-label={`View ${name}`}
|
||||
@@ -129,7 +129,7 @@ export default function WorkspaceSidebar({
|
||||
passHref
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
legacyBehavior>
|
||||
<Button
|
||||
className="grid w-full grid-flow-col gap-1"
|
||||
variant="outlined"
|
||||
@@ -145,7 +145,7 @@ export default function WorkspaceSidebar({
|
||||
passHref
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
legacyBehavior>
|
||||
<Button
|
||||
className="grid w-full grid-flow-col gap-1"
|
||||
variant="outlined"
|
||||
|
||||
@@ -10,12 +10,10 @@ import {
|
||||
useUpdateConfigMutation,
|
||||
type ConfigIngressUpdateInput,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -91,24 +89,19 @@ export default function AuthDomain() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Auth domain is being updated...`,
|
||||
success: `Auth domain has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the auth domain.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Auth domain is being updated...',
|
||||
successMessage: 'Auth domain has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the auth domain.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -124,7 +117,7 @@ export default function AuthDomain() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
className="grid grid-flow-row px-4 gap-y-4 gap-x-4 lg:grid-cols-5"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-4 px-4 lg:grid-cols-5"
|
||||
>
|
||||
<Input
|
||||
{...register('auth_fqdn')}
|
||||
|
||||
@@ -10,12 +10,10 @@ import {
|
||||
useUpdateConfigMutation,
|
||||
type ConfigIngressUpdateInput,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -93,24 +91,19 @@ export default function HasuraDomain() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Hasura domain is being updated...`,
|
||||
success: `Hasura domain has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the Hasura domain.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Hasura domain is being updated...',
|
||||
successMessage: 'Hasura domain has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the Hasura domain.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -126,7 +119,7 @@ export default function HasuraDomain() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
className="grid grid-flow-row px-4 gap-y-4 gap-x-4 lg:grid-cols-5"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-4 px-4 lg:grid-cols-5"
|
||||
>
|
||||
<Input
|
||||
{...register('hasura_fqdn')}
|
||||
|
||||
@@ -6,13 +6,11 @@ import { Text } from '@/components/ui/v2/Text';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { VerifyDomain } from '@/features/projects/custom-domains/settings/components/VerifyDomain';
|
||||
import { useUpdateRunServiceConfigMutation } from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { type RunService } from 'pages/[workspaceSlug]/[appSlug]/services';
|
||||
import { useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
interface RunServicePortProps {
|
||||
@@ -54,11 +52,11 @@ export default function RunServicePortDomain({
|
||||
const runServicePortFQDN = watch('runServicePortFQDN');
|
||||
|
||||
async function handleSubmit(formValues: RunServicePortFormValues) {
|
||||
try {
|
||||
setLoading(true);
|
||||
setLoading(true);
|
||||
|
||||
await toast.promise(
|
||||
updateRunServiceConfig({
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateRunServiceConfig({
|
||||
variables: {
|
||||
appID: currentProject.id,
|
||||
serviceID: service.id,
|
||||
@@ -87,25 +85,18 @@ export default function RunServicePortDomain({
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: `Port ${port} is being updated...`,
|
||||
success: `Port ${port} has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update Port ${port}.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
});
|
||||
|
||||
form.reset(formValues);
|
||||
// TODO refetch the service config
|
||||
// await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
form.reset(formValues);
|
||||
},
|
||||
{
|
||||
loadingMessage: `Port ${port} is being updated...`,
|
||||
successMessage: `Port ${port} has been updated successfully.`,
|
||||
errorMessage: `An error occurred while trying to update Port ${port}.`,
|
||||
},
|
||||
);
|
||||
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -10,12 +10,10 @@ import {
|
||||
useUpdateConfigMutation,
|
||||
type ConfigIngressUpdateInput,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
@@ -95,24 +93,20 @@ export default function ServerlessFunctionsDomain() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: `Serverless Functions domain is being updated...`,
|
||||
success: `Serverless Functions domain has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the Serverless Functions domain.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
await refetchWorkspaceAndProject();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Serverless Functions domain is being updated...',
|
||||
successMessage:
|
||||
'Serverless Functions domain has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the Serverless Functions domain.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -128,7 +122,7 @@ export default function ServerlessFunctionsDomain() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
className="grid grid-flow-row px-4 gap-y-4 gap-x-4 lg:grid-cols-5"
|
||||
className="grid grid-flow-row gap-x-4 gap-y-4 px-4 lg:grid-cols-5"
|
||||
>
|
||||
<Input
|
||||
{...register('functions_fqdn')}
|
||||
|
||||
@@ -3,12 +3,10 @@ import { Button } from '@/components/ui/v2/Button';
|
||||
import { IconButton } from '@/components/ui/v2/IconButton';
|
||||
import { CopyIcon } from '@/components/ui/v2/icons/CopyIcon';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { useDnsLookupCnameLazyQuery } from '@/utils/__generated__/graphql';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
interface VerifyDomainProps {
|
||||
recordType: string;
|
||||
@@ -32,9 +30,9 @@ export default function VerifyDomain({
|
||||
const handleVerifyDomain = async () => {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
fireLookupCNAME({
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await fireLookupCNAME({
|
||||
variables: {
|
||||
hostname,
|
||||
},
|
||||
@@ -42,44 +40,24 @@ export default function VerifyDomain({
|
||||
if (dnsLookupCNAME !== value) {
|
||||
throw new Error(`Could not verify ${hostname}`);
|
||||
}
|
||||
}),
|
||||
{
|
||||
loading: `Verifying ${hostname} ...`,
|
||||
success: () => {
|
||||
setVerificationFailed(false);
|
||||
setVerificationSucceeded(true);
|
||||
setLoading(false);
|
||||
onHostNameVerified?.();
|
||||
return `${hostname} has been verified.`;
|
||||
},
|
||||
error: (arg: Error | ApolloError) => {
|
||||
setVerificationFailed(true);
|
||||
setVerificationSucceeded(false);
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
if (arg instanceof ApolloError) {
|
||||
// we need to get the internal error message from the GraphQL error
|
||||
const { internal } = arg.graphQLErrors[0]?.extensions || {};
|
||||
const { message } =
|
||||
(internal as Record<string, any>)?.error || {};
|
||||
|
||||
// we use the default Apollo error message if we can't find the
|
||||
// internal error message
|
||||
return (
|
||||
message ||
|
||||
arg.message ||
|
||||
`An error occurred while trying to verify ${hostname}. Please try again.`
|
||||
);
|
||||
}
|
||||
|
||||
return arg.message;
|
||||
},
|
||||
setVerificationFailed(false);
|
||||
setVerificationSucceeded(true);
|
||||
setLoading(false);
|
||||
onHostNameVerified?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: `Verifying ${hostname} ...`,
|
||||
successMessage: `${hostname} has been verified.`,
|
||||
errorMessage: `An error occurred while trying to verify ${hostname}. Please try again.`,
|
||||
onError: () => {
|
||||
setVerificationFailed(true);
|
||||
setVerificationSucceeded(false);
|
||||
setLoading(false);
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
} catch (error) {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -95,7 +73,7 @@ export default function VerifyDomain({
|
||||
color: 'success.dark',
|
||||
},
|
||||
]}
|
||||
className="flex flex-col p-4 space-y-4 rounded-md"
|
||||
className="flex flex-col space-y-4 rounded-md p-4"
|
||||
>
|
||||
<div className="flex flex-row items-center justify-between">
|
||||
{!verificationFailed && !verificationSucceeded && (
|
||||
@@ -139,7 +117,7 @@ export default function VerifyDomain({
|
||||
color="secondary"
|
||||
onClick={() => copy(value, 'CNAME Value')}
|
||||
>
|
||||
<CopyIcon className="w-4 h-4" />
|
||||
<CopyIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<Button
|
||||
|
||||
@@ -37,7 +37,7 @@ function NextPrevPageLink(props: NextPrevPageLinkProps) {
|
||||
<Link
|
||||
href={`${window.location.pathname}?page=${currentPage - 1}`}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<IconButton variant="borderless" color="secondary">
|
||||
<ChevronLeftIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
@@ -48,7 +48,10 @@ function NextPrevPageLink(props: NextPrevPageLinkProps) {
|
||||
return <ChevronRightIcon className="h-4 w-4 cursor-not-allowed" />;
|
||||
}
|
||||
return (
|
||||
<Link href={`${window.location.pathname}?page=${currentPage + 1}`} passHref>
|
||||
<Link
|
||||
href={`${window.location.pathname}?page=${currentPage + 1}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<IconButton variant="borderless" color="secondary">
|
||||
<ChevronRightIcon className="h-4 w-4" />
|
||||
</IconButton>
|
||||
|
||||
@@ -10,8 +10,7 @@ import { ListItem } from '@/components/ui/v2/ListItem';
|
||||
import { Tooltip } from '@/components/ui/v2/Tooltip';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { DeploymentDurationLabel } from '@/features/projects/deployments/components/DeploymentDurationLabel';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import type { DeploymentRowFragment } from '@/utils/__generated__/graphql';
|
||||
import {
|
||||
GetAllWorkspacesAndProjectsDocument,
|
||||
@@ -19,7 +18,6 @@ import {
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { formatDistanceToNowStrict, parseISO } from 'date-fns';
|
||||
import type { MouseEvent } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export interface DeploymentListItemProps {
|
||||
@@ -78,14 +76,15 @@ export default function DeploymentListItem({
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
insertDeploymentPromise,
|
||||
{
|
||||
loading: 'Scheduling deployment...',
|
||||
success: 'Deployment has been scheduled successfully.',
|
||||
error: getServerError('An error occurred when scheduling deployment.'),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await insertDeploymentPromise;
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Scheduling deployment...',
|
||||
successMessage: 'Deployment has been scheduled successfully.',
|
||||
errorMessage: 'An error occurred when scheduling deployment.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -138,7 +137,7 @@ export default function DeploymentListItem({
|
||||
startIcon={
|
||||
<ArrowCounterclockwiseIcon className={twMerge('h-4 w-4')} />
|
||||
}
|
||||
className="rounded-full py-1 px-2 text-xs"
|
||||
className="rounded-full px-2 py-1 text-xs"
|
||||
aria-label="Redeploy"
|
||||
>
|
||||
Redeploy
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
BaseEnvironmentVariableForm,
|
||||
baseEnvironmentVariableFormValidationSchema,
|
||||
} from '@/features/projects/environmentVariables/settings/components/BaseEnvironmentVariableForm';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetEnvironmentVariablesDocument,
|
||||
useGetEnvironmentVariablesQuery,
|
||||
@@ -17,7 +16,6 @@ import {
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export interface CreateEnvironmentVariableFormProps
|
||||
extends Pick<BaseEnvironmentVariableFormProps, 'onCancel' | 'location'> {
|
||||
@@ -102,19 +100,18 @@ export default function CreateEnvironmentVariableForm({
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Creating environment variable...',
|
||||
success: 'Environment variable has been created successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while creating the environment variable.',
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Creating environment variable...',
|
||||
successMessage: 'Environment variable has been created successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while creating the environment variable.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
baseEnvironmentVariableFormValidationSchema,
|
||||
} from '@/features/projects/environmentVariables/settings/components/BaseEnvironmentVariableForm';
|
||||
import type { EnvironmentVariable } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetEnvironmentVariablesDocument,
|
||||
useGetEnvironmentVariablesQuery,
|
||||
@@ -18,7 +17,6 @@ import {
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export interface EditEnvironmentVariableFormProps
|
||||
extends Pick<BaseEnvironmentVariableFormProps, 'onCancel' | 'location'> {
|
||||
@@ -116,19 +114,18 @@ export default function EditEnvironmentVariableForm({
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Updating environment variable...',
|
||||
success: 'Environment variable has been updated successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while updating the environment variable.',
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating environment variable...',
|
||||
successMessage: 'Environment variable has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while updating the environment variable.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Button } from '@/components/ui/v2/Button';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetEnvironmentVariablesDocument,
|
||||
useUpdateConfigMutation,
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useEffect } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export interface EditJwtSecretFormProps extends DialogFormProps {
|
||||
@@ -102,24 +101,17 @@ export default function EditJwtSecretForm({
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Updating JWT secret...',
|
||||
success: 'JWT secret has been updated successfully.',
|
||||
error: (arg: Error) =>
|
||||
arg?.message
|
||||
? `Error: ${arg.message}`
|
||||
: 'An error occurred while updating the JWT secret.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
} catch {
|
||||
// Note: error is handled above
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating JWT secret...',
|
||||
successMessage: 'JWT secret has been updated successfully.',
|
||||
errorMessage: 'An error occurred while updating the JWT secret.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -16,15 +16,13 @@ import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/
|
||||
import { CreateEnvironmentVariableForm } from '@/features/projects/environmentVariables/settings/components/CreateEnvironmentVariableForm';
|
||||
import { EditEnvironmentVariableForm } from '@/features/projects/environmentVariables/settings/components/EditEnvironmentVariableForm';
|
||||
import type { EnvironmentVariable } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetEnvironmentVariablesDocument,
|
||||
useGetEnvironmentVariablesQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { Fragment } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export interface EnvironmentVariableSettingsFormValues {
|
||||
@@ -91,21 +89,17 @@ export default function EnvironmentVariableSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Deleting environment variable...',
|
||||
success: 'Environment variable has been deleted successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while deleting the environment variable.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
} catch {
|
||||
// Note: The toast will handle the error.
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Deleting environment variable...',
|
||||
successMessage: 'Environment variable has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while deleting the environment variable.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function handleOpenCreator() {
|
||||
|
||||
@@ -9,13 +9,11 @@ import {
|
||||
GetAllWorkspacesAndProjectsDocument,
|
||||
useUpdateApplicationMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { discordAnnounce } from '@/utils/discordAnnounce';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useEffect } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
export interface BaseDirectoryFormValues {
|
||||
/**
|
||||
@@ -55,20 +53,19 @@ export default function BaseDirectorySettings() {
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateAppMutation,
|
||||
{
|
||||
loading: `The base directory is being updated...`,
|
||||
success: `The base directory has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's base directory.`,
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateAppMutation;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'The base directory is being updated...',
|
||||
successMessage: 'The base directory has been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's base directory.",
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
|
||||
try {
|
||||
await client.refetchQueries({
|
||||
include: [GetAllWorkspacesAndProjectsDocument],
|
||||
|
||||
@@ -8,13 +8,11 @@ import {
|
||||
GetAllWorkspacesAndProjectsDocument,
|
||||
useUpdateApplicationMutation,
|
||||
} from '@/generated/graphql';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { discordAnnounce } from '@/utils/discordAnnounce';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useEffect } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
export interface DeploymentBranchFormValues {
|
||||
/**
|
||||
@@ -56,20 +54,19 @@ export default function DeploymentBranchSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateAppMutation,
|
||||
{
|
||||
loading: `The deployment branch is being updated...`,
|
||||
success: `The deployment branch has been updated successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to update the project's deployment branch.`,
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateAppMutation;
|
||||
form.reset(values);
|
||||
},
|
||||
{
|
||||
loadingMessage: 'The deployment branch is being updated...',
|
||||
successMessage: 'The deployment branch has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to create the permission variable.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
form.reset(values);
|
||||
|
||||
try {
|
||||
await client.refetchQueries({
|
||||
include: [GetAllWorkspacesAndProjectsDocument],
|
||||
|
||||
@@ -32,7 +32,7 @@ function OverviewDeploymentsTopBar() {
|
||||
<NavLink
|
||||
href={`/${currentWorkspace?.slug}/${currentProject?.slug}/deployments`}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<Button variant="borderless" disabled={!isGitHubConnected}>
|
||||
View all
|
||||
<ChevronRightIcon className="ml-1 inline-block h-4 w-4" />
|
||||
@@ -106,7 +106,7 @@ function OverviewDeploymentList() {
|
||||
<NavLink
|
||||
href={`/${currentWorkspace.slug}/${currentProject.slug}/settings/git`}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<Button variant="borderless" size="small">
|
||||
Edit
|
||||
</Button>
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function OverviewRepository() {
|
||||
<NavLink
|
||||
href={`/${currentWorkspace.slug}/${currentProject.slug}/settings/git`}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
@@ -53,7 +53,7 @@ export default function OverviewRepository() {
|
||||
<NavLink
|
||||
href={`/${currentWorkspace.slug}/${currentProject.slug}/settings/git`}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<Button
|
||||
variant="borderless"
|
||||
size="small"
|
||||
|
||||
@@ -127,7 +127,7 @@ export default function OverviewTopBar() {
|
||||
<Link
|
||||
href={`/${currentWorkspace.slug}/${currentProject.slug}/settings/general`}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<Button
|
||||
endIcon={<CogIcon className="h-4 w-4" />}
|
||||
variant="outlined"
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
basePermissionVariableValidationSchema,
|
||||
} from '@/features/projects/permissions/settings/components/BasePermissionVariableForm';
|
||||
import { getAllPermissionVariables } from '@/features/projects/permissions/settings/utils/getAllPermissionVariables';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetRolesPermissionsDocument,
|
||||
useGetRolesPermissionsQuery,
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export interface CreatePermissionVariableFormProps
|
||||
extends Pick<BasePermissionVariableFormProps, 'onCancel' | 'location'> {
|
||||
@@ -103,18 +102,18 @@ export default function CreatePermissionVariableForm({
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
await onSubmit?.();
|
||||
},
|
||||
{
|
||||
loading: 'Creating permission variable...',
|
||||
success: 'Permission variable has been created successfully.',
|
||||
error:
|
||||
loadingMessage: 'Creating permission variable...',
|
||||
successMessage: 'Permission variable has been created successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to create the permission variable.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
await onSubmit?.();
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '@/features/projects/permissions/settings/components/BasePermissionVariableForm';
|
||||
import { getAllPermissionVariables } from '@/features/projects/permissions/settings/utils/getAllPermissionVariables';
|
||||
import type { PermissionVariable } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetRolesPermissionsDocument,
|
||||
useGetRolesPermissionsQuery,
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export interface EditPermissionVariableFormProps
|
||||
extends Pick<BasePermissionVariableFormProps, 'onCancel' | 'location'> {
|
||||
@@ -130,15 +129,16 @@ export default function EditPermissionVariableForm({
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
},
|
||||
{
|
||||
loading: 'Updating permission variable...',
|
||||
success: 'Permission variable has been updated successfully.',
|
||||
error:
|
||||
loadingMessage: 'Updating permission variable...',
|
||||
successMessage: 'Permission variable has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the permission variable.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
await onSubmit?.();
|
||||
|
||||
@@ -19,15 +19,13 @@ import { CreatePermissionVariableForm } from '@/features/projects/permissions/se
|
||||
import { EditPermissionVariableForm } from '@/features/projects/permissions/settings/components/EditPermissionVariableForm';
|
||||
import { getAllPermissionVariables } from '@/features/projects/permissions/settings/utils/getAllPermissionVariables';
|
||||
import type { PermissionVariable } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetRolesPermissionsDocument,
|
||||
useGetRolesPermissionsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { Fragment } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export default function PermissionVariableSettings() {
|
||||
@@ -78,16 +76,16 @@ export default function PermissionVariableSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Deleting permission variable...',
|
||||
success: 'Permission variable has been deleted successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while trying to delete permission variable.',
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Deleting permission variable...',
|
||||
successMessage: 'Permission variable has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to delete permission variable.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ import {
|
||||
RESOURCE_VCPU_MULTIPLIER,
|
||||
RESOURCE_VCPU_PRICE,
|
||||
} from '@/utils/constants/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import type { GetResourcesQuery } from '@/utils/__generated__/graphql';
|
||||
import {
|
||||
GetResourcesDocument,
|
||||
@@ -28,7 +27,6 @@ import {
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import ResourcesFormFooter from './ResourcesFormFooter';
|
||||
|
||||
@@ -216,16 +214,16 @@ export default function ResourcesForm() {
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Updating resources...',
|
||||
success: 'Resources have been updated successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while updating resources. Please try again.',
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating resources...',
|
||||
successMessage: 'Resources have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while updating resources. Please try again.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
if (!formValues.enabled) {
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
baseRoleFormValidationSchema,
|
||||
} from '@/features/projects/roles/settings/components/BaseRoleForm';
|
||||
import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRoles';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetRolesPermissionsDocument,
|
||||
useGetRolesPermissionsQuery,
|
||||
@@ -18,7 +17,6 @@ import {
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export interface CreateRoleFormProps
|
||||
extends Pick<BaseRoleFormProps, 'onCancel' | 'location'> {
|
||||
@@ -84,23 +82,17 @@ export default function CreateRoleForm({
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Creating role...',
|
||||
success: 'Role has been created successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while trying to create the role.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
} catch (updateConfigError) {
|
||||
console.error(updateConfigError);
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Creating role...',
|
||||
successMessage: 'Role has been created successfully.',
|
||||
errorMessage: 'An error occurred while trying to create the role.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
} from '@/features/projects/roles/settings/components/BaseRoleForm';
|
||||
import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRoles';
|
||||
import type { Role } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetRolesPermissionsDocument,
|
||||
useGetRolesPermissionsQuery,
|
||||
@@ -19,7 +18,6 @@ import {
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export interface EditRoleFormProps
|
||||
extends Pick<BaseRoleFormProps, 'onCancel' | 'location'> {
|
||||
@@ -113,23 +111,17 @@ export default function EditRoleForm({
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Updating role...',
|
||||
success: 'Role has been updated successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while trying to update the role.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
} catch (updateConfigError) {
|
||||
console.error(updateConfigError);
|
||||
}
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating role...',
|
||||
successMessage: 'Role has been updated successfully.',
|
||||
errorMessage: 'An error occurred while trying to update the role.',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -19,15 +19,13 @@ import { CreateRoleForm } from '@/features/projects/roles/settings/components/Cr
|
||||
import { EditRoleForm } from '@/features/projects/roles/settings/components/EditRoleForm';
|
||||
import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRoles';
|
||||
import type { Role } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetRolesPermissionsDocument,
|
||||
useGetRolesPermissionsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { Fragment } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export interface RoleSettingsFormValues {
|
||||
@@ -83,16 +81,16 @@ export default function RoleSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Updating default role...',
|
||||
success: 'Default role has been updated successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while trying to update the default role.',
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating default role...',
|
||||
successMessage: 'Default role has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the default role.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,16 +111,16 @@ export default function RoleSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateConfigPromise,
|
||||
{
|
||||
loading: 'Deleting allowed role...',
|
||||
success: 'Allowed Role has been deleted successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while trying to delete the allowed role.',
|
||||
),
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Deleting allowed role...',
|
||||
successMessage: 'Allowed Role has been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to delete the allowed role.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,13 @@ import {
|
||||
BaseSecretForm,
|
||||
baseSecretFormValidationSchema,
|
||||
} from '@/features/projects/secrets/settings/components/BaseSecretForm';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetSecretsDocument,
|
||||
useInsertSecretMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export interface CreateSecretFormProps
|
||||
extends Pick<BaseSecretFormProps, 'onCancel'> {
|
||||
@@ -54,20 +53,17 @@ export default function CreateSecretForm({
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
insertSecretPromise,
|
||||
{
|
||||
loading: 'Creating secret...',
|
||||
success: 'Secret has been created successfully.',
|
||||
error: (arg: Error) =>
|
||||
arg?.message
|
||||
? `Error: ${arg?.message}`
|
||||
: 'An error occurred while creating the secret.',
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await insertSecretPromise;
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Creating secret...',
|
||||
successMessage: 'Secret has been created successfully.',
|
||||
errorMessage: 'An error occurred while creating the secret.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
@@ -8,14 +8,13 @@ import {
|
||||
baseSecretFormValidationSchema,
|
||||
} from '@/features/projects/secrets/settings/components/BaseSecretForm';
|
||||
import type { Secret } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetSecretsDocument,
|
||||
useUpdateSecretMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export interface EditSecretFormProps
|
||||
extends Pick<BaseSecretFormProps, 'onCancel'> {
|
||||
@@ -60,20 +59,17 @@ export default function EditSecretForm({
|
||||
});
|
||||
|
||||
try {
|
||||
await toast.promise(
|
||||
updateSecretPromise,
|
||||
{
|
||||
loading: 'Updating secret...',
|
||||
success: 'Secret has been updated successfully.',
|
||||
error: (arg: Error) =>
|
||||
arg?.message
|
||||
? `Error: ${arg?.message}`
|
||||
: 'An error occurred while updating the secret.',
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateSecretPromise;
|
||||
onSubmit?.();
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating secret...',
|
||||
successMessage: 'Secret has been updated successfully.',
|
||||
errorMessage: 'An error occurred while updating the secret.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
|
||||
onSubmit?.();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@ import { Form } from '@/components/form/Form';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import type { DialogFormProps } from '@/types/common';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { slugifyString } from '@/utils/helpers';
|
||||
import {
|
||||
GetAllWorkspacesAndProjectsDocument,
|
||||
@@ -16,7 +15,6 @@ import { useUserData } from '@nhost/nextjs';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export interface EditWorkspaceNameFormProps extends DialogFormProps {
|
||||
@@ -125,53 +123,52 @@ export default function EditWorkspaceNameForm({
|
||||
query: { ...router.query, updating: true },
|
||||
});
|
||||
|
||||
await toast.promise(
|
||||
updateWorkspaceName({
|
||||
variables: {
|
||||
id: currentWorkspaceId,
|
||||
workspace: {
|
||||
name: newWorkspaceName,
|
||||
slug,
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Updating workspace name...',
|
||||
success: 'Workspace name has been updated successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while updating the workspace name.',
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
} else {
|
||||
await toast.promise(
|
||||
insertWorkspace({
|
||||
variables: {
|
||||
workspace: {
|
||||
name: newWorkspaceName,
|
||||
companyName: newWorkspaceName,
|
||||
email: currentUser.email,
|
||||
slug,
|
||||
workspaceMembers: {
|
||||
data: [
|
||||
{
|
||||
userId: currentUser.id,
|
||||
type: 'owner',
|
||||
},
|
||||
],
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateWorkspaceName({
|
||||
variables: {
|
||||
id: currentWorkspaceId,
|
||||
workspace: {
|
||||
name: newWorkspaceName,
|
||||
slug,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Creating new workspace...',
|
||||
success: 'The new workspace has been created successfully.',
|
||||
error: getServerError(
|
||||
'An error occurred while creating the new workspace.',
|
||||
),
|
||||
});
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Updating workspace name...',
|
||||
successMessage: 'Workspace name has been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while updating the workspace name.',
|
||||
},
|
||||
);
|
||||
} else {
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await insertWorkspace({
|
||||
variables: {
|
||||
workspace: {
|
||||
name: newWorkspaceName,
|
||||
companyName: newWorkspaceName,
|
||||
email: currentUser.email,
|
||||
slug,
|
||||
workspaceMembers: {
|
||||
data: [
|
||||
{
|
||||
userId: currentUser.id,
|
||||
type: 'owner',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Creating new workspace...',
|
||||
successMessage: 'The new workspace has been created successfully.',
|
||||
errorMessage: 'An error occurred while creating the new workspace.',
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -206,7 +203,7 @@ export default function EditWorkspaceNameForm({
|
||||
<FormProvider {...form}>
|
||||
<Form
|
||||
onSubmit={handleSubmit}
|
||||
className="flex flex-auto flex-col content-between overflow-hidden pt-2 pb-6"
|
||||
className="flex flex-auto flex-col content-between overflow-hidden pb-6 pt-2"
|
||||
>
|
||||
<div className="flex-auto overflow-y-auto px-6">
|
||||
<Input
|
||||
|
||||
@@ -3,16 +3,14 @@ import { Box } from '@/components/ui/v2/Box';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Checkbox } from '@/components/ui/v2/Checkbox';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import { getErrorMessage } from '@/utils/getErrorMessage';
|
||||
import { getServerError } from '@/utils/getServerError';
|
||||
import {
|
||||
GetAllWorkspacesAndProjectsDocument,
|
||||
useDeleteWorkspaceMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import router from 'next/router';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
export interface RemoveWorkspaceModalProps {
|
||||
/**
|
||||
@@ -37,35 +35,30 @@ export default function RemoveWorkspaceModal({
|
||||
const { currentWorkspace } = useCurrentWorkspaceAndProject();
|
||||
|
||||
async function handleClick() {
|
||||
try {
|
||||
await toast.promise(
|
||||
deleteWorkspace({
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await deleteWorkspace({
|
||||
variables: {
|
||||
id: currentWorkspace.id,
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Deleting workspace...',
|
||||
success: `Workspace "${currentWorkspace.name}" has been deleted successfully.`,
|
||||
error: getServerError(
|
||||
`An error occurred while trying to delete the workspace "${currentWorkspace.name}". Please try again.`,
|
||||
),
|
||||
},
|
||||
getToastStyleProps(),
|
||||
);
|
||||
} catch (error) {
|
||||
// TODO: Display error to user and use a logging solution
|
||||
return;
|
||||
}
|
||||
await onSubmit?.();
|
||||
await router.push('/');
|
||||
await client.refetchQueries({
|
||||
include: [GetAllWorkspacesAndProjectsDocument],
|
||||
});
|
||||
});
|
||||
|
||||
await onSubmit?.();
|
||||
await router.push('/');
|
||||
await client.refetchQueries({
|
||||
include: [GetAllWorkspacesAndProjectsDocument],
|
||||
});
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Deleting workspace...',
|
||||
successMessage: `Workspace "${currentWorkspace.name}" has been deleted successfully.`,
|
||||
errorMessage: `An error occurred while trying to delete the workspace "${currentWorkspace.name}". Please try again.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box className="grid grid-flow-row gap-4 px-6 pt-4 pb-6">
|
||||
<Box className="grid grid-flow-row gap-4 px-6 pb-6 pt-4">
|
||||
<Box className="border-y py-2">
|
||||
<Checkbox
|
||||
id="accept-remove"
|
||||
|
||||
@@ -46,7 +46,7 @@ function AllWorkspaceApps() {
|
||||
href={`${currentWorkspace?.slug}/${project.slug}`}
|
||||
passHref
|
||||
className='w-full'
|
||||
>
|
||||
legacyBehavior>
|
||||
<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>
|
||||
@@ -110,7 +110,7 @@ export default function WorkspaceApps() {
|
||||
pathname: '/new',
|
||||
query: { workspace: currentWorkspace?.slug },
|
||||
}}
|
||||
>
|
||||
legacyBehavior>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user