// Copyright Amazon.com, Inc. or its affiliates. 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. A copy of the License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "LICENSE.txt" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and
// limitations under the License.
import {CloudFormationResourceStatus, Region} from '../../types/base'
import {ClusterName, ClusterStatus} from '../../types/clusters'
import {StackEvent, StackEvents} from '../../types/stackevents'
import React from 'react'
import {Link, useSearchParams} from 'react-router-dom'
// Model
import {DescribeCluster, GetClusterStackEvents} from '../../model'
import {
consoleDomain,
getState,
setState,
clearState,
useState,
} from '../../store'
import {useCollection} from '@cloudscape-design/collection-hooks'
import {findFirst} from '../../util'
// UI Elements
import {
Button,
CollectionPreferences,
Header,
Pagination,
SpaceBetween,
Table,
TextFilter,
} from '@cloudscape-design/components'
// Components
import {StackEventStatusIndicator} from '../../components/Status'
import DateView from '../../components/date/DateView'
import Loading from '../../components/Loading'
import EmptyState from '../../components/EmptyState'
import {useTranslation} from 'react-i18next'
function EventStatus(stackEvent: StackEvent) {
return (
)
}
export default function ClusterStackEvents() {
const {t} = useTranslation()
const clusterName: ClusterName = useState(['app', 'clusters', 'selected'])
const events: StackEvents = useState([
'clusters',
'index',
clusterName,
'stackevents',
'events',
])
const columns = useState(['app', 'clusters', 'stackevents', 'columns']) || [
'timestamp',
'logicalId',
'status',
'statusReason',
]
const pageSize =
useState(['app', 'clusters', 'stackevents', 'pageSize']) || 100
const defaultRegion = useState(['aws', 'region'])
const region: Region = useState(['app', 'selectedRegion']) || defaultRegion
let [searchParams, setSearchParams] = useSearchParams()
const clusterPath = ['clusters', 'index', clusterName]
const cluster = useState(clusterPath)
let cfnHref = `${consoleDomain(
region,
)}/cloudformation/home?region=${region}#/stacks?filteringStatus=active&filteringText=${clusterName}`
if (cluster)
cfnHref = `${consoleDomain(
region,
)}/cloudformation/home?region=${region}#/stacks/events?filteringStatus=active&filteringText=${clusterName}&viewNested=true&hideStacks=false&stackId=${encodeURIComponent(
cluster.cloudformationStackArn,
)}`
React.useEffect(() => {
const clusterName: ClusterName = getState(['app', 'clusters', 'selected'])
const clusterPath = ['clusters', 'index', clusterName]
const cluster = getState(clusterPath)
const headNode = getState([...clusterPath, 'headNode'])
GetClusterStackEvents(clusterName)
DescribeCluster(clusterName)
let timerId: ReturnType | undefined = setInterval(
() => {
if (cluster.clusterStatus !== ClusterStatus.CreateInProgress) {
clearInterval(timerId)
timerId = undefined
} else {
if (!headNode) DescribeCluster(clusterName)
GetClusterStackEvents(clusterName)
}
},
5000,
)
return () => {
timerId && clearInterval(timerId)
}
}, [])
const refreshStackEvents = () => {
clearState(['clusters', 'index', clusterName, 'stackevents'])
GetClusterStackEvents(clusterName)
}
const {
items,
actions,
filteredItemsCount,
collectionProps,
filterProps,
paginationProps,
} = useCollection(events || [], {
filtering: {
empty: ,
noMatch: (
actions.setFiltering('')}>
Clear filter
}
/>
),
},
pagination: {pageSize: pageSize},
sorting: {
defaultState: {
sortingColumn: {
sortingField: 'timestamp',
},
isDescending: true,
},
},
selection: {},
})
React.useEffect(() => {
filterProps.onChange({
detail: {filteringText: searchParams.get('filter') || ''},
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchParams])
return events ? (
}
>
{t('cluster.stackEvents.title')}
}
resizableColumns
wrapLines
visibleColumns={columns}
variant="container"
columnDefinitions={[
{
id: 'timestamp',
header: 'Timestamp',
cell: event => ,
sortingField: 'timestamp',
},
{
id: 'logicalId',
header: 'Logical ID',
cell: event => event.logicalResourceId,
},
{
id: 'status',
header: 'Status',
cell: event => ,
},
{
id: 'statusReason',
header: 'Status reason',
cell: event => event.resourceStatusReason,
},
]}
loading={events === null}
items={items}
loadingText="Loading Logs..."
pagination={}
filter={
{
searchParams.set('filter', e.detail.filteringText)
setSearchParams(searchParams)
filterProps.onChange(e)
}}
countText={`Results: ${filteredItemsCount}`}
filteringAriaLabel={t(
'cluster.stackEvents.filter.filteringAriaLabel',
)}
filteringPlaceholder={t(
'cluster.stackEvents.filter.filteringPlaceholder',
)}
/>
}
preferences={
{
setState(
['app', 'clusters', 'stackevents', 'columns'],
detail.visibleContent,
)
setState(
['app', 'clusters', 'stackevents', 'pageSize'],
detail.pageSize,
)
}}
title="Preferences"
confirmLabel="Confirm"
cancelLabel="Cancel"
preferences={{
pageSize: pageSize,
visibleContent: columns,
}}
pageSizePreference={{
title: 'Select page size',
options: [
{value: 100, label: '100 Logs'},
{value: 250, label: '250 Logs'},
{value: 500, label: '500 Logs'},
],
}}
visibleContentPreference={{
title: 'Select visible content',
options: [
{
label: 'Log columns',
options: [
{id: 'timestamp', label: 'Timestamp'},
{id: 'logicalId', label: 'Logical ID'},
{id: 'status', label: 'Status'},
{id: 'statusReason', label: 'Status reason'},
],
},
],
}}
/>
}
/>
) : (
)
}