import './App.css';
import HomePage from './components/home/HomePage';
import 'bootstrap/dist/css/bootstrap.min.css';
+import Toaster from './components/toast/Toaster';
function App() {
return (
<div className='App'>
<HomePage />
+ <Toaster />
</div>
);
}
import { Row, Col } from 'react-bootstrap';
import { instance, UCMgr_baseUrl } from '../../../states';
import { featureGroupAPI } from '../../../apis';
+import { toast } from '../../../utils/toast-bus';
class CreateFeatureGroup extends React.Component {
constructor(props) {
handleFGNameChange = event => {
if (this.regName.test(event.target.value)) {
event.preventDefault();
- alert('Please use alphabet, number, and underscore to Feature Group Name.');
+ toast.info('Please use alphabet, number, and underscore to Feature Group Name.');
} else {
this.setState(
{
.then(res => {
this.logger('featureGroup Created', res.data);
if (res.status === 201) {
- alert('FeatureGroup Created');
+ toast.success('FeatureGroup Created', 'Feature Group');
this.resetForm();
}
})
.catch(error => {
this.logger('Error creating featureGroup', error);
- alert('Failed: ' + error.response.data.Exception);
+ toast.error('Failed: ' + error.response.data.Exception, 'Feature Group');
event.preventDefault();
})
.then(function () {
} from '../common/CommonMethods';
import { instance, UCMgr_baseUrl } from '../../../states';
import { featureGroupAPI, pipelineAPI, trainingJobAPI } from '../../../apis';
+import { toast } from '../../../utils/toast-bus';
class CreateTrainingJob extends React.Component {
constructor(props) {
.then(res => {
this.logger('Training responsed ', res);
if (res.status === 201) {
- alert('Training Job created and training initiated');
+ toast.success('Training Job created and training initiated', 'Training Job');
this.resetFrom();
this.props.onHideCreatePopup();
this.props.fetchTrainingJobs();
})
.catch(error => {
this.logger('Error creating Training Job', error);
- alert('Failed: ' + error.response.data.Exception);
+ toast.error('Failed: ' + error.response.data.Exception, 'Training Job');
event.preventDefault();
});
}
.catch(error => {
// handle error
this.logger('Error creating Use case', error);
- alert('Failed: ' + error.response.data.Exception);
+ toast.error('Failed: ' + error.response.data.Exception, 'Training Job');
event.preventDefault();
})
.then(function () {
.then(res => {
this.logger('Training responsed ', res);
if (res.status === 200) {
- alert('Training Job edited and training initiated');
+ toast.success('Training Job edited and training initiated', 'Training Job');
this.props.onHideEditPopup();
this.props.fetchTrainingJobs();
} else {
})
.catch(error => {
this.logger('Error in training api,response', error.response.data);
- alert('Training failed: ' + error.response.data.Exception);
+ toast.error('Training failed: ' + error.response.data.Exception, 'Training Job');
})
.then(function () {
// always executed
import Popover from 'react-bootstrap/Popover';
import { notebook_url, UCMgr_baseUrl } from '../../../states';
import { pipelineAPI } from '../../../apis/pipeline';
+import { toast } from '../../../utils/toast-bus';
class UploadPipelineForm extends Component {
constructor(props) {
console.log('Status responsed ', res.status);
if (res.status === 200) {
console.log('Pipeline uploaded ', res.status);
- alert(res.data.result);
+ toast.success(res.data.result, 'Pipeline');
this.resetFrom(event);
} else {
console.log('Upload pipeline error:', res);
})
.catch(error => {
console.log('Error in uploading pipeline', error.response);
- alert('Pipeline upload failed: ' + error.response.data.result);
+ toast.error('Pipeline upload failed: ' + error.response.data.result, 'Pipeline');
})
.then(function () {
// always executed
import { featureGroupAPI } from '../../../apis/feature-group';
import { trainingJobAPI } from '../../../apis/training-job';
+import { toast } from '../../../utils/toast-bus';
export const invokeStartTraining = async trainingjobNames => {
console.log('Retraining called ', trainingjobNames);
let res = await trainingJobAPI.invokeTrainingJob({ data: { trainingjobs_list: trainingjobNames } });
console.log('Retraining response', res);
let result = 'Retraining initiated for selected trainingjob(s),Result' + '\n' + JSON.stringify(res.data);
- alert(result);
+ toast.success(result, 'Training Job');
} catch (error) {
console.log(error);
}
let res = await trainingJobAPI.deleteTrainingJob({ params: {trainingJobId: job.id} });
console.log('Delete API response', res);
let result = `trainingjob deletion initiated for selected trainingjob ${job.id}, Result` + '\n' + JSON.stringify(res.status);
- alert(result);
+ toast.success(result, 'Training Job');
}
} catch (error) {
console.log(error);
let res = await featureGroupAPI.deleteFeatureGroup({ data: { data: { featuregroups_list: featureGroup_names } } });
console.log('Deletion response', res);
let result = 'FeatureGroup deletion initiated for selected featureGroups ,Result' + '\n' + JSON.stringify(res.data);
- alert(result);
+ toast.success(result, 'Feature Group');
} catch (error) {
console.log('error is : ', error);
}
import FeatureGroupInfo from './FeatureGroupInfo';
import CreateFeatureGroup from '../create/CreateFeatureGroup';
import { deleteFeatureGroups } from './API_STATUS';
+import { toast } from '../../../utils/toast-bus';
const ListFeatureGroup = props => {
const logger = props.logger;
}
toggleAllRowsSelected(false);
} else {
- alert('Please select more than one row');
+ toast.info('Please select more than one row');
}
};
import { Checkbox, Popup, StepsState, TrainingJobInfo } from '../../../components';
import { UCMgr_baseUrl } from '../../../states';
import { trainingJobAPI } from '../../../apis';
-
+import { toast } from '../../../utils/toast-bus';
import { invokeStartTraining, deleteTrainingjobs } from './API_STATUS';
import CreateOrEditTrainingJobForm from '../form/CreateOrEditTrainingJobForm';
import CreateTrainingJob from '../create/CreateTrainingJob';
}
toggleAllRowsSelected(false);
} else {
- alert('Please select atleast one trainingjob');
+ toast.info('Please select atleast one trainingjob');
}
};
setEditPopup(true);
toggleAllRowsSelected(false);
} else {
- alert('Please select exactly one trainingjob');
+ toast.info('Please select exactly one trainingjob');
}
};
}
toggleAllRowsSelected(false);
} else {
- alert('Please select atleast one trainingjob');
+ toast.info('Please select atleast one trainingjob');
}
};
--- /dev/null
+import React, { useEffect, useState } from 'react';
+import { Toast, ToastContainer } from 'react-bootstrap';
+import { toastBus } from '../../utils/toast-bus';
+
+export default function Toaster() {
+ const [items, setItems] = useState([]);
+ const MAX_TOASTS = 3;
+
+ useEffect(() => {
+ const handler = ({ msg, title, bg = 'dark', delay = 4000 }) => {
+ const id = Date.now() + Math.random();
+ setItems(prev => {
+ const next = [...prev, { id, msg, title, bg, delay }];
+ while (next.length > MAX_TOASTS) next.shift();
+ return next;
+ });
+ if (delay > 0) {
+ setTimeout(() => {
+ setItems(prev => prev.filter(i => i.id !== id));
+ }, delay);
+ }
+ };
+ toastBus.on(handler);
+ return () => toastBus.off(handler);
+ }, []);
+
+ return (
+ <ToastContainer position='top-end' className='p-3'>
+ {items.map(t => (
+ <Toast key={t.id} bg={t.bg} onClose={() => setItems(prev => prev.filter(i => i.id !== t.id))} autohide={false}>
+ {t.title ? (
+ <Toast.Header>
+ <strong className='me-auto'>{t.title}</strong>
+ </Toast.Header>
+ ) : null}
+ <Toast.Body style={{ color: 'white' }}>
+ {typeof t.msg === 'string' ? t.msg : JSON.stringify(t.msg)}
+ </Toast.Body>
+ </Toast>
+ ))}
+ </ToastContainer>
+ );
+}
--- /dev/null
+export const toastBus = {
+ _handlers: new Set(),
+ on(handler) {
+ this._handlers.add(handler);
+ },
+ off(handler) {
+ this._handlers.delete(handler);
+ },
+ emit(payload) {
+ for (const h of Array.from(this._handlers)) {
+ try { h(payload); } catch (e) { /* no-op */ }
+ }
+ }
+};
+
+export const toast = {
+ show: (msg, opts) => toastBus.emit({ msg, ...(opts || {}) }),
+ success: (msg, title = 'Success') => toastBus.emit({ msg, title, bg: 'success' }),
+ error: (msg, title = 'Error') => toastBus.emit({ msg, title, bg: 'danger', delay: 6000 }),
+ info: (msg, title = 'Info') => toastBus.emit({ msg, title, bg: 'info' }),
+ warning: (msg, title = 'Warning') => toastBus.emit({ msg, title, bg: 'warning' }),
+};