| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- import React, {
- createContext,
- useCallback,
- useContext,
- useEffect,
- useState,
- } from 'react'
- import PropTypes from 'prop-types'
- import ShareProjectModalContent from './share-project-modal-content'
- import useScopeValue from '../../../shared/context/util/scope-value-hook'
- const ShareProjectContext = createContext()
- ShareProjectContext.Provider.propTypes = {
- value: PropTypes.shape({
- isAdmin: PropTypes.bool.isRequired,
- updateProject: PropTypes.func.isRequired,
- monitorRequest: PropTypes.func.isRequired,
- inFlight: PropTypes.bool,
- setInFlight: PropTypes.func,
- error: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
- setError: PropTypes.func,
- }),
- }
- export function useShareProjectContext() {
- const context = useContext(ShareProjectContext)
- if (!context) {
- throw new Error(
- 'useShareProjectContext is only available inside ShareProjectProvider'
- )
- }
- return context
- }
- const projectShape = PropTypes.shape({
- _id: PropTypes.string.isRequired,
- members: PropTypes.arrayOf(
- PropTypes.shape({
- _id: PropTypes.string.isRequired,
- })
- ),
- invites: PropTypes.arrayOf(
- PropTypes.shape({
- _id: PropTypes.string.isRequired,
- })
- ),
- name: PropTypes.string,
- features: PropTypes.shape({
- collaborators: PropTypes.number,
- }),
- publicAccesLevel: PropTypes.string,
- tokens: PropTypes.shape({
- readOnly: PropTypes.string,
- readAndWrite: PropTypes.string,
- }),
- 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
- }
- export default function ShareProjectModal({
- handleHide,
- show,
- animation = true,
- isAdmin,
- ide,
- }) {
- const [inFlight, setInFlight] = useState(false)
- const [error, setError] = useState()
- const [project, setProject] = useScopeValue('project', ide.$scope, true)
- // reset error when the modal is opened
- useEffect(() => {
- if (show) {
- setError(undefined)
- }
- }, [show])
- // close the modal if not in flight
- const cancel = useCallback(() => {
- if (!inFlight) {
- handleHide()
- }
- }, [handleHide, inFlight])
- // update `error` and `inFlight` while sending a request
- const monitorRequest = useCallback(request => {
- setError(undefined)
- setInFlight(true)
- const promise = request()
- promise.catch(error => {
- setError(
- error.data?.errorReason ||
- error.data?.error ||
- 'generic_something_went_wrong'
- )
- })
- promise.finally(() => {
- setInFlight(false)
- })
- return promise
- }, [])
- // merge the new data with the old project data
- const updateProject = useCallback(
- data => {
- setProject(project => Object.assign(project, data))
- },
- [setProject]
- )
- if (!project) {
- return null
- }
- return (
- <ShareProjectContext.Provider
- value={{
- isAdmin,
- updateProject,
- monitorRequest,
- inFlight,
- setInFlight,
- error,
- setError,
- }}
- >
- <ProjectContext.Provider value={project}>
- <ShareProjectModalContent
- animation={animation}
- cancel={cancel}
- error={error}
- inFlight={inFlight}
- show={show}
- />
- </ProjectContext.Provider>
- </ShareProjectContext.Provider>
- )
- }
- ShareProjectModal.propTypes = {
- animation: PropTypes.bool,
- handleHide: PropTypes.func.isRequired,
- isAdmin: PropTypes.bool.isRequired,
- ide: PropTypes.shape({
- $scope: PropTypes.object.isRequired,
- }).isRequired,
- show: PropTypes.bool.isRequired,
- }
|