Skip to content

Commit 17c4c2d

Browse files
authored
Merge branch 'KelvinTegelaar:main' into main
2 parents fd4fa33 + 5b71920 commit 17c4c2d

Some content is hidden

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

53 files changed

+4665
-3743
lines changed

package-lock.json

Lines changed: 1464 additions & 1278 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cipp",
3-
"version": "4.5.5",
3+
"version": "5.2.1",
44
"description": "The CyberDrain Improved Partner Portal is a portal to help manage administration for Microsoft Partners.",
55
"homepage": "https://cipp.app/",
66
"bugs": {
@@ -31,11 +31,11 @@
3131
"@coreui/react": "^4.11.0",
3232
"@coreui/react-chartjs": "^2.1.3",
3333
"@coreui/utils": "^1.3.1",
34-
"@fortawesome/fontawesome-svg-core": "^1.2.36",
35-
"@fortawesome/free-brands-svg-icons": "^5.15.4",
36-
"@fortawesome/free-regular-svg-icons": "^5.15.4",
37-
"@fortawesome/free-solid-svg-icons": "^5.15.4",
38-
"@fortawesome/react-fontawesome": "^0.1.16",
34+
"@fortawesome/fontawesome-svg-core": "^6.5.1",
35+
"@fortawesome/free-brands-svg-icons": "^6.5.1",
36+
"@fortawesome/free-regular-svg-icons": "^6.5.1",
37+
"@fortawesome/free-solid-svg-icons": "^6.5.1",
38+
"@fortawesome/react-fontawesome": "^0.2.0",
3939
"@monaco-editor/react": "^4.5.2",
4040
"@popperjs/core": "^2.10.2",
4141
"@reduxjs/toolkit": "^1.9.7",

public/version_latest.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5.2.1
1+
5.3.0

src/adminRoutes.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react'
2-
const CIPPSettings = React.lazy(() => import('src/views/cipp/CIPPSettings'))
2+
3+
const CIPPSettings = React.lazy(() => import('src/views/cipp/app-settings/CIPPSettings'))
34
const Setup = React.lazy(() => import('src/views/cipp/Setup'))
45
const ApplyStandard = React.lazy(() => import('src/views/tenant/standards/ListStandards'))
56
const GDAPStatus = React.lazy(() => import('src/views/tenant/administration/ListGDAPQueue'))
@@ -25,7 +26,11 @@ const adminRoutes = [
2526
{ path: '/cipp/setup', name: 'Setup', component: Setup },
2627

2728
{ path: '/tenant/administration/gdap', name: 'GDAP Wizard', component: GDAP },
28-
{ path: '/tenant/administration/gdap-invite', name: 'GDAP Invite Wizard', component: GDAPInvite },
29+
{
30+
path: '/tenant/administration/gdap-invite',
31+
name: 'GDAP Invite Wizard',
32+
component: GDAPInvite,
33+
},
2934
{
3035
path: '/tenant/administration/gdap-role-wizard',
3136
name: 'GDAP Role Wizard',
@@ -41,9 +46,21 @@ const adminRoutes = [
4146
name: 'GDAP Relationships',
4247
component: GDAPRelationships,
4348
},
44-
{ path: '/tenant/administration/appapproval', name: 'App Approval', component: appapproval },
45-
{ path: '/tenant/administration/gdap-status', name: 'GDAP Status', component: GDAPStatus },
46-
{ path: '/tenant/standards/list-standards', name: 'List Standard', component: ApplyStandard },
49+
{
50+
path: '/tenant/administration/appapproval',
51+
name: 'App Approval',
52+
component: appapproval,
53+
},
54+
{
55+
path: '/tenant/administration/gdap-status',
56+
name: 'GDAP Status',
57+
component: GDAPStatus,
58+
},
59+
{
60+
path: '/tenant/standards/list-standards',
61+
name: 'List Standard',
62+
component: ApplyStandard,
63+
},
4764
{
4865
path: '/tenant/administration/tenant-offboarding-wizard',
4966
name: 'Tenant Offboarding',

src/components/forms/RFFComponents.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,11 @@ export const RFFCFormInput = ({
138138
disabled = false,
139139
spellCheck = true,
140140
autoFocus = false,
141+
hiddenValue,
141142
onChange,
142143
}) => {
143144
return (
144-
<Field name={name} validate={validate}>
145+
<Field initialValue={hiddenValue} name={name} validate={validate}>
145146
{({ input, meta }) => {
146147
const handleChange = onChange
147148
? (e) => {
@@ -429,7 +430,12 @@ export const RFFSelectSearch = ({
429430
{label}
430431
{refreshFunction && (
431432
<CTooltip content="Refresh" placement="right">
432-
<CButton onClick={refreshFunction} variant="ghost" className="ms-1" size="sm">
433+
<CButton
434+
onClick={refreshFunction}
435+
variant="ghost"
436+
className="ms-1 py-0 border-0"
437+
size="sm"
438+
>
433439
<FontAwesomeIcon icon="sync" />
434440
</CButton>
435441
</CTooltip>

src/components/header/AppHeaderSearch.jsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useCallback } from 'react'
22
import { faSearch } from '@fortawesome/free-solid-svg-icons'
33
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
44
import { toggleSwitcher } from 'src/store/features/switcher'
5-
import { CButton } from '@coreui/react'
5+
import { CButton, CTooltip } from '@coreui/react'
66
import { useDispatch } from 'react-redux'
77

88
const AppHeaderSearch = () => {
@@ -12,9 +12,11 @@ const AppHeaderSearch = () => {
1212
}, [dispatch])
1313
return (
1414
<>
15-
<CButton variant="ghost" onClick={handleFastSwitcher}>
16-
<FontAwesomeIcon icon={faSearch} size="lg" />
17-
</CButton>
15+
<CTooltip content="Search" placement="bottom">
16+
<CButton variant="ghost" onClick={handleFastSwitcher}>
17+
<FontAwesomeIcon icon={faSearch} size="lg" />
18+
</CButton>
19+
</CTooltip>
1820
</>
1921
)
2022
}

src/components/layout/AppHeader.jsx

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,25 @@ import { useSelector, useDispatch } from 'react-redux'
33
import {
44
CAlert,
55
CAlertLink,
6-
CContainer,
7-
CCollapse,
86
CHeader,
97
CHeaderNav,
108
CNavItem,
119
CHeaderToggler,
12-
CImage,
13-
CSidebarBrand,
1410
CButton,
1511
CFormSwitch,
12+
CTooltip,
1613
} from '@coreui/react'
1714
import { AppHeaderSearch } from 'src/components/header'
18-
import { TenantSelector } from '../utilities'
15+
import { CippActionsOffcanvas, TenantSelector } from '../utilities'
1916
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
2017
import { faBars } from '@fortawesome/free-solid-svg-icons'
2118
import { setCurrentTheme, setUserSettings, toggleSidebarShow } from 'src/store/features/app'
2219
import { useMediaPredicate } from 'react-media-hook'
23-
import { useGenericGetRequestQuery, useLoadAlertsDashQuery } from 'src/store/api/app'
20+
import {
21+
useGenericGetRequestQuery,
22+
useLazyGenericGetRequestQuery,
23+
useLoadAlertsDashQuery,
24+
} from 'src/store/api/app'
2425
import { useLocation } from 'react-router-dom'
2526

2627
const AppHeader = () => {
@@ -31,6 +32,11 @@ const AppHeader = () => {
3132
const sidebarShow = useSelector((state) => state.app.sidebarShow)
3233
const currentTheme = useSelector((state) => state.app.currentTheme)
3334
const preferredTheme = useMediaPredicate('(prefers-color-scheme: dark)') ? 'impact' : 'cyberdrain'
35+
const [cippQueueExtendedInfo, setCippQueueExtendedInfo] = useState([])
36+
const [cippQueueVisible, setCippQueueVisible] = useState(false)
37+
const [cippQueueRefresh, setCippQueueRefresh] = useState(
38+
(Math.random() + 1).toString(36).substring(7),
39+
)
3440
const { data: dashboard } = useLoadAlertsDashQuery()
3541
const {
3642
data: userSettings,
@@ -54,6 +60,49 @@ const AppHeader = () => {
5460
userSettings,
5561
])
5662

63+
const [getCippQueueList, cippQueueList] = useLazyGenericGetRequestQuery()
64+
65+
function loadCippQueue() {
66+
setCippQueueVisible(true)
67+
getCippQueueList({ path: 'api/ListCippQueue', params: { refresh: cippQueueRefresh } })
68+
}
69+
70+
function refreshCippQueue() {
71+
setCippQueueRefresh((Math.random() + 1).toString(36).substring(7))
72+
loadCippQueue()
73+
}
74+
75+
useEffect(() => {
76+
if (cippQueueList.isFetching || cippQueueList.isLoading) {
77+
setCippQueueExtendedInfo([
78+
{
79+
label: 'Fetching recent jobs',
80+
value: 'Please wait',
81+
timestamp: Date(),
82+
link: '#',
83+
},
84+
])
85+
}
86+
if (
87+
cippQueueList.isSuccess &&
88+
Array.isArray(cippQueueList.data) &&
89+
cippQueueList.data.length > 0
90+
) {
91+
setCippQueueExtendedInfo(
92+
cippQueueList.data?.map((job) => ({
93+
label: `${job.Name}`,
94+
value: job.Status,
95+
link: job.Link,
96+
timestamp: job.Timestamp,
97+
})),
98+
)
99+
} else {
100+
setCippQueueExtendedInfo([
101+
{ label: 'No jobs to display', value: '', timpestamp: Date(), link: '#' },
102+
])
103+
}
104+
}, [cippQueueList])
105+
57106
const SwitchTheme = () => {
58107
let targetTheme = preferredTheme
59108
if (isDark) {
@@ -89,14 +138,23 @@ const AppHeader = () => {
89138
target="_blank"
90139
href={`https://docs.cipp.app/user-documentation${location.pathname}`}
91140
>
92-
<CButton variant="ghost">
93-
<FontAwesomeIcon icon={'question'} size="lg" />
94-
</CButton>
141+
<CTooltip content="Documentation" placement="bottom">
142+
<CButton variant="ghost">
143+
<FontAwesomeIcon icon={'question'} size="lg" />
144+
</CButton>
145+
</CTooltip>
95146
</a>
96147
</CNavItem>
97148
<CNavItem>
98149
<AppHeaderSearch />
99150
</CNavItem>
151+
<CNavItem>
152+
<CTooltip content="Recent Jobs" placement="bottom">
153+
<CButton variant="ghost" onClick={() => loadCippQueue()} className="me-1">
154+
<FontAwesomeIcon icon={'history'} size="lg" />
155+
</CButton>
156+
</CTooltip>
157+
</CNavItem>
100158
<CNavItem>
101159
<div className="custom-switch-wrapper primary">
102160
<CFormSwitch
@@ -134,6 +192,26 @@ const AppHeader = () => {
134192
</div>
135193
))}
136194
</div>
195+
<CippActionsOffcanvas
196+
title="Recent Jobs"
197+
extendedInfo={[]}
198+
cards={cippQueueExtendedInfo}
199+
refreshFunction={refreshCippQueue}
200+
actions={[
201+
{
202+
label: 'Clear History',
203+
color: 'info',
204+
modal: true,
205+
modalUrl: `/api/RemoveCippQueue`,
206+
modalMessage: 'Are you sure you want clear the history?',
207+
icon: <FontAwesomeIcon icon="trash" className="me-2" />,
208+
},
209+
]}
210+
placement="end"
211+
visible={cippQueueVisible}
212+
id="cipp-queue"
213+
hideFunction={() => setCippQueueVisible(false)}
214+
/>
137215
</>
138216
)
139217
}

src/components/layout/AppSidebarNav.jsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const AppSidebarNav = ({ items }) => {
6565
)
6666
}
6767
const navGroup = (item, index) => {
68-
const { component, name, icon, to, ...rest } = item
68+
const { component, name, icon, to, items, ...rest } = item
6969
const Component = component
7070
const navGroupKey = `${item.name.toLowerCase().replace(' ', '-')}_${index}`
7171
const navGroupIdx = `${item.section.toLowerCase().replace(' ', '-')}_${item.name
@@ -79,9 +79,7 @@ export const AppSidebarNav = ({ items }) => {
7979
visible={location.pathname.startsWith(to)}
8080
{...rest}
8181
>
82-
{item.items?.map((item, index) =>
83-
item.items ? navGroup(item, index) : navItem(item, index),
84-
)}
82+
{items?.map((item, index) => (item.items ? navGroup(item, index) : navItem(item, index)))}
8583
</Component>
8684
)
8785
}

src/components/layout/CippCallout.css

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.cipp-callout {
2+
--cui-callout-padding-x: 1rem;
3+
--cui-callout-padding-y: 1rem;
4+
--cui-callout-border-width: var(--cui-border-width);
5+
--cui-callout-border-color: var(--cui-border-color);
6+
--cui-callout-border-left-width: calc(var(--cui-border-width) * 4);
7+
--cui-callout-border-radius: var(--cui-border-radius);
8+
border: var(--cui-callout-border-width) solid var(--cui-callout-border-color);
9+
border-radius: var(--cui-callout-border-radius);
10+
margin-bottom: 16px;
11+
padding: var(--cui-callout-padding-y) var(--cui-callout-padding-x);
12+
}
13+
14+
html:not([dir=rtl]) .cipp-callout {
15+
border-left-color: var(--cui-callout-border-left-color);
16+
}
17+
18+
html:not([dir=rtl]) .cipp-callout {
19+
border-left-width: var(--cui-callout-border-left-width);
20+
}
21+
22+
html:not([dir=rtl]) .cipp-callout-dismissible .btn {
23+
right: 0;
24+
}
25+
26+
.cipp-callout-dismissible .btn {
27+
cursor: pointer;
28+
}

src/components/layout/CippCallout.jsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React, { useState } from 'react'
2+
import { CAlert, CCallout } from '@coreui/react'
3+
import PropTypes from 'prop-types'
4+
import './CippCallout.css'
5+
import classNames from 'classnames'
6+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
7+
import { faXmark } from '@fortawesome/free-solid-svg-icons'
8+
9+
export function CippCallout({
10+
dismissible = false,
11+
color = 'primary',
12+
children = null,
13+
className = '',
14+
style = {},
15+
...rest
16+
}) {
17+
const [open, setOpen] = useState(true)
18+
19+
if (!open) {
20+
return null
21+
}
22+
23+
return (
24+
<div
25+
className={classNames(className, 'cipp-callout', `callout-${color}`, {
26+
'cipp-callout-dismissible': dismissible,
27+
})}
28+
color={color}
29+
style={{
30+
backgroundColor: 'rgb(var(--cui-body-color-rgb))',
31+
color: 'var(--cui-body-color)',
32+
display: 'flex',
33+
justifyContent: 'space-between',
34+
alignItems: 'flex-start',
35+
...style,
36+
}}
37+
{...rest}
38+
>
39+
<div>{children}</div>
40+
{dismissible && (
41+
<button
42+
type="button"
43+
className="btn"
44+
aria-label="Close"
45+
onClick={() => setOpen(false)}
46+
style={{ padding: 0, margin: 0 }}
47+
>
48+
<FontAwesomeIcon icon={faXmark} size={'xl'} />
49+
</button>
50+
)}
51+
</div>
52+
)
53+
}
54+
55+
CippCallout.propTypes = {
56+
dismissible: PropTypes.bool,
57+
color: PropTypes.oneOf([
58+
'primary',
59+
'secondary',
60+
'success',
61+
'warning',
62+
'danger',
63+
'info',
64+
'light',
65+
'dark',
66+
]),
67+
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
68+
className: PropTypes.string,
69+
style: PropTypes.object,
70+
}

0 commit comments

Comments
 (0)