@cu-mkp/editioncrafter 1.3.1-beta.1 → 1.3.1-beta.2
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 +11332 -11365
- 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/RouteListener.js +1 -1
- package/dist/es/src/EditionCrafter/saga/RouteListenerSaga.js +3 -4
- 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 +26 -23
- package/dist/es/src/TagExplore/components/DocumentFilters.jsx +293 -0
- package/dist/es/src/TagExplore/components/SurfaceBrowser.jsx +65 -29
- package/dist/es/src/TagExplore/components/TagFilters.jsx +66 -52
- package/dist/es/src/TagExplore/index.jsx +4 -6
- package/dist/es/src/TagExplore/styles/base.css +10 -5
- package/package.json +1 -1
|
@@ -1,29 +1,42 @@
|
|
|
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, 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'
|
|
12
10
|
import TagFilters from './TagFilters'
|
|
13
11
|
|
|
14
12
|
function getData(db) {
|
|
15
13
|
const docStmt = db.prepare(`
|
|
16
14
|
SELECT
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
d.id AS id,
|
|
16
|
+
d.name AS name,
|
|
17
|
+
d.local_id AS local_id,
|
|
18
|
+
json_group_array(document_taggings.tag) as tags
|
|
20
19
|
FROM
|
|
21
|
-
documents
|
|
20
|
+
documents d
|
|
21
|
+
LEFT JOIN document_taggings ON d.id = document_taggings.document
|
|
22
|
+
GROUP BY d.id, d.name, d.local_id
|
|
22
23
|
`)
|
|
23
|
-
|
|
24
24
|
return getObjs(docStmt)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function getDocTags(db) {
|
|
28
|
+
const tagsStmt = db.prepare(`
|
|
29
|
+
SELECT
|
|
30
|
+
tags.id AS id
|
|
31
|
+
FROM
|
|
32
|
+
tags
|
|
33
|
+
LEFT JOIN taxonomies ON tags.taxonomy_id = taxonomies.id
|
|
34
|
+
WHERE
|
|
35
|
+
taxonomies.is_surface = 0 OR taxonomies.is_surface IS NULL
|
|
36
|
+
`)
|
|
37
|
+
return getObjs(tagsStmt)
|
|
38
|
+
}
|
|
39
|
+
|
|
27
40
|
function parseFolioID(folioID) {
|
|
28
41
|
if (!folioID) {
|
|
29
42
|
return null
|
|
@@ -50,27 +63,46 @@ function getSelection(path) {
|
|
|
50
63
|
function SurfaceBrowser(props) {
|
|
51
64
|
const { db, open, toggleOpen } = props
|
|
52
65
|
const documents = useMemo(() => getData(db), [db])
|
|
66
|
+
const docTags = useMemo(() => getDocTags(db)?.map(tag => (tag.id)), [db])
|
|
53
67
|
const [pageCount, setPageCount] = useState({})
|
|
54
68
|
const [totalPages, setTotalPages] = useState(0)
|
|
55
69
|
const [tags, setTags] = useState([])
|
|
56
70
|
const [showFilters, setShowFilters] = useState(false)
|
|
71
|
+
const [query, setQuery] = useState(undefined)
|
|
72
|
+
|
|
73
|
+
const filterDocs = useCallback((docs, tags) => {
|
|
74
|
+
return docs.filter((doc) => {
|
|
75
|
+
const docID = doc.id
|
|
76
|
+
for (const tag of tags) {
|
|
77
|
+
if (docTags.includes(tag) && !JSON.parse(doc.tags)?.includes(tag)) {
|
|
78
|
+
const newCount = pageCount
|
|
79
|
+
newCount[docID] = 0
|
|
80
|
+
setPageCount(newCount)
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true
|
|
85
|
+
})
|
|
86
|
+
}, [docTags, pageCount])
|
|
87
|
+
|
|
88
|
+
const filteredDocs = useMemo(() => (filterDocs(documents, tags)), [filterDocs, documents, tags])
|
|
57
89
|
|
|
58
90
|
const navigate = useNavigate()
|
|
59
91
|
const location = useLocation()
|
|
60
92
|
const selection = useMemo(() => getSelection(location.pathname), [location])
|
|
61
93
|
|
|
62
|
-
const navigateToSelection = (nextSelection) => {
|
|
94
|
+
const navigateToSelection = useCallback((nextSelection) => {
|
|
63
95
|
const folioID = nextSelection?.left ? `${nextSelection.left.localID}_${nextSelection.left.surfaceID}` : null
|
|
64
96
|
const folioID2 = nextSelection?.right ? `${nextSelection.right.localID}_${nextSelection.right.surfaceID}` : null
|
|
65
97
|
const navParams = `/ec/${folioID || '-1'}/${folioID ? 'f' : 'g'}/${folioID2 || '-1'}/${folioID2 ? 'f' : 'g'}`
|
|
66
98
|
navigate(navParams + location.search)
|
|
67
|
-
}
|
|
99
|
+
}, [location.search, navigate])
|
|
68
100
|
|
|
69
|
-
const updatePageCount = (documentID, numPages) => {
|
|
101
|
+
const updatePageCount = useCallback((documentID, numPages) => {
|
|
70
102
|
const newCount = pageCount
|
|
71
103
|
newCount[documentID] = numPages
|
|
72
104
|
setPageCount(newCount)
|
|
73
|
-
}
|
|
105
|
+
}, [pageCount])
|
|
74
106
|
|
|
75
107
|
useEffect(() => {
|
|
76
108
|
let p = 0
|
|
@@ -80,7 +112,7 @@ function SurfaceBrowser(props) {
|
|
|
80
112
|
setTotalPages(p)
|
|
81
113
|
}, [pageCount, tags])
|
|
82
114
|
|
|
83
|
-
const documentDetails =
|
|
115
|
+
const documentDetails = useMemo(() => filteredDocs.map((doc) => {
|
|
84
116
|
return (
|
|
85
117
|
<DocumentDetail
|
|
86
118
|
key={`document-detail-${doc.id}`}
|
|
@@ -91,11 +123,11 @@ function SurfaceBrowser(props) {
|
|
|
91
123
|
selection={selection}
|
|
92
124
|
navigateToSelection={navigateToSelection}
|
|
93
125
|
updatePageCount={count => updatePageCount(doc.id, count)}
|
|
94
|
-
tags={tags}
|
|
126
|
+
tags={tags?.filter(tag => !docTags.includes(tag))}
|
|
95
127
|
>
|
|
96
128
|
</DocumentDetail>
|
|
97
129
|
)
|
|
98
|
-
})
|
|
130
|
+
}), [db, docTags, filteredDocs, navigateToSelection, selection, tags, updatePageCount])
|
|
99
131
|
|
|
100
132
|
return (
|
|
101
133
|
<Collapse in={open} horizontal>
|
|
@@ -152,18 +184,22 @@ function SurfaceBrowser(props) {
|
|
|
152
184
|
</IconButton>
|
|
153
185
|
</ButtonGroup> */}
|
|
154
186
|
{ showFilters && (
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
187
|
+
<div className="tag-filters">
|
|
188
|
+
<Input placeholder="Search for filters" value={query} onChange={(e) => { setQuery(e.target.value) }} className="tag-filters-search" />
|
|
189
|
+
<TagFilters
|
|
190
|
+
db={db}
|
|
191
|
+
filters={tags}
|
|
192
|
+
query={query}
|
|
193
|
+
onToggleSelected={(tagId) => {
|
|
194
|
+
if (tags.includes(tagId)) {
|
|
195
|
+
setTags(current => (current.filter(t => (t !== tagId))))
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
setTags(current => ([...current, tagId]))
|
|
199
|
+
}
|
|
200
|
+
}}
|
|
201
|
+
/>
|
|
202
|
+
</div>
|
|
167
203
|
) }
|
|
168
204
|
<Box className="surface-browser-document-details">
|
|
169
205
|
{ documentDetails }
|
|
@@ -22,12 +22,6 @@ function getData(db) {
|
|
|
22
22
|
tags
|
|
23
23
|
LEFT JOIN taxonomies
|
|
24
24
|
ON tags.taxonomy_id = taxonomies.id
|
|
25
|
-
INNER JOIN taggings
|
|
26
|
-
ON taggings.tag_id = tags.id
|
|
27
|
-
INNER JOIN elements
|
|
28
|
-
ON elements.id = taggings.element_id
|
|
29
|
-
WHERE
|
|
30
|
-
elements.type = 'zone'
|
|
31
25
|
GROUP BY
|
|
32
26
|
tags.xml_id`)
|
|
33
27
|
|
|
@@ -38,8 +32,9 @@ function getData(db) {
|
|
|
38
32
|
}
|
|
39
33
|
|
|
40
34
|
function TagFilters(props) {
|
|
41
|
-
const { onToggleSelected, filters } = props
|
|
35
|
+
const { onToggleSelected, filters, query } = props
|
|
42
36
|
const data = useMemo(() => getData(props.db), [props.db])
|
|
37
|
+
console.log(data.taxonomies)
|
|
43
38
|
const [expanded, setExpanded] = useState(data.taxonomies?.map(() => (false)))
|
|
44
39
|
const [displayedTags, setDisplayedTags] = useState({})
|
|
45
40
|
|
|
@@ -47,59 +42,78 @@ function TagFilters(props) {
|
|
|
47
42
|
|
|
48
43
|
useEffect(() => {
|
|
49
44
|
const tags = {}
|
|
45
|
+
const filteredTags = data.tags.filter(tag => (!query || !query.length || tag.name.toLowerCase().includes(query.toLowerCase())))
|
|
50
46
|
for (let i = 0; i < data.taxonomies.length; i++) {
|
|
51
47
|
const tax = data.taxonomies[i]
|
|
52
|
-
const tagList = expanded[i] ?
|
|
53
|
-
|
|
48
|
+
const tagList = expanded[i] ? filteredTags.filter(t => (t.taxonomy_id === tax.id)) : filteredTags.filter(t => (t.taxonomy_id === tax.id))?.slice(0, 5)
|
|
49
|
+
if (tagList?.length) {
|
|
50
|
+
tags[tax.id] = tagList
|
|
51
|
+
}
|
|
54
52
|
}
|
|
55
53
|
setDisplayedTags(tags)
|
|
56
|
-
}, [expanded, data])
|
|
54
|
+
}, [expanded, data, query])
|
|
57
55
|
|
|
58
56
|
return (
|
|
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
|
-
|
|
57
|
+
<>
|
|
58
|
+
{
|
|
59
|
+
data?.tags?.length
|
|
60
|
+
? (
|
|
61
|
+
<div className="tag-list">
|
|
62
|
+
<FormGroup>
|
|
63
|
+
{ data.taxonomies.map((tax, idx) => {
|
|
64
|
+
const tagList = displayedTags[tax.id]
|
|
65
|
+
return (
|
|
66
|
+
tagList?.length
|
|
67
|
+
? (
|
|
68
|
+
<div key={tax.id}>
|
|
69
|
+
<Typography>{`${tax.name.slice(0, 1).toUpperCase()}${tax.name.slice(1)}`}</Typography>
|
|
70
|
+
<ul>
|
|
71
|
+
{ tagList?.map(tag => (
|
|
72
|
+
<FormControlLabel
|
|
73
|
+
as="li"
|
|
74
|
+
control={(
|
|
75
|
+
<Checkbox
|
|
76
|
+
checked={filters.includes(tag.id)}
|
|
77
|
+
onChange={() => {
|
|
78
|
+
onToggleSelected(tag.id)
|
|
79
|
+
if (tax.is_surface) {
|
|
80
|
+
toggleTag(tag.xml_id, 'left')
|
|
81
|
+
toggleTag(tag.xml_id, 'right')
|
|
82
|
+
}
|
|
83
|
+
}}
|
|
84
|
+
/>
|
|
85
|
+
)}
|
|
86
|
+
key={tag.id}
|
|
87
|
+
label={tag.name}
|
|
88
|
+
/>
|
|
89
|
+
))}
|
|
90
|
+
</ul>
|
|
91
|
+
{ data.tags.filter(t => (t.taxonomy_id === tax.id))?.length && data.tags.filter(t => (t.taxonomy_id === tax.id)).length >= 6
|
|
92
|
+
? (
|
|
93
|
+
<button
|
|
94
|
+
className="tag-filter-button"
|
|
95
|
+
type="button"
|
|
96
|
+
onClick={() => {
|
|
97
|
+
const newState = [...expanded]
|
|
98
|
+
newState[idx] = !expanded[idx]
|
|
99
|
+
setExpanded(newState)
|
|
100
|
+
}}
|
|
101
|
+
>
|
|
102
|
+
{ expanded[idx] ? 'Show less' : 'Show more'}
|
|
103
|
+
</button>
|
|
104
|
+
)
|
|
105
|
+
: null }
|
|
106
|
+
</div>
|
|
107
|
+
)
|
|
108
|
+
: null
|
|
109
|
+
)
|
|
110
|
+
})}
|
|
111
|
+
</FormGroup>
|
|
97
112
|
</div>
|
|
98
113
|
)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
</div>
|
|
114
|
+
: null
|
|
115
|
+
}
|
|
116
|
+
</>
|
|
103
117
|
)
|
|
104
118
|
}
|
|
105
119
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEffect,
|
|
2
|
-
import {
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
import { HashRouter } from 'react-router-dom'
|
|
3
3
|
import initSqlJs from 'sql.js'
|
|
4
4
|
import sqlJsInfo from 'sql.js/package.json'
|
|
5
5
|
import Loading from '../common/components/Loading'
|
|
@@ -71,8 +71,6 @@ function TagExplore(props) {
|
|
|
71
71
|
const [ecProps, setECProps] = useState(null)
|
|
72
72
|
const [filters, setFilters] = useState(initialFilters)
|
|
73
73
|
|
|
74
|
-
const Router = useMemo(() => props.serverNav ? BrowserRouter : HashRouter, [props.serverNav])
|
|
75
|
-
|
|
76
74
|
useEffect(() => {
|
|
77
75
|
const loadDb = async () => {
|
|
78
76
|
const db = await initDb(props.dbUrl)
|
|
@@ -98,12 +96,12 @@ function TagExplore(props) {
|
|
|
98
96
|
|
|
99
97
|
return (
|
|
100
98
|
<div className="tag-explore">
|
|
101
|
-
<
|
|
99
|
+
<HashRouter>
|
|
102
100
|
<TagFilterProvider>
|
|
103
101
|
<TagExploreSidebar db={db} />
|
|
104
102
|
<EditionCrafter {...ecProps} />
|
|
105
103
|
</TagFilterProvider>
|
|
106
|
-
</
|
|
104
|
+
</HashRouter>
|
|
107
105
|
</div>
|
|
108
106
|
)
|
|
109
107
|
}
|
|
@@ -26,13 +26,18 @@
|
|
|
26
26
|
overflow-y: auto;
|
|
27
27
|
position: absolute;
|
|
28
28
|
top: 48px;
|
|
29
|
-
left:
|
|
29
|
+
left: 400px;
|
|
30
30
|
background-color: #242629;
|
|
31
31
|
z-index: 10000;
|
|
32
32
|
padding: 12px 0 12px 12px;
|
|
33
|
-
width:
|
|
33
|
+
width: 300px;
|
|
34
34
|
height: 100%;
|
|
35
|
-
max-height:
|
|
35
|
+
max-height: calc(97dvh - 48px);
|
|
36
|
+
border-left: solid white 1px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.tag-explore .tag-filters .tag-filters-search {
|
|
40
|
+
margin-bottom: 24px;
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
.tag-explore .tag-filter-button {
|
|
@@ -153,8 +158,8 @@
|
|
|
153
158
|
position: absolute;
|
|
154
159
|
top: 0;
|
|
155
160
|
left: 48px;
|
|
156
|
-
height:
|
|
157
|
-
|
|
161
|
+
height: 97dvh;
|
|
162
|
+
width: 400px;
|
|
158
163
|
display: flex;
|
|
159
164
|
flex-direction: column;
|
|
160
165
|
background-color: #242629;
|