Question:
So I made an extension to be able to create, delete, and save tasks. I realized the JSON I was using, was being used for everyone, so I tried to make it so each person had their own JSON, or at the very least tasks under their username that the extension would use. I wasn’t able to get that working, and in the process of doing that creating tasks isn’t working. I am not getting any errors in my code either.
Repl link:
https://replit.com/@SalladShooter/To-Do-Extension
Flask →
from flask import Flask, render_template, request, jsonify
import json
import os
app = Flask(__name__)
def get_replit_username():
return os.environ.get("REPLIT_USER", "default_username")
def get_json_file_path(username):
return f'database/{username}_data.json'
def load_tasks(username):
json_file_path = get_json_file_path(username)
try:
with open(json_file_path, 'r') as file:
tasks = json.load(file)
except FileNotFoundError:
tasks = {'tasks': []}
return tasks.get('tasks', [])
def save_tasks(username, tasks):
json_file_path = get_json_file_path(username)
with open(json_file_path, 'w') as file:
json.dump({'tasks': tasks}, file)
@app.route('/tasks', methods=['GET'])
def get_tasks():
username = get_replit_username()
tasks = load_tasks(username)
return jsonify(tasks)
@app.route('/', methods=['GET', 'POST'])
def index():
username = get_replit_username()
if request.method == 'POST':
task_data = request.form.get('task_data')
if task_data:
tasks = load_tasks(username)
tasks.append({'taskText': task_data, 'completed': False})
save_tasks(username, tasks)
return jsonify({'status': 'success', 'message': 'Task added'})
tasks = load_tasks(username)
return render_template('index.html', tasks=tasks)
@app.route('/delete_task', methods=['POST'])
def delete_task():
username = get_replit_username()
task_data = request.form.get('task_data')
if task_data:
tasks = load_tasks(username)
if task_data in [task['taskText'] for task in tasks]:
tasks = [task for task in tasks if task['taskText'] != task_data]
save_tasks(username, tasks)
return jsonify({'status': 'success', 'message': 'Task deleted'})
return jsonify({'status': 'error', 'message': 'Task not found'})
@app.route('/update_task', methods=['POST'])
def update_task():
username = get_replit_username()
task_data = request.form.get('task_data')
completed = request.form.get('completed') == 'true'
if task_data:
tasks = load_tasks(username)
for task in tasks:
if task['taskText'] == task_data:
task['completed'] = completed
save_tasks(username, tasks)
return jsonify({'status': 'success', 'message': 'Task updated'})
return jsonify({'status': 'error', 'message': 'Task not found'})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
JS →
document.addEventListener('DOMContentLoaded', function () {
var createTaskButton = document.querySelector('.create-task');
var taskList = document.querySelector('.task-list');
createTaskButton.addEventListener('click', function () {
var taskText = prompt('Enter task name:');
if (taskText) {
var formData = new URLSearchParams();
formData.append('task_data', taskText);
fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData,
})
.then(response => response.json())
.then(data => {
console.log('Server response:', data);
addTask(taskText, false);
});
}
});
function addTask(taskText, completed) {
var taskElement = document.createElement('div');
taskElement.className = 'task';
var taskTextElement = document.createElement('span');
taskTextElement.textContent = taskText;
var cancelIconElement = document.createElement('span');
cancelIconElement.className = 'material-symbols-outlined cancel-icon';
cancelIconElement.textContent = 'cancel';
if (completed) {
taskElement.classList.add('completed');
}
taskElement.addEventListener('click', function () {
taskElement.classList.toggle('completed');
updateTaskStatus(taskText, taskElement.classList.contains('completed'));
});
function updateTaskStatus(taskText, completed) {
fetch('/update_task', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'task_data=' + encodeURIComponent(taskText) +
'&completed=' + completed,
})
.then(response => response.json())
.then(data => {
console.log('Server response:', data);
});
}
function deleteTask(taskText) {
fetch('/delete_task', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'task_data=' + encodeURIComponent(taskText),
})
.then(response => response.json())
.then(data => {
console.log('Server response:', data);
});
}
cancelIconElement.addEventListener('click', function (event) {
event.stopPropagation();
taskList.removeChild(taskElement);
});
taskElement.appendChild(taskTextElement);
taskElement.appendChild(cancelIconElement);
taskList.appendChild(taskElement);
}
cancelIconElement.addEventListener('click', function (event) {
event.stopPropagation();
taskList.removeChild(taskElement);
taskElement.appendChild(taskTextElement);
taskElement.appendChild(cancelIconElement);
taskList.appendChild(taskElement);
}
createTaskButton.addEventListener('click', function () {
var taskText = prompt('Enter task name:');
if (taskText) {
var formData = new URLSearchParams();
formData.append('task_data', taskText);
fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData,
})
.then(response => response.json())
.then(data => {
console.log('Server response:', data);
addTask(taskText, false);
});
}
});
fetch('/tasks')
.then(response => response.json())
.then(tasks => {
tasks.forEach(task => {
addTask(task.taskText, task.completed);
});
});
});