Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .traefik.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ testData:
enabled: true
maxEntries: 100
sessionTime: 1m
queuePageFile: queue-page.html
queuePageFile: "/var/public/queue-page.html"
queueTranslationsFile: "/var/public/translations.json"
useCookies: true
cookieName: queue-manager-id
58 changes: 37 additions & 21 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# docker-compose.yml
version: "3.6"

services:
traefik:
image: traefik:v3.3.4
container_name: traefik
image: traefik:v3.6
command:
- --log.level=INFO
- --api
Expand All @@ -21,34 +17,54 @@ services:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./:/plugins-local/src/github.com/hhftechnology/traefik-queue-manager
labels:
- traefik.http.middlewares.queuemanager.plugin.queuemanager.enabled=true
- traefik.http.middlewares.queuemanager.plugin.queuemanager.queuePageFile=/plugins-local/src/github.com/hhftechnology/traefik-queue-manager/queue-page.html
- traefik.http.middlewares.queuemanager.plugin.queuemanager.maxEntries=5
- traefik.http.middlewares.queuemanager.plugin.queuemanager.sessionTime=1m
- traefik.http.middlewares.queuemanager.plugin.queuemanager.purgeTime=5m
- traefik.http.middlewares.queuemanager.plugin.queuemanager.useCookies=true
- traefik.http.middlewares.queuemanager.plugin.queuemanager.cookieName=queue-manager-id
- traefik.http.middlewares.queuemanager.plugin.queuemanager.refreshInterval=30
- traefik.http.middlewares.queuemanager.plugin.queuemanager.debug=true
- ./public:/var/public

whoami:
image: traefik/whoami
container_name: whoami-service
depends_on:
- traefik
networks:
- traefik-network
deploy:
replicas: 3
volumes:
- ./:/plugins-local/src/github.com/hhftechnology/traefik-queue-manager
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`whoami.local`)
- traefik.http.routers.whoami.rule=Host(`localhost`)
- traefik.http.routers.whoami.entrypoints=web
- traefik.http.routers.whoami.service=whoami-service
- traefik.http.services.whoami-service.loadbalancer.server.port=80
- traefik.http.routers.whoami.middlewares=queuemanager
- traefik.http.routers.whoami.middlewares=qm1
- traefik.http.middlewares.qm1.plugin.queuemanager.enabled=true
- traefik.http.middlewares.qm1.plugin.queuemanager.maxEntries=1
- traefik.http.middlewares.qm1.plugin.queuemanager.sessionTime=1m
- traefik.http.middlewares.qm1.plugin.queuemanager.purgeTime=5m
- traefik.http.middlewares.qm1.plugin.queuemanager.useCookies=true
- traefik.http.middlewares.qm1.plugin.queuemanager.cookieName=queue-manager-id
- traefik.http.middlewares.qm1.plugin.queuemanager.refreshInterval=30
- traefik.http.middlewares.qm1.plugin.queuemanager.debug=true

nginx:
image: nginx
depends_on:
- traefik
networks:
- traefik-network
labels:
- traefik.enable=true
- traefik.http.routers.service2.rule=Host(`127.0.0.1`)
- traefik.http.routers.service2.entrypoints=web
- traefik.http.routers.service2.service=nginx-service
- traefik.http.services.nginx-service.loadbalancer.server.port=80
- traefik.http.routers.service2.middlewares=qm2
- traefik.http.middlewares.qm2.plugin.queuemanager.enabled=true
- traefik.http.middlewares.qm2.plugin.queuemanager.maxEntries=2
- traefik.http.middlewares.qm2.plugin.queuemanager.sessionTime=1m
- traefik.http.middlewares.qm2.plugin.queuemanager.purgeTime=5m
- traefik.http.middlewares.qm2.plugin.queuemanager.useCookies=true
- traefik.http.middlewares.qm2.plugin.queuemanager.cookieName=queue-manager-id
- traefik.http.middlewares.qm2.plugin.queuemanager.refreshInterval=30
- traefik.http.middlewares.qm2.plugin.queuemanager.debug=true

networks:
traefik-network:
driver: bridge
driver: bridge
32 changes: 15 additions & 17 deletions queue-page.html → public/queue-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Service Queue - Please Wait</title>
<title>[[.Translations.PageTitle]]</title>

<meta http-equiv="refresh" content="[[.RefreshInterval]];url=./"> <meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate, max-age=0, s-maxage=0">
<meta http-equiv="refresh" content="[[.QueueData.RefreshInterval]];url=./"> <meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate, max-age=0, s-maxage=0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0"> <style>
body {
Expand Down Expand Up @@ -49,7 +49,7 @@
}
.progress-bar {
height: 28px; /* Taller progress bar */
width: [[.ProgressPercentage]]%; /* Dynamically set width */
width: [[.QueueData.ProgressPercentage]]%; /* Dynamically set width */
background: linear-gradient(90deg, #007bff, #0056b3); /* Blue gradient */
border-radius: 8px; /* Match container's rounding */
text-align: center;
Expand Down Expand Up @@ -98,7 +98,7 @@
font-size: 0.8em;
color: #444;
word-break: break-all;
display: [[if .DebugInfo]]block[[else]]none[[end]]; /* Conditional display */
display: [[if .QueueData.DebugInfo]]block[[else]]none[[end]]; /* Conditional display */
}
.debug-info pre {
white-space: pre-wrap; /* Allow wrapping for long debug lines */
Expand All @@ -123,39 +123,37 @@
</head>
<body>
<div class="container">
<div class="spinner"></div> <h1>You're in the Queue</h1>
<p>Our services are currently experiencing high demand. Your patience is appreciated. You will be automatically redirected when it's your turn.</p>
<div class="spinner"></div> <h1>[[.Translations.Title]]</h1>
<p>[[.Translations.Introduction]]</p>

<div class="progress-container">
<div class="progress-bar">[[.ProgressPercentage]]%</div>
<div class="progress-bar">[[.QueueData.ProgressPercentage]]%</div>
</div>

<div class="info-grid">
<div class="info-box">
<strong>Your Position</strong>
<p>[[.Position]] / [[.QueueSize]]</p>
<strong>[[.Translations.YourPosition]]</strong>
<p>[[.QueueData.Position]] / [[.QueueData.QueueSize]]</p>
</div>
<div class="info-box">
<strong>Estimated Wait Time</strong>
<p>~[[.EstimatedWaitTime]] min(s)</p>
<strong>[[.Translations.ETA]]</strong>
<p>~[[.QueueData.EstimatedWaitTime]] [[.Translations.Mins]]</p>
</div>
</div>

<p>[[.Message]]</p>

<div class="countdown-message">
This page will automatically refresh in <strong id="countdown">[[.RefreshInterval]]</strong> seconds.
[[ printf .Translations.RefreshTime .QueueData.RefreshInterval | safeHtml ]]
</div>

<div class="debug-info">
<strong>Debug Information:</strong>
<pre>[[.DebugInfo]]</pre>
<pre>[[.QueueData.DebugInfo]]</pre>
</div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
let countdownSeconds = parseInt("[[.RefreshInterval]]", 10);
let countdownSeconds = parseInt("[[.QueueData.RefreshInterval]]", 10);
const countdownElement = document.getElementById('countdown');

if (countdownElement) {
Expand Down Expand Up @@ -183,7 +181,7 @@
setTimeout(function() {
const cleanUrl = window.location.pathname;
window.location.href = cleanUrl + (cleanUrl.includes('?') ? '&' : '?') + 't_fallback=' + new Date().getTime();
}, (parseInt("[[.RefreshInterval]]", 10) -1) * 1000); // 1 second before meta refresh
}, (parseInt("[[.QueueData.RefreshInterval]]", 10) -1) * 1000); // 1 second before meta refresh
});
</script>
</body>
Expand Down
56 changes: 56 additions & 0 deletions public/translations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"en": {
"pageTitle": "Service Queue - Please Wait",
"title": "You're in the Queue",
"introduction": "Our services are currently experiencing high demand. Your patience is appreciated. You will be automatically redirected when it's your turn.",
"yourPosition": "Your Position",
"eta": "Estimated Wait Time",
"refreshTime": "This page will automatically refresh in <span id=\"countdown\">%d</span> seconds",
"mins": "min(s)"
},
"fr": {
"pageTitle": "File d’attente - Veuillez patienter",
"title": "Vous êtes dans la file d'attente",
"introduction": "Nos services rencontrent actuellement une forte demande. Merci pour votre patience. Vous serez automatiquement redirigé lorsque ce sera votre tour.",
"yourPosition": "Votre position",
"eta": "Temps d’attente estimé",
"refreshTime": "Cette page se rafraîchira automatiquement dans <span id=\"countdown\">%d</span> secondes",
"mins": "min(s)"
},
"es": {
"pageTitle": "Cola de servicio - Por favor espere",
"title": "Estás en la cola",
"introduction": "Nuestros servicios están experimentando una alta demanda. Agradecemos tu paciencia. Serás redirigido automáticamente cuando sea tu turno.",
"yourPosition": "Tu posición",
"eta": "Tiempo de espera estimado",
"refreshTime": "Esta página se actualizará automáticamente en <span id=\"countdown\">%d</span> segundos",
"mins": "min(s)"
},
"de": {
"pageTitle": "Warteschlange - Bitte warten",
"title": "Sie befinden sich in der Warteschlange",
"introduction": "Unsere Dienste verzeichnen derzeit eine hohe Nachfrage. Vielen Dank für Ihre Geduld. Sie werden automatisch weitergeleitet, wenn Sie an der Reihe sind.",
"yourPosition": "Ihre Position",
"eta": "Geschätzte Wartezeit",
"refreshTime": "Diese Seite wird in <span id=\"countdown\">%d</span> Sekunden automatisch aktualisiert",
"mins": "min(s)"
},
"pt": {
"pageTitle": "Fila de serviço - Por favor, aguarde",
"title": "Você está na fila",
"introduction": "Nossos serviços estão com alta demanda no momento. Agradecemos sua paciência. Você será redirecionado automaticamente quando for a sua vez.",
"yourPosition": "Sua posição",
"eta": "Tempo de espera estimado",
"refreshTime": "Esta página será atualizada automaticamente em <span id=\"countdown\">%d</span> segundos",
"mins": "min(s)"
},
"it": {
"pageTitle": "Coda del servizio - Attendere prego",
"title": "Sei in coda",
"introduction": "I nostri servizi stanno riscontrando un'alta domanda. Ti ringraziamo per la pazienza. Verrai reindirizzato automaticamente quando sarà il tuo turno.",
"yourPosition": "La tua posizione",
"eta": "Tempo di attesa stimato",
"refreshTime": "Questa pagina si aggiornerà automaticamente tra <span id=\"countdown\">%d</span> secondi",
"mins": "min(s)"
}
}
Loading
Loading