separation of ui and static
Some checks failed
ci/woodpecker/tag/build/5 Pipeline failed
ci/woodpecker/tag/predeploy Pipeline was successful
ci/woodpecker/tag/deploy/2 unknown status
ci/woodpecker/tag/deploy/1 unknown status
ci/woodpecker/tag/build/2 Pipeline failed
ci/woodpecker/tag/deploy/4 unknown status
ci/woodpecker/tag/deploy/3 unknown status
ci/woodpecker/tag/build/3 Pipeline failed
ci/woodpecker/tag/deploy/5 unknown status
ci/woodpecker/tag/ingress unknown status
ci/woodpecker/tag/build/1 Pipeline failed
ci/woodpecker/tag/build/4 Pipeline failed
@@ -7,6 +7,7 @@ matrix:
|
|||||||
- api
|
- api
|
||||||
- abstraction
|
- abstraction
|
||||||
- rules
|
- rules
|
||||||
|
- static
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
build-${APP}:
|
build-${APP}:
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ matrix:
|
|||||||
- api
|
- api
|
||||||
- abstraction
|
- abstraction
|
||||||
- rules
|
- rules
|
||||||
|
- static
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
deploy-${APP}:
|
deploy-${APP}:
|
||||||
|
|||||||
15
apps/static/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Static assets Dockerfile (minimal webserver for /static only)
|
||||||
|
|
||||||
|
FROM nginx:1.27-alpine
|
||||||
|
|
||||||
|
WORKDIR /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Remove default nginx content
|
||||||
|
RUN rm -rf ./*
|
||||||
|
|
||||||
|
# Copy only static assets from the UI project
|
||||||
|
COPY apps/ui/static/ ./
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Use default nginx config; caller can mount custom config if needed
|
||||||
|
Before Width: | Height: | Size: 618 B After Width: | Height: | Size: 618 B |
|
Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 639 B |
|
Before Width: | Height: | Size: 827 B After Width: | Height: | Size: 827 B |
|
Before Width: | Height: | Size: 884 B After Width: | Height: | Size: 884 B |
|
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 153 B |
|
Before Width: | Height: | Size: 1018 B After Width: | Height: | Size: 1018 B |
|
Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 210 B |
|
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
|
Before Width: | Height: | Size: 413 B After Width: | Height: | Size: 413 B |
|
Before Width: | Height: | Size: 432 B After Width: | Height: | Size: 432 B |
|
Before Width: | Height: | Size: 1018 B After Width: | Height: | Size: 1018 B |
|
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 244 B |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 721 B |
|
Before Width: | Height: | Size: 519 B After Width: | Height: | Size: 519 B |
|
Before Width: | Height: | Size: 547 B After Width: | Height: | Size: 547 B |
|
Before Width: | Height: | Size: 641 B After Width: | Height: | Size: 641 B |
|
Before Width: | Height: | Size: 695 B After Width: | Height: | Size: 695 B |
|
Before Width: | Height: | Size: 126 B After Width: | Height: | Size: 126 B |
|
Before Width: | Height: | Size: 808 B After Width: | Height: | Size: 808 B |
|
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
|
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 271 B |
|
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 347 B |
|
Before Width: | Height: | Size: 368 B After Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 808 B After Width: | Height: | Size: 808 B |
|
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 244 B |
@@ -1,49 +1,41 @@
|
|||||||
# UI Service Dockerfile
|
# UI Service Dockerfile (Application only, without static files)
|
||||||
# FastAPI + Jinja2 + HTMX Dashboard
|
|
||||||
|
|
||||||
FROM python:3.14-alpine
|
FROM python:3.14-alpine
|
||||||
|
|
||||||
# Prevent Python from writing .pyc files and enable unbuffered output
|
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
PYTHONUNBUFFERED=1 \
|
PYTHONUNBUFFERED=1 \
|
||||||
UI_PORT=8002 \
|
UI_PORT=8002 \
|
||||||
API_BASE=http://api:8001 \
|
API_BASE=http://api:8001 \
|
||||||
BASE_PATH=""
|
BASE_PATH="" \
|
||||||
|
STATIC_BASE=http://static:8080
|
||||||
|
|
||||||
# Create non-root user
|
|
||||||
RUN addgroup -g 10001 -S app && \
|
RUN addgroup -g 10001 -S app && \
|
||||||
adduser -u 10001 -S app -G app
|
adduser -u 10001 -S app -G app
|
||||||
|
|
||||||
# Set working directory
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install system dependencies
|
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
curl \
|
curl \
|
||||||
gcc \
|
gcc \
|
||||||
musl-dev \
|
musl-dev \
|
||||||
linux-headers
|
linux-headers
|
||||||
|
|
||||||
# Install Python dependencies
|
|
||||||
COPY apps/ui/requirements.txt /app/requirements.txt
|
COPY apps/ui/requirements.txt /app/requirements.txt
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# Copy application code
|
# Copy only Python code and templates, but exclude static assets
|
||||||
COPY apps/__init__.py /app/apps/__init__.py
|
COPY apps/__init__.py /app/apps/__init__.py
|
||||||
COPY apps/ui/ /app/apps/ui/
|
COPY apps/ui/__init__.py /app/apps/ui/__init__.py
|
||||||
|
COPY apps/ui/main.py /app/apps/ui/main.py
|
||||||
|
COPY apps/ui/api_client.py /app/apps/ui/api_client.py
|
||||||
|
COPY apps/ui/templates/ /app/apps/ui/templates/
|
||||||
|
|
||||||
# Change ownership to app user
|
|
||||||
RUN chown -R app:app /app
|
RUN chown -R app:app /app
|
||||||
|
|
||||||
# Switch to non-root user
|
|
||||||
USER app
|
USER app
|
||||||
|
|
||||||
# Health check
|
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
CMD curl -f http://localhost:${UI_PORT}/health || exit 1
|
CMD curl -f http://localhost:${UI_PORT}/health || exit 1
|
||||||
|
|
||||||
# Expose port
|
|
||||||
EXPOSE 8002
|
EXPOSE 8002
|
||||||
|
|
||||||
# Run application
|
|
||||||
CMD ["python", "-m", "uvicorn", "apps.ui.main:app", "--host", "0.0.0.0", "--port", "8002"]
|
CMD ["python", "-m", "uvicorn", "apps.ui.main:app", "--host", "0.0.0.0", "--port", "8002"]
|
||||||
|
|||||||
@@ -16,9 +16,11 @@ logger = logging.getLogger(__name__)
|
|||||||
# Read configuration from environment variables
|
# Read configuration from environment variables
|
||||||
API_BASE = os.getenv("API_BASE", "http://localhost:8001")
|
API_BASE = os.getenv("API_BASE", "http://localhost:8001")
|
||||||
BASE_PATH = os.getenv("BASE_PATH", "") # e.g., "/ui" for reverse proxy
|
BASE_PATH = os.getenv("BASE_PATH", "") # e.g., "/ui" for reverse proxy
|
||||||
|
STATIC_BASE = os.getenv("STATIC_BASE", "/static")
|
||||||
|
|
||||||
print(f"UI using API_BASE: {API_BASE}")
|
print(f"UI using API_BASE: {API_BASE}")
|
||||||
print(f"UI using BASE_PATH: {BASE_PATH}")
|
print(f"UI using BASE_PATH: {BASE_PATH}")
|
||||||
|
print(f"UI using STATIC_BASE: {STATIC_BASE}")
|
||||||
|
|
||||||
def api_url(path: str) -> str:
|
def api_url(path: str) -> str:
|
||||||
"""Helper function to construct API URLs.
|
"""Helper function to construct API URLs.
|
||||||
@@ -43,6 +45,9 @@ app = FastAPI(
|
|||||||
templates_dir = Path(__file__).parent / "templates"
|
templates_dir = Path(__file__).parent / "templates"
|
||||||
templates = Jinja2Templates(directory=str(templates_dir))
|
templates = Jinja2Templates(directory=str(templates_dir))
|
||||||
|
|
||||||
|
# Make STATIC_BASE available in all templates
|
||||||
|
templates.env.globals["STATIC_BASE"] = STATIC_BASE
|
||||||
|
|
||||||
# Setup static files
|
# Setup static files
|
||||||
static_dir = Path(__file__).parent / "static"
|
static_dir = Path(__file__).parent / "static"
|
||||||
static_dir.mkdir(exist_ok=True)
|
static_dir.mkdir(exist_ok=True)
|
||||||
@@ -98,7 +103,8 @@ async def health() -> JSONResponse:
|
|||||||
"status": "ok",
|
"status": "ok",
|
||||||
"service": "ui",
|
"service": "ui",
|
||||||
"api_base": API_BASE,
|
"api_base": API_BASE,
|
||||||
"base_path": BASE_PATH
|
"base_path": BASE_PATH,
|
||||||
|
"static_base": STATIC_BASE,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -127,7 +133,7 @@ async def rooms(request: Request) -> HTMLResponse:
|
|||||||
"""
|
"""
|
||||||
return templates.TemplateResponse("rooms.html", {
|
return templates.TemplateResponse("rooms.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"api_base": API_BASE
|
"api_base": API_BASE,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -145,7 +151,7 @@ async def room_detail(request: Request, room_name: str) -> HTMLResponse:
|
|||||||
return templates.TemplateResponse("room.html", {
|
return templates.TemplateResponse("room.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"api_base": API_BASE,
|
"api_base": API_BASE,
|
||||||
"room_name": room_name
|
"room_name": room_name,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,17 +6,17 @@
|
|||||||
<title>Home Automation</title>
|
<title>Home Automation</title>
|
||||||
|
|
||||||
<!-- Apple Touch Icon -->
|
<!-- Apple Touch Icon -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="120x120" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
<link rel="icon" type="image/svg+xml" href="{{ STATIC_BASE }}/favicon.svg">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||||
<meta name="apple-mobile-web-app-title" content="Dashboard">
|
<meta name="apple-mobile-web-app-title" content="Dashboard">
|
||||||
<meta name="theme-color" content="#667eea">
|
<meta name="theme-color" content="#667eea">
|
||||||
<link rel="manifest" href="/static/manifest.json">
|
<link rel="manifest" href="{{ STATIC_BASE }}/manifest.json">
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -6,16 +6,16 @@
|
|||||||
<title>Gerät - Home Automation</title>
|
<title>Gerät - Home Automation</title>
|
||||||
|
|
||||||
<!-- Apple Touch Icon -->
|
<!-- Apple Touch Icon -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="120x120" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||||
<meta name="apple-mobile-web-app-title" content="Gerät">
|
<meta name="apple-mobile-web-app-title" content="Gerät">
|
||||||
<meta name="theme-color" content="#667eea">
|
<meta name="theme-color" content="#667eea">
|
||||||
<link rel="manifest" href="/static/manifest.json">
|
<link rel="manifest" href="{{ STATIC_BASE }}/manifest.json">
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -346,8 +346,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Load API client AFTER API_BASE is set -->
|
<!-- Load API client AFTER API_BASE is set -->
|
||||||
<script src="/static/types.js"></script>
|
<script src="{{ STATIC_BASE }}/types.js"></script>
|
||||||
<script src="/static/api-client.js"></script>
|
<script src="{{ STATIC_BASE }}/api-client.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Get device ID from URL
|
// Get device ID from URL
|
||||||
|
|||||||
@@ -6,17 +6,17 @@
|
|||||||
<title>Garage - Home Automation</title>
|
<title>Garage - Home Automation</title>
|
||||||
|
|
||||||
<!-- Apple Touch Icon -->
|
<!-- Apple Touch Icon -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/garage-icon-180x180.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ STATIC_BASE }}/garage-icon-180x180.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/static/garage-icon-152x152.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="{{ STATIC_BASE }}/garage-icon-152x152.png">
|
||||||
<link rel="apple-touch-icon" sizes="120x120" href="/static/garage-icon-120x120.png">
|
<link rel="apple-touch-icon" sizes="120x120" href="{{ STATIC_BASE }}/garage-icon-120x120.png">
|
||||||
<link rel="apple-touch-icon" sizes="76x76" href="/static/garage-icon-76x76.png">
|
<link rel="apple-touch-icon" sizes="76x76" href="{{ STATIC_BASE }}/garage-icon-76x76.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/garage-icon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ STATIC_BASE }}/garage-icon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/garage-icon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ STATIC_BASE }}/garage-icon-16x16.png">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||||
<meta name="apple-mobile-web-app-title" content="Garage">
|
<meta name="apple-mobile-web-app-title" content="Garage">
|
||||||
<meta name="theme-color" content="#667eea">
|
<meta name="theme-color" content="#667eea">
|
||||||
<link rel="manifest" href="/manifest.json">
|
<link rel="manifest" href="{{ STATIC_BASE }}/manifest.json">
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -306,8 +306,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Load API client AFTER API_BASE is set -->
|
<!-- Load API client AFTER API_BASE is set -->
|
||||||
<script src="/static/types.js"></script>
|
<script src="{{ STATIC_BASE }}/types.js"></script>
|
||||||
<script src="/static/api-client.js"></script>
|
<script src="{{ STATIC_BASE }}/api-client.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Device IDs for garage devices
|
// Device IDs for garage devices
|
||||||
|
|||||||
@@ -6,17 +6,17 @@
|
|||||||
<title>Home Automation</title>
|
<title>Home Automation</title>
|
||||||
|
|
||||||
<!-- Apple Touch Icon -->
|
<!-- Apple Touch Icon -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon-180x180.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ STATIC_BASE }}/apple-touch-icon-180x180.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon-152x152.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="{{ STATIC_BASE }}/apple-touch-icon-152x152.png">
|
||||||
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon-120x120.png">
|
<link rel="apple-touch-icon" sizes="120x120" href="{{ STATIC_BASE }}/apple-touch-icon-120x120.png">
|
||||||
<link rel="apple-touch-icon" sizes="76x76" href="/static/apple-touch-icon-76x76.png">
|
<link rel="apple-touch-icon" sizes="76x76" href="{{ STATIC_BASE }}/apple-touch-icon-76x76.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ STATIC_BASE }}/apple-touch-icon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ STATIC_BASE }}/apple-touch-icon-16x16.png">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||||
<meta name="apple-mobile-web-app-title" content="Home Automation">
|
<meta name="apple-mobile-web-app-title" content="Home Automation">
|
||||||
<meta name="theme-color" content="#667eea">
|
<meta name="theme-color" content="#667eea">
|
||||||
<link rel="manifest" href="/static/manifest.json">
|
<link rel="manifest" href="{{ STATIC_BASE }}/manifest.json">
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -6,16 +6,16 @@
|
|||||||
<title>{{ room_name }} - Home Automation</title>
|
<title>{{ room_name }} - Home Automation</title>
|
||||||
|
|
||||||
<!-- Apple Touch Icon -->
|
<!-- Apple Touch Icon -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="120x120" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ STATIC_BASE }}/apple-touch-icon.png">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||||
<meta name="apple-mobile-web-app-title" content="{{ room_name }}">
|
<meta name="apple-mobile-web-app-title" content="{{ room_name }}">
|
||||||
<meta name="theme-color" content="#667eea">
|
<meta name="theme-color" content="#667eea">
|
||||||
<link rel="manifest" href="/static/manifest.json">
|
<link rel="manifest" href="{{ STATIC_BASE }}/manifest.json">
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -229,8 +229,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Load API client AFTER API_BASE is set -->
|
<!-- Load API client AFTER API_BASE is set -->
|
||||||
<script src="/static/types.js"></script>
|
<script src="{{ STATIC_BASE }}/types.js"></script>
|
||||||
<script src="/static/api-client.js"></script>
|
<script src="{{ STATIC_BASE }}/api-client.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Get room name from URL
|
// Get room name from URL
|
||||||
|
|||||||
@@ -6,17 +6,17 @@
|
|||||||
<title>Räume - Home Automation</title>
|
<title>Räume - Home Automation</title>
|
||||||
|
|
||||||
<!-- Apple Touch Icon -->
|
<!-- Apple Touch Icon -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon-180x180.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ STATIC_BASE }}/apple-touch-icon-180x180.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon-152x152.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="{{ STATIC_BASE }}/apple-touch-icon-152x152.png">
|
||||||
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon-120x120.png">
|
<link rel="apple-touch-icon" sizes="120x120" href="{{ STATIC_BASE }}/apple-touch-icon-120x120.png">
|
||||||
<link rel="apple-touch-icon" sizes="76x76" href="/static/apple-touch-icon-76x76.png">
|
<link rel="apple-touch-icon" sizes="76x76" href="{{ STATIC_BASE }}/apple-touch-icon-76x76.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ STATIC_BASE }}/apple-touch-icon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ STATIC_BASE }}/apple-touch-icon-16x16.png">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||||
<meta name="apple-mobile-web-app-title" content="Räume">
|
<meta name="apple-mobile-web-app-title" content="Räume">
|
||||||
<meta name="theme-color" content="#667eea">
|
<meta name="theme-color" content="#667eea">
|
||||||
<link rel="manifest" href="/manifest.json">
|
<link rel="manifest" href="{{ STATIC_BASE }}/manifest.json">
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -163,8 +163,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Load API client AFTER API_BASE is set -->
|
<!-- Load API client AFTER API_BASE is set -->
|
||||||
<script src="/static/types.js"></script>
|
<script src="{{ STATIC_BASE }}/types.js"></script>
|
||||||
<script src="/static/api-client.js"></script>
|
<script src="{{ STATIC_BASE }}/api-client.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Room icon mapping
|
// Room icon mapping
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ data:
|
|||||||
# UI specific environment variables
|
# UI specific environment variables
|
||||||
UI_UI_PORT: "8002"
|
UI_UI_PORT: "8002"
|
||||||
UI_API_BASE: "https://homea2-api.hottis.de"
|
UI_API_BASE: "https://homea2-api.hottis.de"
|
||||||
|
UI_STATIC_BASE: "http://homea2-static.hottis.de"
|
||||||
UI_BASE_PATH: "/"
|
UI_BASE_PATH: "/"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ spec:
|
|||||||
dnsNames:
|
dnsNames:
|
||||||
- homea2.hottis.de
|
- homea2.hottis.de
|
||||||
- homea2-api.hottis.de
|
- homea2-api.hottis.de
|
||||||
|
- homea2-static.hottis.de
|
||||||
---
|
---
|
||||||
apiVersion: traefik.containo.us/v1alpha1
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
kind: TLSOption
|
kind: TLSOption
|
||||||
@@ -60,6 +61,22 @@ spec:
|
|||||||
- name: api
|
- name: api
|
||||||
port: 80
|
port: 80
|
||||||
---
|
---
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: static
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
tls:
|
||||||
|
secretName: homea2-cert
|
||||||
|
routes:
|
||||||
|
- match: Host(`homea2-static.hottis.de`)
|
||||||
|
kind: Rule
|
||||||
|
services:
|
||||||
|
- name: static
|
||||||
|
port: 80
|
||||||
|
---
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
61
deployment/static-deployment.yaml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: static
|
||||||
|
namespace: homea2
|
||||||
|
labels:
|
||||||
|
app: static
|
||||||
|
component: home-automation
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: static
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: static
|
||||||
|
component: home-automation
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: static
|
||||||
|
image: %IMAGE%
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: http
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 80
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 30
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 80
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: static
|
||||||
|
namespace: homea2
|
||||||
|
labels:
|
||||||
|
app: static
|
||||||
|
component: home-automation
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: static
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
name: http
|
||||||
|
type: ClusterIP
|
||||||