#app.py
from flask import Flask, render_template, request, jsonify
from flask_socketio import SocketIO, emit
from flask_sqlalchemy import SQLAlchemy
import os

app = Flask(name)
app.config['SECRET_KEY'] = 'secret!'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///notes.db'
db = SQLAlchemy(app)
socketio = SocketIO(app)

class Note(db.Model):
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.String(500), nullable=False)
x = db.Column(db.Integer, nullable=False)
y = db.Column(db.Integer, nullable=False)

@app.route('/')
def index():
notes = Note.query.all()
return render_template('index.html', notes=notes)

@socketio.on('create_note')
def handle_create_note(data):
text = data['text']
x = data['x']
y = data['y']
new_note = Note(text=text, x=x, y=y)
db.session.add(new_note)
db.session.commit()
emit('new_note', {'id': new_note.id, 'text': text, 'x': x, 'y': y}, broadcast=True)

@socketio.on('update_note')
def handle_update_note(data):
note = Note.query.get(data['id'])
note.text = data['text']
note.x = data['x']
note.y = data['y']
db.session.commit()
emit('updated_note', {'id': note.id, 'text': note.text, 'x': note.x, 'y': note.y}, broadcast=True)

if name == 'main':
with app.app_context():
if not os.path.exists('notes.db'):
db.create_all()
socketio.run(app, debug=True, allow_unsafe_werkzeug=True)

#index.html

{% for note in notes %}
{{ note.text }}
{% endfor %}
Add Note
#style.css
body {
margin: 0;
padding: 0;
overflow: hidden;
}

#board {
position: relative;
width: 100vw;
height: 100vh;
background-color: #f0f0f0;
}

.note {
position: absolute;
width: 200px;
height: 200px;
background-color: #fff;
border: 1px solid #ccc;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
padding: 10px;
box-sizing: border-box;
cursor: move;
}

textarea {
width: 100%;
height: 100%;
border: none;
resize: none;
outline: none;
}

#add-note {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}

#main.js
const socket = io();

document.getElementById('add-note').addEventListener('click', () => {
const x = Math.floor(Math.random() * window.innerWidth);
const y = Math.floor(Math.random() * window.innerHeight);
socket.emit('create_note', { text: 'New Note', x, y });
});

socket.on('new_note', (data) => {
const note = createNoteElement(data);
document.getElementById('board').appendChild(note);
});

socket.on('updated_note', (data) => {
const note = document.querySelector(.note[data-id="${data.id}"]);
if (note) {
note.style.left = ${data.x}px;
note.style.top = ${data.y}px;
note.querySelector('textarea').value = data.text;
}
});

function createNoteElement(data) {
const note = document.createElement('div');
note.className = 'note';
note.dataset.id = data.id;
note.style.left = ${data.x}px;
note.style.top = ${data.y}px;

const textarea = document.createElement('textarea');
textarea.value = data.text;
textarea.addEventListener('input', () => {
socket.emit('update_note', { id: data.id, text: textarea.value, x: note.offsetLeft, y: note.offsetTop });
});

note.appendChild(textarea);

note.addEventListener('mousedown', (e) => {
e.preventDefault();
let offsetX = e.clientX - note.offsetLeft;
let offsetY = e.clientY - note.offsetTop;

function moveNote(e) {
note.style.left = ${e.clientX - offsetX}px;
note.style.top = ${e.clientY - offsetY}px;
socket.emit('update_note', { id: data.id, text: textarea.value, x: note.offsetLeft, y: note.offsetTop });
}

document.addEventListener('mousemove', moveNote);

document.addEventListener('mouseup', () => {
document.removeEventListener('mousemove', moveNote);
}, { once: true });
});

return note;
}

У меня проблема при первом запуске приложения я могу перемещать заметку, но не могу менять текст. Но при перезапуске приложения я могу менять текст, но не могу двигать заметку. Мне надо что бы всегда была возможность и перемещать и менять текст в заметке