feat(health): add health checks to server api
This commit is contained in:
parent
8f48f5fcd6
commit
eca80a1663
|
@ -41,7 +41,7 @@ const Profiles = () => {
|
|||
<footer className="flex justify-end">
|
||||
<Button variant="outlined" startIcon={<Add />} onClick={handleAdd}>
|
||||
{t('builder.common.actions.add', {
|
||||
section: t('builder.leftSidebar.sections.profiles.heading', { count: 1 }),
|
||||
token: t('builder.leftSidebar.sections.profiles.heading', { count: 1 }),
|
||||
})}
|
||||
</Button>
|
||||
</footer>
|
||||
|
|
|
@ -122,7 +122,7 @@ const LoginModal: React.FC = () => {
|
|||
startIcon={<Google />}
|
||||
onClick={handleLoginWithGoogle}
|
||||
>
|
||||
{t('modals.auth.login.actions.login-google')}
|
||||
{t('modals.auth.login.actions.google')}
|
||||
</Button>
|
||||
|
||||
<Button type="submit" onClick={handleSubmit(onSubmit)} disabled={isLoading}>
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import env from '@beam-australia/react-env';
|
||||
import { joiResolver } from '@hookform/resolvers/joi';
|
||||
import { HowToReg } from '@mui/icons-material';
|
||||
import { Google, HowToReg } from '@mui/icons-material';
|
||||
import { Button, TextField } from '@mui/material';
|
||||
import Joi from 'joi';
|
||||
import { Trans, useTranslation } from 'next-i18next';
|
||||
import { GoogleLoginResponse, GoogleLoginResponseOffline, useGoogleLogin } from 'react-google-login';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { useMutation } from 'react-query';
|
||||
|
||||
import BaseModal from '@/components/shared/BaseModal';
|
||||
import { register as registerUser, RegisterParams } from '@/services/auth';
|
||||
import { loginWithGoogle, LoginWithGoogleParams, register as registerUser, RegisterParams } from '@/services/auth';
|
||||
import { ServerError } from '@/services/axios';
|
||||
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
||||
import { setModalState } from '@/store/modal/modalSlice';
|
||||
|
@ -56,6 +58,19 @@ const RegisterModal: React.FC = () => {
|
|||
|
||||
const { mutateAsync, isLoading } = useMutation<void, ServerError, RegisterParams>(registerUser);
|
||||
|
||||
const { mutateAsync: loginWithGoogleMutation } = useMutation<void, ServerError, LoginWithGoogleParams>(
|
||||
loginWithGoogle
|
||||
);
|
||||
|
||||
const { signIn } = useGoogleLogin({
|
||||
clientId: env('GOOGLE_CLIENT_ID'),
|
||||
onSuccess: async (response: GoogleLoginResponse | GoogleLoginResponseOffline) => {
|
||||
await loginWithGoogleMutation({ accessToken: (response as GoogleLoginResponse).accessToken });
|
||||
|
||||
handleClose();
|
||||
},
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
dispatch(setModalState({ modal: 'auth.register', state: { open: false } }));
|
||||
reset();
|
||||
|
@ -63,7 +78,6 @@ const RegisterModal: React.FC = () => {
|
|||
|
||||
const onSubmit = async ({ name, username, email, password }: FormData) => {
|
||||
await mutateAsync({ name, username, email, password });
|
||||
|
||||
handleClose();
|
||||
};
|
||||
|
||||
|
@ -72,6 +86,10 @@ const RegisterModal: React.FC = () => {
|
|||
dispatch(setModalState({ modal: 'auth.login', state: { open: true } }));
|
||||
};
|
||||
|
||||
const handleLoginWithGoogle = () => {
|
||||
signIn();
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseModal
|
||||
icon={<HowToReg />}
|
||||
|
@ -79,9 +97,21 @@ const RegisterModal: React.FC = () => {
|
|||
heading={t('modals.auth.register.heading')}
|
||||
handleClose={handleClose}
|
||||
footerChildren={
|
||||
<Button type="submit" onClick={handleSubmit(onSubmit)} disabled={isLoading}>
|
||||
{t('modals.auth.register.actions.register')}
|
||||
</Button>
|
||||
<>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="outlined"
|
||||
disabled={isLoading}
|
||||
startIcon={<Google />}
|
||||
onClick={handleLoginWithGoogle}
|
||||
>
|
||||
{t('modals.auth.register.actions.google')}
|
||||
</Button>
|
||||
|
||||
<Button type="submit" onClick={handleSubmit(onSubmit)} disabled={isLoading}>
|
||||
{t('modals.auth.register.actions.register')}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<p>{t('modals.auth.register.body')}</p>
|
||||
|
|
|
@ -45,10 +45,10 @@ const ProfileModal: React.FC = () => {
|
|||
const isEditMode = useMemo(() => !!item, [item]);
|
||||
|
||||
const addText = t('builder.common.actions.add', {
|
||||
section: t('builder.leftSidebar.sections.profiles.heading', { count: 1 }),
|
||||
token: t('builder.leftSidebar.sections.profiles.heading', { count: 1 }),
|
||||
});
|
||||
const editText = t('builder.common.actions.edit', {
|
||||
section: t('builder.leftSidebar.sections.profiles.heading', { count: 1 }),
|
||||
token: t('builder.leftSidebar.sections.profiles.heading', { count: 1 }),
|
||||
});
|
||||
|
||||
const { reset, control, handleSubmit } = useForm<FormData>({
|
||||
|
|
|
@ -147,18 +147,6 @@ const Home: NextPage = () => {
|
|||
<h6>{t('landing.links.heading')}</h6>
|
||||
|
||||
<div>
|
||||
<a href={GITHUB_URL} target="_blank" rel="noreferrer">
|
||||
<Button variant="text" startIcon={<LinkIcon />}>
|
||||
{t('landing.links.links.github')}
|
||||
</Button>
|
||||
</a>
|
||||
|
||||
<a href={DONATION_URL} target="_blank" rel="noreferrer">
|
||||
<Button variant="text" startIcon={<LinkIcon />}>
|
||||
{t('landing.links.links.donate')}
|
||||
</Button>
|
||||
</a>
|
||||
|
||||
<Link href="/meta/privacy" passHref>
|
||||
<Button variant="text" startIcon={<LinkIcon />}>
|
||||
{t('landing.links.links.privacy')}
|
||||
|
@ -170,6 +158,18 @@ const Home: NextPage = () => {
|
|||
{t('landing.links.links.service')}
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<a href={GITHUB_URL} target="_blank" rel="noreferrer">
|
||||
<Button variant="text" startIcon={<LinkIcon />}>
|
||||
{t('landing.links.links.github')}
|
||||
</Button>
|
||||
</a>
|
||||
|
||||
<a href={DONATION_URL} target="_blank" rel="noreferrer">
|
||||
<Button variant="text" startIcon={<LinkIcon />}>
|
||||
{t('landing.links.links.donate')}
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"login": {
|
||||
"actions": {
|
||||
"login": "Login",
|
||||
"login-google": "Login with Google"
|
||||
"google": "Login with Google"
|
||||
},
|
||||
"body": "Please enter your username and password associated with your account to login and access, manage and share your resumes.",
|
||||
"form": {
|
||||
|
@ -34,7 +34,8 @@
|
|||
},
|
||||
"register": {
|
||||
"actions": {
|
||||
"register": "Register"
|
||||
"register": "Register",
|
||||
"google": "Register with Google"
|
||||
},
|
||||
"body": "Please enter your personal information to create an account.",
|
||||
"form": {
|
||||
|
@ -112,7 +113,7 @@
|
|||
"actions": {
|
||||
"upload-json": "Upload JSON"
|
||||
},
|
||||
"body": "If you have a JSON that was exported with the current version of Reactive Resume, you can import it back here to get an editable version again.",
|
||||
"body": "If you have a JSON that was exported with the current version of Reactive Resume, you can import it back here to get an editable version again. Previous versions of Reactive Resume are unfortunately not supported at the moment.",
|
||||
"heading": "Import From Reactive Resume"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "reactive-resume",
|
||||
"version": "3.0.0-beta.2",
|
||||
"version": "3.0.0-beta.4",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"schema",
|
||||
|
|
|
@ -188,6 +188,7 @@ importers:
|
|||
'@nestjs/schedule': ^1.0.2
|
||||
'@nestjs/schematics': ^8.0.8
|
||||
'@nestjs/serve-static': ^2.2.2
|
||||
'@nestjs/terminus': ^8.0.4
|
||||
'@nestjs/typeorm': ^8.0.3
|
||||
'@reactive-resume/schema': workspace:*
|
||||
'@sendgrid/mail': ^7.6.1
|
||||
|
@ -240,6 +241,7 @@ importers:
|
|||
'@nestjs/platform-express': 8.4.0_31e7036b193d6d3c9cadab18cbb4af84
|
||||
'@nestjs/schedule': 1.0.2_1ce925e2290a1cea9e3700e8a60baeb5
|
||||
'@nestjs/serve-static': 2.2.2_31e7036b193d6d3c9cadab18cbb4af84
|
||||
'@nestjs/terminus': 8.0.4_44ad68f90df6df0ad3d3ea7593df94f3
|
||||
'@nestjs/typeorm': 8.0.3_d17aee4fbe284d59b832be708c000fe0
|
||||
'@sendgrid/mail': 7.6.1
|
||||
'@types/passport': 1.0.7
|
||||
|
@ -1413,6 +1415,21 @@ packages:
|
|||
path-to-regexp: 0.1.7
|
||||
dev: false
|
||||
|
||||
/@nestjs/terminus/8.0.4_44ad68f90df6df0ad3d3ea7593df94f3:
|
||||
resolution: {integrity: sha512-KjeY7VLt0Az6pA2wO67nkL1QbE68yBb+FLZ7+aa+C/g/IKoDR668nqSuFzJarBrnFBTGEwDD09BwsgqkmymrbQ==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': 8.x
|
||||
'@nestjs/core': 8.x
|
||||
reflect-metadata: 0.1.x
|
||||
rxjs: 7.x
|
||||
dependencies:
|
||||
'@nestjs/common': 8.4.0_add13df2cdecb4b62cd3f7664ea82e18
|
||||
'@nestjs/core': 8.4.0_ded80713f50ec1c99e9ba95af1765d72
|
||||
check-disk-space: 3.1.0
|
||||
reflect-metadata: 0.1.13
|
||||
rxjs: 7.5.5
|
||||
dev: false
|
||||
|
||||
/@nestjs/typeorm/8.0.3_d17aee4fbe284d59b832be708c000fe0:
|
||||
resolution: {integrity: sha512-tf9rTXP6LeFInkwd+tktQhtLRsKp4RRYImprqT8gcHcJDx+xMP1IygnXELOKwF5vo2/mnhrGtBlRQ/iiS6170g==}
|
||||
peerDependencies:
|
||||
|
@ -2808,6 +2825,11 @@ packages:
|
|||
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
|
||||
dev: true
|
||||
|
||||
/check-disk-space/3.1.0:
|
||||
resolution: {integrity: sha512-4L3WVw4uPaBJocwnxTCWTTHc8mNu080pjCVBhZeWFdnaQBAremLHpJ1H90G+uEA0rJcW43fghYMsLBXID9X4Zg==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/chokidar/3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"@nestjs/platform-express": "^8.4.0",
|
||||
"@nestjs/schedule": "^1.0.2",
|
||||
"@nestjs/serve-static": "^2.2.2",
|
||||
"@nestjs/terminus": "^8.0.4",
|
||||
"@nestjs/typeorm": "^8.0.3",
|
||||
"@sendgrid/mail": "^7.6.1",
|
||||
"@types/passport": "^1.0.7",
|
||||
|
|
|
@ -9,6 +9,7 @@ import { ConfigModule } from './config/config.module';
|
|||
import { DatabaseModule } from './database/database.module';
|
||||
import { HttpExceptionFilter } from './filters/http-exception.filter';
|
||||
import { FontsModule } from './fonts/fonts.module';
|
||||
import { HealthModule } from './health/health.module';
|
||||
import { IntegrationsModule } from './integrations/integrations.module';
|
||||
import { MailModule } from './mail/mail.module';
|
||||
import { PrinterModule } from './printer/printer.module';
|
||||
|
@ -32,6 +33,7 @@ import { UsersModule } from './users/users.module';
|
|||
FontsModule,
|
||||
IntegrationsModule,
|
||||
PrinterModule,
|
||||
HealthModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import { Controller, Get } from '@nestjs/common';
|
||||
import { HealthCheck, HealthCheckService, HttpHealthIndicator, TypeOrmHealthIndicator } from '@nestjs/terminus';
|
||||
|
||||
@Controller('health')
|
||||
export class HealthController {
|
||||
constructor(
|
||||
private health: HealthCheckService,
|
||||
private db: TypeOrmHealthIndicator,
|
||||
private http: HttpHealthIndicator
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@HealthCheck()
|
||||
check() {
|
||||
return this.health.check([
|
||||
() => this.db.pingCheck('database'),
|
||||
() => this.http.pingCheck('app', 'https://rxresu.me'),
|
||||
() => this.http.pingCheck('docs', 'https://beta.rxresu.me'),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import { HttpModule } from '@nestjs/axios';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
|
||||
import { HealthController } from './health.controller';
|
||||
|
||||
@Module({
|
||||
imports: [HttpModule, TerminusModule],
|
||||
controllers: [HealthController],
|
||||
})
|
||||
export class HealthModule {}
|
Loading…
Reference in New Issue