project-context.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { createContext, useContext, useMemo } from 'react'
  2. import PropTypes from 'prop-types'
  3. import useScopeValue from '../hooks/use-scope-value'
  4. const ProjectContext = createContext()
  5. export const projectShape = {
  6. _id: PropTypes.string.isRequired,
  7. name: PropTypes.string.isRequired,
  8. rootDocId: PropTypes.string,
  9. members: PropTypes.arrayOf(
  10. PropTypes.shape({
  11. _id: PropTypes.string.isRequired,
  12. })
  13. ),
  14. invites: PropTypes.arrayOf(
  15. PropTypes.shape({
  16. _id: PropTypes.string.isRequired,
  17. })
  18. ),
  19. features: PropTypes.shape({
  20. collaborators: PropTypes.number,
  21. compileGroup: PropTypes.oneOf(['alpha', 'standard', 'priority']),
  22. trackChangesVisible: PropTypes.bool,
  23. references: PropTypes.bool,
  24. mendeley: PropTypes.bool,
  25. zotero: PropTypes.bool,
  26. versioning: PropTypes.bool,
  27. }),
  28. publicAccessLevel: PropTypes.string,
  29. tokens: PropTypes.shape({
  30. readOnly: PropTypes.string,
  31. readAndWrite: PropTypes.string,
  32. }),
  33. owner: PropTypes.shape({
  34. _id: PropTypes.string.isRequired,
  35. email: PropTypes.string.isRequired,
  36. }),
  37. }
  38. ProjectContext.Provider.propTypes = {
  39. value: PropTypes.shape(projectShape),
  40. }
  41. export function useProjectContext(propTypes) {
  42. const context = useContext(ProjectContext)
  43. if (!context) {
  44. throw new Error(
  45. 'useProjectContext is only available inside ProjectProvider'
  46. )
  47. }
  48. PropTypes.checkPropTypes(
  49. propTypes,
  50. context,
  51. 'data',
  52. 'ProjectContext.Provider'
  53. )
  54. return context
  55. }
  56. // when the provider is created the project is still not added to the Angular
  57. // scope. A few props are populated to prevent errors in existing React
  58. // components
  59. const projectFallback = {
  60. _id: window.project_id,
  61. name: '',
  62. features: {},
  63. }
  64. export function ProjectProvider({ children }) {
  65. const [project] = useScopeValue('project', true)
  66. const {
  67. _id,
  68. name,
  69. rootDoc_id: rootDocId,
  70. members,
  71. invites,
  72. features,
  73. publicAccesLevel: publicAccessLevel,
  74. tokens,
  75. owner,
  76. } = project || projectFallback
  77. const value = useMemo(() => {
  78. return {
  79. _id,
  80. name,
  81. rootDocId,
  82. members,
  83. invites,
  84. features,
  85. publicAccessLevel,
  86. tokens,
  87. owner,
  88. }
  89. }, [
  90. _id,
  91. name,
  92. rootDocId,
  93. members,
  94. invites,
  95. features,
  96. publicAccessLevel,
  97. tokens,
  98. owner,
  99. ])
  100. return (
  101. <ProjectContext.Provider value={value}>{children}</ProjectContext.Provider>
  102. )
  103. }
  104. ProjectProvider.propTypes = {
  105. children: PropTypes.any,
  106. }