@chakra-ui/react#AlertTitle TypeScript Examples
The following examples show how to use
@chakra-ui/react#AlertTitle.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ErrorAlert.tsx From takeout-app with MIT License | 6 votes |
ErrorAlert: React.FC<Props> = ({error}) => {
return <>
<Alert status="error">
<AlertIcon />
<AlertTitle mr={2}>{error.name}</AlertTitle>
<AlertDescription>{error.message}</AlertDescription>
</Alert>
</>;
}
Example #2
Source File: index.tsx From calories-in with MIT License | 6 votes |
function Exporter({ onUpdate }: Props) {
const { isLoading, error } = usePdfExport({ onUpdate })
if (isLoading) {
return <Loader label="Exporting..." />
}
return (
<Alert
status={error ? 'error' : 'success'}
variant="subtle"
flexDirection="column"
alignItems="center"
justifyContent="center"
textAlign="center"
height="200px"
bg="white"
>
<AlertIcon color={error ? 'red.400' : 'teal.400'} boxSize="40px" mr={0} />
<AlertTitle mt={4} mb={1} fontSize="lg">
{error
? 'Something went wrong while creating your pdf file'
: 'Your PDF file is ready'}
</AlertTitle>
{!error && (
<AlertDescription maxWidth="sm">
Downloading this plan will allow you to import it later if you need to
update it.
</AlertDescription>
)}
</Alert>
)
}
Example #3
Source File: AddNewFeedForm.tsx From nextjs-hasura-boilerplate with MIT License | 5 votes |
AddNewFeedForm = () => {
const [body, setBody] = useState("");
const [session] = useSession();
const [
insertFeed,
{ loading: insertFeedFetching, error: insertFeedError },
] = useInsertFeedMutation();
if (!session) {
return (
<AccessDeniedIndicator message="You need to be signed in to add a new feed!" />
);
}
const handleSubmit = async () => {
await insertFeed({
variables: {
author_id: session.id,
body,
},
});
setBody("");
};
const errorNode = () => {
if (!insertFeedError) {
return false;
}
return (
<Alert status="error">
<AlertIcon />
<AlertTitle>{insertFeedError}</AlertTitle>
<CloseButton position="absolute" right="8px" top="8px" />
</Alert>
);
};
return (
<Stack spacing={4}>
{errorNode()}
<Box p={4} shadow="lg" rounded="lg">
<Stack spacing={4}>
<FormControl isRequired>
<FormLabel htmlFor="body">What's on your mind?</FormLabel>
<Textarea
id="body"
value={body}
onChange={(e: ChangeEvent<HTMLTextAreaElement>) =>
setBody(e.currentTarget.value)
}
isDisabled={insertFeedFetching}
/>
</FormControl>
<FormControl>
<Button
loadingText="Posting..."
onClick={handleSubmit}
isLoading={insertFeedFetching}
isDisabled={!body.trim()}
>
Post
</Button>
</FormControl>
</Stack>
</Box>
</Stack>
);
}
Example #4
Source File: index.tsx From nextjs-hasura-boilerplate with MIT License | 5 votes |
MyAccountPageComponent = ({ user }) => {
const [name, setName] = useState(user.name);
const [session] = useSession();
const [updateUser, { loading: updateUserFetching, error: updateUserError }] =
useUpdateUserMutation();
const handleSubmit = () => {
updateUser({
variables: {
userId: session.id,
name,
},
});
};
const errorNode = () => {
if (!updateUserError) {
return false;
}
return (
<Alert status="error">
<AlertIcon />
<AlertTitle>{updateUserError}</AlertTitle>
<CloseButton position="absolute" right="8px" top="8px" />
</Alert>
);
};
return (
<Stack spacing={8}>
<Heading>My Account</Heading>
{errorNode()}
<Box shadow="lg" rounded="lg" p={4}>
<Stack spacing={4}>
<FormControl isRequired>
<FormLabel htmlFor="name">Name</FormLabel>
<Input
type="text"
id="name"
value={name}
onChange={(e: FormEvent<HTMLInputElement>) =>
setName(e.currentTarget.value)
}
isDisabled={updateUserFetching}
/>
</FormControl>
<FormControl>
<Button
loadingText="Saving..."
onClick={handleSubmit}
isLoading={updateUserFetching}
isDisabled={!name.trim()}
>
Save
</Button>
</FormControl>
</Stack>
</Box>
</Stack>
);
}
Example #5
Source File: RenderDetail.tsx From ke with MIT License | 4 votes |
RenderDetail = (props: RenderDetailProps): JSX.Element => {
/*
Entry point for displaying components in https://myspa.com/some-url/100500 route format.
Here we fetch data from the backend using the url that we specified in a
admin class.
After that we mounts the widgets of a particular view type. At the moment there are two:
- Detail View (see mountDetailFields for detail)
- Wizard View (see mountWizards for detail)
*/
const [mainDetailObject, setMainDetailObject] = useState<Model>()
const [needRefreshDetailObject, setNeedRefreshDetailObject] = useState<boolean>(true)
const { id } = useParams<{ id: string }>()
const { resourceName, admin, provider, notifier } = props
const toast = useToast()
const detailNotifier = notifier || new ChakraUINotifier(toast)
const [isLoading, setIsLoading] = useState<boolean>(true)
const [loadError, setLoadError] = useState<LoadError | null>(null)
const activeWizardRef = useRef<WizardControl>()
let title = `${admin.verboseName} # ${id}`
if (admin.getPageTitle) {
const pageTitle = admin.getPageTitle(mainDetailObject)
if (pageTitle) {
title = pageTitle
}
}
document.title = title
let favicon = admin.favicon || ''
if (admin.getPageFavicon) {
const favIconSource = admin.getPageFavicon(mainDetailObject)
if (favIconSource) {
favicon = favIconSource
}
}
setFavicon(favicon)
const refreshMainDetailObject = (): void => {
setNeedRefreshDetailObject(true)
}
useEffect(() => {
const backendResourceUrl = admin.getResource(id)
if (needRefreshDetailObject) {
provider
.getObject(backendResourceUrl)
.then(async (res) => {
setNeedRefreshDetailObject(false)
setMainDetailObject(res)
if (admin?.onDetailObjectLoaded !== undefined) {
await admin.onDetailObjectLoaded({
mainDetailObject: res,
provider,
context: containerStore,
setInitialValue,
})
}
})
.catch((er: LoadError) => {
setLoadError(er)
})
.finally(() => setIsLoading(false))
}
}, [id, provider, admin, needRefreshDetailObject, props, mainDetailObject])
const { getDataTestId } = useCreateTestId({ name: admin.name })
useEffect(() => {
admin.onMount()
return () => admin.onUnmount()
}, [admin])
return (
<SaveEventProvider>
<Row>
<Col xs={12} xsOffset={0} md={10} mdOffset={1}>
<Box padding="8px 0px">
<ToListViewLink name={resourceName} />
</Box>
</Col>
</Row>
<Row {...getDataTestId()}>
<Col xs={12} xsOffset={0} md={10} mdOffset={1}>
{isLoading ? <Spinner /> : ''}
{!isLoading && !loadError
? Object.entries(getContainersToMount()).map(([elementsKey, container]: [string, Function]) => {
const elements = admin[elementsKey as keyof typeof admin]
if (!elements) return []
return (
<ErrorBoundary>
{container({
mainDetailObject,
setMainDetailObject,
ViewType,
elements,
elementsKey,
refreshMainDetailObject,
activeWizardRef,
...props,
notifier: detailNotifier,
})}
</ErrorBoundary>
)
})
: ''}
{!isLoading && loadError ? (
<Alert status="error" {...getDataTestId({ postfix: '--loadingError' })}>
<AlertIcon />
<AlertTitle mr={2}>Ошибка при выполнении запроса</AlertTitle>
<AlertDescription>{loadError.response?.data?.message}</AlertDescription>
</Alert>
) : (
''
)}
</Col>
</Row>
</SaveEventProvider>
)
}
Example #6
Source File: create-app-github.tsx From ledokku with MIT License | 4 votes |
CreateAppGithub = () => {
const history = useHistory();
const toast = useToast();
const { user } = useAuth();
const { data: dataApps } = useAppsQuery();
const [isNewWindowClosed, setIsNewWindowClosed] = useState(false);
const [selectedRepo, setSelectedRepo] = useState<Repository>();
const [selectedBranch, setSelectedBranch] = useState('');
const [isProceedModalOpen, setIsProceedModalOpen] = useState(false);
const {
data: installationData,
loading: installationLoading,
} = useGithubInstallationIdQuery({ fetchPolicy: 'network-only' });
const [
getRepos,
{ data: reposData, loading: reposLoading },
] = useRepositoriesLazyQuery({ fetchPolicy: 'network-only' });
const [
getBranches,
{ data: branchesData, loading: branchesLoading },
] = useBranchesLazyQuery({ fetchPolicy: 'network-only' });
const [arrayOfCreateAppLogs, setArrayOfCreateAppLogs] = useState<
RealTimeLog[]
>([]);
const [isTerminalVisible, setIsTerminalVisible] = useState(false);
const [isToastShown, setIsToastShown] = useState(false);
const [createAppGithubMutation, { loading }] = useCreateAppGithubMutation();
const [
isAppCreationSuccess,
setIsAppCreationSuccess,
] = useState<AppCreationStatus>();
useAppCreateLogsSubscription({
onSubscriptionData: (data) => {
const logsExist = data.subscriptionData.data?.appCreateLogs;
if (logsExist) {
setArrayOfCreateAppLogs((currentLogs) => {
return [...currentLogs, logsExist];
});
if (logsExist.type === 'end:success') {
setIsAppCreationSuccess(AppCreationStatus.SUCCESS);
} else if (logsExist.type === 'end:failure') {
setIsAppCreationSuccess(AppCreationStatus.FAILURE);
}
}
},
});
const createAppGithubSchema = yup.object().shape({
name: yup
.string()
.required('App name is required')
.matches(/^[a-z0-9-]+$/)
.test(
'Name exists',
'App with this name already exists',
(val) => !dataApps?.apps.find((app) => app.name === val)
),
repo: yup.object({
fullName: yup.string().required(),
id: yup.string().required(),
name: yup.string().required(),
}),
installationId: yup.string().required(),
gitBranch: yup.string().optional(),
});
const formik = useFormik<{
name: string;
repo: {
fullName: string;
id: string;
name: string;
};
installationId: string;
gitBranch: string;
}>({
initialValues: {
name: '',
repo: {
fullName: '',
id: '',
name: '',
},
installationId: '',
gitBranch: '',
},
validateOnChange: true,
validationSchema: createAppGithubSchema,
onSubmit: async (values) => {
if (installationData) {
try {
await createAppGithubMutation({
variables: {
input: {
name: values.name,
gitRepoFullName: values.repo.fullName,
branchName: values.gitBranch,
gitRepoId: values.repo.id,
githubInstallationId: values.installationId,
},
},
});
setIsTerminalVisible(true);
} catch (error) {
error.message === 'Not Found'
? toast.error(`Repository : ${values.repo.fullName} not found`)
: toast.error(error.message);
}
}
},
});
const handleNext = () => {
setIsTerminalVisible(false);
const appId = arrayOfCreateAppLogs[arrayOfCreateAppLogs.length - 1].message;
history.push(`app/${appId}`, 'new');
trackGoal(trackingGoals.createAppGithub, 0);
};
const handleOpen = () => {
const newWindow = window.open(
`https://github.com/apps/${config.githubAppName}/installations/new`,
'Install App',
'resizable=1, scrollbars=1, fullscreen=0, height=1000, width=1020,top=' +
window.screen.width +
', left=' +
window.screen.width +
', toolbar=0, menubar=0, status=0'
);
const timer = setInterval(async () => {
if (newWindow && newWindow.closed) {
setIsNewWindowClosed(true);
clearInterval(timer);
}
}, 100);
};
useEffect(() => {
if (!installationLoading && installationData && isNewWindowClosed) {
getRepos({
variables: {
installationId: installationData.githubInstallationId.id,
},
});
setIsNewWindowClosed(false);
}
}, [
installationData,
installationLoading,
isNewWindowClosed,
setIsNewWindowClosed,
getRepos,
]);
useEffect(() => {
if (
!installationLoading &&
installationData &&
!reposLoading &&
reposData &&
selectedRepo
) {
getBranches({
variables: {
installationId: installationData.githubInstallationId.id,
repositoryName: selectedRepo.name,
},
});
}
}, [
installationData,
installationLoading,
reposData,
reposLoading,
getBranches,
selectedRepo?.name,
selectedRepo,
]);
const handleChangeRepo = (active: RepoOption) => {
setSelectedRepo(active.value);
setSelectedBranch('');
if (installationData) {
formik.setValues({
name: active.value.name,
installationId: installationData?.githubInstallationId.id,
repo: {
fullName: active.value.fullName,
name: active.value.name,
id: active.value.id,
},
gitBranch: '',
});
}
};
const handleChangeBranch = (active: BranchOption) => {
setSelectedBranch(active.value.name);
formik.setFieldValue('gitBranch', active.value.name);
};
const repoOptions: RepoOption[] = [];
if (reposData && !reposLoading) {
reposData?.repositories.map((r) =>
repoOptions.push({ value: r, label: r.fullName })
);
}
let branchOptions: BranchOption[] = [];
if (branchesData && !branchesLoading) {
branchesData.branches.map((b) =>
branchOptions.push({ value: b, label: b.name })
);
}
useEffect(() => {
if (installationData && !installationLoading) {
getRepos({
variables: {
installationId: installationData?.githubInstallationId.id,
},
});
}
}, [installationLoading, getRepos, installationData]);
useEffect(() => {
if (selectedRepo && installationData) {
getBranches({
variables: {
installationId: installationData?.githubInstallationId.id,
repositoryName: selectedRepo.name,
},
});
}
}, [selectedRepo, getBranches, installationData]);
// Effect for app creation
useEffect(() => {
isAppCreationSuccess === AppCreationStatus.FAILURE && !isToastShown
? toast.error('Failed to create an app') && setIsToastShown(true)
: isAppCreationSuccess === AppCreationStatus.SUCCESS &&
!isToastShown &&
toast.success('App created successfully') &&
setIsToastShown(true);
}, [isToastShown, isAppCreationSuccess, toast]);
return (
<>
<HeaderContainer>
<Header />
</HeaderContainer>
<Container maxW="5xl" mt={10}>
{isTerminalVisible ? (
<>
<p className="mb-2 ">
Creating <b>{formik.values.name}</b> app from{' '}
<b>{formik.values.repo.name}</b>
</p>
<p className="text-gray-500 mb-2">
Creating app usually takes a couple of minutes. Breathe in,
breathe out, logs are about to appear below:
</p>
<Terminal className={'w-6/6'}>
{arrayOfCreateAppLogs.map((log) => (
<p
key={arrayOfCreateAppLogs.indexOf(log)}
className={'text-s leading-5'}
>
{log.message?.replaceAll('[1G', '')}
</p>
))}
</Terminal>
{!!isAppCreationSuccess &&
isAppCreationSuccess === AppCreationStatus.SUCCESS ? (
<div className="mt-12 flex justify-end">
<Button
onClick={() => handleNext()}
color="grey"
iconEnd={<FiArrowRight size={20} />}
>
Next
</Button>
</div>
) : !!isAppCreationSuccess &&
isAppCreationSuccess === AppCreationStatus.FAILURE ? (
<div className="mt-12 flex justify-start">
<Button
onClick={() => {
setIsTerminalVisible(false);
formik.resetForm();
}}
color="grey"
iconEnd={<FiArrowLeft size={20} />}
>
Back
</Button>
</div>
) : null}
</>
) : (
<>
<Heading as="h2" size="md">
Create a new GitHub application
</Heading>
{installationData &&
!installationLoading &&
reposData &&
!reposLoading ? (
<>
<Text color="gray.400">
When you push to Git, your application will be redeployed
automatically.
</Text>
<Grid
templateColumns={{
sm: 'repeat(1, 1fr)',
md: 'repeat(3, 1fr)',
}}
>
<GridItem colSpan={2}>
<Flex alignItems="center" mt="12">
<Avatar
size="sm"
name={user?.userName}
src={user?.avatarUrl}
/>
<Text ml="2" fontWeight="bold">
{user?.userName}
</Text>
</Flex>
<form onSubmit={formik.handleSubmit}>
<Box mt="8">
<FormLabel>Repository</FormLabel>
<Select
placeholder="Select repository"
isSearchable={false}
onChange={handleChangeRepo}
options={repoOptions}
/>
</Box>
<Text mt="1" color="gray.400" fontSize="sm">
Can't see your repo in the list?{' '}
<Link
onClick={() => setIsProceedModalOpen(true)}
textDecoration="underline"
>
Configure the GitHub app.
</Link>
</Text>
<Box mt="8">
<FormLabel>Branch to deploy</FormLabel>
<Select
placeholder="Select branch"
isSearchable={false}
disabled={
!branchesData ||
branchesLoading ||
reposLoading ||
!reposData
}
onChange={handleChangeBranch}
options={branchOptions}
/>
</Box>
<Box mt="8" display="flex" justifyContent="flex-end">
<Button
type="submit"
color="grey"
disabled={!selectedBranch || !selectedRepo}
isLoading={loading}
>
Create
</Button>
</Box>
</form>
</GridItem>
</Grid>
</>
) : !reposLoading && !installationLoading && !reposData ? (
<>
<Alert mb="4" mt="4" w="65%" status="info">
<AlertIcon />
<Box flex="1">
<AlertTitle>Set up repository permissions</AlertTitle>
<AlertDescription display="block">
First you will need to set up permissions for repositories
that you would like to use with Ledokku. Once that's done,
it's time to choose repo and branch that you would like to
create app from and off we go.
</AlertDescription>
</Box>
</Alert>
<Button
color="grey"
onClick={() => setIsProceedModalOpen(true)}
>
Set up permissions
</Button>
</>
) : (
<Spinner />
)}
</>
)}
<Modal
isOpen={isProceedModalOpen}
onClose={() => setIsProceedModalOpen(false)}
isCentered
>
<ModalOverlay />
<ModalContent>
<ModalHeader>Github setup info</ModalHeader>
<ModalCloseButton />
<ModalBody>
New window is about to open. After you are done selecting github
repos, close the window and refresh page.
</ModalBody>
<ModalFooter>
<Button
color="grey"
variant="outline"
className="mr-3"
onClick={() => setIsProceedModalOpen(false)}
>
Cancel
</Button>
<Button
color="grey"
onClick={() => {
handleOpen();
setIsProceedModalOpen(false);
}}
>
Proceed
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</Container>
</>
);
}
Example #7
Source File: create-database.tsx From ledokku with MIT License | 4 votes |
CreateDatabase = () => {
const location = useLocation();
const history = useHistory();
const toast = useToast();
const { data: dataDb } = useDatabaseQuery();
const [arrayOfCreateDbLogs, setArrayofCreateDbLogs] = useState<RealTimeLog[]>(
[]
);
const [isTerminalVisible, setIsTerminalVisible] = useState(false);
const [createDatabaseMutation] = useCreateDatabaseMutation();
const [
isDbCreationSuccess,
setIsDbCreationSuccess,
] = useState<DbCreationStatus>();
useCreateDatabaseLogsSubscription({
onSubscriptionData: (data) => {
const logsExist = data.subscriptionData.data?.createDatabaseLogs;
if (logsExist) {
setArrayofCreateDbLogs((currentLogs) => {
return [...currentLogs, logsExist];
});
if (logsExist.type === 'end:success') {
setIsDbCreationSuccess(DbCreationStatus.SUCCESS);
} else if (logsExist.type === 'end:failure') {
setIsDbCreationSuccess(DbCreationStatus.FAILURE);
}
}
},
});
const createDatabaseSchema = yup.object({
type: yup
.string()
.oneOf(['POSTGRESQL', 'MYSQL', 'MONGODB', 'REDIS'])
.required(),
name: yup.string().when('type', (type: DatabaseTypes) => {
return yup
.string()
.required('Database name is required')
.matches(/^[a-z0-9-]+$/)
.test(
'Name already exists',
`You already have created ${type} database with this name`,
(name) =>
!dataDb?.databases.find(
(db) => db.name === name && type === db.type
)
);
}),
});
const [
isDokkuPluginInstalled,
{ data, loading, error: isDokkuPluginInstalledError },
] = useIsPluginInstalledLazyQuery({
// we poll every 5 sec
pollInterval: 5000,
});
const formik = useFormik<{ name: string; type: DatabaseTypes }>({
initialValues: {
name: location.state ? (location.state as string) : '',
type: 'POSTGRESQL',
},
validateOnChange: true,
validationSchema: createDatabaseSchema,
onSubmit: async (values) => {
try {
await createDatabaseMutation({
variables: {
input: { name: values.name, type: values.type },
},
});
setIsTerminalVisible(true);
trackGoal(trackingGoals.createDatabase, 0);
} catch (error) {
toast.error(error.message);
}
},
});
const isPluginInstalled = data?.isPluginInstalled.isPluginInstalled;
const handleNext = () => {
setIsTerminalVisible(false);
const dbId = arrayOfCreateDbLogs[arrayOfCreateDbLogs.length - 1].message;
history.push(`database/${dbId}`);
};
// Effect for checking whether plugin is installed
useEffect(() => {
isDokkuPluginInstalled({
variables: {
pluginName: dbTypeToDokkuPlugin(formik.values.type),
},
});
}, [formik.values.type, isPluginInstalled, isDokkuPluginInstalled]);
// Effect for db creation
useEffect(() => {
isDbCreationSuccess === DbCreationStatus.FAILURE
? toast.error('Failed to create database')
: isDbCreationSuccess === DbCreationStatus.SUCCESS &&
toast.success('Database created successfully');
}, [isDbCreationSuccess, toast]);
return (
<>
<HeaderContainer>
<Header />
</HeaderContainer>
<Container maxW="5xl" my="4">
<Heading as="h2" size="md">
Create a new database
</Heading>
<Box mt="12">
{isTerminalVisible ? (
<>
<Text mb="2">
Creating <b>{formik.values.type}</b> database{' '}
<b>{formik.values.name}</b>
</Text>
<Text mb="2" color="gray.500">
Creating database usually takes a couple of minutes. Breathe in,
breathe out, logs are about to appear below:
</Text>
<Terminal>
{arrayOfCreateDbLogs.map((log) => (
<Text key={arrayOfCreateDbLogs.indexOf(log)} size="small">
{log.message}
</Text>
))}
</Terminal>
{!!isDbCreationSuccess &&
isDbCreationSuccess === DbCreationStatus.SUCCESS ? (
<Box mt="12" display="flex" justifyContent="flex-end">
<Button
onClick={() => handleNext()}
rightIcon={<FiArrowRight size={20} />}
>
Next
</Button>
</Box>
) : !!isDbCreationSuccess &&
isDbCreationSuccess === DbCreationStatus.FAILURE ? (
<Box mt="12" display="flex" justifyContent="flex-end">
<Button
onClick={() => {
setIsTerminalVisible(false);
formik.resetForm();
}}
rightIcon={<FiArrowLeft size={20} />}
>
Back
</Button>
</Box>
) : null}
</>
) : (
<Box mt="8">
<form onSubmit={formik.handleSubmit}>
<Box mt="12">
{loading && (
<Center>
<Spinner />
</Center>
)}
{isDokkuPluginInstalledError ? (
<Alert
status="error"
variant="top-accent"
flexDirection="column"
alignItems="flex-start"
borderBottomRadius="base"
boxShadow="md"
>
<AlertTitle mr={2}>Request failed</AlertTitle>
<AlertDescription>
{isDokkuPluginInstalledError.message}
</AlertDescription>
</Alert>
) : null}
{data?.isPluginInstalled.isPluginInstalled === false &&
!loading && (
<>
<Text mt="3">
Before creating a{' '}
<b>{formik.values.type.toLowerCase()}</b> database,
you will need to run this command on your dokku
server.
</Text>
<Terminal>{`sudo dokku plugin:install https://github.com/dokku/dokku-${dbTypeToDokkuPlugin(
formik.values.type
)}.git ${dbTypeToDokkuPlugin(
formik.values.type
)}`}</Terminal>
<Text mt="3">
Couple of seconds later you will be able to proceed
further.
</Text>
</>
)}
{data?.isPluginInstalled.isPluginInstalled === true &&
!loading && (
<SimpleGrid columns={{ sm: 1, md: 3 }}>
<FormControl
id="name"
isInvalid={Boolean(
formik.errors.name && formik.touched.name
)}
>
<FormLabel>Database name</FormLabel>
<Input
autoComplete="off"
id="name"
name="name"
value={formik.values.name}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
<FormErrorMessage>
{formik.errors.name}
</FormErrorMessage>
</FormControl>
</SimpleGrid>
)}
</Box>
<Box mt="12">
<Text mb="2">Choose your database</Text>
<Grid
templateColumns={{
base: 'repeat(2, minmax(0, 1fr))',
md: 'repeat(4, minmax(0, 1fr))',
}}
gap="4"
>
<DatabaseBox
selected={formik.values.type === 'POSTGRESQL'}
label="PostgreSQL"
icon={<PostgreSQLIcon size={40} />}
onClick={() => formik.setFieldValue('type', 'POSTGRESQL')}
/>
<DatabaseBox
selected={formik.values.type === 'MYSQL'}
label="MySQL"
icon={<MySQLIcon size={40} />}
onClick={() => formik.setFieldValue('type', 'MYSQL')}
/>
<DatabaseBox
selected={formik.values.type === 'MONGODB'}
label="Mongo"
icon={<MongoIcon size={40} />}
onClick={() => formik.setFieldValue('type', 'MONGODB')}
/>
<DatabaseBox
selected={formik.values.type === 'REDIS'}
label="Redis"
icon={<RedisIcon size={40} />}
onClick={() => formik.setFieldValue('type', 'REDIS')}
/>
</Grid>
</Box>
<Box mt="12" display="flex" justifyContent="flex-end">
<Button
isLoading={formik.isSubmitting}
disabled={
data?.isPluginInstalled.isPluginInstalled === false ||
!formik.values.name ||
!!formik.errors.name ||
!dataDb?.databases
}
rightIcon={<FiArrowRight size={20} />}
type="submit"
>
Create
</Button>
</Box>
</form>
</Box>
)}
</Box>
</Container>
</>
);
}
Example #8
Source File: home.tsx From ledokku with MIT License | 4 votes |
Home = () => {
const toast = useToast();
const history = useHistory();
const { loggedIn, login } = useAuth();
const { data, loading, error } = useSetupQuery({});
const [
registerGithubAppMutation,
{ loading: registerGithubAppLoading },
] = useRegisterGithubAppMutation();
const [
loginWithGithubMutation,
{ loading: loginWithGithubLoading },
] = useLoginWithGithubMutation();
const [showAppSuccessAlert, setShowAppSuccessAlert] = useState(false);
// On mount we check if there is a github code present
useEffect(() => {
const codeToLogin = async () => {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const githubCode = urlParams.get('code');
const githubState = urlParams.get('state');
// In case of login state is empty
if (githubState === 'github_login' && githubCode) {
// Remove hash in url
window.history.replaceState({}, document.title, '.');
try {
const data = await loginWithGithubMutation({
variables: { code: githubCode },
});
if (data.data?.loginWithGithub) {
login(data.data.loginWithGithub.token);
history.push('/dashboard');
}
} catch (error) {
toast.error(error.message);
}
return;
}
if (githubState === 'github_application_setup' && githubCode) {
// Remove hash in url
window.history.replaceState({}, document.title, '.');
try {
const data = await registerGithubAppMutation({
variables: { code: githubCode },
update: (cache, { data }) => {
cache.modify({
fields: {
setup: (existingSetup) => {
if (data?.registerGithubApp?.githubAppClientId) {
// Change the local cache so we don't have to call the server again
const newSetup = {
...existingSetup,
isGithubAppSetup: true,
};
return newSetup;
}
return existingSetup;
},
},
});
},
});
if (data.data?.registerGithubApp?.githubAppClientId) {
// Manually set the config so we don't have to reload the page
config.githubClientId =
data.data?.registerGithubApp?.githubAppClientId;
setShowAppSuccessAlert(true);
}
} catch (error) {
toast.error(error.message);
}
}
};
codeToLogin();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleLogin = () => {
// The redirect_uri parameter should only be used on production,
// on dev env we force the redirection to localhost
window.location.replace(
`https://github.com/login/oauth/authorize?client_id=${config.githubClientId}&state=github_login`
);
};
// We check if the user is connected, if yes we need to redirect him to the dashboard
if (loggedIn) {
return <Redirect to="dashboard" />;
}
return (
<Container maxW="5xl">
<Box
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="center"
minHeight="100vh"
>
<Heading as="h2" size="lg">
Ledokku
</Heading>
{error && (
<Text mt={4} color="red.500">
{error.message}
</Text>
)}
{(loading || registerGithubAppLoading || loginWithGithubLoading) && (
<Spinner mt={4} />
)}
{data?.setup.canConnectSsh === false && (
<>
<Text mt={4}>
In order to setup the ssh connection, run the following command on
your Dokku server.
</Text>
<Terminal wordBreak="break-all">
{`echo "${data.setup.sshPublicKey}" | dokku ssh-keys:add ledokku`}
</Terminal>
<Text mt={3}>Once you are done, just refresh this page.</Text>
</>
)}
{data?.setup.canConnectSsh === true &&
data?.setup.isGithubAppSetup === false &&
!registerGithubAppLoading && (
<Box
maxWidth="xl"
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="center"
>
<Text mt={4} textAlign="center">
In order to be able to login and interact with the Github API,
let's create a new Github Application.
</Text>
<form
action="https://github.com/settings/apps/new?state=github_application_setup"
method="post"
>
<input
type="text"
name="manifest"
id="manifest"
defaultValue={data.setup.githubAppManifest}
style={{ display: 'none' }}
/>
<Button
mt={4}
colorScheme="gray"
type="submit"
leftIcon={<FiGithub size={18} />}
size="lg"
>
Create Github Application
</Button>
</form>
</Box>
)}
{data?.setup.canConnectSsh === true &&
data?.setup.isGithubAppSetup === true &&
!loginWithGithubLoading && (
<Box
maxWidth="2xl"
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="center"
>
{showAppSuccessAlert ? (
<Alert
mt={4}
status="success"
variant="top-accent"
flexDirection="column"
alignItems="flex-start"
borderBottomRadius="base"
boxShadow="md"
>
<AlertTitle mr={2}>
Github application successfully created
</AlertTitle>
<AlertDescription>
You can now login to create your first user.
</AlertDescription>
</Alert>
) : null}
<Button
mt={4}
colorScheme="gray"
onClick={handleLogin}
leftIcon={<FiGithub size={18} />}
size="lg"
>
Log in with Github
</Button>
</Box>
)}
</Box>
</Container>
);
}