Skip to content

Commit

Permalink
Merge pull request #4236 from bcgov/refactor/4227
Browse files Browse the repository at this point in the history
refactor(4227): replace textarea and multi-select with common components
  • Loading branch information
junminahn authored Nov 13, 2024
2 parents f862f8e + d60eb1a commit 28fbe19
Show file tree
Hide file tree
Showing 18 changed files with 160 additions and 227 deletions.
2 changes: 1 addition & 1 deletion app/app/api-account/ApiAccountInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useAppState } from '@/states/global';
import { ApiAccount } from './types';

export default function ApiAccountInfo({ apiAccount }: { apiAccount: ApiAccount }) {
const [appState, appSnap] = useAppState();
const [, appSnap] = useAppState();

const privateProductsEndpoint = `${appSnap.info.BASE_URL}/api/v1/private-cloud/products`;
const publicProductsEndpoint = `${appSnap.info.BASE_URL}/api/v1/public-cloud/products`;
Expand Down
15 changes: 11 additions & 4 deletions app/app/team-api-accounts/AccountMembers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import { Button } from '@mantine/core';
import { IconPlus } from '@tabler/icons-react';
import _get from 'lodash-es/get';
import { useFieldArray, useFormContext } from 'react-hook-form';
import Label from '@/components/generic/Label';
import { cn } from '@/utils';

export default function AccountMembers({ disabled = false }: { disabled?: boolean }) {
export default function AccountMembers({
className = '',
disabled = false,
}: {
className?: string;
disabled?: boolean;
}) {
const {
register,
control,
Expand All @@ -22,8 +29,8 @@ export default function AccountMembers({ disabled = false }: { disabled?: boolea
const values = getValues();

return (
<>
<div className="block text-sm font-bold leading-6 text-gray-900 mt-2 mb-1">Member Emails</div>
<div className={cn(className)}>
<Label htmlFor="member-email">Member Email</Label>
<ul>
{fields.map((item, index) => {
const itemKey = `users.${index}.email`;
Expand Down Expand Up @@ -60,6 +67,6 @@ export default function AccountMembers({ disabled = false }: { disabled?: boolea
Add New
</Button>
)}
</>
</div>
);
}
33 changes: 0 additions & 33 deletions app/app/team-api-accounts/AccountRoles.tsx

This file was deleted.

12 changes: 9 additions & 3 deletions app/app/team-api-accounts/createAccountModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import _get from 'lodash-es/get';
import { useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import HookFormTextInput from '@/components/generic/input/HookFormTextInput';
import HookFormMultiSelect from '@/components/generic/select/HookFormMultiSelect';
import { createModal } from '@/core/modal';
import { listKeycloakAuthRoles, createKeycloakTeamApiAccount } from '@/services/backend/keycloak';
import { teamApiAccountSchema, TeamApiAccount } from '@/validation-schemas/api-accounts';
import AccountMembers from './AccountMembers';
import AccountRoles from './AccountRoles';

interface ModalProps {}
interface ModalState {}
Expand Down Expand Up @@ -104,8 +104,14 @@ export const openCreateAccountModal = createModal<ModalProps, ModalState>({
})}
>
<HookFormTextInput label="Name" name="name" placeholder="Enter name..." required />
<AccountRoles allRoles={(authRoles ?? []).map((v) => v.name ?? '')} disabled={isServerError} />
<AccountMembers disabled={isServerError} />
<HookFormMultiSelect
name="roles"
label="API Account Roles"
data={(authRoles ?? []).map((v) => v.name ?? '')}
disabled={isServerError}
classNames={{ wrapper: 'mt-2' }}
/>
<AccountMembers disabled={isServerError} className="mt-2" />

<Divider my="md" />

Expand Down
11 changes: 8 additions & 3 deletions app/app/team-api-accounts/manageAccountModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import _get from 'lodash-es/get';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import HookFormTextInput from '@/components/generic/input/HookFormTextInput';
import HookFormMultiSelect from '@/components/generic/select/HookFormMultiSelect';
import { openConfirmModal } from '@/components/modal/confirm';
import { createModal } from '@/core/modal';
import {
Expand All @@ -19,7 +20,6 @@ import {
} from '@/services/backend/keycloak';
import { teamApiAccountSchema, TeamApiAccount } from '@/validation-schemas/api-accounts';
import AccountMembers from './AccountMembers';
import AccountRoles from './AccountRoles';

interface ModalProps {
name: string;
Expand Down Expand Up @@ -121,8 +121,13 @@ export const openManageAccountModal = createModal<ModalProps, ModalState>({
})}
>
<HookFormTextInput label="Name" name="name" placeholder="Enter name..." required />
<AccountRoles allRoles={(authRoles ?? []).map((v) => v.name ?? '')} />
<AccountMembers />
<HookFormMultiSelect
name="roles"
label="API Account Roles"
data={(authRoles ?? []).map((v) => v.name ?? '')}
classNames={{ wrapper: 'mt-2' }}
/>
<AccountMembers className="mt-2" />

<Divider my="md" />

Expand Down
27 changes: 22 additions & 5 deletions app/app/team-api-accounts/viewAccountModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { IconUser } from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query';
import _get from 'lodash-es/get';
import CopyableButton from '@/components/generic/button/CopyableButton';
import Label from '@/components/generic/Label';
import { createModal } from '@/core/modal';
import { listKeycloakTeamApiAccountUsers } from '@/services/backend/keycloak';
import { useAppState } from '@/states/global';

interface ModalProps {
clientUid: string;
Expand All @@ -24,6 +26,8 @@ export const openViewAccountModal = createModal<ModalProps, ModalState>({
title: 'View API Account',
},
Component: function ({ clientUid, clientId, clientSecret, name, roles, closeModal }) {
const [, appSnap] = useAppState();

const { data: users, isFetching: isUsersFetching } = useQuery({
queryKey: ['users', clientUid],
queryFn: () => listKeycloakTeamApiAccountUsers(clientUid),
Expand All @@ -32,10 +36,12 @@ export const openViewAccountModal = createModal<ModalProps, ModalState>({
return (
<Box pos="relative">
<LoadingOverlay visible={isUsersFetching} zIndex={1000} overlayProps={{ radius: 'sm', blur: 2 }} />
<div className="block text-sm font-bold leading-6 text-gray-900 mt-2 mb-1">Name</div>
<Label htmlFor="name">Name</Label>
<CopyableButton value={name}>{name}</CopyableButton>

<div className="block text-sm font-bold leading-6 text-gray-900 mt-2 mb-1">API Account Roles</div>
<Label htmlFor="account-roles" className="mt-2">
API Account Roles
</Label>
<InputBase component="div" multiline>
<Pill.Group>
{roles.map((role) => (
Expand All @@ -44,7 +50,9 @@ export const openViewAccountModal = createModal<ModalProps, ModalState>({
</Pill.Group>
</InputBase>

<div className="block text-sm font-bold leading-6 text-gray-900 mt-2 mb-1">Member Emails</div>
<Label htmlFor="member-email" className="mt-2">
Member Email
</Label>
<List icon={<IconUser />}>
{users && users.length > 0 ? (
(users ?? []).map((user) => (
Expand All @@ -57,12 +65,21 @@ export const openViewAccountModal = createModal<ModalProps, ModalState>({
)}
</List>

<div className="block text-sm font-bold leading-6 text-gray-900 mt-2 mb-1">Client ID</div>
<Label htmlFor="client-id" className="mt-2">
Client ID
</Label>
<CopyableButton value={clientId}>{clientId}</CopyableButton>

<div className="block text-sm font-bold leading-6 text-gray-900 mt-2 mb-1">Client Secret</div>
<Label htmlFor="client-secret" className="mt-2">
Client Secret
</Label>
<CopyableButton value={clientSecret}>*************************</CopyableButton>

<Label htmlFor="client-secret" className="mt-2">
Token Endpoint
</Label>
<CopyableButton value={appSnap.info.TOKEN_URL}>{appSnap.info.TOKEN_URL}</CopyableButton>

<Divider my="md" />

<Grid>
Expand Down
2 changes: 1 addition & 1 deletion app/components/form/Budget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export default function Budget({ disabled }: { disabled?: boolean }) {
/>
<span className="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"></span>
{Object.keys(errors.budget || {}).length > 0 && (
<p className={cn(errors.budget ? 'text-red-400' : '', 'mt-3 text-sm leading-6 text-gray-600')}>
<p className={cn(errors.budget ? 'text-red-400' : 'text-gray-600', 'mt-3 text-sm leading-6')}>
Budget is required, Every value should be no less than USD 50
</p>
)}
Expand Down
41 changes: 15 additions & 26 deletions app/components/form/ProjectDescriptionPrivate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import TemporaryProductCheckbox from '@/components/form/TemporaryProductCheckbox
import TemporaryProductCheckboxAdmin from '@/components/form/TemporaryProductCheckboxAdmin';
import ExternalLink from '@/components/generic/button/ExternalLink';
import MailLink from '@/components/generic/button/MailLink';
import HookFormTextarea from '@/components/generic/input/HookFormTextarea';
import FormSelect from '@/components/generic/select/FormSelect';
import HookFormSingleSelect from '@/components/generic/select/HookFormSingleSelect';
import { clusters, ministryOptions, privateCloudTeamEmail } from '@/constants';
Expand Down Expand Up @@ -82,33 +83,21 @@ export default function ProjectDescriptionPrivate({
{...register('name')}
/>
</div>
<p className={cn(errors.name ? 'text-red-400' : '', 'mt-3 text-sm leading-6 text-gray-600')}>
<p className={cn(errors.name ? 'text-red-400' : 'text-gray-600', 'mt-3 text-sm leading-6')}>
Please provide a descriptive product name with no acronyms
</p>
</div>
<div className="col-span-full">
<label htmlFor="description" className="block text-sm font-medium leading-6 text-gray-900">
Description
</label>
<div className="mt-2">
<textarea
disabled={disabled}
id="about"
placeholder="Enter a description..."
{...register('description')}
rows={3}
className={cn(
'block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6',
disabled
? 'disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-noneinvalid:border-pink-500 invalid:text-pink-600 focus:invalid:border-pink-500 focus:invalid:ring-pink-500'
: '',
)}
/>
</div>
<p className={cn(errors.description ? 'text-red-400' : '', 'mt-3 text-sm leading-6 text-gray-600')}>
Tell us more about your product
</p>
</div>

<HookFormTextarea
label="Description"
name="description"
placeholder="Enter description..."
required
error="Tell us more about your product"
classNames={{ wrapper: 'col-span-full' }}
disabled={disabled}
/>

<div className="sm:col-span-3 sm:mr-10">
<FormSelect
id="ministry"
Expand All @@ -118,7 +107,7 @@ export default function ProjectDescriptionPrivate({
selectProps={register('ministry')}
/>

<p className={cn(errors.ministry ? 'text-red-400' : '', 'mt-3 text-sm leading-6 text-gray-600')}>
<p className={cn(errors.ministry ? 'text-red-400' : 'text-gray-600', 'mt-3 text-sm leading-6')}>
Select the government ministry that this product belongs to
</p>
{['create', 'edit'].includes(mode) && <AGMinistryCheckBox disabled={disabled} />}
Expand All @@ -130,7 +119,7 @@ export default function ProjectDescriptionPrivate({
disabled={disabled || clusterDisabled}
data={[{ label: 'Select Hosting tier', value: '' }, ...clustersList.map((v) => ({ label: v, value: v }))]}
/>
<p className={cn(errors.cluster ? 'text-red-400' : '', 'mt-3 text-sm leading-6 text-gray-600')}>
<p className={cn(errors.cluster ? 'text-red-400' : 'text-gray-600', 'mt-3 text-sm leading-6')}>
{session?.isAdmin
? 'Select your hosting tier, select CLAB or KLAB for testing purposes. Read more about hosting tiers '
: 'Select your hosting tier. Read more about hosting tiers '}
Expand Down
Loading

0 comments on commit 28fbe19

Please sign in to comment.