@cu-mkp/editioncrafter 1.3.1-beta.1 → 1.3.1-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editioncrafter.js +12592 -12484
- package/dist/es/src/EditionCrafter/action/DocumentActions.js +1 -0
- package/dist/es/src/EditionCrafter/action/rootReducer.js +9 -4
- package/dist/es/src/EditionCrafter/component/DiploMatic.js +17 -31
- package/dist/es/src/EditionCrafter/component/DocumentView.js +6 -48
- package/dist/es/src/EditionCrafter/component/ImageMetadata.js +13 -0
- package/dist/es/src/EditionCrafter/component/ImageView.js +6 -0
- package/dist/es/src/EditionCrafter/component/RouteListener.js +1 -1
- package/dist/es/src/EditionCrafter/context/TagFilter.jsx +6 -0
- package/dist/es/src/EditionCrafter/context/TagFilterContext.js +1 -0
- package/dist/es/src/EditionCrafter/saga/RouteListenerSaga.js +3 -4
- package/dist/es/src/EditionCrafter/scss/_imageMetadata.scss +16 -0
- package/dist/es/src/EditionCrafter/scss/editioncrafter.scss +1 -0
- package/dist/es/src/TagExplore/assets/InsertLeft.jsx +6 -3
- package/dist/es/src/TagExplore/assets/InsertRight.jsx +5 -3
- package/dist/es/src/TagExplore/components/DocumentDetail.jsx +40 -33
- package/dist/es/src/TagExplore/components/DocumentFilters.jsx +293 -0
- package/dist/es/src/TagExplore/components/SurfaceBrowser.jsx +108 -52
- package/dist/es/src/TagExplore/components/TagFilters.jsx +212 -56
- package/dist/es/src/TagExplore/index.jsx +6 -8
- package/dist/es/src/TagExplore/styles/base.css +12 -5
- package/package.json +1 -1
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { Checkbox, FormControlLabel, FormGroup, Typography } from '@material-ui/core'
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
3
|
+
import { getObjs } from '../../common/lib/sql'
|
|
4
|
+
|
|
5
|
+
function getData(db) {
|
|
6
|
+
const rolesStmt = db.prepare(`
|
|
7
|
+
SELECT * FROM roles
|
|
8
|
+
`)
|
|
9
|
+
const agentStmt = db.prepare(`
|
|
10
|
+
SELECT
|
|
11
|
+
people.name as name,
|
|
12
|
+
roles.name as role,
|
|
13
|
+
people.id as person_id,
|
|
14
|
+
roles.id as role_id
|
|
15
|
+
FROM
|
|
16
|
+
agents
|
|
17
|
+
LEFT JOIN people
|
|
18
|
+
ON people.id = agents.person
|
|
19
|
+
LEFT JOIN roles
|
|
20
|
+
ON roles.id = agents.role
|
|
21
|
+
GROUP BY
|
|
22
|
+
roles.name, people.name, people.id, roles.id
|
|
23
|
+
`)
|
|
24
|
+
|
|
25
|
+
const keywordsStmt = db.prepare(`
|
|
26
|
+
SELECT * FROM keywords
|
|
27
|
+
`)
|
|
28
|
+
|
|
29
|
+
const typesStmt = db.prepare(`
|
|
30
|
+
SELECT type FROM keywords GROUP BY type
|
|
31
|
+
`)
|
|
32
|
+
|
|
33
|
+
const langStmt = db.prepare(`SELECT * FROM languages`)
|
|
34
|
+
const locStmt = db.prepare(`SELECT * FROM locations`)
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
agents: getObjs(agentStmt),
|
|
38
|
+
roles: getObjs(rolesStmt),
|
|
39
|
+
types: getObjs(typesStmt),
|
|
40
|
+
keywords: getObjs(keywordsStmt),
|
|
41
|
+
languages: getObjs(langStmt),
|
|
42
|
+
locations: getObjs(locStmt),
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function DocumentFilters(props) {
|
|
47
|
+
const { filters, query } = props
|
|
48
|
+
const fullData = useMemo(() => getData(props.db), [props.db])
|
|
49
|
+
const [expanded, setExpanded] = useState(fullData.roles?.map(() => (false)))
|
|
50
|
+
const [keywordExpanded, setKeywordExpanded] = useState(fullData.types?.map(() => (false)))
|
|
51
|
+
const [langExpanded, setLangExpanded] = useState(false)
|
|
52
|
+
const [locExpanded, setLocExpanded] = useState(false)
|
|
53
|
+
const [displayedTags, setDisplayedTags] = useState({})
|
|
54
|
+
|
|
55
|
+
const data = useMemo(() => {
|
|
56
|
+
const agents = fullData.agents?.filter(ag => (!query || !query.length || ag.name?.toLowerCase().includes(query.toLowerCase())))
|
|
57
|
+
const keywords = fullData.keywords?.filter(term => (!query || !query.length || term.name?.toLowerCase().includes(query.toLowerCase())))
|
|
58
|
+
const languages = fullData.languages?.filter(lang => (!query || !query.length || lang.name.toLowerCase().includes(query.toLowerCase())))
|
|
59
|
+
const locations = fullData.locations?.filter(loc => (!query || !query.length || loc.name.toLowerCase().includes(query.toLowerCase())))
|
|
60
|
+
return ({
|
|
61
|
+
agents,
|
|
62
|
+
keywords,
|
|
63
|
+
languages,
|
|
64
|
+
locations,
|
|
65
|
+
types: fullData.types,
|
|
66
|
+
roles: fullData.roles,
|
|
67
|
+
})
|
|
68
|
+
}, [fullData, query])
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
const tags = {}
|
|
72
|
+
for (let i = 0; i < data.roles.length; i++) {
|
|
73
|
+
const tax = data.roles[i]
|
|
74
|
+
const tagList = expanded[i] ? data.agents.filter(t => (t.role_id === tax.id)) : data.agents.filter(t => (t.role_id === tax.id))?.slice(0, 5)
|
|
75
|
+
tags[tax.id] = tagList
|
|
76
|
+
}
|
|
77
|
+
setDisplayedTags(tags)
|
|
78
|
+
}, [expanded, data])
|
|
79
|
+
|
|
80
|
+
const onToggleAgent = useCallback((role, person) => {
|
|
81
|
+
const current = [...filters.agents.data]
|
|
82
|
+
if (current.find(f => (f.role === role && f.person === person))) {
|
|
83
|
+
filters.agents.onUpdate(current => (current.filter(item => (item.role !== role || item.person !== person))))
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
filters.agents.onUpdate(current => [...current, { role, person }])
|
|
87
|
+
}
|
|
88
|
+
}, [filters])
|
|
89
|
+
|
|
90
|
+
const onToggleKeyword = useCallback((type, term) => {
|
|
91
|
+
const current = [...filters.keywords.data]
|
|
92
|
+
if (current.find(f => (f.type === type && f.term === term))) {
|
|
93
|
+
filters.keywords.onUpdate(current => (current.filter(item => (item.type !== type || item.term !== term))))
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
filters.keywords.onUpdate(current => [...current, { type, term }])
|
|
97
|
+
}
|
|
98
|
+
}, [filters])
|
|
99
|
+
|
|
100
|
+
const onToggleLanguage = useCallback((item_id) => {
|
|
101
|
+
const current = [...filters.langs.data]
|
|
102
|
+
if (current.includes(item_id)) {
|
|
103
|
+
filters.langs.onUpdate(current => (current.filter(i => (i !== item_id))))
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
filters.langs.onUpdate(current => [...current, item_id])
|
|
107
|
+
}
|
|
108
|
+
}, [filters])
|
|
109
|
+
|
|
110
|
+
const onToggleLocation = useCallback((item_id) => {
|
|
111
|
+
const current = [...filters.locations.data]
|
|
112
|
+
if (current.includes(item_id)) {
|
|
113
|
+
filters.locations.onUpdate(current => (current.filter(i => (i !== item_id))))
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
filters.locations.onUpdate(current => [...current, item_id])
|
|
117
|
+
}
|
|
118
|
+
}, [filters])
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<div className="tag-list">
|
|
122
|
+
<FormGroup>
|
|
123
|
+
{ data.roles.map((tax, idx) => {
|
|
124
|
+
const tagList = displayedTags[tax.id]
|
|
125
|
+
return tagList?.length
|
|
126
|
+
? (
|
|
127
|
+
<div key={tax.id}>
|
|
128
|
+
<Typography>{tax.name}</Typography>
|
|
129
|
+
<ul>
|
|
130
|
+
{ tagList?.map(tag => (
|
|
131
|
+
<FormControlLabel
|
|
132
|
+
as="li"
|
|
133
|
+
control={(
|
|
134
|
+
<Checkbox
|
|
135
|
+
checked={!!filters.agents.data.find(ag => (ag.role === tax.id && ag.person === tag.person_id))}
|
|
136
|
+
onChange={() => {
|
|
137
|
+
onToggleAgent(tax.id, tag.person_id)
|
|
138
|
+
}}
|
|
139
|
+
/>
|
|
140
|
+
)}
|
|
141
|
+
key={tag.person_id}
|
|
142
|
+
label={tag.name}
|
|
143
|
+
/>
|
|
144
|
+
))}
|
|
145
|
+
</ul>
|
|
146
|
+
{ (data.agents.filter(t => (t.role_id === tax.id))?.length && data.agents.filter(t => (t.role_id === tax.id)).length >= 6)
|
|
147
|
+
? (
|
|
148
|
+
<button
|
|
149
|
+
className="tag-filter-button"
|
|
150
|
+
type="button"
|
|
151
|
+
onClick={() => {
|
|
152
|
+
const newState = [...expanded]
|
|
153
|
+
newState[idx] = !expanded[idx]
|
|
154
|
+
setExpanded(newState)
|
|
155
|
+
}}
|
|
156
|
+
>
|
|
157
|
+
{ expanded[idx] ? 'Show less' : 'Show more'}
|
|
158
|
+
</button>
|
|
159
|
+
)
|
|
160
|
+
: null }
|
|
161
|
+
</div>
|
|
162
|
+
)
|
|
163
|
+
: null
|
|
164
|
+
})}
|
|
165
|
+
{ data.types.map((tax, idx) => {
|
|
166
|
+
const tagList = data.keywords.filter(term => (term.type === tax.type))
|
|
167
|
+
return tagList?.length
|
|
168
|
+
? (
|
|
169
|
+
<div key={tax.type}>
|
|
170
|
+
<Typography>
|
|
171
|
+
{tax.type[0].toUpperCase()}
|
|
172
|
+
{tax.type.slice(1)}
|
|
173
|
+
</Typography>
|
|
174
|
+
<ul>
|
|
175
|
+
{ tagList?.map(tag => (
|
|
176
|
+
<FormControlLabel
|
|
177
|
+
as="li"
|
|
178
|
+
control={(
|
|
179
|
+
<Checkbox
|
|
180
|
+
checked={!!filters.keywords.data.find(item => (item.type === tax.type && item.term === tag.id))}
|
|
181
|
+
onChange={() => {
|
|
182
|
+
onToggleKeyword(tax.type, tag.id)
|
|
183
|
+
}}
|
|
184
|
+
/>
|
|
185
|
+
)}
|
|
186
|
+
key={tag.id}
|
|
187
|
+
label={tag.name}
|
|
188
|
+
/>
|
|
189
|
+
))}
|
|
190
|
+
</ul>
|
|
191
|
+
{ tagList.length >= 6
|
|
192
|
+
? (
|
|
193
|
+
<button
|
|
194
|
+
className="tag-filter-button"
|
|
195
|
+
type="button"
|
|
196
|
+
onClick={() => {
|
|
197
|
+
const newState = [...keywordExpanded]
|
|
198
|
+
newState[idx] = !keywordExpanded[idx]
|
|
199
|
+
setKeywordExpanded(newState)
|
|
200
|
+
}}
|
|
201
|
+
>
|
|
202
|
+
{ keywordExpanded[idx] ? 'Show less' : 'Show more'}
|
|
203
|
+
</button>
|
|
204
|
+
)
|
|
205
|
+
: null}
|
|
206
|
+
</div>
|
|
207
|
+
)
|
|
208
|
+
: null
|
|
209
|
+
})}
|
|
210
|
+
{ data.languages?.length
|
|
211
|
+
? (
|
|
212
|
+
<div>
|
|
213
|
+
<Typography>
|
|
214
|
+
Language
|
|
215
|
+
</Typography>
|
|
216
|
+
<ul>
|
|
217
|
+
{ data.languages.map(tag => (
|
|
218
|
+
<FormControlLabel
|
|
219
|
+
as="li"
|
|
220
|
+
control={(
|
|
221
|
+
<Checkbox
|
|
222
|
+
checked={filters.langs.data.includes(tag.id)}
|
|
223
|
+
onChange={() => {
|
|
224
|
+
onToggleLanguage(tag.id)
|
|
225
|
+
}}
|
|
226
|
+
/>
|
|
227
|
+
)}
|
|
228
|
+
key={tag.id}
|
|
229
|
+
label={tag.name}
|
|
230
|
+
/>
|
|
231
|
+
))}
|
|
232
|
+
</ul>
|
|
233
|
+
{ data.languages.length >= 6
|
|
234
|
+
? (
|
|
235
|
+
<button
|
|
236
|
+
className="tag-filter-button"
|
|
237
|
+
type="button"
|
|
238
|
+
onClick={() => {
|
|
239
|
+
setLangExpanded(current => !current)
|
|
240
|
+
}}
|
|
241
|
+
>
|
|
242
|
+
{ langExpanded ? 'Show less' : 'Show more'}
|
|
243
|
+
</button>
|
|
244
|
+
)
|
|
245
|
+
: null}
|
|
246
|
+
</div>
|
|
247
|
+
)
|
|
248
|
+
: null }
|
|
249
|
+
{ data.locations?.length
|
|
250
|
+
? (
|
|
251
|
+
<div>
|
|
252
|
+
<Typography>
|
|
253
|
+
Location of Publication
|
|
254
|
+
</Typography>
|
|
255
|
+
<ul>
|
|
256
|
+
{ data.locations.map(tag => (
|
|
257
|
+
<FormControlLabel
|
|
258
|
+
as="li"
|
|
259
|
+
control={(
|
|
260
|
+
<Checkbox
|
|
261
|
+
checked={filters.locations.data.includes(tag.id)}
|
|
262
|
+
onChange={() => {
|
|
263
|
+
onToggleLocation(tag.id)
|
|
264
|
+
}}
|
|
265
|
+
/>
|
|
266
|
+
)}
|
|
267
|
+
key={tag.id}
|
|
268
|
+
label={tag.name}
|
|
269
|
+
/>
|
|
270
|
+
))}
|
|
271
|
+
</ul>
|
|
272
|
+
{ data.locations.length >= 6
|
|
273
|
+
? (
|
|
274
|
+
<button
|
|
275
|
+
className="tag-filter-button"
|
|
276
|
+
type="button"
|
|
277
|
+
onClick={() => {
|
|
278
|
+
setLocExpanded(current => !current)
|
|
279
|
+
}}
|
|
280
|
+
>
|
|
281
|
+
{ locExpanded ? 'Show less' : 'Show more'}
|
|
282
|
+
</button>
|
|
283
|
+
)
|
|
284
|
+
: null}
|
|
285
|
+
</div>
|
|
286
|
+
)
|
|
287
|
+
: null }
|
|
288
|
+
</FormGroup>
|
|
289
|
+
</div>
|
|
290
|
+
)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export default DocumentFilters
|
|
@@ -1,29 +1,43 @@
|
|
|
1
|
-
import { Box, Button,
|
|
2
|
-
import { red } from '@material-ui/core/colors'
|
|
1
|
+
import { Box, Button, Collapse, Divider, IconButton, Input, Typography } from '@material-ui/core'
|
|
3
2
|
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'
|
|
4
|
-
import GridOnIcon from '@material-ui/icons/GridOn'
|
|
5
|
-
import ListIcon from '@material-ui/icons/List'
|
|
6
3
|
import TuneIcon from '@material-ui/icons/Tune'
|
|
7
|
-
import { useEffect, useMemo, useState } from 'react'
|
|
4
|
+
import { useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
|
8
5
|
|
|
9
6
|
import { useLocation, useNavigate } from 'react-router-dom'
|
|
10
7
|
import { getObjs } from '../../common/lib/sql'
|
|
11
8
|
import DocumentDetail from './DocumentDetail'
|
|
9
|
+
// import DocumentFilters from './DocumentFilters'
|
|
10
|
+
import TagFilterContext from '../../EditionCrafter/context/TagFilterContext'
|
|
12
11
|
import TagFilters from './TagFilters'
|
|
13
12
|
|
|
14
13
|
function getData(db) {
|
|
15
14
|
const docStmt = db.prepare(`
|
|
16
15
|
SELECT
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
d.id AS id,
|
|
17
|
+
d.name AS name,
|
|
18
|
+
d.local_id AS local_id,
|
|
19
|
+
json_group_array(document_taggings.tag) as tags
|
|
20
20
|
FROM
|
|
21
|
-
documents
|
|
21
|
+
documents d
|
|
22
|
+
LEFT JOIN document_taggings ON d.id = document_taggings.document
|
|
23
|
+
GROUP BY d.id, d.name, d.local_id
|
|
22
24
|
`)
|
|
23
|
-
|
|
24
25
|
return getObjs(docStmt)
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
function getDocTags(db) {
|
|
29
|
+
const tagsStmt = db.prepare(`
|
|
30
|
+
SELECT
|
|
31
|
+
tags.id AS id
|
|
32
|
+
FROM
|
|
33
|
+
tags
|
|
34
|
+
LEFT JOIN taxonomies ON tags.taxonomy_id = taxonomies.id
|
|
35
|
+
WHERE
|
|
36
|
+
taxonomies.is_surface = 0 OR taxonomies.is_surface IS NULL
|
|
37
|
+
`)
|
|
38
|
+
return getObjs(tagsStmt)
|
|
39
|
+
}
|
|
40
|
+
|
|
27
41
|
function parseFolioID(folioID) {
|
|
28
42
|
if (!folioID) {
|
|
29
43
|
return null
|
|
@@ -50,27 +64,48 @@ function getSelection(path) {
|
|
|
50
64
|
function SurfaceBrowser(props) {
|
|
51
65
|
const { db, open, toggleOpen } = props
|
|
52
66
|
const documents = useMemo(() => getData(db), [db])
|
|
67
|
+
const docTags = useMemo(() => getDocTags(db)?.map(tag => (tag.id)), [db])
|
|
53
68
|
const [pageCount, setPageCount] = useState({})
|
|
54
69
|
const [totalPages, setTotalPages] = useState(0)
|
|
55
70
|
const [tags, setTags] = useState([])
|
|
56
71
|
const [showFilters, setShowFilters] = useState(false)
|
|
72
|
+
const [query, setQuery] = useState(undefined)
|
|
73
|
+
|
|
74
|
+
const filterDocs = useCallback((docs, tags) => {
|
|
75
|
+
return docs.filter((doc) => {
|
|
76
|
+
const docID = doc.id
|
|
77
|
+
for (const tag of tags) {
|
|
78
|
+
if (docTags.includes(tag) && !JSON.parse(doc.tags)?.includes(tag)) {
|
|
79
|
+
const newCount = pageCount
|
|
80
|
+
newCount[docID] = 0
|
|
81
|
+
setPageCount(newCount)
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return true
|
|
86
|
+
})
|
|
87
|
+
}, [docTags, pageCount])
|
|
88
|
+
|
|
89
|
+
const filteredDocs = useMemo(() => (filterDocs(documents, tags)), [filterDocs, documents, tags])
|
|
90
|
+
|
|
91
|
+
const { clearTags } = useContext(TagFilterContext)
|
|
57
92
|
|
|
58
93
|
const navigate = useNavigate()
|
|
59
94
|
const location = useLocation()
|
|
60
95
|
const selection = useMemo(() => getSelection(location.pathname), [location])
|
|
61
96
|
|
|
62
|
-
const navigateToSelection = (nextSelection) => {
|
|
97
|
+
const navigateToSelection = useCallback((nextSelection) => {
|
|
63
98
|
const folioID = nextSelection?.left ? `${nextSelection.left.localID}_${nextSelection.left.surfaceID}` : null
|
|
64
99
|
const folioID2 = nextSelection?.right ? `${nextSelection.right.localID}_${nextSelection.right.surfaceID}` : null
|
|
65
100
|
const navParams = `/ec/${folioID || '-1'}/${folioID ? 'f' : 'g'}/${folioID2 || '-1'}/${folioID2 ? 'f' : 'g'}`
|
|
66
101
|
navigate(navParams + location.search)
|
|
67
|
-
}
|
|
102
|
+
}, [location.search, navigate])
|
|
68
103
|
|
|
69
|
-
const updatePageCount = (documentID, numPages) => {
|
|
104
|
+
const updatePageCount = useCallback((documentID, numPages) => {
|
|
70
105
|
const newCount = pageCount
|
|
71
106
|
newCount[documentID] = numPages
|
|
72
107
|
setPageCount(newCount)
|
|
73
|
-
}
|
|
108
|
+
}, [pageCount])
|
|
74
109
|
|
|
75
110
|
useEffect(() => {
|
|
76
111
|
let p = 0
|
|
@@ -80,7 +115,7 @@ function SurfaceBrowser(props) {
|
|
|
80
115
|
setTotalPages(p)
|
|
81
116
|
}, [pageCount, tags])
|
|
82
117
|
|
|
83
|
-
const documentDetails =
|
|
118
|
+
const documentDetails = useMemo(() => filteredDocs.map((doc) => {
|
|
84
119
|
return (
|
|
85
120
|
<DocumentDetail
|
|
86
121
|
key={`document-detail-${doc.id}`}
|
|
@@ -91,11 +126,11 @@ function SurfaceBrowser(props) {
|
|
|
91
126
|
selection={selection}
|
|
92
127
|
navigateToSelection={navigateToSelection}
|
|
93
128
|
updatePageCount={count => updatePageCount(doc.id, count)}
|
|
94
|
-
tags={tags}
|
|
129
|
+
tags={tags?.filter(tag => !docTags.includes(tag))}
|
|
95
130
|
>
|
|
96
131
|
</DocumentDetail>
|
|
97
132
|
)
|
|
98
|
-
})
|
|
133
|
+
}), [db, docTags, filteredDocs, navigateToSelection, selection, tags, updatePageCount])
|
|
99
134
|
|
|
100
135
|
return (
|
|
101
136
|
<Collapse in={open} horizontal>
|
|
@@ -108,34 +143,51 @@ function SurfaceBrowser(props) {
|
|
|
108
143
|
<Divider></Divider>
|
|
109
144
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
110
145
|
<Typography>Contents</Typography>
|
|
111
|
-
<
|
|
112
|
-
startIcon={<TuneIcon />}
|
|
113
|
-
onClick={() => setShowFilters(current => (!current))}
|
|
114
|
-
>
|
|
115
|
-
Filter
|
|
146
|
+
<div>
|
|
116
147
|
{ tags && tags.length
|
|
117
148
|
? (
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
color: 'white',
|
|
127
|
-
height: '16px',
|
|
128
|
-
width: '16px',
|
|
129
|
-
position: 'absolute',
|
|
130
|
-
top: '0',
|
|
131
|
-
left: '-12px',
|
|
132
|
-
}}
|
|
149
|
+
<Button
|
|
150
|
+
onClick={() => {
|
|
151
|
+
setTags([])
|
|
152
|
+
clearTags()
|
|
153
|
+
}}
|
|
154
|
+
style={{
|
|
155
|
+
marginRight: '24px',
|
|
156
|
+
}}
|
|
133
157
|
>
|
|
134
|
-
|
|
135
|
-
</
|
|
158
|
+
Clear All
|
|
159
|
+
</Button>
|
|
136
160
|
)
|
|
137
161
|
: null}
|
|
138
|
-
|
|
162
|
+
<Button
|
|
163
|
+
startIcon={<TuneIcon />}
|
|
164
|
+
onClick={() => setShowFilters(current => (!current))}
|
|
165
|
+
>
|
|
166
|
+
Filter
|
|
167
|
+
{ tags && tags.length
|
|
168
|
+
? (
|
|
169
|
+
<div style={{
|
|
170
|
+
fontSize: 'small',
|
|
171
|
+
backgroundColor: 'red',
|
|
172
|
+
borderRadius: '999px',
|
|
173
|
+
display: 'flex',
|
|
174
|
+
justifyContent: 'center',
|
|
175
|
+
alignItems: 'center',
|
|
176
|
+
padding: '3px',
|
|
177
|
+
color: 'white',
|
|
178
|
+
height: '16px',
|
|
179
|
+
width: '16px',
|
|
180
|
+
position: 'absolute',
|
|
181
|
+
top: '0',
|
|
182
|
+
left: '-12px',
|
|
183
|
+
}}
|
|
184
|
+
>
|
|
185
|
+
{tags.length}
|
|
186
|
+
</div>
|
|
187
|
+
)
|
|
188
|
+
: null}
|
|
189
|
+
</Button>
|
|
190
|
+
</div>
|
|
139
191
|
</div>
|
|
140
192
|
<Typography>
|
|
141
193
|
{totalPages}
|
|
@@ -152,18 +204,22 @@ function SurfaceBrowser(props) {
|
|
|
152
204
|
</IconButton>
|
|
153
205
|
</ButtonGroup> */}
|
|
154
206
|
{ showFilters && (
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
207
|
+
<div className="tag-filters">
|
|
208
|
+
<Input placeholder="Search for filters" value={query} onChange={(e) => { setQuery(e.target.value) }} className="tag-filters-search" />
|
|
209
|
+
<TagFilters
|
|
210
|
+
db={db}
|
|
211
|
+
filters={tags}
|
|
212
|
+
query={query}
|
|
213
|
+
onToggleSelected={(tagId) => {
|
|
214
|
+
if (tags.includes(tagId)) {
|
|
215
|
+
setTags(current => (current.filter(t => (t !== tagId))))
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
setTags(current => ([...current, tagId]))
|
|
219
|
+
}
|
|
220
|
+
}}
|
|
221
|
+
/>
|
|
222
|
+
</div>
|
|
167
223
|
) }
|
|
168
224
|
<Box className="surface-browser-document-details">
|
|
169
225
|
{ documentDetails }
|