--- /dev/null
+// ==================================================================================
+
+// Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ==================================================================================
+
+import React from 'react';
+import CreateTrainingJob from './create/CreateTrainingJob';
+import StatusPageRows from './status/StatusPageRows';
+import UploadPipelineForm from './pipelines/UploadPipeline'
+import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
+import NavbarComponent from './navbar/NavbarComponent';
+
+class HomePage extends React.Component {
+
+ render() {
+ return (
+ <>
+ <Router>
+ <NavbarComponent />
+ <Switch>
+ <Route path='/' exact component={Home} />
+ <Route path='/TrainingJob/CreateTrainingJob' exact component={CreateTrainingJob} />
+ <Route path='/TrainingJob/TrainingJobsStatus' exact component={StatusPageRows} />
+ <Route path='/TrainingJob/Pipeline' exact component={UploadPipelineForm} />
+ </Switch>
+ </Router>
+ </>
+ );
+ }
+}
+
+export default HomePage;
+
+
+class Home extends React.Component{
+ render() {
+ return <></>;
+ }
+}
+
--- /dev/null
+// ==================================================================================
+
+// Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ==================================================================================
+
+import React from 'react'
+import Form from 'react-bootstrap/Form'
+import Button from 'react-bootstrap/Button'
+import axios from 'axios';
+import * as CONSTANTS from '../common/Constants'
+
+class UploadPipelineForm extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ fileName: '',
+ plName: '',
+ UCMgr_baseUrl: CONSTANTS.UCMgr_baseUrl
+ }
+ this.handleInputChange = this.handleInputChange.bind(this);
+ }
+
+ handleInputChange(event) {
+ console.log(event)
+ this.setState({
+ fileName: event.target.files[0]
+ })
+ console.log('handleInputChange',this.fileName)
+ }
+
+ handlePlNameChange = (event) => {
+ this.setState({
+ plName: event.target.value
+ })
+ }
+
+
+
+ resetFrom = (event)=> {
+ this.setState({
+ fileName: '',
+ plName: '',
+ })
+ console.log(this.state)
+ event.target.value = null;
+ }
+
+ handleSubmit = event => {
+ const data = new FormData()
+ data.append('file', this.state.fileName)
+
+ let url = this.state.UCMgr_baseUrl + "/pipelines/" + this.state.plName + "/upload";
+
+ //Option-3
+ axios.post(url,data
+ ).then(res => {
+ console.log('Pipeline responsed ', res)
+ console.log('Status responsed ', res.status)
+ if(res.status === 200) {
+ console.log('Pipeline uploaded ', res.status)
+ alert(res.data.result)
+ 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)
+ })
+ .then(function () {
+ // always executed
+ })
+
+ console.log('something')
+ event.preventDefault();
+ }
+
+ handleCreatePipeline = event => {
+ console.log('handleCreatePipeline clicked..', event)
+ window.open(CONSTANTS.notebook_url + '/tree', "_blank")
+ }
+
+ render() {
+ return (
+ <>
+ <div className="upload-pl-form" >
+
+ <Button variant="success" size="sm" onClick={e => this.handleCreatePipeline(e)} >
+ Create Pipeline
+ </Button>{' '}
+
+ <Form onSubmit={this.handleSubmit}>
+ <Form.Group controlId="plName">
+ <Form.Label>Pipeline Name*</Form.Label>
+ <Form.Control type="input"
+ value={this.state.plName}
+ onChange={this.handlePlNameChange}
+ placeholder=""
+ required/>
+ </Form.Group>
+
+ <input type="file" className="form-control"
+ name="upload_file" onChange={this.handleInputChange} />
+
+ <Button type="submit" > Upload </Button>
+
+ </Form>
+ </div>
+ </>
+
+ );
+ }
+}
+
+export default UploadPipelineForm;
\ No newline at end of file
--- /dev/null
+// ==================================================================================
+
+// Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ==================================================================================
+
+import React from 'react'
+
+export const Checkbox = React.forwardRef(
+ ({ indeterminate, ...rest }, ref) => {
+ const defaultRef = React.useRef()
+ const resolvedRef = ref || defaultRef
+
+ React.useEffect(() => {
+ resolvedRef.current.indeterminate = indeterminate
+ }, [resolvedRef, indeterminate])
+
+ return (
+ <>
+ <input type="checkbox" ref={resolvedRef} {...rest} />
+ </>
+ )
+ }
+ )
+
\ No newline at end of file
--- /dev/null
+// ==================================================================================
+
+// Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ==================================================================================
+
+
+import React from 'react';
+import {Modal} from 'react-bootstrap';
+
+function Popup(props){
+ return (
+ <>
+ <Modal show={props.show} onHide={props.onHide} size={props.hasOwnProperty('size') ? props.size : 'medium'} centered>
+ <Modal.Header closeButton>
+ <Modal.Title>
+ {props.title}
+ </Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ {props.children}
+ </Modal.Body>
+ </Modal>
+ </>
+ );
+}
+
+export default Popup;
\ No newline at end of file
--- /dev/null
+// ==================================================================================
+
+// Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ==================================================================================
+
+import React, { useMemo, useState, useEffect } from 'react';
+import BTable from 'react-bootstrap/Table';
+import Button from 'react-bootstrap/Button';
+import { useTable, useRowSelect } from 'react-table';
+import {UCMgr_baseUrl} from '../common/Constants';
+import axios from 'axios';
+import { Checkbox } from './Checkbox';
+import Popup from './Popup';
+import TrainingJobInfo from './TrainingJobInfo';
+import StepsState from './StepsState';
+
+const StatusPageRows = () => {
+
+ const [trainingJobs, setTrainingJobs] = useState([])
+
+ const [stepsStatePopup, setStepsStatePopup] = useState(false);
+ const [stepsStateTrainingJobAndVersion, setStepsStateTrainingJobNameAndVersion] = useState(null);
+ const closeStepsStatePopup = () => setStepsStatePopup(false);
+
+ const [infoPopup, setInfoPopup] = useState(false);
+ const [infoTrainingJobAndVersion, setInfoTrainingJobNameAndVersion] = useState(null);
+ const closeInfoPopup = () => setInfoPopup(false);
+
+ useEffect(() => {
+ console.log('useEffect');
+ fetchTrainingJobs();
+ const timer = setInterval(async ()=>{
+ fetchTrainingJobs();
+ }, 5000);
+ return ()=>clearInterval(timer);
+ }, []);
+
+
+
+ const fetchTrainingJobs = async () => {
+ console.log('fetchTrainingJobs UCMgr_baseUrl', UCMgr_baseUrl)
+ try {
+ const result = await axios.get(`${UCMgr_baseUrl}/trainingjobs/latest`);
+ console.log('fetchTrainingJobs Result', result);
+ console.log('Training Jobs are --> ', result.data.trainingjobs)
+ setTrainingJobs(result.data.trainingjobs);
+
+ } catch (e) {
+ console.error(e)
+ }
+ }
+
+
+ const handleStepStateClick = (trainingjob_name, version) => {
+ setStepsStateTrainingJobNameAndVersion({
+ trainingjob_name : trainingjob_name,
+ version : version
+ });
+ setStepsStatePopup(true);
+ };
+
+ const handleInfoClick = (trainingjob_name, version) => {
+ setInfoTrainingJobNameAndVersion({
+ trainingjob_name : trainingjob_name,
+ version : version
+ });
+ setInfoPopup(true);
+ };
+
+ const columns = useMemo(() => [
+ {
+ id: 'selection',
+ Header: ({ getToggleAllRowsSelectedProps }) => (
+ <div>
+ <Checkbox {...getToggleAllRowsSelectedProps()} />
+ </div>
+ ),
+ Cell: ({ row }) => (
+ <div>
+ <Checkbox {...row.getToggleRowSelectedProps()} />
+ </div>
+ ),
+ },
+ {
+ id : 'trainingjob_name',
+ Header : 'Training Job Name',
+ accessor : 'trainingjob_name'
+ },
+ {
+ id : 'version',
+ Header : 'Version',
+ accessor : 'version'
+ },
+ {
+ id : 'overall_status',
+ Header : 'Overall Status',
+ accessor : row => row.overall_status === 'IN_PROGRESS' ? 'IN PROGRESS' : row.overall_status
+ },
+ {
+ id : 'stepsState',
+ Header : 'Detailed Status',
+ Cell : ({row}) => {
+ return (
+ <Button variant="info" onClick={() => handleStepStateClick(row.original.trainingjob_name, row.original.version)}>Detailed Status</Button>
+ );
+ }
+ },
+ {
+ id : 'info',
+ Header : 'Info',
+ Cell : ({row}) => {
+ return (
+ <Button variant="info" onClick={() => handleInfoClick(row.original.trainingjob_name, row.original.version)}>Info</Button>
+ );
+ }
+ }
+ ], []);
+ const data = useMemo(() => trainingJobs, [trainingJobs]);
+
+ const {
+ getTableProps,
+ headerGroups,
+ rows,
+ prepareRow,
+ selectedFlatRows,
+ toggleAllRowsSelected
+ } = useTable(
+ {
+ columns,
+ data,
+ autoResetSelectedRows : false
+ },
+ useRowSelect
+ )
+
+ return (
+ <>
+
+
+ <BTable className="Status_table" responsive striped bordered hover size="sm" {...getTableProps()}>
+
+ <thead>
+ {headerGroups.map(headerGroup => (
+ <tr {...headerGroup.getHeaderGroupProps()}>
+ {headerGroup.headers.map(column => (
+ <th {...column.getHeaderProps()}>
+ {column.render('Header')}
+ </th>
+ ))}
+ </tr>
+ ))}
+ </thead>
+
+ <tbody>
+ {rows.map((row, i) => {
+ prepareRow(row)
+ return (
+ <tr {...row.getRowProps()}>
+ {row.cells.map(cell => {
+ return (
+ <th {...cell.getCellProps()}>
+ {cell.render('Cell')}
+ </th>
+ )
+ })}
+ </tr>
+ )
+ })}
+ </tbody>
+ </BTable>
+ <Popup size="sm" show={stepsStatePopup} onHide={closeStepsStatePopup} title="Detailed Status">
+ <StepsState trainingjob_name_and_version={stepsStateTrainingJobAndVersion}></StepsState>
+ </Popup>
+ <Popup show={infoPopup} onHide={closeInfoPopup} title="Training Job Info">
+ <TrainingJobInfo trainingjob_name_and_version={infoTrainingJobAndVersion}/>
+ </Popup>
+ </>
+ );
+}
+
+export default StatusPageRows;
--- /dev/null
+ /* ==================================================================================
+
+ Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ ================================================================================== */
+
+.step-progressbar-wrapper{
+
+}
+
+.state{
+ background-color: white;
+ border: 2px solid black;
+ height: 30px;
+ width: 30px;
+ border-radius: 50%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.step{
+ max-width: 400px;
+}
+
+.step-progress-bar-box{
+ display: flex;
+ align-items: center;
+ column-gap: 20px;
+ border: 2px solid pink;
+ padding: 10px;
+}
+
+.step-progress-bar-box-line{
+ border-right: 3px solid black;
+ height: 50px;
+ width: 50%;
+}
+
+.container-for-step-progress-bar-box-line-and-message{
+ display: flex;
+ column-gap: 20px;
+}
+
+.step-progress-bar-box-line-messsage{
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+
+
+
--- /dev/null
+// ==================================================================================
+
+// Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ==================================================================================
+
+import React, { useEffect, useState } from 'react';
+import axios from "axios";
+import './StepsState.css';
+import { UCMgr_baseUrl } from '../common/Constants';
+
+const StepsState = (props) => {
+ const [boxesState, setBoxesState] = useState([]);
+ const [connectionsState, setConnectionsState] = useState([]);
+ const [boxes, setBoxes] = useState([]);
+ useEffect(()=>{
+ const periodicTask = async () => {
+ let res = null;
+ try{
+ res = await axios.get(`${UCMgr_baseUrl}/trainingjobs/${props.trainingjob_name_and_version.trainingjob_name}/${props.trainingjob_name_and_version.version}/steps_state`);
+ }
+ catch(error){
+ console.log(error);
+ }
+ const json_from_backend = res.data;
+ console.log(`response for ${UCMgr_baseUrl}/trainingjobs/${props.trainingjob_name_and_version.trainingjob_name}/${props.trainingjob_name_and_version.version}/steps_state` , res);
+ const newBoxesState = [];
+ const newConnectionsState = [];
+ const newBoxes = ['Data extraction' , 'Training', 'Trained Model'];
+
+
+ newBoxesState.push(json_from_backend.DATA_EXTRACTION);
+ newBoxesState.push(json_from_backend.TRAINING);
+ newBoxesState.push(json_from_backend.TRAINED_MODEL);
+ if(json_from_backend.hasOwnProperty('DEPLOYMENT')){
+ newBoxesState.push(json_from_backend.DEPLOYMENT);
+ newBoxes.push('Deployment');
+ }
+ setBoxesState(newBoxesState);
+ setBoxes(newBoxes);
+
+ newConnectionsState.push(json_from_backend.DATA_EXTRACTION_AND_TRAINING);
+ newConnectionsState.push(json_from_backend.TRAINING_AND_TRAINED_MODEL);
+ if(json_from_backend.hasOwnProperty('TRAINED_MODEL_AND_DEPLOYMENT')){
+ newConnectionsState.push(json_from_backend.TRAINED_MODEL_AND_DEPLOYMENT);
+ }
+ setConnectionsState(newConnectionsState);
+ };
+ periodicTask();
+ const timer = setInterval( async () => {
+ periodicTask();
+ }, 5000);
+ return () => clearInterval(timer);
+
+
+ },[props.trainingjob_name_and_version]);
+
+ return (
+ <div className='step-progressbar-wrapper'>
+ {
+ boxes.map((item, index) => {
+ return (
+ <div key={index}>
+ <div className='step-progress-bar-box'>
+ <div className='state'>
+ {boxesState[index] === 'NOT_STARTED' ? index + 1 :
+ boxesState[index] === 'FINISHED' ? '✔' :
+ boxesState[index] === 'FAILED' ? '❌' :
+ '⌛'}
+ </div>
+ <div className='step'>
+ {item}
+ </div>
+ </div>
+ { index + 1 !== boxes.length &&
+
+ <div className='container-for-step-progress-bar-box-line-and-message'>
+ <div className='step-progress-bar-box-line'/>
+ <div className='step-progress-bar-box-line-messsage'>
+ {
+ connectionsState[index] === 'NOT_STARTED' ? 'Not started' :
+ connectionsState[index] === 'FINISHED' ? '✔ Finished' :
+ connectionsState[index] === 'FAILED' ? '❌ Failed' :
+ '⌛ In progress'
+ }
+ </div>
+ </div>
+ }
+ </div>
+ )
+ })
+ }
+ </div>
+ );
+};
+
+export default StepsState;
\ No newline at end of file
--- /dev/null
+// ==================================================================================
+
+// Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ==================================================================================
+
+import React, { useEffect, useState } from 'react';
+import { Form } from 'react-bootstrap';
+import axios from 'axios';
+import { UCMgr_baseUrl } from '../common/Constants';
+import {convertToCommaSeparatedString, getDatalakeNameWithoutConversion} from '../common/CommonMethods';
+
+const TrainingJobInfo = (props) => {
+ const [trainingJobName, setTrainingJobName] = useState("");
+ const [version, setVersion] = useState("");
+ const [description, setDescription] = useState("");
+ const [featureNames, setFeatureNames] = useState("");
+ const [pipeLineName, setPipelineName] = useState("");
+ const [experimentName, setExperimentName] = useState("");
+ const [featureFilter, setFeatureFilter] = useState("");
+ const [hyperParameters, setHyperParameters] = useState("");
+ const [metrics, setMetrics] = useState("");
+ const [enableVersioning, setEnableVersioning] = useState(false);
+ const [pipelineVersion, setPipelineVersion] = useState("");
+ const [datalakeSource, setDatalakeSource] = useState("");
+ const [modelUrl, setModelUrl] = useState("");
+ const [_measurement, set_measurement] = useState("");
+ const [bucket, setBucket] = useState("");
+
+ useEffect(()=>{
+ try{
+ axios.get(`${UCMgr_baseUrl}/trainingjobs/${props.trainingjob_name_and_version.trainingjob_name}/${props.trainingjob_name_and_version.version}`)
+ .then(response => {
+ console.log(`response for ${UCMgr_baseUrl}/trainingjobs/${props.trainingjob_name_and_version.trainingjob_name}/${props.trainingjob_name_and_version.version}`, response);
+ console.log(response.data);
+ setTrainingJobName(response.data.trainingjob.trainingjob_name);
+ setVersion(response.data.trainingjob.version);
+ setDescription(response.data.trainingjob.description);
+ setFeatureNames(response.data.trainingjob.feature_list);
+ setPipelineName(response.data.trainingjob.pipeline_name);
+ setExperimentName(response.data.trainingjob.experiment_name);
+ setFeatureFilter(response.data.trainingjob.query_filter);
+ setHyperParameters(convertToCommaSeparatedString(response.data.trainingjob.arguments));
+ setMetrics(response.data.trainingjob.accuracy);
+ setEnableVersioning(response.data.trainingjob.enable_versioning);
+ setPipelineVersion(response.data.trainingjob.pipeline_version === response.data.trainingjob.pipeline_name ? "1" : response.data.trainingjob.pipeline_version);
+ setDatalakeSource(getDatalakeNameWithoutConversion(response.data.trainingjob.datalake_source));
+ setModelUrl(response.data.trainingjob.model_url);
+ set_measurement(response.data.trainingjob._measurement);
+ setBucket(response.data.trainingjob.bucket);
+ })
+ .catch(error => {
+ console.log(error);
+ });
+ }
+ catch(error){
+ console.log(error);
+ }
+ },[props.trainingjob_name_and_version]);
+
+
+ return (
+ <>
+ <Form>
+ <Form.Group controlId="ucName">
+ <Form.Label>Training Job Name</Form.Label>
+ <Form.Control type="text" value={trainingJobName} readOnly/>
+ </Form.Group>
+ <Form.Group controlId="version">
+ <Form.Label>Version</Form.Label>
+ <Form.Control type="text" value={version} readOnly />
+ </Form.Group>
+ <Form.Group controlId="description">
+ <Form.Label>Description</Form.Label>
+ <Form.Control type="text" value={description} readOnly />
+ </Form.Group>
+ <Form.Group controlId="featureNames">
+ <Form.Label>Feature Names</Form.Label>
+ <Form.Control type="text" value={featureNames} readOnly />
+ </Form.Group>
+ <Form.Group controlId="pipelineName">
+ <Form.Label>Pipeline Name</Form.Label>
+ <Form.Control type="text" value={pipeLineName} readOnly />
+ </Form.Group>
+ <Form.Group controlId="experimentName">
+ <Form.Label>Experiment Name</Form.Label>
+ <Form.Control type="text" value={experimentName} readOnly />
+ </Form.Group>
+ <Form.Group controlId="featureFilter">
+ <Form.Label>Feature Filter</Form.Label>
+ <Form.Control type="text" value={featureFilter} readOnly />
+ </Form.Group>
+ <Form.Group controlId="hyperParameters">
+ <Form.Label>Hyper Parameters</Form.Label>
+ <Form.Control type="text" value={hyperParameters} readOnly />
+ </Form.Group>
+ <Form.Group controlId="metrics">
+ <Form.Label>Metrics</Form.Label>
+ <Form.Control type="text" value={metrics} readOnly />
+ </Form.Group>
+ <Form.Group id="enableVersioning">
+ <Form.Check type="checkbox" label="Enable versioning"
+ checked={enableVersioning} readOnly/>
+ </Form.Group>
+ <Form.Group controlId="pipelineVersion">
+ <Form.Label>Pipeline Version</Form.Label>
+ <Form.Control type="text" value={pipelineVersion} readOnly />
+ </Form.Group>
+ <Form.Group controlId="datalakeSource">
+ <Form.Label>Datalake Source</Form.Label>
+ <Form.Control type="text" value={datalakeSource} readOnly />
+ </Form.Group>
+ {
+ datalakeSource === "Influx DB" &&
+ <>
+ <Form.Group controlId="_measurement">
+ <Form.Label>_measurement</Form.Label>
+ <Form.Control type="text" value={_measurement} readOnly />
+ </Form.Group>
+ <Form.Group controlId="bucket">
+ <Form.Label>bucket</Form.Label>
+ <Form.Control type="text" value={bucket} readOnly />
+ </Form.Group>
+ </>
+ }
+ <Form.Group controlId="modelUrl">
+ <Form.Label>Model URL</Form.Label>
+ <Form.Control type="text" value={modelUrl} readOnly />
+ </Form.Group>
+ </Form>
+ </>
+ );
+}
+
+export default TrainingJobInfo;
\ No newline at end of file