-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
750 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 194 additions & 0 deletions
194
frontend/src/components/App/Services/ServicesDeleteForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
import * as React from 'react' | ||
import { connect } from 'react-redux' | ||
import { Button } from 'reactstrap' | ||
import { reduxForm, InjectedFormProps } from 'redux-form' | ||
|
||
import { APIRequest } from '@src/apis/Core' | ||
import { Service } from '@src/apis' | ||
import ServicesStatusTable from './ServicesStatusTable' | ||
import { ControlMode } from './index' | ||
|
||
class ServicesDeleteForm extends React.Component<ServicesDeleteFormProps, {}> { | ||
constructor(props, context) { | ||
super(props, context) | ||
|
||
this.handleDiscardChanges = this.handleDiscardChanges.bind(this) | ||
} | ||
|
||
componentWillReceiveProps(nextProps: ServicesDeleteFormProps) { | ||
const { mode, pristine, changeMode } = nextProps | ||
|
||
if (mode === ControlMode.VIEW_SERVICES_STATUS && !pristine) { | ||
changeMode(ControlMode.SELECT_TARGETS) | ||
} else if (mode === ControlMode.SELECT_TARGETS && pristine) { | ||
changeMode(ControlMode.VIEW_SERVICES_STATUS) | ||
} | ||
} | ||
|
||
render() { | ||
const { | ||
onSubmit, | ||
handleSubmit, | ||
} = this.props | ||
|
||
return ( | ||
<form onSubmit={handleSubmit(onSubmit)} > | ||
<div className='mb-2'> | ||
{this.renderDiscardButton()} | ||
</div> | ||
<ServicesStatusTable | ||
{...this.props} | ||
/> | ||
<hr /> | ||
{this.renderSubmitButtons()} | ||
</form> | ||
) | ||
} | ||
|
||
renderDiscardButton = () => { | ||
const { mode } = this.props | ||
|
||
switch (mode) { | ||
case ControlMode.SELECT_TARGETS: | ||
return ( | ||
<Button outline color='danger' onClick={this.handleDiscardChanges}> | ||
<i className={`fas fa-times fa-fw mr-2`}></i> | ||
Discard changes | ||
</Button> | ||
) | ||
default: | ||
return ( | ||
<div> | ||
</div> | ||
This comment has been minimized.
Sorry, something went wrong. |
||
) | ||
} | ||
} | ||
|
||
/** | ||
* Render submit button(s) | ||
* | ||
* Show delete button if selected targets exist | ||
* Show save button if editing deploy status | ||
*/ | ||
renderSubmitButtons(): JSX.Element { | ||
const { | ||
mode, | ||
submitting, | ||
pristine | ||
} = this.props | ||
|
||
const showSubmitButton: boolean = mode !== ControlMode.VIEW_SERVICES_STATUS | ||
|
||
if (!showSubmitButton) { | ||
return null | ||
} | ||
|
||
const paramsMap = { | ||
[ControlMode.SELECT_TARGETS]: { color: 'danger', icon: 'trash', text: 'Delete Services' }, | ||
} | ||
|
||
// Submit button element(s) | ||
const buttons = (params) => ( | ||
<div className='mb-2'> | ||
<Button | ||
color={params.color} | ||
className='mr-2' | ||
disabled={pristine || submitting} | ||
type='submit' | ||
> | ||
<i className={`fas fa-${params.icon} fa-fw mr-2`}></i> | ||
{params.text} | ||
</Button> | ||
</div> | ||
) | ||
|
||
const submittingLoader = ( | ||
<div> | ||
<div className='loader loader-primary loader-xs mr-2'/> | ||
Submitting... | ||
</div> | ||
) | ||
|
||
return submitting ? submittingLoader : buttons(paramsMap[mode]) | ||
} | ||
|
||
renderSubmitButtonElements() { | ||
const { | ||
submitting, | ||
pristine | ||
} = this.props | ||
|
||
const paramsMap = { | ||
[ControlMode.SELECT_TARGETS]: { color: 'danger', icon: 'trash', text: 'Delete Services' }, | ||
} | ||
|
||
return ( | ||
<div className='mb-2'> | ||
<Button | ||
color='danger' | ||
className='mr-2' | ||
disabled={pristine || submitting} | ||
> | ||
<i className='fas fa-trash fa-fw mr-2'></i> | ||
Delete Services | ||
</Button> | ||
</div> | ||
) | ||
} | ||
|
||
// Handle event methods | ||
|
||
handleDiscardChanges(event): void { | ||
const { changeMode, reset } = this.props | ||
reset() | ||
changeMode(ControlMode.VIEW_SERVICES_STATUS) | ||
} | ||
} | ||
|
||
interface ServicesDeleteFormCustomProps { | ||
applicationType: string | ||
applicationId | ||
mode: ControlMode | ||
services: Service[] | ||
onSubmit: (e) => Promise<void> | ||
changeMode: (mode: ControlMode) => void | ||
} | ||
|
||
interface StateProps { | ||
initialValues: { | ||
status | ||
delete | ||
} | ||
} | ||
|
||
const mapStateToProps = (state: any, extraProps: ServicesDeleteFormCustomProps) => { | ||
// Map of service ID to delete flag | ||
const initialDeleteStatus: { [x: string]: boolean } = | ||
extraProps.services | ||
.map((service) => ({[service.id]: false})) | ||
.reduce((l, r) => Object.assign(l, r), {}) | ||
|
||
return { | ||
...state.form, | ||
initialValues: { | ||
delete: { | ||
services: initialDeleteStatus | ||
} | ||
} | ||
} | ||
} | ||
|
||
const mapDispatchToProps = (dispatch): {} => { | ||
return { } | ||
} | ||
|
||
type ServicesDeleteFormProps | ||
= StateProps & ServicesDeleteFormCustomProps & InjectedFormProps<{}, ServicesDeleteFormCustomProps> | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)( | ||
reduxForm<{}, ServicesDeleteFormCustomProps>( | ||
{ | ||
form: 'deployStatusForm' | ||
} | ||
)(ServicesDeleteForm) | ||
) |
161 changes: 161 additions & 0 deletions
161
frontend/src/components/App/Services/ServicesStatusTable.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import * as React from 'react' | ||
import { connect } from 'react-redux' | ||
import { CustomInput, Table, Row } from 'reactstrap' | ||
import { Field, InjectedFormProps } from 'redux-form' | ||
import { Link } from 'react-router-dom' | ||
|
||
import { Service } from '@src/apis' | ||
import { ControlMode } from './index' | ||
|
||
/** | ||
* Table for showing services status | ||
*/ | ||
class ServicesStatusTable extends React.Component<ServicesStatusProps, {tooltipOpen}> { | ||
constructor(props, context) { | ||
super(props, context) | ||
|
||
this.state = { | ||
tooltipOpen: {} | ||
} | ||
} | ||
|
||
render() { | ||
const { services } = this.props | ||
|
||
return ( | ||
<Table hover className='mb-3'> | ||
{this.renderTableHead()} | ||
{this.renderTableBody(services)} | ||
</Table> | ||
) | ||
} | ||
|
||
toggleTooltip(tag) { | ||
return () => { | ||
const nextTooltipOpen = { | ||
...this.state.tooltipOpen, | ||
[tag]: !this.state.tooltipOpen[tag] | ||
} | ||
|
||
this.setState({ | ||
tooltipOpen: nextTooltipOpen | ||
}) | ||
} | ||
} | ||
|
||
/** | ||
* Render head row of the table | ||
*/ | ||
renderTableHead = () => { | ||
return ( | ||
<thead> | ||
<tr className='bg-light text-primary'> | ||
<th>Name</th><th>Service Level</th><th>Description</th><th>Host</th> | ||
</tr> | ||
</thead> | ||
) | ||
} | ||
|
||
/** | ||
* Render body of the table | ||
* | ||
* Render Service names | ||
* Each Service is rendered with a deploy check box on viewing/deleting mode | ||
* @param services Services to be shown (Currently show all, but should be filtered) | ||
*/ | ||
renderTableBody = (services) => { | ||
const { mode, applicationType, applicationId } = this.props | ||
|
||
// Button to delete Service (for deleting k8s services) | ||
const deleteCheckButton = (serviceName: string, serviceId: string) => { | ||
return ( | ||
<Row> | ||
{ applicationType === 'kubernetes' ? | ||
<Field | ||
name={`delete.services.${serviceId}`} | ||
component={CustomCheckBox} | ||
id={`service-${serviceId}`} | ||
label='' | ||
className='mr-1' | ||
/> | ||
: null } | ||
<Link className='text-info' to={`/applications/${applicationId}/services/${serviceId}/edit`}> | ||
{serviceName} | ||
</Link> | ||
</Row> | ||
) | ||
} | ||
|
||
const renderButton = (serviceName, serviceId) => { | ||
const renderMap = { | ||
[ControlMode.VIEW_SERVICES_STATUS] : deleteCheckButton(serviceName, serviceId), | ||
[ControlMode.SELECT_TARGETS] : deleteCheckButton(serviceName, serviceId), | ||
} | ||
return renderMap[mode] | ||
This comment has been minimized.
Sorry, something went wrong. |
||
} | ||
|
||
return ( | ||
<tbody> | ||
{services.map( | ||
(service) => ( | ||
<tr> | ||
<td key={service.name} scope='col'> | ||
{renderButton(service.name, service.id)} | ||
</td> | ||
<td> | ||
{service.serviceLevel} | ||
</td> | ||
<td> | ||
{service.description} | ||
</td> | ||
<td> | ||
{service.host} | ||
</td> | ||
</tr> | ||
) | ||
)} | ||
</tbody> | ||
) | ||
} | ||
|
||
} | ||
|
||
const CustomCheckBox = (props) => { | ||
const { input, id, label } = props | ||
|
||
return ( | ||
<CustomInput | ||
{...input} | ||
type='checkbox' | ||
name={input.name} | ||
id={id} | ||
checked={input.value} | ||
label={label} | ||
/> | ||
) | ||
} | ||
|
||
interface ServicesStatusFormCustomProps { | ||
applicationType: string | ||
applicationId | ||
services: Service[], | ||
mode: ControlMode, | ||
} | ||
|
||
export interface DispatchProps { | ||
dispatchChange | ||
} | ||
|
||
const mapDispatchToProps = (dispatch): DispatchProps => { | ||
return { | ||
dispatchChange: (field, value, changeMethod) => dispatch(changeMethod(field, value)) | ||
} | ||
} | ||
|
||
const mapStateToProps = (state: any, extraProps: ServicesStatusFormCustomProps) => { | ||
return {} | ||
} | ||
|
||
type ServicesStatusProps = DispatchProps & ServicesStatusFormCustomProps & InjectedFormProps<{}, ServicesStatusFormCustomProps> | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(ServicesStatusTable) |
Oops, something went wrong.
You can just return
null