Skip to content

Commit 7d57dc4

Browse files
committed
refactor: update EditTaintsModal for improved UI and messaging; clean up constants
1 parent fdc4357 commit 7d57dc4

File tree

3 files changed

+101
-91
lines changed

3 files changed

+101
-91
lines changed

.eslintignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ src/components/ClusterNodes/NodeActions/NodeActionsMenu.tsx
5757
src/components/ClusterNodes/NodeDetails.tsx
5858
src/components/ClusterNodes/__tests__/ClusterManifest.test.tsx
5959
src/components/ClusterNodes/__tests__/NodeList.test.tsx
60-
src/components/ClusterNodes/constants.ts
6160
src/components/Hotjar/Hotjar.tsx
6261
src/components/Jobs/ExpandedRow/ExpandedRow.tsx
6362
src/components/Jobs/JobDetails/JobDetails.tsx

src/components/ClusterNodes/NodeActions/EditTaintsModal.tsx

Lines changed: 81 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,14 @@ import {
2424
ComponentSizeType,
2525
Drawer,
2626
DynamicDataTable,
27+
GenericEmptyState,
2728
Icon,
28-
InfoBlock,
29+
InfoIconTippy,
2930
showError,
30-
stopPropagation,
31-
TippyCustomized,
32-
TippyTheme,
3331
ToastManager,
3432
ToastVariantType,
3533
} from '@devtron-labs/devtron-fe-common-lib'
3634

37-
import { ReactComponent as HelpIcon } from '../../../assets/icons/ic-help.svg'
3835
import { updateTaints } from '../clusterNodes.service'
3936
import { EDIT_TAINTS_MODAL_MESSAGING, TAINTS_TABLE_HEADERS } from '../constants'
4037
import { EditTaintsModalType, EditTaintsRequest, TaintsTableHeaderKeys, TaintsTableType } from '../types'
@@ -49,35 +46,20 @@ import {
4946
validateUniqueTaintKey,
5047
} from './utils'
5148

52-
const TaintInfoMessage = () => (
53-
<div className="fs-13 fw-4 lh-20">
54-
<span>{EDIT_TAINTS_MODAL_MESSAGING.infoText}</span> &nbsp;
55-
<TippyCustomized
56-
theme={TippyTheme.white}
57-
className="w-400"
58-
placement="top"
59-
Icon={HelpIcon}
60-
iconClass="fcv-5"
61-
heading={EDIT_TAINTS_MODAL_MESSAGING.tippyTitle}
62-
infoText=""
63-
showCloseButton
64-
trigger="click"
65-
interactive
66-
additionalContent={
67-
<div className="p-12 fs-13">
68-
<div>{EDIT_TAINTS_MODAL_MESSAGING.tippyDescription.message}</div>
69-
<ul className="p-0" style={{ listStyleType: 'none' }}>
70-
{EDIT_TAINTS_MODAL_MESSAGING.tippyDescription.messageList.map((message) => (
71-
<li key={`msg-${message}`}>{message}</li>
72-
))}
73-
</ul>
74-
</div>
75-
}
76-
>
77-
<span className="cb-5 cursor" onClick={stopPropagation}>
78-
{EDIT_TAINTS_MODAL_MESSAGING.infoLinkText}
79-
</span>
80-
</TippyCustomized>
49+
const AdditionalContent = () => (
50+
<div className="p-12 h-200 dc__overflow-auto fs-13 lh-20">
51+
{EDIT_TAINTS_MODAL_MESSAGING.infoText}
52+
<br />
53+
<br />
54+
<div>
55+
{EDIT_TAINTS_MODAL_MESSAGING.description.title}
56+
<br />
57+
<ol className="pl-24">
58+
{EDIT_TAINTS_MODAL_MESSAGING.description.messageList.map((text) => (
59+
<li key={text}>{text}</li>
60+
))}
61+
</ol>
62+
</div>
8163
</div>
8264
)
8365

@@ -92,6 +74,9 @@ const EditTaintsModal = ({ name, version, kind, taints, closePopup }: EditTaints
9274
// HOOKS
9375
const { clusterId } = useParams<{ clusterId: string }>()
9476

77+
// CONSTANTS
78+
const isTaintListEmpty = taintList.length === 0
79+
9580
// HANDLERS
9681
const onClose = () => {
9782
if (!apiCallInProgress) {
@@ -177,48 +162,73 @@ const EditTaintsModal = ({ name, version, kind, taints, closePopup }: EditTaints
177162
showAriaLabelInTippy={false}
178163
/>
179164
</div>
180-
<div className="flexbox-col px-20 py-16 dc__overflow-auto flex-grow-1 dc__gap-16">
181-
<InfoBlock description={<TaintInfoMessage />} />
182-
{taintList.length ? (
183-
<DynamicDataTable<TaintsTableHeaderKeys>
184-
headers={TAINTS_TABLE_HEADERS}
185-
rows={taintList}
186-
onRowAdd={handleAddTaint}
187-
onRowDelete={handleDeleteTaint}
188-
onRowEdit={handleEditTaint}
189-
cellError={taintCellError}
190-
addBtnTooltip="Add taint"
165+
<div className="flex-grow-1 dc__overflow-auto flexbox-col dc__gap-16 p-20">
166+
{isTaintListEmpty ? (
167+
<GenericEmptyState
168+
title={EDIT_TAINTS_MODAL_MESSAGING.emptyState.title}
169+
subTitle={EDIT_TAINTS_MODAL_MESSAGING.emptyState.subTitle}
170+
isButtonAvailable
171+
renderButton={() => (
172+
<Button
173+
dataTestId="add-taint"
174+
text={EDIT_TAINTS_MODAL_MESSAGING.addTaint}
175+
startIcon={<Icon name="ic-add" color={null} />}
176+
onClick={handleAddTaint}
177+
/>
178+
)}
191179
/>
192180
) : (
193-
<div className="p-8 bg__secondary dc__border-dashed--n3 br-4 flex dc__content-space">
194-
{/* TODO: update this text */}
195-
<p className="m-0 fs-12 lh-18 cn-7">Add Taint</p>
196-
<Button
197-
dataTestId="add-taint"
198-
variant={ButtonVariantType.text}
199-
text="Add Taint"
200-
startIcon={<Icon name="ic-add" color={null} />}
201-
onClick={handleAddTaint}
181+
<>
182+
<div className="flex dc__content-space">
183+
<div className="flex">
184+
<Icon name="ic-error" color="N900" />
185+
<h3 className="fs-14 lh-20 fw-6 cn-9 mt-0 mb-0 ml-8 mr-4">Taints</h3>
186+
<InfoIconTippy
187+
heading="Taints"
188+
documentationLinkText="View documentation"
189+
documentationLink="https://docs.devtron.ai/usage/resource-browser#taint-a-node"
190+
additionalContent={<AdditionalContent />}
191+
/>
192+
</div>
193+
<Button
194+
dataTestId="add-taint"
195+
variant={ButtonVariantType.secondary}
196+
startIcon={<Icon name="ic-add" color={null} />}
197+
size={ComponentSizeType.small}
198+
text={EDIT_TAINTS_MODAL_MESSAGING.addTaint}
199+
onClick={handleAddTaint}
200+
/>
201+
</div>
202+
<DynamicDataTable<TaintsTableHeaderKeys>
203+
headers={TAINTS_TABLE_HEADERS}
204+
rows={taintList}
205+
onRowAdd={handleAddTaint}
206+
onRowDelete={handleDeleteTaint}
207+
onRowEdit={handleEditTaint}
208+
cellError={taintCellError}
209+
isAdditionNotAllowed
202210
/>
203-
</div>
211+
</>
204212
)}
205213
</div>
206-
<div className="dc__border-top flex right p-16 dc__gap-8">
207-
<Button
208-
dataTestId="edit-taints-modal-cancel"
209-
variant={ButtonVariantType.secondary}
210-
style={ButtonStyleType.neutral}
211-
disabled={apiCallInProgress}
212-
text={EDIT_TAINTS_MODAL_MESSAGING.Actions.cancel}
213-
onClick={onClose}
214-
/>
215-
<Button
216-
dataTestId="edit-taints-modal-save"
217-
isLoading={apiCallInProgress}
218-
text={EDIT_TAINTS_MODAL_MESSAGING.Actions.save}
219-
onClick={onSave}
220-
/>
221-
</div>
214+
{!isTaintListEmpty && (
215+
<div className="dc__border-top flex right p-16 dc__gap-8">
216+
<Button
217+
dataTestId="edit-taints-modal-cancel"
218+
variant={ButtonVariantType.secondary}
219+
style={ButtonStyleType.neutral}
220+
disabled={apiCallInProgress}
221+
text={EDIT_TAINTS_MODAL_MESSAGING.Actions.cancel}
222+
onClick={onClose}
223+
/>
224+
<Button
225+
dataTestId="edit-taints-modal-save"
226+
isLoading={apiCallInProgress}
227+
text={EDIT_TAINTS_MODAL_MESSAGING.Actions.save}
228+
onClick={onSave}
229+
/>
230+
</div>
231+
)}
222232
</div>
223233
</Drawer>
224234
)

src/components/ClusterNodes/constants.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,27 @@ export const clusterSelectStyle = {
3030
backgroundColor: 'var(--bg-menu-primary)',
3131
border: '1px solid var(--N200)',
3232
}),
33-
control: (base, state) => ({
33+
control: (base) => ({
3434
...base,
3535
borderColor: 'transparent',
3636
backgroundColor: 'transparent',
3737
cursor: 'pointer',
3838
height: '28px',
3939
minHeight: '28px',
4040
}),
41-
singleValue: (base, state) => ({
41+
singleValue: (base) => ({
4242
...base,
4343
fontWeight: 600,
4444
color: 'var(--N900)',
4545
direction: 'rtl',
4646
textAlign: 'left',
4747
marginLeft: '2px',
4848
}),
49-
indicatorsContainer: (base, state) => ({
49+
indicatorsContainer: (base) => ({
5050
...base,
5151
height: '28px',
5252
}),
53-
valueContainer: (base, state) => ({
53+
valueContainer: (base) => ({
5454
...base,
5555
height: '28px',
5656
padding: '0 6px',
@@ -105,18 +105,20 @@ export const CLUSTER_NODE_ACTIONS_LABELS = {
105105
export const EDIT_TAINTS_MODAL_MESSAGING = {
106106
titlePrefix: 'Edit taints for node ',
107107
infoText:
108-
'Add taints to nodes so that pods are not scheduled to the nodes or not scheduled to the nodes if possible. After you add taints to nodes, you can set tolerations on a pod to allow the pod to be scheduled to nodes with certain taints.',
109-
infoLinkText: 'Check taint validations.',
110-
tippyTitle: 'Taint validations',
111-
tippyDescription: {
112-
message: 'A taint consists of a key, value, and effect.',
108+
'Add taints to nodes to prevent or discourage pods from being scheduled on them. Use tolerations on pods to let them run on nodes with matching taints.',
109+
description: {
110+
title: 'A taint consists of a key, value, and effect.',
113111
messageList: [
114-
`1. Key: The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to 253 characters.`,
115-
`Optionally, the key can begin with a DNS subdomain prefix and a single '/', like example.com/my-app.`,
116-
`2. Value(Optional) :If given, it must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to 63 characters.`,
117-
`3. Combination of <key, effect> must be unique.`,
112+
'Key: The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots,and underscores, up to 253 characters. Optionally, the key can begin with a DNS subdomain prefix and a single &apos;/&apos;, like example.com/my-app.',
113+
'Value(Optional): If given, it must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to 63 characters.',
114+
'Combination of &lt;key, effect&gt; must be unique',
118115
],
119116
},
117+
emptyState: {
118+
title: 'Manage node taints',
119+
subTitle:
120+
'Add taints to nodes to prevent or discourage pods from being scheduled on them. Use tolerations on pods to let them run on nodes with matching taints.',
121+
},
120122
addTaint: 'Add taint',
121123
Actions: {
122124
cancel: 'Cancel',
@@ -156,7 +158,7 @@ export const AUTO_SELECT = { label: 'Auto select', value: 'autoSelectNode' }
156158

157159
export const clusterImageSelect = {
158160
...clusterSelectStyle,
159-
menu: (base, state) => ({
161+
menu: (base) => ({
160162
...base,
161163
zIndex: 9999,
162164
textAlign: 'left',
@@ -165,8 +167,8 @@ export const clusterImageSelect = {
165167
backgroundColor: 'var(--bg-menu-primary)',
166168
border: '1px solid var(--N200)',
167169
}),
168-
control: (base, state) => ({
169-
...clusterSelectStyle.control(base, state),
170+
control: (base) => ({
171+
...clusterSelectStyle.control(base),
170172
maxWidth: '300px',
171173
}),
172174
}
@@ -330,9 +332,8 @@ export enum ClusterMapListSortableTitle {
330332
}
331333

332334
export enum CLUSTER_PROD_TYPE {
333-
PRODUCTION= 'Production',
334-
NON_PRODUCTION= 'Non Production',
335-
335+
PRODUCTION = 'Production',
336+
NON_PRODUCTION = 'Non Production',
336337
}
337338

338339
export const TAINTS_TABLE_HEADERS: TaintsTableType['headers'] = [

0 commit comments

Comments
 (0)