mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-11 12:43:09 -05:00
Allow schedules to skip weekends (#1505)
* allow schedules to skip weekends * wording * release note * skip weekend in upcoming dates as well * Clean UI * Move switch to the date selection modal
This commit is contained in:
@@ -203,6 +203,8 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
|
||||
start: monthUtils.currentDay(),
|
||||
frequency: 'monthly',
|
||||
patterns: [],
|
||||
skipWeekend: false,
|
||||
weekendSolveMode: 'after',
|
||||
};
|
||||
let schedule = {
|
||||
posts_transaction: false,
|
||||
@@ -411,7 +413,6 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
|
||||
|
||||
// This is derived from the date
|
||||
let repeats = state.fields.date ? !!state.fields.date.frequency : false;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={payee ? `Schedule: ${payee.name}` : 'Schedule'}
|
||||
@@ -527,7 +528,7 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
|
||||
</View>
|
||||
|
||||
<Stack direction="row" align="flex-start">
|
||||
<View style={{ flex: 1 }}>
|
||||
<View style={{ flex: 1, width: '13.44rem' }}>
|
||||
{repeats ? (
|
||||
<RecurringSchedulePicker
|
||||
value={state.fields.date}
|
||||
|
||||
@@ -14,6 +14,7 @@ import Select from '../common/Select';
|
||||
import Stack from '../common/Stack';
|
||||
import Text from '../common/Text';
|
||||
import View from '../common/View';
|
||||
import { Checkbox } from '../forms';
|
||||
import { useTooltip, Tooltip } from '../tooltips';
|
||||
|
||||
import DateSelect from './DateSelect';
|
||||
@@ -54,6 +55,8 @@ function parseConfig(config) {
|
||||
interval: 1,
|
||||
frequency: 'monthly',
|
||||
patterns: [createMonthlyRecurrence(monthUtils.currentDay())],
|
||||
skipWeekend: false,
|
||||
weekendSolveMode: 'before',
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -131,6 +134,22 @@ function reducer(state, action) {
|
||||
patterns: state.config.patterns.filter(p => p !== action.recurrence),
|
||||
},
|
||||
};
|
||||
case 'set-skip-weekend':
|
||||
return {
|
||||
...state,
|
||||
config: {
|
||||
...state.config,
|
||||
skipWeekend: action.skipWeekend,
|
||||
},
|
||||
};
|
||||
case 'set-weekend-solve':
|
||||
return {
|
||||
...state,
|
||||
config: {
|
||||
...state.config,
|
||||
weekendSolveMode: action.value,
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@@ -254,6 +273,9 @@ function RecurringScheduleTooltip({ config: currentConfig, onClose, onSave }) {
|
||||
config: parseConfig(currentConfig),
|
||||
});
|
||||
|
||||
let skipWeekend = state.config.hasOwnProperty('skipWeekend')
|
||||
? state.config.skipWeekend
|
||||
: false;
|
||||
let dateFormat = useSelector(
|
||||
state => state.prefs.local.dateFormat || 'MM/dd/yyyy',
|
||||
);
|
||||
@@ -346,6 +368,56 @@ function RecurringScheduleTooltip({ config: currentConfig, onClose, onSave }) {
|
||||
config.patterns.length > 0 && (
|
||||
<MonthlyPatterns config={config} dispatch={dispatch} />
|
||||
)}
|
||||
<Stack direction="column" style={{ marginTop: 5 }}>
|
||||
<View
|
||||
style={{
|
||||
marginTop: 5,
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
userSelect: 'none',
|
||||
}}
|
||||
>
|
||||
<Checkbox
|
||||
id="form_skipwe"
|
||||
checked={skipWeekend}
|
||||
onChange={e => {
|
||||
dispatch({
|
||||
type: 'set-skip-weekend',
|
||||
skipWeekend: e.target.checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<label
|
||||
htmlFor="form_skipwe"
|
||||
style={{ userSelect: 'none', marginRight: 5 }}
|
||||
>
|
||||
Move schedule{' '}
|
||||
</label>
|
||||
<Select
|
||||
id="solve_dropdown"
|
||||
options={[
|
||||
['before', 'before'],
|
||||
['after', 'after'],
|
||||
]}
|
||||
value={state.config.weekendSolveMode}
|
||||
onChange={value =>
|
||||
dispatch({ type: 'set-weekend-solve', value: value })
|
||||
}
|
||||
style={{
|
||||
minHeight: '1px',
|
||||
width: '5rem',
|
||||
}}
|
||||
/>
|
||||
<label
|
||||
htmlFor="solve_dropdown"
|
||||
style={{ userSelect: 'none', marginLeft: 5 }}
|
||||
>
|
||||
{' '}
|
||||
weekend
|
||||
</label>
|
||||
</View>
|
||||
</Stack>
|
||||
<SchedulePreview previewDates={previewDates} />
|
||||
<div
|
||||
style={{ display: 'flex', marginTop: 15, justifyContent: 'flex-end' }}
|
||||
|
||||
@@ -27,7 +27,13 @@ function parseRecurDate(desc) {
|
||||
|
||||
return {
|
||||
type: 'recur',
|
||||
schedule: new RSchedule({ rrules: rules }),
|
||||
schedule: new RSchedule({
|
||||
rrules: rules,
|
||||
data: {
|
||||
skipWeekend: desc.skipWeekend,
|
||||
weekendSolve: desc.weekendSolveMode,
|
||||
},
|
||||
}),
|
||||
};
|
||||
} catch (e) {
|
||||
throw new RuleError('parse-recur-date', e.message);
|
||||
|
||||
@@ -84,6 +84,12 @@ export function getNextDate(dateCond, start = new Date()) {
|
||||
|
||||
if (dates.length > 0) {
|
||||
let date = dates[0].date;
|
||||
if (value.schedule.data.skipWeekend) {
|
||||
date = getDateWithSkippedWeekend(
|
||||
date,
|
||||
value.schedule.data.weekendSolve,
|
||||
);
|
||||
}
|
||||
return dayFromDate(date);
|
||||
}
|
||||
}
|
||||
@@ -372,7 +378,12 @@ async function getUpcomingDates({ config, count }) {
|
||||
return schedule
|
||||
.occurrences({ start: d.startOfDay(new Date()), take: count })
|
||||
.toArray()
|
||||
.map(date => dayFromDate(date.date));
|
||||
.map(date =>
|
||||
config.skipWeekend
|
||||
? getDateWithSkippedWeekend(date.date, config.weekendSolveMode)
|
||||
: date.date,
|
||||
)
|
||||
.map(date => dayFromDate(date));
|
||||
} catch (err) {
|
||||
captureBreadcrumb(config);
|
||||
throw err;
|
||||
@@ -564,4 +575,17 @@ app.events.on('sync', ({ type, subtype }) => {
|
||||
}
|
||||
});
|
||||
|
||||
function getDateWithSkippedWeekend(date, solveMode) {
|
||||
if (d.isWeekend(date)) {
|
||||
if (solveMode === 'after') {
|
||||
return d.nextMonday(date);
|
||||
} else if (solveMode === 'before') {
|
||||
return d.previousFriday(date);
|
||||
} else {
|
||||
throw new Error('Unknown weekend solve mode, this should not happen!');
|
||||
}
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
export default app;
|
||||
|
||||
6
upcoming-release-notes/1505.md
Normal file
6
upcoming-release-notes/1505.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Enhancements
|
||||
authors: [pole95]
|
||||
---
|
||||
|
||||
Allow schedules to skip weekends, and automatically reschedule to before or after the weekend.
|
||||
Reference in New Issue
Block a user