Skip to content

Commit e5e0375

Browse files
authored
Merge branch 'KelvinTegelaar:main' into main
2 parents 0e1d69e + 1c76dec commit e5e0375

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+5242
-2378
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cipp",
3-
"version": "5.6.2",
3+
"version": "5.7.0",
44
"description": "The CyberDrain Improved Partner Portal is a portal to help manage administration for Microsoft Partners.",
55
"homepage": "https://cipp.app/",
66
"bugs": {

public/GDAPRoles.json

+16
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,22 @@
671671
"Name": "Virtual Visits Administrator",
672672
"ObjectId": "e300d9e7-4a2b-4295-9eff-f1c78b36cc98"
673673
},
674+
{
675+
"ExtensionData": {},
676+
"Description": "Manage and configure all aspects of Microsoft Viva Goals.",
677+
"IsEnabled": true,
678+
"IsSystem": true,
679+
"Name": "Viva Goals Administrator",
680+
"ObjectId": "92b086b3-e367-4ef2-b869-1de128fb986e"
681+
},
682+
{
683+
"ExtensionData": {},
684+
"Description": "Can manage all settings for Microsoft Viva Pulse app.",
685+
"IsEnabled": true,
686+
"IsSystem": true,
687+
"Name": "Viva Pulse Administrator",
688+
"ObjectId": "87761b17-1ed2-4af3-9acd-92a150038160"
689+
},
674690
{
675691
"ExtensionData": {},
676692
"Description": "Can provision and manage all aspects of Cloud PCs.",

public/version_latest.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5.6.2
1+
5.7.0

src/_nav.jsx

+21-7
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,9 @@ const _nav = [
129129
},
130130
{
131131
component: CNavItem,
132-
name: 'Alerts (Classic)',
132+
name: 'Alerts',
133133
to: '/tenant/administration/alertsqueue',
134134
},
135-
{
136-
component: CNavItem,
137-
name: 'Alert Rules',
138-
to: '/tenant/administration/AlertRules',
139-
},
140135
{
141136
component: CNavItem,
142137
name: 'Enterprise Applications',
@@ -155,7 +150,7 @@ const _nav = [
155150
{
156151
component: CNavItem,
157152
name: 'Tenant Onboarding',
158-
to: '/tenant/administration/tenant-onboarding-wizard',
153+
to: '/tenant/administration/tenant-onboarding',
159154
},
160155
{
161156
component: CNavItem,
@@ -707,6 +702,25 @@ const _nav = [
707702
},
708703
],
709704
},
705+
{
706+
component: CNavGroup,
707+
name: ' Room Management',
708+
section: 'Email & Exchange',
709+
to: '/rooms/management',
710+
icon: <FontAwesomeIcon icon={faToolbox} className="nav-icon" />,
711+
items: [
712+
{
713+
component: CNavItem,
714+
name: 'Rooms',
715+
to: '/rooms/management/list-rooms',
716+
},
717+
{
718+
component: CNavItem,
719+
name: 'Room Lists',
720+
to: '/rooms/management/room-lists',
721+
},
722+
],
723+
},
710724
{
711725
component: CNavGroup,
712726
name: 'Reports',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from 'react'
2+
import {
3+
CAccordionBody,
4+
CAccordionHeader,
5+
CAccordionItem,
6+
CCard,
7+
CCardBody,
8+
CCardFooter,
9+
CCardHeader,
10+
CCardTitle,
11+
} from '@coreui/react'
12+
import Skeleton from 'react-loading-skeleton'
13+
import PropTypes from 'prop-types'
14+
15+
export default function CippAccordionItem({
16+
title,
17+
titleType = 'normal',
18+
CardButton,
19+
children,
20+
isFetching,
21+
}) {
22+
return (
23+
<CAccordionItem>
24+
<CAccordionHeader>{title}</CAccordionHeader>
25+
<CAccordionBody>
26+
<CCard>
27+
<CCardHeader>
28+
<CCardTitle>
29+
{titleType === 'big' ? <h3 className="underline mb-3">{title}</h3> : title}
30+
</CCardTitle>
31+
</CCardHeader>
32+
<CCardBody className="my-3">
33+
{isFetching && <Skeleton />}
34+
{children}
35+
</CCardBody>
36+
<CCardFooter>{CardButton}</CCardFooter>
37+
</CCard>
38+
</CAccordionBody>
39+
</CAccordionItem>
40+
)
41+
}
42+
43+
CippAccordionItem.propTypes = {
44+
title: PropTypes.string.isRequired,
45+
titleType: PropTypes.string,
46+
CardButton: PropTypes.element.isRequired,
47+
children: PropTypes.element.isRequired,
48+
isFetching: PropTypes.bool.isRequired,
49+
}

src/components/contentcards/CippChartCard.jsx

+29-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from 'react'
22
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
3-
import { CCard, CCardBody, CCardFooter, CCardHeader, CCardTitle } from '@coreui/react'
4-
import Skeleton from 'react-loading-skeleton'
3+
import { CButton, CCard, CCardBody, CCardHeader, CCardTitle } from '@coreui/react'
54
import { CChart } from '@coreui/react-chartjs'
65
import { getStyle } from '@coreui/utils'
6+
import PropTypes from 'prop-types'
77

88
export default function CippChartCard({
99
title,
@@ -13,23 +13,38 @@ export default function CippChartCard({
1313
ChartType = 'pie',
1414
LegendLocation = 'bottom',
1515
isFetching,
16+
refreshFunction,
1617
}) {
1718
return (
1819
<CCard className="h-100 mb-3">
1920
<CCardHeader>
2021
<CCardTitle>
2122
{titleType === 'big' ? <h3 className="underline mb-3">{title}</h3> : title}
23+
{refreshFunction ? (
24+
<CButton
25+
className="position-absolute top-0 end-0 mt-2 me-2"
26+
variant="ghost"
27+
onClick={refreshFunction}
28+
disabled={isFetching}
29+
>
30+
<FontAwesomeIcon icon="sync" spin={isFetching} />
31+
</CButton>
32+
) : (
33+
<CButton className="position-absolute top-0 end-0 mt-2 me-2" variant="ghost" disabled>
34+
<FontAwesomeIcon icon="sync" spin={isFetching} />
35+
</CButton>
36+
)}
2237
</CCardTitle>
2338
</CCardHeader>
2439
<CCardBody>
25-
{isFetching && <Skeleton />}
26-
{!isFetching && (
40+
{ChartData && (
2741
<CChart
2842
type={ChartType}
2943
data={{
3044
labels: ChartLabels,
3145
datasets: [
3246
{
47+
label: title,
3348
backgroundColor: [
3449
getStyle('--cyberdrain-warning'),
3550
getStyle('--cyberdrain-info'),
@@ -59,3 +74,13 @@ export default function CippChartCard({
5974
</CCard>
6075
)
6176
}
77+
CippChartCard.propTypes = {
78+
title: PropTypes.string.isRequired,
79+
titleType: PropTypes.oneOf(['normal', 'big']),
80+
ChartData: PropTypes.array.isRequired,
81+
ChartLabels: PropTypes.array.isRequired,
82+
ChartType: PropTypes.oneOf(['pie', 'bar', 'line']),
83+
LegendLocation: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
84+
isFetching: PropTypes.bool,
85+
refreshFunction: PropTypes.func,
86+
}

src/components/forms/RFFComponents.jsx

+49-2
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ export const RFFCFormSwitch = ({
123123
>
124124
<div className={className}>
125125
<CFormSwitch
126-
{...input}
126+
onChange={input.onChange}
127+
checked={input.checked}
128+
value={input.value}
127129
// @todo revisit this, only shows green when checked
128130
valid={!meta.error && meta.touched && validate}
129131
invalid={meta.error && meta.touched && validate}
@@ -265,7 +267,9 @@ export const RFFCFormRadio = ({
265267
{({ meta, input }) => (
266268
<div className={className}>
267269
<CFormCheck
268-
{...input}
270+
onChange={input.onChange}
271+
checked={input.checked}
272+
value={input.value}
269273
valid={!meta.error && meta.touched}
270274
invalid={meta.error && meta.touched}
271275
disabled={disabled}
@@ -285,6 +289,49 @@ RFFCFormRadio.propTypes = {
285289
...sharedPropTypes,
286290
}
287291

292+
export const RFFCFormRadioList = ({
293+
name,
294+
options,
295+
className = 'mb-3',
296+
disabled = false,
297+
onClick,
298+
inline = false,
299+
}) => {
300+
return (
301+
<>
302+
<div className={className}>
303+
{options?.map((option, key) => {
304+
return (
305+
<Field name={name} type="radio" value={option.value} key={key}>
306+
{({ input }) => {
307+
return (
308+
<>
309+
<CFormCheck
310+
name={input.name}
311+
checked={input.checked}
312+
onChange={input.onChange}
313+
type="radio"
314+
{...option}
315+
disabled={disabled}
316+
onClick={onClick}
317+
inline={inline}
318+
/>
319+
</>
320+
)
321+
}}
322+
</Field>
323+
)
324+
})}
325+
</div>
326+
</>
327+
)
328+
}
329+
330+
RFFCFormRadioList.propTypes = {
331+
...sharedPropTypes,
332+
inline: PropTypes.bool,
333+
}
334+
288335
export const RFFCFormTextarea = ({
289336
name,
290337
label,

src/components/forms/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
RFFCFormSwitch,
66
RFFCFormInput,
77
RFFCFormRadio,
8+
RFFCFormRadioList,
89
RFFCFormTextarea,
910
RFFCFormSelect,
1011
RFFSelectSearch,
@@ -18,6 +19,7 @@ export {
1819
RFFCFormSwitch,
1920
RFFCFormInput,
2021
RFFCFormRadio,
22+
RFFCFormRadioList,
2123
RFFCFormTextarea,
2224
RFFCFormSelect,
2325
RFFSelectSearch,

src/components/tables/CellBadge.jsx

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import PropTypes from 'prop-types'
22
import React from 'react'
3-
import { CBadge } from '@coreui/react'
3+
import { CBadge, CCol, CRow } from '@coreui/react'
44

55
export const CellBadge = ({ label = '', color = '', children, ...rest }) => {
66
//Create a case select, and return the color based on the label
@@ -19,14 +19,28 @@ export const CellBadge = ({ label = '', color = '', children, ...rest }) => {
1919
break
2020
case 'running':
2121
color = 'primary'
22+
break
2223
}
24+
//if a label contains a comma, split it, and return multiple badges, if not, return one badge. force the badges to be on their own line
2325

24-
return (
25-
<CBadge color={color} {...rest}>
26-
{label}
27-
{children}
28-
</CBadge>
29-
)
26+
if (label.includes(',')) {
27+
const labels = label.split(',')
28+
return labels.map((label, idx) => (
29+
<>
30+
<CBadge key={idx} className="me-2" color={color} {...rest}>
31+
{label}
32+
{children}
33+
</CBadge>
34+
</>
35+
))
36+
} else {
37+
return (
38+
<CBadge className="me-2" color={color} {...rest}>
39+
{label}
40+
{children}
41+
</CBadge>
42+
)
43+
}
3044
}
3145

3246
CellBadge.propTypes = {

src/components/tables/CippTable.jsx

+7-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { debounce } from 'lodash-es'
3838
import { useSearchParams } from 'react-router-dom'
3939
import CopyToClipboard from 'react-copy-to-clipboard'
4040
import { setDefaultColumns } from 'src/store/features/app'
41+
import { CippCallout } from '../layout'
4142

4243
const FilterComponent = ({ filterText, onFilter, onClear, filterlist, onFilterPreset }) => (
4344
<>
@@ -124,6 +125,7 @@ export default function CippTable({
124125
filterlist,
125126
showFilter = true,
126127
endpointName,
128+
defaultSortAsc = true,
127129
tableProps: {
128130
keyField = 'id',
129131
theme = 'cyberdrain',
@@ -614,7 +616,7 @@ export default function CippTable({
614616
className="m-1"
615617
size="sm"
616618
>
617-
<FontAwesomeIcon icon={faSync} />
619+
<FontAwesomeIcon icon={faSync} spin={isFetching} />
618620
</CButton>
619621
</CTooltip>,
620622
])
@@ -888,7 +890,7 @@ export default function CippTable({
888890
{(updatedColumns || !dynamicColumns) && (
889891
<>
890892
{(massResults.length >= 1 || loopRunning) && (
891-
<CCallout color="info">
893+
<CippCallout color="info" dismissible>
892894
{massResults[0]?.data?.Metadata?.Heading && (
893895
<CAccordion flush>
894896
{massResults.map((message, idx) => {
@@ -963,7 +965,7 @@ export default function CippTable({
963965
<CSpinner size="sm" />
964966
</li>
965967
)}
966-
</CCallout>
968+
</CippCallout>
967969
)}
968970
<DataTable
969971
customStyles={customStyles}
@@ -988,7 +990,7 @@ export default function CippTable({
988990
expandableRowsComponent={expandableRowsComponent}
989991
highlightOnHover={highlightOnHover}
990992
expandOnRowClicked={expandOnRowClicked}
991-
defaultSortAsc
993+
defaultSortAsc={defaultSortAsc}
992994
defaultSortFieldId={1}
993995
sortFunction={customSort}
994996
paginationPerPage={tablePageSize}
@@ -1049,6 +1051,7 @@ export const CippTablePropTypes = {
10491051
disableCSVExport: PropTypes.bool,
10501052
error: PropTypes.object,
10511053
filterlist: PropTypes.arrayOf(PropTypes.object),
1054+
defaultSortAsc: PropTypes.bool,
10521055
}
10531056

10541057
CippTable.propTypes = CippTablePropTypes

0 commit comments

Comments
 (0)