diff --git a/backend/notification_service.py b/backend/notification_service.py index 9c09c5a..2612793 100644 --- a/backend/notification_service.py +++ b/backend/notification_service.py @@ -247,53 +247,86 @@ class NotificationService: return self.get() - def delete(self) -> None: - """Delete the service + def delete( + self, + delete_reminders_using: bool = False + ) -> None: + """Delete the service. + + Args: + delete_reminders_using (bool, optional): Instead of throwing an + error when there are still reminders using the service, delete + the reminders. + Defaults to False. Raises: - NotificationServiceInUse: The service is still used by a reminder - """ + NotificationServiceInUse: The service is still used by a reminder. + """ LOGGER.info(f'Deleting notification service {self.id}') - - # Check if no reminders exist with this service - cursor = get_db() - cursor.execute(""" - SELECT 1 - FROM reminder_services - WHERE notification_service_id = ? - AND reminder_id IS NOT NULL - LIMIT 1; - """, - (self.id,) - ) - if cursor.fetchone(): - raise NotificationServiceInUse('reminder') - - # Check if no templates exist with this service - cursor.execute(""" - SELECT 1 - FROM reminder_services - WHERE notification_service_id = ? - AND template_id IS NOT NULL - LIMIT 1; - """, - (self.id,) - ) - if cursor.fetchone(): - raise NotificationServiceInUse('template') - # Check if no static reminders exist with this service - cursor.execute(""" - SELECT 1 - FROM reminder_services - WHERE notification_service_id = ? - AND static_reminder_id IS NOT NULL - LIMIT 1; - """, - (self.id,) - ) - if cursor.fetchone(): - raise NotificationServiceInUse('static reminder') + cursor = get_db() + if not delete_reminders_using: + # Check if no reminders exist with this service + cursor.execute(""" + SELECT 1 + FROM reminder_services + WHERE notification_service_id = ? + AND reminder_id IS NOT NULL + LIMIT 1; + """, + (self.id,) + ) + if cursor.fetchone(): + raise NotificationServiceInUse('reminder') + + # Check if no templates exist with this service + cursor.execute(""" + SELECT 1 + FROM reminder_services + WHERE notification_service_id = ? + AND template_id IS NOT NULL + LIMIT 1; + """, + (self.id,) + ) + if cursor.fetchone(): + raise NotificationServiceInUse('template') + + # Check if no static reminders exist with this service + cursor.execute(""" + SELECT 1 + FROM reminder_services + WHERE notification_service_id = ? + AND static_reminder_id IS NOT NULL + LIMIT 1; + """, + (self.id,) + ) + if cursor.fetchone(): + raise NotificationServiceInUse('static reminder') + + else: + cursor.execute(""" + DELETE FROM reminders + WHERE id IN ( + SELECT reminder_id AS id FROM reminder_services + WHERE notification_service_id = ? + ); + """, (self.id,)) + cursor.execute(""" + DELETE FROM static_reminders + WHERE id IN ( + SELECT static_reminder_id AS id FROM reminder_services + WHERE notification_service_id = ? + ); + """, (self.id,)) + cursor.execute(""" + DELETE FROM templates + WHERE id IN ( + SELECT template_id AS id FROM reminder_services + WHERE notification_service_id = ? + ); + """, (self.id,)) cursor.execute( "DELETE FROM notification_services WHERE id = ?", diff --git a/frontend/api.py b/frontend/api.py index 9f28584..c67e505 100644 --- a/frontend/api.py +++ b/frontend/api.py @@ -33,6 +33,7 @@ from backend.users import Users from frontend.input_validation import (AllowNewAccountsVariable, ColorVariable, CopyHostingSettingsVariable, DatabaseFileVariable, + DeleteRemindersUsingVariable, EditNotificationServicesVariable, EditTimeVariable, EditTitleVariable, EditURLVariable, HostVariable, @@ -333,6 +334,7 @@ def api_test_service(inputs: Dict[str, Any]): description='Edit the notification service' ), delete=Method( + vars=[DeleteRemindersUsingVariable], description='Delete the notification service' ) ), @@ -355,7 +357,9 @@ def api_notification_service(inputs: Dict[str, str], n_id: int): return return_api(result) elif request.method == 'DELETE': - service.delete() + service.delete( + inputs['delete_reminders_using'] + ) return return_api({}) #=================== diff --git a/frontend/input_validation.py b/frontend/input_validation.py index c368fec..49d0d8d 100644 --- a/frontend/input_validation.py +++ b/frontend/input_validation.py @@ -383,7 +383,6 @@ class ColorVariable(NonRequiredVersion, BaseInputVariable): description = 'The hex code of the color of the entry, which is shown in the web-ui' def validate(self) -> bool: - super() return self.value is None or ( isinstance(self.value, str) and color_regex.search(self.value) @@ -396,6 +395,26 @@ class QueryVariable(BaseInputVariable): source = DataSource.VALUES +class DeleteRemindersUsingVariable(NonRequiredVersion, BaseInputVariable): + name = 'delete_reminders_using' + description = 'Instead of throwing an error when there are still reminders using the service, delete the reminders.' + source = DataSource.VALUES + default = 'false' + data_type = [DataType.BOOL] + + def validate(self) -> bool: + if self.value == 'true': + self.value = True + return True + + elif self.value == 'false': + self.value = False + return True + + else: + return False + + class AdminSettingsVariable(BaseInputVariable): def validate(self) -> bool: try: diff --git a/frontend/static/js/notification.js b/frontend/static/js/notification.js index d9172a8..811ee59 100644 --- a/frontend/static/js/notification.js +++ b/frontend/static/js/notification.js @@ -153,9 +153,9 @@ function saveService(id) { }); }; -function deleteService(id) { +function deleteService(id, delete_reminders_using=false) { const row = document.querySelector(`tr[data-id="${id}"]`); - fetch(`${url_prefix}/api/notificationservices/${id}?api_key=${api_key}`, { + fetch(`${url_prefix}/api/notificationservices/${id}?api_key=${api_key}&delete_reminders_using=${delete_reminders_using}`, { 'method': 'DELETE' }) .then(response => response.json()) @@ -164,18 +164,25 @@ function deleteService(id) { row.remove(); fillNotificationServices(); + if (delete_reminders_using) { + fillLibrary(Types.reminder); + fillLibrary(Types.static_reminder); + fillLibrary(Types.template); + }; }) .catch(e => { if (e.error === 'ApiKeyExpired' || e.error === 'ApiKeyInvalid') window.location.href = `${url_prefix}/`; + else if (e.error === 'NotificationServiceInUse') { - const delete_button = row.querySelector('button[title="Delete"]'); - delete_button.classList.add('error-icon'); - delete_button.title = `The notification service is still in use by a ${e.result.type}`; - setTimeout( - () => alert(`The notification service is still in use by a ${e.result.type}`), - 10 + const delete_reminders = confirm( + `The notification service is still in use by a ${e.result.type}. Do you want to delete all ${e.result.type}s that are using the notification service?` ); + + if (delete_reminders) + deleteService(id, delete_reminders_using=true); + return; + } else console.log(e); });