From 2ba04ac2a20a00e54de3b1e5d6e54f7d86e3a16e Mon Sep 17 00:00:00 2001 From: JanhaviAlekar Date: Fri, 19 Jul 2024 02:58:30 +0530 Subject: [PATCH 1/9] Adding environment filter in Infrastructure selection modal Signed-off-by: JanhaviAlekar --- ...netesChaosInfrastructureReferenceField.tsx | 26 ++- chaoscenter/web/src/strings/strings.en.yaml | 1 + chaoscenter/web/src/strings/types.ts | 1 + ...osInfrastructureReferenceField.module.scss | 42 +++- ...rastructureReferenceField.module.scss.d.ts | 5 + .../ChaosInfrastructureReferenceField.tsx | 214 ++++++++++++++---- 6 files changed, 234 insertions(+), 55 deletions(-) diff --git a/chaoscenter/web/src/controllers/KubernetesChaosInfrastructureReferenceField/KubernetesChaosInfrastructureReferenceField.tsx b/chaoscenter/web/src/controllers/KubernetesChaosInfrastructureReferenceField/KubernetesChaosInfrastructureReferenceField.tsx index f7fe8c48d04..0256052e7d7 100644 --- a/chaoscenter/web/src/controllers/KubernetesChaosInfrastructureReferenceField/KubernetesChaosInfrastructureReferenceField.tsx +++ b/chaoscenter/web/src/controllers/KubernetesChaosInfrastructureReferenceField/KubernetesChaosInfrastructureReferenceField.tsx @@ -5,6 +5,7 @@ import { getScope } from '@utils'; import ChaosInfrastructureReferenceFieldView from '@views/ChaosInfrastructureReferenceField'; import type { ChaosInfrastructureReferenceFieldProps } from '@models'; import type { InfrastructureDetails } from '@views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField'; +import { listEnvironment } from '@api/core/environments'; function KubernetesChaosInfrastructureReferenceFieldController({ setFieldValue, @@ -16,14 +17,32 @@ function KubernetesChaosInfrastructureReferenceFieldController({ const [page, setPage] = React.useState(0); const limit = 8; + const [envID, setEnvID] = React.useState('all'); + const [initialAllInfrastructureLength, setInitialAllInfrastructureLength] = React.useState(null); const { data: listChaosInfraData, loading: listChaosInfraLoading } = listChaosInfra({ ...scope, - filter: { name: searchInfrastructure, isActive: true }, + environmentIDs: envID === 'all' ? undefined : [envID], + filter: { name: searchInfrastructure }, pagination: { page, limit }, options: { onError: error => showError(error.message) } }); + const { data: env } = listEnvironment({ + ...scope, + options: { + onError: err => showError(err.message) + } + }); + + const environmentList = env?.listEnvironments?.environments; + + React.useEffect(() => { + if (envID === 'all' && initialAllInfrastructureLength === null && listChaosInfraData?.listInfras?.totalNoOfInfras) { + setInitialAllInfrastructureLength(listChaosInfraData.listInfras.totalNoOfInfras); + } + }, [listChaosInfraData]); + // TODO: replace with get API as this becomes empty during edit const preSelectedInfrastructure = listChaosInfraData?.listInfras.infras.find( ({ infraID }) => infraID === initialInfrastructureID @@ -47,7 +66,7 @@ function KubernetesChaosInfrastructureReferenceFieldController({ } }, [preSelectedInfrastructure, setFieldValue]); - const infrastructureList = listChaosInfraData?.listInfras.infras.map(infra => { + const infrastructureList = listChaosInfraData?.listInfras?.infras.map(infra => { const infraDetails: InfrastructureDetails = { id: infra.infraID, name: infra.name, @@ -87,6 +106,9 @@ function KubernetesChaosInfrastructureReferenceFieldController({ }} searchInfrastructure={searchInfrastructure} setSearchInfrastructure={setSearchInfrastructure} + allInfrastructureLength={initialAllInfrastructureLength} + environmentList={environmentList} + setEnvID={setEnvID} loading={{ listChaosInfra: listChaosInfraLoading }} diff --git a/chaoscenter/web/src/strings/strings.en.yaml b/chaoscenter/web/src/strings/strings.en.yaml index 80fff0b50af..4af1ba3e266 100644 --- a/chaoscenter/web/src/strings/strings.en.yaml +++ b/chaoscenter/web/src/strings/strings.en.yaml @@ -482,6 +482,7 @@ infrastructureRegistered: >- Environment -> Infrastructure list. infrastructureStates: Learn more about the states of Infrastructure infrastructureType: Infrastructure type +infrastructures: Infrastructures initialDelay: Initial Delay initialDelaySeconds: Initial Delay Seconds insecureSkipVerify: Insecure skip verify diff --git a/chaoscenter/web/src/strings/types.ts b/chaoscenter/web/src/strings/types.ts index 9db3a837ac8..72089487e47 100644 --- a/chaoscenter/web/src/strings/types.ts +++ b/chaoscenter/web/src/strings/types.ts @@ -405,6 +405,7 @@ export interface StringsMap { 'infrastructureRegistered': unknown 'infrastructureStates': unknown 'infrastructureType': unknown + 'infrastructures': unknown 'initialDelay': unknown 'initialDelaySeconds': unknown 'insecureSkipVerify': unknown diff --git a/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.module.scss b/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.module.scss index e9ab159eed0..8e6592016e1 100644 --- a/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.module.scss +++ b/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.module.scss @@ -60,14 +60,14 @@ background: #effbff; border: 1.5px solid #0278d5; box-shadow: 0px 0px 1px rgba(40, 41, 61, 0.04), 0px 2px 4px rgba(96, 97, 112, 0.16); - border-radius: 4px; + border-radius: 8px !important; } .notSelected { background: #fafbfc; - border: 1px solid rgba(40, 41, 61, 0.3); + // border: 1px solid rgba(40, 41, 61, 0.3); box-shadow: 0px 0px 1px rgba(40, 41, 61, 0.04), 0px 2px 4px rgba(96, 97, 112, 0.16); - border-radius: 4px; + border-radius: 8px !important; cursor: pointer; } @@ -78,14 +78,14 @@ .agentListInnerContainer { flex-grow: 1; - overflow: auto; + // overflow: auto; gap: 1rem; max-height: calc(100% - 48px); } .item { display: grid; - grid-template-columns: 5fr 4fr 25px; + grid-template-columns: 3fr 4fr 25px; align-items: center; gap: 0.5rem; @@ -190,3 +190,35 @@ } } } + +.listEnvContainer { + box-shadow: 0px 2px 4px 0px #a9aabc29, 0px 0px 1px 0px #28293d0a; + border-radius: 4px; + cursor: pointer; +} + +.itemEnv { + display: grid; + grid-template-columns: 5fr 1fr; + align-items: center; + gap: 0.5rem; +} + +.activeEnv { + border: 1px solid var(--primary-7); +} + +.center { + display: flex; + flex-direction: column; + justify-content: center; + align-self: center; + + img { + width: 200px; + } +} + +.rounded { + border-radius: 999px; +} diff --git a/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.module.scss.d.ts b/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.module.scss.d.ts index db9d0abfa61..21d574627ec 100644 --- a/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.module.scss.d.ts +++ b/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.module.scss.d.ts @@ -1,7 +1,9 @@ declare namespace ChaosInfrastructureReferenceFieldModuleScssNamespace { export interface IChaosInfrastructureReferenceFieldModuleScss { + activeEnv: string; agentList: string; agentListInnerContainer: string; + center: string; container: string; dialog: string; editBtn: string; @@ -13,12 +15,15 @@ declare namespace ChaosInfrastructureReferenceFieldModuleScssNamespace { iconCheck: string; iconChecked: string; item: string; + itemEnv: string; leftInfo: string; + listEnvContainer: string; notSelected: string; paginationContainer: string; placeholder: string; redStatus: string; referenceSelect: string; + rounded: string; selected: string; status: string; } diff --git a/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.tsx b/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.tsx index 4b55ba44ecc..34cd9cabc2d 100644 --- a/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.tsx +++ b/chaoscenter/web/src/views/ChaosInfrastructureReferenceField/ChaosInfrastructureReferenceField.tsx @@ -19,6 +19,7 @@ import FallbackBox from '@images/FallbackBox.svg'; import CustomTagsPopover from '@components/CustomTagsPopover'; import Loader from '@components/Loader'; import { useRouteWithBaseUrl } from '@hooks'; +import { Environment } from '@api/entities'; import css from './ChaosInfrastructureReferenceField.module.scss'; export interface InfrastructureDetails { @@ -34,10 +35,13 @@ export interface InfrastructureDetails { interface ChaosInfrastructureReferenceFieldViewProps { infrastructureList: InfrastructureDetails[] | undefined; + allInfrastructureLength: number | null; + environmentList: Environment[] | undefined; preSelectedInfrastructure?: InfrastructureDetails; setInfrastructureValue: (infrastructure: InfrastructureDetails | undefined) => void; searchInfrastructure: string; setSearchInfrastructure: React.Dispatch>; + setEnvID: (id: string) => void; loading: { listChaosInfra: boolean; }; @@ -46,30 +50,67 @@ interface ChaosInfrastructureReferenceFieldViewProps { function ChaosInfrastructureReferenceFieldView({ infrastructureList, + environmentList, + allInfrastructureLength, preSelectedInfrastructure, setInfrastructureValue, searchInfrastructure, setSearchInfrastructure, + setEnvID, loading, pagination }: ChaosInfrastructureReferenceFieldViewProps): JSX.Element { const [isOpen, setOpen] = React.useState(false); const paths = useRouteWithBaseUrl(); const history = useHistory(); + const [selectedInfrastructure, setSelectedInfrastructure] = React.useState( preSelectedInfrastructure ); + const [activeEnv, setactiveEnv] = React.useState('all'); // const searchParams = useSearchParams(); // const infrastructureType = // (searchParams.get('infrastructureType') as InfrastructureType | undefined) ?? InfrastructureType.KUBERNETES; const { showError } = useToaster(); const { getString } = useStrings(); + const listingEnvironment = ({ env }: { env: Environment }): JSX.Element => { + return ( + { + setEnvID(env.environmentID); + setactiveEnv(env.name); + }} + > +
+ + {env.name} + +
+ + {env.infraIDs.length} + +
+ ); + }; + const listItem = ({ infrastructure }: { infrastructure: InfrastructureDetails }): JSX.Element => { return ( { @@ -153,62 +194,139 @@ function ChaosInfrastructureReferenceFieldView({ }} className={cx(css.referenceSelect, css.dialog)} title={ - + {getString('selectChaosInfrastructure')} } > - - - setSearchInfrastructure(e)} - /> + + + + {getString('environments')} + + + {getString('infrastructures')} + - !infrastructureList, - messageTitle: getString('noData.title'), - message: getString('noData.message') - }} + setSearchInfrastructure(e)} + /> + + {environmentList && environmentList.length > 0 ? ( + - - - {infrastructureList && infrastructureList.length > 0 ? ( - infrastructureList.map(infrastructure => listItem({ infrastructure: infrastructure })) - ) : ( - - {getString('latestRun')} - - {searchInfrastructure === '' - ? getString('newUserNoInfra.title') - : getString('noFilteredActiveInfra')} + + + { + setEnvID('all'); + setactiveEnv('all'); + }} + > + +
+ + {getString('all')} + +
+ + {allInfrastructureLength} - {searchInfrastructure === '' && ( - - { - setOpen(false); - setSearchInfrastructure(''); - }} - className={cx(css.referenceSelect, css.dialog)} - title={ - - {getString('selectChaosInfrastructure')} - - } - > - {environmentList && environmentList.length > 0 ? ( - - - - - {getString('environments')} - - - {getString('infrastructures')} - - - setSearchInfrastructure(e)} - /> + {isOpen && ( + { + close(); + setSearchInfrastructure(''); + }} + className={cx(css.referenceSelect, css.dialog)} + title={ + + {getString('selectChaosInfrastructure')} - - - + {environmentList && environmentList.length > 0 ? ( + + + - { - setEnvID('all'); - setActiveEnv('all'); - }} - > -
- - - {getString('all')} - - - - {allInfrastructureLength} - -
-
- {environmentList.map(env => listingEnvironment({ env: env }))} -
+ + {getString('environments')} + + + {getString('infrastructures')} + +
+
- - - !infrastructureList, - messageTitle: getString('noData.title'), - message: getString('noData.message') - }} + + + - {infrastructureList && infrastructureList.length > 0 ? ( - infrastructureList.map(infrastructure => listItem({ infrastructure: infrastructure })) - ) : ( - - {getString('latestRun')} - - {searchInfrastructure === '' - ? getString('newUserNoInfra.title') - : getString('noFilteredActiveInfra')} - - {searchInfrastructure === '' && ( - - {isOpen && ( - { - close(); - setSearchInfrastructure(''); - }} - className={cx(css.referenceSelect, css.dialog)} - title={ - - {getString('selectChaosInfrastructure')} + { + close(); + setSearchInfrastructure(''); + }} + className={cx(css.referenceSelect, css.dialog)} + title={ + + {getString('selectChaosInfrastructure')} + + } + > + {environmentList && environmentList.length > 0 ? ( + + + + + {getString('environments')} + + + {getString('infrastructures')} + + + - } - > - {environmentList && environmentList.length > 0 ? ( - - - + + - - {getString('environments')} - - - {getString('infrastructures')} - - - + + {environmentList.map(env => ( + + ))} + - - + + - - {environmentList.map(env => ( - - ))} - - - - - !infrastructureList, + messageTitle: getString('noData.title'), + message: getString('noData.message') + }} > - !infrastructureList, - messageTitle: getString('noData.title'), - message: getString('noData.message') - }} - > - {infrastructureList && infrastructureList.length > 0 ? ( - infrastructureList.map(infrastructure => ( - - )) - ) : ( - - )} - - - - {pagination && {pagination}} - + {infrastructureList && infrastructureList.length > 0 ? ( + infrastructureList.map(infrastructure => ( + + )) + ) : ( + + )} + -
- - -