1
1
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'
4
3
5
4
import {
6
5
APIResponseHandler ,
7
6
Button ,
8
7
ButtonComponentType ,
9
- ButtonStyleType ,
10
8
ButtonVariantType ,
11
9
ComponentSizeType ,
12
10
DeleteConfirmationModal ,
13
- GenericEmptyState ,
14
- getAlphabetIcon ,
15
- handleAnalyticsEvent ,
11
+ FiltersTypeEnum ,
16
12
Icon ,
17
- PortalContainer ,
18
- SortableTableHeaderCell ,
19
- stringComparatorBySortOrder ,
20
- Tooltip ,
13
+ PaginationEnum ,
14
+ Table ,
21
15
useAsync ,
22
- useStateFilters ,
23
16
} from '@devtron-labs/devtron-fe-common-lib'
24
17
25
18
import { deleteChartValues } from '@Components/charts/charts.service'
26
19
import { SavedValueType } from '@Components/charts/SavedValues/types'
27
- import { Moment12HourFormat } from '@Config/constants'
28
20
import { URLS } from '@Config/routes'
29
21
import { ApplicationDeletionInfo } from '@Pages/Shared/ApplicationDeletionInfo/ApplicationDeletionInfo'
30
22
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'
32
28
import { fetchChartValuesTemplateList } from './services'
33
- import { ChartDetailsPresetValuesProps , ChartDetailsRouteParams } from './types'
29
+ import { ChartDetailsRouteParams , PresetValuesTable } from './types'
34
30
35
31
const renderEmptyStateButton = ( path : string ) => ( ) => (
36
32
< Button
@@ -44,17 +40,7 @@ const renderEmptyStateButton = (path: string) => () => (
44
40
/>
45
41
)
46
42
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 = ( ) => {
58
44
// STATES
59
45
const [ deletePresetValue , setDeletePresetValue ] = useState < SavedValueType | null > ( null )
60
46
@@ -72,27 +58,18 @@ export const ChartDetailsPresetValues = ({ searchKey, onClearFilters }: ChartDet
72
58
reloadChartValuesTemplateList ,
73
59
] = useAsync ( ( ) => fetchChartValuesTemplateList ( chartId ) , [ chartId ] , true , { resetOnChange : false } )
74
60
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
+ )
86
71
87
72
// 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
-
96
73
const handleChartPresetDelete = async ( ) => {
97
74
await deleteChartValues ( deletePresetValue . id )
98
75
reloadChartValuesTemplateList ( )
@@ -106,139 +83,50 @@ export const ChartDetailsPresetValues = ({ searchKey, onClearFilters }: ChartDet
106
83
setDeletePresetValue ( null )
107
84
}
108
85
86
+ const filter : PresetValuesTable [ 'filter' ] = ( rowData , filterData ) =>
87
+ rowData . data . name . includes ( filterData . searchKey . toLowerCase ( ) )
88
+
109
89
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" >
125
91
< APIResponseHandler
126
- isLoading = { isFetchingChartValuesTemplateList }
92
+ isLoading = { false }
127
93
progressingProps = { { size : 24 } }
128
94
error = { chartValuesTemplateListErr }
129
95
errorScreenManagerProps = { {
130
96
code : chartValuesTemplateListErr ?. code ,
131
97
reload : reloadChartValuesTemplateList ,
132
98
} }
133
99
>
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
+ />
242
130
</ APIResponseHandler >
243
131
{ deletePresetValue && (
244
132
< DeleteConfirmationModal
0 commit comments