mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-09 08:16:11 +00:00
Merge pull request #4245 from overleaf/msm-extract-project-context
React `project-context` GitOrigin-RevId: 6a23437d6e6a328ff5854622ff903d348db1f8b8
This commit is contained in:
parent
d10294a58a
commit
b7802674d5
21 changed files with 177 additions and 120 deletions
|
@ -10,7 +10,7 @@ import PropTypes from 'prop-types'
|
|||
import { v4 as uuid } from 'uuid'
|
||||
|
||||
import { useApplicationContext } from '../../../shared/context/application-context'
|
||||
import { useEditorContext } from '../../../shared/context/editor-context'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
import { getJSON, postJSON } from '../../../infrastructure/fetch-json'
|
||||
import { appendMessage, prependMessages } from '../utils/message-list-appender'
|
||||
import useBrowserWindow from '../../../shared/hooks/use-browser-window'
|
||||
|
@ -120,8 +120,8 @@ export function ChatProvider({ children }) {
|
|||
const { user } = useApplicationContext({
|
||||
user: PropTypes.shape({ id: PropTypes.string.isRequired }),
|
||||
})
|
||||
const { projectId } = useEditorContext({
|
||||
projectId: PropTypes.string.isRequired,
|
||||
const { _id: projectId } = useProjectContext({
|
||||
_id: PropTypes.string.isRequired,
|
||||
})
|
||||
|
||||
const { chatIsOpen } = useLayoutContext({ chatIsOpen: PropTypes.bool })
|
||||
|
|
|
@ -5,16 +5,20 @@ import { useEditorContext } from '../../../shared/context/editor-context'
|
|||
import { useChatContext } from '../../chat/context/chat-context'
|
||||
import { useLayoutContext } from '../../../shared/context/layout-context'
|
||||
import { useApplicationContext } from '../../../shared/context/application-context'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
const applicationContextPropTypes = {
|
||||
user: PropTypes.object,
|
||||
}
|
||||
|
||||
const projectContextPropTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
const editorContextPropTypes = {
|
||||
cobranding: PropTypes.object,
|
||||
loading: PropTypes.bool,
|
||||
isRestrictedTokenMember: PropTypes.bool,
|
||||
projectName: PropTypes.string.isRequired,
|
||||
renameProject: PropTypes.func.isRequired,
|
||||
isProjectOwner: PropTypes.bool,
|
||||
}
|
||||
|
@ -43,11 +47,12 @@ const EditorNavigationToolbarRoot = React.memo(
|
|||
}) {
|
||||
const { user } = useApplicationContext(applicationContextPropTypes)
|
||||
|
||||
const { name: projectName } = useProjectContext(projectContextPropTypes)
|
||||
|
||||
const {
|
||||
cobranding,
|
||||
loading,
|
||||
isRestrictedTokenMember,
|
||||
projectName,
|
||||
renameProject,
|
||||
isProjectOwner,
|
||||
} = useEditorContext(editorContextPropTypes)
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Trans, useTranslation } from 'react-i18next'
|
|||
import Icon from '../../../shared/components/icon'
|
||||
import { formatTime, relativeDate } from '../../utils/format-date'
|
||||
import { postJSON } from '../../../infrastructure/fetch-json'
|
||||
import { useEditorContext } from '../../../shared/context/editor-context'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
import useAbortController from '../../../shared/hooks/use-abort-controller'
|
||||
|
@ -32,8 +32,8 @@ function shortenedUrl(url) {
|
|||
}
|
||||
|
||||
export default function FileViewHeader({ file, storeReferencesKeys }) {
|
||||
const { projectId } = useEditorContext({
|
||||
projectId: PropTypes.string.isRequired,
|
||||
const { _id: projectId } = useProjectContext({
|
||||
_id: PropTypes.string.isRequired,
|
||||
})
|
||||
const { t } = useTranslation()
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import { useEditorContext } from '../../../shared/context/editor-context'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function FileViewImage({ fileName, fileId, onLoad, onError }) {
|
||||
const { projectId } = useEditorContext({
|
||||
projectId: PropTypes.string.isRequired,
|
||||
const { _id: projectId } = useProjectContext({
|
||||
_id: PropTypes.string.isRequired,
|
||||
})
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useEditorContext } from '../../../shared/context/editor-context'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
const MAX_FILE_SIZE = 2 * 1024 * 1024
|
||||
|
||||
export default function FileViewText({ file, onLoad, onError }) {
|
||||
const { projectId } = useEditorContext({
|
||||
projectId: PropTypes.string.isRequired,
|
||||
const { _id: projectId } = useProjectContext({
|
||||
_id: PropTypes.string.isRequired,
|
||||
})
|
||||
|
||||
const [textPreview, setTextPreview] = useState('')
|
||||
|
|
|
@ -7,7 +7,7 @@ import OutlineRoot from './outline-root'
|
|||
import Icon from '../../../shared/components/icon'
|
||||
import localStorage from '../../../infrastructure/local-storage'
|
||||
import withErrorBoundary from '../../../infrastructure/error-boundary'
|
||||
import { useEditorContext } from '../../../shared/context/editor-context'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
const OutlinePane = React.memo(function OutlinePane({
|
||||
isTexFile,
|
||||
|
@ -19,8 +19,8 @@ const OutlinePane = React.memo(function OutlinePane({
|
|||
}) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { projectId } = useEditorContext({
|
||||
projectId: PropTypes.string.isRequired,
|
||||
const { _id: projectId } = useProjectContext({
|
||||
_id: PropTypes.string.isRequired,
|
||||
})
|
||||
|
||||
const storageKey = `file_outline.expanded.${projectId}`
|
||||
|
|
|
@ -2,14 +2,12 @@ import { useState, useMemo } from 'react'
|
|||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Form, FormGroup, FormControl, Button } from 'react-bootstrap'
|
||||
import { useMultipleSelection } from 'downshift'
|
||||
import {
|
||||
useProjectContext,
|
||||
useShareProjectContext,
|
||||
} from './share-project-modal'
|
||||
import { useShareProjectContext } from './share-project-modal'
|
||||
import SelectCollaborators from './select-collaborators'
|
||||
import { resendInvite, sendInvite } from '../utils/api'
|
||||
import { useUserContacts } from '../hooks/use-user-contacts'
|
||||
import useIsMounted from '../../../shared/hooks/use-is-mounted'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function AddCollaborators() {
|
||||
const [privileges, setPrivileges] = useState('readAndWrite')
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import {
|
||||
useProjectContext,
|
||||
useShareProjectContext,
|
||||
} from './share-project-modal'
|
||||
import { useShareProjectContext } from './share-project-modal'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import TransferOwnershipModal from './transfer-ownership-modal'
|
||||
import {
|
||||
|
@ -17,6 +14,7 @@ import {
|
|||
Tooltip,
|
||||
} from 'react-bootstrap'
|
||||
import { removeMemberFromProject, updateMember } from '../utils/api'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function EditMember({ member }) {
|
||||
const [privileges, setPrivileges] = useState(member.privileges)
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import { useCallback } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {
|
||||
useProjectContext,
|
||||
useShareProjectContext,
|
||||
} from './share-project-modal'
|
||||
import { useShareProjectContext } from './share-project-modal'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import { Button, Col, Row, OverlayTrigger, Tooltip } from 'react-bootstrap'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import MemberPrivileges from './member-privileges'
|
||||
import { resendInvite, revokeInvite } from '../utils/api'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function Invite({ invite, isAdmin }) {
|
||||
return (
|
||||
|
|
|
@ -3,12 +3,10 @@ import PropTypes from 'prop-types'
|
|||
import { Button, Col, OverlayTrigger, Row, Tooltip } from 'react-bootstrap'
|
||||
import { Trans } from 'react-i18next'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import {
|
||||
useProjectContext,
|
||||
useShareProjectContext,
|
||||
} from './share-project-modal'
|
||||
import { useShareProjectContext } from './share-project-modal'
|
||||
import { setProjectAccessLevel } from '../utils/api'
|
||||
import CopyLink from '../../../shared/components/copy-link'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function LinkSharing() {
|
||||
const [inflight, setInflight] = useState(false)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useProjectContext } from './share-project-modal'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
import { Col, Row } from 'react-bootstrap'
|
||||
import { Trans } from 'react-i18next'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Col, Row } from 'react-bootstrap'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Trans } from 'react-i18next'
|
||||
import { useProjectContext } from './share-project-modal'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function SendInvitesNotice() {
|
||||
const project = useProjectContext()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { useMemo } from 'react'
|
||||
import { Row } from 'react-bootstrap'
|
||||
import { useProjectContext } from './share-project-modal'
|
||||
import AddCollaborators from './add-collaborators'
|
||||
import AddCollaboratorsUpgrade from './add-collaborators-upgrade'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function SendInvites() {
|
||||
const project = useProjectContext()
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import {
|
||||
useProjectContext,
|
||||
useShareProjectContext,
|
||||
} from './share-project-modal'
|
||||
import { useShareProjectContext } from './share-project-modal'
|
||||
import EditMember from './edit-member'
|
||||
import LinkSharing from './link-sharing'
|
||||
import Invite from './invite'
|
||||
|
@ -9,6 +6,7 @@ import SendInvites from './send-invites'
|
|||
import ViewMember from './view-member'
|
||||
import OwnerInfo from './owner-info'
|
||||
import SendInvitesNotice from './send-invites-notice'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function ShareModalBody() {
|
||||
const { isAdmin } = useShareProjectContext()
|
||||
|
|
|
@ -7,7 +7,7 @@ import React, {
|
|||
} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import ShareProjectModalContent from './share-project-modal-content'
|
||||
import useScopeValue from '../../../shared/context/util/scope-value-hook'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
const ShareProjectContext = createContext()
|
||||
|
||||
|
@ -35,7 +35,7 @@ export function useShareProjectContext() {
|
|||
return context
|
||||
}
|
||||
|
||||
const projectShape = PropTypes.shape({
|
||||
const projectShape = {
|
||||
_id: PropTypes.string.isRequired,
|
||||
members: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
|
@ -59,24 +59,6 @@ const projectShape = PropTypes.shape({
|
|||
owner: PropTypes.shape({
|
||||
email: PropTypes.string,
|
||||
}),
|
||||
})
|
||||
|
||||
const ProjectContext = createContext()
|
||||
|
||||
ProjectContext.Provider.propTypes = {
|
||||
value: projectShape,
|
||||
}
|
||||
|
||||
export function useProjectContext() {
|
||||
const context = useContext(ProjectContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useProjectContext is only available inside ShareProjectProvider'
|
||||
)
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
const ShareProjectModal = React.memo(function ShareProjectModal({
|
||||
|
@ -88,7 +70,7 @@ const ShareProjectModal = React.memo(function ShareProjectModal({
|
|||
const [inFlight, setInFlight] = useState(false)
|
||||
const [error, setError] = useState()
|
||||
|
||||
const [project, setProject] = useScopeValue('project', true)
|
||||
const project = useProjectContext(projectShape)
|
||||
|
||||
// reset error when the modal is opened
|
||||
useEffect(() => {
|
||||
|
@ -127,12 +109,9 @@ const ShareProjectModal = React.memo(function ShareProjectModal({
|
|||
}, [])
|
||||
|
||||
// merge the new data with the old project data
|
||||
const updateProject = useCallback(
|
||||
data => {
|
||||
setProject(project => Object.assign(project, data))
|
||||
},
|
||||
[setProject]
|
||||
)
|
||||
const updateProject = useCallback(data => Object.assign(project, data), [
|
||||
project,
|
||||
])
|
||||
|
||||
if (!project) {
|
||||
return null
|
||||
|
@ -150,15 +129,13 @@ const ShareProjectModal = React.memo(function ShareProjectModal({
|
|||
setError,
|
||||
}}
|
||||
>
|
||||
<ProjectContext.Provider value={project}>
|
||||
<ShareProjectModalContent
|
||||
animation={animation}
|
||||
cancel={cancel}
|
||||
error={error}
|
||||
inFlight={inFlight}
|
||||
show={show}
|
||||
/>
|
||||
</ProjectContext.Provider>
|
||||
<ShareProjectModalContent
|
||||
animation={animation}
|
||||
cancel={cancel}
|
||||
error={error}
|
||||
inFlight={inFlight}
|
||||
show={show}
|
||||
/>
|
||||
</ShareProjectContext.Provider>
|
||||
)
|
||||
})
|
||||
|
|
|
@ -2,11 +2,11 @@ import { useState } from 'react'
|
|||
import { Modal, Button } from 'react-bootstrap'
|
||||
import { Trans } from 'react-i18next'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useProjectContext } from './share-project-modal'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import { transferProjectOwnership } from '../utils/api'
|
||||
import AccessibleModal from '../../../shared/components/accessible-modal'
|
||||
import { reload } from '../utils/location'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
|
||||
export default function TransferOwnershipModal({ member, cancel }) {
|
||||
const [inflight, setInflight] = useState(false)
|
||||
|
|
|
@ -9,6 +9,7 @@ import PropTypes from 'prop-types'
|
|||
import useScopeValue from './util/scope-value-hook'
|
||||
import useBrowserWindow from '../hooks/use-browser-window'
|
||||
import { useIdeContext } from './ide-context'
|
||||
import { useProjectContext } from './project-context'
|
||||
|
||||
export const EditorContext = createContext()
|
||||
|
||||
|
@ -27,43 +28,48 @@ EditorContext.Provider.propTypes = {
|
|||
}),
|
||||
hasPremiumCompile: PropTypes.bool,
|
||||
loading: PropTypes.bool,
|
||||
projectRootDocId: PropTypes.string,
|
||||
projectId: PropTypes.string.isRequired,
|
||||
projectName: PropTypes.string.isRequired,
|
||||
renameProject: PropTypes.func.isRequired,
|
||||
isProjectOwner: PropTypes.bool,
|
||||
isRestrictedTokenMember: PropTypes.bool,
|
||||
rootFolder: PropTypes.object,
|
||||
rootFolder: PropTypes.shape({
|
||||
children: PropTypes.arrayOf(PropTypes.shape({ type: PropTypes.string })),
|
||||
}),
|
||||
}),
|
||||
}
|
||||
|
||||
export function EditorProvider({ children, settings }) {
|
||||
const ide = useIdeContext()
|
||||
|
||||
const cobranding = useMemo(
|
||||
() =>
|
||||
window.brandVariation
|
||||
? {
|
||||
logoImgUrl: window.brandVariation.logo_url,
|
||||
brandVariationName: window.brandVariation.name,
|
||||
brandVariationId: window.brandVariation.id,
|
||||
brandId: window.brandVariation.brand_id,
|
||||
brandVariationHomeUrl: window.brandVariation.home_url,
|
||||
publishGuideHtml: window.brandVariation.publish_guide_html,
|
||||
partner: window.brandVariation.partner,
|
||||
brandedMenu: window.brandVariation.branded_menu,
|
||||
submitBtnHtml: window.brandVariation.submit_button_html,
|
||||
}
|
||||
: undefined,
|
||||
[]
|
||||
)
|
||||
const { owner, features } = useProjectContext({
|
||||
owner: PropTypes.shape({
|
||||
_id: PropTypes.string.isRequired,
|
||||
}),
|
||||
features: PropTypes.shape({
|
||||
compileGroup: PropTypes.string,
|
||||
}),
|
||||
})
|
||||
|
||||
const cobranding = useMemo(() => {
|
||||
if (window.brandVariation) {
|
||||
return {
|
||||
logoImgUrl: window.brandVariation.logo_url,
|
||||
brandVariationName: window.brandVariation.name,
|
||||
brandVariationId: window.brandVariation.id,
|
||||
brandId: window.brandVariation.brand_id,
|
||||
brandVariationHomeUrl: window.brandVariation.home_url,
|
||||
publishGuideHtml: window.brandVariation.publish_guide_html,
|
||||
partner: window.brandVariation.partner,
|
||||
brandedMenu: window.brandVariation.branded_menu,
|
||||
submitBtnHtml: window.brandVariation.submit_button_html,
|
||||
}
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}, [])
|
||||
|
||||
const [loading] = useScopeValue('state.loading')
|
||||
const [projectRootDocId] = useScopeValue('project.rootDoc_id')
|
||||
const [projectName, setProjectName] = useScopeValue('project.name')
|
||||
const [compileGroup] = useScopeValue('project.features.compileGroup')
|
||||
const [rootFolder] = useScopeValue('rootFolder')
|
||||
const [ownerId] = useScopeValue('project.owner._id')
|
||||
|
||||
const renameProject = useCallback(
|
||||
newName => {
|
||||
|
@ -100,24 +106,19 @@ export function EditorProvider({ children, settings }) {
|
|||
const value = useMemo(
|
||||
() => ({
|
||||
cobranding,
|
||||
hasPremiumCompile: compileGroup === 'priority',
|
||||
hasPremiumCompile: features?.compileGroup === 'priority',
|
||||
loading,
|
||||
projectId: window.project_id,
|
||||
projectRootDocId,
|
||||
projectName: projectName || '', // initially might be empty in Angular
|
||||
renameProject,
|
||||
isProjectOwner: ownerId === window.user.id,
|
||||
isProjectOwner: owner?._id === window.user.id,
|
||||
isRestrictedTokenMember: window.isRestrictedTokenMember,
|
||||
rootFolder,
|
||||
}),
|
||||
[
|
||||
cobranding,
|
||||
compileGroup,
|
||||
features?.compileGroup,
|
||||
loading,
|
||||
ownerId,
|
||||
projectName,
|
||||
projectRootDocId,
|
||||
renameProject,
|
||||
owner?._id,
|
||||
rootFolder,
|
||||
]
|
||||
)
|
||||
|
|
72
services/web/frontend/js/shared/context/project-context.js
Normal file
72
services/web/frontend/js/shared/context/project-context.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
import { createContext, useContext } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import useScopeValue from './util/scope-value-hook'
|
||||
|
||||
const ProjectContext = createContext()
|
||||
|
||||
ProjectContext.Provider.propTypes = {
|
||||
value: PropTypes.shape({
|
||||
_id: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
rootDoc_id: PropTypes.string,
|
||||
members: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
_id: PropTypes.string.isRequired,
|
||||
})
|
||||
),
|
||||
invites: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
_id: PropTypes.string.isRequired,
|
||||
})
|
||||
),
|
||||
features: PropTypes.shape({
|
||||
collaborators: PropTypes.number,
|
||||
compileGroup: PropTypes.oneOf(['alpha', 'standard', 'priority'])
|
||||
.isRequired,
|
||||
}),
|
||||
publicAccesLevel: PropTypes.string,
|
||||
tokens: PropTypes.shape({
|
||||
readOnly: PropTypes.string,
|
||||
readAndWrite: PropTypes.string,
|
||||
}),
|
||||
owner: PropTypes.shape({
|
||||
_id: PropTypes.string.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
}),
|
||||
}),
|
||||
}
|
||||
|
||||
export function useProjectContext(propTypes) {
|
||||
const context = useContext(ProjectContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useProjectContext is only available inside ProjectProvider'
|
||||
)
|
||||
}
|
||||
|
||||
PropTypes.checkPropTypes(
|
||||
propTypes,
|
||||
context,
|
||||
'data',
|
||||
'ProjectContext.Provider'
|
||||
)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
export function ProjectProvider({ children }) {
|
||||
const [project] = useScopeValue('project', true)
|
||||
|
||||
// when the provider is created the project is still not added to the Angular scope.
|
||||
// Name is also populated to prevent errors in existing React components
|
||||
const value = project || { _id: window.project_id, name: '' }
|
||||
|
||||
return (
|
||||
<ProjectContext.Provider value={value}>{children}</ProjectContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
ProjectProvider.propTypes = {
|
||||
children: PropTypes.any,
|
||||
}
|
|
@ -7,18 +7,21 @@ import { EditorProvider } from './editor-context'
|
|||
import { CompileProvider } from './compile-context'
|
||||
import { LayoutProvider } from './layout-context'
|
||||
import { ChatProvider } from '../../features/chat/context/chat-context'
|
||||
import { ProjectProvider } from './project-context'
|
||||
|
||||
export function ContextRoot({ children, ide, settings }) {
|
||||
return (
|
||||
<ApplicationProvider>
|
||||
<IdeProvider ide={ide}>
|
||||
<EditorProvider settings={settings}>
|
||||
<CompileProvider>
|
||||
<LayoutProvider>
|
||||
<ChatProvider>{children}</ChatProvider>
|
||||
</LayoutProvider>
|
||||
</CompileProvider>
|
||||
</EditorProvider>
|
||||
<ProjectProvider>
|
||||
<EditorProvider settings={settings}>
|
||||
<CompileProvider>
|
||||
<LayoutProvider>
|
||||
<ChatProvider>{children}</ChatProvider>
|
||||
</LayoutProvider>
|
||||
</CompileProvider>
|
||||
</EditorProvider>
|
||||
</ProjectProvider>
|
||||
</IdeProvider>
|
||||
</ApplicationProvider>
|
||||
)
|
||||
|
|
|
@ -23,8 +23,10 @@ describe('<ShareProjectModal/>', function () {
|
|||
name: 'Test Project',
|
||||
features: {
|
||||
collaborators: 10,
|
||||
compileGroup: 'standard',
|
||||
},
|
||||
owner: {
|
||||
_id: 'member_author',
|
||||
email: 'project-owner@example.com',
|
||||
},
|
||||
members: [],
|
||||
|
@ -623,6 +625,7 @@ describe('<ShareProjectModal/>', function () {
|
|||
publicAccesLevel: 'tokenBased',
|
||||
features: {
|
||||
collaborators: 0,
|
||||
compileGroup: 'standard',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -9,6 +9,7 @@ import { LayoutProvider } from '../../../frontend/js/shared/context/layout-conte
|
|||
import { ChatProvider } from '../../../frontend/js/features/chat/context/chat-context'
|
||||
import { IdeProvider } from '../../../frontend/js/shared/context/ide-context'
|
||||
import { get } from 'lodash'
|
||||
import { ProjectProvider } from '../../../frontend/js/shared/context/project-context'
|
||||
|
||||
export function EditorProviders({
|
||||
user = { id: '123abd' },
|
||||
|
@ -28,8 +29,11 @@ export function EditorProviders({
|
|||
|
||||
const $scope = {
|
||||
project: {
|
||||
_id: window.project_id,
|
||||
name: 'project-name',
|
||||
owner: {
|
||||
_id: '124abd',
|
||||
email: 'owner@example.com',
|
||||
},
|
||||
},
|
||||
ui: {
|
||||
|
@ -50,9 +54,11 @@ export function EditorProviders({
|
|||
return (
|
||||
<ApplicationProvider>
|
||||
<IdeProvider ide={window._ide}>
|
||||
<EditorProvider settings={{}}>
|
||||
<LayoutProvider>{children}</LayoutProvider>
|
||||
</EditorProvider>
|
||||
<ProjectProvider>
|
||||
<EditorProvider settings={{}}>
|
||||
<LayoutProvider>{children}</LayoutProvider>
|
||||
</EditorProvider>
|
||||
</ProjectProvider>
|
||||
</IdeProvider>
|
||||
</ApplicationProvider>
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue