diff --git a/changelog/unreleased/add-file-type-filter-chip.md b/changelog/unreleased/add-file-type-filter-chip.md new file mode 100644 index 00000000000..707c958ad50 --- /dev/null +++ b/changelog/unreleased/add-file-type-filter-chip.md @@ -0,0 +1,6 @@ +Enhancement: Add "File type" filter Chip + +Add "File type" filter Chip + +https://github.com/owncloud/ocis/pull/7602 +https://github.com/owncloud/ocis/issues/7432 diff --git a/services/frontend/pkg/revaconfig/config.go b/services/frontend/pkg/revaconfig/config.go index 39b731ba9a5..a6a413ea7e2 100644 --- a/services/frontend/pkg/revaconfig/config.go +++ b/services/frontend/pkg/revaconfig/config.go @@ -305,7 +305,8 @@ func FrontendConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string "enabled": true, }, "type": map[string]interface{}{ - "enabled": true, + "keywords": []string{"file", "folder", "documents", "spreadsheets", "presentations", "pdfs", "images", "videos", "audio", "archives"}, + "enabled": true, }, "tag": map[string]interface{}{ "enabled": true, diff --git a/services/search/pkg/query/bleve/compiler.go b/services/search/pkg/query/bleve/compiler.go index c7b1c70d821..028af547b8e 100644 --- a/services/search/pkg/query/bleve/compiler.go +++ b/services/search/pkg/query/bleve/compiler.go @@ -95,7 +95,18 @@ func walk(offset int, nodes []ast.Node) (bleveQuery.Query, int, error) { v = strings.ToLower(v) } - q := bleveQuery.NewQueryStringQuery(k + ":" + v) + var q bleveQuery.Query + var group bool + switch k { + case "MimeType": + q, group = mimeType(k, v) + if prev == nil { + isGroup = group + } + default: + q = bleveQuery.NewQueryStringQuery(k + ":" + v) + } + if prev == nil { prev = q } else { @@ -232,9 +243,21 @@ func mapBinary(operator *ast.OperatorNode, ln, rn bleveQuery.Query, leftIsGroup } if operator.Value == kql.BoolOR { if left, ok := ln.(*bleveQuery.DisjunctionQuery); ok { + // if both are DisjunctionQuery then merge + if right, ok := rn.(*bleveQuery.DisjunctionQuery); ok { + left.AddQuery(right.Disjuncts...) + return left + } left.AddQuery(rn) return left } + if _, ok := ln.(*bleveQuery.ConjunctionQuery); !ok { + if right, ok := rn.(*bleveQuery.DisjunctionQuery); ok { + left := bleveQuery.NewDisjunctionQuery([]bleveQuery.Query{ln}) + left.AddQuery(right.Disjuncts...) + return left + } + } return bleveQuery.NewDisjunctionQuery([]bleveQuery.Query{ ln, rn, @@ -264,3 +287,76 @@ func normalizeGroupingProperty(group *ast.GroupNode) *ast.GroupNode { } return group } + +func mimeType(k, v string) (bleveQuery.Query, bool) { + switch v { + case "file": + q := bleve.NewBooleanQuery() + q.AddMustNot(bleveQuery.NewQueryStringQuery(k + ":httpd/unix-directory")) + return q, false + case "folder": + return bleveQuery.NewQueryStringQuery(k + ":httpd/unix-directory"), false + case "documents": + return bleveQuery.NewDisjunctionQuery(newQueryStringQueryList(k, + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.oasis.opendocument.text", + "text/plain", + "text/markdown", + "application/rtf", + "application/vnd.apple.pages", + )), true + case "spreadsheets": + return bleveQuery.NewDisjunctionQuery(newQueryStringQueryList(k, + "application/vnd.ms-excel", + "application/vnd.oasis.opendocument.spreadsheet", + "text/csv", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.oasis.opendocument.presentation", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "application/vnd.oasis.opendocument.spreadsheet", + "application/vnd.apple.numbers", + )), true + case "presentations": + return bleveQuery.NewDisjunctionQuery(newQueryStringQueryList(k, + "application/vnd.ms-excel", + "application/vnd.oasis.opendocument.spreadsheet", + "text/csv", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.oasis.opendocument.presentation", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "application/vnd.oasis.opendocument.spreadsheet", + "application/vnd.apple.numbers", + )), true + case "pdfs": + return bleveQuery.NewQueryStringQuery(k + ":application/pdf"), false + case "images": + return bleveQuery.NewQueryStringQuery(k + ":image/*"), false + case "videos": + return bleveQuery.NewQueryStringQuery(k + ":video/*"), false + case "audio": + return bleveQuery.NewQueryStringQuery(k + ":audio/*"), false + case "archives": + return bleveQuery.NewDisjunctionQuery(newQueryStringQueryList(k, + "application/zip", + "application/x-tar", + "application/x-gzip", + "application/x-7", + "z-compressed", + "application/x-rar-compressed", + "application/x-bzip2", + "application/x-bzip", + "application/x-tgz", + )), true + default: + return bleveQuery.NewQueryStringQuery(k + ":" + v), false + } +} + +func newQueryStringQueryList(k string, v ...string) []bleveQuery.Query { + list := make([]bleveQuery.Query, len(v)) + for i := 0; i < len(v); i++ { + list[i] = bleveQuery.NewQueryStringQuery(k + ":" + v[i]) + } + return list +} diff --git a/services/search/pkg/query/bleve/compiler_test.go b/services/search/pkg/query/bleve/compiler_test.go index 7a36b647dc2..82e4ce0ec12 100644 --- a/services/search/pkg/query/bleve/compiler_test.go +++ b/services/search/pkg/query/bleve/compiler_test.go @@ -120,6 +120,51 @@ func Test_compile(t *testing.T) { }), wantErr: false, }, + { + name: `a OR b AND c`, + args: &ast.Ast{ + Nodes: []ast.Node{ + &ast.StringNode{Value: "a"}, + &ast.OperatorNode{Value: "OR"}, + &ast.StringNode{Value: "b"}, + &ast.OperatorNode{Value: "AND"}, + &ast.StringNode{Value: "c"}, + }, + }, + want: query.NewDisjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`Name:a`), + query.NewConjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`Name:b`), + query.NewQueryStringQuery(`Name:c`), + }), + }), + wantErr: false, + }, + { + name: `(a OR b OR c) AND d`, + args: &ast.Ast{ + Nodes: []ast.Node{ + &ast.GroupNode{Nodes: []ast.Node{ + &ast.StringNode{Value: "a"}, + &ast.OperatorNode{Value: "OR"}, + &ast.StringNode{Value: "b"}, + &ast.OperatorNode{Value: "OR"}, + &ast.StringNode{Value: "c"}, + }}, + &ast.OperatorNode{Value: "AND"}, + &ast.StringNode{Value: "d"}, + }, + }, + want: query.NewConjunctionQuery([]query.Query{ + query.NewDisjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`Name:a`), + query.NewQueryStringQuery(`Name:b`), + query.NewQueryStringQuery(`Name:c`), + }), + query.NewQueryStringQuery(`Name:d`), + }), + wantErr: false, + }, { name: `(name:"moby di*" OR tag:bestseller) AND tag:book`, args: &ast.Ast{ @@ -341,6 +386,129 @@ func Test_compile(t *testing.T) { }), wantErr: false, }, + { + name: `MimeType:documents`, + args: &ast.Ast{ + Nodes: []ast.Node{ + &ast.StringNode{Key: "mimetype", Value: "documents"}, + }, + }, + want: query.NewDisjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`MimeType:application/msword`), + query.NewQueryStringQuery(`MimeType:application/vnd.openxmlformats-officedocument.wordprocessingml.document`), + query.NewQueryStringQuery(`MimeType:application/vnd.oasis.opendocument.text`), + query.NewQueryStringQuery(`MimeType:text/plain`), + query.NewQueryStringQuery(`MimeType:text/markdown`), + query.NewQueryStringQuery(`MimeType:application/rtf`), + query.NewQueryStringQuery(`MimeType:application/vnd.apple.pages`), + }), + wantErr: false, + }, + { + name: `MimeType:documents AND *tdd*`, + args: &ast.Ast{ + Nodes: []ast.Node{ + &ast.StringNode{Key: "mimetype", Value: "documents"}, + &ast.OperatorNode{Value: "AND"}, + &ast.StringNode{Key: "name", Value: "*tdd*"}, + }, + }, + want: query.NewConjunctionQuery([]query.Query{ + query.NewDisjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`MimeType:application/msword`), + query.NewQueryStringQuery(`MimeType:application/vnd.openxmlformats-officedocument.wordprocessingml.document`), + query.NewQueryStringQuery(`MimeType:application/vnd.oasis.opendocument.text`), + query.NewQueryStringQuery(`MimeType:text/plain`), + query.NewQueryStringQuery(`MimeType:text/markdown`), + query.NewQueryStringQuery(`MimeType:application/rtf`), + query.NewQueryStringQuery(`MimeType:application/vnd.apple.pages`), + }), + query.NewQueryStringQuery(`Name:*tdd*`), + }), + wantErr: false, + }, + { + name: `MimeType:documents OR MimeType:pdfs AND *tdd*`, + args: &ast.Ast{ + Nodes: []ast.Node{ + &ast.StringNode{Key: "mimetype", Value: "documents"}, + &ast.OperatorNode{Value: "OR"}, + &ast.StringNode{Key: "mimetype", Value: "pdfs"}, + &ast.OperatorNode{Value: "AND"}, + &ast.StringNode{Key: "name", Value: "*tdd*"}, + }, + }, + want: query.NewDisjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`MimeType:application/msword`), + query.NewQueryStringQuery(`MimeType:application/vnd.openxmlformats-officedocument.wordprocessingml.document`), + query.NewQueryStringQuery(`MimeType:application/vnd.oasis.opendocument.text`), + query.NewQueryStringQuery(`MimeType:text/plain`), + query.NewQueryStringQuery(`MimeType:text/markdown`), + query.NewQueryStringQuery(`MimeType:application/rtf`), + query.NewQueryStringQuery(`MimeType:application/vnd.apple.pages`), + query.NewConjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`MimeType:application/pdf`), + query.NewQueryStringQuery(`Name:*tdd*`), + }), + }), + wantErr: false, + }, + { + name: `(MimeType:documents OR MimeType:pdfs) AND *tdd*`, + args: &ast.Ast{ + Nodes: []ast.Node{ + &ast.GroupNode{Nodes: []ast.Node{ + &ast.StringNode{Key: "mimetype", Value: "documents"}, + &ast.OperatorNode{Value: "OR"}, + &ast.StringNode{Key: "mimetype", Value: "pdfs"}, + }}, + &ast.OperatorNode{Value: "AND"}, + &ast.StringNode{Key: "name", Value: "*tdd*"}, + }, + }, + want: query.NewConjunctionQuery([]query.Query{ + query.NewDisjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`MimeType:application/msword`), + query.NewQueryStringQuery(`MimeType:application/vnd.openxmlformats-officedocument.wordprocessingml.document`), + query.NewQueryStringQuery(`MimeType:application/vnd.oasis.opendocument.text`), + query.NewQueryStringQuery(`MimeType:text/plain`), + query.NewQueryStringQuery(`MimeType:text/markdown`), + query.NewQueryStringQuery(`MimeType:application/rtf`), + query.NewQueryStringQuery(`MimeType:application/vnd.apple.pages`), + query.NewQueryStringQuery(`MimeType:application/pdf`), + }), + query.NewQueryStringQuery(`Name:*tdd*`), + }), + wantErr: false, + }, + { + name: `(MimeType:pdfs OR MimeType:documents) AND *tdd*`, + args: &ast.Ast{ + Nodes: []ast.Node{ + &ast.GroupNode{Nodes: []ast.Node{ + &ast.StringNode{Key: "mimetype", Value: "pdfs"}, + &ast.OperatorNode{Value: "OR"}, + &ast.StringNode{Key: "mimetype", Value: "documents"}, + }}, + &ast.OperatorNode{Value: "AND"}, + &ast.StringNode{Key: "name", Value: "*tdd*"}, + }, + }, + want: query.NewConjunctionQuery([]query.Query{ + query.NewDisjunctionQuery([]query.Query{ + query.NewQueryStringQuery(`MimeType:application/pdf`), + query.NewQueryStringQuery(`MimeType:application/msword`), + query.NewQueryStringQuery(`MimeType:application/vnd.openxmlformats-officedocument.wordprocessingml.document`), + query.NewQueryStringQuery(`MimeType:application/vnd.oasis.opendocument.text`), + query.NewQueryStringQuery(`MimeType:text/plain`), + query.NewQueryStringQuery(`MimeType:text/markdown`), + query.NewQueryStringQuery(`MimeType:application/rtf`), + query.NewQueryStringQuery(`MimeType:application/vnd.apple.pages`), + }), + query.NewQueryStringQuery(`Name:*tdd*`), + }), + wantErr: false, + }, { name: `John Smith`, args: &ast.Ast{