From 21a79f44a8b0b02079fc18b8b33d0828666b8f3c Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 9 Jun 2026 18:23:04 +0200 Subject: [PATCH] Added presenter mode for the event --- app.py | 5 + docker-compose.yml | 426 ++++++++++++++++++++ templates/presenter.html | 830 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 1261 insertions(+) create mode 100644 docker-compose.yml create mode 100644 templates/presenter.html diff --git a/app.py b/app.py index b2303a2..53c7baf 100644 --- a/app.py +++ b/app.py @@ -1209,6 +1209,11 @@ def display(): return render_template('display.html', questions=QUESTIONS) +@app.route('/presenter') +def presenter(): + return render_template('presenter.html', questions=QUESTIONS) + + # Per-question bubble chart — linked from the bottom strip on the display page @app.route('/q/') def question_view(q_id): diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f5fd1f3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,426 @@ +services: + # ------------------------------------------------------ + # Traefik Reverse Proxy + # ------------------------------------------------------ + traefik: + image: traefik:v2.11 + container_name: traefik + restart: unless-stopped + command: + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.web.address=:80" + - "--entrypoints.websecure.address=:443" + - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true" + - "--certificatesresolvers.letsencrypt.acme.email=inventor@txproducts.de" + - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" + ports: + - "80:80" + - "443:443" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - "./letsencrypt:/letsencrypt" + + # ------------------------------------------------------ + # Tika (Office text extraction) + # ------------------------------------------------------ + tika: + image: apache/tika:latest + container_name: tika + restart: unless-stopped + + # ------------------------------------------------------ + # Gotenberg (Office → PDF conversion) + # ------------------------------------------------------ + gotenberg: + image: gotenberg/gotenberg:latest + container_name: gotenberg + restart: unless-stopped + command: + - "gotenberg" + - "--chromium-disable-javascript=true" + - "--chromium-allow-list=file:///tmp/.*" + - "--libreoffice-start-timeout=900s" + - "--chromium-start-timeout=900s" + - "--libreoffice-auto-start=true" + + # ------------------------------------------------------ + # Paperless-NGX + # ------------------------------------------------------ + paperless: + image: ghcr.io/paperless-ngx/paperless-ngx:latest + container_name: paperless + restart: unless-stopped + depends_on: + - redis + - paperless_db + - tika + - gotenberg + environment: + PAPERLESS_URL: https://paperless.txproducts.de + PAPERLESS_REDIS: redis://redis:6379 + PAPERLESS_DBHOST: paperless_db + PAPERLESS_DBNAME: paperless + PAPERLESS_DBUSER: paperless + PAPERLESS_DBPASS: AVeryStrong123Password + PAPERLESS_CONSUMER_RECURSIVE: "true" + PAPERLESS_CONSUMER_DELETE_DUPLICATES: "true" + PAPERLESS_EMAIL_HOST: "mail.cs537.de" + PAPERLESS_EMAIL_PORT: 465 + PAPERLESS_EMAIL_HOST_USER: "system@txproducts.de" + PAPERLESS_EMAIL_HOST_PASSWORD: "OubveTtORoOmPRItNITeRbIDECUppEcT,=,42" + PAPERLESS_EMAIL_FROM: "system@txproducts.de" + PAPERLESS_EMAIL_USE_TLS: "true" + PAPERLESS_EMAIL_USE_SSL: "false" + # --- Office document support --- + PAPERLESS_TIKA_ENABLED: "true" + PAPERLESS_TIKA_GOTENBERG_ENDPOINT: "http://gotenberg:3000" + PAPERLESS_TIKA_ENDPOINT: "http://tika:9998" + volumes: + - ./paperless/data:/usr/src/paperless/data + - ./paperless/media:/usr/src/paperless/media + - ./paperless/export:/usr/src/paperless/export + - ./paperless/consume:/usr/src/paperless/consume + labels: + - "traefik.enable=true" + - "traefik.http.routers.paperless.rule=Host(`paperless.txproducts.de`)" + - "traefik.http.routers.paperless.entrypoints=websecure" + - "traefik.http.routers.paperless.tls.certresolver=letsencrypt" + + paperless_db: + image: postgres:14 + restart: unless-stopped + environment: + POSTGRES_DB: paperless + POSTGRES_USER: paperless + POSTGRES_PASSWORD: AVeryStrong123Password + volumes: + - ./paperless/postgres:/var/lib/postgresql/data + + redis: + image: redis:7 + restart: unless-stopped + + # ------------------------------------------------------ + # Paperless AI + # ------------------------------------------------------ + paperless_ai: + image: clusterzx/paperless-ai:latest + container_name: paperless_ai + restart: unless-stopped + environment: + PUID: 1000 + PGID: 1000 + + # Port config + PAPERLESS_AI_PORT: 3000 + + # RAG engine (enabled by default) + RAG_SERVICE_URL: http://paperless_ai:8000 + RAG_SERVICE_ENABLED: "true" + + # Connect to Paperless + PAPERLESS_URL: https://paperless.txproducts.de + + # ==== OpenRouter (Custom Provider) ==== + AI_PROVIDER: custom + CUSTOM_AI_BASE_URL: https://openrouter.ai/api/v1 + CUSTOM_AI_API_KEY: "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" + CUSTOM_AI_MODEL: "stepfun/step-3.5-flash:free" + + # OpenRouter required headers! + HTTP_REFERER: "https://paperai.txproducts.de" + X_TITLE: "Paperless-AI" + + volumes: + - ./paperless-ai/data:/app/data + + labels: + - "traefik.enable=true" + - "traefik.http.routers.paperlessai.rule=Host(`paperai.txproducts.de`)" + - "traefik.http.routers.paperlessai.entrypoints=websecure" + - "traefik.http.routers.paperlessai.tls.certresolver=letsencrypt" + + + # ------------------------------------------------------ + # InvenTree + DB + # ------------------------------------------------------ + inventree: + image: inventree/inventree:stable + container_name: inventree + restart: unless-stopped + depends_on: + - inventree_db + environment: + INVENTREE_DB_ENGINE: postgresql + INVENTREE_DB_NAME: inventree + INVENTREE_DB_USER: inventree + INVENTREE_DB_PASSWORD: AVeryStrong123Password + INVENTREE_DB_HOST: inventree_db + INVENTREE_ADMIN_USER: admin + INVENTREE_ADMIN_PASSWORD: AVeryStrong123Password + INVENTREE_ADMIN_EMAIL: dschmidt@txproducts.de + INVENTREE_PLUGINS_ENABLED: 1 + INVENTREE_PLUGIN_FILE: /home/inventree/data/plugins.txt + # Required for reverse-proxy setups + INVENTREE_SITE_URL: https://inventree.txproducts.de + CSRF_TRUSTED_ORIGINS: https://inventree.txproducts.de + ALLOWED_HOSTS: inventree.txproducts.de,localhost,127.0.0.1 + volumes: + - ./inventree/data:/home/inventree/data + labels: + - "traefik.enable=true" + - "traefik.http.routers.inventree.rule=Host(`inventree.txproducts.de`)" + - "traefik.http.routers.inventree.entrypoints=websecure" + - "traefik.http.routers.inventree.tls.certresolver=letsencrypt" + # Static files service + - "traefik.http.services.inventree.loadbalancer.server.port=8000" + + inventree_db: + image: postgres:14 + restart: unless-stopped + environment: + POSTGRES_DB: inventree + POSTGRES_USER: inventree + POSTGRES_PASSWORD: AVeryStrong123Password + volumes: + - ./inventree/postgres:/var/lib/postgresql/data + + + inventree_worker: + image: inventree/inventree:stable + container_name: inventree_worker + command: invoke worker + restart: unless-stopped + depends_on: + - inventree + environment: + INVENTREE_DB_ENGINE: postgresql + INVENTREE_DB_NAME: inventree + INVENTREE_DB_USER: inventree + INVENTREE_DB_PASSWORD: AVeryStrong123Password + INVENTREE_DB_HOST: inventree_db + + INVENTREE_SITE_URL: https://inventree.txproducts.de + CSRF_TRUSTED_ORIGINS: https://inventree.txproducts.de + + volumes: + - ./inventree/data:/home/inventree/data + +# ------------------------------------------------------ + # Nextcloud + DB + # ------------------------------------------------------ + nextcloud-db: + image: mariadb:11 + container_name: nextcloud-db + restart: unless-stopped + command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW + environment: + MYSQL_DATABASE: nextcloud + MYSQL_USER: nextcloud + MYSQL_PASSWORD: A_Very_Strong_DB_Password + MYSQL_ROOT_PASSWORD: A_Very_Strong_Root_Password + volumes: + - ./nextcloud/db:/var/lib/mysql + + nextcloud: + image: nextcloud:latest + container_name: nextcloud + restart: unless-stopped + depends_on: + - nextcloud-db + - redis + environment: + # DB connection + MYSQL_HOST: nextcloud-db + MYSQL_DATABASE: nextcloud + MYSQL_USER: nextcloud + MYSQL_PASSWORD: A_Very_Strong_DB_Password + REDIS_HOST: redis + # URL & proxy config + #NEXTCLOUD_ADMIN_USER: admin + #NEXTCLOUD_ADMIN_PASSWORD: 97v2*r7APuS^RV3d$YPU + NEXTCLOUD_TRUSTED_DOMAINS: cloud.txproducts.de + OVERWRITEHOST: cloud.txproducts.de + OVERWRITEPROTOCOL: https + OVERWRITECLIURL: https://cloud.txproducts.de + TRUSTED_PROXIES: 172.16.0.0/12 + + volumes: + - ./nextcloud/html:/var/www/html + - ./nextcloud/data:/var/www/html/data + - ./paperless:/paperless + + labels: + - "traefik.enable=true" + - "traefik.http.routers.nextcloud.rule=Host(`cloud.txproducts.de`)" + - "traefik.http.routers.nextcloud.entrypoints=websecure" + - "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt" + # Optional: increase timeouts for large uploads + - "traefik.http.services.nextcloud.loadbalancer.server.port=80" + + - "traefik.http.routers.nextcloud-http.entrypoints=web" + - "traefik.http.routers.nextcloud-http.rule=Host(`cloud.txproducts.de`)" + - "traefik.http.routers.nextcloud-http.middlewares=nextcloud-redirect" + - "traefik.http.middlewares.nextcloud-redirect.redirectscheme.scheme=https" + + nextcloud-cron: + image: nextcloud:latest + container_name: nextcloud-cron + restart: unless-stopped + volumes: + - ./nextcloud/html:/var/www/html + - ./nextcloud/data:/var/www/html/data + entrypoint: /cron.sh + depends_on: + - nextcloud-db + - redis + + talk-hpb: + image: ghcr.io/nextcloud-releases/aio-talk:latest + container_name: nextcloud-talk-hpb + restart: unless-stopped + init: true + labels: + - "traefik.enable=true" + + # 1. HTTP Router (Redirect HTTP to HTTPS) + - "traefik.http.routers.talk-http.entrypoints=web" + - "traefik.http.routers.talk-http.rule=Host(`signal.cloud.txproducts.de`)" + - "traefik.http.routers.talk-http.middlewares=nextcloud-redirect" + + # 2. HTTPS Router (Secure WebSocket Access) + - "traefik.http.routers.talk-https.entrypoints=websecure" + - "traefik.http.routers.talk-https.rule=Host(`signal.cloud.txproducts.de`)" + - "traefik.http.routers.talk-https.tls=true" + - "traefik.http.routers.talk-https.tls.certresolver=letsencrypt" + + # The Talk service is available internally on port 8081 + - "traefik.http.services.talk-hpb.loadbalancer.server.port=8081" + environment: + - NC_DOMAIN=cloud.txproducts.de + - TALK_HOST=signal.cloud.txproducts.de + - TALK_PORT=3478 + - TURN_SECRET=1ph34w9hrs0gka5xi2qfbn2ti48390 + - SIGNALING_SECRET=avzeyam5ak1e4a4xseak2m43kih3vp + - INTERNAL_SECRET=e5hr4dgxnjbsl71kr1stkubqyrz3zh + ports: + # Expose the TURN ports (required for external clients) + - "3478:3478/tcp" + - "3478:3478/udp" + # Expose the internal signaling port for the reverse proxy + - "8081:8081/tcp" + depends_on: + - nextcloud + + nextcloud-whiteboard: + image: ghcr.io/nextcloud-releases/whiteboard:stable + container_name: nextcloud-whiteboard + restart: unless-stopped + environment: + NEXTCLOUD_URL: https://cloud.txproducts.de + JWT_SECRET_KEY: "d7a6599a3864220838281e1796fb06cb90441519a39621ce077a87f80b9c96a6" + labels: + - "traefik.enable=true" + - "traefik.http.routers.whiteboard.rule=Host(`cloud.txproducts.de`) && PathPrefix(`/whiteboard`)" + - "traefik.http.routers.whiteboard.entrypoints=websecure" + - "traefik.http.routers.whiteboard.tls.certresolver=letsencrypt" + - "traefik.http.services.whiteboard.loadbalancer.server.port=3002" + - "traefik.http.middlewares.strip-whiteboard.stripprefix.prefixes=/whiteboard" + - "traefik.http.routers.whiteboard.middlewares=strip-whiteboard" + depends_on: + - nextcloud + + # ------------------------------------------------------ + # Gitea + # ------------------------------------------------------ + gitea: + image: gitea/gitea:latest + container_name: gitea + restart: unless-stopped + depends_on: + - gitea_db + environment: + USER_UID: 1000 + USER_GID: 1000 + GITEA__database__DB_TYPE: postgres + GITEA__database__HOST: gitea_db:5432 + GITEA__database__NAME: gitea + GITEA__database__USER: gitea + GITEA__database__PASSWD: AVeryStrongGiteaPassword + GITEA__server__DOMAIN: git.txproducts.de + GITEA__server__ROOT_URL: https://git.txproducts.de + GITEA__server__HTTP_PORT: 3000 + GITEA__server__SSH_DOMAIN: git.txproducts.de + GITEA__server__SSH_PORT: 2222 + GITEA__mailer__ENABLED: true + GITEA__mailer__PROTOCOL: smtps + GITEA__mailer__SMTP_ADDR: mail.cs537.de + GITEA__mailer__SMTP_PORT: 465 + GITEA__mailer__USER: system@txproducts.de + GITEA__mailer__PASSWD: OubveTtORoOmPRItNITeRbIDECUppEcT,=,42 + GITEA__mailer__FROM: system@txproducts.de + GITEA__service__REGISTER_EMAIL_CONFIRM: true + GITEA__service__DISABLE_REGISTRATION: false + GITEA__service__ALLOW_ONLY_INTERNAL_REGISTRATION: true + GITEA__service__ENABLE_NOTIFY_MAIL: true + volumes: + - ./gitea/data:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + ports: + - "222:22" # SSH access for git push/pull + labels: + - "traefik.enable=true" + - "traefik.http.routers.gitea.rule=Host(`git.txproducts.de`)" + - "traefik.http.routers.gitea.entrypoints=websecure" + - "traefik.http.routers.gitea.tls.certresolver=letsencrypt" + - "traefik.http.services.gitea.loadbalancer.server.port=3000" + - "traefik.http.routers.gitea-http.entrypoints=web" + - "traefik.http.routers.gitea-http.rule=Host(`git.txproducts.de`)" + - "traefik.http.routers.gitea-http.middlewares=gitea-redirect" + - "traefik.http.middlewares.gitea-redirect.redirectscheme.scheme=https" + + gitea_db: + image: postgres:14 + container_name: gitea_db + restart: unless-stopped + environment: + POSTGRES_DB: gitea + POSTGRES_USER: gitea + POSTGRES_PASSWORD: AVeryStrongGiteaPassword + volumes: + - ./gitea/postgres:/var/lib/postgresql/data + + + # ------------------------------------------------------ + # HiActs Conference Poll + # ------------------------------------------------------ + hiacts-poll: + build: + context: ./poll + dockerfile_inline: | + FROM python:3.12-slim + WORKDIR /app + COPY requirements.txt . + RUN pip install --no-cache-dir -r requirements.txt + COPY . . + EXPOSE 5001 + CMD ["python", "app.py"] + container_name: hiacts-poll + restart: unless-stopped + labels: + - "traefik.enable=true" + - "traefik.http.routers.hiacts-poll.rule=Host(`poll.txproducts.de`)" + - "traefik.http.routers.hiacts-poll.entrypoints=websecure" + - "traefik.http.routers.hiacts-poll.tls.certresolver=letsencrypt" + - "traefik.http.services.hiacts-poll.loadbalancer.server.port=5001" + +networks: + default: + driver: bridge + enable_ipv6: true + ipam: + config: + - subnet: "172.20.0.0/16" + - subnet: "fd01::/80" diff --git a/templates/presenter.html b/templates/presenter.html new file mode 100644 index 0000000..9d056b7 --- /dev/null +++ b/templates/presenter.html @@ -0,0 +1,830 @@ + + + + + + HiActs Live Results - TXproducts + + + + + + + + + + + + +
+ + +
+
+
Hi-Acts · 3rd Network Meeting
+
Innovation Challenge Arena
+
Data and Software Standardization
+
+
+

Every perspective matters.

+
Help us gain insight across the beamline community.
+
+
+ + +
+ + Live +
+
+ +
0
+
responses
+
+
+
+ + +
+
11 questions being asked to today's participants
+
+ +
+
+
Q1
+
What best describes your role at the beamline?
+
+
+
Beamline Scientist
+
Instrument Scientist
+
Industry User
+
Control System / IT
+
Other
+
+
+ +
+
+
Q2
+
In one word, describe your experiment logbook today.
+
+
+ chaotic + fragmented + manual + scattered + analog +
+
+ +
+
+
Q3
+
What is the biggest obstacle when moving data between beamlines or facilities?
+
+
+
Different control systems (TANGO, EPICS, SPOCK)
+
Inconsistent logbook formats
+
Missing or incomplete metadata
+
No common file format standard
+
Manual re-scripting for every beamline
+
Other
+
+
+ +
+
+
Q4
+
How do you feel about standardising beamline workflows?
+
+
+
Necessary and overdue
+
Desirable but very difficult
+
Too rigid for our experimental needs
+
Not our problem to solve
+
Other
+
+
+ +
+
+
Q5
+
When an industry user brings a sample, how well documented is the experiment?
+
+
+
Fully documented, reproducible
+
Mostly documented, some gaps
+
Partial, depends on the scientist
+
Barely documented
+
Other
+
+
+ +
+
+
Q6
+
If every beamline used the same data language, what would become possible?
+
+
+ Automated cross-facility comparison + Direct data delivery without post-processing + Reproducible experiments across facilities +
+
+ +
+
+ +
+
+ + +
+ + +
+ + +
+

Waiting for responses…

+

Results will appear here as people answer

+
+ + Scan to participate +
+ + +
+ + + +
+ + +
Top 5 ranked results per question
+ +
+
+ +
+ +
+ + + + + +
+ +
+ + + + +