Loading js-apps/frontend/src/js/app-constants.js +5 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ export const SANDBOX_MEC_API = 'sandbox-mec-api'; // Dialog IDs export const DLG_DETAILED_DATA = 'dlg-detailed-data'; export const DLG_SIGN_IN = 'dlg-sign-in'; export const DLG_CONFIRM_DELETE_APP = 'dlg-confirm-delete-app'; export const DLG_CREATE_NEW_APP = 'dlg-create-new-app'; // Dialog Types export const DIALOG_DETAILED_DATA = 'DIALOG_DETAILED_DATA'; Loading @@ -50,6 +52,8 @@ export const DIALOG_SIGN_IN = 'DIALOG_SIGN_IN'; export const DIALOG_SIGN_IN_WAIT = 'DIALOG_SIGN_IN_WAIT'; export const DIALOG_SESSION_TERMINATED = 'DIALOG_SESSION_TERMINATED'; export const DIALOG_HELP_GETTING_STARTED = 'DIALOG_HELP_GETTING_STARTED'; export const DIALOG_CONFIRM_DELETE_APP = 'DIALOG_CONFIRM_DELETE_APP'; export const DIALOG_CREATE_NEW_APP = 'DIALOG_CREATE_NEW_APP'; // Alert Types export const ALERT_DEGRADED_NETWORK = 'ALERT_DEGRADED_NETWORK'; Loading Loading @@ -110,3 +114,4 @@ export const ELEMENT_TYPE_MECSVC = 'MEC SERVICE'; export const ELEMENT_TYPE_UE_APP = 'UE APPLICATION'; export const ELEMENT_TYPE_EDGE_APP = 'EDGE APPLICATION'; export const ELEMENT_TYPE_CLOUD_APP = 'CLOUD APPLICATION'; js-apps/frontend/src/js/components/dialogs/confirm-delete-app-dialog.js 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020 ETSI. All rights reserved. */ import React, { Component } from 'react'; import BasicDialog from './basic-dialog'; import { DLG_CONFIRM_DELETE_APP } from '../../app-constants'; class ConfirmDeleteAppDialog extends Component { constructor(props) { super(props); } deleteConfirmed() { this.props.onSubmit(); } onClose(/*closeFromSubmit*/) { this.props.onClose(); } render() { return ( <BasicDialog title={this.props.title} open={this.props.open} onSubmit={() => this.deleteConfirmed()} onClose={(closeFromSubmit) => this.onClose(closeFromSubmit)} closeLabel = {'CANCEL'} submitLabel = {'DELETE'} cydata={DLG_CONFIRM_DELETE_APP} > <p>Are you sure you want to delete the selected application instances?</p> </BasicDialog> ); } } export default ConfirmDeleteAppDialog; js-apps/frontend/src/js/components/dialogs/create-new-app-dialog.js 0 → 100644 +125 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020 ETSI. All rights reserved. */ import React, { Component } from 'react'; import { TextField, TextFieldHelperText } from '@rmwc/textfield'; import { Typography } from '@rmwc/typography'; import { Select } from '@rmwc/select'; import BasicDialog from './basic-dialog'; import { DLG_CREATE_NEW_APP } from '../../app-constants'; class CreateNewAppDialog extends Component { constructor(props) { super(props); this.state = { appName: null, appErr: null, mepName: null }; } changeAppName(name) { var err = null; if (name) { if (name.length > 20) { err = 'Maximum 20 characters'; } else if (!name.match(/^(([A-Za-z0-9][-A-Za-z0-9.]*)?[@.-A-Za-z0-9])+$/)) { err = 'Alphanumeric or \'@.-\''; } } else { err = 'Please enter an application name'; } this.setState({ appName: name, appErr: err }); } changeMepName(name) { this.setState({ mepName: name }); } submitApp() { this.props.onSubmit(this.state); } onClose(closeFromSubmit) { if (closeFromSubmit === true) { this.submitApp(); } this.props.onClose(); this.changeMepName(null); this.setState({ appName: null, appErr: null, mepName: null }); } render() { return ( <BasicDialog title={this.props.title} open={this.props.open} onSubmit={() => this.submitApp()} onClose={(closeFromSubmit) => this.onClose(closeFromSubmit)} closeLabel = {'CANCEL'} submitLabel = {'CREATE'} okDisabled={ (!this.state.appName || this.state.appErr || this.state.mepName === null) } cydata={DLG_CREATE_NEW_APP} > { this.props.errorMsg && <Typography use="body1" style={styles.errorText}>{this.props.errorMsg}</Typography> } <p/> <Typography use="body1">Unique name of the application instance</Typography><p/> <TextField outlined style={{ width: '70%' }} label={'Application Name'} invalid={ this.state.appErr } value={this.state.appName} onChange={e => this.changeAppName(e.target.value)} /> <TextFieldHelperText validationMsg={true}> <span>{this.state.appErr}</span> </TextFieldHelperText> <Typography use="body1">MEC platform where the application instance is running</Typography> <p/> <Select title="Select a MEC platform" style={{ width: '70%' }} label="MEC platform" fullwidth="true" outlined disabled={false} value={this.state.mepName} options={this.props.mepNames} onChange={mepName => { this.changeMepName(mepName.target.value); }} /> </BasicDialog> ); } } const styles = { errorText: { color: 'red' } }; export default CreateNewAppDialog; js-apps/frontend/src/js/components/dialogs/detailed-data-dialog.js +23 −5 Original line number Diff line number Diff line Loading @@ -77,16 +77,34 @@ class DetailedDataDialog extends Component { } mapService(loggerName) { switch(loggerName) { //loggerName is a combination of loggerName and mep name let prefixes = ['meep-loc-serv', 'meep-rnis', 'meep-wais', 'meep-app-enablement']; let prefixStd = ''; var prefix = ''; for (var i = 0; i < prefixes.length; i++) { if (loggerName.startsWith(prefixes[i])) { prefix = prefixes[i]; break; } } switch(prefix) { case 'meep-loc-serv': return '013'; prefixStd = '013'; break; case 'meep-rnis': return '012'; prefixStd = '012'; break; case 'meep-wais': return '028'; prefixStd = '028'; break; case 'meep-app-enablement': prefixStd = '011'; break; default: return 'N/A'; prefixStd = 'N/A'; } return loggerName.replace(prefix, prefixStd); } mapDirection(direction) { Loading js-apps/frontend/src/js/containers/app-container.js +137 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ import SignInOAuthDialog from '../components/dialogs/sign-in-oauth-dialog'; import SignInWaitDialog from '../components/dialogs/sign-in-wait-dialog'; import SessionTerminatedDialog from '../components/dialogs/session-terminated-dialog'; import HelpGettingStartedDialog from '../components/dialogs/help-getting-started-dialog'; import ConfirmDeleteAppDialog from '../components/dialogs/confirm-delete-app-dialog'; import CreateNewAppDialog from '../components/dialogs/create-new-app-dialog'; import * as meepAuthSvcRestApiClient from '../../../../../js-packages/meep-auth-svc-client/src/index.js'; import * as meepPlatformCtrlRestApiClient from '../../../../../js-packages/meep-platform-ctrl-client/src/index.js'; Loading @@ -39,6 +41,8 @@ import { DIALOG_SIGN_IN_WAIT, DIALOG_SESSION_TERMINATED, DIALOG_HELP_GETTING_STARTED, DIALOG_CONFIRM_DELETE_APP, DIALOG_CREATE_NEW_APP, ALERT_DEGRADED_NETWORK, STATUS_SIGNED_IN, STATUS_SIGNING_IN, Loading @@ -64,6 +68,8 @@ import { uiSandboxChangeStationaryUeList, uiSandboxChangeLowVelocityUeList, uiSandboxChangeHighVelocityUeList, uiSandboxChangeMepList, uiSandboxChangeAppInstancesSelected, uiSandboxChangePauseButton, uiSandboxChangeApiDetailedData, uiChangeSignInStatus, Loading @@ -80,7 +86,8 @@ import { sboxChangeMapUeList, sboxChangeMapPoaList, sboxChangeMapComputeList, sboxChangeApiTable sboxChangeApiTable, sboxChangeAppInstancesTable } from '../state/sbox'; const SBOX_ERR_COUNT_MAX = 5; Loading @@ -98,10 +105,11 @@ var basepathMonEngine = ''; const apiTableMaxSize = 100; var metricsQuery = { tags: [{ /* tags: [{ name: 'logger_name', value: 'meep-loc-serv,meep-rnis,meep-wais' value: 'meep-loc-serv,meep-rnis,meep-wais,meep-app-enablement' }], */ fields: ['id', 'endpoint', 'url', 'method', 'resp_code', 'resp_body', 'body', 'proc_time', 'logger_name', 'direction'], scope: { limit: apiTableMaxSize, Loading Loading @@ -141,6 +149,7 @@ class AppContainer extends Component { this.meepSandboxControlApi = new meepPlatformCtrlRestApiClient.SandboxControlApi(); this.meepActiveScenarioApi = new meepSandboxCtrlRestApiClient.ActiveScenarioApi(); this.meepEventsApi = new meepSandboxCtrlRestApiClient.EventsApi(); this.meepAppInfoApi = new meepSandboxCtrlRestApiClient.ApplicationsApi(); this.meepMetricsEngineApi = new meepMetricsEngineRestApiClient.MetricsApi(); this.meepGisAutomationApi = new meepGisEngineRestApiClient.AutomationApi(); this.meepGeoDataApi = new meepGisEngineRestApiClient.GeospatialDataApi(); Loading @@ -167,6 +176,12 @@ class AppContainer extends Component { if (this.props.highVelocityUeList === undefined) { this.props.changeHighVelocityUeList([]); } if (this.props.mepList === undefined) { this.props.changeMepList([]); } if (this.props.appInstancesSelected === undefined) { this.props.changeAppInstancesSelected([]); } if (this.props.helpOnSignIn === undefined) { this.props.changeHelpOnSignIn(true); } Loading Loading @@ -274,6 +289,7 @@ class AppContainer extends Component { this.refreshScenario(); this.refreshMap(); this.refreshMetricsTable(); this.refreshAppInstancesTable(); } } }, Loading Loading @@ -462,6 +478,67 @@ class AppContainer extends Component { window.location.href = HOST_PATH + '/auth/v1/login?provider=' + provider + '&sbox=true'; } deleteAppInstances() { var appInstances = this.props.appInstancesSelected; for (var i = 0; i < appInstances.length; i++) { this.meepAppInfoApi.applicationsAppInstanceIdDELETE(appInstances[i], null); } this.props.changeAppInstancesSelected([]); } createAppInstance(param) { var formParams = { 'name': param.appName, 'mepName': param.mepName, 'type': 'USER', 'state': 'INITIALIZED' }; this.meepAppInfoApi.applicationsPOST(formParams, (error, data, response) => { this.createAppInstanceCb(error, data, response); }); this.props.changeCurrentDialog(null); } /** * Callback function to receive the result of the loginUser operation. * @callback module:api/AppInfo~createAppInstanceIdCallback * @param {String} error Error message, if any. * @param {appInstanceObject} data The data returned by the service call. * @param {String} response The complete HTTP response. */ createAppInstanceCb(error, data) { if (error) { var errMsg; switch (error.status) { case StatusCodes.UNAUTHORIZED: errMsg = 'Invalid credentials. Please try again...'; break; case StatusCodes.SERVICE_UNAVAILABLE: errMsg = 'All MEC Sandboxes are currently in use. Please try again later...'; break; default: errMsg = 'Login failure. Please try again...'; break; } this.props.changeDialogErrorMsg(errMsg); this.props.changeCurrentDialog(DIALOG_CREATE_NEW_APP); return; } // Get sandbox name on successful login var appInstanceId = data ? data.id : ''; // Handle applicationinstance creation error if (!appInstanceId) { this.props.changeDialogErrorMsg('Failed to create a new App Instance, try again...'); this.props.changeCurrentDialog(DIALOG_CREATE_NEW_APP); return; } // clearing error this.props.changeDialogErrorMsg(''); } updateAutomation(pauseButtonEnabled) { this.meepGisAutomationApi.setAutomationStateByName('MOVEMENT', !pauseButtonEnabled); this.meepGisAutomationApi.setAutomationStateByName('MOBILITY', !pauseButtonEnabled); Loading Loading @@ -879,7 +956,9 @@ class AppContainer extends Component { // only update if values present, otherwise means no changes if (data) { data.values = this.mergeApiTableData(this.props.tableData.values, data.values); if (this.props.tableData.apiTable !== null) { data.values = this.mergeApiTableData(this.props.tableData.apiTable.values, data.values); } this.props.changeApiTable(data); } } Loading @@ -899,6 +978,34 @@ class AppContainer extends Component { } } /** * Callback function to receive the result of the postHttpQuery operation. * @callback module:api/AppsApi~applicationsGET * @param {String} error Error message, if any. * @param {module:model/ApplicationInfo} data The data returned by the service call. * @param {String} response The complete HTTP response. */ getAppInstancesCb(error, data) { if (error !== null) { this.props.changeAppInstancesTable([]); return; } // only update if values present, otherwise means no changes if (data) { //flush global app instances this.props.changeAppInstancesTable(data); } else { this.props.changeAppInstancesTable([]); } } refreshAppInstancesTable() { this.meepAppInfoApi.applicationsGET(null, (error, data, response) => { this.getAppInstancesCb(error, data, response); }); } renderPage() { switch (this.props.page) { case PAGE_HOME: Loading @@ -917,6 +1024,7 @@ class AppContainer extends Component { eventsApi={this.meepEventsApi} metricsApi={this.meepMetricsEngineApi} automationApi={this.meepGisAutomationApi} applicationsApi={this.meepAppInfoApi} /> ); Loading Loading @@ -974,6 +1082,25 @@ class AppContainer extends Component { this.closeDialog(); }} /> <ConfirmDeleteAppDialog title='Application instance deletion' open={this.props.currentDialog === DIALOG_CONFIRM_DELETE_APP} onSubmit={() => { this.deleteAppInstances(); }} onClose={() => { this.closeDialog(); }} /> <CreateNewAppDialog title='Application instance creation' open={this.props.currentDialog === DIALOG_CREATE_NEW_APP} onSubmit={param => this.createAppInstance(param)} onClose={() => { this.closeDialog(); }} mepNames={this.props.mepList.meps} /> </> ); } Loading Loading @@ -1027,6 +1154,7 @@ const mapStateToProps = state => { signInStatus: state.ui.signInStatus, signInUsername: state.ui.signInUsername, dialogErrorMsg: state.ui.dialogErrorMsg, networkFiles: state.ui.networkFiles, networkFileSelected: state.ui.networkFileSelected, tableData: state.sbox.apiTable, highVelocityUeList: state.ui.highVelocityUeList, Loading @@ -1034,6 +1162,8 @@ const mapStateToProps = state => { stationaryUeList: state.ui.stationaryUeList, nbLowVelocityUe: state.ui.nbLowVelocityUe, nbHighVelocityUe: state.ui.nbHighVelocityUe, mepList: state.ui.mepList, appInstancesSelected: state.ui.appInstancesSelected, updateUeInProgressCount: state.ui.updateUeInProgressCount, activationInProgressCount: state.ui.activationInProgressCount, activationInProgressScenarioName: state.ui.activationInProgressScenarioName, Loading @@ -1058,6 +1188,8 @@ const mapDispatchToProps = dispatch => { changeStationaryUeList: list => dispatch(uiSandboxChangeStationaryUeList(list)), changeLowVelocityUeList: list => dispatch(uiSandboxChangeLowVelocityUeList(list)), changeHighVelocityUeList: list => dispatch(uiSandboxChangeHighVelocityUeList(list)), changeMepList: list => dispatch(uiSandboxChangeMepList(list)), changeAppInstancesSelected: list => dispatch(uiSandboxChangeAppInstancesSelected(list)), changePauseButton: checked => dispatch(uiSandboxChangePauseButton(checked)), changeApiDetailedData: row => dispatch(uiSandboxChangeApiDetailedData(row)), changeSignInStatus: status => dispatch(uiChangeSignInStatus(status)), Loading @@ -1070,6 +1202,7 @@ const mapDispatchToProps = dispatch => { changeMapPoaList: list => dispatch(sboxChangeMapPoaList(list)), changeMapComputeList: list => dispatch(sboxChangeMapComputeList(list)), changeApiTable: value => dispatch(sboxChangeApiTable(value)), changeAppInstancesTable: value => dispatch(sboxChangeAppInstancesTable(value)), changeUpdateUeInProgressCount: count => dispatch(uiSandboxChangeUpdateUeInProgressCount(count)), changeActivationInProgressCount: count => dispatch(uiSandboxChangeActivationInProgressCount(count)), changeActivationInProgressScenarioName: name => dispatch(uiSandboxChangeActivationInProgressScenarioName(name)) Loading Loading
js-apps/frontend/src/js/app-constants.js +5 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ export const SANDBOX_MEC_API = 'sandbox-mec-api'; // Dialog IDs export const DLG_DETAILED_DATA = 'dlg-detailed-data'; export const DLG_SIGN_IN = 'dlg-sign-in'; export const DLG_CONFIRM_DELETE_APP = 'dlg-confirm-delete-app'; export const DLG_CREATE_NEW_APP = 'dlg-create-new-app'; // Dialog Types export const DIALOG_DETAILED_DATA = 'DIALOG_DETAILED_DATA'; Loading @@ -50,6 +52,8 @@ export const DIALOG_SIGN_IN = 'DIALOG_SIGN_IN'; export const DIALOG_SIGN_IN_WAIT = 'DIALOG_SIGN_IN_WAIT'; export const DIALOG_SESSION_TERMINATED = 'DIALOG_SESSION_TERMINATED'; export const DIALOG_HELP_GETTING_STARTED = 'DIALOG_HELP_GETTING_STARTED'; export const DIALOG_CONFIRM_DELETE_APP = 'DIALOG_CONFIRM_DELETE_APP'; export const DIALOG_CREATE_NEW_APP = 'DIALOG_CREATE_NEW_APP'; // Alert Types export const ALERT_DEGRADED_NETWORK = 'ALERT_DEGRADED_NETWORK'; Loading Loading @@ -110,3 +114,4 @@ export const ELEMENT_TYPE_MECSVC = 'MEC SERVICE'; export const ELEMENT_TYPE_UE_APP = 'UE APPLICATION'; export const ELEMENT_TYPE_EDGE_APP = 'EDGE APPLICATION'; export const ELEMENT_TYPE_CLOUD_APP = 'CLOUD APPLICATION';
js-apps/frontend/src/js/components/dialogs/confirm-delete-app-dialog.js 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020 ETSI. All rights reserved. */ import React, { Component } from 'react'; import BasicDialog from './basic-dialog'; import { DLG_CONFIRM_DELETE_APP } from '../../app-constants'; class ConfirmDeleteAppDialog extends Component { constructor(props) { super(props); } deleteConfirmed() { this.props.onSubmit(); } onClose(/*closeFromSubmit*/) { this.props.onClose(); } render() { return ( <BasicDialog title={this.props.title} open={this.props.open} onSubmit={() => this.deleteConfirmed()} onClose={(closeFromSubmit) => this.onClose(closeFromSubmit)} closeLabel = {'CANCEL'} submitLabel = {'DELETE'} cydata={DLG_CONFIRM_DELETE_APP} > <p>Are you sure you want to delete the selected application instances?</p> </BasicDialog> ); } } export default ConfirmDeleteAppDialog;
js-apps/frontend/src/js/components/dialogs/create-new-app-dialog.js 0 → 100644 +125 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020 ETSI. All rights reserved. */ import React, { Component } from 'react'; import { TextField, TextFieldHelperText } from '@rmwc/textfield'; import { Typography } from '@rmwc/typography'; import { Select } from '@rmwc/select'; import BasicDialog from './basic-dialog'; import { DLG_CREATE_NEW_APP } from '../../app-constants'; class CreateNewAppDialog extends Component { constructor(props) { super(props); this.state = { appName: null, appErr: null, mepName: null }; } changeAppName(name) { var err = null; if (name) { if (name.length > 20) { err = 'Maximum 20 characters'; } else if (!name.match(/^(([A-Za-z0-9][-A-Za-z0-9.]*)?[@.-A-Za-z0-9])+$/)) { err = 'Alphanumeric or \'@.-\''; } } else { err = 'Please enter an application name'; } this.setState({ appName: name, appErr: err }); } changeMepName(name) { this.setState({ mepName: name }); } submitApp() { this.props.onSubmit(this.state); } onClose(closeFromSubmit) { if (closeFromSubmit === true) { this.submitApp(); } this.props.onClose(); this.changeMepName(null); this.setState({ appName: null, appErr: null, mepName: null }); } render() { return ( <BasicDialog title={this.props.title} open={this.props.open} onSubmit={() => this.submitApp()} onClose={(closeFromSubmit) => this.onClose(closeFromSubmit)} closeLabel = {'CANCEL'} submitLabel = {'CREATE'} okDisabled={ (!this.state.appName || this.state.appErr || this.state.mepName === null) } cydata={DLG_CREATE_NEW_APP} > { this.props.errorMsg && <Typography use="body1" style={styles.errorText}>{this.props.errorMsg}</Typography> } <p/> <Typography use="body1">Unique name of the application instance</Typography><p/> <TextField outlined style={{ width: '70%' }} label={'Application Name'} invalid={ this.state.appErr } value={this.state.appName} onChange={e => this.changeAppName(e.target.value)} /> <TextFieldHelperText validationMsg={true}> <span>{this.state.appErr}</span> </TextFieldHelperText> <Typography use="body1">MEC platform where the application instance is running</Typography> <p/> <Select title="Select a MEC platform" style={{ width: '70%' }} label="MEC platform" fullwidth="true" outlined disabled={false} value={this.state.mepName} options={this.props.mepNames} onChange={mepName => { this.changeMepName(mepName.target.value); }} /> </BasicDialog> ); } } const styles = { errorText: { color: 'red' } }; export default CreateNewAppDialog;
js-apps/frontend/src/js/components/dialogs/detailed-data-dialog.js +23 −5 Original line number Diff line number Diff line Loading @@ -77,16 +77,34 @@ class DetailedDataDialog extends Component { } mapService(loggerName) { switch(loggerName) { //loggerName is a combination of loggerName and mep name let prefixes = ['meep-loc-serv', 'meep-rnis', 'meep-wais', 'meep-app-enablement']; let prefixStd = ''; var prefix = ''; for (var i = 0; i < prefixes.length; i++) { if (loggerName.startsWith(prefixes[i])) { prefix = prefixes[i]; break; } } switch(prefix) { case 'meep-loc-serv': return '013'; prefixStd = '013'; break; case 'meep-rnis': return '012'; prefixStd = '012'; break; case 'meep-wais': return '028'; prefixStd = '028'; break; case 'meep-app-enablement': prefixStd = '011'; break; default: return 'N/A'; prefixStd = 'N/A'; } return loggerName.replace(prefix, prefixStd); } mapDirection(direction) { Loading
js-apps/frontend/src/js/containers/app-container.js +137 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ import SignInOAuthDialog from '../components/dialogs/sign-in-oauth-dialog'; import SignInWaitDialog from '../components/dialogs/sign-in-wait-dialog'; import SessionTerminatedDialog from '../components/dialogs/session-terminated-dialog'; import HelpGettingStartedDialog from '../components/dialogs/help-getting-started-dialog'; import ConfirmDeleteAppDialog from '../components/dialogs/confirm-delete-app-dialog'; import CreateNewAppDialog from '../components/dialogs/create-new-app-dialog'; import * as meepAuthSvcRestApiClient from '../../../../../js-packages/meep-auth-svc-client/src/index.js'; import * as meepPlatformCtrlRestApiClient from '../../../../../js-packages/meep-platform-ctrl-client/src/index.js'; Loading @@ -39,6 +41,8 @@ import { DIALOG_SIGN_IN_WAIT, DIALOG_SESSION_TERMINATED, DIALOG_HELP_GETTING_STARTED, DIALOG_CONFIRM_DELETE_APP, DIALOG_CREATE_NEW_APP, ALERT_DEGRADED_NETWORK, STATUS_SIGNED_IN, STATUS_SIGNING_IN, Loading @@ -64,6 +68,8 @@ import { uiSandboxChangeStationaryUeList, uiSandboxChangeLowVelocityUeList, uiSandboxChangeHighVelocityUeList, uiSandboxChangeMepList, uiSandboxChangeAppInstancesSelected, uiSandboxChangePauseButton, uiSandboxChangeApiDetailedData, uiChangeSignInStatus, Loading @@ -80,7 +86,8 @@ import { sboxChangeMapUeList, sboxChangeMapPoaList, sboxChangeMapComputeList, sboxChangeApiTable sboxChangeApiTable, sboxChangeAppInstancesTable } from '../state/sbox'; const SBOX_ERR_COUNT_MAX = 5; Loading @@ -98,10 +105,11 @@ var basepathMonEngine = ''; const apiTableMaxSize = 100; var metricsQuery = { tags: [{ /* tags: [{ name: 'logger_name', value: 'meep-loc-serv,meep-rnis,meep-wais' value: 'meep-loc-serv,meep-rnis,meep-wais,meep-app-enablement' }], */ fields: ['id', 'endpoint', 'url', 'method', 'resp_code', 'resp_body', 'body', 'proc_time', 'logger_name', 'direction'], scope: { limit: apiTableMaxSize, Loading Loading @@ -141,6 +149,7 @@ class AppContainer extends Component { this.meepSandboxControlApi = new meepPlatformCtrlRestApiClient.SandboxControlApi(); this.meepActiveScenarioApi = new meepSandboxCtrlRestApiClient.ActiveScenarioApi(); this.meepEventsApi = new meepSandboxCtrlRestApiClient.EventsApi(); this.meepAppInfoApi = new meepSandboxCtrlRestApiClient.ApplicationsApi(); this.meepMetricsEngineApi = new meepMetricsEngineRestApiClient.MetricsApi(); this.meepGisAutomationApi = new meepGisEngineRestApiClient.AutomationApi(); this.meepGeoDataApi = new meepGisEngineRestApiClient.GeospatialDataApi(); Loading @@ -167,6 +176,12 @@ class AppContainer extends Component { if (this.props.highVelocityUeList === undefined) { this.props.changeHighVelocityUeList([]); } if (this.props.mepList === undefined) { this.props.changeMepList([]); } if (this.props.appInstancesSelected === undefined) { this.props.changeAppInstancesSelected([]); } if (this.props.helpOnSignIn === undefined) { this.props.changeHelpOnSignIn(true); } Loading Loading @@ -274,6 +289,7 @@ class AppContainer extends Component { this.refreshScenario(); this.refreshMap(); this.refreshMetricsTable(); this.refreshAppInstancesTable(); } } }, Loading Loading @@ -462,6 +478,67 @@ class AppContainer extends Component { window.location.href = HOST_PATH + '/auth/v1/login?provider=' + provider + '&sbox=true'; } deleteAppInstances() { var appInstances = this.props.appInstancesSelected; for (var i = 0; i < appInstances.length; i++) { this.meepAppInfoApi.applicationsAppInstanceIdDELETE(appInstances[i], null); } this.props.changeAppInstancesSelected([]); } createAppInstance(param) { var formParams = { 'name': param.appName, 'mepName': param.mepName, 'type': 'USER', 'state': 'INITIALIZED' }; this.meepAppInfoApi.applicationsPOST(formParams, (error, data, response) => { this.createAppInstanceCb(error, data, response); }); this.props.changeCurrentDialog(null); } /** * Callback function to receive the result of the loginUser operation. * @callback module:api/AppInfo~createAppInstanceIdCallback * @param {String} error Error message, if any. * @param {appInstanceObject} data The data returned by the service call. * @param {String} response The complete HTTP response. */ createAppInstanceCb(error, data) { if (error) { var errMsg; switch (error.status) { case StatusCodes.UNAUTHORIZED: errMsg = 'Invalid credentials. Please try again...'; break; case StatusCodes.SERVICE_UNAVAILABLE: errMsg = 'All MEC Sandboxes are currently in use. Please try again later...'; break; default: errMsg = 'Login failure. Please try again...'; break; } this.props.changeDialogErrorMsg(errMsg); this.props.changeCurrentDialog(DIALOG_CREATE_NEW_APP); return; } // Get sandbox name on successful login var appInstanceId = data ? data.id : ''; // Handle applicationinstance creation error if (!appInstanceId) { this.props.changeDialogErrorMsg('Failed to create a new App Instance, try again...'); this.props.changeCurrentDialog(DIALOG_CREATE_NEW_APP); return; } // clearing error this.props.changeDialogErrorMsg(''); } updateAutomation(pauseButtonEnabled) { this.meepGisAutomationApi.setAutomationStateByName('MOVEMENT', !pauseButtonEnabled); this.meepGisAutomationApi.setAutomationStateByName('MOBILITY', !pauseButtonEnabled); Loading Loading @@ -879,7 +956,9 @@ class AppContainer extends Component { // only update if values present, otherwise means no changes if (data) { data.values = this.mergeApiTableData(this.props.tableData.values, data.values); if (this.props.tableData.apiTable !== null) { data.values = this.mergeApiTableData(this.props.tableData.apiTable.values, data.values); } this.props.changeApiTable(data); } } Loading @@ -899,6 +978,34 @@ class AppContainer extends Component { } } /** * Callback function to receive the result of the postHttpQuery operation. * @callback module:api/AppsApi~applicationsGET * @param {String} error Error message, if any. * @param {module:model/ApplicationInfo} data The data returned by the service call. * @param {String} response The complete HTTP response. */ getAppInstancesCb(error, data) { if (error !== null) { this.props.changeAppInstancesTable([]); return; } // only update if values present, otherwise means no changes if (data) { //flush global app instances this.props.changeAppInstancesTable(data); } else { this.props.changeAppInstancesTable([]); } } refreshAppInstancesTable() { this.meepAppInfoApi.applicationsGET(null, (error, data, response) => { this.getAppInstancesCb(error, data, response); }); } renderPage() { switch (this.props.page) { case PAGE_HOME: Loading @@ -917,6 +1024,7 @@ class AppContainer extends Component { eventsApi={this.meepEventsApi} metricsApi={this.meepMetricsEngineApi} automationApi={this.meepGisAutomationApi} applicationsApi={this.meepAppInfoApi} /> ); Loading Loading @@ -974,6 +1082,25 @@ class AppContainer extends Component { this.closeDialog(); }} /> <ConfirmDeleteAppDialog title='Application instance deletion' open={this.props.currentDialog === DIALOG_CONFIRM_DELETE_APP} onSubmit={() => { this.deleteAppInstances(); }} onClose={() => { this.closeDialog(); }} /> <CreateNewAppDialog title='Application instance creation' open={this.props.currentDialog === DIALOG_CREATE_NEW_APP} onSubmit={param => this.createAppInstance(param)} onClose={() => { this.closeDialog(); }} mepNames={this.props.mepList.meps} /> </> ); } Loading Loading @@ -1027,6 +1154,7 @@ const mapStateToProps = state => { signInStatus: state.ui.signInStatus, signInUsername: state.ui.signInUsername, dialogErrorMsg: state.ui.dialogErrorMsg, networkFiles: state.ui.networkFiles, networkFileSelected: state.ui.networkFileSelected, tableData: state.sbox.apiTable, highVelocityUeList: state.ui.highVelocityUeList, Loading @@ -1034,6 +1162,8 @@ const mapStateToProps = state => { stationaryUeList: state.ui.stationaryUeList, nbLowVelocityUe: state.ui.nbLowVelocityUe, nbHighVelocityUe: state.ui.nbHighVelocityUe, mepList: state.ui.mepList, appInstancesSelected: state.ui.appInstancesSelected, updateUeInProgressCount: state.ui.updateUeInProgressCount, activationInProgressCount: state.ui.activationInProgressCount, activationInProgressScenarioName: state.ui.activationInProgressScenarioName, Loading @@ -1058,6 +1188,8 @@ const mapDispatchToProps = dispatch => { changeStationaryUeList: list => dispatch(uiSandboxChangeStationaryUeList(list)), changeLowVelocityUeList: list => dispatch(uiSandboxChangeLowVelocityUeList(list)), changeHighVelocityUeList: list => dispatch(uiSandboxChangeHighVelocityUeList(list)), changeMepList: list => dispatch(uiSandboxChangeMepList(list)), changeAppInstancesSelected: list => dispatch(uiSandboxChangeAppInstancesSelected(list)), changePauseButton: checked => dispatch(uiSandboxChangePauseButton(checked)), changeApiDetailedData: row => dispatch(uiSandboxChangeApiDetailedData(row)), changeSignInStatus: status => dispatch(uiChangeSignInStatus(status)), Loading @@ -1070,6 +1202,7 @@ const mapDispatchToProps = dispatch => { changeMapPoaList: list => dispatch(sboxChangeMapPoaList(list)), changeMapComputeList: list => dispatch(sboxChangeMapComputeList(list)), changeApiTable: value => dispatch(sboxChangeApiTable(value)), changeAppInstancesTable: value => dispatch(sboxChangeAppInstancesTable(value)), changeUpdateUeInProgressCount: count => dispatch(uiSandboxChangeUpdateUeInProgressCount(count)), changeActivationInProgressCount: count => dispatch(uiSandboxChangeActivationInProgressCount(count)), changeActivationInProgressScenarioName: name => dispatch(uiSandboxChangeActivationInProgressScenarioName(name)) Loading