Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Ability to edit contact #2682

Merged
merged 2 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading