Skip to content

Commit 2182f62

Browse files
committed
feat: ChartDetails - PresetValues - update with Table component
1 parent beb8b2a commit 2182f62

File tree

6 files changed

+345
-201
lines changed

6 files changed

+345
-201
lines changed

src/Pages/ChartStore/ChartDetails/ChartDetails.tsx

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ import {
55
APIResponseHandler,
66
BreadCrumb,
77
PageHeader,
8-
SearchBar,
98
SegmentedControl,
109
SegmentedControlProps,
1110
SelectPickerProps,
1211
useAsync,
1312
useBreadcrumb,
14-
useStateFilters,
1513
useUrlFilters,
1614
} from '@devtron-labs/devtron-fe-common-lib'
1715

@@ -21,6 +19,7 @@ import { getAvailableCharts } from '@Services/service'
2119

2220
import { ChartDetailsAbout } from './ChartDetailsAbout'
2321
import { ChartDetailsDeploy } from './ChartDetailsDeploy'
22+
import { ChartDetailsDeployments } from './ChartDetailsDeployments'
2423
import { ChartDetailsPresetValues } from './ChartDetailsPresetValues'
2524
import { ChartDetailsReadme } from './ChartDetailsReadme'
2625
import { CHART_DETAILS_PORTAL_CONTAINER_ID, CHART_DETAILS_SEGMENTS } from './constants'
@@ -44,8 +43,6 @@ export const ChartDetails = () => {
4443
parseSearchParams: parseChartDetailsSearchParams,
4544
})
4645

47-
const { searchKey, handleSearch, clearFilters } = useStateFilters()
48-
4946
// ASYNC CALLS
5047
const [isFetchingChartVersions, chartVersions, chartVersionsErr, reloadChartVersions] = useAsync(
5148
() => fetchChartVersions(chartId),
@@ -65,10 +62,6 @@ export const ChartDetails = () => {
6562
}
6663
}, [isFetchingChartVersions, chartVersions])
6764

68-
useEffect(() => {
69-
clearFilters()
70-
}, [tab])
71-
7265
// CONFIGS
7366
const { breadcrumbs } = useBreadcrumb(
7467
{
@@ -135,9 +128,9 @@ export const ChartDetails = () => {
135128
/>
136129
)
137130
case ChartDetailsSegment.PRESET_VALUES:
138-
return <ChartDetailsPresetValues searchKey={searchKey} onClearFilters={clearFilters} />
131+
return <ChartDetailsPresetValues />
139132
case ChartDetailsSegment.DEPLOYMENTS:
140-
return <div>DEPLOYMENTS</div>
133+
return <ChartDetailsDeployments chartIcon={chartDetails?.icon} />
141134
default:
142135
return null
143136
}
@@ -164,24 +157,13 @@ export const ChartDetails = () => {
164157
<Route>
165158
<div className="chart-details flex-grow-1 p-20 dc__overflow-auto">
166159
<div className="flexbox-col dc__gap-16 mw-none">
167-
<div className="flex dc__content-space">
160+
<div id={CHART_DETAILS_PORTAL_CONTAINER_ID} className="flex dc__content-space">
168161
<SegmentedControl
169162
name="chart-details-segmented-control"
170163
segments={CHART_DETAILS_SEGMENTS}
171164
value={tab}
172165
onChange={handleSegmentChange}
173166
/>
174-
{(tab === ChartDetailsSegment.PRESET_VALUES ||
175-
tab === ChartDetailsSegment.DEPLOYMENTS) && (
176-
<div id={CHART_DETAILS_PORTAL_CONTAINER_ID} className="flex dc__gap-8">
177-
<SearchBar
178-
containerClassName="w-250"
179-
dataTestId="chart-details-search-bar"
180-
initialSearchText={searchKey}
181-
handleEnter={handleSearch}
182-
/>
183-
</div>
184-
)}
185167
</div>
186168
{renderSegments()}
187169
</div>

src/Pages/ChartStore/ChartDetails/ChartDetailsPresetValues.tsx

Lines changed: 56 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,32 @@
11
import { useMemo, useState } from 'react'
2-
import { generatePath, Link, useRouteMatch } from 'react-router-dom'
3-
import moment from 'moment'
2+
import { generatePath, useRouteMatch } from 'react-router-dom'
43

54
import {
65
APIResponseHandler,
76
Button,
87
ButtonComponentType,
9-
ButtonStyleType,
108
ButtonVariantType,
119
ComponentSizeType,
1210
DeleteConfirmationModal,
13-
GenericEmptyState,
14-
getAlphabetIcon,
15-
handleAnalyticsEvent,
11+
FiltersTypeEnum,
1612
Icon,
17-
PortalContainer,
18-
SortableTableHeaderCell,
19-
stringComparatorBySortOrder,
20-
Tooltip,
13+
PaginationEnum,
14+
Table,
2115
useAsync,
22-
useStateFilters,
2316
} from '@devtron-labs/devtron-fe-common-lib'
2417

2518
import { deleteChartValues } from '@Components/charts/charts.service'
2619
import { SavedValueType } from '@Components/charts/SavedValues/types'
27-
import { Moment12HourFormat } from '@Config/constants'
2820
import { URLS } from '@Config/routes'
2921
import { ApplicationDeletionInfo } from '@Pages/Shared/ApplicationDeletionInfo/ApplicationDeletionInfo'
3022

31-
import { CHART_DETAILS_PORTAL_CONTAINER_ID } from './constants'
23+
import {
24+
PresetValuesTableRowActionsOnHoverComponent,
25+
PresetValuesTableViewWrapper,
26+
} from './ChartDetailsTableComponents'
27+
import { PRESET_VALUES_TABLE_COLUMNS } from './constants'
3228
import { fetchChartValuesTemplateList } from './services'
33-
import { ChartDetailsPresetValuesProps, ChartDetailsRouteParams } from './types'
29+
import { ChartDetailsRouteParams, PresetValuesTable } from './types'
3430

3531
const renderEmptyStateButton = (path: string) => () => (
3632
<Button
@@ -44,17 +40,7 @@ const renderEmptyStateButton = (path: string) => () => (
4440
/>
4541
)
4642

47-
const renderFilterEmptyStateButton = (onClick: () => void) => () => (
48-
<Button
49-
dataTestId="chart-preset-values-clear-filters"
50-
variant={ButtonVariantType.secondary}
51-
text="Clear Filters"
52-
size={ComponentSizeType.medium}
53-
onClick={onClick}
54-
/>
55-
)
56-
57-
export const ChartDetailsPresetValues = ({ searchKey, onClearFilters }: ChartDetailsPresetValuesProps) => {
43+
export const ChartDetailsPresetValues = () => {
5844
// STATES
5945
const [deletePresetValue, setDeletePresetValue] = useState<SavedValueType | null>(null)
6046

@@ -72,27 +58,18 @@ export const ChartDetailsPresetValues = ({ searchKey, onClearFilters }: ChartDet
7258
reloadChartValuesTemplateList,
7359
] = useAsync(() => fetchChartValuesTemplateList(chartId), [chartId], true, { resetOnChange: false })
7460

75-
const { sortBy, sortOrder, handleSorting } = useStateFilters<'name'>({ initialSortKey: 'name' })
76-
77-
const filteredChartValuesTemplateList = useMemo(() => {
78-
if (!isFetchingChartValuesTemplateList && chartValuesTemplateList) {
79-
return chartValuesTemplateList
80-
.filter((cluster) => cluster.name.includes(searchKey.toLowerCase()))
81-
.sort((a, b) => stringComparatorBySortOrder(a.name, b.name, sortOrder))
82-
}
83-
84-
return []
85-
}, [chartValuesTemplateList, isFetchingChartValuesTemplateList, searchKey, sortOrder])
61+
const rows = useMemo<PresetValuesTable['rows']>(
62+
() =>
63+
(chartValuesTemplateList || []).map<PresetValuesTable['rows'][0]>(
64+
({ id, chartVersion, name, updatedBy, updatedOn }) => ({
65+
id: id.toString(),
66+
data: { chartVersion, name, updatedBy, updatedOn, id },
67+
}),
68+
),
69+
[chartValuesTemplateList],
70+
)
8671

8772
// HANDLERS
88-
const triggerSorting = () => {
89-
handleSorting('name')
90-
}
91-
92-
const handleChartPresetDeployAndEdit = () => {
93-
handleAnalyticsEvent({ category: 'Chart Store', action: 'CS_CHART_PRESET_VALUES_NEW' })
94-
}
95-
9673
const handleChartPresetDelete = async () => {
9774
await deleteChartValues(deletePresetValue.id)
9875
reloadChartValuesTemplateList()
@@ -106,139 +83,50 @@ export const ChartDetailsPresetValues = ({ searchKey, onClearFilters }: ChartDet
10683
setDeletePresetValue(null)
10784
}
10885

86+
const filter: PresetValuesTable['filter'] = (rowData, filterData) =>
87+
rowData.data.name.includes(filterData.searchKey.toLowerCase())
88+
10989
return (
110-
<div className="mh-500 flexbox-col bg__primary border__primary br-4 w-100 dc__overflow-hidden">
111-
<PortalContainer
112-
portalParentId={CHART_DETAILS_PORTAL_CONTAINER_ID}
113-
condition={Array.isArray(chartValuesTemplateList) && !!chartValuesTemplateList.length}
114-
>
115-
<Button
116-
dataTestId="chart-preset-values-clear-filters"
117-
variant={ButtonVariantType.secondary}
118-
startIcon={<Icon name="ic-add" color={null} />}
119-
text="Create Preset"
120-
size={ComponentSizeType.medium}
121-
component={ButtonComponentType.link}
122-
linkProps={{ to: `${generatePath(path, { chartId })}${URLS.PRESET_VALUES}/0` }}
123-
/>
124-
</PortalContainer>
90+
<div className="mh-500 flexbox-col bg__primary border__primary br-4 w-100 dc__overflow-auto">
12591
<APIResponseHandler
126-
isLoading={isFetchingChartValuesTemplateList}
92+
isLoading={false}
12793
progressingProps={{ size: 24 }}
12894
error={chartValuesTemplateListErr}
12995
errorScreenManagerProps={{
13096
code: chartValuesTemplateListErr?.code,
13197
reload: reloadChartValuesTemplateList,
13298
}}
13399
>
134-
{!chartValuesTemplateList?.length && (
135-
<GenericEmptyState
136-
title="Create your first Preset Template"
137-
subTitle="Create reusable Helm config templates for different scenarios. Set them up once and let your team deploy with confidence."
138-
illustrationName="illustration-code"
139-
isButtonAvailable
140-
renderButton={renderEmptyStateButton(generatePath(path, { chartId }))}
141-
/>
142-
)}
143-
{!!chartValuesTemplateList?.length &&
144-
(filteredChartValuesTemplateList.length ? (
145-
<>
146-
<div className="chart-details-preset-value__row px-16 pt-6 pb-5 border__primary--bottom">
147-
<span className="icon-dim-24" />
148-
<SortableTableHeaderCell
149-
title="Name"
150-
isSortable
151-
isSorted={sortBy === 'name'}
152-
sortOrder={sortOrder}
153-
triggerSorting={triggerSorting}
154-
disabled={false}
155-
/>
156-
<SortableTableHeaderCell title="Version" isSortable={false} />
157-
<SortableTableHeaderCell title="Last updated by" isSortable={false} />
158-
<SortableTableHeaderCell title="Updated at" isSortable={false} />
159-
</div>
160-
{filteredChartValuesTemplateList.map(({ chartVersion, id, name, updatedBy, updatedOn }) => (
161-
<div
162-
key={id}
163-
className="chart-details-preset-value__row px-16 py-12 bg__hover dc__visible-hover dc__visible-hover--parent"
164-
>
165-
<Icon name="ic-file" color="N700" size={24} />
166-
<Link
167-
className="fs-13 lh-20 dc__truncate"
168-
to={`${generatePath(path, { chartId })}${URLS.PRESET_VALUES}/${id}`}
169-
>
170-
{name}
171-
</Link>
172-
<span className="fs-13 lh-20 cn-9">{chartVersion}</span>
173-
<span className="flex left">
174-
{updatedBy && getAlphabetIcon(updatedBy)}
175-
<Tooltip content={updatedBy}>
176-
<span className="fs-13 lh-20 cn-9 dc__truncate">{updatedBy || '-'}</span>
177-
</Tooltip>
178-
</span>
179-
<div className="flex dc__content-space">
180-
<span className="fs-13 lh-20 cn-9">
181-
{updatedOn && !updatedOn.startsWith('0001-01-01')
182-
? moment(updatedOn).format(Moment12HourFormat)
183-
: '-'}
184-
</span>
185-
<div className="flex dc__gap-4 dc__visible-hover--child">
186-
<Button
187-
dataTestId="chart-deploy-with-preset-value"
188-
ariaLabel="Use value to deploy"
189-
icon={<Icon name="ic-rocket-launch" color={null} />}
190-
variant={ButtonVariantType.borderLess}
191-
style={ButtonStyleType.neutral}
192-
size={ComponentSizeType.xs}
193-
component={ButtonComponentType.link}
194-
linkProps={{
195-
to: `${generatePath(path, { chartId })}${URLS.DEPLOY_CHART}/${id}`,
196-
}}
197-
onClick={handleChartPresetDeployAndEdit}
198-
/>
199-
<Button
200-
dataTestId="chart-preset-value-edit"
201-
ariaLabel="Edit value"
202-
icon={<Icon name="ic-edit" color={null} />}
203-
variant={ButtonVariantType.borderLess}
204-
style={ButtonStyleType.neutral}
205-
size={ComponentSizeType.xs}
206-
component={ButtonComponentType.link}
207-
linkProps={{
208-
to: `${generatePath(path, { chartId })}${URLS.PRESET_VALUES}/${id}`,
209-
}}
210-
onClick={handleChartPresetDeployAndEdit}
211-
/>
212-
<Button
213-
dataTestId="chart-preset-value-delete"
214-
ariaLabel="Delete value"
215-
icon={<Icon name="ic-delete" color={null} />}
216-
variant={ButtonVariantType.borderLess}
217-
style={ButtonStyleType.negativeGrey}
218-
size={ComponentSizeType.xs}
219-
onClick={showDeleteModal({
220-
chartVersion,
221-
id,
222-
name,
223-
updatedBy,
224-
updatedOn,
225-
isLoading: false,
226-
})}
227-
/>
228-
</div>
229-
</div>
230-
</div>
231-
))}
232-
</>
233-
) : (
234-
<GenericEmptyState
235-
title="No results"
236-
subTitle="We couldn’t find any matching results"
237-
illustrationName="illustration-no-result"
238-
isButtonAvailable
239-
renderButton={renderFilterEmptyStateButton(onClearFilters)}
240-
/>
241-
))}
100+
<Table
101+
id="table__chart-details-preset-values"
102+
loading={isFetchingChartValuesTemplateList}
103+
columns={PRESET_VALUES_TABLE_COLUMNS}
104+
rows={rows}
105+
stylesConfig={{ showSeparatorBetweenRows: false }}
106+
emptyStateConfig={{
107+
noRowsConfig: {
108+
title: 'Create your first Preset Template',
109+
subTitle:
110+
'Create reusable Helm config templates for different scenarios. Set them up once and let your team deploy with confidence.',
111+
imgName: 'img-code',
112+
isButtonAvailable: true,
113+
renderButton: renderEmptyStateButton(generatePath(path, { chartId })),
114+
},
115+
noRowsForFilterConfig: {
116+
title: 'No results',
117+
subTitle: 'We couldn’t find any matching results',
118+
},
119+
}}
120+
paginationVariant={PaginationEnum.NOT_PAGINATED}
121+
filtersVariant={FiltersTypeEnum.STATE}
122+
filter={filter}
123+
ViewWrapper={PresetValuesTableViewWrapper}
124+
RowActionsOnHoverComponent={PresetValuesTableRowActionsOnHoverComponent}
125+
additionalProps={{ showDeleteModal, chartValuesTemplateList }}
126+
additionalFilterProps={{
127+
initialSortKey: 'name',
128+
}}
129+
/>
242130
</APIResponseHandler>
243131
{deletePresetValue && (
244132
<DeleteConfirmationModal

src/Pages/ChartStore/ChartDetails/ChartDetailsReadme.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export const ChartDetailsReadme = ({
3939
const selectedChartVersionValue = getSelectPickerOptionByValue(chartsOptions, selectedChartVersion, null)
4040

4141
return (
42-
<div className="mh-500 flexbox-col bg__primary border__primary br-4 w-100 dc__overflow-hidden">
42+
<div className="mh-500 flexbox-col bg__primary border__primary br-4 dc__overflow-auto">
4343
<div className="flex left dc__gap-8 bg__secondary border__primary--bottom px-16 pt-10 pb-9">
4444
<div className="flex left dc__gap-6">
4545
<Icon name="ic-list-bullets" color="N900" />
@@ -67,7 +67,7 @@ export const ChartDetailsReadme = ({
6767
<GenericEmptyState
6868
title={`Readme not available for ${chartName} ${selectedChartVersionValue?.label}`}
6969
subTitle="A readme file was not found for this chart’s version."
70-
illustrationName="illustration-no-result"
70+
illustrationName="img-no-result"
7171
isButtonAvailable
7272
renderButton={renderEmptyStateButton}
7373
/>

0 commit comments

Comments
 (0)