Skip to content

Commit f3b2d22

Browse files
Merge pull request #1804 from Jr7468/dev
Advanced Out of Office Editor
2 parents 2fc7853 + 96f34f4 commit f3b2d22

File tree

2 files changed

+244
-2
lines changed

2 files changed

+244
-2
lines changed

src/views/email-exchange/administration/EditMailboxPermissions.js

Lines changed: 242 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ import { Form, Field } from 'react-final-form'
2121
import { RFFSelectSearch, RFFCFormSelect, RFFCFormCheck, RFFCFormInput } from 'src/components/forms'
2222
import { useListUsersQuery } from 'src/store/api/users'
2323
import { ModalService } from 'src/components/utilities'
24-
import { useLazyGenericPostRequestQuery, useLazyGenericGetRequestQuery } from 'src/store/api/app'
24+
import {
25+
useLazyGenericPostRequestQuery,
26+
useLazyGenericGetRequestQuery,
27+
useGenericGetRequestQuery,
28+
} from 'src/store/api/app'
2529
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
2630
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
2731
import {
@@ -32,6 +36,9 @@ import {
3236
import { CippTable } from 'src/components/tables'
3337
import { useListMailboxDetailsQuery } from 'src/store/api/mailbox'
3438
import { CellBoolean } from 'src/components/tables'
39+
import DatePicker from 'react-datepicker'
40+
import 'react-datepicker/dist/react-datepicker.css'
41+
import { RFFCFormSwitch } from 'src/components/forms'
3542

3643
const formatter = (cell, warning = false, reverse = false, colourless = false) =>
3744
CellBoolean({ cell, warning, reverse, colourless })
@@ -114,6 +121,9 @@ const MailboxSettings = () => {
114121
<CNavItem active={active === 3} onClick={() => setActive(3)} href="#">
115122
Mailbox Forwarding
116123
</CNavItem>
124+
<CNavItem active={active === 4} onClick={() => setActive(4)} href="#">
125+
Out Of Office
126+
</CNavItem>
117127
</CNav>
118128
</CCardHeader>
119129
<CCardBody>
@@ -127,6 +137,9 @@ const MailboxSettings = () => {
127137
<CTabPane visible={active === 3} className="mt-3">
128138
<MailboxForwarding />
129139
</CTabPane>
140+
<CTabPane visible={active === 4} className="mt-3">
141+
<OutOfOffice />
142+
</CTabPane>
130143
</CTabContent>
131144
</CCardBody>
132145
</CCard>
@@ -158,6 +171,11 @@ const MailboxSettings = () => {
158171
<ForwardingSettings userId={userId} tenantDomain={tenantDomain} />
159172
</>
160173
)}
174+
{active === 4 && (
175+
<>
176+
<OutOfOfficeSettings userId={userId} tenantDomain={tenantDomain} />
177+
</>
178+
)}
161179
</CCardBody>
162180
</CCard>
163181
</CCol>
@@ -761,3 +779,226 @@ const ForwardingSettings = () => {
761779
</CRow>
762780
)
763781
}
782+
783+
const OutOfOffice = () => {
784+
const dispatch = useDispatch()
785+
let query = useQuery()
786+
const userId = query.get('userId')
787+
const tenantDomain = query.get('tenantDomain')
788+
const [queryError, setQueryError] = useState(false)
789+
const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
790+
const [startDate, setStartDate] = useState(new Date())
791+
const [endDate, setEndDate] = useState(new Date())
792+
const {
793+
data: user = {},
794+
isFetching: userIsFetching,
795+
error: userError,
796+
} = useListMailboxPermissionsQuery({ tenantDomain, userId })
797+
798+
const {
799+
data: users = [],
800+
isFetching: usersIsFetching,
801+
error: usersError,
802+
} = useListUsersQuery({ tenantDomain })
803+
804+
useEffect(() => {
805+
if (postResults.isSuccess) {
806+
}
807+
if (!userId || !tenantDomain) {
808+
ModalService.open({
809+
body: 'Error invalid request, could not load requested user.',
810+
title: 'Invalid Request',
811+
})
812+
setQueryError(true)
813+
} else {
814+
setQueryError(false)
815+
}
816+
}, [userId, tenantDomain, dispatch, postResults])
817+
const onSubmit = (values) => {
818+
const shippedValues = {
819+
user: userId,
820+
tenantFilter: tenantDomain,
821+
AutoReplyState: values.AutoReplyState ? 'Scheduled' : 'Disabled',
822+
StartTime: startDate.toLocaleString(),
823+
EndTime: endDate.toLocaleString(),
824+
InternalMessage: values.InternalMessage ? values.InternalMessage : '',
825+
ExternalMessage: values.ExternalMessage ? values.ExternalMessage : '',
826+
}
827+
//window.alert(JSON.stringify(shippedValues))
828+
genericPostRequest({ path: '/api/ExecSetOoO', values: shippedValues })
829+
}
830+
const initialState = {
831+
...user,
832+
}
833+
834+
const formDisabled = queryError === true
835+
836+
return (
837+
<>
838+
{!queryError && (
839+
<>
840+
{queryError && (
841+
<CRow>
842+
<CCol className="mb-3">
843+
<CCallout color="danger">
844+
{/* @todo add more descriptive help message here */}
845+
Failed to load user
846+
</CCallout>
847+
</CCol>
848+
</CRow>
849+
)}
850+
<CRow>
851+
<CCol className="mb-3">
852+
{usersIsFetching && <CSpinner />}
853+
{userError && <span>Error loading user</span>}
854+
{!usersIsFetching && (
855+
<Form
856+
initialValues={{ ...initialState }}
857+
onSubmit={onSubmit}
858+
render={({ handleSubmit, submitting, values }) => {
859+
return (
860+
<CForm onSubmit={handleSubmit}>
861+
<CRow>
862+
<CCol className="mb-3">
863+
<RFFCFormSwitch name="AutoReplyState" label="Auto Reply State" />
864+
</CCol>
865+
</CRow>
866+
<CRow>
867+
<CCol className="mb-3">
868+
<label>Start Date/Time</label>
869+
<DatePicker
870+
dateFormat="dd/MM/yyyy HH:mm"
871+
className="form-control"
872+
selected={startDate}
873+
onChange={(date) => setStartDate(date)}
874+
showTimeSelect
875+
/>
876+
</CCol>
877+
</CRow>
878+
<CRow>
879+
<CCol className="mb-3">
880+
<label>End Date/Time</label>
881+
<DatePicker
882+
dateFormat="dd/MM/yyyy HH:mm"
883+
className="form-control"
884+
selected={endDate}
885+
onChange={(date) => setEndDate(date)}
886+
showTimeSelect
887+
/>
888+
</CCol>
889+
</CRow>
890+
<CRow>
891+
<CCol className="mb-3">
892+
<RFFCFormInput
893+
type="text"
894+
name="InternalMessage"
895+
label="Internal Message"
896+
disabled={formDisabled}
897+
/>
898+
</CCol>
899+
</CRow>
900+
<CRow>
901+
<CCol className="mb-3">
902+
<RFFCFormInput
903+
type="text"
904+
name="ExternalMessage"
905+
label="External Message"
906+
disabled={formDisabled}
907+
/>
908+
</CCol>
909+
</CRow>
910+
<CRow>
911+
<CCol className="mb-3">
912+
<CButton
913+
type="submit"
914+
disabled={submitting || formDisabled}
915+
style={{ marginRight: '10px' }}
916+
>
917+
Edit Out of Office
918+
{postResults.isFetching && (
919+
<FontAwesomeIcon
920+
icon={faCircleNotch}
921+
spin
922+
className="me-2"
923+
size="1x"
924+
/>
925+
)}
926+
</CButton>
927+
</CCol>
928+
</CRow>
929+
{postResults.isSuccess && (
930+
<CCallout color="success">
931+
{postResults.data.Results.map((result, idx) => (
932+
<li key={idx}>{result}</li>
933+
))}
934+
</CCallout>
935+
)}
936+
</CForm>
937+
)
938+
}}
939+
/>
940+
)}
941+
</CCol>
942+
</CRow>
943+
</>
944+
)}
945+
</>
946+
)
947+
}
948+
949+
const OutOfOfficeSettings = () => {
950+
const query = useQuery()
951+
const userId = query.get('userId')
952+
const tenantDomain = query.get('tenantDomain')
953+
const tenantFilter = tenantDomain
954+
const {
955+
data: details,
956+
isFetching,
957+
error,
958+
} = useGenericGetRequestQuery({
959+
path: '/api/ListOoO',
960+
params: { userId, tenantFilter },
961+
})
962+
const content = [
963+
{
964+
heading: 'Auto Reply State',
965+
body: formatter(details?.AutoReplyState, false, false, true),
966+
},
967+
{
968+
heading: 'Start Date/Time',
969+
body: details?.StartTime ? details?.StartTime : 'N/A',
970+
},
971+
{
972+
heading: 'End Date/Time',
973+
body: details?.EndTime ? details?.EndTime : 'N/A',
974+
},
975+
{
976+
heading: 'Internal Message',
977+
body: details?.InternalMessage ? details?.InternalMessage : 'N/A',
978+
},
979+
{
980+
heading: 'External Message',
981+
body: details?.ExternalMessage ? details?.ExternalMessage : 'N/A',
982+
},
983+
]
984+
return (
985+
<CRow>
986+
{isFetching && (
987+
<CCallout color="info">
988+
<CSpinner>Loading</CSpinner>
989+
</CCallout>
990+
)}
991+
{!isFetching && (
992+
<CCol className="mb-3">
993+
{content.map((item, index) => (
994+
<div key={index}>
995+
<h5>{item.heading}</h5>
996+
<p>{item.body}</p>
997+
</div>
998+
))}
999+
</CCol>
1000+
)}
1001+
{error && <CCallout color="danger">Could not connect to API: {error.message}</CCallout>}
1002+
</CRow>
1003+
)
1004+
}

src/views/identity/administration/Users.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ const Offcanvas = (row, rowIndex, formatExtraData) => {
149149
user: row.userPrincipalName,
150150
TenantFilter: tenant.defaultDomainName,
151151
message: row.message,
152+
AutoReplyState: 'Enabled',
152153
},
153154
modalUrl: `/api/ExecSetOoO`,
154155
modalInput: true,
@@ -163,7 +164,7 @@ const Offcanvas = (row, rowIndex, formatExtraData) => {
163164
modalBody: {
164165
user: row.userPrincipalName,
165166
TenantFilter: tenant.defaultDomainName,
166-
Disable: true,
167+
AutoReplyState: 'Disabled',
167168
},
168169
modalUrl: `/api/ExecSetOoO`,
169170
modalMessage: 'Are you sure you want to disable the out of office?',

0 commit comments

Comments
 (0)