From 47e123504cdc27ffad66bf0e57e9cc8f9acfdfff Mon Sep 17 00:00:00 2001 From: Maxime Beauchamp Date: Tue, 7 Nov 2023 16:18:21 -0500 Subject: [PATCH] added region filtering based on the amount of providers --- .../src/components/sdl/RegionSelect.tsx | 52 +++++++++++++++---- .../src/components/sdl/RentGpusForm.tsx | 5 +- deploy-web/src/queries/queryKeys.ts | 1 + deploy-web/src/queries/useProvidersQuery.ts | 12 ++++- deploy-web/src/types/provider.ts | 6 +++ deploy-web/src/types/providerAttributes.ts | 9 +++- deploy-web/src/types/sdlBuilder.ts | 6 +-- deploy-web/src/utils/apiUtils.ts | 3 ++ 8 files changed, 74 insertions(+), 20 deletions(-) diff --git a/deploy-web/src/components/sdl/RegionSelect.tsx b/deploy-web/src/components/sdl/RegionSelect.tsx index c4361d49d..91f44c1ab 100644 --- a/deploy-web/src/components/sdl/RegionSelect.tsx +++ b/deploy-web/src/components/sdl/RegionSelect.tsx @@ -1,26 +1,39 @@ -import { Autocomplete, Box, ClickAwayListener, TextField } from "@mui/material"; +import { Autocomplete, Box, ClickAwayListener, TextField, useTheme } from "@mui/material"; import { RentGpusFormValues } from "@src/types"; -import { ProviderAttributeSchemaDetailValue, ProviderAttributesSchema } from "@src/types/providerAttributes"; +import { ProviderAttributeSchemaDetailValue, ProviderAttributesSchema, ProviderRegionValue } from "@src/types/providerAttributes"; import { useState } from "react"; import { Control, Controller } from "react-hook-form"; import { CustomTooltip } from "../shared/CustomTooltip"; import InfoIcon from "@mui/icons-material/Info"; +import { useProviderRegions } from "@src/queries/useProvidersQuery"; +import { makeStyles } from "tss-react/mui"; +import { cx } from "@emotion/css"; type RegionSelectProps = { control: Control; - providerAttributesSchema: ProviderAttributesSchema; className?: string; }; -export const RegionSelect: React.FunctionComponent = ({ control, providerAttributesSchema, className }) => { +const useStyles = makeStyles()(theme => ({ + disabled: { + color: theme.palette.mode === "dark" ? theme.palette.grey[600] : theme.palette.grey[400], + pointerEvents: "none", + cursor: "default" + } +})); + +export const RegionSelect: React.FunctionComponent = ({ control, className }) => { + const { classes } = useStyles(); + const theme = useTheme(); const [isOpen, setIsOpen] = useState(false); + const { data: regions, isLoading: isLoadingRegions } = useProviderRegions(); const options = [ { key: "any", - value: "any", - description: "Any region" + description: "Any region", + providers: [] }, - ...(providerAttributesSchema?.["location-region"]?.values || []) + ...(regions || []) ]; return ( @@ -33,12 +46,13 @@ export const RegionSelect: React.FunctionComponent = ({ contr disableClearable open={isOpen} options={options} - value={field.value} + value={field.value as ProviderRegionValue} getOptionLabel={option => option?.key} defaultValue={null} isOptionEqualToValue={(option, value) => option.key === value.key} filterSelectedOptions fullWidth + loading={isLoadingRegions} ChipProps={{ size: "small" }} onChange={(event, newValue: ProviderAttributeSchemaDetailValue) => { field.onChange(newValue); @@ -60,9 +74,25 @@ export const RegionSelect: React.FunctionComponent = ({ contr )} renderOption={(props, option) => { return ( - - {option.key} - + + {option.key} + {option.key !== "any" && ( + 0 ? "bold" : "normal" + }} + > + ({option.providers.length}) + + )} diff --git a/deploy-web/src/components/sdl/RentGpusForm.tsx b/deploy-web/src/components/sdl/RentGpusForm.tsx index d1c980a40..3468f390d 100644 --- a/deploy-web/src/components/sdl/RentGpusForm.tsx +++ b/deploy-web/src/components/sdl/RentGpusForm.tsx @@ -44,9 +44,6 @@ type Props = {}; const useStyles = makeStyles()(theme => ({ formControl: { marginBottom: theme.spacing(1.5) - }, - textField: { - width: "100%" } })); @@ -271,7 +268,7 @@ export const RentGpusForm: React.FunctionComponent = ({}) => { - + diff --git a/deploy-web/src/queries/queryKeys.ts b/deploy-web/src/queries/queryKeys.ts index 8fa4624ea..f004243b5 100644 --- a/deploy-web/src/queries/queryKeys.ts +++ b/deploy-web/src/queries/queryKeys.ts @@ -34,6 +34,7 @@ export class QueryKeys { static getBidListKey = (address: string, dseq: string) => ["BID_LIST", address, dseq]; static getProvidersKey = () => ["PROVIDERS"]; static getProviderListKey = () => ["PROVIDER_LIST"]; + static getProviderRegionsKey = () => ["PROVIDER_REGIONS"]; static getProviderDetailKey = (owner: string) => ["PROVIDERS", owner]; static getDataNodeProvidersKey = () => ["DATA_NODE_PROVIDERS"]; static getProviderStatusKey = (providerUri: string) => ["PROVIDER_STATUS", providerUri]; diff --git a/deploy-web/src/queries/useProvidersQuery.ts b/deploy-web/src/queries/useProvidersQuery.ts index fd839e863..ec35a3f26 100644 --- a/deploy-web/src/queries/useProvidersQuery.ts +++ b/deploy-web/src/queries/useProvidersQuery.ts @@ -4,7 +4,7 @@ import axios, { AxiosResponse } from "axios"; import { ApiUrlService } from "@src/utils/apiUtils"; import { getNetworkCapacityDto, providerStatusToDto } from "@src/utils/providerUtils"; import { PROVIDER_PROXY_URL } from "@src/utils/constants"; -import { ApiProviderDetail, ApiProviderList, Auditor } from "@src/types/provider"; +import { ApiProviderDetail, ApiProviderList, ApiProviderRegion, Auditor } from "@src/types/provider"; import { ProviderAttributesSchema } from "@src/types/providerAttributes"; async function getProviderDetail(owner: string): Promise { @@ -101,3 +101,13 @@ async function getProviderList(): Promise> { export function useProviderList(options = {}) { return useQuery(QueryKeys.getProviderListKey(), () => getProviderList(), options); } + +async function getProviderRegions(): Promise> { + const response = await axios.get(ApiUrlService.providerRegions()); + + return response.data; +} + +export function useProviderRegions(options = {}) { + return useQuery(QueryKeys.getProviderRegionsKey(), () => getProviderRegions(), options); +} diff --git a/deploy-web/src/types/provider.ts b/deploy-web/src/types/provider.ts index 9696f2d63..4e131c5be 100644 --- a/deploy-web/src/types/provider.ts +++ b/deploy-web/src/types/provider.ts @@ -284,3 +284,9 @@ export type Auditor = { address: string; website: string; }; + +export interface ApiProviderRegion { + key: string; + description: string; + providers: string[]; +} diff --git a/deploy-web/src/types/providerAttributes.ts b/deploy-web/src/types/providerAttributes.ts index 230c51b17..563a5bf16 100644 --- a/deploy-web/src/types/providerAttributes.ts +++ b/deploy-web/src/types/providerAttributes.ts @@ -70,4 +70,11 @@ export type ProviderAttributeSchemaDetail = { values?: Array; }; -export type ProviderAttributeSchemaDetailValue = { key: string; description: string; value?: any }; +export interface ProviderAttributeSchemaDetailValue { + key: string; + description: string; + value?: any; +} +export interface ProviderRegionValue extends ProviderAttributeSchemaDetailValue { + providers: string[]; +} diff --git a/deploy-web/src/types/sdlBuilder.ts b/deploy-web/src/types/sdlBuilder.ts index 1583d186d..6af22dfb6 100644 --- a/deploy-web/src/types/sdlBuilder.ts +++ b/deploy-web/src/types/sdlBuilder.ts @@ -1,4 +1,4 @@ -import { ProviderAttributeSchemaDetailValue } from "./providerAttributes"; +import { ProviderAttributeSchemaDetailValue, ProviderRegionValue } from "./providerAttributes"; export type Service = { id: string; @@ -145,5 +145,5 @@ export type SdlSaveTemplateFormValues = { export type RentGpusFormValues = { services: Service[]; - region: ProviderAttributeSchemaDetailValue; -}; \ No newline at end of file + region: Partial; +}; diff --git a/deploy-web/src/utils/apiUtils.ts b/deploy-web/src/utils/apiUtils.ts index 8a0e09548..1c56d44b1 100644 --- a/deploy-web/src/utils/apiUtils.ts +++ b/deploy-web/src/utils/apiUtils.ts @@ -24,6 +24,9 @@ export class ApiUrlService { static providerDetail(owner: string) { return `${BASE_API_URL}/providers/${owner}`; } + static providerRegions() { + return `${BASE_API_URL}/provider-regions`; + } static block(apiEndpoint: string, id: string) { return `${apiEndpoint}/blocks/${id}`; }