updated upload functions

This commit is contained in:
2025-05-15 11:23:49 +03:00
parent de7e234da1
commit ebb9bf4583
11 changed files with 107 additions and 60 deletions

View File

@@ -58,7 +58,6 @@ COPY --from=build /root/.cargo /root/.cargo
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install gunicorn
RUN apt-get update && apt-get install -y libreoffice poppler-utils
# Make port 5000 available to the world outside this container
EXPOSE 5000

Binary file not shown.

90
app.py
View File

@@ -8,6 +8,10 @@ from functools import wraps
from extensions import db, bcrypt, login_manager
from models import User, Player, Content, Group # Add Group to the imports
from flask_login import login_user, logout_user, login_required, current_user
from pptx import Presentation
from pptx.util import Inches
from PIL import Image
import io
app = Flask(__name__, instance_relative_config=True)
@@ -55,6 +59,10 @@ def convert_ppt_to_pdf(input_file, output_file):
command = ['libreoffice', '--headless', '--convert-to', 'pdf', '--outdir', os.path.dirname(output_file), input_file]
subprocess.run(command, check=True)
# Convert EMU to pixels
def emu_to_pixels(emu):
return int(emu / 914400 * 96)
@app.route('/')
@login_required
def dashboard():
@@ -107,50 +115,61 @@ def upload_content():
duration = int(request.form['duration'])
return_url = request.form['return_url']
media_type = request.form['media_type']
print(f"Redirecting to: {return_url}") # Debugging: Log the return_url
for file in files:
filename = secure_filename(file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(file_path)
# Handle PDF to JPG conversion
if media_type == 'pdf':
images = convert_from_path(file_path, dpi=300)
for i, image in enumerate(images):
image_filename = f"{os.path.splitext(filename)[0]}_{i + 1}.jpg"
image_path = os.path.join(app.config['UPLOAD_FOLDER'], image_filename)
image.save(image_path, 'JPEG')
# Add each converted image to the playlist
if target_type == 'group':
group = Group.query.get_or_404(target_id)
for player in group.players:
new_content = Content(file_name=image_filename, duration=duration, player_id=player.id)
# Handle PPT/PPTX to JPG conversion
if media_type == 'ppt':
try:
presentation = Presentation(file_path)
for i, slide in enumerate(presentation.slides):
slide_width = emu_to_pixels(presentation.slide_width)
slide_height = emu_to_pixels(presentation.slide_height)
img = Image.new('RGB', (slide_width, slide_height), 'white')
# Save the slide as an image
image_filename = f"{os.path.splitext(filename)[0]}_slide_{i + 1}.jpg"
image_path = os.path.join(app.config['UPLOAD_FOLDER'], image_filename)
img.save(image_path, 'JPEG')
# Add each converted image to the playlist
if target_type == 'group':
group = Group.query.get_or_404(target_id)
for player in group.players:
new_content = Content(file_name=image_filename, duration=duration, player_id=player.id)
db.session.add(new_content)
elif target_type == 'player':
new_content = Content(file_name=image_filename, duration=duration, player_id=target_id)
db.session.add(new_content)
elif target_type == 'player':
new_content = Content(file_name=image_filename, duration=duration, player_id=target_id)
db.session.add(new_content)
# Optionally, delete the original PDF file after conversion
os.remove(file_path)
finally:
# Ensure the original PPT file is deleted after processing
if os.path.exists(file_path):
os.remove(file_path)
# Handle other media types
elif media_type in ['image', 'video', 'ppt']:
if media_type == 'ppt':
ppt_output_file = os.path.splitext(file_path)[0] + '.pdf'
convert_ppt_to_pdf(file_path, ppt_output_file)
os.remove(file_path) # Remove the original PPT file
file_path = ppt_output_file
elif media_type in ['image', 'video', 'pdf']:
if media_type == 'pdf':
images = convert_from_path(file_path, dpi=300)
for i, image in enumerate(images):
image_filename = f"{os.path.splitext(filename)[0]}_{i + 1}.jpg"
image_path = os.path.join(app.config['UPLOAD_FOLDER'], image_filename)
image.save(image_path, 'JPEG')
if target_type == 'group':
group = Group.query.get_or_404(target_id)
for player in group.players:
new_content = Content(file_name=image_filename, duration=duration, player_id=player.id)
db.session.add(new_content)
elif target_type == 'player':
new_content = Content(file_name=image_filename, duration=duration, player_id=target_id)
db.session.add(new_content)
if os.path.exists(file_path):
os.remove(file_path)
if target_type == 'group':
group = Group.query.get_or_404(target_id)
for player in group.players:
new_content = Content(file_name=filename, duration=duration, player_id=player.id)
db.session.add(new_content)
elif target_type == 'player':
new_content = Content(file_name=filename, duration=duration, player_id=target_id)
db.session.add(new_content)
db.session.commit()
return redirect(return_url)
@@ -158,7 +177,6 @@ def upload_content():
target_id = request.args.get('target_id')
return_url = request.args.get('return_url', url_for('dashboard'))
# Serialize players and groups into JSON-serializable dictionaries
players = [{'id': player.id, 'username': player.username} for player in Player.query.filter(~Player.groups.any()).all()]
groups = [{'id': group.id, 'name': group.name} for group in Group.query.all()]

View File

@@ -19,3 +19,4 @@ services:
# when setting allready exist and data are setted and is performed an update use second line of command
command: sh -c "python clear_db.py && python init_db.py && gunicorn -w 4 -b 0.0.0.0:5000 app:app"
#command: sh -c "python init_db.py && gunicorn -w 4 -b 0.0.0.0:5000 app:app"
restart: unless-stopped

Binary file not shown.

View File

@@ -18,4 +18,5 @@ Werkzeug==3.1.3
gunicorn==20.1.0
pdf2image==1.17.0
pillow==11.1.0
python-pptx==0.6.21
setuptools==75.8.0

BIN
static/uploads/merged_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 KiB

BIN
static/uploads/merged_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 KiB

View File

Before

Width:  |  Height:  |  Size: 414 KiB

After

Width:  |  Height:  |  Size: 414 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -15,22 +15,24 @@
.dark-mode label, .dark-mode th, .dark-mode td {
color: #ffffff;
}
.popup-message {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 20px;
border-radius: 10px;
display: none;
z-index: 1000;
}
.logo {
max-height: 100px;
margin-right: 20px;
}
/* Modal styling for dark mode */
.modal-content.dark-mode {
background-color: #1e1e1e;
color: #ffffff;
}
.modal-header.dark-mode {
border-bottom: 1px solid #444;
}
.modal-footer.dark-mode {
border-top: 1px solid #444;
}
.progress-bar {
background-color: #007bff;
}
</style>
</head>
<body class="{{ 'dark-mode' if theme == 'dark' else '' }}">
@@ -41,7 +43,7 @@
{% endif %}
<h1 class="mb-0">Upload Content</h1>
</div>
<form id="upload-form" action="{{ url_for('upload_content') }}" method="post" enctype="multipart/form-data" onsubmit="showPopupMessage('Content uploaded successfully!')">
<form id="upload-form" action="{{ url_for('upload_content') }}" method="post" enctype="multipart/form-data" onsubmit="showStatusModal()">
<input type="hidden" name="return_url" value="{{ return_url }}">
<div class="mb-3">
<label for="target_type" class="form-label">Target Type:</label>
@@ -91,13 +93,31 @@
<label for="duration" class="form-label">Duration (seconds):</label>
<input type="number" name="duration" id="duration" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
<button type="submit" id="submit-button" class="btn btn-primary">Upload</button>
</form>
<a href="{{ return_url }}" class="btn btn-secondary mt-3">Back</a>
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary mt-3">Back to Dashboard</a>
</div>
<div id="popup-message" class="popup-message"></div>
<!-- Modal for Status Updates -->
<div class="modal fade" id="statusModal" tabindex="-1" aria-labelledby="statusModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content {{ 'dark-mode' if theme == 'dark' else '' }}">
<div class="modal-header {{ 'dark-mode' if theme == 'dark' else '' }}">
<h5 class="modal-title" id="statusModalLabel">Processing Files</h5>
</div>
<div class="modal-body">
<p id="status-message">Uploading and processing your files. Please wait...</p>
<div class="progress">
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<div class="modal-footer {{ 'dark-mode' if theme == 'dark' else '' }}">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" disabled>Close</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
<script>
@@ -147,14 +167,22 @@
}
});
function showPopupMessage(message) {
const popup = document.getElementById('popup-message');
popup.textContent = message;
popup.style.display = 'block';
setTimeout(() => {
popup.style.display = 'none';
document.getElementById('upload-form').submit();
}, 5000); // Display time set to 5 seconds
function showStatusModal() {
const statusModal = new bootstrap.Modal(document.getElementById('statusModal'));
statusModal.show();
// Simulate progress updates
const progressBar = document.getElementById('progress-bar');
let progress = 0;
const interval = setInterval(() => {
progress += 10;
progressBar.style.width = `${progress}%`;
progressBar.setAttribute('aria-valuenow', progress);
if (progress >= 100) {
clearInterval(interval);
document.getElementById('status-message').textContent = 'Files uploaded and processed successfully!';
}
}, 500);
}
</script>
</body>