diff --git a/src/components/contentcards/CippAccordionItem.jsx b/src/components/contentcards/CippAccordionItem.jsx new file mode 100644 index 000000000000..98090b58c0c7 --- /dev/null +++ b/src/components/contentcards/CippAccordionItem.jsx @@ -0,0 +1,49 @@ +import React from 'react' +import { + CAccordionBody, + CAccordionHeader, + CAccordionItem, + CCard, + CCardBody, + CCardFooter, + CCardHeader, + CCardTitle, +} from '@coreui/react' +import Skeleton from 'react-loading-skeleton' +import PropTypes from 'prop-types' + +export default function CippAccordionItem({ + title, + titleType = 'normal', + CardButton, + children, + isFetching, +}) { + return ( + + {title} + + + + + {titleType === 'big' ?

{title}

: title} +
+
+ + {isFetching && } + {children} + + {CardButton} +
+
+
+ ) +} + +CippAccordionItem.propTypes = { + title: PropTypes.string.isRequired, + titleType: PropTypes.string, + CardButton: PropTypes.element.isRequired, + children: PropTypes.element.isRequired, + isFetching: PropTypes.bool.isRequired, +} diff --git a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx b/src/views/cipp/app-settings/SettingsExtensionMappings.jsx index f2deb9d187be..de3246422499 100644 --- a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx +++ b/src/views/cipp/app-settings/SettingsExtensionMappings.jsx @@ -1,12 +1,22 @@ import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app.js' -import { CButton, CCallout, CCardText, CCol, CForm, CRow, CSpinner, CTooltip } from '@coreui/react' +import { + CAccordion, + CButton, + CCallout, + CCardText, + CCol, + CForm, + CRow, + CSpinner, + CTooltip, +} from '@coreui/react' import { Form } from 'react-final-form' import { RFFSelectSearch } from 'src/components/forms/index.js' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import React, { useEffect } from 'react' import { CippCallout } from 'src/components/layout/index.js' -import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import CippAccordionItem from 'src/components/contentcards/CippAccordionItem' import { CippTable } from 'src/components/tables' import { CellTip } from 'src/components/tables/CellGenericFormat' @@ -238,400 +248,385 @@ export function SettingsExtensionMappings() { listNinjaOrgsBackend({ path: 'api/ExecExtensionMapping?List=NinjaOrgs' })} {listBackendNinjaFieldsResult.isUninitialized && listNinjaFieldsBackend({ path: 'api/ExecExtensionMapping?List=NinjaFields' })} - <> - - - - {extensionHaloConfigResult.isFetching && ( - - )} - Save Mappings - - onHaloAutomap()} className="me-2"> - {extensionNinjaOrgsAutomapResult.isFetching && ( - - )} - Automap HaloPSA Clients - - - } - > - {listBackendHaloResult.isFetching && listBackendHaloResult.isUninitialized ? ( - - ) : ( -
{ - return ( - - - Use the table below to map your client to the correct PSA client. - { - //load all the existing mappings and show them first in a table. - listBackendHaloResult.isSuccess && ( - - ) - } - - - { - return !Object.keys(listBackendHaloResult.data?.Mappings).includes( - tenant.customerId, - ) - }).map((tenant) => ({ - name: tenant.displayName, - value: tenant.customerId, - }))} - onChange={(e) => { - setMappingArray(e.value) - }} - isLoading={listBackendHaloResult.isFetching} - /> - - - - - - { - return !Object.values(listBackendHaloResult.data?.Mappings) - .map((value) => { - return value.value - }) - .includes(client.value) - }).map((client) => ({ - name: client.name, - value: client.value, - }))} - onChange={(e) => setMappingValue(e)} - placeholder="Select a HaloPSA Client" - isLoading={listBackendHaloResult.isFetching} - /> - - { - if ( - mappingValue.value !== undefined && - Object.values(haloMappingsArray) - .map((item) => item.haloId) - .includes(mappingValue.value) === false - ) { - //set the new mapping in the array - setHaloMappingsArray([ - ...haloMappingsArray, - { - Tenant: listBackendHaloResult.data?.Tenants.find( - (tenant) => tenant.customerId === mappingArray, - ), - haloName: mappingValue.label, - haloId: mappingValue.value, - }, - ]) - } + + + + {extensionHaloConfigResult.isFetching && ( + + )} + Save Mappings + + onHaloAutomap()} className="me-2"> + {extensionNinjaOrgsAutomapResult.isFetching && ( + + )} + Automap HaloPSA Clients + + + } + > + {listBackendHaloResult.isFetching && listBackendHaloResult.isUninitialized ? ( + + ) : ( + { + return ( + + + Use the table below to map your client to the correct PSA client. + { + //load all the existing mappings and show them first in a table. + listBackendHaloResult.isSuccess && ( + + ) + } + + + { + return !Object.keys(listBackendHaloResult.data?.Mappings).includes( + tenant.customerId, + ) + }).map((tenant) => ({ + name: tenant.displayName, + value: tenant.customerId, + }))} + onChange={(e) => { + setMappingArray(e.value) }} - className={`my-4 circular-button`} - title={'+'} - > - - - - - - {HaloAutoMap && ( - - Automapping has been executed. Remember to check the changes and save - them. - - )} - {(extensionHaloConfigResult.isSuccess || - extensionHaloConfigResult.isError) && - !extensionHaloConfigResult.isFetching && ( - - {extensionHaloConfigResult.isSuccess - ? extensionHaloConfigResult.data.Results - : 'Error'} - - )} - - - - After editing the mappings you must click Save Mappings for the changes to - take effect. The table will be saved exactly as presented. - - - ) - }} - /> - )} - - - - {' '} - - - {extensionNinjaOrgsConfigResult.isFetching && ( - - )} - Set Mappings - - onNinjaOrgsAutomap()} className="me-2"> - {extensionNinjaOrgsAutomapResult.isFetching && ( - - )} - Automap NinjaOne Organizations - - - } - > - {listBackendNinjaOrgsResult.isFetching && listBackendNinjaOrgsResult.isUninitialized ? ( - - ) : ( - { - return ( - - - Use the table below to map your client to the correct NinjaOne Organization. - { - //load all the existing mappings and show them first in a table. - listBackendNinjaOrgsResult.isSuccess && ( - - ) - } - - - { - return !Object.keys( - listBackendNinjaOrgsResult.data?.Mappings, - ).includes(tenant.customerId) - }).map((tenant) => ({ - name: tenant.displayName, - value: tenant.customerId, - }))} - onChange={(e) => { - setMappingArray(e.value) - }} - isLoading={listBackendNinjaOrgsResult.isFetching} - /> - - - - - - { - return !Object.values(listBackendNinjaOrgsResult.data?.Mappings) - .map((value) => { - return value.value - }) - .includes(client.value.toString()) - }, - ).map((client) => ({ - name: client.name, - value: client.value, - }))} - onChange={(e) => setMappingValue(e)} - placeholder="Select a NinjaOne Organization" - isLoading={listBackendNinjaOrgsResult.isFetching} - /> - - { + isLoading={listBackendHaloResult.isFetching} + /> + + + + + + { + return !Object.values(listBackendHaloResult.data?.Mappings) + .map((value) => { + return value.value + }) + .includes(client.value) + }).map((client) => ({ + name: client.name, + value: client.value, + }))} + onChange={(e) => setMappingValue(e)} + placeholder="Select a HaloPSA Client" + isLoading={listBackendHaloResult.isFetching} + /> + + { + if ( + mappingValue.value !== undefined && + Object.values(haloMappingsArray) + .map((item) => item.haloId) + .includes(mappingValue.value) === false + ) { //set the new mapping in the array - if ( - mappingValue.value !== undefined && - Object.values(ninjaMappingsArray) - .map((item) => item.ninjaId) - .includes(mappingValue.value) === false - ) { - setNinjaMappingsArray([ - ...ninjaMappingsArray, - { - Tenant: listBackendNinjaOrgsResult.data?.Tenants.find( - (tenant) => tenant.customerId === mappingArray, - ), - ninjaName: mappingValue.label, - ninjaId: mappingValue.value, - }, - ]) - } - }} - className={`my-4 circular-button`} - title={'+'} + setHaloMappingsArray([ + ...haloMappingsArray, + { + Tenant: listBackendHaloResult.data?.Tenants.find( + (tenant) => tenant.customerId === mappingArray, + ), + haloName: mappingValue.label, + haloId: mappingValue.value, + }, + ]) + } + }} + className={`my-4 circular-button`} + title={'+'} + > + + + + + + {HaloAutoMap && ( + + Automapping has been executed. Remember to check the changes and save + them. + + )} + {(extensionHaloConfigResult.isSuccess || extensionHaloConfigResult.isError) && + !extensionHaloConfigResult.isFetching && ( + - - - - - - {(extensionNinjaOrgsAutomapResult.isSuccess || - extensionNinjaOrgsAutomapResult.isError) && - !extensionNinjaOrgsAutomapResult.isFetching && ( - - {extensionNinjaOrgsAutomapResult.isSuccess - ? extensionNinjaOrgsAutomapResult.data.Results - : 'Error'} - - )} - {(extensionNinjaOrgsConfigResult.isSuccess || - extensionNinjaOrgsConfigResult.isError) && - !extensionNinjaOrgsConfigResult.isFetching && ( - - {extensionNinjaOrgsConfigResult.isSuccess - ? extensionNinjaOrgsConfigResult.data.Results - : 'Error'} - - )} - - - - After editing the mappings you must click Save Mappings for the changes to - take effect. The table will be saved exactly as presented. - - - ) - }} - /> - )} - - - - - {extensionNinjaFieldsConfigResult.isFetching && ( + {extensionHaloConfigResult.isSuccess + ? extensionHaloConfigResult.data.Results + : 'Error'} + + )} + + + + After editing the mappings you must click Save Mappings for the changes to + take effect. The table will be saved exactly as presented. + + + ) + }} + /> + )} + + + + {extensionNinjaOrgsConfigResult.isFetching && ( )} Set Mappings - } - > - {listBackendNinjaFieldsResult.isFetching ? ( - - ) : ( - { - return ( - - -
Organization Global Custom Field Mapping
-

- Use the table below to map your Organization Field to the correct NinjaOne - Field -

- {listBackendNinjaFieldsResult.isSuccess && - listBackendNinjaFieldsResult.data.CIPPOrgFields.map((CIPPOrgFields) => ( - item.type === CIPPOrgFields.Type || item.type === 'unset', - )} - placeholder="Select a Field" - /> - ))} -
- -
Device Custom Field Mapping
-

- Use the table below to map your Device field to the correct NinjaOne - WYSIWYG Field -

- {listBackendNinjaFieldsResult.isSuccess && - listBackendNinjaFieldsResult.data.CIPPNodeFields.map((CIPPNodeFields) => ( - - item.type === CIPPNodeFields.Type || item.type === 'unset', - )} - placeholder="Select a Field" - /> - ))} -
- - {(extensionNinjaFieldsConfigResult.isSuccess || - extensionNinjaFieldsConfigResult.isError) && - !extensionNinjaFieldsConfigResult.isFetching && ( - - {extensionNinjaFieldsConfigResult.isSuccess - ? extensionNinjaFieldsConfigResult.data.Results - : 'Error'} - - )} - -
- ) - }} - /> - )} - - - + onNinjaOrgsAutomap()} className="me-2"> + {extensionNinjaOrgsAutomapResult.isFetching && ( + + )} + Automap NinjaOne Organizations + + + } + > + {listBackendNinjaOrgsResult.isFetching && listBackendNinjaOrgsResult.isUninitialized ? ( + + ) : ( + { + return ( + + + Use the table below to map your client to the correct NinjaOne Organization. + { + //load all the existing mappings and show them first in a table. + listBackendNinjaOrgsResult.isSuccess && ( + + ) + } + + + { + return !Object.keys( + listBackendNinjaOrgsResult.data?.Mappings, + ).includes(tenant.customerId) + }).map((tenant) => ({ + name: tenant.displayName, + value: tenant.customerId, + }))} + onChange={(e) => { + setMappingArray(e.value) + }} + isLoading={listBackendNinjaOrgsResult.isFetching} + /> + + + + + + { + return !Object.values(listBackendNinjaOrgsResult.data?.Mappings) + .map((value) => { + return value.value + }) + .includes(client.value.toString()) + }).map((client) => ({ + name: client.name, + value: client.value, + }))} + onChange={(e) => setMappingValue(e)} + placeholder="Select a NinjaOne Organization" + isLoading={listBackendNinjaOrgsResult.isFetching} + /> + + { + //set the new mapping in the array + if ( + mappingValue.value !== undefined && + Object.values(ninjaMappingsArray) + .map((item) => item.ninjaId) + .includes(mappingValue.value) === false + ) { + setNinjaMappingsArray([ + ...ninjaMappingsArray, + { + Tenant: listBackendNinjaOrgsResult.data?.Tenants.find( + (tenant) => tenant.customerId === mappingArray, + ), + ninjaName: mappingValue.label, + ninjaId: mappingValue.value, + }, + ]) + } + }} + className={`my-4 circular-button`} + title={'+'} + > + + + + + + {(extensionNinjaOrgsAutomapResult.isSuccess || + extensionNinjaOrgsAutomapResult.isError) && + !extensionNinjaOrgsAutomapResult.isFetching && ( + + {extensionNinjaOrgsAutomapResult.isSuccess + ? extensionNinjaOrgsAutomapResult.data.Results + : 'Error'} + + )} + {(extensionNinjaOrgsConfigResult.isSuccess || + extensionNinjaOrgsConfigResult.isError) && + !extensionNinjaOrgsConfigResult.isFetching && ( + + {extensionNinjaOrgsConfigResult.isSuccess + ? extensionNinjaOrgsConfigResult.data.Results + : 'Error'} + + )} + + + + After editing the mappings you must click Save Mappings for the changes to + take effect. The table will be saved exactly as presented. + + + ) + }} + /> + )} +
+ + {extensionNinjaFieldsConfigResult.isFetching && ( + + )} + Set Mappings + + } + > + {listBackendNinjaFieldsResult.isFetching ? ( + + ) : ( + { + return ( + + +
Organization Global Custom Field Mapping
+

+ Use the table below to map your Organization Field to the correct NinjaOne + Field +

+ {listBackendNinjaFieldsResult.isSuccess && + listBackendNinjaFieldsResult.data.CIPPOrgFields.map((CIPPOrgFields) => ( + item.type === CIPPOrgFields.Type || item.type === 'unset', + )} + placeholder="Select a Field" + /> + ))} +
+ +
Device Custom Field Mapping
+

+ Use the table below to map your Device field to the correct NinjaOne WYSIWYG + Field +

+ {listBackendNinjaFieldsResult.isSuccess && + listBackendNinjaFieldsResult.data.CIPPNodeFields.map((CIPPNodeFields) => ( + item.type === CIPPNodeFields.Type || item.type === 'unset', + )} + placeholder="Select a Field" + /> + ))} +
+ + {(extensionNinjaFieldsConfigResult.isSuccess || + extensionNinjaFieldsConfigResult.isError) && + !extensionNinjaFieldsConfigResult.isFetching && ( + + {extensionNinjaFieldsConfigResult.isSuccess + ? extensionNinjaFieldsConfigResult.data.Results + : 'Error'} + + )} + +
+ ) + }} + /> + )} +
+ ) } diff --git a/src/views/cipp/app-settings/SettingsExtensions.jsx b/src/views/cipp/app-settings/SettingsExtensions.jsx index fc728407ded3..20ebbcee9725 100644 --- a/src/views/cipp/app-settings/SettingsExtensions.jsx +++ b/src/views/cipp/app-settings/SettingsExtensions.jsx @@ -1,6 +1,7 @@ import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app.js' import React, { useRef } from 'react' import { + CAccordion, CAlert, CButton, CCallout, @@ -21,6 +22,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import { CippCallout } from 'src/components/layout/index.js' import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import CippAccordionItem from 'src/components/contentcards/CippAccordionItem' /** * Executes various operations related to settings and extensions. @@ -105,65 +107,64 @@ export function SettingsExtensions() { {extensionConfigResult.data.Results} )} - + {Extensions.map((integration, idx) => ( - - -

{integration.helpText}

- { - return ( - - - - {integration.SettingOptions.map( - (integrationOptions, idx) => - integrationOptions.type === 'input' && ( - - - - ), - )} - {integration.SettingOptions.map( - (integrationOptions, idx) => - integrationOptions.type === 'checkbox' && ( - - - - ), - )} - - - - - ) - }} - /> -
-
+ +

{integration.helpText}

+ { + return ( + + + + {integration.SettingOptions.map( + (integrationOptions, idx) => + integrationOptions.type === 'input' && ( + + + + ), + )} + {integration.SettingOptions.map( + (integrationOptions, idx) => + integrationOptions.type === 'checkbox' && ( + + + + ), + )} + + + + + ) + }} + /> +
))} -
+ )