Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: space notification links #10603

Draft
wants to merge 1 commit into
base: stable-8.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions changelog/unreleased/bugfix-space-notification-links
@@ -0,0 +1,6 @@
Bugfix: Space notification links

Links for incoming new space notifications have been fixed. We also made sure links are being removed if a user has been removed from a space and the space had been loaded before.

https://github.com/owncloud/web/issues/10397
https://github.com/owncloud/web/pull/10603
37 changes: 32 additions & 5 deletions packages/web-runtime/src/components/Topbar/Notifications.vue
Expand Up @@ -104,6 +104,7 @@ import { useGettext } from 'vue3-gettext'
import { useTask } from 'vue-concurrency'
import { createFileRouteOptions } from '@ownclouders/web-pkg'
import { MESSAGE_TYPE } from '@ownclouders/web-client/src/sse'
import { buildSpace } from '@ownclouders/web-client/src/helpers'

const POLLING_INTERVAL = 30000

Expand Down Expand Up @@ -159,7 +160,7 @@ export default {
}
return message
}
const getLink = ({ messageRichParameters, object_type }: Notification) => {
const getLink = async ({ messageRichParameters, object_type, subject }: Notification) => {
if (!messageRichParameters) {
return null
}
Expand All @@ -175,21 +176,47 @@ export default {
const space = store.getters['runtime/spaces/spaces'].find(
(s) => s.fileId === messageRichParameters?.space?.id.split('!')[0] && !s.disabled
)
if (space) {

if (space && subject === 'Removed from Space') {
Copy link
Member

Choose a reason for hiding this comment

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

Isn't the subject translated by the backend? So this would only work for users who have set English as language?

Copy link
Member

Choose a reason for hiding this comment

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

also... don't we have a different property to check on? Subject is really ugly for this :-(

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Haha yes, totally forgot 🙈 Well, then this is blocked by the server. There is no other way to distinguish between the subjects.

I'll create an issue for it.

Copy link
Member

Choose a reason for hiding this comment

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

thank you 💪

store.commit('runtime/spaces/REMOVE_SPACE', space)
return null
} else if (space) {
return {
name: 'files-spaces-generic',
...createFileRouteOptions(space, { path: '', fileId: space.fileId })
}
}

try {
const { data } = await clientService.graphAuthenticated.drives.getDrive(
messageRichParameters.space.id
)

const space = buildSpace(data)
if (!space.isMember(store.getters.user)) {
return null
}

store.commit('runtime/spaces/UPSERT_SPACE', space)

return {
name: 'files-spaces-generic',
...createFileRouteOptions(space, { path: '', fileId: space.fileId })
}
} catch (error) {
// user has probably been removed from space
console.error(error)
return null
}
}
return null
}

const setAdditionalData = () => {
const setAdditionalData = async () => {
loading.value = true
for (const notification of unref(notifications)) {
notification.computedMessage = getMessage(notification)
notification.computedLink = getLink(notification)
notification.computedLink = await getLink(notification)
}
loading.value = false
}
Expand All @@ -215,7 +242,7 @@ export default {
console.error(e)
} finally {
if (unref(dropdownOpened)) {
setAdditionalData()
yield setAdditionalData()
}
loading.value = false
}
Expand Down
Expand Up @@ -6,10 +6,12 @@ import {
defaultComponentMocks,
defaultPlugins,
shallowMount,
defaultStoreMockOptions
defaultStoreMockOptions,
mockAxiosResolve
} from 'web-test-helpers'
import { OwnCloudSdk } from '@ownclouders/web-client/src/types'
import { SpaceResource } from '@ownclouders/web-client'
import { Drive } from '@ownclouders/web-client/src/generated'

const selectors = {
notificationBellStub: 'notification-bell-stub',
Expand All @@ -21,7 +23,8 @@ const selectors = {
notificationSubject: '.oc-notifications-subject',
notificationMessage: '.oc-notifications-message',
notificationLink: '.oc-notifications-link',
notificationActions: '.oc-notifications-actions'
notificationActions: '.oc-notifications-actions',
notificationRouterLinkStub: '.oc-notifications-item router-link-stub'
}

jest.mock('@ownclouders/web-pkg', () => ({
Expand Down Expand Up @@ -160,15 +163,14 @@ describe('Notification component', () => {
await wrapper.vm.fetchNotificationsTask.last
wrapper.vm.showDrop()
await wrapper.vm.$nextTick()
const routerLink = wrapper.findComponent<any>(
`${selectors.notificationItem} router-link-stub`
)
await wrapper.vm.$nextTick()
const routerLink = wrapper.findComponent<any>(selectors.notificationRouterLinkStub)
expect(routerLink.props('to').name).toEqual('files-shares-with-me')
expect(routerLink.props('to').query).toEqual({
scrollTo: notification.messageRichParameters.share.id
})
})
it('renders notification as link for spaces', async () => {
it('renders notification as link for already loaded spaces', async () => {
const spaceMock = mock<SpaceResource>({
fileId: '1',
getDriveAliasAndItem: () => 'driveAlias',
Expand All @@ -187,13 +189,66 @@ describe('Notification component', () => {
await wrapper.vm.fetchNotificationsTask.last
wrapper.vm.showDrop()
await wrapper.vm.$nextTick()
const routerLink = wrapper.findComponent<any>(
`${selectors.notificationItem} router-link-stub`
)
await wrapper.vm.$nextTick()
const routerLink = wrapper.findComponent<any>(selectors.notificationRouterLinkStub)
expect(routerLink.props('to').params).toEqual({
driveAliasAndItem: 'driveAlias'
})
})
it('renders notification as link for new spaces after fetching them', async () => {
const spaceMock = mock<SpaceResource>({
fileId: '1',
getDriveAliasAndItem: () => 'driveAlias',
disabled: false
})
const notification = mock<Notification>({
messageRich: '{user} added you to space {space}',
object_type: 'storagespace',
messageRichParameters: {
user: { displayname: 'Albert Einstein' },
space: { name: 'someFile.txt', id: `${spaceMock.fileId}!2` }
}
})

const { wrapper, mocks } = getWrapper({ notifications: [notification] })
mocks.$clientService.graphAuthenticated.drives.getDrive.mockResolvedValue(
mockAxiosResolve(mock<Drive>({ special: [] }))
)

await wrapper.vm.fetchNotificationsTask.perform()
await wrapper.vm.fetchNotificationsTask.last
wrapper.vm.showDrop()
await wrapper.vm.$nextTick()
await wrapper.vm.$nextTick()
const routerLink = wrapper.findComponent<any>(selectors.notificationRouterLinkStub)

expect(mocks.$clientService.graphAuthenticated.drives.getDrive).toHaveBeenCalledTimes(1)
expect(routerLink.exists()).toBeTruthy()
})
it('does not render notification as link if user has been removed from space', async () => {
const spaceMock = mock<SpaceResource>({
fileId: '1',
getDriveAliasAndItem: () => 'driveAlias',
disabled: false
})
const notification = mock<Notification>({
messageRich: '{user} removed you from space {space}',
object_type: 'storagespace',
subject: 'Removed from Space',
messageRichParameters: {
user: { displayname: 'Albert Einstein' },
space: { name: 'someFile.txt', id: `${spaceMock.fileId}!2` }
}
})
const { wrapper } = getWrapper({ notifications: [notification], spaces: [spaceMock] })
await wrapper.vm.fetchNotificationsTask.perform()
await wrapper.vm.fetchNotificationsTask.last
wrapper.vm.showDrop()
await wrapper.vm.$nextTick()
await wrapper.vm.$nextTick()
const routerLink = wrapper.findComponent<any>(selectors.notificationRouterLinkStub)
expect(routerLink.exists()).toBeFalsy()
})
})
})
describe('actions', () => {
Expand Down