-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
from flask import Flask, render_template, request, redirect, url_for, jsonify, session | ||
import yaml | ||
import os | ||
|
||
app = Flask(__name__) | ||
app.secret_key = 'your_secret_key' | ||
|
||
YAML_DIR = '../' | ||
YAML_FILES = [] | ||
for root, dirs, files in os.walk(YAML_DIR): | ||
for file in files: | ||
if file.endswith('.yaml'): | ||
YAML_FILES.append(os.path.relpath(os.path.join(root, file), start=YAML_DIR)) | ||
|
||
def read_yaml(file_path): | ||
with open(file_path, 'r', encoding='utf-8') as file: | ||
return yaml.safe_load(file) | ||
|
||
def write_yaml(file_path, data): | ||
with open(file_path, 'w', encoding='utf-8') as file: | ||
yaml.dump(data, file, allow_unicode=True, sort_keys=True) | ||
|
||
@app.route('/') | ||
def index(): | ||
return render_template('index.html', files=YAML_FILES) | ||
|
||
@app.route('/edit/<path:filepath>', methods=['GET', 'POST']) | ||
def edit_file(filepath): | ||
file_path = os.path.join(YAML_DIR, filepath) | ||
|
||
if not os.path.exists(file_path): | ||
return f"File {filepath} not found.", 404 | ||
|
||
if request.method == 'POST': | ||
items = request.json.get('items', []) | ||
data = {'items': items} | ||
write_yaml(file_path, data) | ||
|
||
return jsonify({'success': True}) | ||
|
||
data = read_yaml(file_path) | ||
return render_template('edit.html', filename=filepath, items=data['items']) | ||
|
||
|
||
@app.route('/add-file', methods=['POST']) | ||
def add_file(): | ||
new_file = request.form.get('filename') | ||
|
||
if not new_file: | ||
session['error'] = 'Filename is required.' | ||
return redirect(url_for('index')) | ||
|
||
new_file = new_file.lstrip('/') | ||
|
||
if not new_file.endswith('.yaml'): | ||
new_file += '.yaml' | ||
|
||
path = os.path.join(YAML_DIR, new_file) | ||
|
||
if not path.startswith(os.path.abspath(YAML_DIR)): | ||
session['error'] = 'Invalid filename or directory traversal attempt.' | ||
return redirect(url_for('index')) | ||
|
||
if os.path.exists(path): | ||
session['error'] = 'File already exists.' | ||
return redirect(url_for('index')) | ||
|
||
try: | ||
write_yaml(path, {'items': []}) | ||
except Exception as e: | ||
session['error'] = f'Failed to create file: {e}' | ||
return redirect(url_for('index')) | ||
|
||
return redirect(url_for('index')) | ||
|
||
def redirect_with_error(error_message): | ||
""" | ||
Helper function to redirect with an error message. | ||
""" | ||
return redirect(url_for('index', error=error_message)) | ||
|
||
if __name__ == '__main__': | ||
os.makedirs(YAML_DIR, exist_ok=True) | ||
app.run(debug=True, port=5000) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Edit {{ filename }}</title> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> | ||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | ||
</head> | ||
<body> | ||
<div class="container mt-4"> | ||
<h1>Edit File: {{ filename }}</h1> | ||
<table class="table table-bordered" id="data-table"> | ||
<thead> | ||
<tr> | ||
<th>ID</th> | ||
<th>Text (EN)</th> | ||
<th>Text (FA)</th> | ||
<th>Actions</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{% for item in items %} | ||
<tr> | ||
<td><input class="form-control" value="{{ item.id }}" /></td> | ||
<td><input class="form-control" value="{{ item.text.en if item.text else '' }}" /></td> | ||
<td><input class="form-control" value="{{ item.text.fa if item.text else '' }}" /></td> | ||
<td> | ||
<button class="btn btn-danger btn-sm" onclick="deleteRow(this)">Delete</button> | ||
</td> | ||
</tr> | ||
{% endfor %} | ||
</tbody> | ||
</table> | ||
<button class="btn btn-success" onclick="addRow()">Add Row</button> | ||
<button class="btn btn-primary" onclick="save()">Save Changes</button> | ||
</div> | ||
|
||
<script> | ||
function addRow() { | ||
const table = document.getElementById('data-table').querySelector('tbody'); | ||
const row = document.createElement('tr'); | ||
row.innerHTML = ` | ||
<td><input class="form-control" value="" /></td> | ||
<td><input class="form-control" value="" /></td> | ||
<td><input class="form-control" value="" /></td> | ||
<td><button class="btn btn-danger btn-sm" onclick="deleteRow(this)">Delete</button></td> | ||
`; | ||
table.appendChild(row); | ||
} | ||
|
||
function deleteRow(button) { | ||
button.closest('tr').remove(); | ||
} | ||
|
||
function save() { | ||
const rows = document.getElementById('data-table').querySelectorAll('tbody tr'); | ||
const items = Array.from(rows).map(row => { | ||
const cells = row.querySelectorAll('input'); | ||
return { | ||
id: cells[0].value, | ||
text: { | ||
en: cells[1].value, | ||
fa: cells[2].value | ||
} | ||
}; | ||
}); | ||
axios.post(window.location.pathname, { items }) | ||
.then(response => alert('Saved successfully!')) | ||
.catch(error => alert('Failed to save.')); | ||
} | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Salam Admin Panel</title> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"> | ||
</head> | ||
<body class="container mt-5"> | ||
<h1>Salam Admin Panel</h1> | ||
|
||
{% if request.args.get('error') %} | ||
<div class="alert alert-danger" role="alert"> | ||
{{ request.args.get('error') }} | ||
</div> | ||
{% endif %} | ||
|
||
<form action="{{ url_for('add_file') }}" method="post" class="mb-4"> | ||
<div class="input-group"> | ||
<input type="text" name="filename" class="form-control" placeholder="Enter new filename"> | ||
<button type="submit" class="btn btn-primary">Add File</button> | ||
</div> | ||
</form> | ||
|
||
<ul class="list-group"> | ||
{% for file in files %} | ||
<li class="list-group-item"> | ||
<a href="{{ url_for('edit_file', filepath=file) }}">{{ file }}</a> | ||
</li> | ||
{% endfor %} | ||
</ul> | ||
</body> | ||
</html> |