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

[pull] dev from KelvinTegelaar:dev #32

Merged
merged 16 commits into from
Sep 5, 2023
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
417 changes: 397 additions & 20 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@
"@fortawesome/free-regular-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.16",
"@monaco-editor/react": "^4.5.2",
"@popperjs/core": "^2.10.2",
"@reduxjs/toolkit": "^1.7.0",
"@rjsf/core": "^5.12.1",
"@rjsf/utils": "^5.12.1",
"@rjsf/validator-ajv8": "^5.12.1",
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.3",
"axios": "^0.24.0",
"buffer": "^6.0.3",
Expand Down
4 changes: 4 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import Skeleton from 'react-loading-skeleton'
import TimeAgo from 'javascript-time-ago'
import en from 'javascript-time-ago/locale/en.json'
TimeAgo.addDefaultLocale(en)
import { library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/free-solid-svg-icons'

library.add(fas)

// Containers
const DefaultLayout = React.lazy(() => import('./layout/DefaultLayout'))
Expand Down
5 changes: 5 additions & 0 deletions src/_nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ const _nav = [
name: 'Individual Domain Check',
to: '/tenant/standards/individual-domains',
},
{
component: CNavItem,
name: 'BPA Field Builder',
to: '/tenant/tools/bpa-field-builder',
},
],
},
{
Expand Down
15 changes: 11 additions & 4 deletions src/components/header/AppHeaderDropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,30 @@ const AppHeaderDropdown = () => {
const [profileVisible, setProfileVisible] = useState(false)
const [cippQueueExtendedInfo, setCippQueueExtendedInfo] = useState([])
const [cippQueueVisible, setCippQueueVisible] = useState(false)
const [cippQueueRefresh, setCippQueueRefresh] = useState('')
const [cippQueueRefresh, setCippQueueRefresh] = useState(
(Math.random() + 1).toString(36).substring(7),
)
const { data: profile } = authApi.endpoints.loadClientPrincipal.useQueryState()

const [getCippQueueList, cippQueueList] = useLazyGenericGetRequestQuery()

function loadCippQueue() {
setCippQueueVisible(true)
getCippQueueList({ path: 'api/ListCippQueue', params: { refresh: cippQueueRefresh } })
}

function refreshCippQueue() {
setCippQueueRefresh((Math.random() + 1).toString(36).substring(7))
getCippQueueList({ path: `api/ListCippQueue?refresh=${cippQueueRefresh}` })
loadCippQueue()
}

useEffect(() => {
if (cippQueueList.isFetching) {
if (cippQueueList.isFetching || cippQueueList.isLoading) {
setCippQueueExtendedInfo([
{
label: 'Fetching recent jobs',
value: 'Please wait',
timpestamp: Date(),
timestamp: Date(),
link: '#',
},
])
Expand Down Expand Up @@ -101,6 +107,7 @@ const AppHeaderDropdown = () => {
title="Recent Jobs"
extendedInfo={[]}
cards={cippQueueExtendedInfo}
refreshFunction={refreshCippQueue}
actions={[
{
label: 'Clear History',
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/AppFooter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import netfriends from 'src/assets/images/netfriends.png'
//todo: Add darkmode detection and change logos accordingly.
const AppFooter = () => {
return (
<CFooter className="d-flex justify-content-between align-items-center">
<CFooter className="d-flex justify-content-between align-items-center" position="sticky">
<div className="sponsors">
<p>
This application is sponsored by{' '}
Expand Down
25 changes: 25 additions & 0 deletions src/components/tables/CellDelegatedPrivilege.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import PropTypes from 'prop-types'
import { CellBadge } from './CellBadge'

export function CellDelegatedPrivilege({ cell }) {
if (!cell) {
return <CellBadge color="info" label="DAP" />
}
if (cell.toLowerCase() == 'none') {
return <CellBadge color="info" label="No Access" />
}
if (cell === 'delegatedAdminPrivileges') {
return <CellBadge color="info" label="DAP Only" />
}
if (cell === 'delegatedAndGranularDelegetedAdminPrivileges') {
return <CellBadge color="info" label="GDAP & DAP" />
}
if (cell === 'granularDelegatedAdminPrivileges') {
return <CellBadge color="info" label="GDAP" />
}
return <CellBadge color="info" label="Unknown" />
}

CellDelegatedPrivilege.propTypes = {
cell: PropTypes.string,
}
2 changes: 2 additions & 0 deletions src/components/tables/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CellDate, cellDateFormatter } from 'src/components/tables/CellDate'
import { CellTip, CellTipButton, CellTipIcon } from 'src/components/tables/CellTip'
import { CellNullText, cellNullTextFormatter } from 'src/components/tables/CellNullText'
import { CellProgressBar, cellProgressBarFormatter } from 'src/components/tables/CellProgressBar'
import { CellDelegatedPrivilege } from './CellDelegatedPrivilege'
import CippDatatable from 'src/components/tables/CippDatatable'
import CippOffcanvasTable from 'src/components/tables/CippOffcanvasTable'
import CippTable from 'src/components/tables/CippTable'
Expand All @@ -27,4 +28,5 @@ export {
CippOffcanvasTable,
CippTable,
WizardTableField,
CellDelegatedPrivilege,
}
3 changes: 2 additions & 1 deletion src/components/utilities/CippActionsOffcanvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export default function CippActionsOffcanvas(props) {
try {
cardContent = props.cards.map((action, index) => (
<>
<CCard className="border-top-dark border-top-3 mb-3">
<CCard key={index} className="border-top-dark border-top-3 mb-3">
<CCardBody>
<CCardTitle>Report Name: {action.label}</CCardTitle>
<CCardText>
Expand Down Expand Up @@ -178,6 +178,7 @@ export default function CippActionsOffcanvas(props) {
visible={props.visible}
id={props.id}
hideFunction={props.hideFunction}
refreshFunction={props.refreshFunction}
>
{getResults.isFetching && (
<CCallout color="info">
Expand Down
21 changes: 18 additions & 3 deletions src/components/utilities/CippOffcanvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,23 @@ export default function CippOffcanvas(props) {
>
<COffcanvasHeader>
<h2>{props.title}</h2>
<CButton className="cipp-offcanvas-close" color="link" onClick={props.hideFunction}>
<FontAwesomeIcon size="lg" icon={faTimes} color="link" />
</CButton>
<span>
{props.refreshFunction && (
<CButton
color="link"
size="lg"
onClick={() => {
console.log('refresh')
props.refreshFunction()
}}
>
<FontAwesomeIcon icon="sync" />
</CButton>
)}
<CButton className="cipp-offcanvas-close" color="link" onClick={props.hideFunction}>
<FontAwesomeIcon size="lg" icon={faTimes} color="link" />
</CButton>
</span>
</COffcanvasHeader>
<COffcanvasBody>{props.children}</COffcanvasBody>
</COffcanvas>
Expand All @@ -33,6 +47,7 @@ export const CippOffcanvasPropTypes = {
visible: PropTypes.bool,
id: PropTypes.string.isRequired,
hideFunction: PropTypes.func.isRequired,
refreshFunction: PropTypes.func,
}

CippOffcanvas.propTypes = CippOffcanvasPropTypes
106 changes: 106 additions & 0 deletions src/components/utilities/CippTenantOffcanvas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React, { useState } from 'react'
import { CButton, CTooltip } from '@coreui/react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faEdit, faEllipsisV, faBuilding } from '@fortawesome/free-solid-svg-icons'
import { CippActionsOffcanvas } from 'src/components/utilities'
import { useLazyGenericGetRequestQuery } from 'src/store/api/app'
import Skeleton from 'react-loading-skeleton'
import Portals from 'src/data/portals'

export const CippTenantOffcanvasRow = (row, rowIndex, formatExtraData) => {
const tenant = row
return CippTenantOffcanvas({ tenant: row })
}

function CippTenantOffcanvas({ tenant, buildingIcon = false }) {
const [getTenantDetails, tenantDetails] = useLazyGenericGetRequestQuery()
const [ocVisible, setOCVisible] = useState(false)
function loadOffCanvasDetails(domainName) {
setOCVisible(true)
getTenantDetails({ path: `api/ListTenantDetails?tenantfilter=${domainName}` })
}

function tenantProperty(tenantDetails, propertyName) {
return (
<>
{tenantDetails.isFetching && <Skeleton count={1} width={150} />}
{!tenantDetails.isFetching &&
tenantDetails.isSuccess &&
(tenantDetails.data[propertyName]?.toString() ?? ' ')}
</>
)
}
const actions = Portals.map((portal) => ({
icon: <FontAwesomeIcon icon={portal.icon} className="me-2" />,
label: portal.label,
external: true,
color: 'info',
link: portal.url.replace(portal.variable, tenant[portal.variable]),
}))
return (
<>
<CTooltip placement="bottom" content="Tenant Information">
<CButton
size="sm"
variant="ghost"
onClick={() => loadOffCanvasDetails(tenant.defaultDomainName)}
>
<FontAwesomeIcon icon={buildingIcon ? faBuilding : faEllipsisV} />
</CButton>
</CTooltip>
<CippActionsOffcanvas
title="Tenant Information"
extendedInfo={[
{
label: 'Display Name',
value: tenantProperty(tenantDetails, 'displayName'),
},
{
label: 'Business Phones',
value: tenantProperty(tenantDetails, 'businessPhones'),
},
{
label: 'Technical Emails',
value: tenantProperty(tenantDetails, 'technicalNotificationMails'),
},
{
label: 'Tenant Type',
value: tenantProperty(tenantDetails, 'tenantType'),
},
{
label: 'Created',
value: tenantProperty(tenantDetails, 'createdDateTime'),
},
{
label: 'AD Connect Enabled',
value: tenantProperty(tenantDetails, 'onPremisesSyncEnabled'),
},
{
label: 'AD Connect Sync',
value: tenantProperty(tenantDetails, 'onPremisesLastSyncDateTime'),
},
{
label: 'AD Password Sync',
value: tenantProperty(tenantDetails, 'onPremisesLastPasswordSyncDateTime'),
},
]}
actions={[
{
id: 'edittenant',
icon: <FontAwesomeIcon icon={faEdit} className="me-2" />,
label: 'Edit Tenant',
link: `/tenant/administration/tenants/Edit?tenantFilter=${tenant.defaultDomainName}&customerId=${tenant.customerId}`,
color: 'warning',
},
...actions,
]}
placement="end"
visible={ocVisible}
id={tenant.id}
hideFunction={() => setOCVisible(false)}
/>
</>
)
}

export default CippTenantOffcanvas
60 changes: 33 additions & 27 deletions src/components/utilities/TenantSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useNavigate, useSearchParams } from 'react-router-dom'
import { queryString } from 'src/helpers'
import { faBuilding } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import CippTenantOffcanvas from './CippTenantOffcanvas'

const TenantSelector = ({ action, showAllTenantSelector = true, NavSelector = false }) => {
const currentTenant = useSelector((state) => state.app.currentTenant)
Expand Down Expand Up @@ -57,7 +58,6 @@ const TenantSelector = ({ action, showAllTenantSelector = true, NavSelector = fa
return t.customerId === customerId
})
dispatch(setCurrentTenant({ tenant: selectedTenant[0] }))

if (typeof action === 'function') {
action(selectedTenant[0])
} else {
Expand All @@ -75,32 +75,38 @@ const TenantSelector = ({ action, showAllTenantSelector = true, NavSelector = fa
return (
<>
{NavSelector && (
<CDropdown component="li" variant="nav-item" className="flex-grow-1 my-auto">
<CDropdownToggle>
<FontAwesomeIcon icon={faBuilding} className="me-2" />
{currentTenant?.defaultDomainName ? (
<>
<span className="text-wrap">{currentTenant.displayName}</span>
</>
) : (
placeholder
)}
</CDropdownToggle>
<CDropdownMenu className="tenantDropdown">
<SelectSearch
search
onChange={activated}
filterOptions={fuzzySearch}
placeholder={placeholder}
disabled={isLoading}
value={currentTenant && currentTenant.customerId}
options={tenants.map(({ customerId, displayName, defaultDomainName }) => ({
value: customerId,
name: [displayName] + [` (${defaultDomainName})`],
}))}
/>
</CDropdownMenu>
</CDropdown>
<>
<CDropdown component="li" variant="nav-item" className="flex-grow-1 my-auto">
<CDropdownToggle>
{currentTenant?.customerId !== 'AllTenants' ? (
<CippTenantOffcanvas tenant={currentTenant} buildingIcon={true} />
) : (
<FontAwesomeIcon icon={faBuilding} className="mx-2" />
)}
{currentTenant?.defaultDomainName ? (
<>
<span className="text-wrap ms-2">{currentTenant.displayName}</span>
</>
) : (
placeholder
)}
</CDropdownToggle>
<CDropdownMenu className="tenantDropdown">
<SelectSearch
search
onChange={activated}
filterOptions={fuzzySearch}
placeholder={placeholder}
disabled={isLoading}
value={currentTenant && currentTenant.customerId}
options={tenants.map(({ customerId, displayName, defaultDomainName }) => ({
value: customerId,
name: [displayName] + [` (${defaultDomainName})`],
}))}
/>
</CDropdownMenu>
</CDropdown>
</>
)}
{!NavSelector && (
<SelectSearch
Expand Down
Loading