ibm-streams
Version:
IBM Streams Support for Visual Studio Code
300 lines (279 loc) • 8.73 kB
JavaScript
import UserAdmin16 from '@carbon/icons-react/es/user--admin/16';
import Button from 'carbon-components-react/es/components/Button';
import {
InlineNotification,
NotificationActionButton
} from 'carbon-components-react/es/components/Notification';
import TextArea from 'carbon-components-react/es/components/TextArea';
import Tooltip from 'carbon-components-react/es/components/Tooltip';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import MessageHandler from '../../../../message.ts';
import ButtonContainer from '../ButtonContainer';
export default class ConnectionFormV4 extends Component {
constructor(props) {
super(props);
const {
params: { instance }
} = this.props;
const authentication =
instance && instance.authentication ? instance.authentication : null;
this.state = {
credentials:
authentication && authentication.credentials
? JSON.stringify(authentication.credentials, null, 2)
: '',
loading: false,
isTestingConnection: false,
connectionSuccessful: null,
isAuthenticating: false,
isStartingService: false,
authError: null
};
this.messageHandler = new MessageHandler(this.handleExtensionMessage);
this.isComponentMounted = false;
}
componentDidMount() {
this.isComponentMounted = true;
}
componentWillUnmount() {
this.isComponentMounted = false;
}
handleExtensionMessage = (message) => {
if (this.isComponentMounted) {
const { command, args } = message;
switch (command) {
case 'set-auth-error': {
const newState = args;
const { authError } = args;
if (authError) {
newState.isAuthenticating = false;
}
this.setState(newState);
break;
}
default:
break;
}
}
};
onTextChange = (e) => {
this.setState({ [e.target.id]: e.target.value });
};
validate = () => {
const { credentials } = this.state;
// True if errors, false otherwise
const errors = {};
try {
// eslint-disable-next-line no-unused-vars
const json = JSON.parse(credentials);
if (!json.apikey || !json.v2_rest_url) {
errors.credentials = 'The value must be valid.';
}
} catch (err) {
errors.credentials = 'The value must be valid JSON.';
}
return errors;
};
isFormValid = () => {
const errors = this.validate();
const isValid = !Object.keys(errors).some((e) => errors[e]);
return isValid;
};
getButtonContainer = () => {
const { credentials } = this.state;
const {
instanceType,
closePanel,
params: { instance }
} = this.props;
const isValid = this.isFormValid();
return (
<ButtonContainer
primaryBtn={{
label: instance ? 'Authenticate' : 'Add',
isValid,
onClick: () => {
this.setState({ isAuthenticating: true });
this.messageHandler.postMessage({
command: 'authenticate',
args: {
instanceType,
credentials: JSON.parse(credentials),
instance
}
});
}
}}
secondaryBtn={{
label: 'Cancel',
isValid: true,
onClick: () => {
closePanel();
}
}}
/>
);
};
renderErrorNotification = (authError, type, callbackFn) => {
const { credentials } = this.state;
const {
instanceType,
renderErrorNotification: renderErrorNotificationProp
} = this.props;
if (
authError &&
authError.data &&
authError.data.type === 'STREAMING_ANALYTICS_SERVICE_NOT_STARTED'
) {
const {
data: { connectionId }
} = authError;
const startServiceAction = (
<NotificationActionButton
onClick={async () => {
this.setState({ loading: true, isStartingService: true });
const result = await this.messageHandler.postMessage({
command: 'start-streaming-analytics-service',
args: {
instanceType,
credentials: JSON.parse(credentials),
connectionId
}
});
if (result.errorMsg) {
this.setState({ authError: { message: result.errorMsg } });
this.messageHandler.postMessage({
command: 'remove-instance',
args: { connectionId }
});
}
this.setState({ loading: false, isStartingService: false });
}}
>
Start service and retry
</NotificationActionButton>
);
return (
<InlineNotification
title="Error"
subtitle={authError.message}
actions={startServiceAction}
iconDescription="Close"
kind="error"
statusIconDescription="Error"
onCloseButtonClick={callbackFn}
className="connection-form__error-notification"
/>
);
}
return renderErrorNotificationProp(authError, type, callbackFn);
};
render() {
const {
credentials,
loading,
isTestingConnection,
connectionSuccessful,
isAuthenticating,
isStartingService,
authError
} = this.state;
const {
instanceType,
renderLoadingOverlay,
renderTestConnectionNotification,
params: { instance }
} = this.props;
const errors = this.validate();
const isValid = this.isFormValid();
const credentialsLabel = (
<>
<Tooltip
triggerText="IBM Streaming Analytics service credentials"
iconDescription="IBM Streaming Analytics service credentials"
tabIndex={0}
className="streams-auth-container__help-tooltip"
>
IBM Streaming Analytics is a cloud version of IBM Streams that is
available from IBM Cloud. Afer you create an instance of the Streaming
Analytics service, you may access the service credentials (in JSON
format) from the service details page.
</Tooltip>
<Button
className="connection-form__test-connection-button"
disabled={!isValid || isTestingConnection}
hasIconOnly
iconDescription="Test connection"
title="Test connection"
kind="ghost"
onClick={async () => {
this.setState({ isTestingConnection: true });
const result = await this.messageHandler.postMessage({
command: 'test-connection',
args: {
instanceType,
credentials: JSON.parse(credentials)
}
});
this.setState({
isTestingConnection: false,
connectionSuccessful: result
});
}}
renderIcon={UserAdmin16}
size="small"
tooltipAlignment="center"
tooltipPosition="bottom"
type="button"
/>
</>
);
return (
<>
{renderLoadingOverlay(
loading,
isAuthenticating,
isStartingService ? 'Starting the service...' : 'Loading...'
)}
{renderTestConnectionNotification(connectionSuccessful, () => {
this.setState({ connectionSuccessful: null });
})}
<div className="connection-form__form-item">
<TextArea
id="credentials"
labelText={credentialsLabel}
placeholder='{ "apikey": ..., "v2_rest_url": ... }'
value={credentials}
disabled={!!instance}
invalid={!!errors.credentials && credentials.length > 0}
invalidText={errors.credentials || null}
onChange={this.onTextChange}
className="connection-form-v4__credentials"
rows={16}
/>
</div>
{this.renderErrorNotification(
authError,
'IBM Streaming Analytics',
() => {
this.setState({ authError: null });
}
)}
{this.getButtonContainer()}
</>
);
}
}
ConnectionFormV4.propTypes = {
instanceType: PropTypes.string.isRequired,
closePanel: PropTypes.func.isRequired,
renderLoadingOverlay: PropTypes.func.isRequired,
renderTestConnectionNotification: PropTypes.func.isRequired,
renderErrorNotification: PropTypes.func.isRequired,
params: PropTypes.shape({
instanceTypes: PropTypes.objectOf(PropTypes.string),
cpdVersions: PropTypes.objectOf(PropTypes.string),
instance: PropTypes.object
}).isRequired
};