Fix orientation parameter handling and template URL endpoints

- Add orientation parameter support to create_group and edit_group functions
- Fix manage_group.html template URL endpoint from 'update_group_content_order' to 'update_group_content_order_route'
- Add orientation field and filtering to edit_group.html template with JavaScript functionality
- Update group_player_management.py to handle orientation validation in create and edit operations
- Fix docker-compose.yml to include build directive and correct volume paths
- Update entrypoint.sh to handle fresh deployments without migrations
- Ensure orientation consistency across group and player management

These changes resolve:
- Internal Server Error on manage_group page
- Missing orientation parameter in group creation/editing
- Template URL endpoint mismatches
- Docker deployment issues with fresh installations
This commit is contained in:
2025-08-01 15:15:59 -04:00
parent 70d76f45e7
commit 318f783de3
7 changed files with 76 additions and 18 deletions

6
app.py
View File

@@ -488,7 +488,8 @@ def create_group():
if request.method == 'POST':
group_name = request.form['name']
player_ids = request.form.getlist('players')
create_group_util(group_name, player_ids)
orientation = request.form.get('orientation', 'Landscape')
create_group_util(group_name, player_ids, orientation)
flash(f'Group "{group_name}" created successfully.', 'success')
return redirect(url_for('dashboard'))
players = Player.query.all()
@@ -514,7 +515,8 @@ def edit_group(group_id):
if request.method == 'POST':
name = request.form['name']
player_ids = request.form.getlist('players')
edit_group_util(group_id, name, player_ids)
orientation = request.form.get('orientation', group.orientation)
edit_group_util(group_id, name, player_ids, orientation)
flash(f'Group "{name}" updated successfully.', 'success')
return redirect(url_for('dashboard'))
players = Player.query.all()

View File

@@ -1,6 +1,7 @@
#version: '"1.1.0"'
services:
web:
build: .
image: digiserver:latest
ports:
- "8880:5000"
@@ -12,5 +13,5 @@ services:
- SECRET_KEY=Ma_Duc_Dupa_Merele_Lui_Ana
volumes:
- /opt/digi-s/instance:/app/instance
- /opt/digi-s/static/uploads:/app/static/uploads
- /opt/digi-s/uploads:/app/static/uploads
restart: unless-stopped

View File

@@ -7,16 +7,7 @@ mkdir -p instance
# Check if database exists
if [ ! -f instance/dashboard.db ]; then
echo "No database found, initializing..."
# Remove and recreate migrations directory to ensure clean state
rm -rf migrations
mkdir -p migrations
# Initialize the database
flask db init
flask db migrate -m "Initial migration"
flask db upgrade
echo "No database found, creating fresh database..."
# Create admin user if environment variables are set
if [ -n "$ADMIN_USER" ] && [ -n "$ADMIN_PASSWORD" ]; then
@@ -26,8 +17,11 @@ if [ ! -f instance/dashboard.db ]; then
echo "Warning: ADMIN_USER or ADMIN_PASSWORD not set, skipping admin creation"
fi
else
echo "Existing database found, applying migrations..."
flask db upgrade
echo "Existing database found, skipping initialization..."
echo "Creating admin user if needed..."
if [ -n "$ADMIN_USER" ] && [ -n "$ADMIN_PASSWORD" ]; then
flask create-admin --username "$ADMIN_USER" --password "$ADMIN_PASSWORD" 2>/dev/null || echo "Default user '$ADMIN_USER' already exists."
fi
fi
echo "Starting DigiServer..."

Binary file not shown.

View File

@@ -49,12 +49,24 @@
</select>
</div>
</div>
<div class="col-md-6 col-12">
<div class="mb-3">
<label for="orientation" class="form-label">Group Orientation</label>
<select class="form-control {{ 'dark-mode' if theme == 'dark' else '' }}" id="orientation" name="orientation" required>
<option value="Landscape" {% if group.orientation == 'Landscape' %}selected{% endif %}>Landscape</option>
<option value="Portret" {% if group.orientation == 'Portret' %}selected{% endif %}>Portret</option>
</select>
</div>
</div>
</div>
<!-- Add this above the player selection -->
<div class="alert alert-warning" role="alert">
<strong>Warning:</strong> Adding new players to this group will delete their individual playlists.
Removing players from the group will allow them to have their own playlists again.
</div>
<div id="orientation-warning" class="alert alert-danger d-none" role="alert">
No players with the selected orientation are available.
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Save Changes</button>
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary mt-3">Back to Dashboard</a>
@@ -62,5 +74,45 @@
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Get all players and their orientations from the backend
const players = [
{% for player in players %}
{id: {{ player.id }}, username: "{{ player.username }}", orientation: "{{ player.orientation }}", inGroup: {% if player in group.players %}true{% else %}false{% endif %}},
{% endfor %}
];
const orientationSelect = document.getElementById('orientation');
const playersSelect = document.getElementById('players');
const orientationWarning = document.getElementById('orientation-warning');
function filterPlayers() {
const selectedOrientation = orientationSelect.value;
const currentSelection = Array.from(playersSelect.selectedOptions).map(option => option.value);
playersSelect.innerHTML = '';
let compatibleCount = 0;
players.forEach(player => {
if (player.orientation === selectedOrientation) {
const option = document.createElement('option');
option.value = player.id;
option.textContent = player.username;
// Re-select if it was previously selected
if (currentSelection.includes(player.id.toString()) || player.inGroup) {
option.selected = true;
}
playersSelect.appendChild(option);
compatibleCount++;
}
});
orientationWarning.classList.toggle('d-none', compatibleCount > 0);
}
orientationSelect.addEventListener('change', filterPlayers);
// Initial filter on page load
filterPlayers();
</script>
</body>
</html>

View File

@@ -189,7 +189,7 @@ document.addEventListener('DOMContentLoaded', function() {
});
// Send to server
fetch('{{ url_for("update_group_content_order", group_id=group.id) }}', {
fetch('{{ url_for("update_group_content_order_route", group_id=group.id) }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',

View File

@@ -35,15 +35,24 @@ def create_group(name, player_ids, orientation='Landscape'):
log_group_created(name)
return new_group
def edit_group(group_id, name, player_ids):
def edit_group(group_id, name, player_ids, orientation=None):
"""
Edit an existing group, updating its name and players.
Edit an existing group, updating its name, orientation, and players.
Handles locking/unlocking players appropriately.
"""
group = Group.query.get_or_404(group_id)
old_name = group.name # Store old name in case it changes
group.name = name
# Update orientation if provided
if orientation:
group.orientation = orientation
# Validate that all selected players have the matching orientation
for player_id in player_ids:
player = Player.query.get(player_id)
if player and player.orientation != orientation:
raise ValueError(f"Player '{player.username}' has orientation '{player.orientation}', which does not match group orientation '{orientation}'.")
# Get current players in the group
current_player_ids = [player.id for player in group.players]