Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/web-app-admin-settings/src/views/Users.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@
/>
<oc-button
id="users-filter-confirm"
v-oc-tooltip="$gettext('Search')"
class="ml-1 p-1 mt-5"
appearance="raw"
:aria-label="$gettext('Search users')"
v-oc-tooltip="$gettext('Search')"
@click="filterDisplayName"
>
<oc-icon name="search" fill-type="line" aria-hidden="true" />
Expand Down
2 changes: 1 addition & 1 deletion packages/web-pkg/src/components/FilesList/ResourceLink.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<component
v-if="isResourceClickable"
:is="isNavigatable ? 'router-link' : 'oc-button'"
v-if="isResourceClickable"
:to="isNavigatable ? link : undefined"
:target="isNavigatable ? linkTarget : undefined"
:rel="isNavigatable && linkTarget === '_blank' ? 'noopener noreferrer' : undefined"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
>
<resource-link
v-if="isIconDisplayed"
v-oc-tooltip="isResourceClickable ? tooltipLabelIcon : undefined"
:resource="resource"
:link="link"
:is-resource-clickable="isResourceClickable"
class="relative"
:class="{ 'hover:underline': isResourceClickable }"
v-oc-tooltip="isResourceClickable ? tooltipLabelIcon : undefined"
:aria-label="
isResourceClickable ? $gettext('Open »%{name}«', { name: resource?.name ?? '' }) : undefined
"
Expand Down
1 change: 1 addition & 0 deletions packages/web-pkg/src/composables/piniaStores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export * from './theme'
export * from './user'
export * from './webWorkers'
export * from './avatars'
export * from './updates'
30 changes: 30 additions & 0 deletions packages/web-pkg/src/composables/piniaStores/updates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { Updates } from '../../types'

export const useUpdatesStore = defineStore('updates', () => {
const isLoading = ref<boolean>(true)
const hasError = ref<boolean>(false)
const updates = ref<Updates>()

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<typeof useUpdatesStore>
9 changes: 9 additions & 0 deletions packages/web-pkg/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, UpdateChannel>
}
17 changes: 16 additions & 1 deletion packages/web-runtime/src/components/MobileNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,43 @@
</oc-button>
</li>
</oc-list>
<div
class="versions flex flex-col items-center justify-center py-2 mt-4 bg-role-surface-container text-xs text-role-on-surface-variant"
>
<div v-text="backendVersion" />
<version-check v-if="checkForUpdates" />
</div>
</oc-drop>
</nav>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, unref } from 'vue'
import { NavItem } from '../helpers/navItems'
import VersionCheck from './VersionCheck.vue'
import { getBackendVersion } from '../container/versions'
import { useCapabilityStore } from '@opencloud-eu/web-pkg/src'

export default defineComponent({
name: 'MobileNav',
components: { VersionCheck },
props: {
navItems: {
type: Array as PropType<NavItem[]>,
required: true
}
},
setup(props) {
const capabilityStore = useCapabilityStore()

const checkForUpdates = capabilityStore.capabilities.core['check-for-updates']

const backendVersion = computed(() => getBackendVersion({ capabilityStore }))
const activeNavItem = computed(() => {
return unref(props.navItems).find((n) => n.active) || props.navItems[0]
})

return { activeNavItem }
return { activeNavItem, checkForUpdates, backendVersion }
}
})
</script>
77 changes: 20 additions & 57 deletions packages/web-runtime/src/components/VersionCheck.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,74 +32,37 @@
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useTask } from 'vue-concurrency'
import { ref, watch, unref } from 'vue'
import { useGettext } from 'vue3-gettext'
import semver from 'semver'
import { useCapabilityStore, useClientService, useConfigStore } from '@opencloud-eu/web-pkg'
import { promiseTimeout } from '@vueuse/core'

export interface UpdateChannelData {
current_version: string
url: string
}

export type UpdateChannelName = 'rolling' | 'production'

export type UpdateChannels = Record<UpdateChannelName, UpdateChannelData>

export interface UpdateResponseData {
channels: UpdateChannels
}
import { UpdateChannel, useCapabilityStore, useUpdatesStore } from '@opencloud-eu/web-pkg'
import { storeToRefs } from 'pinia'

const { $gettext } = useGettext()
const { httpUnAuthenticated } = useClientService()
const capabilityStore = useCapabilityStore()
const configStore = useConfigStore()
const updatesStore = useUpdatesStore()

const { updates, isLoading, hasError } = storeToRefs(updatesStore)

const updateAvailable = ref(false)
const hasError = ref(false)
const updateData = ref<UpdateChannelData>()
//TODO: retrieve serverEdition
const serverEdition = 'rolling'
const updateData = ref<UpdateChannel>()

const serverEdition = capabilityStore.status.edition || 'rolling'
const currentServerVersion = capabilityStore.status.productversion
const currentServerVersionSanitized = currentServerVersion.split('+')[0]

const hasMinLoadingTimePassed = ref(false)
const isLoading = computed(
() => loadVersionsTask.isRunning || !loadVersionsTask.last || !hasMinLoadingTimePassed.value
)

const loadVersionsTask = useTask(function* (signal) {
promiseTimeout(1000).then(() => {
hasMinLoadingTimePassed.value = true
})

try {
const { data }: { data: UpdateResponseData } = yield httpUnAuthenticated.get(
`https://update.opencloud.eu/server.json`,
{
params: {
server: configStore.serverUrl,
edition: serverEdition,
version: currentServerVersion
},
signal
}
)

const newestVersion = data.channels[serverEdition].current_version
watch(
() => updates,
() => {
if (!unref(updates)) {
return
}
const newestVersion = unref(updates).channels[serverEdition].current_version
if (semver.gt(newestVersion, currentServerVersionSanitized)) {
updateAvailable.value = true
updateData.value = data.channels[serverEdition]
updateData.value = unref(updates).channels[serverEdition]
}
} catch (error) {
console.error(error)
hasError.value = true
}
}).restartable()

onMounted(() => {
loadVersionsTask.perform()
})
},
{ immediate: true, deep: true }
)
</script>
54 changes: 52 additions & 2 deletions packages/web-runtime/src/container/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -386,6 +389,7 @@ export const announcePiniaStores = () => {
const spacesStore = useSpacesStore()
const userStore = useUserStore()
const webWorkersStore = useWebWorkersStore()
const updatesStore = useUpdatesStore()

return {
appsStore,
Expand All @@ -399,7 +403,8 @@ export const announcePiniaStores = () => {
sharesStore,
spacesStore,
userStore,
webWorkersStore
webWorkersStore,
updatesStore
}
}

Expand Down Expand Up @@ -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<void> => {
if (!capabilityStore.capabilities.core['check-for-updates']) {
return
}

try {
updatesStore.setIsLoading(true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you set loading to true here? It's initialized with true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just in case, if we re-use this function, e.G polling or something else, this would come in handy

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
*
Expand Down
7 changes: 5 additions & 2 deletions packages/web-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import {
setViewOptions,
announceGettext,
announceArchiverService,
announceAppProviderService
announceAppProviderService,
announceUpdates
} from './container/bootstrap'
import { applicationStore } from './container/store'
import {
Expand Down Expand Up @@ -65,7 +66,8 @@ export const bootstrapApp = async (configurationPath: string, appsReadyCallback:
resourcesStore,
messagesStore,
sharesStore,
webWorkersStore
webWorkersStore,
updatesStore
} = announcePiniaStores()

extensionRegistry.registerExtensionPoints(extensionPoints())
Expand Down Expand Up @@ -181,6 +183,7 @@ export const bootstrapApp = async (configurationPath: string, appsReadyCallback:
return
}
announceVersions({ capabilityStore })
announceUpdates({ updatesStore, capabilityStore, configStore, clientService })

await announceApplicationsReady({
app,
Expand Down
Loading