@cu-mkp/editioncrafter 1.3.1-beta.7 → 1.3.1-beta.8

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.
@@ -4,12 +4,11 @@ import { createReducer } from '../model/ReduxStore'
4
4
  import DiplomaticActions from './DiplomaticActions'
5
5
  import DocumentActions from './DocumentActions'
6
6
  import GlossaryActions from './GlossaryActions'
7
- import NotesActions from './NotesActions'
8
-
9
7
  import diplomaticInitialState from './initialState/diplomaticInitialState'
10
8
  import documentInitialState from './initialState/documentInitialState'
11
9
  import glossaryInitialState from './initialState/glossaryInitialState'
12
10
  import notesInitialState from './initialState/notesInitialState'
11
+ import NotesActions from './NotesActions'
13
12
 
14
13
  export default function rootReducer(config) {
15
14
  const {
@@ -30,8 +29,14 @@ export default function rootReducer(config) {
30
29
  derivativesInfo[key] = config.documentInfo[key].documentName
31
30
  })
32
31
  }
33
- const transcriptionTypes = variorum ? transcriptionTypesInfo : config.transcriptionTypes
34
- const iiifManifest = variorum ? manifestInfo : config.iiifManifest
32
+
33
+ // handle the case that there's exactly one document in documentInfo
34
+ let docConfig = config
35
+ if (documentInfo && Object.keys(documentInfo).length === 1) {
36
+ docConfig = Object.values(documentInfo)[0]
37
+ }
38
+ const transcriptionTypes = variorum ? transcriptionTypesInfo : docConfig.transcriptionTypes
39
+ const iiifManifest = variorum ? manifestInfo : docConfig.iiifManifest
35
40
  const derivativeNames = variorum && derivativesInfo
36
41
  return combineReducers({
37
42
  diplomatic: createReducer('DiplomaticActions', DiplomaticActions, diplomaticInitialState),
@@ -1,5 +1,6 @@
1
- import { Checkbox, FormControlLabel, FormGroup, Typography } from '@material-ui/core'
2
- import { useContext, useEffect, useMemo, useState } from 'react'
1
+ import { Accordion, AccordionDetails, AccordionSummary, Checkbox, FormControlLabel, FormGroup, Typography } from '@material-ui/core'
2
+ import ExpandMoreIcon from '@material-ui/icons/ExpandMore'
3
+ import { useCallback, useContext, useEffect, useMemo, useState } from 'react'
3
4
  import { getObjs } from '../../common/lib/sql'
4
5
  import TagFilterContext from '../../EditionCrafter/context/TagFilterContext'
5
6
 
@@ -9,6 +10,17 @@ function getData(db) {
9
10
  *
10
11
  FROM
11
12
  taxonomies;
13
+ ORDER BY
14
+ name ASC;
15
+ `)
16
+
17
+ const categoriesStmt = db.prepare(`
18
+ SELECT
19
+ *
20
+ FROM
21
+ categories
22
+ ORDER BY
23
+ name ASC;
12
24
  `)
13
25
 
14
26
  const tagsStmt = db.prepare(`
@@ -16,6 +28,7 @@ function getData(db) {
16
28
  tags.id AS id,
17
29
  tags.name AS name,
18
30
  tags.xml_id AS xml_id,
31
+ tags.parent_category_id AS parent_category_id,
19
32
  taxonomies.name as taxonomy,
20
33
  taxonomies.id as taxonomy_id
21
34
  FROM
@@ -23,18 +36,119 @@ function getData(db) {
23
36
  LEFT JOIN taxonomies
24
37
  ON tags.taxonomy_id = taxonomies.id
25
38
  GROUP BY
26
- tags.xml_id`)
39
+ tags.xml_id
40
+ ORDER BY
41
+ tags.name ASC`)
27
42
 
28
43
  return {
29
44
  tags: getObjs(tagsStmt),
45
+ categories: getObjs(categoriesStmt),
30
46
  taxonomies: getObjs(taxonomiesStmt),
31
47
  }
32
48
  }
33
49
 
50
+ function CategoryFilter(props) {
51
+ const {
52
+ name,
53
+ categoryId,
54
+ tags,
55
+ categories,
56
+ toggleTag,
57
+ onToggleSelected,
58
+ isSurface,
59
+ filters,
60
+ } = props
61
+
62
+ const hasDescendentTags = useCallback((catId) => {
63
+ if (tags?.filter(tag => (tag.parent_category_id === catId))?.length) {
64
+ return true
65
+ }
66
+
67
+ const subs = categories?.filter(cat => (cat.parent_category_id === catId))
68
+
69
+ for (const sub of subs) {
70
+ if (hasDescendentTags(sub.id)) {
71
+ return true
72
+ }
73
+ }
74
+
75
+ return false
76
+ }, [tags, categories])
77
+
78
+ const categoryTags = useMemo(() => {
79
+ return tags?.filter(tag => (tag.parent_category_id === categoryId))
80
+ }, [tags, categoryId])
81
+
82
+ const subcategories = useMemo(() => {
83
+ return categories?.filter(cat => (cat.parent_category_id === categoryId))
84
+ }, [categories, categoryId])
85
+
86
+ return hasDescendentTags(categoryId) && (
87
+ <Accordion>
88
+ <AccordionSummary
89
+ expandIcon={<ExpandMoreIcon />}
90
+ aria-controls={`category-tags-${name}-content`}
91
+ id={`category-tags-${name}`}
92
+ className="accordion-summary"
93
+ >
94
+ <Typography>{name}</Typography>
95
+ <Typography>{categoryTags?.length || ''}</Typography>
96
+ </AccordionSummary>
97
+ <AccordionDetails
98
+ className="accordion-detail"
99
+ >
100
+ { !!categoryTags?.length && (
101
+ <ul>
102
+ { categoryTags?.map(tag => (
103
+ <FormControlLabel
104
+ as="li"
105
+ control={(
106
+ <Checkbox
107
+ checked={filters.includes(tag.id)}
108
+ onChange={() => {
109
+ onToggleSelected(tag.id)
110
+ if (isSurface) {
111
+ toggleTag(tag.xml_id, 'left')
112
+ toggleTag(tag.xml_id, 'right')
113
+ }
114
+ }}
115
+ />
116
+ )}
117
+ key={tag.id}
118
+ label={tag.name}
119
+ />
120
+ ))}
121
+ </ul>
122
+ )}
123
+ {
124
+ !!subcategories?.length && (
125
+ <>
126
+ {
127
+ subcategories.map(cat => (
128
+ <CategoryFilter
129
+ key={cat.id}
130
+ name={cat.name}
131
+ categoryId={cat.id}
132
+ tags={tags}
133
+ categories={categories}
134
+ toggleTag={toggleTag}
135
+ onToggleSelected={onToggleSelected}
136
+ isSurface={isSurface}
137
+ filters={filters}
138
+ />
139
+ ))
140
+ }
141
+ </>
142
+ )
143
+ }
144
+ </AccordionDetails>
145
+ </Accordion>
146
+ )
147
+ }
148
+
34
149
  function TagFilters(props) {
35
150
  const { onToggleSelected, filters, query } = props
36
151
  const data = useMemo(() => getData(props.db), [props.db])
37
- const [expanded, setExpanded] = useState(data.taxonomies?.map(() => (false)))
38
152
  const [displayedTags, setDisplayedTags] = useState({})
39
153
 
40
154
  const { toggleTag } = useContext(TagFilterContext)
@@ -44,13 +158,13 @@ function TagFilters(props) {
44
158
  const filteredTags = data.tags.filter(tag => (!query || !query.length || tag.name.toLowerCase().includes(query.toLowerCase())))
45
159
  for (let i = 0; i < data.taxonomies.length; i++) {
46
160
  const tax = data.taxonomies[i]
47
- const tagList = expanded[i] ? filteredTags.filter(t => (t.taxonomy_id === tax.id)) : filteredTags.filter(t => (t.taxonomy_id === tax.id))?.slice(0, 5)
161
+ const tagList = filteredTags.filter(t => t.taxonomy_id === tax.id)
48
162
  if (tagList?.length) {
49
163
  tags[tax.id] = tagList
50
164
  }
51
165
  }
52
166
  setDisplayedTags(tags)
53
- }, [expanded, data, query])
167
+ }, [data, query])
54
168
 
55
169
  return (
56
170
  <>
@@ -59,49 +173,52 @@ function TagFilters(props) {
59
173
  ? (
60
174
  <div className="tag-list">
61
175
  <FormGroup>
62
- { data.taxonomies.map((tax, idx) => {
176
+ { data.taxonomies.map((tax) => {
63
177
  const tagList = displayedTags[tax.id]
178
+ const topLevelTags = tagList?.filter(tag => (!tag.parent_category_id))
64
179
  return (
65
180
  tagList?.length
66
181
  ? (
67
182
  <div key={tax.id}>
68
183
  <Typography>{`${tax.name.slice(0, 1).toUpperCase()}${tax.name.slice(1)}`}</Typography>
69
- <ul>
70
- { tagList?.map(tag => (
71
- <FormControlLabel
72
- as="li"
73
- control={(
74
- <Checkbox
75
- checked={filters.includes(tag.id)}
76
- onChange={() => {
77
- onToggleSelected(tag.id)
78
- if (tax.is_surface) {
79
- toggleTag(tag.xml_id, 'left')
80
- toggleTag(tag.xml_id, 'right')
81
- }
82
- }}
83
- />
84
- )}
85
- key={tag.id}
86
- label={tag.name}
184
+ { !!topLevelTags?.length && (
185
+ <ul>
186
+ { topLevelTags?.map(tag => (
187
+ <FormControlLabel
188
+ as="li"
189
+ control={(
190
+ <Checkbox
191
+ checked={filters.includes(tag.id)}
192
+ onChange={() => {
193
+ onToggleSelected(tag.id)
194
+ if (tax.is_surface) {
195
+ toggleTag(tag.xml_id, 'left')
196
+ toggleTag(tag.xml_id, 'right')
197
+ }
198
+ }}
199
+ />
200
+ )}
201
+ key={tag.id}
202
+ label={tag.name}
203
+ />
204
+ ))}
205
+ </ul>
206
+ )}
207
+ {
208
+ data.categories?.filter(cat => (cat.taxonomy_id === tax.id && !cat.parent_category_id))?.map(cat => (
209
+ <CategoryFilter
210
+ key={cat.id}
211
+ name={cat.name}
212
+ categoryId={cat.id}
213
+ tags={tagList}
214
+ categories={data.categories}
215
+ toggleTag={toggleTag}
216
+ onToggleSelected={onToggleSelected}
217
+ isSurface={tax.is_surface}
218
+ filters={filters}
87
219
  />
88
- ))}
89
- </ul>
90
- { data.tags.filter(t => (t.taxonomy_id === tax.id))?.length && data.tags.filter(t => (t.taxonomy_id === tax.id)).length >= 6
91
- ? (
92
- <button
93
- className="tag-filter-button"
94
- type="button"
95
- onClick={() => {
96
- const newState = [...expanded]
97
- newState[idx] = !expanded[idx]
98
- setExpanded(newState)
99
- }}
100
- >
101
- { expanded[idx] ? 'Show less' : 'Show more'}
102
- </button>
103
- )
104
- : null }
220
+ ))
221
+ }
105
222
  </div>
106
223
  )
107
224
  : null
@@ -30,7 +30,7 @@
30
30
  background-color: #242629;
31
31
  z-index: 10000;
32
32
  padding: 12px 0 12px 12px;
33
- width: 300px;
33
+ width: 430px;
34
34
  height: 100%;
35
35
  max-height: calc(97dvh - 48px);
36
36
  border-left: solid white 1px;
@@ -194,4 +194,6 @@
194
194
 
195
195
  .tag-explore .accordion-detail {
196
196
  background-color: #242629;
197
+ display: flex;
198
+ flex-direction: column;
197
199
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cu-mkp/editioncrafter",
3
3
  "type": "module",
4
- "version": "1.3.1-beta.7",
4
+ "version": "1.3.1-beta.8",
5
5
  "private": false,
6
6
  "description": "A simple digital critical edition publication tool",
7
7
  "license": "MIT",