Skip to content

Commit

Permalink
fixes and changes according to dev review
Browse files Browse the repository at this point in the history
  • Loading branch information
BartoszButrymSoftwareMill committed Jan 14, 2025
1 parent 0f0d2fc commit cfc294d
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 3,341 deletions.
11 changes: 10 additions & 1 deletion ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ You will also see any lint errors in the console.

Before running `yarn start`, make sure to run `sbt "backend/generateOpenAPIDescription"` in the project's root directory. This command will generate the `<project_root>/backend/target/openapi.yaml` file.

API types in `./src/api-client` directory (in `openapi.d.ts` file) are generated upon UI application start (`yarn start`), based on the `openapi.yaml` contents. A file watch is engaged, re-generating types on each change to the `<project_root>/backend/target/openapi.yaml` file.
Type-safe React Query hooks are generated upon UI application start (`yarn start`), based on the `openapi.yaml` contents.

These files are:

- `src/api/{namespace}Fetcher.ts` - defines a function that will make requests to your API.
- `src/api/{namespace}Context.ts` - the context that provides `{namespace}Fetcher` to other components.
- `src/api/{namespace}Components.ts` - generated React Query components (if you selected React Query as part of initialization).
- `src/api/{namespace}Schemas.ts` - the generated Typescript types from the provided Open API schemas.

A file watch is engaged, re-generating types on each change to the `<project_root>/backend/target/openapi.yaml` file.

### `yarn test`

Expand Down
6 changes: 1 addition & 5 deletions ui/openapi-codegen.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
generateFetchers,
generateSchemaTypes,
generateReactQueryComponents,
} from "@openapi-codegen/typescript";
import { generateSchemaTypes, generateReactQueryComponents } from "@openapi-codegen/typescript";
import { defineConfig } from "@openapi-codegen/cli";
export default defineConfig({
apiFile: {
Expand Down
9 changes: 2 additions & 7 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"proxy": "http://localhost:8080",
"engines": {
"node": ">=16"
"node": ">=22"
},
"dependencies": {
"@tanstack/react-query": "^5.62.7",
Expand All @@ -19,12 +19,10 @@
"@types/react-router-bootstrap": "^0.26.6",
"@types/react-router-dom": "^5.3.3",
"@types/yup": "^0.32.0",
"axios": "0.27.2",
"bootstrap": "^5.3.2",
"eslint-config-prettier": "^9.1.0",
"formik": "^2.4.5",
"immer": "^10.0.3",
"openapicmd": "^2.4.0",
"prettier": "^3.1.1",
"react": "^18.2.0",
"react-bootstrap": "^2.9.2",
Expand All @@ -33,7 +31,7 @@
"react-router-bootstrap": "^0.26.2",
"react-router-dom": "^6.21.1",
"react-scripts": "^5.0.1",
"typescript": "4.9.5",
"typescript": "5.7.3",
"yup": "^1.3.3"
},
"scripts": {
Expand All @@ -60,9 +58,6 @@
"src/**/*.{ts,tsx}",
"!src/index.tsx",
"!src/serviceWorker.ts"
],
"transformIgnorePatterns": [
"node_modules/(?!(axios)/)"
]
},
"browserslist": {
Expand Down
6 changes: 3 additions & 3 deletions ui/src/components/FeedbackButton/FeedbackButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import { ReactElement } from "react";
import Button, { ButtonProps } from "react-bootstrap/Button";
import Spinner from "react-bootstrap/Spinner";
import Form from "react-bootstrap/Form";
Expand All @@ -15,13 +15,13 @@ interface FeedbackButtonProps extends ButtonProps {
successLabel?: string;
}

export const FeedbackButton = <TMutationData,>({
export const FeedbackButton = ({
mutation,
label,
Icon,
successLabel = "Success",
...buttonProps
}: FeedbackButtonProps): React.ReactElement => {
}: FeedbackButtonProps): ReactElement => {
useFormikValuesChanged(() => {
!mutation.isIdle && mutation.reset();
});
Expand Down
5 changes: 1 addition & 4 deletions ui/src/main/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import React from "react";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Spinner from "react-bootstrap/Spinner";
import { useGetAdminVersion } from "api/apiComponents";

type Props = {};

export const Footer: React.FC<Props> = ({}) => {
export const Footer = () => {
const mutation = useGetAdminVersion({});

return (
Expand Down
8 changes: 3 additions & 5 deletions ui/src/main/Top/Top.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect } from "react";
import { useEffect, useContext } from "react";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import Container from "react-bootstrap/Container";
Expand All @@ -7,13 +7,11 @@ import { BiPowerOff, BiHappy } from "react-icons/bi";
import { UserContext } from "contexts";
import { usePostUserLogout } from "api/apiComponents";

type Props = {};

export const Top: React.FC<Props> = ({}) => {
export const Top = () => {
const {
state: { user, loggedIn, apiKey },
dispatch,
} = React.useContext(UserContext);
} = useContext(UserContext);

const { mutateAsync: logout, isSuccess } = usePostUserLogout();

Expand Down
4 changes: 4 additions & 0 deletions ui/src/pages/Login/Login.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ test("handles login success", async () => {
isSuccess: true,
isError: false,
error: "",
onSuccess: dispatch({
type: "SET_API_KEY",
apiKey: "test-api-key",
}),
});

renderWithClient(
Expand Down
21 changes: 8 additions & 13 deletions ui/src/pages/Login/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useEffect } from "react";
import { useContext, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import Form from "react-bootstrap/Form";
import { BiLogInCircle } from "react-icons/bi";
Expand All @@ -15,26 +15,21 @@ const validationSchema = Yup.object({

export type LoginParams = Yup.InferType<typeof validationSchema>;

type Props = {};

export const Login: React.FC<Props> = ({}) => {
export const Login = () => {
const {
dispatch,
state: { loggedIn },
} = useContext(UserContext);

const navigate = useNavigate();

const mutation = usePostUserLogin();
const { isSuccess, data } = mutation;
const login = mutation.mutateAsync;

useEffect(() => {
if (isSuccess) {
const { apiKey } = data;
const mutation = usePostUserLogin({
onSuccess: ({ apiKey }) => {
dispatch({ type: "SET_API_KEY", apiKey });
}
}, [isSuccess, dispatch]);
},
});

const login = mutation.mutateAsync;

useEffect(() => {
if (loggedIn) navigate("/main");
Expand Down
16 changes: 7 additions & 9 deletions ui/src/pages/Profile/components/PasswordDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import { useContext, useEffect } from "react";
import Form from "react-bootstrap/Form";
import Container from "react-bootstrap/Container";
import Col from "react-bootstrap/Col";
Expand All @@ -20,25 +20,23 @@ const validationSchema = Yup.object({

type PasswordDetailsParams = Yup.InferType<typeof validationSchema>;

type Props = {};

export const PasswordDetails: React.FC<Props> = ({}) => {
export const PasswordDetails = () => {
const {
state: { user, loggedIn, apiKey },
state: { apiKey },
dispatch,
} = React.useContext(UserContext);
} = useContext(UserContext);

const mutation = usePostUserChangepassword();
const { isSuccess, data } = mutation;

React.useEffect(() => {
useEffect(() => {
if (isSuccess) {
const { apiKey } = data;
dispatch({ type: "SET_API_KEY", apiKey });
}
}, [isSuccess, data]);
}, [isSuccess, data, dispatch]);

React.useEffect(() => {
useEffect(() => {
localStorage.setItem("apiKey", apiKey || "");
}, [apiKey]);

Expand Down
12 changes: 5 additions & 7 deletions ui/src/pages/Profile/components/ProfileDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import { useContext, useEffect } from "react";
import Form from "react-bootstrap/Form";
import Container from "react-bootstrap/Container";
import Col from "react-bootstrap/Col";
Expand All @@ -17,22 +17,20 @@ const validationSchema = Yup.object({

export type ProfileDetailsParams = Yup.InferType<typeof validationSchema>;

type Props = {};

export const ProfileDetails: React.FC<Props> = ({}) => {
export const ProfileDetails = () => {
const {
dispatch,
state: { apiKey, user },
} = React.useContext(UserContext);
} = useContext(UserContext);

const mutation = usePostUser();
const { data, isSuccess } = mutation;

React.useEffect(() => {
useEffect(() => {
if (isSuccess) {
dispatch({ type: "UPDATE_USER_DATA", user: data });
}
}, [isSuccess, dispatch]);
}, [isSuccess, dispatch, data]);

return (
<Container className="py-5">
Expand Down
5 changes: 1 addition & 4 deletions ui/src/pages/RecoverLostPassword/RecoverLostPassword.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from "react";
import Form from "react-bootstrap/Form";
import { BiReset } from "react-icons/bi";
import { Formik, Form as FormikForm } from "formik";
Expand All @@ -12,9 +11,7 @@ const validationSchema = Yup.object({

export type RecoverLostPasswordParams = Yup.InferType<typeof validationSchema>;

type Props = {};

export const RecoverLostPassword: React.FC<Props> = ({}) => {
export const RecoverLostPassword = () => {
const mutation = usePostPasswordresetForgot();

return (
Expand Down
14 changes: 6 additions & 8 deletions ui/src/pages/Register/Register.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import { useContext, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import Form from "react-bootstrap/Form";
import { BiUserPlus } from "react-icons/bi";
Expand All @@ -19,27 +19,25 @@ const validationSchema = Yup.object({

type RegisterParams = Yup.InferType<typeof validationSchema>;

type Props = {};

export const Register: React.FC<Props> = ({}) => {
export const Register = () => {
const {
dispatch,
state: { loggedIn },
} = React.useContext(UserContext);
} = useContext(UserContext);

const navigate = useNavigate();

const mutation = usePostUserRegister();
const { isSuccess, data } = mutation;

React.useEffect(() => {
useEffect(() => {
if (isSuccess) {
const { apiKey } = data;
dispatch({ type: "SET_API_KEY", apiKey });
}
}, [isSuccess, dispatch]);
}, [isSuccess, dispatch, data]);

React.useEffect(() => {
useEffect(() => {
if (loggedIn) navigate("/main");
}, [loggedIn, navigate]);

Expand Down
Loading

0 comments on commit cfc294d

Please sign in to comment.