ProjectEditorHandler.js 4.1 KB

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