ProjectEditorHandler.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. let ProjectEditorHandler
  2. const _ = require('lodash')
  3. const Path = require('path')
  4. function mergeDeletedDocs(a, b) {
  5. const docIdsInA = new Set(a.map(doc => doc._id.toString()))
  6. return a.concat(b.filter(doc => !docIdsInA.has(doc._id.toString())))
  7. }
  8. module.exports = ProjectEditorHandler = {
  9. trackChangesAvailable: false,
  10. buildProjectModelView(project, members, invites, deletedDocsFromDocstore) {
  11. let owner, ownerFeatures
  12. if (!Array.isArray(project.deletedDocs)) {
  13. project.deletedDocs = []
  14. }
  15. project.deletedDocs.forEach(doc => {
  16. // The frontend does not use this field.
  17. delete doc.deletedAt
  18. })
  19. const result = {
  20. _id: project._id,
  21. name: project.name,
  22. rootDoc_id: project.rootDoc_id,
  23. mainBibliographyDoc_id: project.mainBibliographyDoc_id,
  24. rootFolder: [this.buildFolderModelView(project.rootFolder[0])],
  25. publicAccesLevel: project.publicAccesLevel,
  26. dropboxEnabled: !!project.existsInDropbox,
  27. compiler: project.compiler,
  28. description: project.description,
  29. spellCheckLanguage: project.spellCheckLanguage,
  30. deletedByExternalDataSource: project.deletedByExternalDataSource || false,
  31. deletedDocs: mergeDeletedDocs(
  32. project.deletedDocs,
  33. deletedDocsFromDocstore
  34. ),
  35. members: [],
  36. invites: this.buildInvitesView(invites),
  37. imageName:
  38. project.imageName != null
  39. ? Path.basename(project.imageName)
  40. : undefined,
  41. }
  42. ;({ owner, ownerFeatures, members } =
  43. this.buildOwnerAndMembersViews(members))
  44. result.owner = owner
  45. result.members = members
  46. result.features = _.defaults(ownerFeatures || {}, {
  47. collaborators: -1, // Infinite
  48. versioning: false,
  49. dropbox: false,
  50. compileTimeout: 60,
  51. compileGroup: 'standard',
  52. templates: false,
  53. references: false,
  54. referencesSearch: false,
  55. mendeley: false,
  56. trackChanges: false,
  57. trackChangesVisible: ProjectEditorHandler.trackChangesAvailable,
  58. symbolPalette: false,
  59. })
  60. if (result.features.trackChanges) {
  61. result.trackChangesState = project.track_changes || false
  62. }
  63. // Originally these two feature flags were both signalled by the now-deprecated `references` flag.
  64. // For older users, the presence of the `references` feature flag should still turn on these features.
  65. result.features.referencesSearch =
  66. result.features.referencesSearch || result.features.references
  67. result.features.mendeley =
  68. result.features.mendeley || result.features.references
  69. return result
  70. },
  71. buildOwnerAndMembersViews(members) {
  72. let owner = null
  73. let ownerFeatures = null
  74. const filteredMembers = []
  75. for (const member of members || []) {
  76. if (member.privilegeLevel === 'owner') {
  77. ownerFeatures = member.user.features
  78. owner = this.buildUserModelView(member)
  79. } else {
  80. filteredMembers.push(this.buildUserModelView(member))
  81. }
  82. }
  83. return {
  84. owner,
  85. ownerFeatures,
  86. members: filteredMembers,
  87. }
  88. },
  89. buildUserModelView(member) {
  90. const user = member.user
  91. return {
  92. _id: user._id,
  93. first_name: user.first_name,
  94. last_name: user.last_name,
  95. email: user.email,
  96. privileges: member.privilegeLevel,
  97. signUpDate: user.signUpDate,
  98. pendingEditor: member.pendingEditor,
  99. }
  100. },
  101. buildFolderModelView(folder) {
  102. const fileRefs = _.filter(folder.fileRefs || [], file => file != null)
  103. return {
  104. _id: folder._id,
  105. name: folder.name,
  106. folders: (folder.folders || []).map(childFolder =>
  107. this.buildFolderModelView(childFolder)
  108. ),
  109. fileRefs: fileRefs.map(file => this.buildFileModelView(file)),
  110. docs: (folder.docs || []).map(doc => this.buildDocModelView(doc)),
  111. }
  112. },
  113. buildFileModelView(file) {
  114. return {
  115. _id: file._id,
  116. name: file.name,
  117. linkedFileData: file.linkedFileData,
  118. created: file.created,
  119. hash: file.hash,
  120. }
  121. },
  122. buildDocModelView(doc) {
  123. return {
  124. _id: doc._id,
  125. name: doc.name,
  126. }
  127. },
  128. buildInvitesView(invites) {
  129. if (invites == null) {
  130. return []
  131. }
  132. return invites.map(invite => _.pick(invite, ['_id', 'email', 'privileges']))
  133. },
  134. }