mirror of
https://github.com/Casvt/MIND.git
synced 2026-02-19 11:54:46 -05:00
Added option to enable/disable reminders (#77)
This commit is contained in:
@@ -242,6 +242,7 @@ class ReminderData(GeneralReminderData):
|
||||
repeat_quantity: Union[str, None]
|
||||
repeat_interval: Union[int, None]
|
||||
_weekdays: Union[str, None]
|
||||
enabled: bool
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self._weekdays is not None:
|
||||
|
||||
@@ -57,7 +57,8 @@ class Reminder:
|
||||
repeat_quantity: Union[None, RepeatQuantity] = None,
|
||||
repeat_interval: Union[None, int] = None,
|
||||
weekdays: Union[None, List[WEEKDAY_NUMBER]] = None,
|
||||
color: Union[None, str] = None
|
||||
color: Union[None, str] = None,
|
||||
enabled: Union[None, bool] = None
|
||||
) -> ReminderData:
|
||||
"""Edit the reminder.
|
||||
|
||||
@@ -92,6 +93,10 @@ class Reminder:
|
||||
of the reminder, which is shown in the web-ui.
|
||||
Defaults to None.
|
||||
|
||||
enabled (Union[None, bool], optional): Whether the reminder should
|
||||
be enabled.
|
||||
Defaults to None.
|
||||
|
||||
Note about args:
|
||||
Either repeat_quantity and repeat_interval are given, weekdays is
|
||||
given or neither, but not both.
|
||||
@@ -107,7 +112,8 @@ class Reminder:
|
||||
LOGGER.info(
|
||||
f'Updating notification service {self.id}: '
|
||||
+ f'{title=}, {time=}, {notification_services=}, {text=}, '
|
||||
+ f'{repeat_quantity=}, {repeat_interval=}, {weekdays=}, {color=}'
|
||||
+ f'{repeat_quantity=}, {repeat_interval=}, {weekdays=}, {color=}, '
|
||||
+ f"{enabled=}"
|
||||
)
|
||||
|
||||
# Validate data
|
||||
@@ -151,7 +157,8 @@ class Reminder:
|
||||
lambda w: ",".join(map(str, sorted(w)))
|
||||
),
|
||||
'color': color,
|
||||
'notification_services': notification_services
|
||||
'notification_services': notification_services,
|
||||
'enabled': enabled
|
||||
}
|
||||
for k, v in new_values.items():
|
||||
if (
|
||||
@@ -163,7 +170,7 @@ class Reminder:
|
||||
if repeated_reminder:
|
||||
next_time = find_next_time(
|
||||
data["time"],
|
||||
data["repeat_quantity"],
|
||||
repeat_quantity,
|
||||
data["repeat_interval"],
|
||||
weekdays
|
||||
)
|
||||
@@ -177,7 +184,8 @@ class Reminder:
|
||||
data["weekdays"],
|
||||
data["time"],
|
||||
data["color"],
|
||||
data["notification_services"]
|
||||
data["notification_services"],
|
||||
data["enabled"]
|
||||
)
|
||||
|
||||
else:
|
||||
@@ -192,7 +200,8 @@ class Reminder:
|
||||
data["weekdays"],
|
||||
data["original_time"],
|
||||
data["color"],
|
||||
data["notification_services"]
|
||||
data["notification_services"],
|
||||
data["enabled"]
|
||||
)
|
||||
|
||||
REMINDER_HANDLER.find_next_reminder(next_time)
|
||||
@@ -281,7 +290,8 @@ class Reminders:
|
||||
repeat_quantity: Union[None, RepeatQuantity] = None,
|
||||
repeat_interval: Union[None, int] = None,
|
||||
weekdays: Union[None, List[WEEKDAY_NUMBER]] = None,
|
||||
color: Union[None, str] = None
|
||||
color: Union[None, str] = None,
|
||||
enabled: bool = True
|
||||
) -> Reminder:
|
||||
"""Add a reminder.
|
||||
|
||||
@@ -312,6 +322,10 @@ class Reminders:
|
||||
reminder, which is shown in the web-ui.
|
||||
Defaults to None.
|
||||
|
||||
enabled (Union[None, bool], optional): Whether the reminder should
|
||||
be enabled.
|
||||
Defaults to None.
|
||||
|
||||
Note about args:
|
||||
Either repeat_quantity and repeat_interval are given,
|
||||
weekdays is given or neither, but not both.
|
||||
@@ -327,7 +341,8 @@ class Reminders:
|
||||
"""
|
||||
LOGGER.info(
|
||||
f'Adding reminder with {title=}, {time=}, {notification_services=}, ' +
|
||||
f'{text=}, {repeat_quantity=}, {repeat_interval=}, {weekdays=}, {color=}')
|
||||
f'{text=}, {repeat_quantity=}, {repeat_interval=}, {weekdays=}, {color=}' +
|
||||
f'{enabled=}')
|
||||
|
||||
# Validate data
|
||||
if time < datetime.utcnow().timestamp():
|
||||
@@ -377,7 +392,8 @@ class Reminders:
|
||||
weekdays_str,
|
||||
original_time,
|
||||
color,
|
||||
notification_services
|
||||
notification_services,
|
||||
enabled
|
||||
)
|
||||
|
||||
REMINDER_HANDLER.find_next_reminder(time)
|
||||
|
||||
@@ -314,6 +314,7 @@ def setup_db() -> None:
|
||||
weekdays VARCHAR(13),
|
||||
|
||||
color VARCHAR(7),
|
||||
enabled BOOL NOT NULL DEFAULT 1,
|
||||
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
@@ -303,3 +303,18 @@ class MigrateUpdateManifest(DBMigrator):
|
||||
# So the migration doesn't do anything anymore, and a function used
|
||||
# doesn't exist anymore, so the whole migration is just removed.
|
||||
return
|
||||
|
||||
|
||||
class MigrateAddEnabled(DBMigrator):
|
||||
start_version = 10
|
||||
|
||||
def run(self) -> None:
|
||||
# V10 -> V11
|
||||
|
||||
from backend.internals.db import get_db
|
||||
|
||||
get_db().execute("""
|
||||
ALTER TABLE reminders
|
||||
ADD enabled BOOL NOT NULL DEFAULT 1;
|
||||
""")
|
||||
return
|
||||
|
||||
@@ -547,7 +547,7 @@ class RemindersDB:
|
||||
id, title, text, color,
|
||||
time, original_time,
|
||||
repeat_quantity, repeat_interval,
|
||||
weekdays AS _weekdays
|
||||
weekdays AS _weekdays, enabled
|
||||
FROM reminders
|
||||
WHERE user_id = :user_id
|
||||
{id_filter};
|
||||
@@ -576,7 +576,8 @@ class RemindersDB:
|
||||
weekdays: Union[str, None],
|
||||
original_time: Union[int, None],
|
||||
color: Union[str, None],
|
||||
notification_services: List[int]
|
||||
notification_services: List[int],
|
||||
enabled: bool
|
||||
) -> int:
|
||||
new_id = get_db().execute("""
|
||||
INSERT INTO reminders(
|
||||
@@ -586,7 +587,8 @@ class RemindersDB:
|
||||
repeat_quantity, repeat_interval,
|
||||
weekdays,
|
||||
original_time,
|
||||
color
|
||||
color,
|
||||
enabled
|
||||
)
|
||||
VALUES (
|
||||
:user_id,
|
||||
@@ -595,7 +597,8 @@ class RemindersDB:
|
||||
:rq, :ri,
|
||||
:wd,
|
||||
:ot,
|
||||
:color
|
||||
:color,
|
||||
:enabled
|
||||
);
|
||||
""",
|
||||
{
|
||||
@@ -607,7 +610,8 @@ class RemindersDB:
|
||||
"ri": repeat_interval,
|
||||
"wd": weekdays,
|
||||
"ot": original_time,
|
||||
"color": color
|
||||
"color": color,
|
||||
"enabled": enabled
|
||||
}
|
||||
).lastrowid
|
||||
|
||||
@@ -628,7 +632,8 @@ class RemindersDB:
|
||||
weekdays: Union[str, None],
|
||||
original_time: Union[int, None],
|
||||
color: Union[str, None],
|
||||
notification_services: List[int]
|
||||
notification_services: List[int],
|
||||
enabled: bool
|
||||
) -> None:
|
||||
get_db().execute("""
|
||||
UPDATE reminders
|
||||
@@ -640,7 +645,8 @@ class RemindersDB:
|
||||
repeat_interval = :ri,
|
||||
weekdays = :wd,
|
||||
original_time = :ot,
|
||||
color = :color
|
||||
color = :color,
|
||||
enabled = :enabled
|
||||
WHERE id = :r_id;
|
||||
""",
|
||||
{
|
||||
@@ -652,6 +658,7 @@ class RemindersDB:
|
||||
"wd": weekdays,
|
||||
"ot": original_time,
|
||||
"color": color,
|
||||
"enabled": enabled,
|
||||
"r_id": reminder_id
|
||||
}
|
||||
)
|
||||
@@ -701,7 +708,14 @@ class UserlessRemindersDB:
|
||||
).exists() or -1
|
||||
|
||||
def get_soonest_time(self) -> Union[int, None]:
|
||||
return get_db().execute("SELECT MIN(time) FROM reminders;").exists()
|
||||
"""Get the earliest time a reminder goes off that is enabled.
|
||||
|
||||
Returns:
|
||||
Union[int, None]: The time, or None if there are no reminders.
|
||||
"""
|
||||
return get_db().execute(
|
||||
"SELECT MIN(time) FROM reminders WHERE enabled = 1;"
|
||||
).exists()
|
||||
|
||||
def fetch(
|
||||
self,
|
||||
@@ -717,7 +731,7 @@ class UserlessRemindersDB:
|
||||
title, text, color,
|
||||
time, original_time,
|
||||
repeat_quantity, repeat_interval,
|
||||
weekdays AS _weekdays
|
||||
weekdays AS _weekdays, enabled
|
||||
FROM reminders
|
||||
{time_filter};
|
||||
""",
|
||||
@@ -745,7 +759,8 @@ class UserlessRemindersDB:
|
||||
weekdays: Union[str, None],
|
||||
original_time: Union[int, None],
|
||||
color: Union[str, None],
|
||||
notification_services: List[int]
|
||||
notification_services: List[int],
|
||||
enabled: bool
|
||||
) -> int:
|
||||
new_id = get_db().execute("""
|
||||
INSERT INTO reminders(
|
||||
@@ -755,7 +770,8 @@ class UserlessRemindersDB:
|
||||
repeat_quantity, repeat_interval,
|
||||
weekdays,
|
||||
original_time,
|
||||
color
|
||||
color,
|
||||
enabled
|
||||
)
|
||||
VALUES (
|
||||
:user_id,
|
||||
@@ -764,7 +780,8 @@ class UserlessRemindersDB:
|
||||
:rq, :ri,
|
||||
:wd,
|
||||
:ot,
|
||||
:color
|
||||
:color,
|
||||
:enabled
|
||||
);
|
||||
""",
|
||||
{
|
||||
@@ -776,7 +793,8 @@ class UserlessRemindersDB:
|
||||
"ri": repeat_interval,
|
||||
"wd": weekdays,
|
||||
"ot": original_time,
|
||||
"color": color
|
||||
"color": color,
|
||||
"enabled": enabled
|
||||
}
|
||||
).lastrowid
|
||||
|
||||
|
||||
@@ -306,7 +306,8 @@ def api_reminders_list(inputs: Dict[str, Any]):
|
||||
repeat_quantity=inputs['repeat_quantity'],
|
||||
repeat_interval=inputs['repeat_interval'],
|
||||
weekdays=inputs['weekdays'],
|
||||
color=inputs['color']
|
||||
color=inputs['color'],
|
||||
enabled=inputs['enabled']
|
||||
)
|
||||
return return_api(result.get().todict(), code=201)
|
||||
|
||||
@@ -344,6 +345,7 @@ def api_get_reminder(inputs: Dict[str, Any], r_id: int):
|
||||
return return_api(result.todict())
|
||||
|
||||
elif request.method == 'PUT':
|
||||
print(inputs)
|
||||
result = reminders.fetchone(r_id).update(
|
||||
title=inputs['title'],
|
||||
time=inputs['time'],
|
||||
@@ -352,7 +354,8 @@ def api_get_reminder(inputs: Dict[str, Any], r_id: int):
|
||||
repeat_quantity=inputs['repeat_quantity'],
|
||||
repeat_interval=inputs['repeat_interval'],
|
||||
weekdays=inputs['weekdays'],
|
||||
color=inputs['color']
|
||||
color=inputs['color'],
|
||||
enabled=inputs['enabled']
|
||||
)
|
||||
return return_api(result.todict())
|
||||
|
||||
@@ -453,7 +456,7 @@ def api_static_reminders_query(inputs: Dict[str, Any]):
|
||||
return return_api([r.todict() for r in result])
|
||||
|
||||
|
||||
@api.route('staticreminders/<int:s_id>', StaticReminderData)
|
||||
@api.route('/staticreminders/<int:s_id>', StaticReminderData)
|
||||
@endpoint_wrapper
|
||||
def api_get_static_reminder(inputs: Dict[str, Any], s_id: int):
|
||||
reminders = StaticReminders(
|
||||
|
||||
@@ -306,6 +306,23 @@ class ColorVariable(NonRequiredInputVariable):
|
||||
)
|
||||
|
||||
|
||||
class EnabledVariable(NonRequiredInputVariable):
|
||||
name = "enabled"
|
||||
description = "Whether the reminder should be enabled"
|
||||
data_type = [DataType.BOOL]
|
||||
default = True
|
||||
|
||||
def validate(self) -> bool:
|
||||
return isinstance(self.value, bool)
|
||||
|
||||
|
||||
class EditEnabledVariable(EnabledVariable):
|
||||
default = None
|
||||
|
||||
def validate(self) -> bool:
|
||||
return self.value is None or super().validate()
|
||||
|
||||
|
||||
class QueryVariable(InputVariable):
|
||||
name = "query"
|
||||
description = "The search term"
|
||||
@@ -538,7 +555,8 @@ class RemindersData(EndpointData):
|
||||
RepeatQuantityVariable,
|
||||
RepeatIntervalVariable,
|
||||
WeekDaysVariable,
|
||||
ColorVariable
|
||||
ColorVariable,
|
||||
EnabledVariable
|
||||
]
|
||||
)
|
||||
)
|
||||
@@ -570,7 +588,8 @@ class ReminderData(EndpointData):
|
||||
RepeatQuantityVariable,
|
||||
RepeatIntervalVariable,
|
||||
WeekDaysVariable,
|
||||
ColorVariable
|
||||
ColorVariable,
|
||||
EditEnabledVariable
|
||||
]
|
||||
),
|
||||
delete=(
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
--gap: 1rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--gap);
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
.sub-inputs > :where(
|
||||
input, select, button, label
|
||||
) {
|
||||
width: calc(50% - (var(--gap) / 2));
|
||||
flex: 1 0;
|
||||
}
|
||||
|
||||
.form-container > form > button,
|
||||
@@ -54,6 +54,19 @@
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#enabled-container {
|
||||
height: 4rem;
|
||||
flex: 1 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 1rem;
|
||||
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
#color-button {
|
||||
--color: var(--color-dark);
|
||||
background-color: var(--color);
|
||||
@@ -254,6 +267,7 @@ div.options > button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#info.show-add-static-reminder #enabled-container,
|
||||
#info.show-add-static-reminder #time-input,
|
||||
#info.show-add-static-reminder #normal-button,
|
||||
#info.show-add-static-reminder #repeat-button,
|
||||
@@ -274,6 +288,7 @@ div.options > button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info.show-add-template #enabled-container,
|
||||
#info.show-add-template #template-selection,
|
||||
#info.show-add-template #time-input,
|
||||
#info.show-add-template #normal-button,
|
||||
@@ -307,6 +322,7 @@ div.options > button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info.show-edit-static-reminder #enabled-container,
|
||||
#info.show-edit-static-reminder #template-selection,
|
||||
#info.show-edit-static-reminder #time-input,
|
||||
#info.show-edit-static-reminder #normal-button,
|
||||
@@ -326,6 +342,7 @@ div.options > button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info.show-edit-template #enabled-container,
|
||||
#info.show-edit-template #template-selection,
|
||||
#info.show-edit-template #time-input,
|
||||
#info.show-edit-template #normal-button,
|
||||
|
||||
@@ -81,6 +81,9 @@ function fillTable(table, results) {
|
||||
} else if (r.weekdays !== null)
|
||||
formatted_date += ` (each ${r.weekdays.map(d => week_days[d]).join(', ')})`;
|
||||
|
||||
if (!r.enabled)
|
||||
formatted_date += ' (Disabled)';
|
||||
|
||||
time.innerText = formatted_date;
|
||||
entry.appendChild(time);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
function showAdd(type) {
|
||||
const default_service = getLocalStorage('default_service')['default_service'];
|
||||
inputs.enabled.checked = true;
|
||||
inputs.template.value = '0';
|
||||
inputs.title.value = '';
|
||||
inputs.text.value = '';
|
||||
@@ -69,6 +70,7 @@ function showEdit(id, type) {
|
||||
inputs.title.value = json.result.title;
|
||||
|
||||
if (type === Types.reminder) {
|
||||
inputs.enabled.checked = json.result.enabled;
|
||||
var trigger_date = new Date(
|
||||
(json.result.time
|
||||
+ new Date(json.result.time * 1000).getTimezoneOffset()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const colors = ["#3c3c3c", "#49191e", "#171a42", "#083b06", "#3b3506", "#300e40"];
|
||||
|
||||
const inputs = {
|
||||
'enabled': document.querySelector('#enabled-input'),
|
||||
'template': document.querySelector('#template-selection'),
|
||||
'color_toggle': document.querySelector('#color-toggle'),
|
||||
'color_button': document.querySelector('#color-button'),
|
||||
@@ -219,6 +220,8 @@ function submitInfo() {
|
||||
const cl = document.getElementById('info').classList;
|
||||
if (cl.contains('show-add-reminder')) {
|
||||
// Add reminder
|
||||
data['enabled'] = inputs.enabled.checked;
|
||||
|
||||
data['time'] =
|
||||
(new Date(inputs.time.value) / 1000)
|
||||
+ (new Date(inputs.time.value).getTimezoneOffset() * 60);
|
||||
@@ -262,6 +265,8 @@ function submitInfo() {
|
||||
|
||||
} else if (cl.contains('show-edit-reminder')) {
|
||||
// Edit reminder
|
||||
data['enabled'] = inputs.enabled.checked;
|
||||
|
||||
data['time'] =
|
||||
(new Date(inputs.time.value) / 1000)
|
||||
+ (new Date(inputs.time.value).getTimezoneOffset() * 60);
|
||||
|
||||
@@ -228,6 +228,10 @@
|
||||
<select id="template-selection">
|
||||
<option value="0" selected>No template</option>
|
||||
</select>
|
||||
<div id="enabled-container" class="as-button">
|
||||
<input type="checkbox" id="enabled-input" checked>
|
||||
<label for="enabled-input">Enabled</label>
|
||||
</div>
|
||||
<label for="color-toggle" id="color-button" class="as-button">Color</label>
|
||||
</div>
|
||||
<div class="color-list"></div>
|
||||
|
||||
Reference in New Issue
Block a user