Skip to content

Commit

Permalink
Shortcut url followup (#9908)
Browse files Browse the repository at this point in the history
* Shortcut url followup 2

* open in same window if is ocis uri

* add more tests

* add drop

* Duplicate filename handling

* Confirm modal with enter button

* Add https in front of uri if missing

* Fix file extension placement

* Add unit test

* Don't throw

* Fix styling

* Add search and fix unit tests

* Add more tests

* Change code comment

* Add changelog item

* Don't scope scss

* Kick oc10 leftover

* Fix space icon not shown

* Refactor search

* Fix unit tests

* Refactor tests

* React on code review

* React on code review

* Fix display Link to a file, shown if no search results

* Lint
  • Loading branch information
AlexAndBear authored Nov 8, 2023
1 parent 6f6a6a9 commit ad51cdc
Show file tree
Hide file tree
Showing 19 changed files with 600 additions and 290 deletions.
12 changes: 12 additions & 0 deletions changelog/unreleased/enhancement-create-shortcuts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Enhancement: Create shortcuts

We've added a new functionality to add to shortcuts to web, those can be created via the "+ New" context menu.
Users can enter URLs or pick a file via the drop down menu and create a '.url' file.

'.url' files can be opened via web or downloaded and opened on the desktop.

https://github.com/owncloud/web/pull/9890
https://github.com/owncloud/web/pull/9908
https://github.com/owncloud/web/issues/9796
https://github.com/owncloud/web/issues/9887
https://github.com/owncloud/web/issues/9850
3 changes: 2 additions & 1 deletion packages/web-app-files/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"vuex": "4.1.0",
"web-app-files": "workspace:*",
"web-app-search": "workspace:*",
"web-runtime": "workspace:*"
"web-runtime": "workspace:*",
"dompurify": "^3.0.6"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,12 @@

<script lang="ts">
import { mapActions, mapGetters } from 'vuex'
import { useFileActions, useFileActionsCreateNewShortcut } from '@ownclouders/web-pkg'
import { isLocationPublicActive, isLocationSpacesActive } from '@ownclouders/web-pkg'
import {
isLocationPublicActive,
isLocationSpacesActive,
useFileActions,
useFileActionsCreateNewShortcut
} from '@ownclouders/web-pkg'
import { useActiveLocation } from '@ownclouders/web-pkg'
import {
useFileActionsCreateNewFile,
Expand Down
8 changes: 3 additions & 5 deletions packages/web-app-files/src/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@ import {
Extension,
useStore,
useRouter,
useClientService,
useConfigurationManager
useSearch
} from '@ownclouders/web-pkg'
import { computed } from 'vue'
import { SDKSearch } from './search'

export const extensions = ({ applicationConfig }: ApplicationSetupOptions) => {
const store = useStore()
const router = useRouter()
const clientService = useClientService()
const configurationManager = useConfigurationManager()
const { search: searchFunction } = useSearch()

return computed(
() =>
[
{
id: 'com.github.owncloud.web.files.search',
type: 'search',
searchProvider: new SDKSearch(store, router, clientService, configurationManager)
searchProvider: new SDKSearch(store, router, searchFunction)
}
] satisfies Extension[]
)
Expand Down
20 changes: 5 additions & 15 deletions packages/web-app-files/src/search/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,24 @@ import Preview from './preview'
import List from './list'
import { Store } from 'vuex'
import { Router } from 'vue-router'
import {
ClientService,
ConfigurationManager,
SearchList,
SearchPreview,
SearchProvider
} from '@ownclouders/web-pkg'
import { SearchFunction, SearchList, SearchPreview, SearchProvider } from '@ownclouders/web-pkg'

function $gettext(msg) {
return msg
}

export default class Provider implements SearchProvider {
public readonly id: string
public readonly displayName: string
public readonly previewSearch: SearchPreview
public readonly listSearch: SearchList
private readonly store: Store<any>

constructor(
store: Store<any>,
router: Router,
clientService: ClientService,
configurationManager: ConfigurationManager
) {
constructor(store: Store<any>, router: Router, searchFunction: SearchFunction) {
this.id = 'files.sdk'
this.displayName = $gettext('Files')
this.previewSearch = new Preview(store, router, clientService, configurationManager)
this.listSearch = new List(store, clientService, configurationManager)
this.previewSearch = new Preview(router, searchFunction)
this.listSearch = new List(searchFunction)
this.store = store
}

Expand Down
69 changes: 7 additions & 62 deletions packages/web-app-files/src/search/sdk/list.ts
Original file line number Diff line number Diff line change
@@ -1,74 +1,19 @@
import ListComponent from '../../components/Search/List.vue'
import { ClientService, SearchList, SearchResult } from '@ownclouders/web-pkg'
import { ProjectSpaceResource, isProjectSpaceResource } from '@ownclouders/web-client/src/helpers'
import { Component, computed, Ref, unref } from 'vue'
import { DavProperties } from '@ownclouders/web-client/src/webdav/constants'
import { Store } from 'vuex'
import { ConfigurationManager } from '@ownclouders/web-pkg'
import { urlJoin } from '@ownclouders/web-client/src/utils'
import { SearchFunction, SearchList, SearchResult } from '@ownclouders/web-pkg'
import { Component } from 'vue'

export const searchLimit = 200

export default class List implements SearchList {
public readonly component: Component
private readonly store: Store<any>
private readonly clientService: ClientService
private readonly configurationManager: ConfigurationManager
private readonly projectSpaces: Ref<ProjectSpaceResource[]>
private readonly searchFunction: SearchFunction

constructor(
store: Store<any>,
clientService: ClientService,
configurationManager: ConfigurationManager
) {
constructor(searchFunction: SearchFunction) {
this.component = ListComponent
this.store = store
this.clientService = clientService
this.configurationManager = configurationManager
this.projectSpaces = computed(() =>
this.store.getters['runtime/spaces/spaces'].filter((s) => isProjectSpaceResource(s))
)
this.searchFunction = searchFunction
}

getProjectSpace(id): ProjectSpaceResource {
return unref(this.projectSpaces).find((s) => s.id === id)
}

async search(term: string): Promise<SearchResult> {
if (this.configurationManager.options.routing.fullShareOwnerPaths) {
await this.store.dispatch('runtime/spaces/loadMountPoints', {
graphClient: this.clientService.graphAuthenticated
})
}

if (!term) {
return {
totalResults: null,
values: []
}
}

const { resources, totalResults } = await this.clientService.webdav.search(term, {
searchLimit,
davProperties: DavProperties.Default
})

return {
totalResults,
values: resources.map((resource) => {
const matchingSpace = this.getProjectSpace(resource.parentFolderId)
const data = matchingSpace ? matchingSpace : resource

// info: in oc10 we have no storageId in resources. All resources are mounted into the personal space.
if (!data.storageId) {
data.storageId = this.store.getters.user.id
}
if (this.configurationManager.options.routing.fullShareOwnerPaths && data.shareRoot) {
data.path = urlJoin(data.shareRoot, data.path)
}

return { id: data.id, data }
})
}
public async search(term: string): Promise<SearchResult> {
return this.searchFunction(term, searchLimit)
}
}
83 changes: 7 additions & 76 deletions packages/web-app-files/src/search/sdk/preview.ts
Original file line number Diff line number Diff line change
@@ -1,92 +1,23 @@
import { ClientService, Cache, SearchPreview, SearchResult } from '@ownclouders/web-pkg'
import { ProjectSpaceResource, isProjectSpaceResource } from '@ownclouders/web-client/src/helpers'
import { Component, computed, Ref, unref } from 'vue'
import { SearchFunction, SearchPreview, SearchResult } from '@ownclouders/web-pkg'
import { Component, unref } from 'vue'
import { Router } from 'vue-router'
import { DavProperties } from '@ownclouders/web-client/src/webdav/constants'
import { Store } from 'vuex'
import { ConfigurationManager, ResourcePreview } from '@ownclouders/web-pkg'
import { urlJoin } from '@ownclouders/web-client/src/utils'
import { ResourcePreview } from '@ownclouders/web-pkg'

export const previewSearchLimit = 8

export default class Preview implements SearchPreview {
public readonly component: Component
private readonly cache: Cache<string, SearchResult>
private readonly router: Router
private readonly store: Store<any>
private readonly clientService: ClientService
private readonly configurationManager: ConfigurationManager
private readonly projectSpaces: Ref<ProjectSpaceResource[]>
private readonly searchFunction: SearchFunction

constructor(
store: Store<any>,
router: Router,
clientService: ClientService,
configurationManager: ConfigurationManager
) {
constructor(router: Router, searchFunction: SearchFunction) {
this.component = ResourcePreview
this.router = router
this.store = store
// define how long the cache should be valid, maybe conf option?
this.cache = new Cache({ ttl: 10000, capacity: 100 })
this.clientService = clientService
this.configurationManager = configurationManager
this.projectSpaces = computed(() =>
this.store.getters['runtime/spaces/spaces'].filter((s) => isProjectSpaceResource(s))
)
}

getProjectSpace(id): ProjectSpaceResource {
return unref(this.projectSpaces).find((s) => s.id === id)
this.searchFunction = searchFunction
}

public async search(term: string): Promise<SearchResult> {
if (!term) {
return {
totalResults: null,
values: []
}
}

if (this.configurationManager.options.routing.fullShareOwnerPaths) {
await this.store.dispatch('runtime/spaces/loadMountPoints', {
graphClient: this.clientService.graphAuthenticated
})
}

if (this.cache.has(term)) {
return this.cache.get(term)
}

const areHiddenFilesShown = this.store.state.Files?.areHiddenFilesShown

const { resources, totalResults } = await this.clientService.webdav.search(term, {
searchLimit: previewSearchLimit,
davProperties: DavProperties.Default
})

return {
totalResults,
values: resources
.map((resource) => {
const matchingSpace = this.getProjectSpace(resource.parentFolderId)
const data = matchingSpace ? matchingSpace : resource

// info: in oc10 we have no storageId in resources. All resources are mounted into the personal space.
if (!data.storageId) {
data.storageId = this.store.getters.user.id
}
if (this.configurationManager.options.routing.fullShareOwnerPaths && data.shareRoot) {
data.path = urlJoin(data.shareRoot, data.path)
}

return { id: data.id, data }
})
.filter(({ data }) => {
// filter results if hidden files shouldn't be shown due to settings
return !data.name.startsWith('.') || areHiddenFilesShown
})
}
return this.searchFunction(term, previewSearchLimit)
}

public get available(): boolean {
Expand Down
Loading

0 comments on commit ad51cdc

Please sign in to comment.