project-context.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { FC, createContext, useContext, useMemo } from 'react'
  2. import useScopeValue from '../hooks/use-scope-value'
  3. import getMeta from '@/utils/meta'
  4. import { UserId } from '../../../../types/user'
  5. import { PublicAccessLevel } from '../../../../types/public-access-level'
  6. import type * as ReviewPanel from '@/features/source-editor/context/review-panel/types/review-panel-state'
  7. const ProjectContext = createContext<
  8. | {
  9. _id: string
  10. name: string
  11. rootDocId?: string
  12. members: { _id: UserId; email: string; privileges: string }[]
  13. invites: { _id: UserId }[]
  14. features: {
  15. collaborators?: number
  16. compileGroup?: 'alpha' | 'standard' | 'priority'
  17. trackChanges?: boolean
  18. trackChangesVisible?: boolean
  19. references?: boolean
  20. mendeley?: boolean
  21. zotero?: boolean
  22. versioning?: boolean
  23. gitBridge?: boolean
  24. referencesSearch?: boolean
  25. github?: boolean
  26. }
  27. publicAccessLevel?: PublicAccessLevel
  28. owner: {
  29. _id: UserId
  30. email: string
  31. }
  32. tags: {
  33. _id: string
  34. name: string
  35. color?: string
  36. }[]
  37. trackChangesState: ReviewPanel.Value<'trackChangesState'>
  38. }
  39. | undefined
  40. >(undefined)
  41. export function useProjectContext() {
  42. const context = useContext(ProjectContext)
  43. if (!context) {
  44. throw new Error(
  45. 'useProjectContext is only available inside ProjectProvider'
  46. )
  47. }
  48. return context
  49. }
  50. // when the provider is created the project is still not added to the Angular
  51. // scope. A few props are populated to prevent errors in existing React
  52. // components
  53. const projectFallback = {
  54. _id: window.project_id,
  55. name: '',
  56. features: {},
  57. }
  58. export const ProjectProvider: FC = ({ children }) => {
  59. const [project] = useScopeValue('project', true)
  60. const {
  61. _id,
  62. name,
  63. rootDoc_id: rootDocId,
  64. members,
  65. invites,
  66. features,
  67. publicAccesLevel: publicAccessLevel,
  68. owner,
  69. trackChangesState,
  70. } = project || projectFallback
  71. const tags = useMemo(
  72. () =>
  73. getMeta('ol-projectTags', [])
  74. // `tag.name` data may be null for some old users
  75. .map((tag: any) => ({ ...tag, name: tag.name ?? '' })),
  76. []
  77. )
  78. const value = useMemo(() => {
  79. return {
  80. _id,
  81. name,
  82. rootDocId,
  83. members,
  84. invites,
  85. features,
  86. publicAccessLevel,
  87. owner,
  88. tags,
  89. trackChangesState,
  90. }
  91. }, [
  92. _id,
  93. name,
  94. rootDocId,
  95. members,
  96. invites,
  97. features,
  98. publicAccessLevel,
  99. owner,
  100. tags,
  101. trackChangesState,
  102. ])
  103. return (
  104. <ProjectContext.Provider value={value}>{children}</ProjectContext.Provider>
  105. )
  106. }