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 #40

Merged
merged 14 commits into from
May 29, 2024
2 changes: 0 additions & 2 deletions src/components/forms/RFFComponents.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ export const RFFCFormRadioList = ({
name,
options,
className = 'mb-3',
disabled = false,
onClick,
inline = false,
}) => {
Expand All @@ -312,7 +311,6 @@ export const RFFCFormRadioList = ({
onChange={input.onChange}
type="radio"
{...option}
disabled={disabled}
onClick={onClick}
inline={inline}
/>
Expand Down
9 changes: 7 additions & 2 deletions src/components/utilities/CippListOffcanvas.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ CippListOffcanvas.propTypes = {
hideFunction: PropTypes.func.isRequired,
}

export function OffcanvasListSection({ title, items }) {
export function OffcanvasListSection({ title, items, showCardTitle = true }) {
//console.log(items)
const mappedItems = items.map((item, key) => ({ value: item.content, label: item.heading }))
return (
Expand All @@ -48,7 +48,11 @@ export function OffcanvasListSection({ title, items }) {
<CCard className="content-card">
<CCardHeader className="d-flex justify-content-between align-items-center">
<CCardTitle>
<FontAwesomeIcon icon={faGlobe} className="mx-2" /> Extended Information
{showCardTitle && (
<>
<FontAwesomeIcon icon={faGlobe} className="mx-2" /> Extended Information
</>
)}
</CCardTitle>
</CCardHeader>
<CCardBody>
Expand All @@ -62,4 +66,5 @@ export function OffcanvasListSection({ title, items }) {
OffcanvasListSection.propTypes = {
title: PropTypes.string,
items: PropTypes.array,
showCardTitle: PropTypes.bool,
}
276 changes: 276 additions & 0 deletions src/components/utilities/CippScheduleOffcanvas.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import {
CButton,
CCallout,
CCard,
CCardBody,
CCardHeader,
CCol,
CForm,
CRow,
CSpinner,
CTooltip,
} from '@coreui/react'
import { CippOffcanvas, TenantSelector } from '.'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { Field, Form, FormSpy } from 'react-final-form'
import arrayMutators from 'final-form-arrays'
import {
RFFCFormInput,
RFFCFormInputArray,
RFFCFormSwitch,
RFFSelectSearch,
} from 'src/components/forms'
import { useSelector } from 'react-redux'
import { useGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app'
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'

export default function CippScheduleOffcanvas({
state: visible,
hideFunction,
title,
placement,
...props
}) {
const currentDate = new Date()
const [startDate, setStartDate] = useState(currentDate)
const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName)
const [refreshState, setRefreshState] = useState(false)
const taskName = `Scheduled Task ${currentDate.toLocaleString()}`
const { data: availableCommands = [], isLoading: isLoadingcmd } = useGenericGetRequestQuery({
path: 'api/ListFunctionParameters?Module=CIPPCore',
})

const recurrenceOptions = [
{ value: '0', name: 'Only once' },
{ value: '1', name: 'Every 1 day' },
{ value: '7', name: 'Every 7 days' },
{ value: '30', name: 'Every 30 days' },
{ value: '365', name: 'Every 365 days' },
]

const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
const onSubmit = (values) => {
const unixTime = Math.floor(startDate.getTime() / 1000)
const shippedValues = {
TenantFilter: tenantDomain,
Name: values.taskName,
Command: values.command,
Parameters: values.parameters,
ScheduledTime: unixTime,
Recurrence: values.Recurrence,
AdditionalProperties: values.additional,
PostExecution: {
Webhook: values.webhook,
Email: values.email,
PSA: values.psa,
},
}
genericPostRequest({ path: '/api/AddScheduledItem', values: shippedValues }).then((res) => {
setRefreshState(res.requestId)
if (props.submitFunction) {
props.submitFunction()
}
})
}

return (
<CippOffcanvas
placement={placement}
title={title}
visible={visible}
hideFunction={hideFunction}
>
<CCard>
<CCardHeader></CCardHeader>
<CCardBody>
<Form
onSubmit={onSubmit}
mutators={{
...arrayMutators,
}}
initialValues={{ ...props.initialValues }}
render={({ handleSubmit, submitting, values }) => {
return (
<CForm onSubmit={handleSubmit}>
<CRow className="mb-3">
<CCol>
<label>Tenant</label>
<Field name="tenantFilter">{(props) => <TenantSelector />}</Field>
</CCol>
</CRow>
<CRow>
<CCol>
<RFFCFormInput
type="text"
name="taskName"
label="Task Name"
firstValue={`Task ${currentDate.toLocaleString()}`}
/>
</CCol>
</CRow>
<CRow>
<CCol>
<label>Scheduled Date</label>
<DatePicker
className="form-control mb-3"
selected={startDate}
showTimeSelect
timeFormat="HH:mm"
timeIntervals={15}
dateFormat="Pp"
onChange={(date) => setStartDate(date)}
/>
</CCol>
</CRow>
<CRow className="mb-3">
<CCol>
<RFFSelectSearch
values={recurrenceOptions}
name="Recurrence"
placeholder="Select a recurrence"
label="Recurrence"
/>
</CCol>
</CRow>
<CRow className="mb-3">
<CCol>
<RFFSelectSearch
values={availableCommands.map((cmd) => ({
value: cmd.Function,
name: cmd.Function,
}))}
name="command"
placeholder={
isLoadingcmd ? (
<CSpinner size="sm" />
) : (
'Select a command or report to execute.'
)
}
label="Command to execute"
/>
</CCol>
</CRow>
<FormSpy>
{/* eslint-disable react/prop-types */}
{(props) => {
const selectedCommand = availableCommands.find(
(cmd) => cmd.Function === props.values.command?.value,
)
return (
<CRow className="mb-3">
<CCol>{selectedCommand?.Synopsis}</CCol>
</CRow>
)
}}
</FormSpy>
<CRow>
<FormSpy>
{/* eslint-disable react/prop-types */}
{(props) => {
const selectedCommand = availableCommands.find(
(cmd) => cmd.Function === props.values.command?.value,
)
let paramblock = null
if (selectedCommand) {
//if the command parameter type is boolean we use <RFFCFormCheck /> else <RFFCFormInput />.
const parameters = selectedCommand.Parameters
if (parameters.length > 0) {
paramblock = parameters.map((param, idx) => (
<CRow key={idx} className="mb-3">
<CTooltip
content={
param?.Description !== null
? param.Description
: 'No Description'
}
placement="left"
>
<CCol>
{param.Type === 'System.Boolean' ||
param.Type ===
'System.Management.Automation.SwitchParameter' ? (
<>
<label>{param.Name}</label>
<RFFCFormSwitch
initialValue={false}
name={`parameters.${param.Name}`}
label={`True`}
/>
</>
) : (
<>
{param.Type === 'System.Collections.Hashtable' ? (
<RFFCFormInputArray
name={`parameters.${param.Name}`}
label={`${param.Name}`}
key={idx}
/>
) : (
<RFFCFormInput
type="text"
key={idx}
name={`parameters.${param.Name}`}
label={`${param.Name}`}
/>
)}
</>
)}
</CCol>
</CTooltip>
</CRow>
))
}
}
return paramblock
}}
</FormSpy>
</CRow>
<CRow className="mb-3">
<CCol>
<RFFCFormInputArray name={`additional`} label="Additional Properties" />
</CCol>
</CRow>
<CRow className="mb-3">
<CCol>
<label>Send results to</label>
<RFFCFormSwitch name="webhook" label="Webhook" />
<RFFCFormSwitch name="email" label="E-mail" />
<RFFCFormSwitch name="psa" label="PSA" />
</CCol>
</CRow>
<CRow className="mb-3">
<CCol md={6}>
<CButton type="submit" disabled={submitting}>
Add Schedule
{postResults.isFetching && (
<FontAwesomeIcon icon="circle-notch" spin className="ms-2" size="1x" />
)}
</CButton>
</CCol>
</CRow>
{postResults.isSuccess && (
<CCallout color="success">
<li>{postResults.data.Results}</li>
</CCallout>
)}
</CForm>
)
}}
/>
</CCardBody>
</CCard>
</CippOffcanvas>
)
}

CippScheduleOffcanvas.propTypes = {
groups: PropTypes.array,
placement: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
state: PropTypes.bool,
hideFunction: PropTypes.func.isRequired,
}
42 changes: 42 additions & 0 deletions src/data/standards.json
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,48 @@
"impact": "Low Impact",
"impactColour": "info"
},
{
"name": "standards.ShortenMeetings",
"cat": "Exchange Standards",
"tag": ["mediumimpact"],
"helpText": "Sets the shorten meetings settings on a tenant level. This will shorten meetings by the selected amount of minutes. Valid values are 0 to 29. Short meetings are under 60 minutes, long meetings are over 60 minutes.",
"addedComponent": [
{
"type": "Select",
"label": "Select value",
"name": "standards.ShortenMeetings.ShortenEventScopeDefault",
"values": [
{
"label": "Disabled/None",
"value": "None"
},
{
"label": "End early",
"value": "EndEarly"
},
{
"label": "Start late",
"value": "StartLate"
}
]
},
{
"type": "number",
"name": "standards.ShortenMeetings.DefaultMinutesToReduceShortEventsBy",
"label": "Minutes to reduce short calendar events by (Default is 5)",
"default": 5
},
{
"type": "number",
"name": "standards.ShortenMeetings.DefaultMinutesToReduceLongEventsBy",
"label": "Minutes to reduce long calendar events by (Default is 10)",
"default": 10
}
],
"label": "Set shorten meetings state",
"impact": "Medium Impact",
"impactColour": "warning"
},
{
"name": "standards.DisableOutlookAddins",
"cat": "Exchange Standards",
Expand Down
1 change: 0 additions & 1 deletion src/views/cipp/Scheduler.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ const Scheduler = () => {
if (typeof row?.Parameters[key] === 'object') {
var nestedParamList = []
Object.keys(row?.Parameters[key]).forEach((nestedKey) => {
console.log(nestedKey)
nestedParamList.push({
Key: nestedKey,
Value: row?.Parameters[key][nestedKey],
Expand Down
2 changes: 2 additions & 0 deletions src/views/cipp/app-settings/SettingsExtensionMappings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ export function SettingsExtensionMappings() {
onClick={() => {
if (
mappingValue.value !== undefined &&
mappingValue.value !== '-1' &&
Object.values(haloMappingsArray)
.map((item) => item.haloId)
.includes(mappingValue.value) === false
Expand Down Expand Up @@ -481,6 +482,7 @@ export function SettingsExtensionMappings() {
//set the new mapping in the array
if (
mappingValue.value !== undefined &&
mappingValue.value !== '-1' &&
Object.values(ninjaMappingsArray)
.map((item) => item.ninjaId)
.includes(mappingValue.value) === false
Expand Down
Loading