Implement API fetch error display for select dropdown. #8668

pull/8733/head
Yogesh Mahajan 2025-05-06 10:52:42 +05:30 committed by GitHub
parent f64b59e735
commit 3bdeb9ace1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 110 additions and 61 deletions

View File

@ -159,7 +159,9 @@ def get_projects():
"""
if 'google' in session and 'google_obj' in session['google']:
google_obj = pickle.loads(session['google']['google_obj'])
projects_list = google_obj.get_projects()
projects_list,error = google_obj.get_projects()
if error:
return bad_request(errormsg=error)
return make_json_response(data=projects_list)
@ -175,8 +177,10 @@ def get_regions(project_id):
if 'google' in session and 'google_obj' in session['google'] \
and project_id:
google_obj = pickle.loads(session['google']['google_obj'])
regions_list = google_obj.get_regions(project_id)
regions_list,error = google_obj.get_regions(project_id)
session['google']['google_obj'] = pickle.dumps(google_obj, -1)
if error:
return bad_request(errormsg=error)
return make_json_response(data=regions_list)
else:
return make_json_response(data=[])
@ -216,7 +220,10 @@ def get_instance_types(project_id, region, instance_class):
google_obj = pickle.loads(session['google']['google_obj'])
instance_types_dict = google_obj.get_instance_types(
project_id, region)
instance_types_list = instance_types_dict.get(instance_class, [])
instance_types_list, error = (
instance_types_dict.get(instance_class, []))
if error:
return bad_request(errormsg=error)
return make_json_response(data=instance_types_list)
else:
return make_json_response(data=[])
@ -232,7 +239,9 @@ def get_database_versions():
"""
if 'google' in session and 'google_obj' in session['google']:
google_obj = pickle.loads(session['google']['google_obj'])
db_version_list = google_obj.get_database_versions()
db_version_list, error = google_obj.get_database_versions()
if error:
return bad_request(errormsg=error)
return make_json_response(data=db_version_list)
else:
return make_json_response(data=[])
@ -431,16 +440,22 @@ class Google:
:return:
"""
projects = []
error = None
credentials = self._get_credentials(self._scopes)
service = discovery.build('cloudresourcemanager',
self._cloud_resource_manager_api_version,
credentials=credentials)
req = service.projects().list()
res = req.execute()
for project in res.get('projects', []):
projects.append({'label': project['projectId'],
'value': project['projectId']})
return projects
try:
req = service.projects().list()
res = req.execute()
for project in res.get('projects', []):
projects.append({'label': project['projectId'],
'value': project['projectId']})
except HttpError as e:
error = e.reason
except Exception as e:
error = str(e)
return projects, error
def get_regions(self, project):
"""
@ -453,20 +468,23 @@ class Google:
service = discovery.build('compute',
self._compute_api_version,
credentials=credentials)
error = None
try:
req = service.regions().list(project=project)
res = req.execute()
except HttpError:
self._regions = []
return self._regions
for item in res.get('items', []):
region_name = item['name']
self._regions.append({'label': region_name, 'value': region_name})
region_zones = item.get('zones', [])
region_zones = list(
map(lambda region: region.split('/')[-1], region_zones))
self._availability_zones[region_name] = region_zones
return self._regions
for item in res.get('items', []):
region_name = item['name']
self._regions.append(
{'label': region_name, 'value': region_name})
region_zones = item.get('zones', [])
region_zones = list(
map(lambda region: region.split('/')[-1], region_zones))
self._availability_zones[region_name] = region_zones
except HttpError as e:
error = e.reason
except Exception as e:
error = str(e)
return self._regions, error
def get_availability_zones(self, region):
"""
@ -489,35 +507,47 @@ class Google:
standard_instances = []
shared_instances = []
high_mem = []
instance_types = {}
error = None
credentials = self._get_credentials(self._scopes)
service = discovery.build('sqladmin',
self._sqladmin_api_version,
credentials=credentials)
req = service.tiers().list(project=project)
res = req.execute()
for item in res.get('items', []):
if region in item.get('region', []):
if item['tier'].find('standard') != -1:
vcpu = item['tier'].split('-')[-1]
mem = round(int(item['RAM']) / (1024 * 1024))
label = vcpu + ' vCPU, ' + str(round(mem / 1024)) + ' GB'
value = 'db-custom-' + str(vcpu) + '-' + str(mem)
standard_instances.append({'label': label, 'value': value})
elif item['tier'].find('highmem') != -1:
vcpu = item['tier'].split('-')[-1]
mem = round(int(item['RAM']) / (1024 * 1024))
label = vcpu + ' vCPU, ' + str(round(mem / 1024)) + ' GB'
value = 'db-custom-' + str(vcpu) + '-' + str(mem)
high_mem.append({'label': label, 'value': value})
else:
label = '1 vCPU, ' + str(
round((int(item['RAM']) / 1073741824), 2)) + ' GB'
value = item['tier']
shared_instances.append({'label': label, 'value': value})
instance_types = {'standard': standard_instances,
'highmem': high_mem,
'shared': shared_instances}
return instance_types
try:
req = service.tiers().list(project=project)
res = req.execute()
for item in res.get('items', []):
if region in item.get('region', []):
if item['tier'].find('standard') != -1:
vcpu = item['tier'].split('-')[-1]
mem = round(int(item['RAM']) / (1024 * 1024))
label = (
vcpu + ' vCPU, ' + str(round(mem / 1024)) + ' GB')
value = 'db-custom-' + str(vcpu) + '-' + str(mem)
standard_instances.append(
{'label': label, 'value': value})
elif item['tier'].find('highmem') != -1:
vcpu = item['tier'].split('-')[-1]
mem = round(int(item['RAM']) / (1024 * 1024))
label = \
(vcpu + ' vCPU, ' + str(round(mem / 1024)) + ' GB')
value = 'db-custom-' + str(vcpu) + '-' + str(mem)
high_mem.append(
{'label': label, 'value': value})
else:
label = '1 vCPU, ' + str(
round((int(item['RAM']) / 1073741824), 2)) + ' GB'
value = item['tier']
shared_instances.append(
{'label': label, 'value': value})
instance_types = {'standard': standard_instances,
'highmem': high_mem,
'shared': shared_instances}
except HttpError as e:
error = e.reason
except Exception as e:
error = str(e)
return instance_types, error
def get_database_versions(self):
"""
@ -526,17 +556,23 @@ class Google:
"""
pg_database_versions = []
database_versions = []
error = None
credentials = self._get_credentials(self._scopes)
service = discovery.build('sqladmin',
self._sqladmin_api_version,
credentials=credentials)
req = service.flags().list()
res = req.execute()
for item in res.get('items', []):
if item.get('name', '') == 'max_parallel_workers':
pg_database_versions = item.get('appliesTo', [])
for version in pg_database_versions:
label = (version.title().split('_')[0])[0:7] \
+ 'SQL ' + version.split('_')[1]
database_versions.append({'label': label, 'value': version})
return database_versions
try:
req = service.flags().list()
res = req.execute()
for item in res.get('items', []):
if item.get('name', '') == 'max_parallel_workers':
pg_database_versions = item.get('appliesTo', [])
for version in pg_database_versions:
label = (version.title().split('_')[0])[0:7] \
+ 'SQL ' + version.split('_')[1]
database_versions.append({'label': label, 'value': version})
except HttpError as e:
error = e.reason
except Exception as e:
error = str(e)
return database_versions, error

View File

@ -121,7 +121,7 @@ const StyledGrid = styled(Grid)(({theme}) => ({
}));
/* Wrapper on any form component to add label, error indicator and help message */
export function FormInput({ children, error, className, label, helpMessage, required, testcid, lid, withContainer=true, labelGridBasis=3, controlGridBasis=9, labelTooltip='' }) {
export function FormInput({ children, error, className, label, helpMessage, required, testcid, lid, withContainer=true, labelGridBasis=3, controlGridBasis=9, labelTooltip='', errorMessage='' }) {
const cid = testcid || _.uniqueId('c');
const helpid = `h${cid}`;
@ -163,6 +163,7 @@ export function FormInput({ children, error, className, label, helpMessage, requ
{React.cloneElement(children, { cid, helpid })}
</FormControl>
<FormHelperText id={helpid} variant="outlined">{HTMLReactParse(helpMessage || '')}</FormHelperText>
{errorMessage && <FormHelperText variant="outlined" error= {true} style={{ wordBreak: 'break-word', overflowWrap: 'anywhere' }}>{HTMLReactParse(errorMessage)}</FormHelperText> }
</Grid>
</StyledGrid>
);
@ -179,7 +180,8 @@ FormInput.propTypes = {
withContainer: PropTypes.bool,
labelGridBasis: PropTypes.number,
controlGridBasis: PropTypes.number,
labelTooltip: PropTypes.string
labelTooltip: PropTypes.string,
errorMessage: PropTypes.string
};
export function InputSQL({ value, options={}, onChange, className, controlProps, inputRef, ...props }) {
@ -917,7 +919,7 @@ InputSelectNonSearch.propTypes = {
};
export const InputSelect = forwardRef(({
cid, helpid, onChange, options, readonly = false, value, controlProps = {}, optionsLoaded, optionsReloadBasis, disabled, ...props }, ref) => {
cid, helpid, onChange, options, readonly = false, value, controlProps = {}, optionsLoaded, optionsReloadBasis, disabled, onError, ...props }, ref) => {
const [[finalOptions, isLoading], setFinalOptions] = useState([[], true]);
const theme = useTheme();
@ -953,6 +955,11 @@ export const InputSelect = forwardRef(({
}
setFinalOptions([res || [], false]);
}
})
.catch((err)=>{
let error_msg = err.response.data.errormsg;
onError?.(error_msg);
setFinalOptions([[], false]);
});
return () => umounted = true;
}, [optionsReloadBasis]);
@ -1052,14 +1059,20 @@ InputSelect.propTypes = {
onChange: PropTypes.func,
disabled: PropTypes.bool,
readonly: PropTypes.bool,
onError: PropTypes.func,
};
export function FormInputSelect({
hasError, required, className, label, helpMessage, testcid, labelTooltip, ...props }) {
const [selectError, setSelectError] = useState(null);
const handleSelectError = (errorMessage) => {
setSelectError(errorMessage);
};
return (
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip}>
<InputSelect ref={props.inputRef} {...props} />
<FormInput required={required} label={label} error={hasError} className={className} helpMessage={helpMessage} testcid={testcid} labelTooltip={labelTooltip} errorMessage={selectError}>
<InputSelect ref={props.inputRef} onError={handleSelectError} {...props} />
</FormInput>
);
}