enh(search): Always search in current folder

Signed-off-by: Marcel Klehr <mklehr@gmx.net>
This commit is contained in:
Marcel Klehr 2024-02-04 11:55:25 +01:00
parent eaaae2b531
commit 88cd54bae8
12 changed files with 58 additions and 15 deletions

View File

@ -23,7 +23,7 @@ return [
//Web Template Route
['name' => 'web_view#index', 'url' => '/', 'verb' => 'GET'],
['name' => 'web_view#index', 'url' => '/recent', 'verb' => 'GET', 'postfix' => 'recent'],
['name' => 'web_view#index', 'url' => '/search/{search}', 'verb' => 'GET', 'postfix' => 'search'],
['name' => 'web_view#index', 'url' => '/folders/{folder}/search/{search}', 'verb' => 'GET', 'postfix' => 'search'],
['name' => 'web_view#index', 'url' => '/folders/{folder}', 'verb' => 'GET', 'postfix' => 'folder'],
['name' => 'web_view#index', 'url' => '/bookmarks/{bookmark}', 'verb' => 'GET', 'postfix' => 'bookmark'],
['name' => 'web_view#index', 'url' => '/tags/{tags}', 'verb' => 'GET', 'postfix' => 'tags'],

View File

@ -284,7 +284,8 @@ class BookmarkController extends ApiController {
?string $url = null,
?bool $unavailable = null,
?bool $archived = null,
?bool $duplicated = null
?bool $duplicated = null,
bool $recursive = false,
): DataResponse {
$this->registerResponder('rss', function (DataResponse $res) {
if ($res->getData()['status'] === 'success') {
@ -372,6 +373,7 @@ class BookmarkController extends ApiController {
return new DataResponse(['status' => 'error', 'data' => 'Not found'], Http::STATUS_BAD_REQUEST);
}
$params->setFolder($this->toInternalFolderId($folder));
$params->setRecursive($recursive);
}
if ($userId !== null) {

View File

@ -74,9 +74,10 @@ class InternalBookmarkController extends ApiController {
$url = null,
$unavailable = null,
$archived = null,
$duplicated = null
$duplicated = null,
bool $recursive = false,
): DataResponse {
return $this->publicController->getBookmarks($page, $tags, $conjunction, $sortby, $search, $limit, $untagged, $folder, $url, $unavailable, $archived, $duplicated);
return $this->publicController->getBookmarks($page, $tags, $conjunction, $sortby, $search, $limit, $untagged, $folder, $url, $unavailable, $archived, $duplicated, $recursive);
}
/**

View File

@ -464,7 +464,13 @@ class BookmarkMapper extends QBMapper {
*/
private function _filterFolder(IQueryBuilder $qb, QueryParameters $params): void {
if ($params->getFolder() !== null) {
$qb->andWhere($qb->expr()->eq('tree.parent_folder', $qb->createPositionalParameter($params->getFolder(), IQueryBuilder::PARAM_INT)));
if ($params->getRecursive()) {
$childFolders = \OC::$server->get(TreeMapper::class)->findByAncestorFolder(TreeMapper::TYPE_FOLDER, $params->getFolder());
$ids = array_map(fn (Folder $folder) => $folder->getId(), $childFolders);
$qb->andWhere($qb->expr()->in('tree.parent_folder', $qb->createPositionalParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));
} else {
$qb->andWhere($qb->expr()->eq('tree.parent_folder', $qb->createPositionalParameter($params->getFolder(), IQueryBuilder::PARAM_INT)));
}
}
}

View File

@ -25,6 +25,7 @@ class QueryParameters {
private $duplicated = false;
private $search = [];
private $tags = [];
private bool $recursive = false;
/**
* @return array
@ -241,4 +242,20 @@ class QueryParameters {
public function getDuplicated(): bool {
return $this->duplicated;
}
/**
* @param bool $recursive
* @return static
*/
public function setRecursive(bool $recursive): self {
$this->recursive = $recursive;
return $this;
}
/**
* @return bool
*/
public function getRecursive(): bool {
return $this->recursive;
}
}

View File

@ -138,7 +138,7 @@ export default {
}
return results
}
return this.$store.getters.getFolder(-1)[0].children.flatMap(searchFolder)
return this.$store.getters.getFolder(this.$store.state.fetchState.query.folder)[0].children.flatMap(searchFolder)
}
if (this.$route.name !== this.routes.HOME && this.$route.name !== this.routes.FOLDER) {
return []

View File

@ -7,7 +7,7 @@
<template>
<div :class="['controls', $store.state.public && 'wide']">
<div class="controls__left">
<NcActions v-if="$route.name === routes.FOLDER">
<NcActions v-if="$route.name === routes.FOLDER || ($route.name === routes.SEARCH && $route.params.folder !== -1)">
<NcActionButton @click="onClickBack">
<template #icon>
<ArrowLeftIcon :size="20" />
@ -15,7 +15,7 @@
{{ t('bookmarks', 'Go back') }}
</NcActionButton>
</NcActions>
<template v-if="$route.name === routes.FOLDER">
<template v-if="$route.name === routes.FOLDER || ($route.name === routes.SEARCH && $route.params.folder !== -1)">
<h2><FolderIcon :size="20" /> <span>{{ folder.title }}</span></h2>
<NcActions v-if="permissions.canShare">
<NcActionButton :close-after-click="true" @click="onOpenFolderShare">
@ -271,7 +271,17 @@ export default {
onSearch(query) {
if (this.searchTimeout) clearTimeout(this.searchTimeout)
this.searchTimeout = setTimeout(() => this.$router.push({ name: this.routes.SEARCH, params: { search: query } }), 350)
this.searchTimeout = setTimeout(() => {
if (query.trim()) {
this.$router.push({ name: this.routes.SEARCH, params: { search: query, folder: this.folder?.id || -1 } })
} else if (this.$route.name === this.routes.SEARCH) {
if (this.folder) {
this.$router.push({ name: this.routes.FOLDER, params: { folder: this.folder.id } })
} else {
this.$router.push({ name: this.routes.HOME })
}
}
}, 350)
},
copyRssUrl() {

View File

@ -13,6 +13,13 @@
<FileDocumentMultipleIcon :size="20" />
</template>
</NcEmptyContent>
<NcEmptyContent v-else-if="$route.name === routes.SEARCH"
:name="t('bookmarks', 'Nothing found')"
:description="t('bookmarks', 'Your search yielded no results in the current folder.')">
<template #icon>
<StarShootingIcon :size="20" />
</template>
</NcEmptyContent>
<NcEmptyContent v-else-if="$route.name === routes.UNAVAILABLE"
:name="t('bookmarks', 'No broken links')"
:description="t('bookmarks', 'Bookmarked links are checked regularly and the ones that cannot be reached are listed here.')">

View File

@ -169,7 +169,7 @@ export default {
)
break
case privateRoutes.SEARCH:
this.$store.dispatch(actions.FILTER_BY_SEARCH, route.params.search)
this.$store.dispatch(actions.FILTER_BY_SEARCH, { search: route.params.search, folder: route.params.folder || -1 })
break
default:
throw new Error('Nothing here. Move along.')

View File

@ -84,7 +84,7 @@ export default {
route.params.tags.split(',')
)
case this.routes.SEARCH:
return this.$store.dispatch(actions.FILTER_BY_SEARCH, route.params.search)
return this.$store.dispatch(actions.FILTER_BY_SEARCH, { search: route.params.search, folder: route.params.folder || -1 })
default:
throw new Error('Nothing here. Move along.')
}

View File

@ -55,7 +55,7 @@ export default new Router({
component: ViewPrivate,
},
{
path: '/search/:search',
path: '/folders/:folder/search/:search',
name: privateRoutes.SEARCH,
component: ViewPrivate,
},
@ -116,7 +116,7 @@ export default new Router({
component: ViewPublic,
},
{
path: '/public/:token/search/:search',
path: '/public/:token/folder/:folder/search/:search',
name: publicRoutes.SEARCH,
component: ViewPublic,
},

View File

@ -962,8 +962,8 @@ export default {
commit(mutations.SET_QUERY, { sortby: 'clickcount' })
return dispatch(actions.FETCH_PAGE)
},
[actions.FILTER_BY_SEARCH]({ dispatch, commit }, search) {
commit(mutations.SET_QUERY, { search: search.split(' '), conjunction: 'and' })
[actions.FILTER_BY_SEARCH]({ dispatch, commit }, { search, folder }) {
commit(mutations.SET_QUERY, { search: search.split(' '), conjunction: 'and', folder, recursive: true })
return dispatch(actions.FETCH_PAGE)
},
[actions.FILTER_BY_TAGS]({ dispatch, commit }, tags) {