+
+
+
- renderWebhookModal = () => {
- if (this.state.view === ViewType.LOADING) {
- return (
-
- )
- }
- return (
- <>
-
-
-
-
-
-
- {this.renderHeadersList()}
-
-
-
- {this.renderConfigureLinkInfoColumn()}
-
-
-
-
-
+
+
Data to be shared through webhook
+
+
+ {isFormValid[ConfigurationFieldKeys.PAYLOAD].message && (
+
+
+ {isFormValid[ConfigurationFieldKeys.PAYLOAD].message}
+
+ )}
- >
- )
- }
+
+ {renderConfigureLinkInfoColumn()}
+
+ )
- render() {
- return this.renderWithBackdrop(this.renderWebhookModal())
- }
+ return (
+
+ )
}
diff --git a/src/components/notifications/WebhookConfigurationTable.tsx b/src/components/notifications/WebhookConfigurationTable.tsx
index 7a7ad7a595..26ce598ba9 100644
--- a/src/components/notifications/WebhookConfigurationTable.tsx
+++ b/src/components/notifications/WebhookConfigurationTable.tsx
@@ -1,94 +1,68 @@
-import { Trash } from '@Components/common'
import { DeleteComponentsName } from '@Config/constantMessaging'
-import { ViewType } from '@Config/constants'
-import { Progressing } from '@devtron-labs/devtron-fe-common-lib'
-import Tippy from '@tippyjs/react'
-import { ReactComponent as Edit } from '@Icons/ic-edit.svg'
+import { noop, useSearchString } from '@devtron-labs/devtron-fe-common-lib'
+import { useHistory } from 'react-router-dom'
import { ConfigurationTableProps } from './types'
import { EmptyConfigurationView } from './EmptyConfigurationView'
import { ConfigurationsTabTypes } from './constants'
+import { ConfigTableRowActionButton } from './ConfigTableRowActionButton'
+import { getConfigTabIcons, renderText } from './notifications.util'
+import webhookEmpty from '../../assets/img/webhook-empty.png'
+
+export const WebhookConfigurationTable = ({ state, deleteClickHandler }: ConfigurationTableProps) => {
+ const { webhookConfigurationList } = state
+ const { searchParams } = useSearchString()
+ const history = useHistory()
-export const WebhookConfigurationTable = ({ setState, state, deleteClickHandler }: ConfigurationTableProps) => {
- const { view, webhookConfigurationList } = state
- if (view === ViewType.LOADING) {
- return (
-
- )
- }
if (webhookConfigurationList.length === 0) {
- return
+ return
}
- const editWebhookHandler = (e) => {
- setState({ ...state, showWebhookConfigModal: true, webhookConfigId: e.currentTarget.dataset.webhookid })
+ const onClickWebhookConfigEdit = (id: number) => () => {
+ const newParams = {
+ ...searchParams,
+ configId: id.toString(),
+ modal: ConfigurationsTabTypes.WEBHOOK,
+ }
+ history.push({
+ search: new URLSearchParams(newParams).toString(),
+ })
}
return (
-
-
-
- Name |
- Webhook URL |
- |
-
-
-
-
- {webhookConfigurationList.map((webhookConfig) => (
-
-
- {webhookConfig.name}
-
-
- {webhookConfig.webhookUrl}
-
-
-
-
-
-
-
-
-
- |
- ))}
-
-
-
+
+
+
+
Name
+
Webhook URL
+
+
+
+ {webhookConfigurationList.map((webhookConfig) => (
+
+ {getConfigTabIcons(ConfigurationsTabTypes.WEBHOOK)}
+ {renderText(
+ webhookConfig.name,
+ true,
+ onClickWebhookConfigEdit(webhookConfig.id),
+ `webhook-config-name-${webhookConfig.name}`,
+ )}
+ {renderText(webhookConfig.name, false, noop, `webhook-url-${webhookConfig.webhookUrl}`)}
+
+
+ ))}
+
+
)
}
diff --git a/src/components/notifications/constants.ts b/src/components/notifications/constants.ts
index f2080c492c..f5b1481daf 100644
--- a/src/components/notifications/constants.ts
+++ b/src/components/notifications/constants.ts
@@ -1,3 +1,7 @@
+// ------------ Configuration Constants ------------
+
+import { SlackFormType } from './types'
+
export enum ConfigurationsTabTypes {
SES = 'ses',
SMTP = 'smtp',
@@ -5,6 +9,13 @@ export enum ConfigurationsTabTypes {
WEBHOOK = 'webhook',
}
+export const ConfigurationTabText = {
+ SES: 'Email (SES)',
+ SMTP: 'Email (SMTP)',
+ SLACK: 'Slack',
+ WEBHOOK: 'Webhook',
+}
+
export const EmptyConfigurationSubTitle = {
[ConfigurationsTabTypes.SES]:
'SES configuration will be used to send email notifications to the desired email address',
@@ -14,9 +25,84 @@ export const EmptyConfigurationSubTitle = {
[ConfigurationsTabTypes.WEBHOOK]: 'Configure webhook to send event data to external tools',
}
-export const ConfigurationTabText = {
- SES: 'Email (SES)',
- SMTP: 'Email (SMTP)',
- SLACK: 'Slack',
- WEBHOOK: 'Webhook',
+export enum ConfigurationFieldKeys {
+ CONFIG_NAME = 'configName',
+ ACCESS_KEY = 'accessKey',
+ SECRET_KEY = 'secretKey',
+ REGION = 'region',
+ FROM_EMAIL = 'fromEmail',
+ PROJECT_ID = 'projectId',
+ WEBHOOK_URL = 'webhookUrl',
+ CONFIG_ID = 'configId',
+ HOST = 'host',
+ PORT = 'port',
+ AUTH_USER = 'authUser',
+ AUTH_PASSWORD = 'authPassword',
+ DEFAULT = 'default',
+ PAYLOAD = 'payload',
+}
+
+// ------------ SES Configuration Constants ------------
+
+export const ConfigValidationKeys = { isValid: true, message: '' }
+
+export const DefaultSESValidations = {
+ [ConfigurationFieldKeys.CONFIG_NAME]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.ACCESS_KEY]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.SECRET_KEY]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.REGION]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.FROM_EMAIL]: ConfigValidationKeys,
}
+
+export const SESSortableHeaderTitle = {
+ CONFIG_NAME: 'Name',
+ ACCESS_KEY: 'Access Key Id',
+ EMAIL: "Sender's Email",
+}
+
+// ------------ SMTP Configuration Constants ------------
+
+export const DefaultSMTPValidation = {
+ [ConfigurationFieldKeys.CONFIG_NAME]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.HOST]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.PORT]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.AUTH_USER]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.AUTH_PASSWORD]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.FROM_EMAIL]: ConfigValidationKeys,
+}
+
+// ------------ Slack Configuration Constants ------------
+
+export const DefaultSlackKeys: SlackFormType = {
+ [ConfigurationFieldKeys.PROJECT_ID]: 0,
+ [ConfigurationFieldKeys.CONFIG_NAME]: '',
+ [ConfigurationFieldKeys.WEBHOOK_URL]: '',
+ isLoading: false,
+ id: null,
+}
+
+export const DefaultSlackValidations = {
+ [ConfigurationFieldKeys.PROJECT_ID]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.CONFIG_NAME]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.WEBHOOK_URL]: ConfigValidationKeys,
+}
+
+// ------------ Webhook Configuration Constants ------------
+
+export const DefaultHeaders = { key: '', value: '' }
+
+export const DefaultWebhookConfig = {
+ [ConfigurationFieldKeys.CONFIG_NAME]: '',
+ [ConfigurationFieldKeys.WEBHOOK_URL]: '',
+ [ConfigurationFieldKeys.PAYLOAD]: '',
+ isLoading: false,
+ header: [DefaultHeaders],
+}
+
+export const DefaultWebhookValidations = {
+ [ConfigurationFieldKeys.CONFIG_NAME]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.WEBHOOK_URL]: ConfigValidationKeys,
+ [ConfigurationFieldKeys.PAYLOAD]: ConfigValidationKeys,
+}
+
+export const SlackIncomingWebhookUrl = 'https://slack.com/marketplace/A0F7XDUAZ-incoming-webhooks'
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 4e89fd7031..2c1fb07120 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -122,17 +122,6 @@
box-shadow: 0 -1px 0 0 var(--N200);
}
-.configuration-tab__header {
- display: flex;
- justify-content: space-between;
- padding: 18px 24px;
-}
-
-.configuration-tab__title {
- font-size: 14px;
- font-weight: 600;
- margin: 0px;
-}
.white-card--configuration-tab {
overflow-y: auto;
@@ -141,92 +130,71 @@
height: 100%;
}
-.configuration-tab {
- display: grid;
- grid-template-rows: 1fr 1fr 1fr 1fr;
- padding: 16px 24px;
- grid-gap: 16px;
- height: calc(100vh - 220px);
-}
-
-.configuration-tab__table-row {
- display: flex;
- font-size: 14px;
- font-weight: normal;
- line-height: 1.43;
- letter-spacing: normal;
- color: var(--N600);
- align-items: center;
- padding: 10px 24px;
- height: 48px;
- cursor: default;
- box-shadow: inset 0 -1px 0 0 var(--N100);
- &:hover {
- background-color: var(--window-bg);
+.configuration-drawer{
+ .webhook-config-modal{
+ display: grid;
+ grid-template-columns: 1fr 280px;
}
}
+// --------------Configuration Tab----------------
+.configuration-tab__container {
+ .configuration-tab__table-row {
+ display: flex;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 1.43;
+ letter-spacing: normal;
+ color: var(--N900);
+ align-items: center;
+ padding: 10px 20px;
+ height: 48px;
+ }
-.configuration-tab__table-header {
- display: flex;
- font-size: 12px;
- font-weight: 600;
- line-height: 1.5;
- letter-spacing: normal;
- color: var(--N500);
- text-transform: uppercase;
- align-items: center;
- padding: 9px 24px;
- cursor: default;
- box-shadow: 0 1px 0 0 var(--N200);
-}
-
-.ses-config-table__name {
- flex-basis: 25%;
- color: var(--N900);
- font-weight: inherit;
-}
-
-.ses-config-table__access-key {
- flex-basis: 20%;
- font-weight: inherit;
-}
-
-.ses-config-table__email {
- flex-basis: 40%;
- font-weight: inherit;
-}
+ .ses-config-container {
+ .ses-config-grid {
+ display: grid;
+ grid-template-columns: 24px 250px 1fr 1fr 52px;
+ }
+ }
-.smtp-config-table__host {
- flex-basis: 33%;
- font-weight: inherit;
-}
+ .slack-config-container {
+ .slack-config-grid {
+ display: grid;
+ grid-template-columns: 24px 250px 1fr 52px;
+ }
+ }
-.smtp-config-table__port {
- flex-basis: 5%;
- font-weight: inherit;
-}
+ .smtp-config-container {
+ .smtp-config-grid {
+ display: grid;
+ grid-template-columns: 24px 250px 1fr 60px 1fr 52px;
+ }
+ }
-.smtp-config-table__email {
- flex-basis: 30%;
- font-weight: inherit;
-}
+ .webhook-config-container {
+ .webhook-config-grid {
+ display: grid;
+ grid-template-columns: 24px 250px 1fr 52px;
+ }
+ }
-.slack-config-table__name {
- flex-basis: 25%;
- color: var(--N900);
- font-weight: inherit;
-}
+ .configuration-tab__table-row:hover .slack-config-table__action,
+ .configuration-tab__table-row:hover .ses-config-table__action,
+ .configuration-tab__table-row:hover .webhook-config-table__action,
+ .configuration-tab__table-row:hover .smtp-config-table__action {
+ display: flex;
+ }
-.slack-config-table__webhook {
- flex-basis: 60%;
-}
+ .slack-config-table__action,
+ .ses-config-table__action,
+ .webhook-config-table__action,
+ .smtp-config-table__action {
+ display: none;
+ margin: auto;
+ margin-right: 0;
+ }
-.slack-config-table__action,
-.ses-config-table__action {
- display: none;
- margin: auto;
- margin-right: 0;
}
.form__row--ses-account {
@@ -234,12 +202,6 @@
min-width: 300px;
}
-.configuration-tab__table-row:hover .slack-config-table__action,
-.configuration-tab__table-row:hover .ses-config-table__action {
- display: flex;
- background-color: var(--window-bg);
-}
-
.kebab-menu__list--notification-tab {
width: 216px;
}
@@ -384,7 +346,7 @@
}
}
-.data-conatiner {
+.data-container {
.hover-only {
display: none;
}
@@ -404,12 +366,4 @@
}
}
}
-}
-
-.empty-state-height {
- height: 'calc(100% - 70px)';
-}
-
-.progressing-loader-height {
- height: 'calc(100% - 68px)';
-}
+}
\ No newline at end of file
diff --git a/src/components/notifications/notifications.util.tsx b/src/components/notifications/notifications.util.tsx
index 9ebd66f7eb..e59f6b3ef0 100644
--- a/src/components/notifications/notifications.util.tsx
+++ b/src/components/notifications/notifications.util.tsx
@@ -15,7 +15,6 @@
*/
import { components } from 'react-select'
-import { validateEmail } from '../common'
import { ReactComponent as ArrowDown } from '@Icons/ic-chevron-down.svg'
import { ReactComponent as Email } from '@Icons/ic-mail.svg'
import { ReactComponent as RedWarning } from '@Icons/ic-error-medium.svg'
@@ -26,7 +25,19 @@ import { ReactComponent as Slack } from '@Icons/slack-logo.svg'
import { ReactComponent as SES } from '@Icons/ic-aws-ses.svg'
import { ReactComponent as Webhook } from '@Icons/ic-CIWebhook.svg'
import { ReactComponent as SMTP } from '@Icons/ic-smtp.svg'
-import { ConfigurationsTabTypes, ConfigurationTabText } from './constants'
+import {
+ DynamicDataTableHeaderType,
+ DynamicDataTableRowDataType,
+ DynamicDataTableRowType,
+ getUniqueId,
+ ToastManager,
+ ToastVariantType,
+ Tooltip,
+} from '@devtron-labs/devtron-fe-common-lib'
+import { ConfigurationFieldKeys, ConfigurationsTabTypes, ConfigurationTabText } from './constants'
+import { validateEmail } from '../common'
+import { FormError, FormValidation, SESFormType, SMTPFormType, WebhookDataRowType, WebhookHeaderKeyType, WebhookRowCellType } from './types'
+import { REQUIRED_FIELD_MSG } from '@Config/constantMessaging'
export const multiSelectStyles = {
control: (base, state) => ({
@@ -39,60 +50,48 @@ export const multiSelectStyles = {
...base,
top: `38px`,
}),
- option: (base, state) => {
- return {
- ...base,
- color: 'var(--N900)',
- display: `flex`,
- alignItems: `center`,
- fontSize: '12px',
- padding: '8px 24px',
- }
- },
- multiValue: (base, state) => {
- return {
- ...base,
- border:
- state.data.data.dest !== 'slack' &&
- state.data.data.dest !== 'webhook' &&
- !validateEmail(state.data.label)
- ? `1px solid var(--R500)`
- : `1px solid var(--N200)`,
- borderRadius: `4px`,
- background:
- state.data.data.dest !== 'slack' &&
- state.data.data.dest !== 'webhook' &&
- !validateEmail(state.data.label)
- ? 'var(--R100)'
- : 'var(--N000)',
- padding: `2px`,
- textTransform: `lowercase`,
- fontSize: `12px`,
- lineHeight: `1.5`,
- letterSpacing: `normal`,
- color: `var(--N900)`,
- userSelect: `none`,
- display: `inline-flex`,
- }
- },
- multiValueLabel: (base, state) => {
- return {
- ...base,
- display: `flex`,
- alignItems: `center`,
- fontSize: '12px',
- padding: '0px',
- }
- },
+ option: (base, state) => ({
+ ...base,
+ color: 'var(--N900)',
+ display: `flex`,
+ alignItems: `center`,
+ fontSize: '12px',
+ padding: '8px 24px',
+ }),
+ multiValue: (base, state) => ({
+ ...base,
+ border:
+ state.data.data.dest !== 'slack' && state.data.data.dest !== 'webhook' && !validateEmail(state.data.label)
+ ? `1px solid var(--R500)`
+ : `1px solid var(--N200)`,
+ borderRadius: `4px`,
+ background:
+ state.data.data.dest !== 'slack' && state.data.data.dest !== 'webhook' && !validateEmail(state.data.label)
+ ? 'var(--R100)'
+ : 'var(--N000)',
+ padding: `2px`,
+ textTransform: `lowercase`,
+ fontSize: `12px`,
+ lineHeight: `1.5`,
+ letterSpacing: `normal`,
+ color: `var(--N900)`,
+ userSelect: `none`,
+ display: `inline-flex`,
+ }),
+ multiValueLabel: (base, state) => ({
+ ...base,
+ display: `flex`,
+ alignItems: `center`,
+ fontSize: '12px',
+ padding: '0px',
+ }),
}
-export const DropdownIndicator = (props) => {
- return (
-
-
-
- )
-}
+export const DropdownIndicator = (props) => (
+
+
+
+)
export const MultiValueLabel = (props) => {
const item = props.data
@@ -164,25 +163,198 @@ export const renderPipelineTypeIcon = (row) => {
return
}
+export const getConfigTabIcons = (tab: ConfigurationsTabTypes, size: number = 24) => {
+ switch (tab) {
+ case ConfigurationsTabTypes.SES:
+ return
+ case ConfigurationsTabTypes.SMTP:
+ return
+ case ConfigurationsTabTypes.SLACK:
+ return
+ case ConfigurationsTabTypes.WEBHOOK:
+ return
+ default:
+ return SES
+ }
+}
+
export const getConfigurationTabTextWithIcon = () => [
{
label: ConfigurationTabText.SES,
- icon: SES,
+ icon: getConfigTabIcons(ConfigurationsTabTypes.SES, 20),
link: ConfigurationsTabTypes.SES,
},
{
label: ConfigurationTabText.SMTP,
- icon: SMTP,
+ icon: getConfigTabIcons(ConfigurationsTabTypes.SMTP, 20),
link: ConfigurationsTabTypes.SMTP,
},
{
label: ConfigurationTabText.SLACK,
- icon: Slack,
+ icon: getConfigTabIcons(ConfigurationsTabTypes.SLACK, 20),
link: ConfigurationsTabTypes.SLACK,
},
{
label: ConfigurationTabText.WEBHOOK,
- icon: Webhook,
+ icon: getConfigTabIcons(ConfigurationsTabTypes.WEBHOOK, 20),
link: ConfigurationsTabTypes.WEBHOOK,
},
]
+
+export const getSESDefaultConfiguration = (shouldBeDefault: boolean): SESFormType => ({
+ configName: '',
+ accessKey: '',
+ secretKey: '',
+ region: null,
+ fromEmail: '',
+ default: shouldBeDefault,
+ isLoading: false,
+})
+
+export const getSMTPDefaultConfiguration = (shouldBeDefault: boolean): SMTPFormType => ({
+ configName: '',
+ host: '',
+ port: '',
+ authUser: '',
+ authPassword: '',
+ fromEmail: '',
+ default: shouldBeDefault,
+ isLoading: false,
+})
+
+export const renderText = (text: string, isLink: boolean = false, linkTo?: () => void, dataTestId?: string) => (
+
+ {isLink ? (
+
+ ) : (
+
+ {text || '-'}
+
+ )}
+
+)
+
+export const renderDefaultTag = (isDefault: boolean) => {
+ if (isDefault) {
+ return
Default
+ }
+ return null
+}
+
+export const getTableHeaders = (): DynamicDataTableHeaderType
[] => [
+ { label: 'Header key', key: 'key', width: '300px' },
+ { label: 'Value', key: 'value', width: '1fr' },
+]
+
+export const getInitialWebhookKeyRow = (rows: WebhookRowCellType[]): DynamicDataTableRowType[] =>
+ rows.map((row) => {
+ return {
+ data: {
+ key: {
+ value: row.key || null,
+ type: DynamicDataTableRowDataType.TEXT,
+ props: {
+ placeholder: 'Eg. owner-name',
+ },
+ },
+ value: {
+ value: row.value || '',
+ type: DynamicDataTableRowDataType.TEXT,
+ props: {
+ placeholder: 'Enter value',
+ },
+ },
+ },
+ id: row.id,
+ }
+ })
+
+export const getEmptyVariableDataRow = (): WebhookDataRowType => {
+ const id = getUniqueId()
+ return {
+ data: {
+ key: {
+ value: '',
+ type: DynamicDataTableRowDataType.TEXT,
+ props: {
+ placeholder: 'Eg. owner-name',
+ },
+ },
+ value: {
+ value: '',
+ type: DynamicDataTableRowDataType.TEXT,
+ props: {
+ placeholder: 'Enter value',
+ },
+ },
+ },
+ id,
+ }
+}
+
+export const validateKeyValueConfig = (key: ConfigurationFieldKeys, value: string): FormError => {
+ if (!value) {
+ return { isValid: false, message: REQUIRED_FIELD_MSG }
+ }
+ if (key === ConfigurationFieldKeys.FROM_EMAIL) {
+ return { isValid: validateEmail(value), message: validateEmail(value) ? '' : 'Invalid email' }
+ }
+ return { isValid: true, message: '' }
+}
+
+export const getFormValidated = (isFormValid: FormValidation, fromEmail?: string): boolean => {
+ const isKeysValid = Object.values(isFormValid).every((field) => field.isValid && !field.message)
+ if (fromEmail) {
+ return isKeysValid && validateEmail(fromEmail)
+ }
+ return isKeysValid
+}
+export enum ConfigTableRowActionType {
+ ADD_ROW = 'ADD_ROW',
+ UPDATE_ROW = 'UPDATE_ROW',
+ DELETE_ROW = 'DELETE_ROW',
+}
+
+export const getTabText = (tab: ConfigurationsTabTypes) => {
+ switch (tab) {
+ case ConfigurationsTabTypes.SES:
+ return 'SES'
+ case ConfigurationsTabTypes.SLACK:
+ return 'Slack'
+ case ConfigurationsTabTypes.WEBHOOK:
+ return 'Webhook'
+ case ConfigurationsTabTypes.SMTP:
+ return 'SMTP'
+ default:
+ return ''
+ }
+}
+
+export const validatePayloadField = (value: string): FormError => {
+ let isValid = true
+ let errorMessage = ''
+ // Validate if the value is a valid JSON string
+ if (!value) {
+ return { isValid: false, message: REQUIRED_FIELD_MSG }
+ }
+ try {
+ JSON.parse(value)
+ } catch {
+ isValid = false
+ errorMessage = 'Invalid JSON format.'
+ }
+ return { isValid, message: errorMessage }
+}
+
+export const renderErrorToast = () =>
+ ToastManager.showToast({
+ variant: ToastVariantType.error,
+ description: 'Some required fields are missing or Invalid',
+ })
diff --git a/src/components/notifications/types.tsx b/src/components/notifications/types.tsx
index fa62cc55b9..2e9eb0837f 100644
--- a/src/components/notifications/types.tsx
+++ b/src/components/notifications/types.tsx
@@ -15,8 +15,14 @@
*/
import { RouteComponentProps } from 'react-router-dom'
-import { ServerError, ResponseType } from '@devtron-labs/devtron-fe-common-lib'
-import { ConfigurationsTabTypes } from './constants'
+import {
+ ServerError,
+ ResponseType,
+ DynamicDataTableRowType,
+ SelectPickerOptionType,
+} from '@devtron-labs/devtron-fe-common-lib'
+import { VariableDataTableActionType } from '@Components/CIPipelineN/VariableDataTable/types'
+import { ConfigurationFieldKeys, ConfigurationsTabTypes } from './constants'
export interface NotifierProps extends RouteComponentProps<{ id: string }> {}
@@ -26,6 +32,7 @@ export interface NotifierState {
successMessage: string | null
channel: string
}
+
export interface SMTPConfigResponseType extends ResponseType {
result?: {
configName: string
@@ -48,41 +55,13 @@ export interface SMTPConfigModalProps {
shouldBeDefault: boolean
selectSMTPFromChild?: (smtpConfigId: number) => void
onSaveSuccess: () => void
- closeSMTPConfigModal: (event) => void
+ closeSMTPConfigModal?: () => void
}
-export interface SMTPConfigModalState {
- view: string
- form: {
- configName: string
- port: number
- host: string
- authUser: string
- authPassword: string
- fromEmail: string
- default: boolean
- isLoading: boolean
- isError: boolean
- }
- isValid: {
- configName: boolean
- port: boolean
- host: boolean
- authUser: boolean
- authPassword: boolean
- fromEmail: boolean
- }
-}
+// ----------------------------Configuration Tab Types----------------------------
export interface ConfigurationTabState {
- view: string
- showSlackConfigModal: boolean
- showSESConfigModal: boolean
- showSMTPConfigModal: boolean
- slackConfigId: number
- sesConfigId: number
- smtpConfigId: number
- webhookConfigId: number
+ isLoading: boolean
sesConfigurationList: Array<{ id: number; name: string; accessKeyId: string; email: string; isDefault: boolean }>
smtpConfigurationList: Array<{
id: number
@@ -95,70 +74,174 @@ export interface ConfigurationTabState {
slackConfigurationList: Array<{ id: number; slackChannel: string; projectId: number; webhookUrl: string }>
webhookConfigurationList: Array<{ id: number; name: string; webhookUrl: string }>
abortAPI: boolean
- deleting: boolean
confirmation: boolean
sesConfig: any
smtpConfig: any
slackConfig: any
webhookConfig: any
- showDeleteConfigModalType: string
- showWebhookConfigModal: boolean
activeTab?: ConfigurationsTabTypes
+ showCannotDeleteDialogModal: boolean
}
export interface ConfigurationTableProps {
- setState: React.Dispatch>
state: ConfigurationTabState
deleteClickHandler: (id: number, name: string) => void
}
+export interface FormError {
+ isValid: boolean
+ message: string
+}
+
+export interface ConfigurationTabDrawerModalProps {
+ renderContent: () => JSX.Element
+ closeModal: () => void
+ modal: ConfigurationsTabTypes
+ isLoading: boolean
+ saveConfigModal: () => void
+ disableSave?: boolean
+}
+
+export type FormValidation = {
+ [key: string]: FormError
+}
+
+export interface DefaultCheckboxProps {
+ shouldBeDefault: boolean
+ handleCheckbox: () => void
+ isDefault: boolean
+}
+
+// ----------------------------Configuration Tab----------------------------
+
+export interface EmptyConfigurationViewProps {
+ configTabType: ConfigurationsTabTypes
+ image?: any
+}
+
+export interface ConfigurationTabSwitcherProps {
+ activeTab: ConfigurationsTabTypes
+}
+
+export interface ConfigTableRowActionButtonProps {
+ onClickEditRow: () => void
+ onClickDeleteRow: any
+ rootClassName: string
+ modal: ConfigurationsTabTypes
+}
+
+// ----------------------------SES Config Modal----------------------------
+
+export interface SESConfigModalProps {
+ shouldBeDefault: boolean
+ selectSESFromChild?: (sesConfigId: number) => void
+ onSaveSuccess: () => void
+ closeSESConfigModal?: () => void
+ sesConfigId: number
+}
+
+export interface SESFormType {
+ configName: string
+ accessKey: string
+ secretKey: string
+ region: SelectPickerOptionType
+ default: boolean
+ isLoading: boolean
+ fromEmail: string
+}
+
+// ----------------------------Slack Config Modal----------------------------
+
+export interface ProjectListTypes {
+ id: number
+ name: string
+ active: boolean
+}
+
+export interface SlackConfigModalProps {
+ slackConfigId: number
+ onSaveSuccess: () => void
+ closeSlackConfigModal?: () => void
+}
+
+export interface SlackFormType {
+ configName: string
+ projectId: number
+ webhookUrl: string
+ isLoading: boolean
+ id: number | null
+}
+
+// ----------------------------SMTP Config Modal----------------------------
+export interface SMTPFormType {
+ configName: string
+ port: string
+ host: string
+ authUser: string
+ authPassword: string
+ fromEmail: string
+ default: boolean
+ isLoading: boolean
+}
+
+// ----------------------------Webhook Config Modal--------------------------------
+
+export interface WebhookAttributesResponseType extends ResponseType {
+ result?: Record
+}
+
export interface WebhookConfigModalProps {
webhookConfigId: number
+ closeWebhookConfigModal?: () => void
onSaveSuccess: () => void
- closeWebhookConfigModal: (event) => void
}
-export interface WebhhookConfigModalState {
- view: string
- form: {
- configName: string
- webhookUrl: string
- isLoading: boolean
- isError: boolean
- payload: string
- header: HeaderType[]
- }
- isValid: {
- configName: boolean
- webhookUrl: boolean
- payload: boolean
- }
- webhookAttribute: Record
- copyAttribute: boolean
-}
+export type WebhookHeaderKeyType = 'key' | 'value'
-export interface HeaderType {
+export type WebhookDataRowType = DynamicDataTableRowType
+
+export interface WebhookRowCellType {
key: string
value: string
+ id?: number
}
-export interface CreateHeaderDetailsType {
- index: number
- headerData: HeaderType
- setHeaderData: (index: number, headerData: HeaderType) => void
- removeHeader?: (index: number) => void
+export interface WebhookConfigDynamicDataTableProps {
+ rows: WebhookDataRowType[]
+ setRows: React.Dispatch>
+ headers: WebhookRowCellType[]
}
-export interface WebhookAttributesResponseType extends ResponseType {
- result?: Record
+type VariableDataTableActionPropsMap = {
+ [VariableDataTableActionType.UPDATE_ROW]: string
}
-export interface EmptyConfigurationViewProps {
- configTabType: ConfigurationsTabTypes
+export type VariableDataTableAction<
+ T extends keyof VariableDataTableActionPropsMap = keyof VariableDataTableActionPropsMap,
+> = T extends keyof VariableDataTableActionPropsMap
+ ? { actionType: T; actionValue: VariableDataTableActionPropsMap[T] }
+ : never
+
+export type HandleRowUpdateActionProps = VariableDataTableAction & {
+ headerKey: WebhookHeaderKeyType
+ rowId: string | number
}
-export interface ConfigurationTabSwitcherProps {
- activeTab: ConfigurationsTabTypes
- state: ConfigurationTabState
- setState: React.Dispatch>
+export type WebhookValidations = {
+ [ConfigurationFieldKeys.CONFIG_NAME]: FormError
+ [ConfigurationFieldKeys.WEBHOOK_URL]: FormError
+ [ConfigurationFieldKeys.PAYLOAD]: FormError
+}
+
+export interface HeaderType {
+ key: string
+ value: string
+}
+
+export interface WebhookFormTypes {
+ configName: string
+ webhookUrl: string
+ isLoading: boolean
+ payload: string
+ header: HeaderType[]
}
diff --git a/src/css/base.scss b/src/css/base.scss
index a1919100d4..67b3a64605 100644
--- a/src/css/base.scss
+++ b/src/css/base.scss
@@ -957,21 +957,6 @@ button.anchor {
background-color: var(--N000);
}
-.dc__ses_config-table__tag {
- border-radius: 2px;
- padding: 2px 8px;
- font-size: 11px;
- font-weight: 600;
- font-stretch: normal;
- line-height: 1.82;
- text-transform: uppercase;
- margin: 0 8px;
- color: var(--B500);
- border: solid 1px #b5d3f2;
- background-blend-mode: multiply;
- background-image: linear-gradient(to bottom, var(--B50), var(--B50));
-}
-
.dc__saved-filter__clear-btn--dark {
height: 36px;
background-color: var(--white);
@@ -3222,6 +3207,10 @@ textarea,
.w-160 {
width: 160px;
+
+ &--imp {
+ width: 160px !important;
+ }
}
.w-180 {
@@ -3458,6 +3447,10 @@ textarea,
// width fix content
.dc__w-fit-content {
width: fit-content;
+
+ &--imp {
+ width: fit-content !important;
+ }
}
.dc__width-inherit {
@@ -3469,6 +3462,15 @@ textarea,
height: inherit;
}
+.dc__height-auto {
+ height: auto;
+
+ &--imp {
+ height: auto !important;
+ }
+
+}
+
.dc__min-width-fit-content {
min-width: fit-content !important;
}
@@ -4383,6 +4385,10 @@ textarea::placeholder {
background-color: var(--N50);
}
+.dc__hover-text-n90:hover {
+ color: var(--N900) !important;
+}
+
.dc__bg-g5 {
background-color: var(--G500) !important;
}
@@ -5349,9 +5355,14 @@ details[open] {
background: inherit;
border: none;
padding: inherit;
- white-space: pre-wrap; /* Since CSS 2.1 */
- white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
- white-space: -pre-wrap; /* Opera 4-6 */
- white-space: -o-pre-wrap; /* Opera 7 */
- word-wrap: break-word; /* Internet Explorer 5.5+ */
-}
+ white-space: pre-wrap;
+ /* Since CSS 2.1 */
+ white-space: -moz-pre-wrap;
+ /* Mozilla, since 1999 */
+ white-space: -pre-wrap;
+ /* Opera 4-6 */
+ white-space: -o-pre-wrap;
+ /* Opera 7 */
+ word-wrap: break-word;
+ /* Internet Explorer 5.5+ */
+}
\ No newline at end of file