feat: single source of truth for app version from health check
Read version from the backend /api/health endpoint instead of hardcoding from package.json at build time. Add About section in Settings with link to the DZone design article.
This commit is contained in:
parent
f487b752dc
commit
abf3325923
3 changed files with 78 additions and 3 deletions
|
|
@ -7,6 +7,7 @@ type DeploymentMode = 'self-hosted' | 'huggingface'
|
|||
|
||||
interface HealthResponse {
|
||||
status: string
|
||||
version?: string
|
||||
engine: ConversionEngine
|
||||
deploymentMode?: DeploymentMode
|
||||
maxPageCount?: number
|
||||
|
|
@ -41,6 +42,7 @@ export const useFeatureFlagStore = defineStore('feature-flags', () => {
|
|||
const deploymentMode = ref<DeploymentMode | null>(null)
|
||||
const maxPageCount = ref<number>(0)
|
||||
const maxFileSizeMb = ref<number>(0)
|
||||
const appVersion = ref<string>(__APP_VERSION__)
|
||||
const loaded = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
|
|
@ -62,6 +64,7 @@ export const useFeatureFlagStore = defineStore('feature-flags', () => {
|
|||
deploymentMode.value = data.deploymentMode ?? 'self-hosted'
|
||||
maxPageCount.value = data.maxPageCount ?? 0
|
||||
maxFileSizeMb.value = data.maxFileSizeMb ?? 0
|
||||
if (data.version) appVersion.value = data.version
|
||||
loaded.value = true
|
||||
error.value = null
|
||||
} catch (e) {
|
||||
|
|
@ -70,5 +73,15 @@ export const useFeatureFlagStore = defineStore('feature-flags', () => {
|
|||
}
|
||||
}
|
||||
|
||||
return { engine, deploymentMode, maxPageCount, maxFileSizeMb, loaded, error, isEnabled, load }
|
||||
return {
|
||||
engine,
|
||||
deploymentMode,
|
||||
maxPageCount,
|
||||
maxFileSizeMb,
|
||||
appVersion,
|
||||
loaded,
|
||||
error,
|
||||
isEnabled,
|
||||
load,
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -36,15 +36,43 @@
|
|||
<label class="setting-label">{{ t('settings.version') }}</label>
|
||||
<span class="setting-value">{{ version }}</span>
|
||||
</div>
|
||||
|
||||
<div class="setting-group">
|
||||
<label class="setting-label">{{ t('settings.about') }}</label>
|
||||
<a
|
||||
href="https://dzone.com/articles/designing-docling-studio"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="about-link"
|
||||
>
|
||||
<svg viewBox="0 0 20 20" fill="currentColor" class="about-link-icon">
|
||||
<path
|
||||
d="M9 4.804A7.968 7.968 0 005.5 4c-1.255 0-2.443.29-3.5.804v10A7.969 7.969 0 015.5 14c1.669 0 3.218.51 4.5 1.385A7.962 7.962 0 0114.5 14c1.255 0 2.443.29 3.5.804v-10A7.968 7.968 0 0014.5 4c-1.255 0-2.443.29-3.5.804V12a1 1 0 11-2 0V4.804z"
|
||||
/>
|
||||
</svg>
|
||||
{{ t('settings.designArticle') }}
|
||||
<svg viewBox="0 0 20 20" fill="currentColor" class="about-link-external">
|
||||
<path
|
||||
d="M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z"
|
||||
/>
|
||||
<path
|
||||
d="M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useSettingsStore } from '../store'
|
||||
import { useFeatureFlagStore } from '../../feature-flags/store'
|
||||
import { useI18n } from '../../../shared/i18n'
|
||||
|
||||
const version = __APP_VERSION__
|
||||
const store = useSettingsStore()
|
||||
const featureStore = useFeatureFlagStore()
|
||||
const version = computed(() => featureStore.appVersion)
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
|
|
@ -118,4 +146,35 @@ const { t } = useI18n()
|
|||
color: var(--text);
|
||||
font-family: 'IBM Plex Mono', monospace;
|
||||
}
|
||||
|
||||
.about-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-elevated);
|
||||
transition: all var(--transition);
|
||||
width: fit-content;
|
||||
}
|
||||
.about-link:hover {
|
||||
color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
background: var(--accent-muted);
|
||||
}
|
||||
.about-link-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.about-link-external {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
flex-shrink: 0;
|
||||
opacity: 0.4;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -97,10 +97,13 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import { useI18n } from '../i18n'
|
||||
import { useFeatureFlagStore } from '../../features/feature-flags/store'
|
||||
|
||||
const version = __APP_VERSION__
|
||||
const featureStore = useFeatureFlagStore()
|
||||
const version = computed(() => featureStore.appVersion)
|
||||
const route = useRoute()
|
||||
const { t } = useI18n()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue