Skip to content

Commit

Permalink
Merge pull request #2682 from BNWEIN/dev
Browse files Browse the repository at this point in the history
Added Ability to edit contact
  • Loading branch information
KelvinTegelaar authored Jul 16, 2024
2 parents 97fae4d + adbb19f commit 2091edd
Show file tree
Hide file tree
Showing 4 changed files with 301 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/importsMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ import React from 'react'
"/email/administration/add-contact": React.lazy(() => import('./views/email-exchange/administration/AddContact')),
"/email/administration/edit-calendar-permissions": React.lazy(() => import('./views/email-exchange/administration/EditCalendarPermissions')),
"/email/administration/view-mobile-devices": React.lazy(() => import('./views/email-exchange/administration/ViewMobileDevices')),
"/email/administration/edit-contact": React.lazy(() => import('./views/email-exchange/administration/EditContact')),
"/email/administration/edit-contact": React.lazy(() => import('./views/email-exchange/administration/EditContact.jsx')),
"/email/administration/mailboxes": React.lazy(() => import('./views/email-exchange/administration/MailboxesList')),
"/email/administration/deleted-mailboxes": React.lazy(() => import('./views/email-exchange/administration/DeletedMailboxes')),
"/email/administration/mailbox-rules": React.lazy(() => import('./views/email-exchange/administration/MailboxRuleList')),
Expand Down
3 changes: 2 additions & 1 deletion src/store/api/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ export const usersApi = baseApi.injectEndpoints({
}),
}),
listContacts: builder.query({
query: ({ tenantDomain }) => ({
query: ({ tenantDomain, ContactID }) => ({
path: '/api/ListContacts',
params: {
TenantFilter: tenantDomain,
ContactID,
},
}),
}),
Expand Down
17 changes: 9 additions & 8 deletions src/views/email-exchange/administration/ContactsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useSelector } from 'react-redux'
import { CButton } from '@coreui/react'
import { CippPageList } from 'src/components/layout'
import { CellTip, cellBooleanFormatter } from 'src/components/tables'
import { Link, useSearchParams } from 'react-router-dom'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faEdit, faEllipsisV } from '@fortawesome/free-solid-svg-icons'
import { TitleButton } from 'src/components/buttons'
Expand All @@ -11,16 +12,16 @@ import { CippActionsOffcanvas } from 'src/components/utilities'
const Actions = (row, rowIndex, formatExtraData) => {
const tenant = useSelector((state) => state.app.currentTenant)
const [ocVisible, setOCVisible] = useState(false)
const editLink = row?.tenant
? `/email/administration/edit-contact?ContactID=${row.id}&tenantDomain=${row.Tenant}`
: `/email/administration/edit-contact?ContactID=${row.id}&tenantDomain=${tenant.defaultDomainName}`
return (
<>
<CButton size="sm" variant="ghost" color="warning">
<a
rel={'noreferrer'}
target={'_blank'}
href={`https://outlook.office365.com/ecp/@${tenant.defaultDomainName}/UsersGroups/EditContact.aspx?exsvurl=1&realm=${tenant.customerId}&mkt=en-US&id=${row.id}`}
></a>
<FontAwesomeIcon icon={faEdit} />
</CButton>
<Link to={editLink}>
<CButton size="sm" variant="ghost" color="warning">
<FontAwesomeIcon icon={faEdit} />
</CButton>
</Link>
<CButton size="sm" color="link" onClick={() => setOCVisible(true)}>
<FontAwesomeIcon icon={faEllipsisV} />
</CButton>
Expand Down
295 changes: 289 additions & 6 deletions src/views/email-exchange/administration/EditContact.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,294 @@
import React from 'react'
import React, { useEffect, useState } from 'react'
import { CButton, CCallout, CCol, CForm, CRow, CSpinner } from '@coreui/react'
import useQuery from 'src/hooks/useQuery'
import { useDispatch, useSelector } from 'react-redux'
import { Form } from 'react-final-form'
import { RFFCFormInput } from 'src/components/forms'
import { useListContactsQuery } from 'src/store/api/users'
import { CippCodeBlock, ModalService } from 'src/components/utilities'
import { useLazyGenericPostRequestQuery } from 'src/store/api/app'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCircleNotch, faEdit, faEye } from '@fortawesome/free-solid-svg-icons'
import { CippContentCard, CippPage } from 'src/components/layout'

const EditContact = (props) => {
const EditContact = () => {
const dispatch = useDispatch()
let query = useQuery()
const ContactID = query.get('ContactID')
const tenantDomain = query.get('tenantDomain')

const [queryError, setQueryError] = useState(false)

const {
data: Contact = [],
isFetching: ContactIsFetching,
error: ContactError,
} = useListContactsQuery({ tenantDomain, ContactID })

useEffect(() => {
if (!ContactID || !tenantDomain) {
ModalService.open({
body: 'Error invalid request, could not load requested contact.',
title: 'Invalid Request',
})
setQueryError(true)
} else {
setQueryError(false)
}
}, [ContactID, tenantDomain, dispatch])
const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
const onSubmit = (values) => {
if (values.defaultAttributes) {
//map default attributes to the addedAttributes array. If addedAttributes is not present, create it.
values.addedAttributes = values.addedAttributes ? values.addedAttributes : []
Object.keys(values.defaultAttributes).forEach((key) => {
values.addedAttributes.push({ Key: key, Value: values.defaultAttributes[key].Value })
})
}
const shippedValues = {
BusinessPhone: values.businessPhones,
City: values.city,
CompanyName: values.companyName,
Country: values.country,
mail: values.mail,
DisplayName: values.displayName,
firstName: values.givenName,
Jobtitle: values.jobTitle,
LastName: values.surname,
MobilePhone: values.mobilePhone,
PostalCode: values.postalCode,
ContactID: ContactID,
streetAddress: values.streetAddress,
tenantID: tenantDomain,
}
// window.alert(JSON.stringify(shippedValues))
genericPostRequest({ path: '/api/EditContact', values: shippedValues })
}
const [addedAttributes, setAddedAttribute] = React.useState(0)
const currentSettings = useSelector((state) => state.app)

// Extract the first contact from the array
const contactData = Contact.length > 0 ? Contact[0] : {}

// Extract address and phone details
const address =
contactData.addresses && contactData.addresses.length > 0 ? contactData.addresses[0] : {}
const mobilePhone = contactData.phones
? contactData.phones.find((phone) => phone.type === 'mobile')
: {}
const businessPhones = contactData.phones
? contactData.phones
.filter((phone) => phone.type === 'business')
.map((phone) => phone.number)
.join(', ')
: ''

const initialState = {
...contactData,
streetAddress: address.street || '',
postalCode: address.postalCode || '',
city: address.city || '',
country: address.countryOrRegion || '',
mobilePhone: mobilePhone ? mobilePhone.number : '',
businessPhones: businessPhones || '',
}

const formDisabled =
queryError === true || !!ContactError || !Contact || Object.keys(contactData).length === 0
const RawUser = JSON.stringify(contactData, null, 2)
return (
<div>
<h3>Edit Contact</h3>
future release.
</div>
<CippPage
title={`Edit Contact: ${ContactIsFetching ? 'Loading...' : contactData.displayName}`}
tenantSelector={false}
>
{!queryError && (
<>
{postResults.isSuccess && (
<CCallout color="success">{postResults.data?.Results}</CCallout>
)}
{queryError && (
<CRow>
<CCol xs={12}>
<CCallout color="danger">
{/* @todo add more descriptive help message here */}
Failed to load contact
</CCallout>
</CCol>
</CRow>
)}
<CRow className="mb-3">
<CCol lg={6} xs={12}>
<CippContentCard title="Contact Details" icon={faEdit}>
{ContactIsFetching && <CSpinner />}
{ContactError && <span>Error loading user</span>}
{!ContactIsFetching && (
<Form
initialValues={{ ...initialState }}
onSubmit={onSubmit}
render={({ handleSubmit, submitting, values }) => {
return (
<CForm onSubmit={handleSubmit}>
<CRow>
<CCol lg={6} xs={12}>
<RFFCFormInput
type="text"
name="givenName"
label="Edit First Name"
disabled={formDisabled}
/>
</CCol>
<CCol lg={6} xs={12}>
<RFFCFormInput
type="text"
name="surname"
label="Edit Last Name"
disabled={formDisabled}
/>
</CCol>
</CRow>
<CRow>
<CCol xs={12}>
<RFFCFormInput
type="text"
name="displayName"
label="Edit Display Name"
disabled={formDisabled}
/>
</CCol>
</CRow>
<CRow>
<CCol xs={12}>
<RFFCFormInput
type="text"
name="mail"
label="Edit email"
disabled={formDisabled}
/>
</CCol>
</CRow>
<CRow>
<CCol xs={12}>
<RFFCFormInput
type="text"
name="jobTitle"
label="Edit Job Title"
disabled={formDisabled}
/>
</CCol>
</CRow>
<CRow>
<CCol md={6}>
<RFFCFormInput
name="streetAddress"
label="Street"
type="text"
disabled={formDisabled}
/>
</CCol>
<CCol md={6}>
<RFFCFormInput
name="postalCode"
label="Postal Code"
type="text"
disabled={formDisabled}
/>
</CCol>
</CRow>
<CRow>
<CCol md={6}>
<RFFCFormInput
name="city"
label="City"
type="text"
disabled={formDisabled}
/>
</CCol>
<CCol md={6}>
<RFFCFormInput
name="country"
label="Country"
type="text"
disabled={formDisabled}
/>
</CCol>
</CRow>
<CRow>
<CCol md={6}>
<RFFCFormInput
name="companyName"
label="Company Name"
type="text"
disabled={formDisabled}
/>
</CCol>
</CRow>
<CRow>
<CCol md={6}>
<RFFCFormInput
name="mobilePhone"
label="Mobile #"
type="text"
disabled={formDisabled}
/>
</CCol>
<CCol md={6}>
<RFFCFormInput
name="businessPhones"
label="Business #"
type="text"
disabled={formDisabled}
/>
</CCol>
</CRow>
<CRow className="mb-3">
<CCol md={6}>
<CButton type="submit" disabled={submitting || formDisabled}>
Edit Contact
{postResults.isFetching && (
<FontAwesomeIcon
icon={faCircleNotch}
spin
className="ms-2"
size="1x"
/>
)}
</CButton>
</CCol>
</CRow>
{postResults.isSuccess && (
<CCallout color="success">
{Array.isArray(postResults.data.Results) ? (
postResults.data.Results.map((message, idx) => (
<li key={idx}>{message}</li>
))
) : (
<span>{postResults.data.Results}</span>
)}
</CCallout>
)}
</CForm>
)
}}
/>
)}
</CippContentCard>
</CCol>
<CCol lg={6} xs={12}>
<CippContentCard title="Raw User Data" icon={faEye}>
{ContactIsFetching && <CSpinner />}
{ContactError && <span>Error loading user</span>}
{!ContactIsFetching && (
<>
This is the (raw) information for this contact.
<CippCodeBlock language="json" code={RawUser} />
</>
)}
</CippContentCard>
</CCol>
</CRow>
</>
)}
</CippPage>
)
}

Expand Down

0 comments on commit 2091edd

Please sign in to comment.