mirror of
https://github.com/Casvt/MIND.git
synced 2026-02-19 11:54:46 -05:00
Fixes issue #9
This commit is contained in:
@@ -151,6 +151,18 @@ def setup_db() -> None:
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (notification_service) REFERENCES notification_services(id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS static_reminders(
|
||||
id INTEGER PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
text TEXT,
|
||||
notification_service INTEGER NOT NULL,
|
||||
|
||||
color VARCHAR(7),
|
||||
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (notification_service) REFERENCES notification_services(id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS config(
|
||||
key VARCHAR(255) PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
|
||||
@@ -96,7 +96,15 @@ class NotificationService:
|
||||
)
|
||||
if cursor.fetchone():
|
||||
raise NotificationServiceInUse('template')
|
||||
|
||||
|
||||
# Check if no static reminders exist with this service
|
||||
cursor.execute(
|
||||
"SELECT 1 FROM static_reminders WHERE notification_service = ? LIMIT 1;",
|
||||
(self.id,)
|
||||
)
|
||||
if cursor.fetchone():
|
||||
raise NotificationServiceInUse('static reminder')
|
||||
|
||||
cursor.execute(
|
||||
"DELETE FROM notification_services WHERE id = ?",
|
||||
(self.id,)
|
||||
|
||||
209
backend/static_reminders.py
Normal file
209
backend/static_reminders.py
Normal file
@@ -0,0 +1,209 @@
|
||||
#-*- coding: utf-8 -*-
|
||||
|
||||
from sqlite3 import IntegrityError
|
||||
from typing import List
|
||||
|
||||
from apprise import Apprise
|
||||
|
||||
from backend.custom_exceptions import NotificationServiceNotFound, ReminderNotFound
|
||||
from backend.db import get_db
|
||||
|
||||
|
||||
class StaticReminder:
|
||||
"""Represents a static reminder
|
||||
"""
|
||||
def __init__(self, reminder_id: int) -> None:
|
||||
self.id = reminder_id
|
||||
|
||||
# Check if reminder exists
|
||||
if not get_db().execute(
|
||||
"SELECT 1 FROM static_reminders WHERE id = ? LIMIT 1;",
|
||||
(self.id,)
|
||||
).fetchone():
|
||||
raise ReminderNotFound
|
||||
|
||||
def get(self) -> dict:
|
||||
"""Get info about the static reminder
|
||||
|
||||
Returns:
|
||||
dict: The info about the reminder
|
||||
"""
|
||||
reminder = get_db(dict).execute("""
|
||||
SELECT
|
||||
r.id,
|
||||
r.title, r.text,
|
||||
r.notification_service,
|
||||
ns.title AS notification_service_title,
|
||||
r.color
|
||||
FROM static_reminders r
|
||||
INNER JOIN notification_services ns
|
||||
ON r.notification_service = ns.id
|
||||
WHERE r.id = ?
|
||||
LIMIT 1;
|
||||
""",
|
||||
(self.id,)
|
||||
).fetchone()
|
||||
|
||||
return dict(reminder)
|
||||
|
||||
def update(
|
||||
self,
|
||||
title: str = None,
|
||||
notification_service: int = None,
|
||||
text: str = None,
|
||||
color: str = None
|
||||
) -> dict:
|
||||
"""Edit the static reminder
|
||||
|
||||
Args:
|
||||
title (str, optional): The new title of the entry. Defaults to None.
|
||||
notification_service (int, optional): The new id of the notification service to use to send the reminder. Defaults to None.
|
||||
text (str, optional): The new body of the reminder. Defaults to None.
|
||||
color (str, optional): The new hex code of the color of the reminder, which is shown in the web-ui. Defaults to None.
|
||||
|
||||
Raises:
|
||||
NotificationServiceNotFound: The notification service with the given id was not found
|
||||
|
||||
Returns:
|
||||
dict: The new static reminder info
|
||||
"""
|
||||
# Get current data and update it with new values
|
||||
data = self.get()
|
||||
new_values = {
|
||||
'title': title,
|
||||
'notification_service': notification_service,
|
||||
'text': text,
|
||||
'color': color
|
||||
}
|
||||
for k, v in new_values.items():
|
||||
if k == 'color' or v is not None:
|
||||
data[k] = v
|
||||
|
||||
# Update database
|
||||
try:
|
||||
get_db().execute("""
|
||||
UPDATE static_reminders
|
||||
SET
|
||||
title = ?, text = ?,
|
||||
notification_service = ?,
|
||||
color = ?
|
||||
WHERE id = ?;
|
||||
""",
|
||||
(data['title'], data['text'],
|
||||
data['notification_service'],
|
||||
data['color'],
|
||||
self.id)
|
||||
)
|
||||
except IntegrityError:
|
||||
raise NotificationServiceNotFound
|
||||
|
||||
return self.get()
|
||||
|
||||
def delete(self) -> None:
|
||||
"""Delete the static reminder
|
||||
"""
|
||||
get_db().execute("DELETE FROM static_reminders WHERE id = ?", (self.id,))
|
||||
return
|
||||
|
||||
class StaticReminders:
|
||||
"""Represents the static reminder library of the user account
|
||||
"""
|
||||
|
||||
def __init__(self, user_id: int) -> None:
|
||||
self.user_id = user_id
|
||||
|
||||
def fetchall(self) -> List[dict]:
|
||||
"""Get all static reminders
|
||||
|
||||
Returns:
|
||||
List[dict]: The id, title, text, notification_service, notification_service_title and color of each static reminder
|
||||
"""
|
||||
reminders: list = list(map(
|
||||
dict,
|
||||
get_db(dict).execute("""
|
||||
SELECT
|
||||
r.id,
|
||||
r.title, r.text,
|
||||
r.notification_service,
|
||||
ns.title AS notification_service_title,
|
||||
r.color
|
||||
FROM static_reminders r
|
||||
INNER JOIN notification_services ns
|
||||
ON r.notification_service = ns.id
|
||||
WHERE r.user_id = ?
|
||||
ORDER BY r.title, r.id;
|
||||
""",
|
||||
(self.user_id,)
|
||||
)
|
||||
))
|
||||
|
||||
return reminders
|
||||
|
||||
def fetchone(self, id: int) -> StaticReminder:
|
||||
"""Get one static reminder
|
||||
|
||||
Args:
|
||||
id (int): The id of the static reminder to fetch
|
||||
|
||||
Returns:
|
||||
StaticReminder: A StaticReminder instance
|
||||
"""
|
||||
return StaticReminder(id)
|
||||
|
||||
def add(
|
||||
self,
|
||||
title: str,
|
||||
notification_service: int,
|
||||
text: str = '',
|
||||
color: str = None
|
||||
) -> StaticReminder:
|
||||
"""Add a static reminder
|
||||
|
||||
Args:
|
||||
title (str): The title of the entry
|
||||
notification_service (int): The id of the notification service to use to send the reminder.
|
||||
text (str, optional): The body of the reminder. Defaults to ''.
|
||||
color (str, optional): The hex code of the color of the reminder, which is shown in the web-ui. Defaults to None.
|
||||
|
||||
Raises:
|
||||
NotificationServiceNotFound: The notification service with the given id was not found
|
||||
|
||||
Returns:
|
||||
StaticReminder: A StaticReminder instance representing the newly created static reminder
|
||||
"""
|
||||
try:
|
||||
id = get_db().execute("""
|
||||
INSERT INTO static_reminders(user_id, title, text, notification_service, color)
|
||||
VALUES (?,?,?,?,?);
|
||||
""",
|
||||
(self.user_id, title, text, notification_service, color)
|
||||
).lastrowid
|
||||
except IntegrityError:
|
||||
raise NotificationServiceNotFound
|
||||
|
||||
return self.fetchone(id)
|
||||
|
||||
def trigger_reminder(self, id: int) -> None:
|
||||
"""Trigger a static reminder to send it's reminder
|
||||
|
||||
Args:
|
||||
id (int): The id of the static reminder to trigger
|
||||
|
||||
Raises:
|
||||
ReminderNotFound: The static reminder with the given id was not found
|
||||
"""
|
||||
reminder = get_db(dict).execute("""
|
||||
SELECT r.title, r.text, ns.url
|
||||
FROM static_reminders r
|
||||
INNER JOIN notification_services ns
|
||||
ON r.notification_service = ns.id
|
||||
WHERE r.id = ?;
|
||||
""", (id,)).fetchone()
|
||||
if not reminder:
|
||||
raise ReminderNotFound
|
||||
reminder = dict(reminder)
|
||||
|
||||
a = Apprise()
|
||||
a.add(reminder['url'])
|
||||
a.notify(title=reminder['title'], body=reminder['text'])
|
||||
return
|
||||
@@ -6,6 +6,7 @@ from backend.db import get_db
|
||||
from backend.notification_service import NotificationServices
|
||||
from backend.reminders import Reminders
|
||||
from backend.security import generate_salt_hash, get_hash
|
||||
from backend.static_reminders import StaticReminders
|
||||
from backend.templates import Templates
|
||||
|
||||
ONEPASS_USERNAME_CHARACTERS = 'abcedfghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.!@$'
|
||||
@@ -64,6 +65,17 @@ class User:
|
||||
self.templates_instance = Templates(self.user_id)
|
||||
return self.templates_instance
|
||||
|
||||
@property
|
||||
def static_reminders(self) -> StaticReminders:
|
||||
"""Get access to the static reminders of the user account
|
||||
|
||||
Returns:
|
||||
StaticReminders: StaticReminders instance that can be used to access the static reminders of the user account
|
||||
"""
|
||||
if not hasattr(self, 'static_reminders_instance'):
|
||||
self.static_reminders_instance = StaticReminders(self.user_id)
|
||||
return self.static_reminders_instance
|
||||
|
||||
def edit_password(self, new_password: str) -> None:
|
||||
"""Change the password of the account
|
||||
|
||||
|
||||
130
frontend/api.py
130
frontend/api.py
@@ -1,9 +1,9 @@
|
||||
#-*- coding: utf-8 -*-
|
||||
|
||||
from os import urandom
|
||||
from re import compile
|
||||
from time import time as epoch_time
|
||||
from typing import Any, Tuple
|
||||
from re import compile
|
||||
|
||||
from flask import Blueprint, g, request
|
||||
|
||||
@@ -16,6 +16,7 @@ from backend.custom_exceptions import (AccessUnauthorized, InvalidKeyValue,
|
||||
from backend.notification_service import (NotificationService,
|
||||
NotificationServices)
|
||||
from backend.reminders import Reminders, reminder_handler, test_reminder
|
||||
from backend.static_reminders import StaticReminders
|
||||
from backend.templates import Template, Templates
|
||||
from backend.users import User, register_user
|
||||
|
||||
@@ -243,7 +244,7 @@ def api_add_user():
|
||||
user_id = register_user(username, password)
|
||||
return return_api({'user_id': user_id}, code=201)
|
||||
|
||||
@api.route('/user', methods=['PUT','DELETE'])
|
||||
@api.route('/user', methods=['PUT', 'DELETE'])
|
||||
@error_handler
|
||||
@auth
|
||||
def api_manage_user():
|
||||
@@ -287,7 +288,7 @@ def api_manage_user():
|
||||
# Notification service endpoints
|
||||
#===================
|
||||
|
||||
@api.route('/notificationservices', methods=['GET','POST'])
|
||||
@api.route('/notificationservices', methods=['GET', 'POST'])
|
||||
@error_handler
|
||||
@auth
|
||||
def api_notification_services_list():
|
||||
@@ -387,7 +388,7 @@ def api_notification_service(n_id: int):
|
||||
# Library endpoints
|
||||
#===================
|
||||
|
||||
@api.route('/reminders', methods=['GET','POST'])
|
||||
@api.route('/reminders', methods=['GET', 'POST'])
|
||||
@error_handler
|
||||
@auth
|
||||
def api_reminders_list():
|
||||
@@ -498,7 +499,7 @@ def api_test_reminder():
|
||||
test_reminder(title, notification_service, text)
|
||||
return return_api({}, code=201)
|
||||
|
||||
@api.route('/reminders/<int:r_id>', methods=['GET','PUT','DELETE'])
|
||||
@api.route('/reminders/<int:r_id>', methods=['GET', 'PUT', 'DELETE'])
|
||||
@error_handler
|
||||
@auth
|
||||
def api_get_reminder(r_id: int):
|
||||
@@ -677,3 +678,122 @@ def api_get_template(t_id: int):
|
||||
elif request.method == 'DELETE':
|
||||
template.delete()
|
||||
return return_api({})
|
||||
|
||||
#===================
|
||||
# Static reminder endpoints
|
||||
#===================
|
||||
|
||||
@api.route('/staticreminders', methods=['GET', 'POST'])
|
||||
@error_handler
|
||||
@auth
|
||||
def api_static_reminders_list():
|
||||
"""
|
||||
Endpoint: /staticreminders
|
||||
Description: Manage the static reminders
|
||||
Requires being logged in: Yes
|
||||
Methods:
|
||||
GET:
|
||||
Description: Get a list of all static reminders
|
||||
Returns:
|
||||
200:
|
||||
The id, title, text, notification_service, notification_service_title and color of each static reminder
|
||||
POST:
|
||||
Description: Add a static reminder
|
||||
Parameters (body):
|
||||
title (required): the title of the static reminder
|
||||
notification_service (required): the id of the notification service to use to send the notification
|
||||
text: the body of the static reminder
|
||||
color: The hex code of the color of the static reminder, which is shown in the web-ui
|
||||
Returns:
|
||||
200:
|
||||
The info about the new static reminder entry
|
||||
400:
|
||||
KeyNotFound: One of the required parameters was not given
|
||||
"""
|
||||
reminders: StaticReminders = g.user_data.static_reminders
|
||||
|
||||
if request.method == 'GET':
|
||||
result = reminders.fetchall()
|
||||
return return_api(result)
|
||||
|
||||
elif request.method == 'POST':
|
||||
data = request.get_json()
|
||||
title = extract_key(data, 'title')
|
||||
notification_service = extract_key(data, 'notification_service')
|
||||
text = extract_key(data, 'text', check_existence=False)
|
||||
color = extract_key(data, 'color', check_existence=False)
|
||||
|
||||
result = reminders.add(title=title,
|
||||
notification_service=notification_service,
|
||||
text=text,
|
||||
color=color)
|
||||
return return_api(result.get(), code=201)
|
||||
|
||||
@api.route('/staticreminders/<int:r_id>', methods=['GET', 'POST', 'PUT', 'DELETE'])
|
||||
@error_handler
|
||||
@auth
|
||||
def api_get_static_reminder(r_id: int):
|
||||
"""
|
||||
Endpoint: /staticreminders/<r_id>
|
||||
Description: Manage a specific static reminder
|
||||
Requires being logged in: Yes
|
||||
URL Parameters:
|
||||
<r_id>:
|
||||
The id of the static reminder
|
||||
Methods:
|
||||
GET:
|
||||
Returns:
|
||||
200:
|
||||
All info about the static reminder
|
||||
404:
|
||||
No static reminder found with the given id
|
||||
POST:
|
||||
Description: Trigger the static reminder
|
||||
Returns:
|
||||
200:
|
||||
Static reminder triggered successfully
|
||||
PUT:
|
||||
Description: Edit the static reminder
|
||||
Parameters (body):
|
||||
title: The new title of the static reminder.
|
||||
notification_service: The new id of the notification service to use to send the reminder.
|
||||
text: The new body of the static reminder.
|
||||
color: The new hex code of the color of the static reminder, which is shown in the web-ui.
|
||||
Returns:
|
||||
200:
|
||||
Static reminder updated successfully
|
||||
404:
|
||||
No static reminder found with the given id
|
||||
DELETE:
|
||||
Description: Delete the static reminder
|
||||
Returns:
|
||||
200:
|
||||
Static reminder deleted successfully
|
||||
404:
|
||||
No static reminder found with the given id
|
||||
"""
|
||||
reminders: StaticReminders = g.user_data.static_reminders
|
||||
if request.method == 'GET':
|
||||
result = reminders.fetchone(r_id).get()
|
||||
return return_api(result)
|
||||
|
||||
elif request.method == 'POST':
|
||||
reminders.trigger_reminder(r_id)
|
||||
return return_api({})
|
||||
|
||||
elif request.method == 'PUT':
|
||||
data = request.get_json()
|
||||
title = extract_key(data, 'title', check_existence=False)
|
||||
notification_service = extract_key(data, 'notification_service', check_existence=False)
|
||||
text = extract_key(data, 'text', check_existence=False)
|
||||
color = extract_key(data, 'color', check_existence=False)
|
||||
|
||||
result = reminders.fetchone(r_id).update(title=title,
|
||||
notification_service=notification_service,
|
||||
text=text,
|
||||
color=color)
|
||||
return return_api(result)
|
||||
|
||||
elif request.method == 'DELETE':
|
||||
reminders.fetchone(r_id).delete()
|
||||
return return_api({})
|
||||
|
||||
@@ -167,6 +167,31 @@ div.options > button {
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
/* Adding */
|
||||
/* */
|
||||
#info.show-add-reminder #delete-info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#info.show-add-static-reminder #time-input,
|
||||
#info.show-add-static-reminder #normal-button,
|
||||
#info.show-add-static-reminder #repeat-button,
|
||||
#info.show-add-static-reminder .repeat-bar,
|
||||
#info.show-add-static-reminder #delete-info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#info.show-add-static-reminder #text-input {
|
||||
margin-top: -1rem;
|
||||
}
|
||||
|
||||
#info.show-add-static-reminder #template-selection,
|
||||
#info.show-add-static-reminder #color-toggle,
|
||||
#info.show-add-static-reminder #notification-service-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info.show-add-template #template-selection,
|
||||
#info.show-add-template #time-input,
|
||||
#info.show-add-template #normal-button,
|
||||
@@ -181,15 +206,14 @@ div.options > button {
|
||||
margin-top: -1rem;
|
||||
}
|
||||
|
||||
#info.show-add-template form > *,
|
||||
#info.show-add-template .sub-inputs > * {
|
||||
#info.show-add-template #color-toggle,
|
||||
#info.show-add-template #notification-service-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info.show-add-reminder #delete-info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* */
|
||||
/* Editing */
|
||||
/* */
|
||||
#info.show-edit-reminder #template-selection,
|
||||
#info.show-edit-reminder #test-reminder {
|
||||
display: none;
|
||||
@@ -199,6 +223,23 @@ div.options > button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info.show-edit-static-reminder #template-selection,
|
||||
#info.show-edit-static-reminder #time-input,
|
||||
#info.show-edit-static-reminder #normal-button,
|
||||
#info.show-edit-static-reminder #repeat-button,
|
||||
#info.show-edit-static-reminder .repeat-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#info.show-edit-static-reminder #text-input {
|
||||
margin-top: -1rem;
|
||||
}
|
||||
|
||||
#info.show-edit-static-reminder #color-toggle,
|
||||
#info.show-edit-static-reminder #notification-service-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#info.show-edit-template #template-selection,
|
||||
#info.show-edit-template #time-input,
|
||||
#info.show-edit-template #normal-button,
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
|
||||
/* REMINDER LIST */
|
||||
#reminder-list,
|
||||
#static-reminder-list,
|
||||
#template-list {
|
||||
--gap: 1rem;
|
||||
--entry-width: 13rem;
|
||||
@@ -115,11 +116,6 @@ button.entry.fit {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#delete-template {
|
||||
border-color: var(--color-error);
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
@media (max-width: 543px) {
|
||||
header > div {
|
||||
transform: translateX(0);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const types = {
|
||||
'reminder': document.getElementById('reminder-list'),
|
||||
'static_reminder': document.getElementById('static-reminder-list'),
|
||||
'template': document.getElementById('template-list')
|
||||
};
|
||||
|
||||
@@ -9,7 +10,10 @@ const icons = {
|
||||
'delete': '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" width="256" height="256" x="0" y="0" viewBox="0 0 24 24" style="enable-background:new 0 0 512 512" xml:space="preserve"><g><g id="_01_align_center" data-name="01 align center"><path d="M22,4H17V2a2,2,0,0,0-2-2H9A2,2,0,0,0,7,2V4H2V6H4V21a3,3,0,0,0,3,3H17a3,3,0,0,0,3-3V6h2ZM9,2h6V4H9Zm9,19a1,1,0,0,1-1,1H7a1,1,0,0,1-1-1V6H18Z"></path><rect x="9" y="10" width="2" height="8"></rect><rect x="13" y="10" width="2" height="8"></rect></g></g></svg>'
|
||||
};
|
||||
|
||||
const info_classes = ['show-add-reminder', 'show-add-template', 'show-edit-reminder', 'show-edit-template'];
|
||||
const info_classes = [
|
||||
'show-add-reminder', 'show-add-template', 'show-add-static-reminder',
|
||||
'show-edit-reminder', 'show-edit-template', 'show-edit-static-reminder'
|
||||
];
|
||||
|
||||
function toggleNav() {
|
||||
document.querySelector('.nav-divider').classList.toggle('show-nav');
|
||||
|
||||
@@ -16,7 +16,7 @@ function showTab(button) {
|
||||
//
|
||||
function fillTable(table, results) {
|
||||
table.querySelectorAll('button.entry:not(.add-entry)').forEach(e => e.remove());
|
||||
|
||||
|
||||
results.forEach(r => {
|
||||
const entry = document.createElement('button');
|
||||
entry.classList.add('entry');
|
||||
@@ -75,6 +75,10 @@ function fillReminders() {
|
||||
fillLibrary(`/api/reminders?api_key=${api_key}`, types.reminder);
|
||||
};
|
||||
|
||||
function fillStaticReminders() {
|
||||
fillLibrary(`/api/staticreminders?api_key=${api_key}`, types.static_reminder);
|
||||
}
|
||||
|
||||
function fillTemplates() {
|
||||
fillLibrary(`/api/templates?api_key=${api_key}`, types.template);
|
||||
};
|
||||
@@ -110,6 +114,7 @@ document.querySelectorAll('.tab-selector > button').forEach(b => {
|
||||
});
|
||||
|
||||
fillReminders();
|
||||
fillStaticReminders();
|
||||
fillTemplates();
|
||||
setInterval(fillReminders, 60000);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ function showAdd(type) {
|
||||
inputs.notification_service.value = document.querySelector('#notification-service-input option[selected]').value;
|
||||
toggleNormal();
|
||||
toggleColor(true);
|
||||
document.getElementById('test-reminder').classList.remove('show-sent');
|
||||
|
||||
const cl = document.getElementById('info').classList;
|
||||
cl.forEach(c => {
|
||||
@@ -15,10 +16,17 @@ function showAdd(type) {
|
||||
if (type === types.reminder) {
|
||||
cl.add('show-add-reminder');
|
||||
document.querySelector('#info h2').innerText = 'Add a reminder';
|
||||
document.querySelector('#test-reminder > div:first-child').innerText = 'Test';
|
||||
inputs.time.setAttribute('required', '');
|
||||
} else if (type === types.template) {
|
||||
cl.add('show-add-template');
|
||||
document.querySelector('#info h2').innerText = 'Add a template';
|
||||
document.querySelector('#test-reminder > div:first-child').innerText = 'Test';
|
||||
inputs.time.removeAttribute('required');
|
||||
} else if (type === types.static_reminder) {
|
||||
cl.add('show-add-static-reminder');
|
||||
document.querySelector('#info h2').innerText = 'Add a static reminder';
|
||||
document.querySelector('#test-reminder > div:first-child').innerText = 'Test';
|
||||
inputs.time.removeAttribute('required');
|
||||
} else
|
||||
return;
|
||||
@@ -34,6 +42,11 @@ function showEdit(id, type) {
|
||||
url = `${url_prefix}/api/templates/${id}?api_key=${api_key}`;
|
||||
inputs.time.removeAttribute('required');
|
||||
type_buttons.repeat_interval.removeAttribute('required');
|
||||
} else if (type === types.static_reminder) {
|
||||
url = `${url_prefix}/api/staticreminders/${id}?api_key=${api_key}`;
|
||||
document.getElementById('test-reminder').classList.remove('show-sent');
|
||||
inputs.time.removeAttribute('required');
|
||||
type_buttons.repeat_interval.removeAttribute('required');
|
||||
} else return;
|
||||
|
||||
fetch(url)
|
||||
@@ -89,14 +102,26 @@ function showEdit(id, type) {
|
||||
if (type === types.reminder) {
|
||||
cl.add('show-edit-reminder');
|
||||
document.querySelector('#info h2').innerText = 'Edit a reminder';
|
||||
document.querySelector('#test-reminder > div:first-child').innerText = 'Test';
|
||||
} else if (type === types.template) {
|
||||
cl.add('show-edit-template');
|
||||
document.querySelector('#info h2').innerText = 'Edit a template';
|
||||
document.querySelector('#test-reminder > div:first-child').innerText = 'Test';
|
||||
} else if (type === types.static_reminder) {
|
||||
cl.add('show-edit-static-reminder');
|
||||
document.querySelector('#info h2').innerText = 'Edit a static reminder';
|
||||
document.querySelector('#test-reminder > div:first-child').innerText = 'Trigger';
|
||||
} else
|
||||
return;
|
||||
};
|
||||
|
||||
// code run on load
|
||||
|
||||
document.getElementById('add-reminder').addEventListener('click', e => showAdd(types.reminder));
|
||||
document.getElementById('add-reminder').addEventListener('click', e => {
|
||||
if (document.getElementById('add-reminder').classList.contains('error'))
|
||||
showWindow('notification');
|
||||
else
|
||||
showAdd(types.reminder);
|
||||
});
|
||||
document.getElementById('add-static-reminder').addEventListener('click', e => showAdd(types.static_reminder));
|
||||
document.getElementById('add-template').addEventListener('click', e => showAdd(types.template));
|
||||
|
||||
@@ -58,136 +58,3 @@ function applyTemplate() {
|
||||
// code run on load
|
||||
|
||||
loadTemplateSelection();
|
||||
|
||||
// function addTemplate() {
|
||||
// const data = {
|
||||
// 'title': template_inputs.title.value,
|
||||
// 'notification_service': template_inputs["notification-service"].value,
|
||||
// 'text': template_inputs.text.value,
|
||||
// 'color': null
|
||||
// };
|
||||
// if (!template_inputs.color.classList.contains('hidden')) {
|
||||
// data['color'] = template_inputs.color.querySelector('button[data-selected="true"]').dataset.color;
|
||||
// };
|
||||
// fetch(`${url_prefix}/api/templates?api_key=${api_key}`, {
|
||||
// 'method': 'POST',
|
||||
// 'headers': {'Content-Type': 'application/json'},
|
||||
// 'body': JSON.stringify(data)
|
||||
// })
|
||||
// .then(response => {
|
||||
// // catch errors
|
||||
// if (!response.ok) {
|
||||
// return Promise.reject(response.status);
|
||||
// };
|
||||
|
||||
// loadTemplateSelection();
|
||||
// closeAddTemplate();
|
||||
// return
|
||||
// })
|
||||
// .catch(e => {
|
||||
// if (e === 401) {
|
||||
// window.location.href = `${url_prefix}/`;
|
||||
// } else {
|
||||
// console.log(e);
|
||||
// };
|
||||
// });
|
||||
// };
|
||||
|
||||
// function closeAddTemplate() {
|
||||
// hideWindow();
|
||||
// setTimeout(() => {
|
||||
// template_inputs.title.value = '';
|
||||
// template_inputs['notification-service'].value = document.querySelector('#notification-service-template-input option[selected]').value;
|
||||
// template_inputs.text.value = '';
|
||||
// if (!template_inputs.color.classList.contains('hidden')) {
|
||||
// toggleColor(inputs.color);
|
||||
// };
|
||||
// }, 500);
|
||||
// };
|
||||
|
||||
// function showEditTemplate(id) {
|
||||
// fetch(`${url_prefix}/api/templates/${id}?api_key=${api_key}`)
|
||||
// .then(response => {
|
||||
// // catch errors
|
||||
// if (!response.ok) {
|
||||
// return Promise.reject(response.status);
|
||||
// };
|
||||
// return response.json();
|
||||
// })
|
||||
// .then(json => {
|
||||
// document.getElementById('template-edit-form').dataset.id = id;
|
||||
// edit_template_inputs.title.value = json.result.title;
|
||||
// edit_template_inputs['notification-service'].value = json.result.notification_service;
|
||||
// edit_template_inputs.text.value = json.result.text;
|
||||
// if (json.result.color !== null) {
|
||||
// if (edit_template_inputs.color.classList.contains('hidden')) {
|
||||
// toggleColor(edit_template_inputs.color);
|
||||
// };
|
||||
// selectColor(edit_template_inputs.color, json.result.color);
|
||||
// };
|
||||
// showWindow('edit-template');
|
||||
// })
|
||||
// .catch(e => {
|
||||
// if (e === 401) {
|
||||
// window.location.href = `${url_prefix}/`;
|
||||
// } else {
|
||||
// console.log(e);
|
||||
// };
|
||||
// });
|
||||
// };
|
||||
|
||||
// function saveTemplate() {
|
||||
// const id = document.getElementById('template-edit-form').dataset.id;
|
||||
// const data = {
|
||||
// 'title': edit_template_inputs.title.value,
|
||||
// 'notification_service': edit_template_inputs['notification-service'].value,
|
||||
// 'text': edit_template_inputs.text.value,
|
||||
// 'color': null
|
||||
// };
|
||||
// if (!edit_template_inputs.color.classList.contains('hidden')) {
|
||||
// data['color'] = edit_template_inputs.color.querySelector('button[data-selected="true"]').dataset.color;
|
||||
// };
|
||||
// fetch(`${url_prefix}/api/templates/${id}?api_key=${api_key}`, {
|
||||
// 'method': 'PUT',
|
||||
// 'headers': {'Content-Type': 'application/json'},
|
||||
// 'body': JSON.stringify(data)
|
||||
// })
|
||||
// .then(response => {
|
||||
// // catch errors
|
||||
// if (!response.ok) {
|
||||
// return Promise.reject(response.status);
|
||||
// };
|
||||
// loadTemplateSelection();
|
||||
// hideWindow();
|
||||
// })
|
||||
// .catch(e => {
|
||||
// if (e === 401) {
|
||||
// window.location.href = `${url_prefix}/`;
|
||||
// } else {
|
||||
// console.log(e);
|
||||
// };
|
||||
// });
|
||||
// };
|
||||
|
||||
// function deleteTemplate() {
|
||||
// const id = document.getElementById('template-edit-form').dataset.id;
|
||||
// fetch(`${url_prefix}/api/templates/${id}?api_key=${api_key}`, {
|
||||
// 'method': 'DELETE'
|
||||
// })
|
||||
// .then(response => {
|
||||
// // catch errors
|
||||
// if (!response.ok) {
|
||||
// return Promise.reject(response.status);
|
||||
// };
|
||||
|
||||
// loadTemplateSelection();
|
||||
// hideWindow();
|
||||
// })
|
||||
// .catch(e => {
|
||||
// if (e === 401) {
|
||||
// window.location.href = `${url_prefix}/`;
|
||||
// } else {
|
||||
// console.log(e);
|
||||
// };
|
||||
// });
|
||||
// };
|
||||
|
||||
@@ -63,24 +63,35 @@ function toggleRepeated() {
|
||||
|
||||
function testReminder() {
|
||||
const input = document.getElementById('test-reminder');
|
||||
if (inputs.title.value === '') {
|
||||
input.classList.add('error-input');
|
||||
input.title = 'No title set';
|
||||
return
|
||||
} else {
|
||||
input.classList.remove('error-input');
|
||||
input.removeAttribute('title');
|
||||
};
|
||||
const data = {
|
||||
'title': inputs.title.value,
|
||||
'notification_service': inputs.notification_service.value,
|
||||
'text': inputs.text.value
|
||||
};
|
||||
fetch(`${url_prefix}/api/reminders/test?api_key=${api_key}`, {
|
||||
const cl = document.getElementById('info').classList;
|
||||
const r_id = document.getElementById('info').dataset.id;
|
||||
const headers = {
|
||||
'method': 'POST',
|
||||
'headers': {'Content-Type': 'application/json'},
|
||||
'body': JSON.stringify(data)
|
||||
})
|
||||
'headers': {'Content-Type': 'application/json'}
|
||||
};
|
||||
let url;
|
||||
if (cl.contains('show-edit-static-reminder')) {
|
||||
// Trigger static reminder
|
||||
url = `${url_prefix}/api/staticreminders/${r_id}?api_key=${api_key}`;
|
||||
} else {
|
||||
// Test reminder draft
|
||||
if (inputs.title.value === '') {
|
||||
input.classList.add('error-input');
|
||||
input.title = 'No title set';
|
||||
return
|
||||
} else {
|
||||
input.classList.remove('error-input');
|
||||
input.removeAttribute('title');
|
||||
};
|
||||
const data = {
|
||||
'title': inputs.title.value,
|
||||
'notification_service': inputs.notification_service.value,
|
||||
'text': inputs.text.value
|
||||
};
|
||||
headers.body = JSON.stringify(data);
|
||||
url = `${url_prefix}/api/reminders/test?api_key=${api_key}`;
|
||||
};
|
||||
fetch(url, headers)
|
||||
.then(response => {
|
||||
if (!response.ok) return Promise.reject(response.status);
|
||||
input.classList.add('show-sent');
|
||||
@@ -103,6 +114,9 @@ function deleteInfo() {
|
||||
} else if (cl.contains('show-edit-template')) {
|
||||
// Delete template
|
||||
url = `${url_prefix}/api/templates/${e_id}?api_key=${api_key}`;
|
||||
} else if (cl.contains('show-edit-static-reminder')) {
|
||||
// Delete static reminder
|
||||
url = `${url_prefix}/api/staticreminders/${e_id}?api_key=${api_key}`;
|
||||
} else return;
|
||||
|
||||
fetch(url, {'method': 'DELETE'})
|
||||
@@ -111,6 +125,7 @@ function deleteInfo() {
|
||||
|
||||
fillNotificationSelection();
|
||||
fillReminders();
|
||||
fillStaticReminders();
|
||||
fillTemplates();
|
||||
hideWindow();
|
||||
})
|
||||
@@ -156,6 +171,11 @@ function submitInfo() {
|
||||
fetch_data.url = `${url_prefix}/api/templates?api_key=${api_key}`;
|
||||
fetch_data.method = 'POST';
|
||||
|
||||
} else if (cl.contains('show-add-static-reminder')) {
|
||||
// Add static reminder
|
||||
fetch_data.url = `${url_prefix}/api/staticreminders?api_key=${api_key}`;
|
||||
fetch_data.method = 'POST';
|
||||
|
||||
} else if (cl.contains('show-edit-reminder')) {
|
||||
// Edit reminder
|
||||
data['time'] = (new Date(inputs.time.value) / 1000) + (new Date(inputs.time.value).getTimezoneOffset() * 60)
|
||||
@@ -171,6 +191,11 @@ function submitInfo() {
|
||||
fetch_data.url = `${url_prefix}/api/templates/${e_id}?api_key=${api_key}`;
|
||||
fetch_data.method = 'PUT';
|
||||
|
||||
} else if (cl.contains('show-edit-static-reminder')) {
|
||||
// Edit a static reminder
|
||||
fetch_data.url = `${url_prefix}/api/staticreminders/${e_id}?api_key=${api_key}`;
|
||||
fetch_data.method = 'PUT';
|
||||
|
||||
} else return;
|
||||
|
||||
fetch(fetch_data.url, {
|
||||
@@ -182,6 +207,7 @@ function submitInfo() {
|
||||
if (!response.ok) return Promise.reject(response.status);
|
||||
|
||||
fillReminders();
|
||||
fillStaticReminders();
|
||||
fillTemplates();
|
||||
hideWindow();
|
||||
})
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
<div id="home">
|
||||
<div class="tab-selector">
|
||||
<button data-target="reminder-tab" data-selected="true">Reminders</button>
|
||||
<button data-target="static-reminder-tab">Static Reminders</button>
|
||||
<button data-target="template-tab">Templates</button>
|
||||
</div>
|
||||
<div id="reminder-tab">
|
||||
@@ -120,6 +121,19 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="static-reminder-tab" class="hidden">
|
||||
<div id="static-reminder-list">
|
||||
<button class="entry add-entry" id="add-static-reminder" aria-label="Add static reminder" title="Add static reminder">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" width="256" height="256" x="0" y="0" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M480,224H288V32c0-17.673-14.327-32-32-32s-32,14.327-32,32v192H32c-17.673,0-32,14.327-32,32s14.327,32,32,32h192v192 c0,17.673,14.327,32,32,32s32-14.327,32-32V288h192c17.673,0,32-14.327,32-32S497.673,224,480,224z"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="template-tab" class="hidden">
|
||||
<div id="template-list">
|
||||
<button class="entry add-entry" id="add-template" aria-label="Add template" title="Add template">
|
||||
|
||||
Reference in New Issue
Block a user