mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-24 00:17:23 +00:00
* fix(plugin-bridge): enhance task update logic and validation for project movement
* fix(plugin-bridge): include changes in task update event payload
* feat(RuleEditor): add tests for rule editing functionality and enhance action handling
* test(RuleEditor): add comprehensive tests for rule editing and condition handling
* feat(RuleRegistry): enhance rule validation and add support for advanced conditions and actions
* feat(types): extend condition and action types for enhanced automation capabilities
* feat(conditions): add regex support for title conditions and enhance checks
* feat(actions): add ActionMoveToProject to move tasks between projects
* feat(ActionDialog, ActionInput): add support for moveToProject action and enhance input handling
* feat(ConditionDialog, ConditionInput): add support for titleStartsWith and weekdayIs conditions, enhance regex handling
* feat(styles): add new input-with-toggle and field-error styles for improved layout and error handling
* feat(automation): add titleStartsWith condition and enhance task event handling
* feat(automations): add delete task action
add a new `deleteTask` action to the automations plugin
- register the action in the automation runtime
- expose it in the rule editor UI
- restrict it to task-based triggers
- validate and persist rules using `deleteTask`
- add focused tests for runtime behavior, validation, persistence, and UI
* feat(automations): remove false trigger workaround
remove the temporary taskCreated fallback after confirming the
reported trigger bug was a mistaken assumption
* fix(automations): address PR review feedback
- Add regex pattern length cap (200 chars) to mitigate ReDoS risk
- Use project ID instead of title as option value to prevent duplicate name collisions
- Replace dynamic import('rxjs') with static import for firstValueFrom
- Replace any[] with proper types for projects/tags props
- Replace changes?: any with Record<string, unknown> in TaskEvent
- Use createMemo + <Show> for regexError to avoid double reactive computation
- Remove noisy/inconsistent debug logging from automation-manager
- Remove verbose intermediate log from moveToProject action
- Clean up mock: remove unused moveTaskToProject, restore PluginAPI type
- Prefer ID lookup over title in ActionMoveToProject
* fix(automations): harden regex, use IDs for conditions, add validation and tests
- Add dangerous-pattern heuristic to reject nested quantifiers (e.g. (a+)+$)
that cause catastrophic backtracking, supplementing the length cap
- Switch projectIs/hasTag condition dropdowns to store IDs instead of titles
to survive project/tag renames (with title fallback for backward compat)
- Disable ActionDialog Save button when value is empty (except deleteTask)
- Fix webhook test to actually validate payload sanitization
- Add test for HTML escaping in ActionDisplayDialog
- Add tests for regex length cap and dangerous-pattern rejection
- Add tests for ConditionWeekdayIs (7 test cases covering full names,
abbreviations, comma-separated lists, case insensitivity, edge cases)
* test(automations): build dangerous regex pattern dynamically to avoid CodeQL flag
The test intentionally uses a catastrophic-backtracking pattern to verify
our safety heuristic rejects it. Build it via string concatenation so
CodeQL's static analysis doesn't flag the test itself.
* fix(automations): addTag lookup by ID, widen ReDoS heuristic to catch {n,}
- ActionAddTag now looks up tags by ID first (with title fallback),
consistent with all other condition/action lookups
- Extend DANGEROUS_REGEX_PATTERN to also detect {n,} quantifiers
inside nested groups (e.g. (a{2,})+) which also cause backtracking
---------
Co-authored-by: Johannes Millan <johannes.millan@gmail.com>
117 lines
2.2 KiB
CSS
117 lines
2.2 KiB
CSS
/*
|
|
* Automations Plugin Styles
|
|
* UI Kit provides base element styles (body, headings, buttons, inputs, etc.)
|
|
* Only plugin-specific layout and component rules here.
|
|
*/
|
|
|
|
html,
|
|
body {
|
|
background-color: transparent;
|
|
}
|
|
|
|
/* Responsive equal-column grid (replaces Pico .grid) */
|
|
.grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
|
|
gap: var(--s);
|
|
align-items: center;
|
|
}
|
|
|
|
/* Dialog/modal styling (replaces Pico <dialog>/<article>) */
|
|
dialog {
|
|
border: none;
|
|
border-radius: var(--card-border-radius);
|
|
background: var(--card-bg);
|
|
color: var(--text-color);
|
|
padding: 0;
|
|
max-width: 600px;
|
|
width: calc(100% - var(--s4));
|
|
}
|
|
|
|
dialog::backdrop {
|
|
background: rgba(0, 0, 0, 0.5);
|
|
}
|
|
|
|
dialog article {
|
|
padding: var(--s3);
|
|
}
|
|
|
|
dialog article header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: var(--s2);
|
|
}
|
|
|
|
dialog article footer {
|
|
margin-top: var(--s3);
|
|
padding-top: var(--s2);
|
|
border-top: 1px solid var(--divider-color);
|
|
}
|
|
|
|
/* Close button in dialogs */
|
|
.close-btn {
|
|
background: none;
|
|
border: none;
|
|
padding: var(--s-half);
|
|
font-size: 1.2em;
|
|
line-height: 1;
|
|
cursor: pointer;
|
|
color: var(--text-color-muted);
|
|
}
|
|
|
|
.close-btn:hover {
|
|
color: var(--text-color);
|
|
background: none;
|
|
border: none;
|
|
}
|
|
|
|
/* Figure wrapper for table overflow */
|
|
figure {
|
|
margin: 0;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.app {
|
|
padding: var(--s3);
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.app-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: var(--s3);
|
|
border-bottom: 1px solid var(--divider-color);
|
|
padding-bottom: var(--s);
|
|
}
|
|
|
|
.warning-box {
|
|
background-color: color-mix(in srgb, var(--color-warning) 15%, transparent);
|
|
color: var(--color-warning);
|
|
padding: var(--s);
|
|
margin-bottom: var(--s3);
|
|
border-radius: var(--card-border-radius);
|
|
border: 1px solid color-mix(in srgb, var(--color-warning) 30%, transparent);
|
|
}
|
|
|
|
.input-with-toggle {
|
|
display: flex;
|
|
align-items: stretch;
|
|
gap: var(--s);
|
|
}
|
|
|
|
.input-with-toggle input {
|
|
flex: 1;
|
|
}
|
|
|
|
.regex-toggle {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.field-error {
|
|
display: block;
|
|
margin-top: var(--s-half);
|
|
color: var(--color-danger);
|
|
}
|