1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
---
title: "Viewer: index v2.1"
author: pacien
date: 2022-10-22 (v2)
---
# Abstract
This is a short documentation of the viewer's internal index dating from the
first version of this software and still currently in use in version 2.1.
This index was written without proper specifications or documentation, and has
evolved a lot since then.
This document is an attempt at describing how this index is currently being
generated and used, before further work can be done on some proper
specification to clarify the problematic behaviours.
# Document version history
1. 2022-10-15: call notes
2. 2022-10-22: rewritten
# Description of the current implementation
## Generating the index(es) from the item tree
The gallery item index (`index.json`) is loaded by the `galleryStore` and made
available as the `galleryIndex` attribute.
Two indexes are derived from that file through the `indexFactory` service:
- `tagsIndex`:
- Maps each tag "part" (component) to items tagged with it.
- Maps the left-most disambiguating component to all components on its right.
- Includes a normalised version of the tag for searching.
- (Stores the left-most `rootPart` component. This is not used anywhere).
- `tagsCategories`:
- Same as `tagsIndex`, but partitioned by tag category prefixes as defined in
the viewer configuration.
## Search query input auto-completion "suggestions"
The `TagInput` component suggests tags as the user types in that input field.
This is provided by the `indexFactory.searchTags` function in fuzzy
(non-strict) mode, which only uses the global tag index.
The fuzzy search is implemented as a normalised (lowercase) infix word lookup,
including the disambiguating tag parts.
The auto-completion suggestions are independent of the current directory.
Suggestions yielding no result (incompatible with the current search query) are
not excluded either.
## Item search
The search query is stored in the URL query. This allows a search to be shared
by copying the current URL.
This URL search query is updated by `LayoutLeft.vue` to match modifications
made through the tag input or related filters "propositions". This component
also updates the store to match the URL query through `galleryStore.search`.
A search query consists of three sets of tags: an intersection list, a forced
inclusion (union) list, and a forced exclusion list. The last two are denoted
with a `+` and `-` modifier prefix before the tag name. The order of the terms
does not matter.
The result computed in `indexSearch.indexSearch` is given by
`(⋂(intersection) ∪ ⋃(forced inclusion)) ∖ ⋃(forced exclusion)`.
The string representation of a query is parsed in `indexFactory`. It is
serialised by taking the `filter.display` property of filters, in
`LayouLeft.vue` for being displayed in the tag input and in the URL.
## Related filters "propositions"
The left pane of the user interface lists related filters "propositions",
related to the current search results or directory being viewed.
Tags in that pane are grouped according to the `tagCategories` gallery
configuration key. (This is currently buggy: some tags can appear in the wrong
category under some circumstances).
The related tags are filtered with respect to the current search query or
directory: only tags that are present on the listed items are shown.
Each "proposed" tag has an occurrence count of the items having that tag in the
whole gallery. (This is inconsistent with the locality of the filter).
This is computed using a full gallery search through the `galleryStore` using
`indexFactory.searchTags` in strict (non-fuzzy) mode.
# Identified issues and proposals
## Issues affecting the end users
- Tags categories and disambiguation aren't properly defined:
- It is not clear whether intermediate tag components should be treated as
tags and suggested at all. (They currently are).
- Tags with more than two components do not seem to be handled correctly:
- `a:b:c`: `c` is not registered as a child of `a` in `tagsIndex`.
- This seems to be the cause of tags being displayed in the wrong category in
the suggestion pane.
- The tag input's auto-completion suggests impossible intersections:
- The fuzzy (non-strict) search does not work the same way as the suggestions
panel, which restricts the suggestions.
- This might however be problematic for forced inclusions (union) tags
which are still meaningful.
- The tag occurrence counts in the related tags "propositions" pane is
misleading:
- This view suggests only the tags for the current search results
(descendants of the current directory and matching the current search query
if any),
- But the occurrence count for each tag is global (on the whole gallery
instead of the current search results).
## Issues affecting only the developers
- Ambiguous terminology:
- For example "index" vs "index.json", or "tag suggestions" vs
"tag propositions" vs "tag completion".
- This confusion is reflected in the component naming and coupling…
- A glossary and would help.
- Refactoring and renaming the modules would help.
- Tight coupling of the tag-related and index operations:
- It goes all over the place.
- Some concerns should and can clearly be separated for example:
- For example query parsing, compiling and actual run on the item tree.
- The new modules should make use of composition with the rest of the
components.
- Lack of unit tests:
- Coupling is preventing easy unit testing.
- Once the concerns are separated:
- We'll have clear expected outputs with respect to some input.
- It should be easier to do unit testing:
- (perhaps through randomised property testing).
- Minor: relatively verbose and intertwined imperative code:
- The query parsing and recursive tree operations would probably be more
elegant in PureScript than Javascript/Typescript.
- Same with unit and property tests.
|