Redesign UI with dropdown sound selection
Major UI Overhaul: - Replace individual buttons with dropdown selectors - New "Sound Assignment" card with 3 dropdowns: * Greeting Sound (plays on pickup) * Button Sound (plays when button pressed) * Recording Beep (plays before recording) - Rename "Greeting Messages" to "Available Sounds" - Show sound usage badges (⭐🔘📣) in sound list - Cleaner, more intuitive interface Benefits: - Easier to see which sound is assigned where - One click to change assignments - Less clutter with fewer buttons - Shows duration in dropdown options - Better visual hierarchy Template v1.5.0 - will auto-regenerate on restart 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -81,7 +81,7 @@ BACKUP_ON_WRITE = BACKUP_CONFIG.get('backup_on_write', True)
|
|||||||
WEB_PORT = SYS_CONFIG['web']['port']
|
WEB_PORT = SYS_CONFIG['web']['port']
|
||||||
|
|
||||||
# Template version - increment this when HTML template changes
|
# Template version - increment this when HTML template changes
|
||||||
TEMPLATE_VERSION = "1.4.0" # Updated: Added recording beep sound feature
|
TEMPLATE_VERSION = "1.5.0" # Updated: Redesigned sound selection with dropdowns
|
||||||
|
|
||||||
# Flask app
|
# Flask app
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
@@ -1176,7 +1176,28 @@ def main():
|
|||||||
.upload-label:hover {
|
.upload-label:hover {
|
||||||
background: #5568d3;
|
background: #5568d3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sound-selector {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 1em;
|
||||||
|
border: 2px solid #e5e7eb;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sound-selector:hover {
|
||||||
|
border-color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sound-selector:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #667eea;
|
||||||
|
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -1555,20 +1576,62 @@ def main():
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Greeting Messages Card -->
|
<!-- Sound Assignment Card -->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>🎵 Greeting Messages</h2>
|
<h2>🎵 Sound Assignment</h2>
|
||||||
|
|
||||||
<div class="alert alert-info">
|
<div style="padding: 20px; border-bottom: 1px solid #e5e7eb;">
|
||||||
ℹ️ Active greeting: <strong>{{ active_greeting }}</strong>
|
<h3 style="margin: 0 0 15px 0; font-size: 1.1em; color: #333;">⭐ Greeting Sound</h3>
|
||||||
{% if extra_button_enabled %}
|
<p style="margin-bottom: 10px; color: #6b7280; font-size: 0.9em;">
|
||||||
<br>🔘 Extra button sound: <strong>{{ extra_button_sound }}</strong>
|
Plays when handset is picked up
|
||||||
{% endif %}
|
</p>
|
||||||
|
<select id="greeting-selector" class="sound-selector" onchange="setActiveGreeting(this.value)">
|
||||||
|
{% for greeting in greetings %}
|
||||||
|
<option value="{{ greeting.filename }}" {% if greeting.is_active %}selected{% endif %}>
|
||||||
|
{{ greeting.filename }} ({{ "%.1f"|format(greeting.duration) }}s)
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if extra_button_enabled %}
|
||||||
|
<div style="padding: 20px; border-bottom: 1px solid #e5e7eb;">
|
||||||
|
<h3 style="margin: 0 0 15px 0; font-size: 1.1em; color: #333;">🔘 Button Sound</h3>
|
||||||
|
<p style="margin-bottom: 10px; color: #6b7280; font-size: 0.9em;">
|
||||||
|
Plays when extra button is pressed during recording
|
||||||
|
</p>
|
||||||
|
<select id="button-selector" class="sound-selector" onchange="setExtraButtonSound(this.value)">
|
||||||
|
{% for greeting in greetings %}
|
||||||
|
<option value="{{ greeting.filename }}" {% if greeting.is_button_sound %}selected{% endif %}>
|
||||||
|
{{ greeting.filename }} ({{ "%.1f"|format(greeting.duration) }}s)
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div style="padding: 20px;">
|
||||||
|
<h3 style="margin: 0 0 15px 0; font-size: 1.1em; color: #333;">📣 Recording Beep</h3>
|
||||||
|
<p style="margin-bottom: 10px; color: #6b7280; font-size: 0.9em;">
|
||||||
|
Plays after greeting to signal recording start
|
||||||
|
</p>
|
||||||
|
<select id="beep-selector" class="sound-selector" onchange="setBeepSound(this.value)">
|
||||||
|
{% for greeting in greetings %}
|
||||||
|
<option value="{{ greeting.filename }}" {% if greeting.is_beep_sound %}selected{% endif %}>
|
||||||
|
{{ greeting.filename }} ({{ "%.1f"|format(greeting.duration) }}s)
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Available Sounds Card -->
|
||||||
|
<div class="card">
|
||||||
|
<h2>🔊 Available Sounds</h2>
|
||||||
|
|
||||||
<div class="upload-section">
|
<div class="upload-section">
|
||||||
<p style="margin-bottom: 15px; color: #6b7280;">
|
<p style="margin-bottom: 15px; color: #6b7280;">
|
||||||
Upload WAV files to play when the handset is picked up
|
Upload WAV audio files for greetings, button sounds, and beeps
|
||||||
</p>
|
</p>
|
||||||
<form id="upload-form" enctype="multipart/form-data">
|
<form id="upload-form" enctype="multipart/form-data">
|
||||||
<label for="soundfile" class="upload-label">
|
<label for="soundfile" class="upload-label">
|
||||||
@@ -1580,7 +1643,7 @@ def main():
|
|||||||
|
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
<button class="btn btn-primary" onclick="uploadGreeting()" id="upload-btn" disabled>
|
<button class="btn btn-primary" onclick="uploadGreeting()" id="upload-btn" disabled>
|
||||||
⬆️ Upload Greeting(s)
|
⬆️ Upload Sound(s)
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary" onclick="restoreDefault()">
|
<button class="btn btn-secondary" onclick="restoreDefault()">
|
||||||
🔄 Generate Default Dial Tone
|
🔄 Generate Default Dial Tone
|
||||||
@@ -1588,60 +1651,32 @@ def main():
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Greetings List -->
|
<!-- Sounds List -->
|
||||||
{% if greetings %}
|
{% if greetings %}
|
||||||
<h3 style="margin-top: 30px; margin-bottom: 15px; color: #333;">Available Greetings</h3>
|
<h3 style="margin-top: 30px; margin-bottom: 15px; color: #333;">Uploaded Sounds</h3>
|
||||||
<div class="recordings-grid">
|
<div class="recordings-grid">
|
||||||
{% for greeting in greetings %}
|
{% for greeting in greetings %}
|
||||||
<div class="recording-item {% if greeting.is_active %}active-greeting{% endif %}" id="greeting-{{ loop.index }}">
|
<div class="recording-item" id="greeting-{{ loop.index }}">
|
||||||
<div class="recording-info">
|
<div class="recording-info">
|
||||||
<h3>
|
<h3>{{ greeting.filename }}</h3>
|
||||||
{% if greeting.is_active %}⭐{% endif %}
|
|
||||||
{% if greeting.is_button_sound and extra_button_enabled %}🔘{% endif %}
|
|
||||||
{{ greeting.filename }}
|
|
||||||
</h3>
|
|
||||||
<div class="recording-meta">
|
<div class="recording-meta">
|
||||||
📅 {{ greeting.date }} |
|
📅 {{ greeting.date }} |
|
||||||
⏱️ {{ "%.1f"|format(greeting.duration) }}s |
|
⏱️ {{ "%.1f"|format(greeting.duration) }}s |
|
||||||
💾 {{ "%.2f"|format(greeting.size_mb) }} MB
|
💾 {{ "%.2f"|format(greeting.size_mb) }} MB
|
||||||
</div>
|
</div>
|
||||||
|
<div style="margin-top: 5px; font-size: 0.85em; color: #667eea;">
|
||||||
|
{% if greeting.is_active %}⭐ Active Greeting{% endif %}
|
||||||
|
{% if greeting.is_button_sound and extra_button_enabled %}{% if greeting.is_active %} | {% endif %}🔘 Button Sound{% endif %}
|
||||||
|
{% if greeting.is_beep_sound %}{% if greeting.is_active or greeting.is_button_sound %} | {% endif %}📣 Beep Sound{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="recording-actions">
|
<div class="recording-actions">
|
||||||
<button class="btn btn-success" onclick="playAudio('greeting', '{{ greeting.filename }}')">
|
<button class="btn btn-success" onclick="playAudio('greeting', '{{ greeting.filename }}')">
|
||||||
▶️ Play
|
▶️ Play
|
||||||
</button>
|
</button>
|
||||||
{% if not greeting.is_active %}
|
|
||||||
<button class="btn btn-primary" onclick="setActiveGreeting('{{ greeting.filename }}')">
|
|
||||||
⭐ Set Active
|
|
||||||
</button>
|
|
||||||
{% if extra_button_enabled and not greeting.is_button_sound %}
|
|
||||||
<button class="btn btn-primary" onclick="setExtraButtonSound('{{ greeting.filename }}')">
|
|
||||||
🔘 Set Button
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if not greeting.is_beep_sound %}
|
|
||||||
<button class="btn btn-primary" onclick="setBeepSound('{{ greeting.filename }}')">
|
|
||||||
📣 Set Beep
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
<button class="btn btn-danger" onclick="deleteGreeting('{{ greeting.filename }}', {{ loop.index }})">
|
<button class="btn btn-danger" onclick="deleteGreeting('{{ greeting.filename }}', {{ loop.index }})">
|
||||||
🗑️ Delete
|
🗑️ Delete
|
||||||
</button>
|
</button>
|
||||||
{% else %}
|
|
||||||
<button class="btn btn-secondary" disabled>
|
|
||||||
✓ Active
|
|
||||||
</button>
|
|
||||||
{% if extra_button_enabled and not greeting.is_button_sound %}
|
|
||||||
<button class="btn btn-primary" onclick="setExtraButtonSound('{{ greeting.filename }}')">
|
|
||||||
🔘 Set Button
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if not greeting.is_beep_sound %}
|
|
||||||
<button class="btn btn-primary" onclick="setBeepSound('{{ greeting.filename }}')">
|
|
||||||
📣 Set Beep
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -1649,7 +1684,7 @@ def main():
|
|||||||
{% else %}
|
{% else %}
|
||||||
<div class="no-recordings" style="margin-top: 20px;">
|
<div class="no-recordings" style="margin-top: 20px;">
|
||||||
<p style="font-size: 2em; margin-bottom: 10px;">🎵</p>
|
<p style="font-size: 2em; margin-bottom: 10px;">🎵</p>
|
||||||
<p>No greeting messages uploaded yet. Upload your first greeting!</p>
|
<p>No sounds uploaded yet. Upload your first sound file!</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user