-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v2.4 Feature - Time Clock Triggers - Scheduled Presets (#163)
* bump * TS Docs aren't actually provided as far as I can see * Bump * Add database structure * Add edit page * Add config option to macro preset * Allow presets to be recalled over http * Bump version * Improve locked message, and fix logic error in web server * Basic work on time clock triggers * Remove time clock triggers * Lint * Remove stats file * Lint * Update folder.ts * Add badge showing preset type * Add parent name to folders * Add duplicate preset button * Refactor folder icons to allow them to be used with other buttons * Add preset icons, and make icons searchable * Add more icons * Improve admin pin entry * Update settings.json * Start UI * Bump * Fix imports * Add more ui * Remove webpack cache to fix database error in electron/forge#2412 (comment) * Radically simplify icon file * Basic UI * UI tweaks * Edit functionality complete * Build out function * Update NavbarItem.tsx * Fix bugs * Time clock trigger bugfixes * Clarify skip behaviour * Lint * Closes #164 by removing effect mode * Update index.ts * Add error handling to sampling mode * Add docs
- Loading branch information
Showing
42 changed files
with
1,024 additions
and
233 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
--- | ||
sidebar_position: 30 | ||
title: Scheduled Presets | ||
--- | ||
|
||
The Scheduled Presets page allows you to define times of the day when presets are triggered automatically. | ||
|
||
To start, use the plus button to add a new schedule. Next, select the days of the week you'd like the schedule to run on, and the time to run during those days. Finally, select the preset you'd like to run at that time, and click save. | ||
|
||
To trigger a preset at multiple times during the day, simply add multiple schedules for that preset. | ||
|
||
![scheduled presets page](@site/static/img/tutorial/admin/admin-scheduled-presets.png) | ||
|
||
The cog icon on the right side of each preset allows you to edit the advanced settings for that preset. | ||
|
||
![scheduled presets cog page](@site/static/img/tutorial/admin/admin-scheduled-presets-cog.png) | ||
|
||
The advanced settings allow you to set the following: | ||
|
||
- Notes: A description of why the schedule exists as a reminder in the administrator menu - this can help you differentiate between large numbers of schedules. | ||
- Enabled: whether the schedule is enabled or not. If disabled, the schedule will not run. | ||
- Run when locked: if the control panel is locked, the schedule will still run if this is enabled. | ||
- Timeout: how many minutes to keep trying to trigger the preset for. If the preset is not triggered within this time, the schedule will be skipped for that day. This is particularly relevant if ParadisePi is powered off at the time the schedule is due to run, and later powered on - if the timeout plus the scheduled time is earlier than the time ParadisePi boots, then it will be skipped. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Database, createDatabaseObject, sendDatabaseObject } from '../database' | ||
import { DatabaseTimeClockTrigger, TimeClockTriggersRepository } from './../../database/repository/timeClockTrigger' | ||
/** | ||
* This is a REST router for the preset API. | ||
* @param path - The path requested by the original route requestor | ||
* @param method - The method requested by the original route requestor | ||
* @param payload - Any payload sent | ||
* @returns the retrieved response from the given route | ||
* @throws an error if the requested route is not found | ||
*/ | ||
export const timeClockTriggersRouter = ( | ||
path: Array<string>, | ||
method: 'GET' | 'POST' | 'PUT' | 'DELETE', | ||
payload: apiObject | ||
): Promise<apiObject> => { | ||
logger.debug('Time clock trigger router has a request', { path, method, payload }) | ||
return new Promise((resolve, reject) => { | ||
if (method === 'PUT') { | ||
return TimeClockTriggersRepository.setAllFromApp(payload as Array<DatabaseTimeClockTrigger>) | ||
.then(() => { | ||
return createDatabaseObject('updating all time clock triggers in bulk') | ||
}) | ||
.then((response: Database) => { | ||
sendDatabaseObject(response) | ||
resolve({}) | ||
}) | ||
} else reject(new Error('Path not found')) | ||
}) | ||
} |
104 changes: 104 additions & 0 deletions
104
src/app/Components/Admin/Controls/Presets/EditModal/TimeClockTriggers.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import React, { useEffect } from 'react' | ||
import { Group, ActionIcon, Button, Text, Checkbox, NumberInput } from '@mantine/core' | ||
import { useForm } from '@mantine/form' | ||
import { FaTrash } from '@react-icons/all-files/fa/FaTrash' | ||
import { randomId } from '@mantine/hooks' | ||
import { InputProps } from '../../../../InputProps' | ||
|
||
interface Trigger { | ||
time: string | ||
enabled: boolean | ||
timeout: number | ||
countdownWarning: number | ||
key: string | ||
} | ||
interface FormValues { | ||
triggers: Array<Trigger> | ||
} | ||
|
||
export const TimeClockTriggersEditor = (props: InputProps) => { | ||
const form = useForm<FormValues>({ | ||
initialValues: { | ||
triggers: [], | ||
}, | ||
}) | ||
useEffect(() => { | ||
if (props.value !== null) { | ||
const valueObject = JSON.parse(props.value) || {} | ||
form.setValues({ | ||
triggers: valueObject.map((item: Trigger) => ({ | ||
time: item.time, | ||
key: item.key, | ||
})), | ||
}) | ||
} | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [props.value]) | ||
return ( | ||
<> | ||
<Group mt="xs"> | ||
<Text mt={'md'}>Time Clock Triggers</Text> | ||
<Button | ||
mt={'md'} | ||
size="sm" | ||
onClick={() => | ||
form.insertListItem('triggers', { | ||
time: '', | ||
enabled: true, | ||
timeout: 60, | ||
countdownWarning: 0, | ||
key: randomId(), | ||
}) | ||
} | ||
> | ||
Add Trigger | ||
</Button> | ||
{form.isDirty() ? ( | ||
<Button mt={'md'} size="sm" onClick={() => props.onChange(JSON.stringify(form.values.triggers))}> | ||
Apply | ||
</Button> | ||
) : null} | ||
</Group> | ||
<Text size={'sm'}>Time Clock Triggers will recall this preset at the following times (if enabled)</Text> | ||
{form.values.triggers.map((item, index) => ( | ||
<Group key={item.key} mt="xs"> | ||
<NumberInput | ||
label="Trigger Time" | ||
max={2359} | ||
min={0} | ||
parser={value => | ||
value.match(/\d(?=(?:\D*\d){0,3}$)/g) ? value.match(/\d(?=(?:\D*\d){0,3}$)/g).join('') : '' | ||
} | ||
formatter={value => | ||
!Number.isNaN(parseFloat(value)) | ||
? value.replace(/\b\d{1,4}\b/g, match => { | ||
const paddedNumber = match.padStart(4, '0') | ||
const hours = paddedNumber.slice(0, 2) | ||
const minutes = paddedNumber.slice(2) | ||
return `${hours}:${minutes}` | ||
}) | ||
: '' | ||
} | ||
{...form.getInputProps(`triggers.${index}.time`)} | ||
/> | ||
<Checkbox | ||
mt={'lg'} | ||
size={'lg'} | ||
label="Enabled" | ||
{...form.getInputProps(`triggers.${index}.enabled`, { type: 'checkbox' })} | ||
/> | ||
<ActionIcon | ||
mt={'lg'} | ||
color="red" | ||
variant="transparent" | ||
onClick={() => form.removeListItem('triggers', index)} | ||
> | ||
<FaTrash /> | ||
</ActionIcon> | ||
</Group> | ||
))} | ||
|
||
<Group position="center" mt="md"></Group> | ||
</> | ||
) | ||
} |
Oops, something went wrong.