diff --git a/packages/web-app-admin-settings/src/views/Users.vue b/packages/web-app-admin-settings/src/views/Users.vue
index 00fe2a7337..4b7e50d37e 100644
--- a/packages/web-app-admin-settings/src/views/Users.vue
+++ b/packages/web-app-admin-settings/src/views/Users.vue
@@ -99,10 +99,10 @@
/>
diff --git a/packages/web-pkg/src/components/FilesList/ResourceLink.vue b/packages/web-pkg/src/components/FilesList/ResourceLink.vue
index 9a7d1e7fc9..65659ebe31 100644
--- a/packages/web-pkg/src/components/FilesList/ResourceLink.vue
+++ b/packages/web-pkg/src/components/FilesList/ResourceLink.vue
@@ -1,7 +1,7 @@
{
+ const isLoading = ref(true)
+ const hasError = ref(false)
+ const updates = ref()
+
+ const setIsLoading = (value: boolean) => {
+ isLoading.value = value
+ }
+ const setHasError = (value: boolean) => {
+ hasError.value = value
+ }
+ const setUpdates = (data: Updates) => {
+ updates.value = data
+ }
+
+ return {
+ updates,
+ isLoading,
+ hasError,
+ setUpdates,
+ setHasError,
+ setIsLoading
+ }
+})
+
+export type UpdatesStore = ReturnType
diff --git a/packages/web-pkg/src/types.ts b/packages/web-pkg/src/types.ts
index 8afedfc6c5..5bea5c1690 100644
--- a/packages/web-pkg/src/types.ts
+++ b/packages/web-pkg/src/types.ts
@@ -18,3 +18,12 @@ export type FederatedUser = {
export type FederatedConnection = FederatedUser & {
id: string
}
+
+export interface UpdateChannel {
+ current_version: string
+ url: string
+}
+
+export interface Updates {
+ channels: Record
+}
diff --git a/packages/web-runtime/src/components/MobileNav.vue b/packages/web-runtime/src/components/MobileNav.vue
index 36ce19ddf0..275cfc452d 100644
--- a/packages/web-runtime/src/components/MobileNav.vue
+++ b/packages/web-runtime/src/components/MobileNav.vue
@@ -36,6 +36,12 @@
+
@@ -43,9 +49,13 @@
diff --git a/packages/web-runtime/src/components/VersionCheck.vue b/packages/web-runtime/src/components/VersionCheck.vue
index 29ce6524b8..7e94440a09 100644
--- a/packages/web-runtime/src/components/VersionCheck.vue
+++ b/packages/web-runtime/src/components/VersionCheck.vue
@@ -32,74 +32,37 @@
diff --git a/packages/web-runtime/src/container/bootstrap.ts b/packages/web-runtime/src/container/bootstrap.ts
index 8cbca54ccd..74e55681a2 100644
--- a/packages/web-runtime/src/container/bootstrap.ts
+++ b/packages/web-runtime/src/container/bootstrap.ts
@@ -43,7 +43,10 @@ import {
AppConfigObject,
resourceIconMappingInjectionKey,
ResourceIconMapping,
- ClassicApplicationScript
+ ClassicApplicationScript,
+ UpdatesStore,
+ useUpdatesStore,
+ Updates
} from '@opencloud-eu/web-pkg'
import { authService } from '../services/auth'
import { init as sentryInit } from '@sentry/vue'
@@ -386,6 +389,7 @@ export const announcePiniaStores = () => {
const spacesStore = useSpacesStore()
const userStore = useUserStore()
const webWorkersStore = useWebWorkersStore()
+ const updatesStore = useUpdatesStore()
return {
appsStore,
@@ -399,7 +403,8 @@ export const announcePiniaStores = () => {
sharesStore,
spacesStore,
userStore,
- webWorkersStore
+ webWorkersStore,
+ updatesStore
}
}
@@ -676,6 +681,51 @@ export const announceVersions = ({
})
}
+/**
+ * announce updates
+ *
+ * @param updateStore
+ * @param capabilityStore
+ * @param configStore
+ * @param clientService
+ */
+export const announceUpdates = async ({
+ updatesStore,
+ capabilityStore,
+ configStore,
+ clientService
+}: {
+ updatesStore: UpdatesStore
+ capabilityStore: CapabilityStore
+ configStore: ConfigStore
+ clientService: ClientService
+}): Promise => {
+ if (!capabilityStore.capabilities.core['check-for-updates']) {
+ return
+ }
+
+ try {
+ updatesStore.setIsLoading(true)
+ const { data }: { data: Updates } = await clientService.httpUnAuthenticated.get(
+ 'https://update.opencloud.eu/server.json',
+ {
+ params: {
+ server: configStore.serverUrl,
+ edition: capabilityStore.status.edition || 'rolling',
+ version: capabilityStore.status.productversion
+ }
+ }
+ )
+
+ updatesStore.setUpdates(data)
+ } catch (e) {
+ console.error(e)
+ updatesStore.setHasError(true)
+ } finally {
+ updatesStore.setIsLoading(false)
+ }
+}
+
/**
* starts the sentry monitor
*
diff --git a/packages/web-runtime/src/index.ts b/packages/web-runtime/src/index.ts
index 1c085f4979..681ea0dc22 100644
--- a/packages/web-runtime/src/index.ts
+++ b/packages/web-runtime/src/index.ts
@@ -28,7 +28,8 @@ import {
setViewOptions,
announceGettext,
announceArchiverService,
- announceAppProviderService
+ announceAppProviderService,
+ announceUpdates
} from './container/bootstrap'
import { applicationStore } from './container/store'
import {
@@ -65,7 +66,8 @@ export const bootstrapApp = async (configurationPath: string, appsReadyCallback:
resourcesStore,
messagesStore,
sharesStore,
- webWorkersStore
+ webWorkersStore,
+ updatesStore
} = announcePiniaStores()
extensionRegistry.registerExtensionPoints(extensionPoints())
@@ -181,6 +183,7 @@ export const bootstrapApp = async (configurationPath: string, appsReadyCallback:
return
}
announceVersions({ capabilityStore })
+ announceUpdates({ updatesStore, capabilityStore, configStore, clientService })
await announceApplicationsReady({
app,
diff --git a/packages/web-runtime/tests/unit/components/VersionCheck.spec.ts b/packages/web-runtime/tests/unit/components/VersionCheck.spec.ts
index c17f715b90..7734500037 100644
--- a/packages/web-runtime/tests/unit/components/VersionCheck.spec.ts
+++ b/packages/web-runtime/tests/unit/components/VersionCheck.spec.ts
@@ -1,62 +1,42 @@
import VersionCheck from '../../../src/components/VersionCheck.vue'
-import {
- defaultComponentMocks,
- defaultPlugins,
- mockAxiosResolve,
- mount
-} from '@opencloud-eu/web-test-helpers'
+import { defaultComponentMocks, defaultPlugins, mount } from '@opencloud-eu/web-test-helpers'
+import { nextTick } from 'vue'
describe('VersionCheck component', () => {
- it('shows loading spinner while loading', () => {
- const { wrapper } = getWrapper()
+ it('shows loading spinner while loading', async () => {
+ const { wrapper } = getWrapper({ isLoading: true })
+ await nextTick()
expect(wrapper.find('.version-check-loading').exists()).toBe(true)
expect(wrapper.find('.version-check-no-updates').exists()).toBe(false)
expect(wrapper.find('.version-check-update').exists()).toBe(false)
})
it('shows no update available, when up to date', async () => {
const { wrapper } = getWrapper()
- await (wrapper.vm as any).loadVersionsTask.last
- await new Promise((r) => setTimeout(r, 1100))
+ await nextTick()
expect(wrapper.find('.version-check-no-updates').exists()).toBe(true)
expect(wrapper.find('.version-check-update').exists()).toBe(false)
expect(wrapper.find('.version-check-loading').exists()).toBe(false)
})
it('shows update available, when not up to date', async () => {
const { wrapper } = getWrapper({ productversion: '3.4.0' })
- await new Promise((r) => setTimeout(r, 1100))
- await (wrapper.vm as any).loadVersionsTask.last
+ await nextTick()
expect(wrapper.find('.version-check-update').exists()).toBe(true)
expect(wrapper.find('.version-check-no-updates').exists()).toBe(false)
expect(wrapper.find('.version-check-loading').exists()).toBe(false)
})
})
-function getWrapper({ productversion = '3.5.0' }: { productversion?: string } = {}) {
+function getWrapper({
+ productversion = '3.5.0',
+ hasError = false,
+ isLoading = false
+}: {
+ productversion?: string
+ hasError?: boolean
+ isLoading?: boolean
+} = {}) {
const mocks = { ...defaultComponentMocks() }
- mocks.$clientService.httpUnAuthenticated.get.mockResolvedValue(
- mockAxiosResolve({
- channels: {
- rolling: {
- current_version: '3.5.0',
- url: 'https://github.com/opencloud-eu/opencloud/releases/tag/v3.5.0'
- },
- stable: {
- current_version: '2.0.4',
- url: 'https://github.com/opencloud-eu/opencloud/releases/tag/v2.0.4'
- },
- lts: {
- current_version: '2.0.4',
- url: 'https://github.com/opencloud-eu/opencloud/releases/tag/v2.0.4'
- },
- 'lts-2.0': {
- current_version: '2.0.4',
- url: 'https://github.com/opencloud-eu/opencloud/releases/tag/v2.0.4'
- }
- }
- })
- )
-
return {
wrapper: mount(VersionCheck, {
global: {
@@ -65,7 +45,31 @@ function getWrapper({ productversion = '3.5.0' }: { productversion?: string } =
plugins: [
...defaultPlugins({
piniaOptions: {
- capabilityState: { capabilities: { core: { status: { productversion } } } }
+ capabilityState: { capabilities: { core: { status: { productversion } } } },
+ updatesState: {
+ isLoading,
+ hasError,
+ updates: {
+ channels: {
+ rolling: {
+ current_version: '3.5.0',
+ url: 'https://github.com/opencloud-eu/opencloud/releases/tag/v3.5.0'
+ },
+ stable: {
+ current_version: '2.0.4',
+ url: 'https://github.com/opencloud-eu/opencloud/releases/tag/v2.0.4'
+ },
+ lts: {
+ current_version: '2.0.4',
+ url: 'https://github.com/opencloud-eu/opencloud/releases/tag/v2.0.4'
+ },
+ 'lts-2.0': {
+ current_version: '2.0.4',
+ url: 'https://github.com/opencloud-eu/opencloud/releases/tag/v2.0.4'
+ }
+ }
+ }
+ }
}
})
]
diff --git a/packages/web-test-helpers/src/mocks/pinia.ts b/packages/web-test-helpers/src/mocks/pinia.ts
index 5a8091c430..e13d45c4a9 100644
--- a/packages/web-test-helpers/src/mocks/pinia.ts
+++ b/packages/web-test-helpers/src/mocks/pinia.ts
@@ -9,6 +9,7 @@ import {
Message,
Modal,
OptionsConfig,
+ Updates,
WebThemeType
} from '@opencloud-eu/web-pkg'
import {
@@ -83,6 +84,11 @@ export type PiniaMockOptions = {
capabilities?: Partial
isInitialized?: boolean
}
+ updatesState?: {
+ isLoading?: boolean
+ hasError?: boolean
+ updates?: Updates
+ }
}
export function createMockStore({
@@ -102,7 +108,8 @@ export function createMockStore({
sharesState = {},
spacesState = {},
userState = {},
- capabilityState = {}
+ capabilityState = {},
+ updatesState = {}
}: PiniaMockOptions = {}) {
const defaultOpenCloudTheme = {
defaults: {
@@ -164,7 +171,8 @@ export function createMockStore({
...mock(),
...(capabilityState?.capabilities && { ...capabilityState.capabilities })
}
- }
+ },
+ updates: { isLoading: true, hasError: false, ...updatesState }
}
})
}