project-context.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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 * as ReviewPanel from '@/features/ide-react/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. }
  26. publicAccessLevel?: PublicAccessLevel
  27. owner: {
  28. _id: UserId
  29. email: string
  30. }
  31. showNewCompileTimeoutUI?: string
  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. showNewCompileTimeoutUI,
  70. trackChangesState,
  71. } = project || projectFallback
  72. const tags = useMemo(
  73. () =>
  74. getMeta('ol-projectTags', [])
  75. // `tag.name` data may be null for some old users
  76. .map((tag: any) => ({ ...tag, name: tag.name ?? '' })),
  77. []
  78. )
  79. // temporary override for new compile timeout
  80. const forceNewCompileTimeout = new URLSearchParams(
  81. window.location.search
  82. ).get('force_new_compile_timeout')
  83. const newCompileTimeoutOverride =
  84. forceNewCompileTimeout === 'active'
  85. ? 'active'
  86. : forceNewCompileTimeout === 'changing'
  87. ? 'changing'
  88. : undefined
  89. const value = useMemo(() => {
  90. return {
  91. _id,
  92. name,
  93. rootDocId,
  94. members,
  95. invites,
  96. features,
  97. publicAccessLevel,
  98. owner,
  99. showNewCompileTimeoutUI:
  100. newCompileTimeoutOverride || showNewCompileTimeoutUI,
  101. tags,
  102. trackChangesState,
  103. }
  104. }, [
  105. _id,
  106. name,
  107. rootDocId,
  108. members,
  109. invites,
  110. features,
  111. publicAccessLevel,
  112. owner,
  113. showNewCompileTimeoutUI,
  114. newCompileTimeoutOverride,
  115. tags,
  116. trackChangesState,
  117. ])
  118. return (
  119. <ProjectContext.Provider value={value}>{children}</ProjectContext.Provider>
  120. )
  121. }