diff --git a/src/actions/functions.js b/src/actions/functions.js index 01ccb07ee..e17601217 100644 --- a/src/actions/functions.js +++ b/src/actions/functions.js @@ -210,12 +210,12 @@ const functionsActions = { payload: err }), fetchFunctions: - (project, filters, withoutLoader = false) => + (project, filters, setLargeRequestErrorMessage) => dispatch => { - dispatch(functionsActions.fetchFunctionsBegin(withoutLoader)) + dispatch(functionsActions.fetchFunctionsBegin()) return functionsApi - .getFunctions(project, filters) + .getFunctions(project, filters, null, setLargeRequestErrorMessage) .then(({ data }) => { dispatch(functionsActions.fetchFunctionsSuccess(data.funcs)) diff --git a/src/actions/jobs.js b/src/actions/jobs.js index 9059722e9..5e9d716e4 100644 --- a/src/actions/jobs.js +++ b/src/actions/jobs.js @@ -125,11 +125,11 @@ const jobsActions = { type: EDIT_JOB_FAILURE, payload: error }), - fetchAllJobRuns: (project, filters, jobName, cancelToken) => dispatch => { + fetchAllJobRuns: (project, filters, jobName, setLargeRequestErrorMessage) => dispatch => { dispatch(jobsActions.fetchAllJobRunsBegin()) return jobsApi - .getAllJobRuns(project, jobName, filters, cancelToken) + .getAllJobRuns(project, jobName, filters, setLargeRequestErrorMessage) .then(({ data }) => { dispatch(jobsActions.fetchAllJobRunsSuccess(data.runs || [])) @@ -257,12 +257,12 @@ const jobsActions = { fetchJobLogsSuccess: () => ({ type: FETCH_JOB_LOGS_SUCCESS }), - fetchJobs: (project, filters, scheduled) => dispatch => { + fetchJobs: (project, filters, scheduled, setLargeRequestErrorMessage) => dispatch => { const getJobs = scheduled ? jobsApi.getScheduledJobs : jobsApi.getJobs dispatch(jobsActions.fetchJobsBegin()) - return getJobs(project, filters) + return getJobs(project, filters, setLargeRequestErrorMessage) .then(({ data }) => { const newJobs = scheduled ? (data || {}).schedules diff --git a/src/actions/workflow.js b/src/actions/workflow.js index 82773dd86..0e1b21263 100644 --- a/src/actions/workflow.js +++ b/src/actions/workflow.js @@ -58,11 +58,11 @@ const workflowActions = { type: FETCH_WORKFLOW_FAILURE, payload: error }), - fetchWorkflows: (project, filter) => dispatch => { + fetchWorkflows: (project, filter, setLargeRequestErrorMessage) => dispatch => { dispatch(workflowActions.fetchWorkflowsBegin()) return workflowApi - .getWorkflows(project, filter) + .getWorkflows(project, filter, setLargeRequestErrorMessage) .then(response => dispatch(workflowActions.fetchWorkflowsSuccess(parseWorkflows(response.data.runs))) ) diff --git a/src/api/artifacts-api.js b/src/api/artifacts-api.js index 6e431b93b..e5f543544 100644 --- a/src/api/artifacts-api.js +++ b/src/api/artifacts-api.js @@ -50,7 +50,7 @@ const fetchArtifacts = (project, filters, config = {}) => { const artifactsApi = { addTag: (project, tag, data) => mainHttpClient.put(`/projects/${project}/tags/${tag}`, data), buildFunction: data => mainHttpClient.post('/build/function', data), - deleteArtifact: (project, key, tag) => { + deleteArtifact: (project, key, tag, uid) => { const config = { params: { key, @@ -58,7 +58,7 @@ const artifactsApi = { } } - return mainHttpClient.delete(`/projects/${project}/artifacts`, config) + return mainHttpClient.delete(`/projects/${project}/artifacts/${uid}`, config) }, deleteTag: (project, tag, data) => mainHttpClient.delete(`/projects/${project}/tags/${tag}`, { data }), @@ -107,8 +107,16 @@ const artifactsApi = { } ) }, - getDataSets: (project, filters, config) => { - return fetchArtifacts(project, filters, { ...config, params: { category: DATASET_TYPE } }) + getDataSets: (project, filters, config, setLargeRequestErrorMessage) => { + const newConfig = { + ...config, + params: { category: DATASET_TYPE }, + ui: { + setLargeRequestErrorMessage + } + } + + return fetchArtifacts(project, filters, newConfig) }, getFile: (project, file, iter, tag) => { return fetchArtifacts( @@ -124,10 +132,15 @@ const artifactsApi = { } ) }, - getFiles: (project, filters) => { - return fetchArtifacts(project, filters, { - params: { category: ARTIFACT_OTHER_TYPE, format: 'full' } - }) + getFiles: (project, filters, setLargeRequestErrorMessage) => { + const config = { + params: { category: ARTIFACT_OTHER_TYPE, format: 'full' }, + ui: { + setLargeRequestErrorMessage + } + } + + return fetchArtifacts(project, filters, config) }, getModel: (project, model, iter, tag) => { return fetchArtifacts( @@ -143,17 +156,29 @@ const artifactsApi = { } ) }, - getModelEndpoints: (project, filters, params = {}) => { + getModelEndpoints: (project, filters, params = {}, setLargeRequestErrorMessage) => { + const config = { + params, + ui: { + setLargeRequestErrorMessage + } + } + if (filters?.labels) { - params.label = filters.labels?.split(',') + config.params.label = filters.labels?.split(',') } - return mainHttpClient.get(`/projects/${project}/model-endpoints`, { - params - }) + return mainHttpClient.get(`/projects/${project}/model-endpoints`, config) }, - getModels: (project, filters) => { - return fetchArtifacts(project, filters, { params: { category: MODEL_TYPE, format: 'full' } }) + getModels: (project, filters, setLargeRequestErrorMessage) => { + const config = { + params: { category: MODEL_TYPE, format: 'full' }, + ui: { + setLargeRequestErrorMessage + } + } + + return fetchArtifacts(project, filters, config) }, registerArtifact: (project, data) => mainHttpClient.post( diff --git a/src/api/functions-api.js b/src/api/functions-api.js index c123ae2ee..7f9fad26a 100644 --- a/src/api/functions-api.js +++ b/src/api/functions-api.js @@ -30,18 +30,23 @@ const functionsApi = { deleteSelectedFunction: (func, project) => mainHttpClient.delete(`/projects/${project}/functions/${func}`), deployFunction: data => mainHttpClient.post('/build/function', data), - getFunctions: (project, filters, hash) => { - const params = {} + getFunctions: (project, filters, hash, setLargeRequestErrorMessage) => { + const config = { + params: {}, + ui: { + setLargeRequestErrorMessage + } + } if (filters?.name) { - params.name = `~${filters.name}` + config.params.name = `~${filters.name}` } if (hash) { - params.hash_key = hash + config.params.hash_key = hash } - return mainHttpClient.get(`/projects/${project}/functions`, { params }) + return mainHttpClient.get(`/projects/${project}/functions`, config) }, getFunction: (project, functionName, hash, tag) => { const params = {} diff --git a/src/api/jobs-api.js b/src/api/jobs-api.js index 5eae4e50f..8eef9a7c1 100644 --- a/src/api/jobs-api.js +++ b/src/api/jobs-api.js @@ -74,18 +74,23 @@ const jobsApi = { `/projects/${project}/schedules/${postData.scheduled_object.task.metadata.name}`, postData ), - getJobs: (project, filters, isAllJobs) => { - const params = { - project, - ...generateRequestParams(filters) + getJobs: (project, filters, setLargeRequestErrorMessage, isAllJobs) => { + const config = { + params: { + project, + ...generateRequestParams(filters) + }, + ui: { + setLargeRequestErrorMessage + } } if (!isAllJobs) { - params['partition-by'] = 'name' - params['partition-sort-by'] = 'updated' + config.params['partition-by'] = 'name' + config.params['partition-sort-by'] = 'updated' } - return mainHttpClient.get('/runs', { params }) + return mainHttpClient.get('/runs', config) }, getSpecificJobs: (project, filters, jobList) => { const params = { @@ -97,19 +102,18 @@ const jobsApi = { return mainHttpClient.get(`/runs?${jobListQuery}`, { params }) }, - getAllJobRuns: (project, jobName, filters, cancelToken) => { + getAllJobRuns: (project, jobName, filters, setLargeRequestErrorMessage) => { const config = { params: { project, name: jobName, ...generateRequestParams(filters) + }, + ui: { + setLargeRequestErrorMessage } } - if (cancelToken) { - config.cancelToken = cancelToken - } - return mainHttpClient.get('/runs', config) }, getJob: (project, jobId, iter) => { @@ -125,24 +129,29 @@ const jobsApi = { fetch(`${mainBaseUrl}/log/${project}/${id}`, { method: 'get' }), - getScheduledJobs: (project, filters) => { - const params = { - include_last_run: 'yes' + getScheduledJobs: (project, filters, setLargeRequestErrorMessage) => { + const config = { + params: { + include_last_run: 'yes' + }, + ui: { + setLargeRequestErrorMessage + } } if (filters?.owner) { - params.owner = filters.owner + config.params.owner = filters.owner } if (filters?.name) { - params.name = `~${filters.name}` + config.params.name = `~${filters.name}` } if (filters?.labels) { - params.labels = filters.labels?.split(',') + config.params.labels = filters.labels?.split(',') } - return mainHttpClient.get(`/projects/${project}/schedules`, { params }) + return mainHttpClient.get(`/projects/${project}/schedules`, config) }, removeScheduledJob: (project, scheduleName) => mainHttpClient.delete(`/projects/${project}/schedules/${scheduleName}`), diff --git a/src/api/projects-iguazio-api.js b/src/api/projects-iguazio-api.js index 61b52f645..614475ace 100644 --- a/src/api/projects-iguazio-api.js +++ b/src/api/projects-iguazio-api.js @@ -53,7 +53,8 @@ const projectsIguazioApi = { return iguazioHttpClient.post('/async_transactions', data) }, getScrubbedUsers: config => iguazioHttpClient.get('/scrubbed_users', config), - getScrubbedUserGroups: config => iguazioHttpClient.get('/scrubbed_user_groups', config) + getScrubbedUserGroups: config => iguazioHttpClient.get('/scrubbed_user_groups', config), + getActiveUser: () => iguazioHttpClient.get('/self') } export default projectsIguazioApi diff --git a/src/api/workflow-api.js b/src/api/workflow-api.js index 530813b62..00177cc47 100644 --- a/src/api/workflow-api.js +++ b/src/api/workflow-api.js @@ -69,21 +69,26 @@ const generateQueryParams = filter => { } } - return `?filter=${encodeURI(JSON.stringify(queryParams))}` + return JSON.stringify(queryParams) } const workflowsApi = { getWorkflow: (project, workflowId) => { return mainHttpClient.get(`/projects/${project}/pipelines/${workflowId}`) }, - getWorkflows: (project, filter) => { - let queryParams = '' + getWorkflows: (project, filter, setLargeRequestErrorMessage) => { + const config = { + params: {}, + ui: { + setLargeRequestErrorMessage + } + } if (filter?.groupBy === GROUP_BY_WORKFLOW) { - queryParams = generateQueryParams(filter) + config.params.filter = generateQueryParams(filter) } - return mainHttpClient.get(`/projects/${project}/pipelines` + queryParams) + return mainHttpClient.get(`/projects/${project}/pipelines`, config) } } diff --git a/src/common/Breadcrumbs/Breadcrumbs.js b/src/common/Breadcrumbs/Breadcrumbs.js index 40c045a24..7cefb41e2 100755 --- a/src/common/Breadcrumbs/Breadcrumbs.js +++ b/src/common/Breadcrumbs/Breadcrumbs.js @@ -95,7 +95,7 @@ const Breadcrumbs = ({ onClick, projectStore, fetchProjectsNames }) => { searchValue ? projectListRef.current.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) : setTimeout(() => { - selectedOptionEl.scrollIntoView( + selectedOptionEl?.scrollIntoView( { behavior: 'smooth', block: 'center' diff --git a/src/common/Breadcrumbs/breadcrumbs.util.js b/src/common/Breadcrumbs/breadcrumbs.util.js index 90c8f9fd1..b8f9339c5 100644 --- a/src/common/Breadcrumbs/breadcrumbs.util.js +++ b/src/common/Breadcrumbs/breadcrumbs.util.js @@ -41,7 +41,7 @@ export const generateProjectScreens = params => [ label: 'Quick actions', id: PROJECT_QUICK_ACTIONS_PAGE }, - { label: 'Feature Store', id: 'feature-store' }, + { label: 'Feature store', id: 'feature-store' }, { label: 'Datasets', id: 'datasets' }, { label: 'Artifacts', id: 'files' }, { label: 'Models', id: 'models' }, diff --git a/src/common/Input/input.scss b/src/common/Input/input.scss index a08008ae7..85db53b08 100644 --- a/src/common/Input/input.scss +++ b/src/common/Input/input.scss @@ -134,8 +134,14 @@ background-color: transparent; pointer-events: none; + label { + display: flex; + align-items: center; + } + &-mandatory { color: $amaranth; + margin-left: 2px; &_disabled { color: $spunPearl; @@ -143,15 +149,16 @@ } &.active-label { - top: 9px; + top: 8px; height: auto; font-weight: 700; font-size: 10px; line-height: 12px; pointer-events: auto; - .input__label-mandatory:not(.input__label-mandatory_disabled) { - color: $topaz; + .input__label-mandatory, + .input__label-mandatory_disabled { + font-size: 13px; } } diff --git a/src/common/ProjectDetailsHeader/ProjectDetailsHeader.js b/src/common/ProjectDetailsHeader/ProjectDetailsHeader.js index 63bca4622..cf4634eae 100644 --- a/src/common/ProjectDetailsHeader/ProjectDetailsHeader.js +++ b/src/common/ProjectDetailsHeader/ProjectDetailsHeader.js @@ -35,38 +35,46 @@ const ProjectDetailsHeader = ({ projectData, projectName }) => {
{projectName}
-

{projectData.spec.description ?? ''}

+ +

+ {projectData && projectData.spec.description} +

- + {projectData && ( + + )} ) diff --git a/src/common/ProjectDetailsHeader/ProjectDetailsHeader.scss b/src/common/ProjectDetailsHeader/ProjectDetailsHeader.scss index 3390a7713..755d3715b 100644 --- a/src/common/ProjectDetailsHeader/ProjectDetailsHeader.scss +++ b/src/common/ProjectDetailsHeader/ProjectDetailsHeader.scss @@ -28,8 +28,9 @@ } &__description { - max-width: 75%; + max-width: 90%; margin: 0; + word-break: break-word; } &__details { diff --git a/src/components/AddToFeatureVectorPage/AddToFeatureVectorView.js b/src/components/AddToFeatureVectorPage/AddToFeatureVectorView.js index b84eef3c6..1555d1a04 100644 --- a/src/components/AddToFeatureVectorPage/AddToFeatureVectorView.js +++ b/src/components/AddToFeatureVectorPage/AddToFeatureVectorView.js @@ -73,6 +73,7 @@ const AddToFeatureVectorView = React.forwardRef( message={getNoDataMessage( filtersStore, filters, + null, FEATURE_STORE_PAGE, ADD_TO_FEATURE_VECTOR_TAB )} diff --git a/src/components/Datasets/Datasets.js b/src/components/Datasets/Datasets.js index 0b2d39489..8700be457 100644 --- a/src/components/Datasets/Datasets.js +++ b/src/components/Datasets/Datasets.js @@ -50,6 +50,7 @@ import { handleApplyDetailsChanges, registerDatasetTitle } from './datasets.util' +import { largeResponseCatchHandler } from '../../utils/largeResponseCatchHandler' import { cancelRequest } from '../../utils/cancelRequest' import { getArtifactIdentifier } from '../../utils/getUniqueIdentifier' import { isDetailsTabExists } from '../../utils/isDetailsTabExists' @@ -69,6 +70,7 @@ const Datasets = () => { const [allDatasets, setAllDatasets] = useState([]) const [selectedDataset, setSelectedDataset] = useState({}) const [selectedRowData, setSelectedRowData] = useState({}) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const [convertedYaml, toggleConvertedYaml] = useYaml('') const [urlTagOption] = useGetTagOptions(null, filters, null, DATASETS_FILTERS) const artifactsStore = useSelector(store => store.artifactsStore) @@ -98,7 +100,7 @@ const Datasets = () => { const fetchData = useCallback( filters => { - dispatch(fetchDataSets({ project: params.projectName, filters })) + dispatch(fetchDataSets({ project: params.projectName, filters, setLargeRequestErrorMessage })) .unwrap() .then(dataSetsResponse => { setArtifactTags( @@ -112,6 +114,7 @@ const Datasets = () => { return dataSetsResponse }) + .catch(largeResponseCatchHandler) }, [dispatch, params.projectName] ) @@ -326,8 +329,9 @@ const Datasets = () => { detailsFormInitialValues={detailsFormInitialValues} filtersStore={filtersStore} handleExpandRow={handleExpandRow} - handleRegisterDataset={handleRegisterDataset} handleRefresh={handleRefresh} + handleRegisterDataset={handleRegisterDataset} + largeRequestErrorMessage={largeRequestErrorMessage} pageData={pageData} ref={datasetsRef} selectedDataset={selectedDataset} @@ -339,8 +343,8 @@ const Datasets = () => { tableContent={sortedTableContent} tableHeaders={sortedTableHeaders} toggleConvertedYaml={toggleConvertedYaml} - viewMode={viewMode} urlTagOption={urlTagOption} + viewMode={viewMode} /> ) } diff --git a/src/components/Datasets/DatasetsView.js b/src/components/Datasets/DatasetsView.js index 253a6af37..6027d8ac1 100644 --- a/src/components/Datasets/DatasetsView.js +++ b/src/components/Datasets/DatasetsView.js @@ -52,6 +52,7 @@ const DatasetsView = React.forwardRef( handleExpandRow, handleRefresh, handleRegisterDataset, + largeRequestErrorMessage, pageData, selectedDataset, selectedRowData, @@ -62,8 +63,8 @@ const DatasetsView = React.forwardRef( tableContent, tableHeaders, toggleConvertedYaml, - viewMode, - urlTagOption + urlTagOption, + viewMode }, ref ) => { @@ -100,6 +101,7 @@ const DatasetsView = React.forwardRef( message={getNoDataMessage( filtersStore, filters, + largeRequestErrorMessage, DATASETS_PAGE, null, DATASETS_FILTERS @@ -179,6 +181,7 @@ DatasetsView.propTypes = { handleExpandRow: PropTypes.func.isRequired, handleRefresh: PropTypes.func.isRequired, handleRegisterDataset: PropTypes.func.isRequired, + largeRequestErrorMessage: PropTypes.string.isRequired, pageData: PropTypes.object.isRequired, selectedDataset: PropTypes.object.isRequired, selectedRowData: PropTypes.object.isRequired, @@ -189,8 +192,8 @@ DatasetsView.propTypes = { tableContent: PropTypes.arrayOf(PropTypes.object).isRequired, tableHeaders: PropTypes.arrayOf(PropTypes.object).isRequired, toggleConvertedYaml: PropTypes.func.isRequired, - viewMode: PropTypes.string, - urlTagOption: PropTypes.string + urlTagOption: PropTypes.string, + viewMode: PropTypes.string } export default DatasetsView diff --git a/src/components/Datasets/datasets.util.js b/src/components/Datasets/datasets.util.js index 6460a5000..51ea92468 100644 --- a/src/components/Datasets/datasets.util.js +++ b/src/components/Datasets/datasets.util.js @@ -275,6 +275,7 @@ export const generateActionsMenu = ( { label: 'Delete', icon: , + disabled: !dataset.tag, className: 'danger', onClick: () => handleDeleteArtifact( @@ -282,6 +283,7 @@ export const generateActionsMenu = ( projectName, dataset.db_key, dataset.tag, + dataset.tree, handleRefresh, datasetsFilters, DATASET_TYPE diff --git a/src/components/Details/details.util.js b/src/components/Details/details.util.js index 4eef8fbfb..54b4b53b5 100644 --- a/src/components/Details/details.util.js +++ b/src/components/Details/details.util.js @@ -255,6 +255,9 @@ export const generateFunctionsContent = selectedItem => ({ command: { value: selectedItem.command }, + defaultHandler: { + value: selectedItem.default_handler + }, image: { value: getFunctionImage(selectedItem) }, diff --git a/src/components/FeatureSetsPanel/FeatureSetsPanelSchema/FeatureSetsPanelSchemaView.js b/src/components/FeatureSetsPanel/FeatureSetsPanelSchema/FeatureSetsPanelSchemaView.js index ff0b2db9d..262de9887 100644 --- a/src/components/FeatureSetsPanel/FeatureSetsPanelSchema/FeatureSetsPanelSchemaView.js +++ b/src/components/FeatureSetsPanel/FeatureSetsPanelSchema/FeatureSetsPanelSchemaView.js @@ -40,8 +40,11 @@ const FeatureSetsPanelSchemaView = ({
- Each feature set must be associated with one or more index column. - when joining feature sets the entity is used as the key column. + Each feature set must be associated with one or more index column. When joining feature + sets, the entity is used as the key column. + + +   - setData(state => ({ ...state, timestamp_key })) - } + onChange={timestamp_key => setData(state => ({ ...state, timestamp_key }))} onBlur={event => { - if ( - featureStore.newFeatureSet.spec.timestamp_key !== - event.target.value - ) { + if (featureStore.newFeatureSet.spec.timestamp_key !== event.target.value) { setNewFeatureSetSchemaTimestampKey(event.target.value) } }} diff --git a/src/components/FeatureStore/FeatureSets/FeatureSets.js b/src/components/FeatureStore/FeatureSets/FeatureSets.js index 145ae73dc..b31bd0f99 100644 --- a/src/components/FeatureStore/FeatureSets/FeatureSets.js +++ b/src/components/FeatureStore/FeatureSets/FeatureSets.js @@ -64,6 +64,7 @@ const FeatureSets = ({ const [featureSets, setFeatureSets] = useState([]) const [selectedFeatureSet, setSelectedFeatureSet] = useState({}) const [selectedRowData, setSelectedRowData] = useState({}) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const openPanelByDefault = useOpenPanel() const [urlTagOption] = useGetTagOptions(fetchFeatureSetsTags, featureSetsFilters) @@ -106,14 +107,20 @@ const FeatureSets = ({ const config = { cancelToken: new axios.CancelToken(cancel => { featureStoreRef.current.cancel = cancel - }) + }), + ui: { + setLargeRequestErrorMessage + } } - return fetchFeatureSets(params.projectName, filters, config).then(result => { - setFeatureSets(parseFeatureSets(result)) + return fetchFeatureSets(params.projectName, filters, config) + .then(result => { + if (result) { + setFeatureSets(parseFeatureSets(result)) - return result - }) + return result + } + }) }, [fetchFeatureSets, params.projectName] ) @@ -353,6 +360,7 @@ const FeatureSets = ({ filtersStore={filtersStore} handleExpandRow={handleExpandRow} handleRefresh={handleRefresh} + largeRequestErrorMessage={largeRequestErrorMessage} pageData={pageData} ref={featureStoreRef} selectedFeatureSet={selectedFeatureSet} diff --git a/src/components/FeatureStore/FeatureSets/FeatureSetsView.js b/src/components/FeatureStore/FeatureSets/FeatureSetsView.js index 214146b53..43b4d373a 100644 --- a/src/components/FeatureStore/FeatureSets/FeatureSetsView.js +++ b/src/components/FeatureStore/FeatureSets/FeatureSetsView.js @@ -46,6 +46,7 @@ const FeatureSetsView = React.forwardRef( filtersStore, handleExpandRow, handleRefresh, + largeRequestErrorMessage, pageData, selectedFeatureSet, selectedRowData, @@ -74,6 +75,7 @@ const FeatureSetsView = React.forwardRef( message={getNoDataMessage( filtersStore, featureSetsFilters, + largeRequestErrorMessage, FEATURE_STORE_PAGE, FEATURE_SETS_TAB )} @@ -133,6 +135,7 @@ FeatureSetsView.propTypes = { filtersStore: PropTypes.object.isRequired, handleExpandRow: PropTypes.func.isRequired, handleRefresh: PropTypes.func.isRequired, + largeRequestErrorMessage: PropTypes.string.isRequired, pageData: PropTypes.object.isRequired, selectedFeatureSet: PropTypes.object.isRequired, selectedRowData: PropTypes.object.isRequired, diff --git a/src/components/FeatureStore/FeatureVectors/FeatureVectors.js b/src/components/FeatureStore/FeatureVectors/FeatureVectors.js index 93f3724bf..a180a7987 100644 --- a/src/components/FeatureStore/FeatureVectors/FeatureVectors.js +++ b/src/components/FeatureStore/FeatureVectors/FeatureVectors.js @@ -67,6 +67,7 @@ const FeatureVectors = ({ const [featureVectors, setFeatureVectors] = useState([]) const [selectedFeatureVector, setSelectedFeatureVector] = useState({}) const [selectedRowData, setSelectedRowData] = useState({}) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const openPanelByDefault = useOpenPanel() const [urlTagOption] = useGetTagOptions(fetchFeatureVectorsTags, featureVectorsFilters) const params = useParams() @@ -86,29 +87,31 @@ const FeatureVectors = ({ const pageData = useMemo(() => generatePageData(selectedFeatureVector), [selectedFeatureVector]) - const detailsFormInitialValues = useMemo( - () => { - return { - features: (selectedFeatureVector.specFeatures ?? []).map( featureData => { - return {...parseFeatureTemplate(featureData)} - }) - } - }, - [selectedFeatureVector.specFeatures] - ) + const detailsFormInitialValues = useMemo(() => { + return { + features: (selectedFeatureVector.specFeatures ?? []).map(featureData => { + return { ...parseFeatureTemplate(featureData) } + }) + } + }, [selectedFeatureVector.specFeatures]) const fetchData = useCallback( filters => { const config = { cancelToken: new axios.CancelToken(cancel => { featureVectorsRef.current.cancel = cancel - }) + }), + ui: { + setLargeRequestErrorMessage + } } return fetchFeatureVectors(params.projectName, filters, config).then(result => { - setFeatureVectors(parseFeatureVectors(result)) + if (result) { + setFeatureVectors(parseFeatureVectors(result)) - return result + return result + } }) }, [fetchFeatureVectors, params.projectName] @@ -430,6 +433,7 @@ const FeatureVectors = ({ filtersStore={filtersStore} handleExpandRow={handleExpandRow} handleRefresh={handleRefresh} + largeRequestErrorMessage={largeRequestErrorMessage} pageData={pageData} ref={featureVectorsRef} selectedFeatureVector={selectedFeatureVector} diff --git a/src/components/FeatureStore/FeatureVectors/FeatureVectorsView.js b/src/components/FeatureStore/FeatureVectors/FeatureVectorsView.js index 786d0041a..2320002b8 100644 --- a/src/components/FeatureStore/FeatureVectors/FeatureVectorsView.js +++ b/src/components/FeatureStore/FeatureVectors/FeatureVectorsView.js @@ -43,6 +43,7 @@ const FeatureVectorsView = React.forwardRef( filtersStore, handleExpandRow, handleRefresh, + largeRequestErrorMessage, pageData, selectedFeatureVector, selectedRowData, @@ -70,6 +71,7 @@ const FeatureVectorsView = React.forwardRef( message={getNoDataMessage( filtersStore, featureVectorsFilters, + largeRequestErrorMessage, FEATURE_STORE_PAGE, FEATURE_VECTORS_TAB )} @@ -126,6 +128,7 @@ FeatureVectorsView.propTypes = { filtersStore: PropTypes.object.isRequired, handleExpandRow: PropTypes.func.isRequired, handleRefresh: PropTypes.func.isRequired, + largeRequestErrorMessage: PropTypes.string.isRequired, pageData: PropTypes.object.isRequired, selectedFeatureVector: PropTypes.object.isRequired, selectedRowData: PropTypes.object.isRequired, diff --git a/src/components/FeatureStore/Features/Features.js b/src/components/FeatureStore/Features/Features.js index acd0925fa..de310b055 100644 --- a/src/components/FeatureStore/Features/Features.js +++ b/src/components/FeatureStore/Features/Features.js @@ -32,16 +32,19 @@ import { FEATURE_STORE_PAGE, GROUP_BY_NAME, GROUP_BY_NONE, - TAG_FILTER_ALL_ITEMS + TAG_FILTER_ALL_ITEMS, + LARGE_REQUEST_CANCELED } from '../../../constants' import { createFeaturesRowData } from '../../../utils/createFeatureStoreContent' import { featuresActionCreator, featuresFilters } from './features.util' import { getFeatureIdentifier } from '../../../utils/getUniqueIdentifier' +import { cancelRequest } from '../../../utils/cancelRequest' import { getFilterTagOptions, setFilters } from '../../../reducers/filtersReducer' import { parseFeatures } from '../../../utils/parseFeatures' import { setTablePanelOpen } from '../../../reducers/tableReducer' import { useGetTagOptions } from '../../../hooks/useGetTagOptions.hook' import { useGroupContent } from '../../../hooks/groupContent.hook' +import { showLargeResponsePopUp } from '../../../httpClient' import { ReactComponent as Yaml } from 'igz-controls/images/yaml.svg' @@ -59,6 +62,7 @@ const Features = ({ }) => { const [features, setFeatures] = useState([]) const [selectedRowData, setSelectedRowData] = useState({}) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const [urlTagOption] = useGetTagOptions(fetchFeatureSetsTags, featuresFilters) const params = useParams() const featureStore = useSelector(store => store.featureStore) @@ -89,6 +93,9 @@ const Features = ({ const fetchData = useCallback( filters => { + const cancelRequestTimeout = setTimeout(() => { + cancelRequest(featureStoreRef, LARGE_REQUEST_CANCELED) + }, 30000) const config = { cancelToken: new axios.CancelToken(cancel => { featureStoreRef.current.cancel = cancel @@ -98,27 +105,37 @@ const Features = ({ return Promise.allSettled([ fetchFeatures(params.projectName, filters, config), fetchEntities(params.projectName, filters, config) - ]).then(result => { - if (result) { - const features = result.reduce((prevValue, nextValue) => { - return nextValue.value ? prevValue.concat(nextValue.value) : prevValue - }, []) - - setFeatures(parseFeatures(features)) - - return features - } + ]) + .then(result => { + if (result) { + const features = result.reduce((prevValue, nextValue) => { + return nextValue.value ? prevValue.concat(nextValue.value) : prevValue + }, []) + + if (features.length > 1500) { + showLargeResponsePopUp(setLargeRequestErrorMessage) + setFeatures([]) + } else { + setFeatures(parseFeatures(features)) + setLargeRequestErrorMessage('') + + return features + } + } - return result - }) + return result + }) + .catch(error => { + if (error.message === LARGE_REQUEST_CANCELED) { + showLargeResponsePopUp(setLargeRequestErrorMessage) + setFeatures([]) + } + }) + .finally(() => clearTimeout(cancelRequestTimeout)) }, [fetchEntities, fetchFeatures, params.projectName] ) - const cancelRequest = message => { - featureStoreRef.current?.cancel && featureStoreRef.current.cancel(message) - } - const handleRefresh = filters => { dispatch(getFilterTagOptions({ fetchTags: fetchFeatureSetsTags, project: params.projectName })) @@ -266,6 +283,7 @@ const Features = ({ getPopUpTemplate={getPopUpTemplate} handleExpandRow={handleExpandRow} handleRefresh={handleRefresh} + largeRequestErrorMessage={largeRequestErrorMessage} pageData={pageData} ref={featureStoreRef} selectedRowData={selectedRowData} diff --git a/src/components/FeatureStore/Features/FeaturesView.js b/src/components/FeatureStore/Features/FeaturesView.js index ee8cd9ba5..137ee0c9d 100644 --- a/src/components/FeatureStore/Features/FeaturesView.js +++ b/src/components/FeatureStore/Features/FeaturesView.js @@ -40,6 +40,7 @@ const FeaturesView = React.forwardRef( getPopUpTemplate, handleExpandRow, handleRefresh, + largeRequestErrorMessage, pageData, selectedRowData, tableContent, @@ -71,6 +72,7 @@ const FeaturesView = React.forwardRef( message={getNoDataMessage( filtersStore, featuresFilters, + largeRequestErrorMessage, FEATURE_STORE_PAGE, FEATURES_TAB )} @@ -117,6 +119,7 @@ FeaturesView.propTypes = { getPopUpTemplate: PropTypes.func.isRequired, handleExpandRow: PropTypes.func.isRequired, handleRefresh: PropTypes.func.isRequired, + largeRequestErrorMessage: PropTypes.string.isRequired, pageData: PropTypes.object.isRequired, selectedRowData: PropTypes.object.isRequired, tableContent: PropTypes.arrayOf(PropTypes.object).isRequired, diff --git a/src/components/Files/Files.js b/src/components/Files/Files.js index c35abed2b..7e350fcf9 100644 --- a/src/components/Files/Files.js +++ b/src/components/Files/Files.js @@ -46,6 +46,7 @@ import { } from './files.util' import { cancelRequest } from '../../utils/cancelRequest' import { createFilesRowData } from '../../utils/createArtifactsContent' +import {largeResponseCatchHandler } from '../../utils/largeResponseCatchHandler' import { fetchFile, fetchFiles, removeFile, removeFiles } from '../../reducers/artifactsReducer' import { getArtifactIdentifier } from '../../utils/getUniqueIdentifier' import { isDetailsTabExists } from '../../utils/isDetailsTabExists' @@ -64,6 +65,7 @@ const Files = () => { const [allFiles, setAllFiles] = useState([]) const [selectedFile, setSelectedFile] = useState({}) const [selectedRowData, setSelectedRowData] = useState({}) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const [convertedYaml, toggleConvertedYaml] = useYaml('') const [urlTagOption] = useGetTagOptions(null, filters, null, FILES_FILTERS) const artifactsStore = useSelector(store => store.artifactsStore) @@ -90,13 +92,14 @@ const Files = () => { const fetchData = useCallback( filters => { - dispatch(fetchFiles({ project: params.projectName, filters })) + dispatch(fetchFiles({ project: params.projectName, filters, setLargeRequestErrorMessage })) .unwrap() .then(filesResponse => { setArtifactTags(filesResponse, setFiles, setAllFiles, filters, dispatch, FILES_PAGE) return filesResponse }) + .catch(largeResponseCatchHandler) }, [dispatch, params.projectName] ) @@ -311,6 +314,7 @@ const Files = () => { handleExpandRow={handleExpandRow} handleRefresh={handleRefresh} handleRegisterArtifact={handleRegisterArtifact} + largeRequestErrorMessage={largeRequestErrorMessage} pageData={pageData} ref={filesRef} selectedFile={selectedFile} @@ -322,8 +326,8 @@ const Files = () => { tableContent={sortedTableContent} tableHeaders={sortedTableHeaders} toggleConvertedYaml={toggleConvertedYaml} - viewMode={viewMode} urlTagOption={urlTagOption} + viewMode={viewMode} /> ) } diff --git a/src/components/Files/FilesView.js b/src/components/Files/FilesView.js index d91415336..77ea2b929 100644 --- a/src/components/Files/FilesView.js +++ b/src/components/Files/FilesView.js @@ -52,6 +52,7 @@ const FilesView = React.forwardRef( handleExpandRow, handleRefresh, handleRegisterArtifact, + largeRequestErrorMessage, pageData, selectedFile, selectedRowData, @@ -62,8 +63,8 @@ const FilesView = React.forwardRef( tableContent, tableHeaders, toggleConvertedYaml, - viewMode, - urlTagOption + urlTagOption, + viewMode }, ref ) => { @@ -97,7 +98,14 @@ const FilesView = React.forwardRef(
{artifactsStore.loading ? null : files.length === 0 ? ( ) : ( <> @@ -173,6 +181,7 @@ FilesView.propTypes = { handleExpandRow: PropTypes.func.isRequired, handleRefresh: PropTypes.func.isRequired, handleRegisterArtifact: PropTypes.func.isRequired, + largeRequestErrorMessage: PropTypes.string.isRequired, pageData: PropTypes.object.isRequired, selectedFile: PropTypes.object.isRequired, selectedRowData: PropTypes.object.isRequired, diff --git a/src/components/Files/files.util.js b/src/components/Files/files.util.js index 6594588e5..b587f1a24 100644 --- a/src/components/Files/files.util.js +++ b/src/components/Files/files.util.js @@ -246,6 +246,7 @@ export const generateActionsMenu = ( { label: 'Delete', icon: , + disabled: !file.tag, className: 'danger', onClick: () => handleDeleteArtifact( @@ -253,6 +254,7 @@ export const generateActionsMenu = ( projectName, file.db_key, file.tag, + file.tree, handleRefresh, datasetsFilters, ARTIFACT_TYPE diff --git a/src/components/FunctionsPage/Functions.js b/src/components/FunctionsPage/Functions.js index 79cb37afb..86a1f704e 100644 --- a/src/components/FunctionsPage/Functions.js +++ b/src/components/FunctionsPage/Functions.js @@ -46,6 +46,7 @@ import { FUNCTIONS_PAGE, GROUP_BY_NAME, PANEL_FUNCTION_CREATE_MODE, + LARGE_REQUEST_CANCELED, SHOW_UNTAGGED_ITEMS, TAG_LATEST } from '../../constants' @@ -66,7 +67,6 @@ const Functions = ({ deleteFunction, fetchFunctionLogs, fetchFunctions, - fetchJobFunction, functionsStore, removeFunctionsError, removeNewFunction @@ -82,6 +82,7 @@ const Functions = ({ const [jobWizardMode, setJobWizardMode] = useState(null) const filtersStore = useSelector(store => store.filtersStore) const [selectedRowData, setSelectedRowData] = useState({}) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') let fetchFunctionLogsTimeout = useRef(null) const { isStagingMode } = useMode() const params = useParams() @@ -91,13 +92,19 @@ const Functions = ({ const refreshFunctions = useCallback( filters => { - return fetchFunctions(params.projectName, filters).then(functions => { - const newFunctions = parseFunctions(functions, params.projectName) + return fetchFunctions(params.projectName, filters, setLargeRequestErrorMessage) + .then(functions => { + const newFunctions = parseFunctions(functions, params.projectName) - setFunctions(newFunctions) + setFunctions(newFunctions) - return newFunctions - }) + return newFunctions + }) + .catch(error => { + if (error.message === LARGE_REQUEST_CANCELED) { + setFunctions([]) + } + }) }, [fetchFunctions, params.projectName] ) @@ -253,15 +260,15 @@ const Functions = ({ label: 'Run', icon: , onClick: func => { - if (func?.project && func?.name && func?.hash) { - fetchJobFunction(func.project, func.name, func.hash) + if (func?.project && func?.name && func?.hash && func?.ui?.originalContent) { + dispatch(jobsActions.fetchJobFunctionSuccess(func.ui.originalContent)) setJobWizardMode(PANEL_FUNCTION_CREATE_MODE) } else { dispatch( setNotification({ status: 400, id: Math.random(), - message: 'Failed to fetch the function' + message: 'Failed to retrieve function data' }) ) } @@ -294,7 +301,7 @@ const Functions = ({ } ] ], - [dispatch, fetchJobFunction, isStagingMode, onRemoveFunction, toggleConvertedYaml] + [dispatch, isStagingMode, onRemoveFunction, toggleConvertedYaml] ) useEffect(() => { @@ -495,6 +502,7 @@ const Functions = ({ handleExpandAll={handleExpandAll} handleExpandRow={handleExpandRow} handleSelectFunction={handleSelectFunction} + largeRequestErrorMessage={largeRequestErrorMessage} pageData={pageData} refreshFunctions={refreshFunctions} selectedFunction={selectedFunction} @@ -507,6 +515,5 @@ const Functions = ({ } export default connect(({ functionsStore }) => ({ functionsStore }), { - ...functionsActions, - ...jobsActions + ...functionsActions })(React.memo(Functions)) diff --git a/src/components/FunctionsPage/FunctionsView.js b/src/components/FunctionsPage/FunctionsView.js index b6946dfe8..94d016da9 100644 --- a/src/components/FunctionsPage/FunctionsView.js +++ b/src/components/FunctionsPage/FunctionsView.js @@ -55,6 +55,7 @@ const FunctionsView = ({ handleExpandAll, handleExpandRow, handleSelectFunction, + largeRequestErrorMessage, pageData, refreshFunctions, selectedFunction, @@ -91,7 +92,14 @@ const FunctionsView = ({ {functionsStore.loading ? ( ) : taggedFunctions.length === 0 ? ( - + ) : ( <> mode === PANEL_EDIT_MODE || mode === PANEL_RERUN_MODE, [mode]) + const isRunMode = useMemo(() => mode === PANEL_FUNCTION_CREATE_MODE, [mode]) const [selectedFunctionData, setSelectedFunctionData] = useState({}) const [filteredFunctions, setFilteredFunctions] = useState([]) const [filteredTemplates, setFilteredTemplates] = useState([]) @@ -159,16 +160,16 @@ const JobWizard = ({ useEffect(() => { if (!isEmpty(jobsStore.jobFunc)) { - if ([PANEL_EDIT_MODE, PANEL_RERUN_MODE].includes(mode)) { + if (isEditMode) { setSelectedFunctionData(jobsStore.jobFunc) - } else if (mode === PANEL_FUNCTION_CREATE_MODE) { + } else if (isRunMode) { setSelectedFunctionData({ name: jobsStore.jobFunc.metadata.name, functions: [jobsStore.jobFunc] }) } } - }, [editJob, jobsStore, mode]) + }, [isEditMode, isRunMode, jobsStore.jobFunc]) const setJobData = useCallback( (formState, jobFormData, jobAdditionalData) => { @@ -201,7 +202,7 @@ const JobWizard = ({ setJobData(formStateRef.current, jobFormData, jobAdditionalData) } else if ( formStateRef.current && - isBatchInference && + (isBatchInference || isRunMode) && !isEmpty(selectedFunctionData) && isEmpty(jobAdditionalData) ) { @@ -219,6 +220,7 @@ const JobWizard = ({ frontendSpec, isBatchInference, isEditMode, + isRunMode, jobAdditionalData, params.projectName, selectedFunctionData, @@ -234,7 +236,7 @@ const JobWizard = ({ { id: FUNCTION_SELECTION_STEP, label: 'Function Selection', - hidden: isEditMode || isBatchInference || mode === PANEL_FUNCTION_CREATE_MODE, + hidden: isEditMode || isRunMode || isBatchInference, nextIsDisabled: isEmpty(selectedFunctionData) }, { @@ -437,7 +439,7 @@ const JobWizard = ({ stepsConfig={getStepsConfig(formState)} getActions={getActionsParams => getActions(getActionsParams, formState)} title={wizardTitle} - subTitle={formState.values?.[RUN_DETAILS_STEP]?.name} + subTitle={formState.values?.[RUN_DETAILS_STEP]?.runName} > { +export const getHandlerData = (selectedFunctionData, handler) => { const currentFunction = selectedFunctionData?.functions ? chain(selectedFunctionData.functions).orderBy('metadata.updated', 'desc').get(0).value() : selectedFunctionData - const methodData = get(currentFunction, ['spec', 'entry_points', method], {}) - const outputs = (methodData?.outputs ?? []).filter(output => !isEveryObjectValueEmpty(output)) + const handlerData = get(currentFunction, ['spec', 'entry_points', handler], {}) + const outputs = (handlerData?.outputs ?? []).filter(output => !isEveryObjectValueEmpty(output)) return { - doc: methodData?.doc, - has_kwargs: methodData?.has_kwargs || false, + doc: handlerData?.doc, + has_kwargs: handlerData?.has_kwargs || false, outputs } } @@ -316,10 +318,10 @@ const getFunctionInfo = selectedFunctionData => { if (!isEmpty(functions)) { const versionOptions = getVersionOptions(functions) - const methodOptions = getMethodOptions(functions) - const { defaultVersion, defaultMethod } = getDefaultMethodAndVersion( + const handlerOptions = getHandlerOptions(functions) + const { defaultVersion, defaultHandler } = getDefaultHandlerAndVersion( versionOptions, - methodOptions, + handlerOptions, functions ) const currentFunctionVersion = selectedFunctionData.tag || defaultVersion @@ -328,10 +330,10 @@ const getFunctionInfo = selectedFunctionData => { return { name: selectedFunctionData.name, - method: defaultMethod, + handler: defaultHandler, version: currentFunctionVersion, - methodData: getMethodData(currentFunction, defaultMethod), - methodOptions, + handlerData: getHandlerData(currentFunction, defaultHandler), + handlerOptions, versionOptions, function: currentFunction || {} } @@ -342,15 +344,15 @@ const getRunDefaultInfo = (defaultData, selectedFunctionData) => { return { labels: parseChipsData(defaultData.task?.metadata?.labels), name: defaultData.task?.metadata?.name || '', - method: defaultData.task?.spec?.handler, - methodData: getMethodData(selectedFunctionData, defaultData.task?.spec?.handler), - methodOptions: [], + handler: defaultData.task?.spec?.handler, + handlerData: getHandlerData(selectedFunctionData, defaultData.task?.spec?.handler), + handlerOptions: [], version: '', versionOptions: [] } } -const getMethodOptions = selectedFunctions => { +const getHandlerOptions = selectedFunctions => { return chain(selectedFunctions) .map(func => Object.values(func.spec?.entry_points ?? {})) .flatten() @@ -367,57 +369,57 @@ const getVersionOptions = selectedFunctions => { const versionOptions = unionBy( selectedFunctions.map(func => { return { - label: func.metadata.tag || TAG_LATEST, - id: func.metadata.tag || TAG_LATEST + label: func.metadata.tag || 'N/A', + id: func.metadata.tag || TAG_NA } }), 'id' ) - return versionOptions.length ? versionOptions : [{ label: 'latest', id: TAG_LATEST }] + return versionOptions.length ? versionOptions : [{ label: 'N/A', id: TAG_NA }] } -const getDefaultMethod = (methodOptions, selectedFunctions) => { - let method = '' +const getDefaultHandler = (handlerOptions, selectedFunctions) => { + let handler = '' const latestFunction = selectedFunctions.find(item => item.metadata.tag === TAG_LATEST) - if (methodOptions.length) { - method = methodOptions[0]?.id + if (handlerOptions.length) { + handler = handlerOptions[0]?.id } else if (latestFunction) { - method = latestFunction.spec.default_handler || 'handler' + handler = latestFunction.spec.default_handler || FUNCTION_DEFAULT_HANDLER } else { - method = selectedFunctions[0]?.spec.default_handler || 'handler' + handler = selectedFunctions[0]?.spec.default_handler || FUNCTION_DEFAULT_HANDLER } - return method + return handler } -const getDefaultMethodAndVersion = (versionOptions, methodOptions, selectedFunctions) => { +const getDefaultHandlerAndVersion = (versionOptions, handlerOptions, selectedFunctions) => { const defaultVersion = versionOptions.find(version => version.id === TAG_LATEST)?.id || versionOptions[0].id || '' - const defaultMethod = getDefaultMethod(methodOptions, selectedFunctions) + const defaultHandler = getDefaultHandler(handlerOptions, selectedFunctions) return { defaultVersion, - defaultMethod + defaultHandler } } -export const getFunctionParameters = (selectedFunction, method) => { +export const getFunctionParameters = (selectedFunction, handler) => { return chain(selectedFunction) .orderBy('metadata.updated', 'desc') .map(func => { - return func.spec.entry_points ? func.spec.entry_points[method]?.parameters ?? [] : [] + return func.spec.entry_points ? func.spec.entry_points[handler]?.parameters ?? [] : [] }) .flatten() .unionBy('name') .value() } -export const getFunctionDefaultParameters = (selectedFunction, method) => { - const functionParameters = get(selectedFunction, `spec.entry_points[${method}].parameters`, []) +export const getFunctionDefaultParameters = (selectedFunction, handler) => { + const functionParameters = get(selectedFunction, `spec.entry_points[${handler}].parameters`, []) return keyBy(functionParameters, 'name') } @@ -919,14 +921,14 @@ const generateParameters = parametersTableData => { parametersTableData?.predefined ?.filter(parameter => !parameter.data.isHyper && parameter.data.isChecked) - .forEach(value => { - parameters[value.data.name] = convertParameterValue(value.data.value, value.data.type) + .forEach(parameter => { + parameters[parameter.data.name] = convertParameterValue(parameter.data.value, parameter.data.type) }) parametersTableData?.custom ?.filter(parameter => !parameter.data.isHyper && parameter.data.isChecked) - .forEach(value => { - parameters[value.data.name] = convertParameterValue(value.data.value, value.data.type) + .forEach(parameter => { + parameters[parameter.data.name] = convertParameterValue(parameter.data.value, parameter.data.type) }) return parameters @@ -1069,7 +1071,7 @@ export const generateJobRequestData = ( task: { metadata: { project: params.projectName, - name: formData[RUN_DETAILS_STEP].name, + name: formData[RUN_DETAILS_STEP].runName, labels: convertChipsData(formData[RUN_DETAILS_STEP].labels) }, spec: { @@ -1079,7 +1081,7 @@ export const generateJobRequestData = ( // secret_sources: formData[ADVANCED_STEP].secretSourcesTable.map(secretSource => { // return { kind: secretSource.data.key, source: secretSource.data.value } // }), - handler: formData[RUN_DETAILS_STEP].method ?? '', + handler: formData[RUN_DETAILS_STEP].handler ?? '', input_path: formData[ADVANCED_STEP].inputPath ?? '', output_path: formData[ADVANCED_STEP].outputPath, function: diff --git a/src/components/JobWizard/JobWizardSteps/JobWizardDataInputs/JobWizardDataInputs.js b/src/components/JobWizard/JobWizardSteps/JobWizardDataInputs/JobWizardDataInputs.js index 88d4ff435..d752f42aa 100644 --- a/src/components/JobWizard/JobWizardSteps/JobWizardDataInputs/JobWizardDataInputs.js +++ b/src/components/JobWizard/JobWizardSteps/JobWizardDataInputs/JobWizardDataInputs.js @@ -35,7 +35,7 @@ const JobWizardDataInputs = ({ formState, stepIsActive }) => { exitEditModeTriggerItem={stepIsActive} fieldsPath={`${DATA_INPUTS_STEP}.dataInputsTable`} formState={formState} - rowCanBeAdded={formState.values.runDetails.methodData?.has_kwargs} + rowCanBeAdded={formState.values.runDetails.handlerData?.has_kwargs} /> diff --git a/src/components/JobWizard/JobWizardSteps/JobWizardFunctionSelection/JobWizardFunctionSelection.js b/src/components/JobWizard/JobWizardSteps/JobWizardFunctionSelection/JobWizardFunctionSelection.js index e670d9e99..5d0100b5a 100644 --- a/src/components/JobWizard/JobWizardSteps/JobWizardFunctionSelection/JobWizardFunctionSelection.js +++ b/src/components/JobWizard/JobWizardSteps/JobWizardFunctionSelection/JobWizardFunctionSelection.js @@ -45,7 +45,7 @@ import { generateProjectsList } from '../../../../utils/projects' import { functionRunKinds } from '../../../Jobs/jobs.util' import { openConfirmPopUp } from 'igz-controls/utils/common.util' import { - filterTrainFunctionMethods, + filterTrainFunctionHandlers, FUNCTIONS_SELECTION_FUNCTIONS_TAB, FUNCTIONS_SELECTION_HUB_TAB, functionsSelectionTabs, @@ -238,7 +238,7 @@ const JobWizardFunctionSelection = ({ } const onSelectedProjectNameChange = currentValue => { - dispatch(functionsActions.fetchFunctions(currentValue, {}, true)).then(functions => { + dispatch(functionsActions.fetchFunctions(currentValue, {})).then(functions => { const validFunctions = functions.filter(func => { return includes(functionRunKinds, func.kind) }) @@ -335,7 +335,7 @@ const JobWizardFunctionSelection = ({ const functionTemplatePath = `${functionData.spec.item_uri}${functionData.spec.assets.function}` dispatch(functionsActions.fetchFunctionTemplate(functionTemplatePath)).then(result => { - const resultData = isTrain ? filterTrainFunctionMethods(result) : result + const resultData = isTrain ? filterTrainFunctionHandlers(result) : result setSelectedFunctionData(resultData) generateData(resultData) diff --git a/src/components/JobWizard/JobWizardSteps/JobWizardFunctionSelection/jobWizardFunctionSelection.util.js b/src/components/JobWizard/JobWizardSteps/JobWizardFunctionSelection/jobWizardFunctionSelection.util.js index d9e2a8586..2333455cd 100644 --- a/src/components/JobWizard/JobWizardSteps/JobWizardFunctionSelection/jobWizardFunctionSelection.util.js +++ b/src/components/JobWizard/JobWizardSteps/JobWizardFunctionSelection/jobWizardFunctionSelection.util.js @@ -69,13 +69,13 @@ export const generateFunctionTemplateCardData = templateData => { return functionTemplateCardData } -export const filterTrainFunctionMethods = result => { - const allowedMethods = trainModelAllowedHubFunctions[result.name] +export const filterTrainFunctionHandlers = result => { + const allowedHandlers = trainModelAllowedHubFunctions[result.name] const { entry_points } = result.functions[0].spec if (entry_points) { result.functions[0].spec.entry_points = Object.fromEntries( - Object.entries(entry_points).filter(([key]) => allowedMethods.includes(key)) + Object.entries(entry_points).filter(([key]) => allowedHandlers.includes(key)) ) } diff --git a/src/components/JobWizard/JobWizardSteps/JobWizardParameters/JobWizardParameters.js b/src/components/JobWizard/JobWizardSteps/JobWizardParameters/JobWizardParameters.js index 8a4b7bf35..a41cc69d9 100644 --- a/src/components/JobWizard/JobWizardSteps/JobWizardParameters/JobWizardParameters.js +++ b/src/components/JobWizard/JobWizardSteps/JobWizardParameters/JobWizardParameters.js @@ -70,7 +70,7 @@ const JobWizardParameters = ({ formState, stepIsActive }) => { fieldsPath={`${PARAMETERS_STEP}.parametersTable`} formState={formState} parametersFromPath={parametersFromPath} - rowCanBeAdded={formState.values.runDetails.methodData?.has_kwargs} + rowCanBeAdded={formState.values.runDetails.handlerData?.has_kwargs} withHyperparameters={ hyperParametersAreEnabled && selectedFromValue === PARAMETERS_FROM_UI_VALUE } diff --git a/src/components/JobWizard/JobWizardSteps/JobWizardRunDetails/JobWizardRunDetails.js b/src/components/JobWizard/JobWizardSteps/JobWizardRunDetails/JobWizardRunDetails.js index 747278ef7..25b28b90a 100644 --- a/src/components/JobWizard/JobWizardSteps/JobWizardRunDetails/JobWizardRunDetails.js +++ b/src/components/JobWizard/JobWizardSteps/JobWizardRunDetails/JobWizardRunDetails.js @@ -38,7 +38,8 @@ import { DATA_INPUTS_STEP, EXISTING_IMAGE_SOURCE, PARAMETERS_STEP, - RUN_DETAILS_STEP + RUN_DETAILS_STEP, + TAG_NA } from '../../../../constants' import { SECONDARY_BUTTON, TERTIARY_BUTTON } from 'igz-controls/constants' import { areFormValuesChanged } from 'igz-controls/utils/form.util' @@ -47,7 +48,7 @@ import { getValidationRules } from 'igz-controls/utils/validation.util' import { openPopUp } from 'igz-controls/utils/common.util' import { getFunctionParameters, - getMethodData, + getHandlerData, parseDataInputs, parsePredefinedParameters } from '../../JobWizard.util' @@ -63,10 +64,10 @@ const JobWizardRunDetails = ({ selectedFunctionData, stepIsActive }) => { - const methodPath = `${RUN_DETAILS_STEP}.method` + const handlerPath = `${RUN_DETAILS_STEP}.handler` const imageSourcePath = `${RUN_DETAILS_STEP}.image.imageSource` - const outputsPath = `${RUN_DETAILS_STEP}.methodData.outputs` - const [spyOnMethodChange, setSpyOnMethodChange] = useState(true) + const outputsPath = `${RUN_DETAILS_STEP}.handlerData.outputs` + const [spyOnHandlerChange, setspyOnHandlerChange] = useState(true) const commonImageWarningMsg = 'The image must include all the software packages that are required to run the function. ' + 'For example, for an XGBoost model, ensure that the image includes the correct XGboost package and version' @@ -79,13 +80,13 @@ const JobWizardRunDetails = ({ [formState.values, imageSourcePath] ) - const handleMethodChange = method => { - setSpyOnMethodChange(true) + const handleHandlerChange = handler => { + setspyOnHandlerChange(true) - const functionParameters = getFunctionParameters(selectedFunctionData.functions, method) - const dataInputs = parseDataInputs(functionParameters, prePopulatedData.dataInputs) + const functionParameters = getFunctionParameters(selectedFunctionData.functions, handler) + const dataInputs = parseDataInputs(functionParameters, prePopulatedData?.dataInputs) const predefinedParameters = parsePredefinedParameters(functionParameters) - const methodData = getMethodData(selectedFunctionData, method) + const handlerData = getHandlerData(selectedFunctionData, handler) set(formState.initialValues, `${DATA_INPUTS_STEP}.dataInputsTable`, dataInputs) set( @@ -93,18 +94,18 @@ const JobWizardRunDetails = ({ `${PARAMETERS_STEP}.parametersTable.predefined`, predefinedParameters ) - set(formState.initialValues, `${RUN_DETAILS_STEP}.methodData`, methodData) + set(formState.initialValues, `${RUN_DETAILS_STEP}.handlerData`, handlerData) formState.form.change(`${DATA_INPUTS_STEP}.dataInputsTable`, dataInputs) formState.form.change(`${PARAMETERS_STEP}.parametersTable.predefined`, predefinedParameters) - formState.form.change(`${RUN_DETAILS_STEP}.methodData`, methodData) + formState.form.change(`${RUN_DETAILS_STEP}.handlerData`, handlerData) formState.form.change( `${PARAMETERS_STEP}.parametersTable.custom`, get(formState.initialValues, `${PARAMETERS_STEP}.parametersTable.custom`, []) ) } - const onMethodChange = (value, prevValue) => { - setSpyOnMethodChange(false) + const onHandlerChange = (value, prevValue) => { + setspyOnHandlerChange(false) const dataInputsAreChanged = areFormValuesChanged( formState.initialValues[DATA_INPUTS_STEP].dataInputsTable, @@ -125,22 +126,22 @@ const JobWizardRunDetails = ({ label: 'Cancel', variant: TERTIARY_BUTTON, handler: () => { - formState.form.change(methodPath, prevValue) - setSpyOnMethodChange(true) + formState.form.change(handlerPath, prevValue) + setspyOnHandlerChange(true) } }, confirmButton: { label: 'OK', variant: SECONDARY_BUTTON, handler: () => { - handleMethodChange(value) + handleHandlerChange(value) } }, header: 'Are you sure?', message: 'Changes made to the Data Inputs and Parameters sections will be lost' }) } else { - handleMethodChange(value) + handleHandlerChange(value) } } @@ -158,8 +159,8 @@ const JobWizardRunDetails = ({
)} {!isBatchInference ? ( - jobAdditionalData.methodOptions?.length !== 0 ? ( + jobAdditionalData.handlerOptions?.length !== 0 ? (
) : (
- +
) ) : null} @@ -263,10 +268,10 @@ const JobWizardRunDetails = ({
)} - {get(formState.values, `${RUN_DETAILS_STEP}.methodData.doc`, '') && ( + {get(formState.values, `${RUN_DETAILS_STEP}.handlerData.doc`, '') && ( <>
Description
-
{formState.values[RUN_DETAILS_STEP].methodData.doc}
+
{formState.values[RUN_DETAILS_STEP].handlerData.doc}
)} {get(formState.values, outputsPath, []).length > 0 && ( @@ -305,8 +310,8 @@ const JobWizardRunDetails = ({ )} - {stepIsActive && spyOnMethodChange && ( - {onMethodChange} + {stepIsActive && spyOnHandlerChange && ( + {onHandlerChange} )} ) diff --git a/src/components/Jobs/MonitorJobs/MonitorJobs.js b/src/components/Jobs/MonitorJobs/MonitorJobs.js index 0817a8e5e..eea5a70e7 100644 --- a/src/components/Jobs/MonitorJobs/MonitorJobs.js +++ b/src/components/Jobs/MonitorJobs/MonitorJobs.js @@ -22,7 +22,6 @@ import classnames from 'classnames' import { useLocation, useNavigate, useParams } from 'react-router-dom' import { connect, useDispatch, useSelector } from 'react-redux' import { isEmpty } from 'lodash' -import axios from 'axios' import JobWizard from '../../JobWizard/JobWizard' import Details from '../../Details/Details' @@ -32,7 +31,6 @@ import NoData from '../../../common/NoData/NoData' import Table from '../../Table/Table' import TableTop from '../../../elements/TableTop/TableTop' import YamlModal from '../../../common/YamlModal/YamlModal' -import { ConfirmDialog } from 'igz-controls/components' import { DANGER_BUTTON, TERTIARY_BUTTON } from 'igz-controls/constants' import { @@ -40,7 +38,7 @@ import { JOBS_PAGE, MONITOR_JOBS_TAB, PANEL_RERUN_MODE, - REQUEST_CANCELED + LARGE_REQUEST_CANCELED } from '../../../constants' import { generateActionsMenu, @@ -55,7 +53,6 @@ import { getCloseDetailsLink } from '../../../utils/getCloseDetailsLink' import { getNoDataMessage } from '../../../utils/getNoDataMessage' import { enrichRunWithFunctionFields, handleAbortJob } from '../jobs.util' import { isDetailsTabExists } from '../../../utils/isDetailsTabExists' -import { cancelRequest } from '../../../utils/cancelRequest' import { openPopUp } from 'igz-controls/utils/common.util' import { getJobLogs } from '../../../utils/getJobLogs.util' import { parseJob } from '../../../utils/parseJob' @@ -92,7 +89,6 @@ const MonitorJobs = ({ const dispatch = useDispatch() const { isStagingMode } = useMode() const fetchJobFunctionsPromiseRef = useRef() - const fetchJobsRef = useRef({ current: {} }) const { editableItem, handleMonitoring, @@ -145,37 +141,24 @@ const MonitorJobs = ({ } const fetchData = params.jobName ? fetchAllJobRuns : fetchJobs - const cancelJobsRequestTimeout = setTimeout(() => { - cancelRequest(fetchJobsRef, REQUEST_CANCELED) - }, 30000) - fetchData( - params.projectName, - filters, - params.jobName ?? false, - new axios.CancelToken(cancel => { - fetchJobsRef.current.cancel = cancel - }) - ) + fetchData(params.projectName, filters, params.jobName ?? false, setLargeRequestErrorMessage) .then(jobs => { - if (jobs.length > 1500) { - showJobsErrorPopUp() - setJobRuns([]) - } else { - const parsedJobs = jobs.map(job => parseJob(job, MONITOR_JOBS_TAB)) + const parsedJobs = jobs.map(job => parseJob(job, MONITOR_JOBS_TAB)) - if (params.jobName) { - setJobRuns(parsedJobs) - } else { - setJobs(parsedJobs) - } - setLargeRequestErrorMessage('') + if (params.jobName) { + setJobRuns(parsedJobs) + } else { + setJobs(parsedJobs) } }) .catch(error => { - if (error.message === REQUEST_CANCELED) { - showJobsErrorPopUp() - setJobRuns([]) + if (error.message === LARGE_REQUEST_CANCELED) { + if (params.jobName) { + setJobRuns([]) + } else { + setJobs([]) + } } else { dispatch( setNotification({ @@ -187,16 +170,6 @@ const MonitorJobs = ({ ) } }) - .finally(() => clearTimeout(cancelJobsRequestTimeout)) - - const showJobsErrorPopUp = () => { - const errorMessage = - 'The query result is too large to display. Add a filter (or narrow it) to retrieve fewer results.' - openPopUp(ConfirmDialog, { - message: errorMessage - }) - setLargeRequestErrorMessage(errorMessage) - } }, [dispatch, fetchAllJobRuns, fetchJobs, params.jobName, params.projectName] ) @@ -500,10 +473,13 @@ const MonitorJobs = ({ {jobsStore.loading ? null : (params.jobName && jobRuns.length === 0) || (jobs.length === 0 && !params.jobName) ? ( ) : ( isEmpty(selectedJob) && ( diff --git a/src/components/Jobs/MonitorWorkflows/MonitorWorkflows.js b/src/components/Jobs/MonitorWorkflows/MonitorWorkflows.js index 4970b237e..2be60bf44 100644 --- a/src/components/Jobs/MonitorWorkflows/MonitorWorkflows.js +++ b/src/components/Jobs/MonitorWorkflows/MonitorWorkflows.js @@ -83,6 +83,7 @@ const MonitorWorkflows = ({ const [workflowsAreLoaded, setWorkflowsAreLoaded] = useState(false) const [itemIsSelected, setItemIsSelected] = useState(false) const [selectedJob, setSelectedJob] = useState({}) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const [convertedYaml, toggleConvertedYaml] = useYaml('') const appStore = useSelector(store => store.appStore) const workflowsStore = useSelector(state => state.workflowsStore) @@ -299,7 +300,7 @@ const MonitorWorkflows = ({ const getWorkflows = useCallback( filter => { - fetchWorkflows(params.projectName, filter) + fetchWorkflows(params.projectName, filter, setLargeRequestErrorMessage) }, [fetchWorkflows, params.projectName] ) @@ -536,10 +537,17 @@ const MonitorWorkflows = ({ )} - {workflowsStore.workflows.loading ? null : !params.workflowId && - workflowsStore.workflows.data.length === 0 ? ( + {workflowsStore.workflows.loading ? null : (!params.workflowId && + workflowsStore.workflows.data.length === 0) || + largeRequestErrorMessage ? ( ) : ( <> diff --git a/src/components/Jobs/ScheduledJobs/ScheduledJobs.js b/src/components/Jobs/ScheduledJobs/ScheduledJobs.js index 8ae682a2d..c8bc96a39 100644 --- a/src/components/Jobs/ScheduledJobs/ScheduledJobs.js +++ b/src/components/Jobs/ScheduledJobs/ScheduledJobs.js @@ -36,6 +36,7 @@ import { LABELS_FILTER, NAME_FILTER, PANEL_EDIT_MODE, + LARGE_REQUEST_CANCELED, SCHEDULE_TAB } from '../../../constants' import { DANGER_BUTTON, FORBIDDEN_ERROR_STATUS_CODE } from 'igz-controls/constants' @@ -67,6 +68,7 @@ const ScheduledJobs = ({ const [dataIsLoaded, setDataIsLoaded] = useState(false) const [convertedYaml, toggleConvertedYaml] = useYaml('') const [editableItem, setEditableItem] = useState(null) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const dispatch = useDispatch() const params = useParams() const filtersStore = useSelector(store => store.filtersStore) @@ -96,20 +98,22 @@ const ScheduledJobs = ({ const refreshJobs = useCallback( filters => { - fetchJobs(params.projectName, filters, true) + fetchJobs(params.projectName, filters, true, setLargeRequestErrorMessage) .then(jobs => { setJobs(jobs.map(job => parseJob(job, SCHEDULE_TAB))) }) .catch(error => { - dispatch( - setNotification({ - status: error?.response?.status || 400, - id: Math.random(), - message: 'Failed to fetch jobs', - retry: () => refreshJobs(filters), - error - }) - ) + if (error.message !== LARGE_REQUEST_CANCELED) { + dispatch( + setNotification({ + status: error?.response?.status || 400, + id: Math.random(), + message: 'Failed to fetch jobs', + retry: () => refreshJobs(filters), + error + }) + ) + } }) }, [dispatch, fetchJobs, params.projectName] @@ -297,7 +301,15 @@ const ScheduledJobs = ({ {jobsStore.loading ? null : jobs.length === 0 ? ( - + ) : ( <>
{ + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const [modelEndpoints, setModelEndpoints] = useState([]) const [selectedModelEndpoint, setSelectedModelEndpoint] = useState({}) const artifactsStore = useSelector(store => store.artifactsStore) @@ -71,13 +73,15 @@ const ModelEndpoints = () => { params: { metric: 'latency_avg_1h', start: 'now-10m' - } + }, + setLargeRequestErrorMessage }) ) .unwrap() .then(result => { setModelEndpoints(result) }) + .catch(largeResponseCatchHandler) }, [dispatch, params.projectName] ) @@ -159,6 +163,7 @@ const ModelEndpoints = () => { artifactsStore={artifactsStore} fetchData={fetchData} filtersStore={filtersStore} + largeRequestErrorMessage={largeRequestErrorMessage} modelEndpoints={modelEndpoints} pageData={pageData} ref={modelEndpointsRef} diff --git a/src/components/ModelsPage/ModelEndpoints/ModelEndpointsView.js b/src/components/ModelsPage/ModelEndpoints/ModelEndpointsView.js index 20f4d63c2..764d310d2 100644 --- a/src/components/ModelsPage/ModelEndpoints/ModelEndpointsView.js +++ b/src/components/ModelsPage/ModelEndpoints/ModelEndpointsView.js @@ -38,6 +38,7 @@ const ModelEndpointsView = React.forwardRef( artifactsStore, fetchData, filtersStore, + largeRequestErrorMessage, modelEndpoints, pageData, selectedModelEndpoint, @@ -64,7 +65,13 @@ const ModelEndpointsView = React.forwardRef( {artifactsStore.loading ? null : modelEndpoints.length === 0 ? ( ) : ( <> @@ -106,6 +113,7 @@ ModelEndpointsView.propTypes = { artifactsStore: PropTypes.object.isRequired, fetchData: PropTypes.func.isRequired, filtersStore: PropTypes.object.isRequired, + largeRequestErrorMessage: PropTypes.string.isRequired, modelEndpoints: PropTypes.arrayOf(PropTypes.object).isRequired, pageData: PropTypes.object.isRequired, selectedModelEndpoint: PropTypes.object.isRequired, diff --git a/src/components/ModelsPage/Models/Models.js b/src/components/ModelsPage/Models/Models.js index db0bbba49..ca4bdc219 100644 --- a/src/components/ModelsPage/Models/Models.js +++ b/src/components/ModelsPage/Models/Models.js @@ -68,10 +68,12 @@ import { useGetTagOptions } from '../../../hooks/useGetTagOptions.hook' import { getViewMode } from '../../../utils/helper' import { useMode } from '../../../hooks/mode.hook' import { setArtifactTags } from '../../../utils/artifacts.util' +import { largeResponseCatchHandler } from '../../../utils/largeResponseCatchHandler' const Models = ({ fetchModelFeatureVector }) => { const [models, setModels] = useState([]) const [allModels, setAllModels] = useState([]) + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const [selectedModel, setSelectedModel] = useState({}) const [selectedRowData, setSelectedRowData] = useState({}) const [urlTagOption] = useGetTagOptions(null, filters, null, MODELS_FILTERS) @@ -106,13 +108,16 @@ const Models = ({ fetchModelFeatureVector }) => { const fetchData = useCallback( async filters => { - return dispatch(fetchModels({ project: params.projectName, filters: filters })) + return dispatch( + fetchModels({ project: params.projectName, filters, setLargeRequestErrorMessage }) + ) .unwrap() .then(modelsResponse => { setArtifactTags(modelsResponse, setModels, setAllModels, filters, dispatch, MODELS_TAB) return modelsResponse }) + .catch(largeResponseCatchHandler) }, [dispatch, setModels, params.projectName] ) @@ -356,6 +361,7 @@ const Models = ({ fetchModelFeatureVector }) => { handleRegisterModel={handleRegisterModel} handleTrainModel={handleTrainModel} isDemoMode={isDemoMode} + largeRequestErrorMessage={largeRequestErrorMessage} models={models} pageData={pageData} ref={modelsRef} diff --git a/src/components/ModelsPage/Models/ModelsView.js b/src/components/ModelsPage/Models/ModelsView.js index 4b082cc04..7547d800a 100644 --- a/src/components/ModelsPage/Models/ModelsView.js +++ b/src/components/ModelsPage/Models/ModelsView.js @@ -40,9 +40,9 @@ const ModelsView = React.forwardRef( ( { actionsMenu, - artifactsStore, applyDetailsChanges, applyDetailsChangesCallback, + artifactsStore, detailsFormInitialValues, filtersStore, handleExpandRow, @@ -50,6 +50,7 @@ const ModelsView = React.forwardRef( handleRegisterModel, handleTrainModel, isDemoMode, + largeRequestErrorMessage, models, pageData, selectedModel, @@ -103,6 +104,7 @@ const ModelsView = React.forwardRef( message={getNoDataMessage( filtersStore, filters, + largeRequestErrorMessage, MODELS_PAGE, MODELS_TAB, MODELS_FILTERS @@ -171,15 +173,16 @@ ModelsView.defaultProps = { ModelsView.propTypes = { actionsMenu: ACTIONS_MENU.isRequired, - artifactsStore: PropTypes.object.isRequired, applyDetailsChanges: PropTypes.func.isRequired, applyDetailsChangesCallback: PropTypes.func.isRequired, + artifactsStore: PropTypes.object.isRequired, filtersStore: PropTypes.object.isRequired, handleExpandRow: PropTypes.func.isRequired, handleRefresh: PropTypes.func.isRequired, handleRegisterModel: PropTypes.func.isRequired, handleTrainModel: PropTypes.func.isRequired, isDemoMode: PropTypes.bool.isRequired, + largeRequestErrorMessage: PropTypes.string.isRequired, models: PropTypes.arrayOf(PropTypes.object).isRequired, pageData: PropTypes.object.isRequired, selectedModel: PropTypes.object.isRequired, diff --git a/src/components/ModelsPage/Models/models.util.js b/src/components/ModelsPage/Models/models.util.js index b57064dd6..9307616b2 100644 --- a/src/components/ModelsPage/Models/models.util.js +++ b/src/components/ModelsPage/Models/models.util.js @@ -345,6 +345,7 @@ export const generateActionsMenu = ( projectName, model.db_key, model.tag, + model.tree, handleRefresh, modelsFilters, MODEL_TYPE diff --git a/src/components/ModelsPage/RealTimePipelines/RealTimePipelines.js b/src/components/ModelsPage/RealTimePipelines/RealTimePipelines.js index 6d9e3cb16..82566bba0 100644 --- a/src/components/ModelsPage/RealTimePipelines/RealTimePipelines.js +++ b/src/components/ModelsPage/RealTimePipelines/RealTimePipelines.js @@ -28,6 +28,7 @@ import { fetchArtifactsFunctions, removePipelines } from '../../../reducers/arti import createFunctionsContent from '../../../utils/createFunctionsContent' import { cancelRequest } from '../../../utils/cancelRequest' import { generatePageData } from './realTimePipelines.util' +import { largeResponseCatchHandler } from '../../../utils/largeResponseCatchHandler' import { getFunctionIdentifier } from '../../../utils/getUniqueIdentifier' import { setFilters } from '../../../reducers/filtersReducer' import { useGroupContent } from '../../../hooks/groupContent.hook' @@ -36,6 +37,7 @@ import { useModelsPage } from '../ModelsPage.context' import { ReactComponent as Yaml } from 'igz-controls/images/yaml.svg' const RealTimePipelines = () => { + const [largeRequestErrorMessage, setLargeRequestErrorMessage] = useState('') const [pipelines, setPipelines] = useState([]) const [selectedRowData, setSelectedRowData] = useState({}) const artifactsStore = useSelector(store => store.artifactsStore) @@ -62,7 +64,13 @@ const RealTimePipelines = () => { const fetchData = useCallback( filters => { - dispatch(fetchArtifactsFunctions({ project: params.projectName, filters })) + dispatch( + fetchArtifactsFunctions({ + project: params.projectName, + filters, + setLargeRequestErrorMessage + }) + ) .unwrap() .then(result => { setPipelines( @@ -72,6 +80,7 @@ const RealTimePipelines = () => { ) ) }) + .catch(largeResponseCatchHandler) }, [dispatch, params.projectName] ) @@ -166,6 +175,7 @@ const RealTimePipelines = () => { filtersStore={filtersStore} handleExpandAll={handleExpandAll} handleExpandRow={handleExpandRow} + largeRequestErrorMessage={largeRequestErrorMessage} pageData={pageData} params={params} pipelines={pipelines} diff --git a/src/components/ModelsPage/RealTimePipelines/RealTimePipelinesView.js b/src/components/ModelsPage/RealTimePipelines/RealTimePipelinesView.js index 13df7da1c..c533b6d77 100644 --- a/src/components/ModelsPage/RealTimePipelines/RealTimePipelinesView.js +++ b/src/components/ModelsPage/RealTimePipelines/RealTimePipelinesView.js @@ -32,6 +32,7 @@ import { filters } from './realTimePipelines.util' import { MODELS_PAGE, REAL_TIME_PIPELINES_TAB } from '../../../constants' import NoData from '../../../common/NoData/NoData' import { getNoDataMessage } from '../../../utils/getNoDataMessage' +import { ACTIONS_MENU } from '../../../types' const RealTimePipelinesView = React.forwardRef( ( @@ -43,6 +44,7 @@ const RealTimePipelinesView = React.forwardRef( filtersStore, handleExpandAll, handleExpandRow, + largeRequestErrorMessage, pageData, params, pipelines, @@ -80,6 +82,7 @@ const RealTimePipelinesView = React.forwardRef( message={getNoDataMessage( filtersStore, filters, + largeRequestErrorMessage, MODELS_PAGE, REAL_TIME_PIPELINES_TAB )} @@ -122,13 +125,14 @@ const RealTimePipelinesView = React.forwardRef( ) RealTimePipelinesView.propTypes = { - actionsMenu: PropTypes.arrayOf(PropTypes.object).isRequired, + actionsMenu: ACTIONS_MENU.isRequired, artifactsStore: PropTypes.object.isRequired, expand: PropTypes.bool.isRequired, fetchData: PropTypes.func.isRequired, filtersStore: PropTypes.object.isRequired, handleExpandAll: PropTypes.func.isRequired, handleExpandRow: PropTypes.func.isRequired, + largeRequestErrorMessage: PropTypes.string.isRequired, pageData: PropTypes.object.isRequired, params: PropTypes.object.isRequired, pipelines: PropTypes.arrayOf(PropTypes.object).isRequired, diff --git a/src/components/Project/ProjectDescription/ProjectDescription.js b/src/components/Project/ProjectDescription/ProjectDescription.js index 9af885df9..f30594959 100644 --- a/src/components/Project/ProjectDescription/ProjectDescription.js +++ b/src/components/Project/ProjectDescription/ProjectDescription.js @@ -40,7 +40,7 @@ const ProjectDescription = ({