Skip to content

Commit dcfec36

Browse files
committed
feat: events integration in add notification component
1 parent 829218e commit dcfec36

File tree

6 files changed

+290
-182
lines changed

6 files changed

+290
-182
lines changed

src/components/notifications/AddNotification.tsx

Lines changed: 105 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React, { Component } from 'react'
17+
import { Component } from 'react'
1818
import {
1919
showError,
2020
Progressing,
@@ -34,6 +34,13 @@ import {
3434
TYPE_3_CHARACTERS_TO_SEE_MATCHING_RESULTS,
3535
TYPE_TO_SEE_MATCHING_RESULTS,
3636
SourceTypeMap,
37+
Button,
38+
ButtonStyleType,
39+
ButtonVariantType,
40+
ComponentSizeType,
41+
Icon,
42+
IconsProps,
43+
ButtonComponentType,
3744
} from '@devtron-labs/devtron-fe-common-lib'
3845
import { RouteComponentProps, Link } from 'react-router-dom'
3946
import { components } from 'react-select'
@@ -59,98 +66,16 @@ import {
5966
import './notifications.scss'
6067
import { getAppListMin, getEnvironmentListMin } from '../../services/service'
6168
import { SMTPConfigModal } from './SMTPConfigModal'
62-
import { EMAIL_AGENT } from './types'
69+
import {
70+
AddNotificationsProps,
71+
AddNotificationState,
72+
EMAIL_AGENT,
73+
FilterOptions,
74+
NotificationEventsType,
75+
} from './types'
6376
import { WebhookConfigModal } from './WebhookConfigModal'
6477
import { getClusterListMin } from '@Components/ClusterNodes/clusterNodes.service'
65-
66-
interface AddNotificationsProps extends RouteComponentProps<{}> {}
67-
68-
export enum FilterOptions {
69-
ENVIRONMENT = 'environment',
70-
APPLICATION = 'application',
71-
PROJECT = 'project',
72-
CLUSTER = 'cluster',
73-
}
74-
interface Options {
75-
environment: {
76-
value: number
77-
label: string
78-
type: string
79-
}[]
80-
application: {
81-
value: number
82-
label: string
83-
type: string
84-
}[]
85-
project: {
86-
value: number
87-
label: string
88-
type: string
89-
}[]
90-
cluster: {
91-
value: number
92-
label: string
93-
type: string
94-
}[]
95-
}
96-
export interface PipelineType {
97-
checkbox: {
98-
isChecked: boolean
99-
value: 'CHECKED' | 'INTERMEDIATE'
100-
}
101-
type: 'CI' | 'CD'
102-
pipelineId: number
103-
pipelineName: string
104-
environmentName?: string
105-
branch?: string
106-
appName: string
107-
success: boolean
108-
trigger: boolean
109-
failure: boolean
110-
appliedFilters: Array<{ type: string; value: number | string | undefined; name: string; label: string | undefined }>
111-
isVirtualEnvironment?: boolean
112-
}
113-
114-
interface AddNotificationState {
115-
view: string
116-
showSlackConfigModal: boolean
117-
showSESConfigModal: boolean
118-
showSMTPConfigModal: boolean
119-
channelOptions: {
120-
__isNew__?: boolean
121-
label: string
122-
value
123-
data: { dest: 'slack' | 'ses' | 'smtp' | 'webhook' | ''; configId: number; recipient: string }
124-
}[]
125-
sesConfigOptions: {
126-
id: number
127-
configName: string
128-
dest: 'slack' | 'ses' | 'smtp' | 'webhook' | ''
129-
recipient: string
130-
}[]
131-
smtpConfigOptions: {
132-
id: number
133-
configName: string
134-
dest: 'slack' | 'ses' | 'smtp' | 'webhook' | ''
135-
recipient: string
136-
}[]
137-
isLoading: boolean
138-
appliedFilters: Array<{ type: string; value: number | string | undefined; label: string | undefined }>
139-
selectedChannels: {
140-
__isNew__?: boolean
141-
label: string
142-
value
143-
data: { dest: 'slack' | 'ses' | 'smtp' | 'webhook' | ''; configId: number; recipient: string }
144-
}[]
145-
openSelectPipeline: boolean
146-
pipelineList: PipelineType[]
147-
filterInput: string
148-
emailAgentConfigId: number
149-
options: Options
150-
isApplistLoading: boolean
151-
selectedEmailAgent: string
152-
showWebhookConfigModal: boolean
153-
}
78+
import { EVENT_ICONS, EVENTS } from './constants'
15479

15580
export class AddNotification extends Component<AddNotificationsProps, AddNotificationState> {
15681
filterOptionsMain = [
@@ -189,7 +114,6 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
189114
this.handleFilterInput = this.handleFilterInput.bind(this)
190115
this.selectFilterType = this.selectFilterType.bind(this)
191116
this.toggleSelectPipeline = this.toggleSelectPipeline.bind(this)
192-
this.handlePipelineEventType = this.handlePipelineEventType.bind(this)
193117
this.selectChannel = this.selectChannel.bind(this)
194118
this.handleFilterTag = this.handleFilterTag.bind(this)
195119
this.selectEmailAgentAccount = this.selectEmailAgentAccount.bind(this)
@@ -343,23 +267,38 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
343267
})
344268
}
345269

346-
handlePipelineEventType(pipelineIndex: number, stage: 'success' | 'trigger' | 'failure'): void {
270+
handlePipelineEventType = (
271+
pipelineIndex: number,
272+
stage: 'trigger' | 'success' | 'failure' | 'configApproval' | 'imageApproval',
273+
): void => {
347274
const state = { ...this.state }
348275
const pipeline = state.pipelineList[pipelineIndex]
349276
pipeline[stage] = !pipeline[stage]
350-
if (pipeline.success && pipeline.trigger && pipeline.failure) {
277+
if (
278+
pipeline.success &&
279+
pipeline.trigger &&
280+
pipeline.failure &&
281+
pipeline.configApproval &&
282+
pipeline.imageApproval
283+
) {
351284
pipeline.checkbox = {
352-
value: 'CHECKED',
285+
value: CHECKBOX_VALUE.CHECKED,
353286
isChecked: true,
354287
}
355-
} else if (pipeline.success || pipeline.trigger || pipeline.failure) {
288+
} else if (
289+
pipeline.success ||
290+
pipeline.trigger ||
291+
pipeline.failure ||
292+
pipeline.configApproval ||
293+
pipeline.imageApproval
294+
) {
356295
pipeline.checkbox = {
357-
value: 'INTERMEDIATE',
296+
value: CHECKBOX_VALUE.INTERMEDIATE,
358297
isChecked: true,
359298
}
360-
} else if (!(pipeline.success && pipeline.trigger && pipeline.failure)) {
299+
} else {
361300
pipeline.checkbox = {
362-
value: 'CHECKED',
301+
value: CHECKBOX_VALUE.CHECKED,
363302
isChecked: false,
364303
}
365304
}
@@ -371,10 +310,12 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
371310
const state = { ...this.state }
372311
const pipeline = state.pipelineList[pipelineIndex]
373312
pipeline.checkbox.isChecked = !pipeline.checkbox.isChecked
374-
pipeline.checkbox.value = pipeline.checkbox.isChecked ? 'CHECKED' : 'INTERMEDIATE'
313+
pipeline.checkbox.value = pipeline.checkbox.isChecked ? CHECKBOX_VALUE.CHECKED : CHECKBOX_VALUE.INTERMEDIATE
375314
pipeline.trigger = pipeline.checkbox.isChecked
376315
pipeline.success = pipeline.checkbox.isChecked
377316
pipeline.failure = pipeline.checkbox.isChecked
317+
pipeline.configApproval = pipeline.checkbox.isChecked
318+
pipeline.imageApproval = pipeline.checkbox.isChecked
378319
state.pipelineList[pipelineIndex] = pipeline
379320
this.setState(state)
380321
}
@@ -405,6 +346,10 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
405346
}
406347
}
407348

349+
handleBackClick = () => {
350+
this.props.history.push(`${URLS.APPLICATION_MANAGEMENT_CONFIGURATIONS_NOTIFICATIONS}/channels`)
351+
}
352+
408353
saveNotification(): void {
409354
const selectedPipelines = this.state.pipelineList.filter((p) => p.checkbox.isChecked)
410355
if (!selectedPipelines.length) {
@@ -448,7 +393,7 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
448393

449394
saveNotification(selectedPipelines, selectedChannels)
450395
.then(() => {
451-
this.props.history.push(`${URLS.APPLICATION_MANAGEMENT_CONFIGURATIONS_NOTIFICATIONS}/channels`)
396+
this.handleBackClick()
452397
ToastManager.showToast({
453398
variant: ToastVariantType.success,
454399
description: 'Saved Successfully',
@@ -813,52 +758,33 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
813758
)}
814759
{row.type === 'CD' ? row?.environmentName : ''}
815760
</td>
816-
<td className="pipeline-list__stages flexbox flex-justify">
817-
<Tippy className="default-tt" arrow placement="top" content="Trigger">
818-
<div>
819-
<Checkbox
820-
dataTestId={`trigger-notification-checkbox-${rowIndex}`}
821-
rootClassName="gray"
822-
isChecked={row.trigger}
823-
value={CHECKBOX_VALUE.CHECKED}
824-
onChange={(e) => {
825-
this.handlePipelineEventType(rowIndex, 'trigger')
826-
}}
827-
>
828-
<span />
829-
</Checkbox>
830-
</div>
831-
</Tippy>
832-
<Tippy className="default-tt" arrow placement="top" content="Success">
833-
<div>
834-
<Checkbox
835-
dataTestId={`success-notification-checkbox-${rowIndex}`}
836-
rootClassName="green"
837-
isChecked={row.success}
838-
value={CHECKBOX_VALUE.CHECKED}
839-
onChange={(e) => {
840-
this.handlePipelineEventType(rowIndex, 'success')
841-
}}
842-
>
843-
<span />
844-
</Checkbox>
845-
</div>
846-
</Tippy>
847-
<Tippy className="default-tt" arrow placement="top" content="Failure">
848-
<div>
849-
<Checkbox
850-
dataTestId={`failure-notification-checkbox-${rowIndex}`}
851-
rootClassName="red"
852-
isChecked={row.failure}
853-
value={CHECKBOX_VALUE.CHECKED}
854-
onChange={(e) => {
855-
this.handlePipelineEventType(rowIndex, 'failure')
761+
<td className="pipeline-list__stages flexbox flex-justify dc__gap-12">
762+
{Object.values(EVENTS).map((event) => {
763+
return (
764+
<Button
765+
key={event}
766+
icon={
767+
<Icon
768+
name={EVENT_ICONS[event] as IconsProps['name']}
769+
color={null}
770+
/>
771+
}
772+
variant={
773+
row[event]
774+
? ButtonVariantType.primary
775+
: ButtonVariantType.borderLess
776+
}
777+
style={row[event] ? ButtonStyleType.default : ButtonStyleType.neutral}
778+
size={ComponentSizeType.xs}
779+
onClick={() => {
780+
this.handlePipelineEventType(rowIndex, event)
856781
}}
857-
>
858-
<span />
859-
</Checkbox>
860-
</div>
861-
</Tippy>
782+
ariaLabel={event}
783+
showAriaLabelInTippy={false}
784+
dataTestId={`${event}-notification-checkbox-${rowIndex}`}
785+
/>
786+
)
787+
})}
862788
</td>
863789
</tr>
864790
)
@@ -936,7 +862,6 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
936862
</div>
937863
)
938864
}
939-
940865
renderAddCard() {
941866
return (
942867
<div className="white-card white-card--no-padding dc__mxw-1000">
@@ -949,26 +874,23 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
949874
</div>
950875
{this.renderPipelineList()}
951876
</div>
952-
<div className="form__button-group-bottom flex right">
953-
<Link
954-
to={`${URLS.APPLICATION_MANAGEMENT_CONFIGURATIONS_NOTIFICATIONS}/channels`}
955-
className="cta cancel mr-16 dc__no-decor"
956-
tabIndex={8}
957-
>
958-
Cancel
959-
</Link>
960-
<button
961-
data-testid="add-notification-save-button"
962-
type="submit"
963-
className="cta"
964-
tabIndex={7}
965-
disabled={this.state.isLoading}
966-
onClick={(event) => {
967-
this.saveNotification()
877+
<div className="form__button-group-bottom flex right dc__gap-16">
878+
<Button
879+
dataTestId="cancel-add-notification"
880+
text="Cancel"
881+
variant={ButtonVariantType.secondary}
882+
style={ButtonStyleType.neutral}
883+
component={ButtonComponentType.link}
884+
linkProps={{
885+
to: URLS.APPLICATION_MANAGEMENT_CONFIGURATIONS_NOTIFICATIONS,
968886
}}
969-
>
970-
{this.state.isLoading ? <Progressing /> : 'Save'}
971-
</button>
887+
/>
888+
<Button
889+
dataTestId="add-notification-save-button"
890+
text="Save"
891+
style={ButtonStyleType.default}
892+
onClick={this.saveNotification}
893+
/>
972894
</div>
973895
</div>
974896
)
@@ -1070,7 +992,23 @@ export class AddNotification extends Component<AddNotificationsProps, AddNotific
1070992
return (
1071993
<ErrorBoundary>
1072994
<div className="flexbox-col bg__primary h-100 dc__gap-24 px-20 py-16">
1073-
<div data-testid="add-notifications-heading-title" className="form__title mb-16">
995+
<div
996+
data-testid="add-notifications-heading-title"
997+
className="form__title mb-16 flex left dc__gap-12"
998+
>
999+
<Button
1000+
dataTestId="back-to-notifications"
1001+
icon={<Icon name="ic-arrow-right" color={null} rotateBy={180} />}
1002+
component={ButtonComponentType.link}
1003+
linkProps={{
1004+
to: URLS.APPLICATION_MANAGEMENT_CONFIGURATIONS_NOTIFICATIONS,
1005+
}}
1006+
ariaLabel="Back to notifications"
1007+
showAriaLabelInTippy={false}
1008+
variant={ButtonVariantType.borderLess}
1009+
style={ButtonStyleType.neutral}
1010+
size={ComponentSizeType.small}
1011+
/>
10741012
Add Notifications
10751013
</div>
10761014
{this.renderAddCard()}

0 commit comments

Comments
 (0)