Skip to content

Commit 8b9e13e

Browse files
authored
Merge pull request #84 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 254d3c8 + ff0eacb commit 8b9e13e

24 files changed

+1089
-7284
lines changed

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cipp",
3-
"version": "5.2.1",
3+
"version": "5.3.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": {

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.1

src/components/forms/RFFComponents.jsx

Lines changed: 2 additions & 1 deletion
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) => {

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/tables/CellTable.jsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default function cellTable(
1111
propertyName,
1212
checkWhenZero = false,
1313
crossWhenZero = false,
14-
dangerButton = false, // Added 4th parameter for btn-danger class
14+
dangerButton = false,
1515
) {
1616
var columnProp = ''
1717
if (propertyName) {
@@ -21,10 +21,10 @@ export default function cellTable(
2121
}
2222

2323
if (!Array.isArray(columnProp) && typeof columnProp === 'object') {
24-
columnProp = Object.entries(columnProp).map((row) => {
25-
return { Name: row[0], Value: row[1] }
26-
})
27-
} else if (Array.isArray(columnProp) && typeof Object.entries(columnProp)[0][1] !== 'object') {
24+
columnProp = [columnProp]
25+
}
26+
27+
if (Array.isArray(columnProp) && typeof columnProp[0] !== 'object') {
2828
columnProp = columnProp.map((row) => {
2929
return {
3030
Value: row,
@@ -77,7 +77,6 @@ export default function cellTable(
7777
return <FontAwesomeIcon icon={faCheckCircle} className="text-success" />
7878
}
7979

80-
// Use dangerButton to determine button class
8180
const buttonClassName = dangerButton ? 'btn-danger' : ''
8281
return (
8382
<CButton

src/components/tables/CippDatatable.jsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,36 @@ export default function CippDatatable({ path, params, ...rest }) {
1414
refetch,
1515
} = useListDatatableQuery({ path, params: { $filter: graphFilter, ...params } })
1616

17+
let anonimized = false // Assuming default value is false
18+
const regex = new RegExp('^[A-Z0-9]+$')
19+
const principalNameOrUPN =
20+
data[0]?.userPrincipalName ??
21+
data[0]?.UPN ??
22+
data.Results?.[0]?.upn ??
23+
data.Results?.[0]?.userPrincipalName
24+
25+
if (principalNameOrUPN && regex.test(principalNameOrUPN)) {
26+
anonimized = true
27+
}
28+
1729
var defaultFilterText = ''
1830
if (params?.Parameters?.$filter) {
1931
defaultFilterText = 'Graph: ' + params?.Parameters?.$filter
2032
}
2133
return (
2234
<>
35+
{anonimized && (
36+
<CCallout color="info">
37+
This table might contain anonymized data. Please check this
38+
<a
39+
className="m-1"
40+
href="https://docs.cipp.app/troubleshooting/frequently-asked-questions#my-usernames-or-sites-are-guids-or-blank"
41+
>
42+
documentation link
43+
</a>
44+
to resolve this.
45+
</CCallout>
46+
)}
2347
{data?.Metadata?.Queued && <CCallout color="info">{data?.Metadata?.QueueMessage}</CCallout>}
2448
<CippTable
2549
{...rest}

src/components/tables/CippTable.jsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export default function CippTable({
155155
const [filterviaURL, setFilterviaURL] = React.useState(false)
156156
const [originalColumns, setOrginalColumns] = React.useState(columns)
157157
const [updatedColumns, setUpdatedColumns] = React.useState(columns)
158-
if (defaultColumns && defaultColumnsSet === false) {
158+
if (defaultColumns && defaultColumnsSet === false && endpointName) {
159159
const defaultColumnsArray = defaultColumns.split(',').filter((item) => item)
160160

161161
const actionsColumn = columns.length > 0 ? columns[columns.length - 1] : null
@@ -180,11 +180,13 @@ export default function CippTable({
180180
let newColumns = tempColumns.filter(
181181
(column) => defaultColumnsArray.includes(column.exportSelector) || column === actionsColumn,
182182
)
183-
184183
setUpdatedColumns(newColumns)
185184
setDefaultColumnsSet(true)
186185
}
187-
186+
if (!endpointName && defaultColumnsSet === false) {
187+
setUpdatedColumns(columns)
188+
setDefaultColumnsSet(true)
189+
}
188190
const [selectedRows, setSelectedRows] = React.useState(false)
189191
const [genericGetRequest, getResults] = useLazyGenericGetRequestQuery()
190192
const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
@@ -342,10 +344,12 @@ export default function CippTable({
342344
useEffect(() => {
343345
if (columns.length !== updatedColumns.length) {
344346
setUpdatedColumns(updatedColumns)
345-
setColumnDefaultLayout(
346-
endpointName,
347-
updatedColumns.map((column) => column.exportSelector).join(','),
348-
)
347+
if (endpointName) {
348+
setColumnDefaultLayout(
349+
endpointName,
350+
updatedColumns.map((column) => column.exportSelector).join(','),
351+
)
352+
}
349353
}
350354
}, [
351355
columns,
@@ -971,7 +975,7 @@ export default function CippTable({
971975
responsive={responsive}
972976
dense={dense}
973977
striped={striped}
974-
columns={updatedColumns}
978+
columns={dynamicColumns ? updatedColumns : columns}
975979
data={filteredItems}
976980
expandableRows={expandableRows}
977981
expandableRowsComponent={expandableRowsComponent}

src/components/utilities/CippActionsOffcanvas.jsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,10 @@ export default function CippActionsOffcanvas(props) {
215215
cardContent = props.cards.map((action, index) => (
216216
<>
217217
<CCard key={index} className="border-top-dark border-top-3 mb-3">
218-
<CCardBody>
218+
<CCardHeader className="d-flex justify-content-between align-items-center">
219219
<CCardTitle>Report Name: {action.label}</CCardTitle>
220+
</CCardHeader>
221+
<CCardBody>
220222
<CCardText>
221223
{action.value && <Link to={action.link}>Status: {action.value}</Link>}
222224
</CCardText>
@@ -325,15 +327,16 @@ export default function CippActionsOffcanvas(props) {
325327
{getResults.isError && (
326328
<CCallout color="danger">Could not connect to API: {getResults.error.message}</CCallout>
327329
)}
328-
329-
<CCard className="content-card">
330-
<CCardHeader className="d-flex justify-content-between align-items-center">
331-
<CCardTitle>
332-
<FontAwesomeIcon icon={faGlobe} className="mx-2" /> Extended Information
333-
</CCardTitle>
334-
</CCardHeader>
335-
<CCardBody>{extendedInfoContent}</CCardBody>
336-
</CCard>
330+
{!cardContent && (
331+
<CCard className="content-card">
332+
<CCardHeader className="d-flex justify-content-between align-items-center">
333+
<CCardTitle>
334+
<FontAwesomeIcon icon={faGlobe} className="mx-2" /> Extended Information
335+
</CCardTitle>
336+
</CCardHeader>
337+
<CCardBody>{extendedInfoContent}</CCardBody>
338+
</CCard>
339+
)}
337340
{cardContent && cardContent}
338341
{<COffcanvasTitle>Actions</COffcanvasTitle>}
339342
<CListGroup>

0 commit comments

Comments
 (0)