Include saved views in global search
This commit is contained in:
parent
05495794e8
commit
314e34c3b7
1079
src-ui/messages.xlf
1079
src-ui/messages.xlf
File diff suppressed because it is too large
Load Diff
@ -33,6 +33,9 @@
|
||||
@if (type === DataType.Document) {
|
||||
<i-bs width="1em" height="1em" name="pencil"></i-bs>
|
||||
<span> <ng-container i18n>Open</ng-container></span>
|
||||
} @else if (type === DataType.SavedView) {
|
||||
<i-bs width="1em" height="1em" name="eye"></i-bs>
|
||||
<span> <ng-container i18n>Open</ng-container></span>
|
||||
} @else if (type === DataType.Workflow || type === DataType.CustomField || type === DataType.Group || type === DataType.User || type === DataType.MailAccount || type === DataType.MailRule) {
|
||||
<i-bs width="1em" height="1em" name="pencil"></i-bs>
|
||||
<span> <ng-container i18n>Edit</ng-container></span>
|
||||
@ -41,7 +44,7 @@
|
||||
<span> <ng-container i18n>Filter documents</ng-container></span>
|
||||
}
|
||||
</button>
|
||||
@if (type !== DataType.Workflow && type !== DataType.CustomField && type !== DataType.Group && type !== DataType.User && type !== DataType.MailAccount && type !== DataType.MailRule) {
|
||||
@if (type !== DataType.SavedView && type !== DataType.Workflow && type !== DataType.CustomField && type !== DataType.Group && type !== DataType.User && type !== DataType.MailAccount && type !== DataType.MailRule) {
|
||||
<button #secondaryButton type="button" class="btn btn-sm btn-outline-primary d-flex"
|
||||
(click)="secondaryAction(type, item); $event.stopPropagation()"
|
||||
[disabled]="disableSecondaryButton(type, item)"
|
||||
@ -69,6 +72,12 @@
|
||||
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: document, nameProp: 'title', type: DataType.Document, icon: 'file-text', date: document.added}"></ng-container>
|
||||
}
|
||||
}
|
||||
@if (searchResults?.saved_views.length) {
|
||||
<h6 class="dropdown-header" i18n="@@searchResults.saved_views">Saved Views</h6>
|
||||
@for (saved_view of searchResults.saved_views; track saved_view.id) {
|
||||
<ng-container *ngTemplateOutlet="resultItemTemplate; context: {item: saved_view, nameProp: 'name', type: DataType.SavedView, icon: 'funnel'}"></ng-container>
|
||||
}
|
||||
}
|
||||
|
||||
@if (searchResults?.tags.length) {
|
||||
<h6 class="dropdown-header" i18n="@@searchResults.tags">Tags</h6>
|
||||
|
@ -51,6 +51,12 @@ const searchResults = {
|
||||
custom_fields: [],
|
||||
},
|
||||
],
|
||||
saved_views: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'TestSavedView',
|
||||
},
|
||||
],
|
||||
correspondents: [
|
||||
{
|
||||
id: 1,
|
||||
|
@ -112,6 +112,9 @@ export class GlobalSearchComponent implements OnInit {
|
||||
case DataType.Document:
|
||||
this.router.navigate(['/documents', object.id])
|
||||
return
|
||||
case DataType.SavedView:
|
||||
this.router.navigate(['/view', object.id])
|
||||
return
|
||||
case DataType.Correspondent:
|
||||
filterRuleType = FILTER_HAS_CORRESPONDENT_ANY
|
||||
break
|
||||
|
@ -1,5 +1,6 @@
|
||||
export enum DataType {
|
||||
Document = 'document',
|
||||
SavedView = 'saved_view',
|
||||
Correspondent = 'correspondent',
|
||||
DocumentType = 'document_type',
|
||||
StoragePath = 'storage_path',
|
||||
|
@ -15,10 +15,12 @@ import { User } from 'src/app/data/user'
|
||||
import { Workflow } from 'src/app/data/workflow'
|
||||
import { SettingsService } from '../settings.service'
|
||||
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
|
||||
import { SavedView } from 'src/app/data/saved-view'
|
||||
|
||||
export interface GlobalSearchResult {
|
||||
total: number
|
||||
documents: Document[]
|
||||
saved_views: SavedView[]
|
||||
correspondents: Correspondent[]
|
||||
document_types: DocumentType[]
|
||||
storage_paths: StoragePath[]
|
||||
|
@ -21,6 +21,7 @@ from documents.models import CustomFieldInstance
|
||||
from documents.models import Document
|
||||
from documents.models import DocumentType
|
||||
from documents.models import Note
|
||||
from documents.models import SavedView
|
||||
from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
from documents.models import Workflow
|
||||
@ -1171,10 +1172,17 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
StoragePath.objects.create(name="path 2", path="path2")
|
||||
tag1 = Tag.objects.create(name="bank tag1")
|
||||
Tag.objects.create(name="tag2")
|
||||
user1 = User.objects.create_user("bank user1")
|
||||
user1 = User.objects.create_superuser("bank user1")
|
||||
User.objects.create_user("user2")
|
||||
group1 = Group.objects.create(name="bank group1")
|
||||
Group.objects.create(name="group2")
|
||||
SavedView.objects.create(
|
||||
name="bank view",
|
||||
show_on_dashboard=True,
|
||||
show_in_sidebar=True,
|
||||
sort_field="",
|
||||
owner=user1,
|
||||
)
|
||||
mail_account1 = MailAccount.objects.create(name="bank mail account 1")
|
||||
mail_account2 = MailAccount.objects.create(name="mail account 2")
|
||||
mail_rule1 = MailRule.objects.create(
|
||||
@ -1198,10 +1206,13 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
workflow1 = Workflow.objects.create(name="bank workflow 1")
|
||||
Workflow.objects.create(name="workflow 2")
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
response = self.client.get("/api/search/?query=bank")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
results = response.data
|
||||
self.assertEqual(len(results["documents"]), 2)
|
||||
self.assertEqual(len(results["saved_views"]), 1)
|
||||
self.assertNotEqual(results["documents"][0]["id"], d3.id)
|
||||
self.assertNotEqual(results["documents"][1]["id"], d3.id)
|
||||
self.assertEqual(results["correspondents"][0]["id"], correspondent1.id)
|
||||
|
@ -1135,7 +1135,13 @@ class GlobalSearchView(PassUserMixin):
|
||||
)._get_query()
|
||||
results = s.search(q, limit=OBJECT_LIMIT)
|
||||
docs = docs | all_docs.filter(id__in=[r["id"] for r in results])
|
||||
|
||||
saved_views = (
|
||||
SavedView.objects.filter(owner=request.user, name__icontains=query)[
|
||||
:OBJECT_LIMIT
|
||||
]
|
||||
if request.user.has_perm("documents.view_savedview")
|
||||
else []
|
||||
)
|
||||
tags = (
|
||||
get_objects_for_user_owner_aware(request.user, "view_tag", Tag).filter(
|
||||
name__icontains=query,
|
||||
@ -1206,6 +1212,11 @@ class GlobalSearchView(PassUserMixin):
|
||||
}
|
||||
|
||||
docs_serializer = DocumentSerializer(docs, many=True, context=context)
|
||||
saved_views_serializer = SavedViewSerializer(
|
||||
saved_views,
|
||||
many=True,
|
||||
context=context,
|
||||
)
|
||||
tags_serializer = TagSerializer(tags, many=True, context=context)
|
||||
correspondents_serializer = CorrespondentSerializer(
|
||||
correspondents,
|
||||
@ -1244,6 +1255,7 @@ class GlobalSearchView(PassUserMixin):
|
||||
return Response(
|
||||
{
|
||||
"total": len(docs)
|
||||
+ len(saved_views)
|
||||
+ len(tags)
|
||||
+ len(correspondents)
|
||||
+ len(document_types)
|
||||
@ -1255,6 +1267,7 @@ class GlobalSearchView(PassUserMixin):
|
||||
+ len(workflows)
|
||||
+ len(custom_fields),
|
||||
"documents": docs_serializer.data,
|
||||
"saved_views": saved_views_serializer.data,
|
||||
"tags": tags_serializer.data,
|
||||
"correspondents": correspondents_serializer.data,
|
||||
"document_types": document_types_serializer.data,
|
||||
|
@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-19 01:15-0700\n"
|
||||
"POT-Creation-Date: 2024-04-19 11:01-0700\n"
|
||||
"PO-Revision-Date: 2022-02-17 04:17\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: English\n"
|
||||
@ -25,27 +25,27 @@ msgstr ""
|
||||
msgid "owner"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:53 documents/models.py:902
|
||||
#: documents/models.py:53 documents/models.py:897
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:54 documents/models.py:903
|
||||
#: documents/models.py:54 documents/models.py:898
|
||||
msgid "Any word"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:55 documents/models.py:904
|
||||
#: documents/models.py:55 documents/models.py:899
|
||||
msgid "All words"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:56 documents/models.py:905
|
||||
#: documents/models.py:56 documents/models.py:900
|
||||
msgid "Exact match"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:57 documents/models.py:906
|
||||
#: documents/models.py:57 documents/models.py:901
|
||||
msgid "Regular expression"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:58 documents/models.py:907
|
||||
#: documents/models.py:58 documents/models.py:902
|
||||
msgid "Fuzzy word"
|
||||
msgstr ""
|
||||
|
||||
@ -53,20 +53,20 @@ msgstr ""
|
||||
msgid "Automatic"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:62 documents/models.py:397 documents/models.py:1223
|
||||
#: documents/models.py:62 documents/models.py:397 documents/models.py:1218
|
||||
#: paperless_mail/models.py:18 paperless_mail/models.py:93
|
||||
msgid "name"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:64 documents/models.py:963
|
||||
#: documents/models.py:64 documents/models.py:958
|
||||
msgid "match"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:67 documents/models.py:966
|
||||
#: documents/models.py:67 documents/models.py:961
|
||||
msgid "matching algorithm"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:72 documents/models.py:971
|
||||
#: documents/models.py:72 documents/models.py:966
|
||||
msgid "is insensitive"
|
||||
msgstr ""
|
||||
|
||||
@ -615,246 +615,246 @@ msgstr ""
|
||||
msgid "custom field instances"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:910
|
||||
#: documents/models.py:905
|
||||
msgid "Consumption Started"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:911
|
||||
#: documents/models.py:906
|
||||
msgid "Document Added"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:912
|
||||
#: documents/models.py:907
|
||||
msgid "Document Updated"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:915
|
||||
#: documents/models.py:910
|
||||
msgid "Consume Folder"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:916
|
||||
#: documents/models.py:911
|
||||
msgid "Api Upload"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:917
|
||||
#: documents/models.py:912
|
||||
msgid "Mail Fetch"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:920
|
||||
#: documents/models.py:915
|
||||
msgid "Workflow Trigger Type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:932
|
||||
#: documents/models.py:927
|
||||
msgid "filter path"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:937
|
||||
#: documents/models.py:932
|
||||
msgid ""
|
||||
"Only consume documents with a path that matches this if specified. Wildcards "
|
||||
"specified as * are allowed. Case insensitive."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:944
|
||||
#: documents/models.py:939
|
||||
msgid "filter filename"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:949 paperless_mail/models.py:148
|
||||
#: documents/models.py:944 paperless_mail/models.py:148
|
||||
msgid ""
|
||||
"Only consume documents which entirely match this filename if specified. "
|
||||
"Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:960
|
||||
#: documents/models.py:955
|
||||
msgid "filter documents from this mail rule"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:976
|
||||
#: documents/models.py:971
|
||||
msgid "has these tag(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:984
|
||||
#: documents/models.py:979
|
||||
msgid "has this document type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:992
|
||||
#: documents/models.py:987
|
||||
msgid "has this correspondent"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:996
|
||||
#: documents/models.py:991
|
||||
msgid "workflow trigger"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:997
|
||||
#: documents/models.py:992
|
||||
msgid "workflow triggers"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1007
|
||||
#: documents/models.py:1002
|
||||
msgid "Assignment"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1011
|
||||
#: documents/models.py:1006
|
||||
msgid "Removal"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1015
|
||||
#: documents/models.py:1010
|
||||
msgid "Workflow Action Type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1021
|
||||
#: documents/models.py:1016
|
||||
msgid "assign title"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1026
|
||||
#: documents/models.py:1021
|
||||
msgid ""
|
||||
"Assign a document title, can include some placeholders, see documentation."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1035 paperless_mail/models.py:216
|
||||
#: documents/models.py:1030 paperless_mail/models.py:216
|
||||
msgid "assign this tag"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1044 paperless_mail/models.py:224
|
||||
#: documents/models.py:1039 paperless_mail/models.py:224
|
||||
msgid "assign this document type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1053 paperless_mail/models.py:238
|
||||
#: documents/models.py:1048 paperless_mail/models.py:238
|
||||
msgid "assign this correspondent"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1062
|
||||
#: documents/models.py:1057
|
||||
msgid "assign this storage path"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1071
|
||||
#: documents/models.py:1066
|
||||
msgid "assign this owner"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1078
|
||||
#: documents/models.py:1073
|
||||
msgid "grant view permissions to these users"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1085
|
||||
#: documents/models.py:1080
|
||||
msgid "grant view permissions to these groups"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1092
|
||||
#: documents/models.py:1087
|
||||
msgid "grant change permissions to these users"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1099
|
||||
#: documents/models.py:1094
|
||||
msgid "grant change permissions to these groups"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1106
|
||||
#: documents/models.py:1101
|
||||
msgid "assign these custom fields"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1113
|
||||
#: documents/models.py:1108
|
||||
msgid "remove these tag(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1118
|
||||
#: documents/models.py:1113
|
||||
msgid "remove all tags"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1125
|
||||
#: documents/models.py:1120
|
||||
msgid "remove these document type(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1130
|
||||
#: documents/models.py:1125
|
||||
msgid "remove all document types"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1137
|
||||
#: documents/models.py:1132
|
||||
msgid "remove these correspondent(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1142
|
||||
#: documents/models.py:1137
|
||||
msgid "remove all correspondents"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1149
|
||||
#: documents/models.py:1144
|
||||
msgid "remove these storage path(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1154
|
||||
#: documents/models.py:1149
|
||||
msgid "remove all storage paths"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1161
|
||||
#: documents/models.py:1156
|
||||
msgid "remove these owner(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1166
|
||||
#: documents/models.py:1161
|
||||
msgid "remove all owners"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1173
|
||||
#: documents/models.py:1168
|
||||
msgid "remove view permissions for these users"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1180
|
||||
#: documents/models.py:1175
|
||||
msgid "remove view permissions for these groups"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1187
|
||||
#: documents/models.py:1182
|
||||
msgid "remove change permissions for these users"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1194
|
||||
#: documents/models.py:1189
|
||||
msgid "remove change permissions for these groups"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1199
|
||||
#: documents/models.py:1194
|
||||
msgid "remove all permissions"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1206
|
||||
#: documents/models.py:1201
|
||||
msgid "remove these custom fields"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1211
|
||||
#: documents/models.py:1206
|
||||
msgid "remove all custom fields"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1215
|
||||
#: documents/models.py:1210
|
||||
msgid "workflow action"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1216
|
||||
#: documents/models.py:1211
|
||||
msgid "workflow actions"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1225 paperless_mail/models.py:95
|
||||
#: documents/models.py:1220 paperless_mail/models.py:95
|
||||
msgid "order"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1231
|
||||
#: documents/models.py:1226
|
||||
msgid "triggers"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1238
|
||||
#: documents/models.py:1233
|
||||
msgid "actions"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1241
|
||||
#: documents/models.py:1236
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: documents/serialisers.py:115
|
||||
#: documents/serialisers.py:114
|
||||
#, python-format
|
||||
msgid "Invalid regular expression: %(error)s"
|
||||
msgstr ""
|
||||
|
||||
#: documents/serialisers.py:418
|
||||
#: documents/serialisers.py:417
|
||||
msgid "Invalid color."
|
||||
msgstr ""
|
||||
|
||||
#: documents/serialisers.py:1148
|
||||
#: documents/serialisers.py:1171
|
||||
#, python-format
|
||||
msgid "File type %(type)s not supported"
|
||||
msgstr ""
|
||||
|
||||
#: documents/serialisers.py:1257
|
||||
#: documents/serialisers.py:1280
|
||||
msgid "Invalid variable detected."
|
||||
msgstr ""
|
||||
|
||||
@ -1350,7 +1350,7 @@ msgstr ""
|
||||
msgid "Chinese Simplified"
|
||||
msgstr ""
|
||||
|
||||
#: paperless/urls.py:230
|
||||
#: paperless/urls.py:236
|
||||
msgid "Paperless-ngx administration"
|
||||
msgstr ""
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user