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 {
|
interface HealthResponse {
|
||||||
status: string
|
status: string
|
||||||
|
version?: string
|
||||||
engine: ConversionEngine
|
engine: ConversionEngine
|
||||||
deploymentMode?: DeploymentMode
|
deploymentMode?: DeploymentMode
|
||||||
maxPageCount?: number
|
maxPageCount?: number
|
||||||
|
|
@ -41,6 +42,7 @@ export const useFeatureFlagStore = defineStore('feature-flags', () => {
|
||||||
const deploymentMode = ref<DeploymentMode | null>(null)
|
const deploymentMode = ref<DeploymentMode | null>(null)
|
||||||
const maxPageCount = ref<number>(0)
|
const maxPageCount = ref<number>(0)
|
||||||
const maxFileSizeMb = ref<number>(0)
|
const maxFileSizeMb = ref<number>(0)
|
||||||
|
const appVersion = ref<string>(__APP_VERSION__)
|
||||||
const loaded = ref(false)
|
const loaded = ref(false)
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
|
|
@ -62,6 +64,7 @@ export const useFeatureFlagStore = defineStore('feature-flags', () => {
|
||||||
deploymentMode.value = data.deploymentMode ?? 'self-hosted'
|
deploymentMode.value = data.deploymentMode ?? 'self-hosted'
|
||||||
maxPageCount.value = data.maxPageCount ?? 0
|
maxPageCount.value = data.maxPageCount ?? 0
|
||||||
maxFileSizeMb.value = data.maxFileSizeMb ?? 0
|
maxFileSizeMb.value = data.maxFileSizeMb ?? 0
|
||||||
|
if (data.version) appVersion.value = data.version
|
||||||
loaded.value = true
|
loaded.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
} catch (e) {
|
} 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>
|
<label class="setting-label">{{ t('settings.version') }}</label>
|
||||||
<span class="setting-value">{{ version }}</span>
|
<span class="setting-value">{{ version }}</span>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
import { useSettingsStore } from '../store'
|
import { useSettingsStore } from '../store'
|
||||||
|
import { useFeatureFlagStore } from '../../feature-flags/store'
|
||||||
import { useI18n } from '../../../shared/i18n'
|
import { useI18n } from '../../../shared/i18n'
|
||||||
|
|
||||||
const version = __APP_VERSION__
|
|
||||||
const store = useSettingsStore()
|
const store = useSettingsStore()
|
||||||
|
const featureStore = useFeatureFlagStore()
|
||||||
|
const version = computed(() => featureStore.appVersion)
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -118,4 +146,35 @@ const { t } = useI18n()
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-family: 'IBM Plex Mono', monospace;
|
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>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -97,10 +97,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
import { RouterLink, useRoute } from 'vue-router'
|
import { RouterLink, useRoute } from 'vue-router'
|
||||||
import { useI18n } from '../i18n'
|
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 route = useRoute()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue