From 9b6dfec1b27a5a711e58ba8751ac1964232dab7f Mon Sep 17 00:00:00 2001 From: cgoodwin90 Date: Tue, 24 Oct 2023 13:14:55 +1100 Subject: [PATCH 01/11] Changed edit notification on projects to link to notifications page --- .../ProjectNotifications/index.js | 228 +----------------- .../link/Organizations/Notifications.js | 14 +- 2 files changed, 11 insertions(+), 231 deletions(-) diff --git a/src/components/Organizations/ProjectNotifications/index.js b/src/components/Organizations/ProjectNotifications/index.js index 0be5b179..f9e12eb5 100644 --- a/src/components/Organizations/ProjectNotifications/index.js +++ b/src/components/Organizations/ProjectNotifications/index.js @@ -2,21 +2,11 @@ import React, { useState } from 'react'; import { Mutation } from 'react-apollo'; import { EditOutlined } from '@ant-design/icons'; -import { useMutation } from '@apollo/react-hooks'; -import Button from 'components/Button'; -import Modal from 'components/Modal'; import RemoveProjectGroupConfirm from 'components/Organizations/RemoveProjectGroupConfirm'; import gql from 'graphql-tag'; - +import OrgNotificationsLink from 'components/link/Organizations/Notifications'; import AddNotificationToProject from '../AddNotificationToProject'; -import { - UPDATE_NOTIFICATION_EMAIL, - UPDATE_NOTIFICATION_ROCKETCHAT, - UPDATE_NOTIFICATION_SLACK, - UPDATE_NOTIFICATION_TEAMS, - UPDATE_NOTIFICATION_WEBHOOK, -} from '../Notifications'; -import { Footer, ModalChildren, TableActions } from '../SharedStyles'; +import { TableActions } from '../SharedStyles'; import { StyledProjectNotifications } from './Styles'; const REMOVE_NOTIFICATION_FROM_PROJECT = gql` @@ -44,165 +34,6 @@ const ProjectNotifications = ({ notifications = [], organizationId, projectName, return ['name', '__typename'].includes(key) ? false : true && sortByName; }); - const [notificationName, setNotificationName] = useState(''); - const [email, setEmail] = useState(''); - const [webhook, setWebhook] = useState(''); - const [channel, setChannel] = useState(''); - - const [updateSlack] = useMutation(UPDATE_NOTIFICATION_SLACK); - const [updateRocketChat] = useMutation(UPDATE_NOTIFICATION_ROCKETCHAT); - const [updateEmail] = useMutation(UPDATE_NOTIFICATION_EMAIL); - const [updateWebhook] = useMutation(UPDATE_NOTIFICATION_WEBHOOK); - const [updateTeams] = useMutation(UPDATE_NOTIFICATION_TEAMS); - - const [editModalState, setEditModalState] = useState({ - open: false, - current: { - name: '', - type: '', - }, - }); - - const closeModal = () => { - setEditModalState({ open: false, current: { name: '', type: '' } }); - resetState(); - }; - - const resetState = () => { - setNotificationName(''); - setEmail(''); - setWebhook(''); - setChannel(''); - }; - - const getAction = () => { - switch (editModalState?.current?.type) { - case 'SLACK': - return () => - updateSlack({ - variables: { - name: editModalState?.current?.name, - patch: { - ...(notificationName ? { name: notificationName } : {}), - ...(channel ? { channel } : {}), - ...(webhook ? { webhook } : {}), - }, - }, - }); - case 'ROCKETCHAT': - return () => - updateRocketChat({ - variables: { - name: editModalState?.current?.name, - patch: { - ...(notificationName ? { name: notificationName } : {}), - ...(channel ? { channel } : {}), - ...(webhook ? { webhook } : {}), - }, - }, - }); - case 'EMAIL': - return () => - updateEmail({ - variables: { - name: editModalState?.current?.name, - patch: { - ...(notificationName ? { name: notificationName } : {}), - ...(email ? { emailAddress: email } : {}), - }, - }, - }); - case 'MICROSOFTTEAMS': - return () => - updateTeams({ - variables: { - name: editModalState?.current?.name, - patch: { - ...(notificationName ? { name: notificationName } : {}), - ...(webhook ? { webhook } : {}), - }, - }, - }); - case 'WEBHOOK': - return () => - updateWebhook({ - variables: { - name: editModalState?.current?.name, - patch: { - ...(notificationName ? { name: notificationName } : {}), - ...(webhook ? { webhook } : {}), - }, - }, - }); - } - }; - - const renderFields = () => { - switch (editModalState?.current?.type) { - case 'EMAIL': - return ( -
- -
- ); - case 'SLACK': - case 'ROCKETCHAT': - return ( - <> -
- -
- -
- -
- - ); - case 'MICROSOFTTEAMS': - case 'WEBHOOK': - return ( -
- -
- ); - } - }; return (
@@ -237,21 +68,9 @@ const ProjectNotifications = ({ notifications = [], organizationId, projectName, } return ( - - setEditModalState({ - open: true, - current: { - name: notification.name, - type: notification.type, - }, - }) - } - > + - - + - - -
- -
- {renderFields()} -
- -
- - - -
-
({ +export const getLinkData = (organizationSlug) => ({ urlObject: { - pathname: '/organizations/notifications', - query: { organizationSlug: organizationSlug, organizationName: organizationName } + pathname: `/organizations/notifications`, + query: { organizationSlug: organizationSlug }, }, asPath: `/organizations/${organizationSlug}/notifications` }); @@ -13,12 +13,11 @@ export const getLinkData = (organizationSlug, organizationName) => ({ */ const OrgNotificationsLink = ({ organizationSlug, - organizationName, children, - className = '', - prefetch = false + className = null, + prefetch = false, }) => { - const linkData = getLinkData(organizationSlug, organizationName); + const linkData = getLinkData(organizationSlug); return ( {children} @@ -27,3 +26,4 @@ const OrgNotificationsLink = ({ }; export default OrgNotificationsLink; + From 441ff7f215bffcb5171df064299d8a2801b46d7f Mon Sep 17 00:00:00 2001 From: Davit Date: Wed, 8 Nov 2023 06:57:33 +0400 Subject: [PATCH 02/11] some recommended fixes/changes to organizations --- src/components/Header/StyledHeader.tsx | 13 ++- src/components/Header/index.js | 87 ++++++++++--------- .../HeaderMenu/StyledHeaderMenu.tsx | 4 +- src/components/HeaderMenu/index.js | 7 +- src/components/NewEnvironment/index.js | 2 +- .../Organizations/AddGroupToProject/index.js | 5 +- .../AddNotificationToProject/index.js | 5 +- .../Organizations/GroupMembers/index.js | 43 ++++++--- src/components/Organizations/Groups/index.js | 13 ++- src/components/Organizations/Manage/index.js | 11 ++- .../Organizations/NewGroup/index.js | 11 ++- .../Organizations/NewProject/index.js | 52 +++++++---- .../Notifications/AddNotifications.tsx | 2 +- .../Organizations/Notifications/Styles.tsx | 4 +- .../Organization/OrganizationSkeleton.tsx | 2 +- .../Organizations/Organization/index.js | 2 +- .../Organizations/PaginatedTable/Styles.tsx | 4 +- .../ProjectGroupMembers/Styles.tsx | 4 +- .../ProjectNotifications/Styles.tsx | 4 +- .../ProjectNotifications/index.js | 5 +- .../Organizations/Projects/Styles.tsx | 29 +++++-- .../Organizations/Projects/index.js | 31 ++++--- .../RemoveProjectGroupConfirm/index.js | 11 ++- .../Organizations/RemoveUserConfirm/index.js | 5 +- src/components/Organizations/SharedStyles.tsx | 8 +- src/styles/theme.ts | 2 + styled.d.ts | 1 + 27 files changed, 236 insertions(+), 131 deletions(-) diff --git a/src/components/Header/StyledHeader.tsx b/src/components/Header/StyledHeader.tsx index be1998b5..4ef0f7b9 100644 --- a/src/components/Header/StyledHeader.tsx +++ b/src/components/Header/StyledHeader.tsx @@ -1,10 +1,14 @@ import { color } from 'lib/variables'; import styled from 'styled-components'; -export const StyledHeader = styled.header` +export const StyledHeader = styled.header<{ isOrganizationsPath: boolean }>` background: ${color.brightBlue} ${color.lightBlue}; background: ${color.lightBlue}; - background: ${props => props.theme.gradients.headerFooterGradient}; + background: ${props => + props.isOrganizationsPath + ? props.theme.gradients.organizationsHeaderGradient + : props.theme.gradients.headerFooterGradient}; + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='${color.brightBlue}', endColorstr='${color.lightBlue}',GradientType=1 ); display: flex; justify-content: space-between; @@ -38,7 +42,10 @@ export const StyledHeader = styled.header` } &.navitem { align-items: center; - border-left: 1px solid ${color.blue}; + border-left: 1px solid ${props => + props.isOrganizationsPath + ? "transparent" + : color.blue}; cursor: pointer; display: flex; &::before { diff --git a/src/components/Header/index.js b/src/components/Header/index.js index 847e7c79..50619fcf 100644 --- a/src/components/Header/index.js +++ b/src/components/Header/index.js @@ -2,6 +2,7 @@ import React from 'react'; import getConfig from 'next/config'; import Link from 'next/link'; +import { useRouter } from 'next/router'; import lagoonLogo from '!svg-inline-loader?classPrefix!./lagoon.svg'; import HeaderMenu from 'components/HeaderMenu'; @@ -16,45 +17,53 @@ const { publicRuntimeConfig } = getConfig(); /** * Displays the header using the provided logo. */ -const Header = ({ logo }) => ( - - - - Home { + const { asPath } = useRouter(); + + const isOrganizationsPath = asPath.includes('/organizations'); + + console.log(isOrganizationsPath); + + return ( + + + + Home + + + + + + + + {auth => { + if (auth.authenticated) { + return ( +
+ + Deployments + + +
+ ); } - /> - - - - - - - - {auth => { - if (auth.authenticated) { - return ( -
- - Deployments - - -
- ); - } - - return null; - }} -
-
-); + + return null; + }} + + + ); +}; export default Header; diff --git a/src/components/HeaderMenu/StyledHeaderMenu.tsx b/src/components/HeaderMenu/StyledHeaderMenu.tsx index 436562f2..3912f110 100644 --- a/src/components/HeaderMenu/StyledHeaderMenu.tsx +++ b/src/components/HeaderMenu/StyledHeaderMenu.tsx @@ -25,8 +25,8 @@ export const DropdownButton = styled.a` } `; -export const StyledDropdown = styled.div` - border-left: 1px solid ${color.blue}; +export const StyledDropdown = styled.div<{ isOrganizationsPath: boolean }>` + border-left: 1px solid ${props => (props.isOrganizationsPath ? 'transparent' : color.blue)}; cursor: pointer; padding: 10px 20px; hr { diff --git a/src/components/HeaderMenu/index.js b/src/components/HeaderMenu/index.js index 6b27fae8..02e6b574 100644 --- a/src/components/HeaderMenu/index.js +++ b/src/components/HeaderMenu/index.js @@ -29,7 +29,7 @@ const useOutsideClick = callback => { return ref; }; -const HeaderMenu = ({ auth }) => { +const HeaderMenu = ({ auth, isOrganizationsPath }) => { const [open, setOpen] = React.useState(false); const handleClickOutside = () => { @@ -55,6 +55,7 @@ const HeaderMenu = ({ auth }) => { return ( <> @@ -96,10 +97,10 @@ const HeaderMenu = ({ auth }) => { ); }; -const Dropdown = ({ open, trigger, menu }) => { +const Dropdown = ({ open, trigger, menu, isOrganizationsPath }) => { return ( <> - + {trigger} {open ? ( diff --git a/src/components/NewEnvironment/index.js b/src/components/NewEnvironment/index.js index 0d4b07d4..1bcbdcf5 100644 --- a/src/components/NewEnvironment/index.js +++ b/src/components/NewEnvironment/index.js @@ -118,7 +118,7 @@ const NewEnvironment = ({ id="branchName" className="inputBranch" type="text" - placeholder="e.g. main or develop" + placeholder="Enter branch name" value={inputBranchName} onChange={setBranchName} onBlur={() => toggleShowEnvType()} diff --git a/src/components/Organizations/AddGroupToProject/index.js b/src/components/Organizations/AddGroupToProject/index.js index 7ecf19b6..0e2072a9 100644 --- a/src/components/Organizations/AddGroupToProject/index.js +++ b/src/components/Organizations/AddGroupToProject/index.js @@ -42,10 +42,7 @@ export const AddGroupToProject = ({
diff --git a/src/components/Organizations/AddNotificationToProject/index.js b/src/components/Organizations/AddNotificationToProject/index.js index 57f22e12..e63b52af 100644 --- a/src/components/Organizations/AddNotificationToProject/index.js +++ b/src/components/Organizations/AddNotificationToProject/index.js @@ -48,10 +48,7 @@ export const AddNotificationToProject = ({
diff --git a/src/components/Organizations/GroupMembers/index.js b/src/components/Organizations/GroupMembers/index.js index e3eaedda..0ff0d800 100644 --- a/src/components/Organizations/GroupMembers/index.js +++ b/src/components/Organizations/GroupMembers/index.js @@ -6,15 +6,18 @@ import Link from 'next/link'; import { DisconnectOutlined, EditOutlined, EyeOutlined } from '@ant-design/icons'; import { useMutation } from '@apollo/react-hooks'; +import { Tooltip } from 'antd'; import Button from 'components/Button'; import Modal from 'components/Modal'; import RemoveUserConfirm from 'components/Organizations/RemoveUserConfirm'; import ProjectGroupLink from 'components/link/Organizations/ProjectGroup'; +import ProjectLink from 'components/link/Project'; import gql from 'graphql-tag'; import AddUserToGroup, { ADD_GROUP_MEMBER_MUTATION, options } from '../AddUserToGroup'; import { RoleSelect } from '../AddUserToGroup/Styles'; import PaginatedTable from '../PaginatedTable/PaginatedTable'; +import { ProjectDashboard } from '../Projects/Styles'; import { AddButtonContent, Footer, @@ -171,12 +174,16 @@ const GroupMembers = ({ }) } > - + + + - + + + @@ -246,13 +253,23 @@ const GroupMembers = ({ render: project => { return ( + + + View Dashboard + + +
@@ -352,10 +371,12 @@ const GroupMembers = ({
diff --git a/src/components/Organizations/Groups/index.js b/src/components/Organizations/Groups/index.js index 7d4aebed..41950112 100644 --- a/src/components/Organizations/Groups/index.js +++ b/src/components/Organizations/Groups/index.js @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import { Mutation } from 'react-apollo'; import { DeleteOutlined, EditOutlined, UserAddOutlined } from '@ant-design/icons'; +import { Tooltip } from 'antd'; import Button from 'components/Button'; import Modal from 'components/Modal'; import OrgGroupsLink from 'components/link/Organizations/Group'; @@ -95,7 +96,9 @@ const Groups = ({ groups = [], organizationId, organizationName, ableToAddGroup, return ( <> - modalAction('open', 'addUser', i)} /> + + modalAction('open', 'addUser', i)} /> + - + + + {i.type !== 'project-default-group' && ( <> - modalAction('open', 'deleteGroup', i)} /> + + modalAction('open', 'deleteGroup', i)} /> + diff --git a/src/components/Organizations/NewGroup/index.js b/src/components/Organizations/NewGroup/index.js index a57d180c..58059951 100644 --- a/src/components/Organizations/NewGroup/index.js +++ b/src/components/Organizations/NewGroup/index.js @@ -1,6 +1,7 @@ import React from 'react'; import { Mutation } from 'react-apollo'; +import { Tooltip } from 'antd'; import Button from 'components/Button'; import Modal from 'components/Modal'; // @TODO: add this once the logic exists @@ -93,10 +94,12 @@ export const NewGroup = ({
diff --git a/src/components/Organizations/NewProject/index.js b/src/components/Organizations/NewProject/index.js index 8fff2b97..548e6df7 100644 --- a/src/components/Organizations/NewProject/index.js +++ b/src/components/Organizations/NewProject/index.js @@ -2,16 +2,18 @@ import React from 'react'; import { Mutation } from 'react-apollo'; import ReactSelect from 'react-select'; +import Image from 'next/image'; + +import { Tooltip } from 'antd'; import Button from 'components/Button'; import Modal from 'components/Modal'; import withLogic from 'components/Organizations/NewProject/logic'; import gql from 'graphql-tag'; +import info from '../../../static/images/info.svg'; import { RoleSelect } from '../AddUserToGroup/Styles'; -import {StyledNewProject, Checkbox} from './StyledNewProject'; import { AddButtonContent, Footer, StyledNotificationWrapper } from '../SharedStyles'; -import Image from "next/image"; -import info from "../../../static/images/info.svg"; +import { Checkbox, StyledNewProject } from './StyledNewProject'; const ADD_PROJECT_MUTATION = gql` mutation ( @@ -73,10 +75,12 @@ const OrgNewProject = ({
@@ -132,7 +136,7 @@ const OrgNewProject = ({ @@ -162,21 +166,35 @@ const OrgNewProject = ({ setAddUserToProject(checked)} + type="checkbox" + checked={addUserToProject} + onChange={({ target: { checked } }) => setAddUserToProject(checked)} /> Add my user to this project
- +
-

Please note, once the project has been created you will need to add the Deploy Key and Webhook to your Git service, these will be generated in the ‘create environment’ wizard available from the project overview page.

+

+ Please note, once the project has been created you will need to add the{' '} + + Deploy Key + {' '} + and{' '} + + Webhook + {' '} + to your Git service, these will be generated in the ‘create environment’ wizard available from + the project overview page. +

@@ -200,7 +218,7 @@ const OrgNewProject = ({ kubernetes: parseInt(selectedDeployTarget.value, 10), productionEnvironment: inputProdEnv, organization: parseInt(organizationId, 10), - addOrgOwner: addUserToProject + addOrgOwner: addUserToProject, }, }); }} diff --git a/src/components/Organizations/Notifications/AddNotifications.tsx b/src/components/Organizations/Notifications/AddNotifications.tsx index 7c5095d8..323533e7 100644 --- a/src/components/Organizations/Notifications/AddNotifications.tsx +++ b/src/components/Organizations/Notifications/AddNotifications.tsx @@ -250,7 +250,7 @@ const AddNotification: FC = ({ modalOpen, organizationId, onNotificationA singleValue: base => ({ ...base, fontSize: '16px' }), }} aria-label="service" - placeholder="Select target" + placeholder="Select service" name="service" value={options.find(o => o.value === selectedService?.value)} onChange={selectedOption => setSelectedService(selectedOption)} diff --git a/src/components/Organizations/Notifications/Styles.tsx b/src/components/Organizations/Notifications/Styles.tsx index 54c38d85..ce0a3acc 100644 --- a/src/components/Organizations/Notifications/Styles.tsx +++ b/src/components/Organizations/Notifications/Styles.tsx @@ -251,9 +251,9 @@ export const StyledOrgNotifications = styled.div` &:not(:last-child) { border-bottom: 1px solid ${props => props.theme.borders.tableRow}; } - &:hover { + /* &:hover { border: 1px solid #2bc0d8; - } + } */ } .description { line-height: 24px; diff --git a/src/components/Organizations/Organization/OrganizationSkeleton.tsx b/src/components/Organizations/Organization/OrganizationSkeleton.tsx index 5e55249f..3334b60e 100644 --- a/src/components/Organizations/Organization/OrganizationSkeleton.tsx +++ b/src/components/Organizations/Organization/OrganizationSkeleton.tsx @@ -48,7 +48,7 @@ const OrganizationSkeleton = () => {
- Available Deployments + Available deploy targets
diff --git a/src/components/Organizations/Organization/index.js b/src/components/Organizations/Organization/index.js index 82f8646f..83197141 100644 --- a/src/components/Organizations/Organization/index.js +++ b/src/components/Organizations/Organization/index.js @@ -245,7 +245,7 @@ const Organization = ({ organization, refetch }) => {
- Available Deployments + Available deploy targets {organization.deployTargets.map(deploytarget => (
diff --git a/src/components/Organizations/PaginatedTable/Styles.tsx b/src/components/Organizations/PaginatedTable/Styles.tsx index 6bff0c0a..6586f5d6 100644 --- a/src/components/Organizations/PaginatedTable/Styles.tsx +++ b/src/components/Organizations/PaginatedTable/Styles.tsx @@ -53,9 +53,9 @@ export const TableRow = styled.div` border: 2px solid transparent; border-bottom: 2px solid ${props => props.theme.borders.tableRow}; } - &:hover { + /* &:hover { border: 2px solid #2bc0d8; - } + } */ `; export const TableColumn = styled.div<{ width: string }>` &:not(:last-child) { diff --git a/src/components/Organizations/ProjectGroupMembers/Styles.tsx b/src/components/Organizations/ProjectGroupMembers/Styles.tsx index 30e1e4e2..6ce0eaf4 100644 --- a/src/components/Organizations/ProjectGroupMembers/Styles.tsx +++ b/src/components/Organizations/ProjectGroupMembers/Styles.tsx @@ -62,9 +62,9 @@ export const StyledGroupMembers = styled.div` &:not(:last-child) { border-bottom: 1px solid ${props => props.theme.borders.tableRow}; } - &:hover { + /* &:hover { border: 1px solid #2bc0d8; - } + } */ } } `; diff --git a/src/components/Organizations/ProjectNotifications/Styles.tsx b/src/components/Organizations/ProjectNotifications/Styles.tsx index 7616992f..f492cdfa 100644 --- a/src/components/Organizations/ProjectNotifications/Styles.tsx +++ b/src/components/Organizations/ProjectNotifications/Styles.tsx @@ -53,9 +53,9 @@ export const StyledProjectNotifications = styled.div` &:not(:last-child) { border-bottom: 1px solid ${props => props.theme.borders.tableRow}; } - &:hover { + /* &:hover { border: 1px solid #2bc0d8; - } + } */ } } .slack-group-label { diff --git a/src/components/Organizations/ProjectNotifications/index.js b/src/components/Organizations/ProjectNotifications/index.js index 0be5b179..8687f086 100644 --- a/src/components/Organizations/ProjectNotifications/index.js +++ b/src/components/Organizations/ProjectNotifications/index.js @@ -3,6 +3,7 @@ import { Mutation } from 'react-apollo'; import { EditOutlined } from '@ant-design/icons'; import { useMutation } from '@apollo/react-hooks'; +import { Tooltip } from 'antd'; import Button from 'components/Button'; import Modal from 'components/Modal'; import RemoveProjectGroupConfirm from 'components/Organizations/RemoveProjectGroupConfirm'; @@ -249,7 +250,9 @@ const ProjectNotifications = ({ notifications = [], organizationId, projectName, }) } > - + + + ` + ${props => + !props.inlineLink + ? ` margin-left:1.5rem; font-size:13px; - background:${props => props.theme.backgrounds.sidebar}; + background:${props.theme.backgrounds.sidebar}; padding:0.25rem 0.5rem; color:#497ffa; -`; \ No newline at end of file + ` + : ` + margin-right: 1.25rem; + font-size: 12px; + background: #fff !important; + text-align: center; + line-height: 18px; + padding-bottom: 0.1rem; + padding-inline: 0.15rem; + height: 36px; + color: #497ffa; + border: 1px solid #4578e6; + + `} +`; diff --git a/src/components/Organizations/Projects/index.js b/src/components/Organizations/Projects/index.js index 2109f465..58d528b5 100644 --- a/src/components/Organizations/Projects/index.js +++ b/src/components/Organizations/Projects/index.js @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import { Mutation } from 'react-apollo'; import { DeleteOutlined, EditOutlined } from '@ant-design/icons'; +import { Tooltip } from 'antd'; import Button from 'components/Button'; import Modal from 'components/Modal'; import ProjectGroupLink from 'components/link/Organizations/ProjectGroup'; @@ -44,10 +45,6 @@ const OrgProjects = ({ projects = [], organizationId, organizationName, refresh, > {project.name} - - - View in Dashboard - ); }, @@ -68,7 +65,13 @@ const OrgProjects = ({ projects = [], organizationId, organizationName, refresh, key: 'actions', render: function (project) { return ( - + + + + View Dashboard + + + - + + + <> - { - setModalState({ open: true, current: project.name }); - }} - /> + + { + setModalState({ open: true, current: project.name }); + }} + /> + { return ( - ) : ( + + <> + + +
@@ -140,6 +142,7 @@ export const NewGroup = ({
+

Please use (a to z) lower case, numbers and - only

+ {!isValidEmail &&

Invalid email address

}
); case 'slack': @@ -250,7 +262,7 @@ const AddNotification: FC = ({ modalOpen, organizationId, onNotificationA singleValue: base => ({ ...base, fontSize: '16px' }), }} aria-label="service" - placeholder="Select service" + placeholder="Make a selection" name="service" value={options.find(o => o.value === selectedService?.value)} onChange={selectedOption => setSelectedService(selectedOption)} @@ -295,7 +307,7 @@ const AddNotification: FC = ({ modalOpen, organizationId, onNotificationA }} variant="primary" loading={loading} - disabled={loading} + disabled={loading || (selectedService?.value === 'email' && !isValidEmail)} > Add diff --git a/src/components/Organizations/Notifications/index.js b/src/components/Organizations/Notifications/index.js index 759685a6..65b6dd5b 100644 --- a/src/components/Organizations/Notifications/index.js +++ b/src/components/Organizations/Notifications/index.js @@ -139,17 +139,26 @@ const OrgNotifications = ({ const [editState, setEditState] = useState(initialEditState); - const [notificationName, setNotificationName] = useState(''); - const [email, setEmail] = useState(''); - const [webhook, setWebhook] = useState(''); - const [channel, setChannel] = useState(''); - const closeEditModal = () => { setEditState(initialEditState); - setNotificationName(''); - setEmail(''); - setWebhook(''); - setChannel(''); + }; + + const [isValidEmail, setIsValidEmail] = useState(true); + + const handleInputChange = (e, property) => { + const newValue = e.target.value; + setEditState(prevState => ({ + ...prevState, + current: { + ...prevState.current, + [property]: newValue, + }, + })); + + if (property === 'emailAddress') { + const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; + newValue && setIsValidEmail(emailRegex.test(newValue)); + } }; return ( @@ -190,7 +199,12 @@ const OrgNotifications = ({ Channel: {project.channel}
- setEditState({ open: true, current: project, type: 'slack' })}> + { + setEditState({ open: true, current: project, type: 'slack' }); + }} + > setNotificationName(e.target.value)} + value={editState.current.name} + onChange={e => handleInputChange(e, 'name')} />
@@ -219,8 +233,8 @@ const OrgNotifications = ({ className="inputWebhook" type="text" placeholder="Enter Webhook" - value={webhook || editState.current.webhook} - onChange={e => setWebhook(e.target.value)} + value={editState.current.webhook} + onChange={e => handleInputChange(e, 'webhook')} />
@@ -232,8 +246,8 @@ const OrgNotifications = ({ className="inputChannel" type="text" placeholder="Enter channel" - value={channel || editState.current.channel} - onChange={e => setChannel(e.target.value)} + value={editState.current.channel} + onChange={e => handleInputChange(e, 'channel')} />
@@ -257,11 +271,11 @@ const OrgNotifications = ({ action={() => { updateSlack({ variables: { - name: editState.current.name, + name: project.name, patch: { - ...(notificationName ? { name: notificationName } : {}), - ...(channel ? { channel } : {}), - ...(webhook ? { webhook } : {}), + ...(editState.current.name ? { name: editState.current.name } : {}), + ...(editState.current.channel ? { channel: editState.current.channel } : {}), + ...(editState.current.webhook ? { webhook: editState.current.webhook } : {}), }, }, }); @@ -335,8 +349,8 @@ const OrgNotifications = ({ className="inputName" type="text" placeholder="Enter name" - value={notificationName || editState.current.name} - onChange={e => setNotificationName(e.target.value)} + value={editState.current.name} + onChange={e => handleInputChange(e, 'name')} />
@@ -348,8 +362,8 @@ const OrgNotifications = ({ className="inputWebhook" type="text" placeholder="Enter Webhook" - value={webhook || editState.current.webhook} - onChange={e => setWebhook(e.target.value)} + value={editState.current.webhook} + onChange={e => handleInputChange(e, 'webhook')} /> @@ -361,8 +375,8 @@ const OrgNotifications = ({ className="inputChannel" type="text" placeholder="Enter channel" - value={channel || editState.current.channel} - onChange={e => setChannel(e.target.value)} + value={editState.current.channel} + onChange={e => handleInputChange(e, 'channel')} /> @@ -386,11 +400,11 @@ const OrgNotifications = ({ action={() => { updateRocketChat({ variables: { - name: editState.current.name, + name: project.name, patch: { - ...(notificationName ? { name: notificationName } : {}), - ...(channel ? { channel } : {}), - ...(webhook ? { webhook } : {}), + ...(editState.current.name ? { name: editState.current.name } : {}), + ...(editState.current.channel ? { channel: editState.current.channel } : {}), + ...(editState.current.webhook ? { webhook: editState.current.webhook } : {}), }, }, }); @@ -460,8 +474,8 @@ const OrgNotifications = ({ className="inputName" type="text" placeholder="Enter name" - value={notificationName || editState.current.name} - onChange={e => setNotificationName(e.target.value)} + value={editState.current.name} + onChange={e => handleInputChange(e, 'name')} /> @@ -473,10 +487,11 @@ const OrgNotifications = ({ className="inputEmail" type="text" placeholder="Enter Email" - value={email || editState.current.emailAddress} - onChange={e => setEmail(e.target.value)} + value={editState.current.emailAddress} + onChange={e => handleInputChange(e, 'emailAddress')} /> + {!isValidEmail &&

Invalid email address

}