Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/my organization #1198

Merged
merged 12 commits into from
Apr 11, 2024
Merged
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"flowbite-typography": "^1.0.3",
"formik": "^2.4.5",
"lodash": "^4.17.21",
"qrcode.react": "^3.1.0",
"react": "^18.2.0",
"react-content-loader": "^7.0.0",
"react-dom": "^18.2.0",
Expand Down
9 changes: 8 additions & 1 deletion src/renderer/api/cadt/v1/governance/governance.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ const governanceApi = cadtApi.injectEndpoints({
});
},
}),

getDefaultOrgList: builder.query<{ orgUid: string }[], void>({
query: () => ({
url: `/v1/governance/meta/orgList`,
method: 'GET',
}),
}),
}),
});

export const { useGetGlossaryQuery } = governanceApi;
export const { useGetGlossaryQuery, useGetDefaultOrgListQuery } = governanceApi;
78 changes: 67 additions & 11 deletions src/renderer/api/cadt/v1/organizations/organizations.api.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import {cadtApi, organizationsTag} from "../";
import { cadtApi, organizationsTag } from '../';
// @ts-ignore
import {BaseQueryResult} from "@reduxjs/toolkit/dist/query/baseQueryTypes";
import {Organization} from "@/schemas/Organization.schema";
import { BaseQueryResult } from '@reduxjs/toolkit/dist/query/baseQueryTypes';
import { Organization } from '@/schemas/Organization.schema';

interface GetOrgnaizationsMapResponse {
[index: string]: Organization
[index: string]: Organization;
}

interface CreateOrganizationResponse {
message: string;
orgId: string;
}

const organizationsApi = cadtApi.injectEndpoints({
Expand All @@ -15,9 +20,9 @@ const organizationsApi = cadtApi.injectEndpoints({
method: 'GET',
}),
providesTags: [organizationsTag],
transformResponse(baseQueryReturnValue: BaseQueryResult<Organization[]>): Organization[]{
transformResponse(baseQueryReturnValue: BaseQueryResult<Organization[]>): Organization[] {
return Object.values(baseQueryReturnValue);
}
},
}),

getOrganizationsMap: builder.query<GetOrgnaizationsMapResponse, void | null>({
Expand All @@ -26,12 +31,63 @@ const organizationsApi = cadtApi.injectEndpoints({
method: 'GET',
}),
providesTags: [organizationsTag],
})
})
});
}),

createOrganization: builder.mutation<CreateOrganizationResponse, string>({
query: (orgName: string) => {
const formData: FormData = new FormData();
formData.append('name', orgName);

return {
url: `/v1/organizations/create`,
method: 'POST',
body: formData,
};
},
invalidatesTags: [organizationsTag],
}),

importOrganization: builder.mutation<CreateOrganizationResponse, string>({
query: (orgUid: string) => ({
url: `/v1/organizations`,
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: { orgUid },
}),
invalidatesTags: [organizationsTag],
}),

deleteOrganization: builder.mutation<any, string>({
query: (orgUid: string) => ({
url: `/v1/organizations`,
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: { orgUid },
}),
invalidatesTags: [organizationsTag],
}),

editOrganization: builder.mutation<any, { orgUid: string; orgName: string }>({
query: ({ orgUid, orgName }) => {
const formData: FormData = new FormData();
formData.append('orgUid', orgUid);
formData.append('name', orgName);

return {
url: `/v1/organizations/edit`,
method: 'PUT',
body: formData,
};
},
}),
}),
});

export const {
useGetOrganizationsListQuery,
useGetOrganizationsMapQuery
} = organizationsApi;
useGetOrganizationsMapQuery,
useCreateOrganizationMutation,
useImportOrganizationMutation,
useDeleteOrganizationMutation,
useEditOrganizationMutation,
} = organizationsApi;
18 changes: 10 additions & 8 deletions src/renderer/components/blocks/buttons/QueryRefetchButton.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import React from "react";
import {Button} from "@/components";
import {FormattedMessage} from "react-intl";
import React from 'react';
import { Button } from '@/components';
import { FormattedMessage } from 'react-intl';

interface QueryRefetchButtonProps {
onRefetch: () => void;
}

const QueryRefetchButton: React.FC<QueryRefetchButtonProps> = ({onRefetch}) => {
const QueryRefetchButton: React.FC<QueryRefetchButtonProps> = ({ onRefetch }) => {
return (
<Button
onClick={() => {onRefetch()}}
onClick={() => {
onRefetch();
}}
>
<FormattedMessage id={"unable-to-load-click-to-retry"} />
<FormattedMessage id="unable-to-load-click-to-retry" />
</Button>
);
}
};

export {QueryRefetchButton};
export { QueryRefetchButton };
5 changes: 2 additions & 3 deletions src/renderer/components/blocks/forms/ConnectForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React, { useCallback } from 'react';
import { noop } from 'lodash';
import { ErrorMessage, Field, Form, Formik } from 'formik';
import * as yup from 'yup';
import { FloatingLabel, HelperText, Spacer, FormButton } from '@/components';
import { FloatingLabel, FormButton, HelperText, Spacer } from '@/components';
import { Alert } from 'flowbite-react';
import { IntlShape, useIntl, FormattedMessage } from 'react-intl';
import { FormattedMessage, IntlShape, useIntl } from 'react-intl';

const validationSchema = yup.object({
apiHost: yup
Expand Down Expand Up @@ -87,7 +87,6 @@ const ConnectForm: React.FC<FormProps> = ({ onSubmit, hasServerError, onClearErr
type="text"
{...field}
onChange={(event) => handleChange(event, field)}
ccccccrjflurktedcrhvrbtgldlgnjicvleikebbgnju
/>
)}
</Field>
Expand Down
54 changes: 54 additions & 0 deletions src/renderer/components/blocks/forms/CreateOrganizationForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useCallback } from 'react';
import { ErrorMessage, Field, Form, Formik } from 'formik';
import * as yup from 'yup';
import { Button, FloatingLabel, Spinner } from '@/components';
import { IntlShape, useIntl } from 'react-intl';

const validationSchema = yup.object({
name: yup.string().required('Name is required'),
});

interface FormProps {
onSubmit: (orgName: string) => Promise<any>;
}

const CreateOrganizationForm: React.FC<FormProps> = ({ onSubmit }) => {
const intl: IntlShape = useIntl();

const handleSubmit = useCallback(
async (values: { name: string }, { setSubmitting }) => {
await onSubmit(values.name);
setSubmitting(false);
},
[onSubmit],
); // Include onSuccess in the dependencies array

return (
<Formik initialValues={{ name: '' }} validationSchema={validationSchema} onSubmit={handleSubmit}>
{({ errors, touched, isSubmitting }) => (
<Form>
<div className="mb-4">
<Field name="name">
{({ field }) => (
<FloatingLabel
id="name"
label={intl.formatMessage({ id: 'organization-name' })}
color={errors.name && touched.name && 'error'}
variant="outlined"
type="text"
{...field}
/>
)}
</Field>
{touched.name && <ErrorMessage name="name" component="div" className="text-red-600" />}
</div>
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? <Spinner size="sm" light={true} /> : 'Submit'}
</Button>
</Form>
)}
</Formik>
);
};

export { CreateOrganizationForm };
87 changes: 87 additions & 0 deletions src/renderer/components/blocks/forms/EditOrganizationForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React, { useCallback } from 'react';
import { ErrorMessage, Field, Form, Formik } from 'formik';
import * as yup from 'yup';
import { Button, FormButton, TextInput } from '@/components';
import { FormattedMessage } from 'react-intl';
import { Organization } from '@/schemas/Organization.schema';

const validationSchema = yup.object({
organizationName: yup.string().required('The organization name must be at least 3 characters').min(3),
});

interface FormProps {
myOrganization: Organization;
onSubmit: (organizationName: string) => Promise<any>;
onCancel: () => void;
}

const EditOrganizationForm: React.FC<FormProps> = ({ myOrganization, onSubmit, onCancel }: FormProps) => {
const handleSubmit = useCallback(
async (values: { organizationName: string }, { setSubmitting }) => {
await onSubmit(values.organizationName);
setSubmitting(false);
},
[onSubmit],
);

const handleChange = useCallback((event, field) => {
field.onChange(event); // Call Formik's original onChange
}, []);

return (
<Formik
initialValues={{ organizationName: myOrganization.name }}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{({ errors, touched, isSubmitting }) => (
<Form>
<div className="mb-4">
<Field name="organizationName">
{({ field }) => (
<div className="flex justify-start align-middle">
<div>
<p className="font-bold text-left text-gray-700 dark:text-gray-400 mr-4">
<FormattedMessage id="name" />
</p>
</div>
<TextInput
className="w-3/5 mb-2"
id="organizationName"
color={errors.organizationName && touched.organizationName && 'failure'}
variant="outlined"
required
type="text"
{...field}
onChange={(event) => handleChange(event, field)}
/>
</div>
)}
</Field>
{touched.organizationName && (
<ErrorMessage name="organizationName" component="div" className="text-red-600" />
)}
<div className="flex justify-start">
<p className="font-bold text-left text-gray-700 dark:text-gray-400 mr-4">
<FormattedMessage id="orguid" />
</p>
<p className="font-normal text-left text-gray-700 dark:text-gray-400 inline-block">
{myOrganization.orgUid}
</p>
</div>
</div>
<div className="space-x-2 flex">
<FormButton isSubmitting={isSubmitting} formikErrors={errors}>
<FormattedMessage id="save" />
</FormButton>
<Button onClick={onCancel} color="gray">
<FormattedMessage id="cancel" />
</Button>
</div>
</Form>
)}
</Formik>
);
};

export { EditOrganizationForm };
56 changes: 56 additions & 0 deletions src/renderer/components/blocks/forms/ImportOrganizationForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { useCallback } from 'react';
import { ErrorMessage, Field, Form, Formik } from 'formik';
import * as yup from 'yup';
import { Button, FloatingLabel, Spinner } from '@/components';
import { IntlShape, useIntl } from 'react-intl';

const validationSchema = yup.object({
orgUid: yup.string().length(64).required('OrgUid is required'),
});

interface FormProps {
onSubmit: (orgUid: string) => Promise<any>;
}

const ImportOrganizationForm: React.FC<FormProps> = ({ onSubmit }) => {
const intl: IntlShape = useIntl();

const handleSubmit = useCallback(
async (values: { orgUid: string }, { setSubmitting }) => {
await onSubmit(values.orgUid);
setSubmitting(false);
},
[onSubmit],
); // Include onSuccess in the dependencies array

return (
<>
<Formik initialValues={{ orgUid: '' }} validationSchema={validationSchema} onSubmit={handleSubmit}>
{({ errors, touched, isSubmitting }) => (
<Form>
<div className="mb-4">
<Field name="orgUid">
{({ field }) => (
<FloatingLabel
id="name"
label={intl.formatMessage({ id: 'organization-orguid' })}
color={errors.orgUid && touched.orgUid && 'error'}
variant="outlined"
type="text"
{...field}
/>
)}
</Field>
{touched.orgUid && <ErrorMessage name="orgUid" component="div" className="text-red-600" />}
</div>
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? <Spinner size="sm" light={true} /> : 'Submit'}
</Button>
</Form>
)}
</Formik>
</>
);
};

export { ImportOrganizationForm };
Loading
Loading