|
1 import _ from 'lodash'; |
|
2 |
|
3 import { RECEIVE_ANNOTATIONS, RECEIVE_MESSAGES_COUNT } from '../actions'; |
|
4 import { isDefinitionInTags } from '../utils'; |
|
5 |
|
6 /** |
|
7 * termsMap is a mapping { term: [annotations,...] } |
|
8 * where annotation |
|
9 */ |
|
10 function getDefinitionsAndReferences(annotations, termsMap) { |
|
11 return Object.keys(termsMap).reduce((res, term) => { |
|
12 res[term] = res[term] || { |
|
13 keywordAnnotations: termsMap[term], |
|
14 definitions: [], |
|
15 references: [], |
|
16 }; |
|
17 |
|
18 termsMap[term].forEach((annotation) => { |
|
19 const annotationText = (annotation.text && annotation.text.trim()) || ''; |
|
20 const tags = annotation.tags.map(t => t.toLowerCase()); |
|
21 if (annotationText && isDefinitionInTags(tags)) { |
|
22 const annotationObj = annotation; |
|
23 annotationObj.isPersonal = true; |
|
24 res[term].definitions.push(annotationObj); |
|
25 } |
|
26 }); |
|
27 |
|
28 annotations.forEach((annotation) => { |
|
29 const tags = annotation.tags.map(t => t.toLowerCase()); |
|
30 if (isDefinitionInTags(tags) && tags.includes(term.toLowerCase())) { |
|
31 const annotationObj = annotation; |
|
32 annotationObj.isPersonal = false; |
|
33 res[term].definitions.push(annotationObj); |
|
34 } else { |
|
35 let exactText; |
|
36 |
|
37 (annotation.target[0].selector || []).some((selector) => { |
|
38 if (selector.type === 'TextQuoteSelector' && selector.exact) { |
|
39 exactText = selector.exact.trim().toLowerCase(); |
|
40 return true; |
|
41 } |
|
42 return false; |
|
43 }); |
|
44 |
|
45 if (exactText && exactText.includes(term.toLowerCase()) && !tags.includes('cat:mot-clef')) { |
|
46 res[term].references.push(annotation); |
|
47 } |
|
48 } |
|
49 }); |
|
50 return res; |
|
51 }, {}); |
|
52 } |
|
53 |
|
54 /** |
|
55 * Calculate stats on terms |
|
56 */ |
|
57 function addTermStats(termsMap) { |
|
58 return _.reduce( |
|
59 termsMap, |
|
60 (res, termDef, term) => { |
|
61 res[term] = _.assign({ |
|
62 definitionsNb: (termDef.definitions || []).length, |
|
63 referenceNb: (termDef.references || []).length, |
|
64 }, termDef); |
|
65 return res; |
|
66 }, |
|
67 {}, |
|
68 ); |
|
69 } |
|
70 |
|
71 |
|
72 function terms( |
|
73 state = { |
|
74 }, |
|
75 action, |
|
76 ) { |
|
77 switch (action.type) { |
|
78 case RECEIVE_ANNOTATIONS: { |
|
79 const { annotations } = action; |
|
80 // let termsMap = getTerms(annotations); |
|
81 let termsMap = action.terms; |
|
82 termsMap = getDefinitionsAndReferences(annotations, termsMap); |
|
83 return Object.assign({}, state, addTermStats(termsMap)); |
|
84 } |
|
85 case RECEIVE_MESSAGES_COUNT: { |
|
86 const { terms: termList, messagesCount: counts } = action; |
|
87 const termCountMap = _.zipObject(termList, counts); |
|
88 |
|
89 return Object.assign({}, state, _.mapValues( |
|
90 state, |
|
91 (termDef, term) => Object.assign( |
|
92 {}, |
|
93 termDef, |
|
94 { messagesCount: termCountMap[term] || 0 }, |
|
95 ), |
|
96 )); |
|
97 } |
|
98 default: |
|
99 return state; |
|
100 } |
|
101 } |
|
102 |
|
103 export default terms; |