Initial Commit
This commit is contained in:
parent
a14396e23c
commit
56827a66e8
108
index.html
Normal file
108
index.html
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>YAML Editor</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
color: #212529;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
background-color: #007bff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 20px;
|
||||||
|
margin: 10px 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/vanjs-org/van/public/van-1.2.7.nomodule.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container" id="appContainer">
|
||||||
|
<label for="yamlContent"></label><textarea id="yamlContent" rows="10"></textarea><br>
|
||||||
|
<button class="button" onclick="loadData()">Reload Data</button>
|
||||||
|
<button class="button" onclick="saveData()">Save Data</button>
|
||||||
|
<div id="statusMessage"></div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function displayStatus(message) {
|
||||||
|
document.getElementById('statusMessage').textContent = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadData() {
|
||||||
|
try {
|
||||||
|
displayStatus('Loading data...');
|
||||||
|
const response = await fetch('/data');
|
||||||
|
if (!response.ok) {
|
||||||
|
displayStatus(`HTTP error! Status: ${response.status}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
if (typeof data !== 'object' || data === null || !('text' in data)) {
|
||||||
|
displayStatus('Invalid format in response data');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.getElementById('yamlContent').value = data.text || '';
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading data:', error);
|
||||||
|
displayStatus(`Failed to load data: ${error.message}`);
|
||||||
|
} finally {
|
||||||
|
displayStatus('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveData() {
|
||||||
|
const content = document.getElementById('yamlContent').value;
|
||||||
|
displayStatus('Saving data...');
|
||||||
|
fetch('/data', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ text: content }),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(data => {
|
||||||
|
alert(data);
|
||||||
|
displayStatus('');
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
displayStatus('Failed to save data.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
105
main.py
Normal file
105
main.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
"""
|
||||||
|
Flask app for YAML file I/O.
|
||||||
|
|
||||||
|
Provides web interface for reading and updating YAML file content.
|
||||||
|
Handles HTTP GET (view) and POST (update) at '/data', and serves index page at '/'.
|
||||||
|
|
||||||
|
Author: Isaak Buslovich
|
||||||
|
Date: 2023-12-21
|
||||||
|
"""
|
||||||
|
from flask import Flask, request, jsonify, send_from_directory
|
||||||
|
import yaml
|
||||||
|
from pathlib import Path
|
||||||
|
import logging
|
||||||
|
|
||||||
|
app = Flask(__name__, static_folder='.', static_url_path='')
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
DATA_FILE = 'data.yaml'
|
||||||
|
|
||||||
|
|
||||||
|
def read_yaml():
|
||||||
|
"""
|
||||||
|
Reads and returns content from the YAML file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: A dictionary with the key 'text' containing file content.
|
||||||
|
None: If an error occurs, along with an error message.
|
||||||
|
"""
|
||||||
|
file_path = Path(DATA_FILE)
|
||||||
|
try:
|
||||||
|
if not file_path.is_file():
|
||||||
|
logging.info("YAML file not found. Returning empty data.")
|
||||||
|
return {'text': ''}, None
|
||||||
|
with file_path.open() as file:
|
||||||
|
data = yaml.safe_load(file) or {}
|
||||||
|
return {'text': data.get('text', '')}, None
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
logging.error(f"YAML Error: {e}", exc_info=True)
|
||||||
|
return None, f"YAML parsing error: {e}"
|
||||||
|
except IOError as e:
|
||||||
|
logging.error(f"IO Error: {e}", exc_info=True)
|
||||||
|
return None, f"File I/O error: {e}"
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Unexpected Error: {e}", exc_info=True)
|
||||||
|
return None, f"Unexpected error: {e}"
|
||||||
|
|
||||||
|
|
||||||
|
def write_yaml(content):
|
||||||
|
"""
|
||||||
|
Writes content to the YAML file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
content (str): The text content to be saved in the file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the operation was successful, False otherwise.
|
||||||
|
None: If successful, or an error message if an error occurs.
|
||||||
|
"""
|
||||||
|
file_path = Path(DATA_FILE)
|
||||||
|
try:
|
||||||
|
with file_path.open('w') as file:
|
||||||
|
yaml.dump({'text': content}, file)
|
||||||
|
return True, None
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error writing YAML file: {e}", exc_info=True)
|
||||||
|
return False, f"Error writing file: {e}"
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/data', methods=['GET', 'POST'])
|
||||||
|
def handle_data():
|
||||||
|
"""
|
||||||
|
Handles GET and POST requests to '/data'.
|
||||||
|
GET: Returns the content of the YAML file.
|
||||||
|
POST: Updates the content of the YAML file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON response for GET requests.
|
||||||
|
Text message for POST requests.
|
||||||
|
"""
|
||||||
|
if request.method == 'GET':
|
||||||
|
data, error = read_yaml()
|
||||||
|
if error:
|
||||||
|
return error, 500
|
||||||
|
return jsonify(data), 200
|
||||||
|
elif request.method == 'POST':
|
||||||
|
content = request.json.get('text', '')
|
||||||
|
success, error = write_yaml(content)
|
||||||
|
if error:
|
||||||
|
return error, 500
|
||||||
|
return "File saved successfully", 200
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
"""
|
||||||
|
Serves the main index HTML page.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
HTML content of the main page.
|
||||||
|
"""
|
||||||
|
return send_from_directory('.', 'index.html')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True)
|
||||||
Loading…
Reference in New Issue
Block a user