Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/components/app/details/appDetails/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import moment from 'moment'
import { AggregationKeys } from '../../types'
import { getVersionArr, isVersionLessThanOrEqualToTarget, DayPickerRangeControllerPresets } from '../../../common'
import { getVersionArr, isVersionLessThanOrEqualToTarget } from '../../../common'
import { ChartTypes, AppMetricsTabType, StatusType, StatusTypes } from './appDetails.type'
import {
ZERO_TIME_STRING,
Expand All @@ -31,6 +31,7 @@
AppEnvironment,
SelectPickerOptionType,
IconsProps,
DayPickerRangeControllerPresets,

Check failure on line 34 in src/components/app/details/appDetails/utils.tsx

View workflow job for this annotation

GitHub Actions / ci

Module '"@devtron-labs/devtron-fe-common-lib"' has no exported member 'DayPickerRangeControllerPresets'.
} from '@devtron-labs/devtron-fe-common-lib'
import { GetIFrameSrcParamsType } from './types'

Expand Down
112 changes: 10 additions & 102 deletions src/components/common/DatePickers/DayPickerRangeController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,101 +24,11 @@
import './calendar.css'
import { ReactComponent as ArrowDown } from '../../../assets/icons/ic-chevron-down.svg'
import { DA_APP_DETAILS_GA_EVENTS } from '@Components/app/details/appDetails/constants'
import { Button, customDayStyles, DatePickerRangeControllerProps, DayPickerCalendarInfoHorizontal, DayPickerRangeControllerPresets } from '@devtron-labs/devtron-fe-common-lib/dist'

Check failure on line 27 in src/components/common/DatePickers/DayPickerRangeController.tsx

View workflow job for this annotation

GitHub Actions / ci

Module '"@devtron-labs/devtron-fe-common-lib/dist"' has no exported member 'DayPickerRangeControllerPresets'.

Check failure on line 27 in src/components/common/DatePickers/DayPickerRangeController.tsx

View workflow job for this annotation

GitHub Actions / ci

Module '"@devtron-labs/devtron-fe-common-lib/dist"' has no exported member 'DayPickerCalendarInfoHorizontal'.

Check failure on line 27 in src/components/common/DatePickers/DayPickerRangeController.tsx

View workflow job for this annotation

GitHub Actions / ci

Module '"@devtron-labs/devtron-fe-common-lib/dist"' has no exported member 'DatePickerRangeControllerProps'.
import { customStyles } from './constants'

interface DatePickerType2Props {
calendar
calendarInputs
focusedInput
handleFocusChange
handleDatesChange
handleCalendarInputs?
calendarValue: string
handlePredefinedRange: (start: Moment, end: Moment, endStr: string) => void
handleDateInput: (key: 'startDate' | 'endDate', value: string) => void
handleApply: (...args) => void
}

const hoveredSpanStyles = {
background: 'var(--B100)',
color: 'var(--B500)',
}

const selectedStyles = {
background: 'var(--B100)',
color: 'var(--B500)',
hover: {
background: 'var(--B500)',
color: 'var(--N0)',
},
}

const selectedSpanStyles = {
background: 'var(--B100)',
color: 'var(--B500)',

hover: {
background: 'var(--B500)',
color: 'var(--N0)',
},
}

const customDayStyles = {
selectedStartStyles: selectedStyles,
selectedEndStyles: selectedStyles,
hoveredSpanStyles,
selectedSpanStyles,
selectedStyles,
border: 'none',
}

const styless = {
PresetDateRangePicker_panel: {
padding: '0px',
width: '200px',
height: '100%',
},
PresetDateRangePicker_button: {
width: '188px',
background: 'var(--transparent)',
border: 'none',
color: 'var(--N900)',
padding: '8px',
font: 'inherit',
fontWeight: 500,
lineHeight: 'normal',
overflow: 'visible',
cursor: 'pointer',
':active': {
outline: 0,
},
},
DayPicker__horizontal: {
borderRadius: '4px',
},
PresetDateRangePicker_button__selected: {
color: 'var(--B500)',
fontWeight: 600,
background: 'var(--B100)',
outline: 'none',
},
}

const DayPicker_calendarInfo__horizontal = {
width: '532px',
boxShadow: 'none',
}

export const DayPickerRangeControllerPresets = [
{ text: 'Last 5 minutes', endDate: moment(), startDate: moment().subtract(5, 'minutes'), endStr: 'now-5m' },
{ text: 'Last 30 minutes', endDate: moment(), startDate: moment().subtract(30, 'minutes'), endStr: 'now-30m' },
{ text: 'Last 1 hour', endDate: moment(), startDate: moment().subtract(1, 'hours'), endStr: 'now-1h' },
{ text: 'Last 24 hours', endDate: moment(), startDate: moment().subtract(24, 'hours'), endStr: 'now-24h' },
{ text: 'Last 7 days', endDate: moment(), startDate: moment().subtract(7, 'days'), endStr: 'now-7d' },
{ text: 'Last 1 month', endDate: moment(), startDate: moment().subtract(1, 'months'), endStr: 'now-1M' },
{ text: 'Last 6 months', endDate: moment(), startDate: moment().subtract(6, 'months'), endStr: 'now-6M' },
]

export class DatePickerType2 extends Component<DatePickerType2Props, any> {
export class DatePickerType2 extends Component<DatePickerRangeControllerProps, any> {
constructor(props) {
super(props)
this.state = {
Expand All @@ -144,15 +54,15 @@
<div
className="flex left top"
style={{
...styless.PresetDateRangePicker_panel,
...DayPicker_calendarInfo__horizontal,
...customStyles.PresetDateRangePicker_panel,
...DayPickerCalendarInfoHorizontal,
...{
PresetDateRangePicker_panel: {
padding: '0px',
width: '200px',
height: '100%',
},
...styless.DayPicker__horizontal,
...customStyles.DayPicker__horizontal,
},
}}
>
Expand Down Expand Up @@ -181,25 +91,23 @@
}}
/>
</label>
<button type="button" className="cta small" onClick={this.onClickApplyTimeChange}>
Apply Time Range
</button>
<Button text="Apply Time Range" onClick={this.onClickApplyTimeChange} dataTestId="apply-time-range" />
</div>
</div>
<div style={{ width: '220px', padding: '16px', borderLeft: 'solid 1px var(--N200)', height: '304px' }}>
<div className='w-200 p-16 h-300'>
{DayPickerRangeControllerPresets.map(({ text, startDate, endDate, endStr }) => {
const isSelected =
startDate.isSame(this.props.calendar.startDate, 'minute') &&
startDate.isSame(this.props.calendar.startDate, 'hour') &&
startDate.isSame(this.props.calendar.startDate, 'day') &&
endDate.isSame(this.props.calendar.endDate, 'day')
let buttonStyles = {
...styless.PresetDateRangePicker_button,
...customStyles.PresetDateRangePicker_button,
}
if (isSelected) {
buttonStyles = {
...buttonStyles,
...styless.PresetDateRangePicker_button__selected,
...customStyles.PresetDateRangePicker_button__selected,
}
}
return (
Expand Down
31 changes: 31 additions & 0 deletions src/components/common/DatePickers/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export const customStyles = {
PresetDateRangePicker_panel: {
padding: '0px',
width: '200px',
height: '100%',
},
PresetDateRangePicker_button: {
width: '188px',
background: 'var(--transparent)',
border: 'none',
color: 'var(--N900)',
padding: '8px',
font: 'inherit',
fontWeight: 500,
lineHeight: 'normal',
overflow: 'visible',
cursor: 'pointer',
':active': {
outline: 0,
},
},
DayPicker__horizontal: {
borderRadius: '4px',
},
PresetDateRangePicker_button__selected: {
color: 'var(--B500)',
fontWeight: 600,
background: 'var(--B100)',
outline: 'none',
},
}
12 changes: 11 additions & 1 deletion src/components/common/navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import React, { Component } from 'react'
import { NavLink, RouteComponentProps } from 'react-router-dom'
import ReactGA from 'react-ga4'
import { URLS as CommonURLS, Icon, MainContext } from '@devtron-labs/devtron-fe-common-lib'
import { URLS as CommonURLS, Icon, MainContext, URLS as CommonUrls } from '@devtron-labs/devtron-fe-common-lib'
import {
ModuleNameMap,
MODULE_STATUS_POLLING_INTERVAL,
Expand Down Expand Up @@ -96,6 +96,16 @@
markAsBeta: false,
isAvailableInDesktop: true,
},
{
title: 'Observability',
dataTestId: 'click-on-observability',
type: 'link',
icon: 'ic-binoculars',

Check failure on line 103 in src/components/common/navigation/Navigation.tsx

View workflow job for this annotation

GitHub Actions / ci

Type '"ic-binoculars"' is not assignable to type '"ic-arrow-clockwise" | "ic-73strings" | "ic-aborted" | "ic-activity" | "ic-add" | "ic-amazon-eks" | "ic-app-group" | "ic-app-template" | "ic-arrow-right" | "ic-arrow-square-out" | ... 225 more ... | "ic-world-globe"'.
href: CommonUrls.OBSERVABILITY,

Check failure on line 104 in src/components/common/navigation/Navigation.tsx

View workflow job for this annotation

GitHub Actions / ci

Property 'OBSERVABILITY' does not exist on type '{ readonly LOGIN: "/login"; readonly LOGIN_SSO: "/login/sso"; readonly PERMISSION_GROUPS: "/global-config/auth/groups"; readonly APP: "/app"; readonly APP_LIST: "list"; readonly CHARTS_DISCOVER: "/chart-store/discover"; ... 29 more ...; readonly GLOBAL_CONFIG_EDIT_CLUSTER: "/global-config/cluster-env/edit/:clusterId...'.
isAvailableInEA: false,
markAsBeta: false,
isAvailableInDesktop: true,
},
{
title: 'Resource Watcher',
dataTestId: 'click-on-resource-watcher',
Expand Down
4 changes: 4 additions & 0 deletions src/components/common/navigation/NavigationRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
const DevtronStackManager = lazy(() => import('../../v2/devtronStackManager/DevtronStackManager'))
const AppGroupRoute = lazy(() => import('../../ApplicationGroup/AppGroupRoute'))
const Jobs = lazy(() => import('../../Jobs/Jobs'))
const Observability = lazy(() => import('../../observability/ObservabilityRouter'))

const ResourceWatcherRouter = importComponentFromFELibrary('ResourceWatcherRouter')
const SoftwareDistributionHub = importComponentFromFELibrary('SoftwareDistributionHub', null, 'function')
Expand Down Expand Up @@ -549,6 +550,9 @@
path={URLS.SECURITY}
render={(props) => <Security {...props} serverMode={serverMode} />}
/>,
<Route key={CommonURLS.OBSERVABILITY} path={CommonURLS.OBSERVABILITY}>

Check failure on line 553 in src/components/common/navigation/NavigationRoutes.tsx

View workflow job for this annotation

GitHub Actions / ci

Property 'OBSERVABILITY' does not exist on type '{ readonly LOGIN: "/login"; readonly LOGIN_SSO: "/login/sso"; readonly PERMISSION_GROUPS: "/global-config/auth/groups"; readonly APP: "/app"; readonly APP_LIST: "list"; readonly CHARTS_DISCOVER: "/chart-store/discover"; ... 29 more ...; readonly GLOBAL_CONFIG_EDIT_CLUSTER: "/global-config/cluster-env/edit/:clusterId...'.

Check failure on line 553 in src/components/common/navigation/NavigationRoutes.tsx

View workflow job for this annotation

GitHub Actions / ci

Property 'OBSERVABILITY' does not exist on type '{ readonly LOGIN: "/login"; readonly LOGIN_SSO: "/login/sso"; readonly PERMISSION_GROUPS: "/global-config/auth/groups"; readonly APP: "/app"; readonly APP_LIST: "list"; readonly CHARTS_DISCOVER: "/chart-store/discover"; ... 29 more ...; readonly GLOBAL_CONFIG_EDIT_CLUSTER: "/global-config/cluster-env/edit/:clusterId...'.
<Observability />
</Route>,
...(!window._env_.HIDE_RESOURCE_WATCHER && ResourceWatcherRouter
? [
<Route key={URLS.RESOURCE_WATCHER} path={URLS.RESOURCE_WATCHER}>
Expand Down
51 changes: 51 additions & 0 deletions src/components/observability/Customer/CustomerList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useMemo } from 'react'

import { FiltersTypeEnum, PaginationEnum, Table, useAsync } from '@devtron-labs/devtron-fe-common-lib'

import { CUSTOMER_TABLE_COLUMN } from '../constants'
import { getCustomerListData } from '../service'
import { CustomerObservabilityDTO, CustomerTableProps } from '../types'

export const CustomerList = () => {
// ASYNC CALLS
const [isFetching, customerData] = useAsync(() => getCustomerListData(), [])

// CONFIGS
const rows = useMemo<CustomerTableProps['rows']>(
() =>
(customerData || []).map((data) => ({
id: `observe_project_${data.id.toString()}`,
data,
})),
[customerData],
)

const filter: CustomerTableProps['filter'] = (
rowData: { id: string; data: CustomerObservabilityDTO },
filterData: { searchKey: string },
) => rowData.data.name.toLowerCase().includes(filterData.searchKey.toLowerCase())

return (
<div className="observability-table-wrapper flexbox-col flex-grow-1 dc__overflow-auto">
<Table<CustomerObservabilityDTO, FiltersTypeEnum.STATE, {}>
id="table__customer-list"
loading={isFetching}
stylesConfig={{ showSeparatorBetweenRows: true }}
columns={CUSTOMER_TABLE_COLUMN}
rows={rows}
filtersVariant={FiltersTypeEnum.STATE}
emptyStateConfig={{
noRowsConfig: {
title: 'No resources found',
subTitle: `No resources found in this cluster for upgrade compatibility check`,
},
}}
filter={filter}
additionalFilterProps={{
initialSortKey: 'name',
}}
paginationVariant={PaginationEnum.PAGINATED}
/>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { FunctionComponent, useEffect, useRef } from 'react'
import { Link, useRouteMatch } from 'react-router-dom'

import {
FiltersTypeEnum,
Icon,
TableCellComponentProps,
TableSignalEnum,
Tooltip,
} from '@devtron-labs/devtron-fe-common-lib/dist'

import { CustomerObservabilityDTO, ObservabilityListFields } from '../types'

export const CustomerListCellComponent: FunctionComponent<
TableCellComponentProps<CustomerObservabilityDTO, FiltersTypeEnum.STATE, {}>
> = ({
field,
row: {
data: { id, name, status, projects, totalVms, activeVms, healthStatus, icon },
},
isRowActive,
signals,
}: TableCellComponentProps<CustomerObservabilityDTO, FiltersTypeEnum.STATE, {}>) => {
const linkRef = useRef<HTMLAnchorElement>(null)
const match = useRouteMatch()

useEffect(() => {
const handleEnter = ({ detail: { activeRowData } }) => {
if (activeRowData.data.id === id) {
linkRef.current?.click()
}
}

if (isRowActive) {
signals.addEventListener(TableSignalEnum.ENTER_PRESSED, handleEnter)
}

return () => {
signals.removeEventListener(TableSignalEnum.ENTER_PRESSED, handleEnter)
}
}, [isRowActive])

switch (field) {
case ObservabilityListFields.ICON:
return (
<span className="flexbox dc__align-items-center dc__gap-6 py-10">
<Icon name={icon as any} color={null} size={24} />
</span>
)
case ObservabilityListFields.PROJECT_NAME:
return (
<Link
ref={linkRef}
to={`${match.path}/${name}/overview`}
className="flexbox dc__align-items-center dc__gap-6 py-10"
>
<Tooltip content={name}>
<span className="dc__truncate">{name}</span>
</Tooltip>
</Link>
)
case ObservabilityListFields.STATUS:
return (
<span className="flexbox dc__align-items-center dc__gap-6">
<Icon name={status === 'ACTIVE' ? 'ic-success' : 'ic-error'} color={null} />
{status}
</span>
)
case ObservabilityListFields.PROJECTS:
return <span className="flexbox dc__align-items-center dc__gap-6 py-10">{projects}</span>
case ObservabilityListFields.TOTAL_VMS:
return <span className="flexbox dc__align-items-center dc__gap-6 py-10">{totalVms}</span>
case ObservabilityListFields.ACTIVE_VMS:
return <span className="flexbox dc__align-items-center dc__gap-6 py-10">{activeVms}</span>
case ObservabilityListFields.HEALTH_STATUS:
return (
<div className="flexbox dc__align-items-center dc__gap-6 py-10">
<Tooltip content={healthStatus}>
<span className="dc__truncate">{healthStatus}</span>
</Tooltip>
</div>
)
default:
return null
}
}
Loading
Loading