mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-06-20 15:17:32 -05:00
QoL: log version at startup, show backend vs frontend mismatch in system status (#10214)
This commit is contained in:
parent
83391af866
commit
52b95f2b62
@ -21,7 +21,7 @@ ARG PNGX_TAG_VERSION=
|
|||||||
RUN set -eux && \
|
RUN set -eux && \
|
||||||
case "${PNGX_TAG_VERSION}" in \
|
case "${PNGX_TAG_VERSION}" in \
|
||||||
dev|beta|fix*|feature*) \
|
dev|beta|fix*|feature*) \
|
||||||
sed -i -E "s/version: '([0-9\.]+)'/version: '\1 #${PNGX_TAG_VERSION}'/g" /src/src-ui/src/environments/environment.prod.ts \
|
sed -i -E "s/tag: '([a-z\.]+)'/tag: '${PNGX_TAG_VERSION}'/g" /src/src-ui/src/environments/environment.prod.ts \
|
||||||
;; \
|
;; \
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ export class AppFrameComponent
|
|||||||
extends ComponentWithPermissions
|
extends ComponentWithPermissions
|
||||||
implements OnInit, ComponentCanDeactivate
|
implements OnInit, ComponentCanDeactivate
|
||||||
{
|
{
|
||||||
versionString = `${environment.appTitle} ${environment.version}`
|
|
||||||
appRemoteVersion: AppRemoteVersion
|
appRemoteVersion: AppRemoteVersion
|
||||||
|
|
||||||
isMenuCollapsed: boolean = true
|
isMenuCollapsed: boolean = true
|
||||||
@ -142,6 +141,10 @@ export class AppFrameComponent
|
|||||||
}, 200) // slightly longer than css animation for slim sidebar
|
}, 200) // slightly longer than css animation for slim sidebar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get versionString(): string {
|
||||||
|
return `${environment.appTitle} v${this.settingsService.get(SETTINGS_KEYS.VERSION)}${environment.production ? '' : ` #${environment.tag}`}`
|
||||||
|
}
|
||||||
|
|
||||||
get customAppTitle(): string {
|
get customAppTitle(): string {
|
||||||
return this.settingsService.get(SETTINGS_KEYS.APP_TITLE)
|
return this.settingsService.get(SETTINGS_KEYS.APP_TITLE)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,18 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<dl class="card-text">
|
<dl class="card-text">
|
||||||
<dt i18n>Paperless-ngx Version</dt>
|
<dt i18n>Paperless-ngx Version</dt>
|
||||||
<dd>{{status.pngx_version}}</dd>
|
<dd>
|
||||||
|
{{status.pngx_version}}
|
||||||
|
@if (versionMismatch) {
|
||||||
|
<button class="btn btn-sm d-inline align-items-center btn-dark text-uppercase small" [ngbPopover]="versionPopover" triggers="click mouseenter:mouseleave">
|
||||||
|
<i-bs name="exclamation-triangle-fill" class="text-danger lh-1"></i-bs>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
<ng-template #versionPopover>
|
||||||
|
Frontend version: {{frontendVersion}}<br>
|
||||||
|
Backend version: {{status.pngx_version}}
|
||||||
|
</ng-template>
|
||||||
|
</dd>
|
||||||
<dt i18n>Install Type</dt>
|
<dt i18n>Install Type</dt>
|
||||||
<dd>{{status.install_type}}</dd>
|
<dd>{{status.install_type}}</dd>
|
||||||
<dt i18n>Server OS</dt>
|
<dt i18n>Server OS</dt>
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
// Mock production environment for testing
|
||||||
|
jest.mock('src/environments/environment', () => ({
|
||||||
|
environment: {
|
||||||
|
production: true,
|
||||||
|
apiBaseUrl: 'http://localhost:8000/api/',
|
||||||
|
apiVersion: '9',
|
||||||
|
appTitle: 'Paperless-ngx',
|
||||||
|
tag: 'prod',
|
||||||
|
version: '2.4.3',
|
||||||
|
webSocketHost: 'localhost:8000',
|
||||||
|
webSocketProtocol: 'ws:',
|
||||||
|
webSocketBaseUrl: '/ws/',
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
import { Clipboard } from '@angular/cdk/clipboard'
|
import { Clipboard } from '@angular/cdk/clipboard'
|
||||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||||
import { provideHttpClientTesting } from '@angular/common/http/testing'
|
import { provideHttpClientTesting } from '@angular/common/http/testing'
|
||||||
@ -142,4 +157,15 @@ describe('SystemStatusDialogComponent', () => {
|
|||||||
`Task ${PaperlessTaskName.IndexOptimize} started`
|
`Task ${PaperlessTaskName.IndexOptimize} started`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('shoduld handle version mismatch', () => {
|
||||||
|
component.frontendVersion = '2.4.2'
|
||||||
|
component.ngOnInit()
|
||||||
|
expect(component.versionMismatch).toBeTruthy()
|
||||||
|
expect(component.status.pngx_version).toContain('(frontend: 2.4.2)')
|
||||||
|
component.frontendVersion = '2.4.3'
|
||||||
|
component.status.pngx_version = '2.4.3'
|
||||||
|
component.ngOnInit()
|
||||||
|
expect(component.versionMismatch).toBeFalsy()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Clipboard, ClipboardModule } from '@angular/cdk/clipboard'
|
import { Clipboard, ClipboardModule } from '@angular/cdk/clipboard'
|
||||||
import { Component } from '@angular/core'
|
import { Component, OnInit } from '@angular/core'
|
||||||
import {
|
import {
|
||||||
NgbActiveModal,
|
NgbActiveModal,
|
||||||
NgbModalModule,
|
NgbModalModule,
|
||||||
@ -18,6 +18,7 @@ import { PermissionsService } from 'src/app/services/permissions.service'
|
|||||||
import { SystemStatusService } from 'src/app/services/system-status.service'
|
import { SystemStatusService } from 'src/app/services/system-status.service'
|
||||||
import { TasksService } from 'src/app/services/tasks.service'
|
import { TasksService } from 'src/app/services/tasks.service'
|
||||||
import { ToastService } from 'src/app/services/toast.service'
|
import { ToastService } from 'src/app/services/toast.service'
|
||||||
|
import { environment } from 'src/environments/environment'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pngx-system-status-dialog',
|
selector: 'pngx-system-status-dialog',
|
||||||
@ -33,10 +34,12 @@ import { ToastService } from 'src/app/services/toast.service'
|
|||||||
NgxBootstrapIconsModule,
|
NgxBootstrapIconsModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SystemStatusDialogComponent {
|
export class SystemStatusDialogComponent implements OnInit {
|
||||||
public SystemStatusItemStatus = SystemStatusItemStatus
|
public SystemStatusItemStatus = SystemStatusItemStatus
|
||||||
public PaperlessTaskName = PaperlessTaskName
|
public PaperlessTaskName = PaperlessTaskName
|
||||||
public status: SystemStatus
|
public status: SystemStatus
|
||||||
|
public frontendVersion: string = environment.version
|
||||||
|
public versionMismatch: boolean = false
|
||||||
|
|
||||||
public copied: boolean = false
|
public copied: boolean = false
|
||||||
|
|
||||||
@ -55,6 +58,17 @@ export class SystemStatusDialogComponent {
|
|||||||
private permissionsService: PermissionsService
|
private permissionsService: PermissionsService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
public ngOnInit() {
|
||||||
|
this.versionMismatch =
|
||||||
|
environment.production &&
|
||||||
|
this.status.pngx_version &&
|
||||||
|
this.frontendVersion &&
|
||||||
|
this.status.pngx_version !== this.frontendVersion
|
||||||
|
if (this.versionMismatch) {
|
||||||
|
this.status.pngx_version = `${this.status.pngx_version} (frontend: ${this.frontendVersion})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public close() {
|
public close() {
|
||||||
this.activeModal.close()
|
this.activeModal.close()
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ export enum GlobalSearchType {
|
|||||||
export const PAPERLESS_GREEN_HEX = '#17541f'
|
export const PAPERLESS_GREEN_HEX = '#17541f'
|
||||||
|
|
||||||
export const SETTINGS_KEYS = {
|
export const SETTINGS_KEYS = {
|
||||||
|
VERSION: 'version',
|
||||||
LANGUAGE: 'language',
|
LANGUAGE: 'language',
|
||||||
APP_LOGO: 'app_logo',
|
APP_LOGO: 'app_logo',
|
||||||
APP_TITLE: 'app_title',
|
APP_TITLE: 'app_title',
|
||||||
@ -76,6 +77,11 @@ export const SETTINGS_KEYS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const SETTINGS: UiSetting[] = [
|
export const SETTINGS: UiSetting[] = [
|
||||||
|
{
|
||||||
|
key: SETTINGS_KEYS.VERSION,
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: SETTINGS_KEYS.LANGUAGE,
|
key: SETTINGS_KEYS.LANGUAGE,
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
@ -5,6 +5,7 @@ export const environment = {
|
|||||||
apiBaseUrl: document.baseURI + 'api/',
|
apiBaseUrl: document.baseURI + 'api/',
|
||||||
apiVersion: '9', // match src/paperless/settings.py
|
apiVersion: '9', // match src/paperless/settings.py
|
||||||
appTitle: 'Paperless-ngx',
|
appTitle: 'Paperless-ngx',
|
||||||
|
tag: 'prod',
|
||||||
version: '2.16.3',
|
version: '2.16.3',
|
||||||
webSocketHost: window.location.host,
|
webSocketHost: window.location.host,
|
||||||
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
||||||
|
@ -7,6 +7,7 @@ export const environment = {
|
|||||||
apiBaseUrl: 'http://localhost:8000/api/',
|
apiBaseUrl: 'http://localhost:8000/api/',
|
||||||
apiVersion: '9',
|
apiVersion: '9',
|
||||||
appTitle: 'Paperless-ngx',
|
appTitle: 'Paperless-ngx',
|
||||||
|
tag: 'dev',
|
||||||
version: 'DEVELOPMENT',
|
version: 'DEVELOPMENT',
|
||||||
webSocketHost: 'localhost:8000',
|
webSocketHost: 'localhost:8000',
|
||||||
webSocketProtocol: 'ws:',
|
webSocketProtocol: 'ws:',
|
||||||
|
@ -7,6 +7,7 @@ from rest_framework import status
|
|||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from documents.tests.utils import DirectoriesMixin
|
from documents.tests.utils import DirectoriesMixin
|
||||||
|
from paperless.version import __full_version_str__
|
||||||
|
|
||||||
|
|
||||||
class TestApiUiSettings(DirectoriesMixin, APITestCase):
|
class TestApiUiSettings(DirectoriesMixin, APITestCase):
|
||||||
@ -39,6 +40,7 @@ class TestApiUiSettings(DirectoriesMixin, APITestCase):
|
|||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
response.data["settings"],
|
response.data["settings"],
|
||||||
{
|
{
|
||||||
|
"version": __full_version_str__,
|
||||||
"app_title": None,
|
"app_title": None,
|
||||||
"app_logo": None,
|
"app_logo": None,
|
||||||
"auditlog_enabled": True,
|
"auditlog_enabled": True,
|
||||||
|
@ -2184,6 +2184,8 @@ class UiSettingsView(GenericAPIView):
|
|||||||
|
|
||||||
general_config = GeneralConfig()
|
general_config = GeneralConfig()
|
||||||
|
|
||||||
|
ui_settings["version"] = version.__full_version_str__
|
||||||
|
|
||||||
ui_settings["app_title"] = settings.APP_TITLE
|
ui_settings["app_title"] = settings.APP_TITLE
|
||||||
if general_config.app_title is not None and len(general_config.app_title) > 0:
|
if general_config.app_title is not None and len(general_config.app_title) > 0:
|
||||||
ui_settings["app_title"] = general_config.app_title
|
ui_settings["app_title"] = general_config.app_title
|
||||||
|
@ -21,3 +21,10 @@ application = ProtocolTypeRouter(
|
|||||||
"websocket": AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),
|
"websocket": AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import logging # noqa: E402
|
||||||
|
|
||||||
|
from paperless.version import __full_version_str__ # noqa: E402
|
||||||
|
|
||||||
|
logger = logging.getLogger("paperless.asgi")
|
||||||
|
logger.info(f"[init] Paperless-ngx version: v{__full_version_str__}")
|
||||||
|
@ -14,3 +14,10 @@ from django.core.wsgi import get_wsgi_application
|
|||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "paperless.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "paperless.settings")
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
|
|
||||||
|
import logging # noqa: E402
|
||||||
|
|
||||||
|
from paperless.version import __full_version_str__ # noqa: E402
|
||||||
|
|
||||||
|
logger = logging.getLogger("paperless.wsgi")
|
||||||
|
logger.info(f"[init] Paperless-ngx version: v{__full_version_str__}")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user