Skip to content

Commit 441414e

Browse files
authored
Merge pull request #199 from it-at-m/show-versions-in-frontend-179
Make the version information visible in the frontend
2 parents f9a74ec + d80efdd commit 441414e

File tree

9 files changed

+214
-10
lines changed

9 files changed

+214
-10
lines changed

.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ RISKI_DOCUMENTS__OCR_BATCH_SIZE=10
5353
# BACKEND #
5454
###########
5555
RISKI_BACKEND__VERSION=0.1.0
56-
56+
RISKI_BACKEND__FRONTEND_VERSION=0.1.0
57+
RISKI_BACKEND__TITLE="RIS KI Suche (Beta-Version)"
58+
RISKI_BACKEND__DOCUMENTATION_URL="https://ki.muenchen.de"
5759
############
5860
# Langfuse #
5961
############

riski-backend/app/api/routers/system.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from app.core.settings import get_settings
2+
from app.models.config_response import ConfigResponse
23
from app.models.health_check_response import HealthCheckResponse
34
from fastapi import APIRouter
45

@@ -11,3 +12,14 @@
1112
def healthz() -> HealthCheckResponse:
1213
"""Health check endpoint for backend availability and version info."""
1314
return HealthCheckResponse(version=settings.version)
15+
16+
17+
@router.get("/config", response_model=ConfigResponse)
18+
def get_config() -> ConfigResponse:
19+
"""Get application configuration."""
20+
return ConfigResponse(
21+
version=settings.version,
22+
frontend_version=settings.frontend_version,
23+
title=settings.title,
24+
documentation_url=settings.documentation_url,
25+
)

riski-backend/app/core/settings.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from pathlib import Path
55
from typing import Literal
66

7-
from pydantic import BaseModel, Field, RedisDsn, SecretStr
7+
from pydantic import BaseModel, Field, RedisDsn, SecretStr, field_validator
88
from pydantic_settings import SettingsConfigDict
99

1010
from core.settings.base import AppBaseSettings
@@ -20,6 +20,19 @@ class BackendSettings(AppBaseSettings):
2020
"""
2121

2222
version: str = Field(default="DUMMY FOR GITHUBACTION", description="The version of the riski backend.")
23+
frontend_version: str = Field(default="DUMMY FOR GITHUBACTION", description="The version of the riski frontend.")
24+
title: str = Field(default="RIS KI Suche (Beta-Version)", description="The title of the application.")
25+
documentation_url: str = Field(default="https://ki.muenchen.de", description="The URL to the documentation.")
26+
27+
@field_validator("version", "frontend_version", mode="before")
28+
@staticmethod
29+
def parse_version(value: str) -> str:
30+
"""Parse version string to extract only the version number before @sha256."""
31+
if not isinstance(value, str):
32+
return value
33+
# Split by '@' and take the first part to remove the sha256 hash
34+
return value.split("@")[0]
35+
2336
enable_docs: bool = Field(default=False, description="Is the OpenAPI docs endpoint enabled.")
2437

2538
# === Langfuse Settings ===
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from pydantic import BaseModel, Field
2+
3+
4+
class ConfigResponse(BaseModel):
5+
"""Response for the config endpoint."""
6+
7+
version: str = Field(description="The version of the backend.")
8+
frontend_version: str = Field(description="The version of the frontend.")
9+
title: str = Field(description="The title of the application.")
10+
documentation_url: str = Field(description="The URL to the documentation.")
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import type ConfigResponse from "@/types/ConfigResponse";
2+
3+
import { getAPIBaseURL } from "@/util/constants";
4+
5+
export default class SystemClient {
6+
static async getConfig(): Promise<ConfigResponse> {
7+
const isMockMode = import.meta.env.MODE === "development";
8+
if (isMockMode) {
9+
return {
10+
version: "0.1.0-dev",
11+
frontend_version: "0.1.0-dev",
12+
title: "RIS KI Suche (Beta-Version)",
13+
documentation_url: "https://ki.muenchen.de",
14+
};
15+
}
16+
17+
const url = `${getAPIBaseURL()}/api/config`;
18+
const response = await fetch(url);
19+
if (!response.ok) {
20+
throw new Error(`Failed to fetch config: ${response.statusText}`);
21+
}
22+
return await response.json();
23+
}
24+
}

riski-frontend/src/components/riski-intro.vue

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
<script setup lang="ts"></script>
1+
<script setup lang="ts">
2+
defineProps<{
3+
title: string;
4+
}>();
5+
</script>
26

37
<template>
4-
<div
5-
class="m-intro m-intro-static-image"
6-
style="background-color: var(--color-neutrals-blue-xlight)"
7-
>
8+
<div class="m-intro m-intro-static-image" style="background-color: var(--color-neutrals-blue-xlight)">
89
<div class="container">
910
<div class="muc-intro-content padded-intro">
10-
<h1 class="m-intro-vertical__title">RIS KI Suche (Beta-Version)</h1>
11+
<h1 class="m-intro-vertical__title">{{ title }}</h1>
1112

1213
<div class="m-intro-vertical__content">
1314
<div class="intro-info">
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<script setup lang="ts">
2+
import { MucButton } from "@muenchen/muc-patternlab-vue";
3+
4+
defineProps<{
5+
frontendVersion: string;
6+
version: string;
7+
documentationUrl: string;
8+
}>();
9+
10+
const openKIMuenchen = (url: string) => {
11+
window.open(url, "_blank")?.focus();
12+
};
13+
</script>
14+
15+
<template>
16+
<div class="feedback-container" style="background-color: var(--color-neutrals-blue-xlight)">
17+
<div class="container">
18+
<div class="m-callout feedback-callout callout-margin" style="background-color: #ffffff">
19+
<div class="m-callout__inner">
20+
<div class="m-callout__body">
21+
<div class="m-callout__body__inner">
22+
<div class="m-callout__headline">
23+
<h2>Lernen Sie unsere KI-Suche besser kennen!</h2>
24+
</div>
25+
26+
<div class="m-callout__content">
27+
<div>
28+
<p class="docs-paragraph">
29+
In einer Beta-Version testen wir aktuell eine Suche mit
30+
Künstlicher Intelligenz. Wie das genau funktioniert,
31+
erklären wir Ihnen auf unserer Dokumentations-Webseite.
32+
</p>
33+
<muc-button variant="secondary" class="open-extern-button" icon="ext-link"
34+
@click="openKIMuenchen(documentationUrl)">
35+
ki.muenchen.de besuchen
36+
</muc-button>
37+
<div class="version-row">
38+
<div class="version-badge">
39+
<span class="version-label">Frontend</span>
40+
<span class="version-number">{{ frontendVersion }}</span>
41+
</div>
42+
<div class="version-badge">
43+
<span class="version-label">Backend</span>
44+
<span class="version-number">{{ version }}</span>
45+
</div>
46+
</div>
47+
</div>
48+
</div>
49+
</div>
50+
</div>
51+
</div>
52+
</div>
53+
</div>
54+
</div>
55+
</template>
56+
57+
<style scoped>
58+
.feedback-container {
59+
padding-bottom: 40px;
60+
padding-top: 40px;
61+
}
62+
63+
.callout-margin {
64+
margin-left: 20%;
65+
margin-right: 20%;
66+
}
67+
68+
.m-callout__content ul li {
69+
padding-left: 0;
70+
}
71+
72+
.feedback-callout {
73+
padding-top: 32px;
74+
margin-top: 0;
75+
}
76+
77+
.open-extern-button {
78+
margin-top: 16px;
79+
}
80+
81+
.docs-paragraph {
82+
margin-bottom: 16px;
83+
}
84+
85+
.version-row {
86+
margin-top: 24px;
87+
display: flex;
88+
gap: 12px;
89+
flex-wrap: wrap;
90+
}
91+
92+
.version-badge {
93+
display: inline-flex;
94+
align-items: center;
95+
font-size: 0.7rem;
96+
color: #909090;
97+
padding: 0;
98+
}
99+
100+
.version-label {
101+
font-weight: 400;
102+
margin-right: 4px;
103+
font-size: 0.7rem;
104+
}
105+
106+
.version-number {
107+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
108+
}
109+
110+
@media screen and (max-width: 768px) {
111+
.callout-margin {
112+
margin-left: 0%;
113+
margin-right: 0%;
114+
}
115+
}
116+
</style>

riski-frontend/src/riski-search-webcomponent.ce.vue

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import type RiskiAnswer from "@/types/RiskiAnswer";
44
import { MucCallout } from "@muenchen/muc-patternlab-vue";
55
import customIconsSprite from "@muenchen/muc-patternlab-vue/assets/icons/custom-icons.svg?raw";
66
import mucIconsSprite from "@muenchen/muc-patternlab-vue/assets/icons/muc-icons.svg?raw";
7-
import { nextTick, ref } from "vue";
7+
import { onMounted, nextTick, ref } from "vue";
88
99
import SearchService from "@/api/SearchService";
10+
import SystemClient from "@/api/SystemClient";
1011
import riskiIconsSprite from "@/assets/custom-icons.svg?raw";
1112
import RiskiResponseCard from "@/components/common/riski-response-card.vue";
1213
import riskiIntro from "@/components/riski-intro.vue";
14+
import riskiOutro from "@/components/riski-outro.vue";
1315
import riskiSearchbar from "@/components/riski-searchbar.vue";
1416
import { EXAMPLE_QUESTIONS } from "@/util/constants";
1517
@@ -22,6 +24,23 @@ const loading = ref<boolean>(false);
2224
const initial = ref<boolean>(true);
2325
const fehler = ref<string>("");
2426
const searchquery = ref<string>("");
27+
const title = ref("RIS KI Suche (Beta-Version)");
28+
const version = ref("unknown");
29+
const frontendVersion = ref("unknown");
30+
const documentationUrl = ref("https://ki.muenchen.de");
31+
32+
onMounted(async () => {
33+
try {
34+
const config = await SystemClient.getConfig();
35+
title.value = config.title;
36+
version.value = config.version;
37+
frontendVersion.value = config.frontend_version;
38+
documentationUrl.value = config.documentation_url;
39+
} catch (error) {
40+
console.error("Failed to load config", error);
41+
}
42+
});
43+
2544
2645
/**
2746
* Callback function for a successfully processed document with the answer chain.
@@ -101,7 +120,7 @@ const submitQuery = (query: string) => {
101120
<div v-html="customIconsSprite" />
102121
<div v-html="riskiIconsSprite" />
103122

104-
<riski-intro>
123+
<riski-intro :title="title">
105124
<riski-searchbar id="riski-searchbar" :submit-query="submitQuery" :query="searchquery"
106125
:on-clear="resetInitialState" />
107126
<ul v-if="initial" class="example-chips" role="list" aria-label="Beispielfragen">
@@ -173,6 +192,7 @@ const submitQuery = (query: string) => {
173192
</div>
174193
</div>
175194
</div>
195+
<riski-outro :version="version" :frontend-version="frontendVersion" :documentation-url="documentationUrl" />
176196
</div>
177197
</main>
178198
</template>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default interface ConfigResponse {
2+
version: string;
3+
frontend_version: string;
4+
title: string;
5+
documentation_url: string;
6+
}

0 commit comments

Comments
 (0)