utils.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import { hierarchy } from 'd3-hierarchy'
  2. export const RELATIONS = [
  3. 'parents',
  4. 'siblings',
  5. 'children'
  6. ]
  7. export const DATA_LEVELS = {
  8. initial: 0,
  9. partial: 1,
  10. full: 2
  11. }
  12. export const ID_VARIANTS = {
  13. 9: 'depart',
  14. 22: 'critique',
  15. 63: 'echo',
  16. 6: 'reflexion',
  17. 7: 'lecture',
  18. 8: 'sensible',
  19. 23: 'kit',
  20. 0: 'creation'
  21. }
  22. export const VARIANT_IDS = Object.fromEntries(
  23. Object.entries(ID_VARIANTS).map(([key, value]) => [value, parseInt(key)])
  24. )
  25. export const SEARCH_KEYS = ['content', 'title', 'preTitle', 'authors']
  26. export function parseNodesQueryParams ({ mode, nodes = [] }) {
  27. let nodebook = typeof nodes === 'string' ? [nodes] : nodes
  28. nodebook = nodebook.map(ids => {
  29. return typeof ids === 'string'
  30. ? ids.split(',').map(id => parseInt(id))
  31. : [...ids]
  32. })
  33. return { mode, nodebook }
  34. }
  35. export function getUniqueNodesIds (tree) {
  36. function extractId (ids, node) {
  37. ids.add(node.id)
  38. for (const relation of RELATIONS) {
  39. if (relation in node && node[relation]) {
  40. for (const subNode of node[relation]) {
  41. extractId(ids, subNode)
  42. }
  43. }
  44. }
  45. return ids
  46. }
  47. return Array.from(extractId(new Set(), tree))
  48. }
  49. export function getRelatedNodesIds (nodes, ignored) {
  50. const ids = new Set()
  51. for (const node of nodes) {
  52. for (const relation of RELATIONS) {
  53. if (relation in node && node[relation]) {
  54. node[relation].forEach(({ id }) => {
  55. if (ignored.includes(id)) return
  56. ids.add(id)
  57. })
  58. }
  59. }
  60. }
  61. return Array.from(ids)
  62. }
  63. export function getRandomIds (ids, count = 3) {
  64. const randomIds = []
  65. while (randomIds.length < count) {
  66. const id = ids[Math.floor(Math.random() * ids.length)]
  67. if (!randomIds.includes(id)) {
  68. randomIds.push(id)
  69. }
  70. }
  71. return randomIds
  72. }
  73. export function parseTree (treeData) {
  74. if ('creations' in treeData) {
  75. if (treeData.creations) {
  76. if (!Array.isArray(treeData.children)) {
  77. treeData.children = []
  78. }
  79. treeData.creations.forEach(item => {
  80. item.variant = [{ id: 0 }]
  81. treeData.children.push(item)
  82. })
  83. }
  84. delete treeData.creations
  85. }
  86. for (const relation of RELATIONS) {
  87. if (relation in treeData && treeData[relation]) {
  88. treeData[relation] = treeData[relation].map(node => parseTree(node))
  89. }
  90. }
  91. return treeData
  92. }
  93. export function buildTree (treeData, nodesData) {
  94. const uniqueIds = []
  95. const nodes = []
  96. const links = []
  97. const h = hierarchy(treeData, (node) => {
  98. return RELATIONS.reduce((acc, relation) => {
  99. if (node[relation]) {
  100. node[relation].forEach((item, i) => {
  101. item.linkType = relation
  102. })
  103. return [...acc, ...node[relation]]
  104. }
  105. return acc
  106. }, [])
  107. })
  108. h.each(node => {
  109. node.id = node.data.id
  110. if (!uniqueIds.includes(node.id)) {
  111. uniqueIds.push(node.id)
  112. node.data = nodesData.find(n => n.id === node.id)
  113. // Add `x` and `y` keys so Vue can update on these values updates
  114. Object.assign(node, { x: undefined, y: undefined })
  115. nodes.push(node)
  116. if (node.children) {
  117. node.children.forEach(child => {
  118. const asSource = links.find(link => link.source === node.id && link.target === child.data.id)
  119. const asTarget = links.find(link => link.source === child.data.id && link.target === node.id)
  120. if (!asSource && !asTarget) {
  121. links.push({ source: node.id, target: child.data.id, linkType: child.data.linkType })
  122. }
  123. })
  124. }
  125. }
  126. })
  127. return {
  128. nodes,
  129. links
  130. }
  131. }
  132. export function searchInNode (search, node) {
  133. if (!search) return true
  134. for (const key of SEARCH_KEYS) {
  135. if (!node[key]) continue
  136. let match = false
  137. if (key === 'authors') {
  138. match = node[key].some(author => author.name.toLowerCase().includes(search))
  139. } else {
  140. match = node[key].toLowerCase().includes(search)
  141. }
  142. if (match) return true
  143. }
  144. return false
  145. }
  146. export function tagsInNode (tags, nodeTags) {
  147. if (tags.length === 0) return true
  148. if (!nodeTags || nodeTags.length === 0) return false
  149. return tags.every(tag => nodeTags.some(nodeTag => nodeTag.name === tag))
  150. }
  151. export function getRelation (node) {
  152. if (node.type === 'prod' && node.parents && node.parents.length) {
  153. return { parentId: node.parents[0].id, childId: node.id }
  154. }
  155. return { parentId: node.id }
  156. }
  157. export function getStrangenessOpacity (currentStrangeness, node) {
  158. if (currentStrangeness === undefined) return 1
  159. const strangeness = (
  160. node.type === 'prod' && node.parents && node.parents.length ? node.parents[0] : node
  161. ).strangeness
  162. return 1 / (Math.abs(strangeness - currentStrangeness) + 1)
  163. }