|
@@ -27,7 +27,6 @@ import EditReplica from '../../organisms/EditReplica'
|
|
|
import ReplicaMigrationOptions from '../../organisms/ReplicaMigrationOptions'
|
|
import ReplicaMigrationOptions from '../../organisms/ReplicaMigrationOptions'
|
|
|
import DeleteReplicaModal from '../../molecules/DeleteReplicaModal'
|
|
import DeleteReplicaModal from '../../molecules/DeleteReplicaModal'
|
|
|
|
|
|
|
|
-import type { MainItem } from '../../../@types/MainItem'
|
|
|
|
|
import type { InstanceScript } from '../../../@types/Instance'
|
|
import type { InstanceScript } from '../../../@types/Instance'
|
|
|
import type { Execution } from '../../../@types/Execution'
|
|
import type { Execution } from '../../../@types/Execution'
|
|
|
import type { Schedule } from '../../../@types/Schedule'
|
|
import type { Schedule } from '../../../@types/Schedule'
|
|
@@ -45,11 +44,12 @@ import notificationStore from '../../../stores/NotificationStore'
|
|
|
import providerStore from '../../../stores/ProviderStore'
|
|
import providerStore from '../../../stores/ProviderStore'
|
|
|
|
|
|
|
|
import configLoader from '../../../utils/Config'
|
|
import configLoader from '../../../utils/Config'
|
|
|
-import utils from '../../../utils/ObjectUtils'
|
|
|
|
|
import { providerTypes } from '../../../constants'
|
|
import { providerTypes } from '../../../constants'
|
|
|
|
|
|
|
|
import replicaImage from './images/replica.svg'
|
|
import replicaImage from './images/replica.svg'
|
|
|
import Palette from '../../styleUtils/Palette'
|
|
import Palette from '../../styleUtils/Palette'
|
|
|
|
|
+import { ReplicaItemDetails } from '../../../@types/MainItem'
|
|
|
|
|
+import ObjectUtils from '../../../utils/ObjectUtils'
|
|
|
|
|
|
|
|
const Wrapper = styled.div<any>``
|
|
const Wrapper = styled.div<any>``
|
|
|
|
|
|
|
@@ -65,7 +65,7 @@ type State = {
|
|
|
showForceCancelConfirmation: boolean,
|
|
showForceCancelConfirmation: boolean,
|
|
|
showDeleteReplicaConfirmation: boolean,
|
|
showDeleteReplicaConfirmation: boolean,
|
|
|
showDeleteReplicaDisksConfirmation: boolean,
|
|
showDeleteReplicaDisksConfirmation: boolean,
|
|
|
- confirmationItem: MainItem | null | Execution | null,
|
|
|
|
|
|
|
+ confirmationItem?: ReplicaItemDetails | null | Execution | null,
|
|
|
showCancelConfirmation: boolean,
|
|
showCancelConfirmation: boolean,
|
|
|
isEditable: boolean,
|
|
isEditable: boolean,
|
|
|
pausePolling: boolean,
|
|
pausePolling: boolean,
|
|
@@ -88,12 +88,12 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
|
|
|
|
|
stopPolling: boolean | null = null
|
|
stopPolling: boolean | null = null
|
|
|
|
|
|
|
|
- UNSAFE_componentWillMount() {
|
|
|
|
|
|
|
+ componentDidMount() {
|
|
|
document.title = 'Replica Details'
|
|
document.title = 'Replica Details'
|
|
|
|
|
|
|
|
const loadReplica = async () => {
|
|
const loadReplica = async () => {
|
|
|
await endpointStore.getEndpoints({ showLoading: true })
|
|
await endpointStore.getEndpoints({ showLoading: true })
|
|
|
- const replica = await this.loadReplicaWithInstances(this.replicaId, true)
|
|
|
|
|
|
|
+ const replica = await this.loadReplicaWithInstances(true)
|
|
|
if (!replica) {
|
|
if (!replica) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
@@ -141,7 +141,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
|
|
|
|
|
UNSAFE_componentWillReceiveProps(newProps: Props) {
|
|
UNSAFE_componentWillReceiveProps(newProps: Props) {
|
|
|
if (newProps.match.params.id !== this.props.match.params.id) {
|
|
if (newProps.match.params.id !== this.props.match.params.id) {
|
|
|
- this.loadReplicaWithInstances(newProps.match.params.id, true)
|
|
|
|
|
|
|
+ this.loadReplicaWithInstances(true, newProps.match.params.id)
|
|
|
scheduleStore.getSchedules(newProps.match.params.id)
|
|
scheduleStore.getSchedules(newProps.match.params.id)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -159,8 +159,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
get replica() {
|
|
get replica() {
|
|
|
- const replica = replicaStore.replicas.find(r => r.id === this.replicaId)
|
|
|
|
|
- return replica
|
|
|
|
|
|
|
+ return replicaStore.replicaDetails
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
getLastExecution() {
|
|
getLastExecution() {
|
|
@@ -176,11 +175,11 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
return lastExecution && lastExecution.status
|
|
return lastExecution && lastExecution.status
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- async loadIsEditable(replicaDetails: MainItem) {
|
|
|
|
|
|
|
+ async loadIsEditable(replicaDetails: ReplicaItemDetails) {
|
|
|
const targetEndpointId = replicaDetails.destination_endpoint_id
|
|
const targetEndpointId = replicaDetails.destination_endpoint_id
|
|
|
const sourceEndpointId = replicaDetails.origin_endpoint_id
|
|
const sourceEndpointId = replicaDetails.origin_endpoint_id
|
|
|
await providerStore.loadProviders()
|
|
await providerStore.loadProviders()
|
|
|
- await utils.waitFor(() => endpointStore.endpoints.length > 0)
|
|
|
|
|
|
|
+ await ObjectUtils.waitFor(() => endpointStore.endpoints.length > 0)
|
|
|
const sourceEndpoint = endpointStore.endpoints.find(e => e.id === sourceEndpointId)
|
|
const sourceEndpoint = endpointStore.endpoints.find(e => e.id === sourceEndpointId)
|
|
|
const targetEndpoint = endpointStore.endpoints.find(e => e.id === targetEndpointId)
|
|
const targetEndpoint = endpointStore.endpoints.find(e => e.id === targetEndpointId)
|
|
|
if (!sourceEndpoint || !targetEndpoint || !providerStore.providers) {
|
|
if (!sourceEndpoint || !targetEndpoint || !providerStore.providers) {
|
|
@@ -196,8 +195,8 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
this.setState({ isEditable })
|
|
this.setState({ isEditable })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- async loadReplicaWithInstances(_: string, cache: boolean) {
|
|
|
|
|
- await replicaStore.getReplicas({ showLoading: true })
|
|
|
|
|
|
|
+ async loadReplicaWithInstances(cache: boolean, replicaId?: string) {
|
|
|
|
|
+ await replicaStore.getReplicaDetails({ replicaId: replicaId || this.replicaId })
|
|
|
const replica = this.replica
|
|
const replica = this.replica
|
|
|
if (!replica) {
|
|
if (!replica) {
|
|
|
return null
|
|
return null
|
|
@@ -259,7 +258,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
this.handleCloseExecutionConfirmation()
|
|
this.handleCloseExecutionConfirmation()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- handleDeleteExecutionClick(execution: Execution | null) {
|
|
|
|
|
|
|
+ handleDeleteExecutionClick(execution?: Execution | null) {
|
|
|
this.setState({
|
|
this.setState({
|
|
|
showDeleteExecutionConfirmation: true,
|
|
showDeleteExecutionConfirmation: true,
|
|
|
confirmationItem: execution,
|
|
confirmationItem: execution,
|
|
@@ -304,7 +303,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
replicaStore.deleteDisks(replica.id)
|
|
replicaStore.deleteDisks(replica.id)
|
|
|
- this.props.history.push(`/replica/executions/${replica.id}`)
|
|
|
|
|
|
|
+ this.props.history.push(`/replicas/${replica.id}/executions`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
handleCloseDeleteReplicaDisksConfirmation() {
|
|
handleCloseDeleteReplicaDisksConfirmation() {
|
|
@@ -354,7 +353,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
this.handleCancelExecution(this.getLastExecution(), force)
|
|
this.handleCancelExecution(this.getLastExecution(), force)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- handleCancelExecution(confirmationItem: Execution | null, force?: boolean | null) {
|
|
|
|
|
|
|
+ handleCancelExecution(confirmationItem?: Execution | null, force?: boolean | null) {
|
|
|
if (force) {
|
|
if (force) {
|
|
|
this.setState({ confirmationItem, showForceCancelConfirmation: true })
|
|
this.setState({ confirmationItem, showForceCancelConfirmation: true })
|
|
|
} else {
|
|
} else {
|
|
@@ -374,11 +373,11 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
if (!this.state.confirmationItem || !replica) {
|
|
if (!this.state.confirmationItem || !replica) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
- replicaStore.cancelExecution(
|
|
|
|
|
- replica.id,
|
|
|
|
|
- this.state.confirmationItem.id,
|
|
|
|
|
|
|
+ replicaStore.cancelExecution({
|
|
|
|
|
+ replicaId: replica.id,
|
|
|
|
|
+ executionId: this.state.confirmationItem.id,
|
|
|
force,
|
|
force,
|
|
|
- )
|
|
|
|
|
|
|
+ })
|
|
|
this.setState({
|
|
this.setState({
|
|
|
showForceCancelConfirmation: false,
|
|
showForceCancelConfirmation: false,
|
|
|
showCancelConfirmation: false,
|
|
showCancelConfirmation: false,
|
|
@@ -404,7 +403,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
action: {
|
|
action: {
|
|
|
label: 'View Migration Status',
|
|
label: 'View Migration Status',
|
|
|
callback: () => {
|
|
callback: () => {
|
|
|
- this.props.history.push(`/migration/tasks/${migration.id}`)
|
|
|
|
|
|
|
+ this.props.history.push(`/migrations/${migration.id}/tasks/`)
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
})
|
|
})
|
|
@@ -417,7 +416,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
}
|
|
}
|
|
|
replicaStore.execute(replica.id, fields)
|
|
replicaStore.execute(replica.id, fields)
|
|
|
this.handleCloseOptionsModal()
|
|
this.handleCloseOptionsModal()
|
|
|
- this.props.history.push(`/replica/executions/${replica.id}`)
|
|
|
|
|
|
|
+ this.props.history.push(`/replicas/${replica.id}/executions`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async pollData(showLoading: boolean) {
|
|
async pollData(showLoading: boolean) {
|
|
@@ -425,7 +424,16 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- await replicaStore.getReplicas({ showLoading, skipLog: true })
|
|
|
|
|
|
|
+ await Promise.all([
|
|
|
|
|
+ replicaStore.getReplicaDetails({
|
|
|
|
|
+ replicaId: this.replicaId, showLoading, polling: true,
|
|
|
|
|
+ }),
|
|
|
|
|
+ (async () => {
|
|
|
|
|
+ if (window.location.pathname.indexOf('executions') > -1) {
|
|
|
|
|
+ await replicaStore.getExecutionTasks({ replicaId: this.replicaId, polling: true })
|
|
|
|
|
+ }
|
|
|
|
|
+ })(),
|
|
|
|
|
+ ])
|
|
|
|
|
|
|
|
setTimeout(() => { this.pollData(false) }, configLoader.config.requestPollTimeout)
|
|
setTimeout(() => { this.pollData(false) }, configLoader.config.requestPollTimeout)
|
|
|
}
|
|
}
|
|
@@ -437,7 +445,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
handleEditReplicaReload() {
|
|
handleEditReplicaReload() {
|
|
|
- this.loadReplicaWithInstances(this.replicaId, false)
|
|
|
|
|
|
|
+ this.loadReplicaWithInstances(false)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
handleUpdateComplete(redirectTo: string) {
|
|
handleUpdateComplete(redirectTo: string) {
|
|
@@ -445,6 +453,14 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
this.closeEditModal()
|
|
this.closeEditModal()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ async handleExecutionChange(executionId: string) {
|
|
|
|
|
+ await ObjectUtils.waitFor(() => Boolean(replicaStore.replicaDetails))
|
|
|
|
|
+ if (!replicaStore.replicaDetails?.id) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ replicaStore.getExecutionTasks({ replicaId: replicaStore.replicaDetails.id, executionId })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
renderEditReplica() {
|
|
renderEditReplica() {
|
|
|
const replica = this.replica
|
|
const replica = this.replica
|
|
|
if (!replica) {
|
|
if (!replica) {
|
|
@@ -516,7 +532,18 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
},
|
|
},
|
|
|
]
|
|
]
|
|
|
const replica = this.replica
|
|
const replica = this.replica
|
|
|
-
|
|
|
|
|
|
|
+ let title = null
|
|
|
|
|
+ if (replica) {
|
|
|
|
|
+ const { instances } = replica
|
|
|
|
|
+ if (instances) {
|
|
|
|
|
+ title = instances[0]
|
|
|
|
|
+ if (instances.length > 1) {
|
|
|
|
|
+ title += ` (+${instances.length - 1} more)`
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ title = replica.name
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
return (
|
|
return (
|
|
|
<Wrapper>
|
|
<Wrapper>
|
|
|
<DetailsTemplate
|
|
<DetailsTemplate
|
|
@@ -528,7 +555,10 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
)}
|
|
)}
|
|
|
contentHeaderComponent={(
|
|
contentHeaderComponent={(
|
|
|
<DetailsContentHeader
|
|
<DetailsContentHeader
|
|
|
- item={replica}
|
|
|
|
|
|
|
+ statusPill={replica?.last_execution_status}
|
|
|
|
|
+ itemTitle={title}
|
|
|
|
|
+ itemType="replica"
|
|
|
|
|
+ itemDescription={replica?.description}
|
|
|
dropdownActions={dropdownActions}
|
|
dropdownActions={dropdownActions}
|
|
|
backLink="/replicas"
|
|
backLink="/replicas"
|
|
|
typeImage={replicaImage}
|
|
typeImage={replicaImage}
|
|
@@ -543,7 +573,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
endpoints={endpointStore.endpoints}
|
|
endpoints={endpointStore.endpoints}
|
|
|
scheduleStore={scheduleStore}
|
|
scheduleStore={scheduleStore}
|
|
|
networks={networkStore.networks}
|
|
networks={networkStore.networks}
|
|
|
- detailsLoading={replicaStore.loading || endpointStore.loading}
|
|
|
|
|
|
|
+ detailsLoading={replicaStore.replicaDetailsLoading || endpointStore.loading}
|
|
|
sourceSchema={providerStore.sourceSchema}
|
|
sourceSchema={providerStore.sourceSchema}
|
|
|
sourceSchemaLoading={providerStore.sourceSchemaLoading
|
|
sourceSchemaLoading={providerStore.sourceSchemaLoading
|
|
|
|| providerStore.sourceOptionsPrimaryLoading
|
|
|| providerStore.sourceOptionsPrimaryLoading
|
|
@@ -552,7 +582,13 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
destinationSchemaLoading={providerStore.destinationSchemaLoading
|
|
destinationSchemaLoading={providerStore.destinationSchemaLoading
|
|
|
|| providerStore.destinationOptionsPrimaryLoading
|
|
|| providerStore.destinationOptionsPrimaryLoading
|
|
|
|| providerStore.destinationOptionsSecondaryLoading}
|
|
|| providerStore.destinationOptionsSecondaryLoading}
|
|
|
- executionsLoading={replicaStore.startingExecution}
|
|
|
|
|
|
|
+ executionsLoading={replicaStore.startingExecution
|
|
|
|
|
+ || replicaStore.replicaDetailsLoading}
|
|
|
|
|
+ onExecutionChange={id => { this.handleExecutionChange(id) }}
|
|
|
|
|
+ executions={replicaStore.replicaDetails?.executions || []}
|
|
|
|
|
+ executionsTasksLoading={replicaStore.executionsTasksLoading
|
|
|
|
|
+ || replicaStore.replicaDetailsLoading || replicaStore.startingExecution}
|
|
|
|
|
+ executionsTasks={replicaStore.executionsTasks}
|
|
|
page={this.props.match.params.page || ''}
|
|
page={this.props.match.params.page || ''}
|
|
|
onCancelExecutionClick={(e, f) => { this.handleCancelExecution(e, f) }}
|
|
onCancelExecutionClick={(e, f) => { this.handleCancelExecution(e, f) }}
|
|
|
onDeleteExecutionClick={execution => { this.handleDeleteExecutionClick(execution) }}
|
|
onDeleteExecutionClick={execution => { this.handleDeleteExecutionClick(execution) }}
|
|
@@ -602,7 +638,7 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
|
|
|
/>
|
|
/>
|
|
|
{this.state.showDeleteReplicaConfirmation ? (
|
|
{this.state.showDeleteReplicaConfirmation ? (
|
|
|
<DeleteReplicaModal
|
|
<DeleteReplicaModal
|
|
|
- hasDisks={replicaStore.hasReplicaDisks(this.replica)}
|
|
|
|
|
|
|
+ hasDisks={replicaStore.testReplicaHasDisks(this.replica)}
|
|
|
onRequestClose={() => this.handleCloseDeleteReplicaConfirmation()}
|
|
onRequestClose={() => this.handleCloseDeleteReplicaConfirmation()}
|
|
|
onDeleteReplica={() => { this.handleDeleteReplicaConfirmation() }}
|
|
onDeleteReplica={() => { this.handleDeleteReplicaConfirmation() }}
|
|
|
onDeleteDisks={() => { this.handleDeleteReplicaDisksConfirmation() }}
|
|
onDeleteDisks={() => { this.handleDeleteReplicaDisksConfirmation() }}
|