Merge pull request #3977 from overleaf/as-file-tree-application-context

Pull user id from ApplicationContext instead of window in file tree

GitOrigin-RevId: e6c037b4a46ecdca066bcb5c67f6eeb8834f11fd
This commit is contained in:
Alf Eaton 2021-05-12 11:31:18 +01:00 committed by Copybot
parent 0026e9d246
commit 7d3b989d74
8 changed files with 88 additions and 47 deletions

View file

@ -3,6 +3,7 @@ import { react2angular } from 'react2angular'
import { cloneDeep } from 'lodash'
import FileTreeRoot from '../components/file-tree-root'
import { rootContext } from '../../../shared/context/root-context'
App.controller('ReactFileTreeController', function (
$scope,
@ -115,4 +116,10 @@ App.controller('ReactFileTreeController', function (
}
})
App.component('fileTreeRoot', react2angular(FileTreeRoot))
App.component(
'fileTreeRoot',
react2angular(
rootContext.use(FileTreeRoot),
Object.keys(FileTreeRoot.propTypes)
)
)

View file

@ -1,10 +1,15 @@
import { useCallback, useEffect } from 'react'
import PropTypes from 'prop-types'
import { useApplicationContext } from '../../../shared/context/application-context'
import { useFileTreeMutable } from '../contexts/file-tree-mutable'
import { useFileTreeSelectable } from '../contexts/file-tree-selectable'
import { findInTreeOrThrow } from '../util/find-in-tree'
export function useFileTreeSocketListener() {
const { user } = useApplicationContext({
user: PropTypes.shape({ id: PropTypes.string.isRequired }),
})
const {
dispatchRename,
dispatchDelete,
@ -25,14 +30,17 @@ export function useFileTreeSocketListener() {
const selectEntityIfCreatedByUser = useCallback(
// hack to automatically re-open refreshed linked files
(entityId, entityName, userId) => {
if (window.user && window.user.id && window.user.id === userId) {
// If the created entity's user exists and is the current user
if (userId && user?.id === userId) {
// And we're expecting a refreshed socket for this entity
if (window.expectingLinkedFileRefreshedSocketFor === entityName) {
// Then select it
select(entityId)
window.expectingLinkedFileRefreshedSocketFor = null
}
}
},
[select]
[user, select]
)
useEffect(() => {

View file

@ -1,6 +1,7 @@
import React from 'react'
import MockedSocket from 'socket.io-mock'
import { ContextRoot } from '../js/shared/context/root-context'
import { rootFolderBase } from './fixtures/file-tree-base'
import { rootFolderLimit } from './fixtures/file-tree-limit'
import FileTreeRoot from '../js/features/file-tree/components/file-tree-root'
@ -149,7 +150,9 @@ export default {
<style>{'html, body, .file-tree { height: 100%; width: 100%; }'}</style>
<div className="editor-sidebar full-size">
<div className="file-tree">
<Story />
<ContextRoot ide={window._ide} settings={{}}>
<Story />
</ContextRoot>
</div>
</div>
</>

View file

@ -1,9 +1,13 @@
import { expect } from 'chai'
import React from 'react'
import sinon from 'sinon'
import { screen, render, fireEvent, waitFor } from '@testing-library/react'
import { screen, fireEvent, waitFor } from '@testing-library/react'
import fetchMock from 'fetch-mock'
import {
renderWithEditorContext,
cleanUpContext,
} from '../../../helpers/render-with-context'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('<FileTreeRoot/>', function () {
@ -19,6 +23,7 @@ describe('<FileTreeRoot/>', function () {
fetchMock.restore()
onSelect.reset()
onInit.reset()
cleanUpContext()
global.localStorage.clear()
})
@ -31,7 +36,7 @@ describe('<FileTreeRoot/>', function () {
fileRefs: [],
},
]
const { container } = render(
const { container } = renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -67,7 +72,7 @@ describe('<FileTreeRoot/>', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -106,7 +111,7 @@ describe('<FileTreeRoot/>', function () {
},
]
const { container } = render(
const { container } = renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -138,7 +143,7 @@ describe('<FileTreeRoot/>', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -191,7 +196,7 @@ describe('<FileTreeRoot/>', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"

View file

@ -1,14 +1,24 @@
import { expect } from 'chai'
import React from 'react'
import sinon from 'sinon'
import { screen, render, fireEvent } from '@testing-library/react'
import { screen, fireEvent } from '@testing-library/react'
import {
renderWithEditorContext,
cleanUpContext,
} from '../../../helpers/render-with-context'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('FileTree Context Menu Flow', function () {
const onSelect = sinon.stub()
const onInit = sinon.stub()
afterEach(function () {
onSelect.reset()
onInit.reset()
cleanUpContext()
})
it('opens on contextMenu event', async function () {
const rootFolder = [
{
@ -18,7 +28,7 @@ describe('FileTree Context Menu Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -52,7 +62,7 @@ describe('FileTree Context Menu Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"

View file

@ -1,10 +1,14 @@
import { expect } from 'chai'
import React from 'react'
import sinon from 'sinon'
import { screen, render, fireEvent, waitFor } from '@testing-library/react'
import { screen, fireEvent, waitFor } from '@testing-library/react'
import fetchMock from 'fetch-mock'
import MockedSocket from 'socket.io-mock'
import {
renderWithEditorContext,
cleanUpContext,
} from '../../../helpers/render-with-context'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('FileTree Create Folder Flow', function () {
@ -13,9 +17,6 @@ describe('FileTree Create Folder Flow', function () {
beforeEach(function () {
global.requestAnimationFrame = sinon.stub()
window._ide = {
socket: new MockedSocket(),
}
})
afterEach(function () {
@ -23,7 +24,7 @@ describe('FileTree Create Folder Flow', function () {
fetchMock.restore()
onSelect.reset()
onInit.reset()
delete window._ide
cleanUpContext()
})
it('add to root when no files are selected', async function () {
@ -35,7 +36,7 @@ describe('FileTree Create Folder Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -48,7 +49,8 @@ describe('FileTree Create Folder Flow', function () {
onSelect={onSelect}
onInit={onInit}
isConnected
/>
/>,
{ socket: new MockedSocket() }
)
const newFolderName = 'Foo Bar In Root'
@ -95,7 +97,7 @@ describe('FileTree Create Folder Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -109,7 +111,8 @@ describe('FileTree Create Folder Flow', function () {
onSelect={onSelect}
onInit={onInit}
isConnected
/>
/>,
{ socket: new MockedSocket() }
)
const expandButton = screen.getByRole('button', { name: 'Expand' })
@ -165,7 +168,7 @@ describe('FileTree Create Folder Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -179,7 +182,8 @@ describe('FileTree Create Folder Flow', function () {
onSelect={onSelect}
onInit={onInit}
isConnected
/>
/>,
{ socket: new MockedSocket() }
)
const newFolderName = 'Foo Bar In thefolder'
@ -224,7 +228,7 @@ describe('FileTree Create Folder Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -238,7 +242,8 @@ describe('FileTree Create Folder Flow', function () {
onSelect={onSelect}
onInit={onInit}
isConnected
/>
/>,
{ socket: new MockedSocket() }
)
var newFolderName = 'existingFile'

View file

@ -1,27 +1,25 @@
import { expect } from 'chai'
import React from 'react'
import sinon from 'sinon'
import { screen, render, fireEvent, waitFor } from '@testing-library/react'
import { screen, fireEvent, waitFor } from '@testing-library/react'
import fetchMock from 'fetch-mock'
import MockedSocket from 'socket.io-mock'
import {
renderWithEditorContext,
cleanUpContext,
} from '../../../helpers/render-with-context'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('FileTree Delete Entity Flow', function () {
const onSelect = sinon.stub()
const onInit = sinon.stub()
beforeEach(function () {
window._ide = {
socket: new MockedSocket(),
}
})
afterEach(function () {
fetchMock.restore()
onSelect.reset()
onInit.reset()
delete window._ide
cleanUpContext()
})
describe('single entity', function () {
@ -34,7 +32,7 @@ describe('FileTree Delete Entity Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -47,7 +45,8 @@ describe('FileTree Delete Entity Flow', function () {
onSelect={onSelect}
onInit={onInit}
isConnected
/>
/>,
{ socket: new MockedSocket() }
)
const treeitem = screen.getByRole('treeitem', { name: 'main.tex' })
@ -151,7 +150,7 @@ describe('FileTree Delete Entity Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -164,7 +163,8 @@ describe('FileTree Delete Entity Flow', function () {
onSelect={onSelect}
onInit={onInit}
isConnected
/>
/>,
{ socket: new MockedSocket() }
)
const expandButton = screen.queryByRole('button', { name: 'Expand' })
@ -208,7 +208,7 @@ describe('FileTree Delete Entity Flow', function () {
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -221,7 +221,8 @@ describe('FileTree Delete Entity Flow', function () {
onSelect={onSelect}
onInit={onInit}
isConnected
/>
/>,
{ socket: new MockedSocket() }
)
// select two files

View file

@ -1,10 +1,14 @@
import { expect } from 'chai'
import React from 'react'
import sinon from 'sinon'
import { screen, render, fireEvent } from '@testing-library/react'
import { screen, fireEvent } from '@testing-library/react'
import fetchMock from 'fetch-mock'
import MockedSocket from 'socket.io-mock'
import {
renderWithEditorContext,
cleanUpContext,
} from '../../../helpers/render-with-context'
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
describe('FileTree Rename Entity Flow', function () {
@ -12,9 +16,6 @@ describe('FileTree Rename Entity Flow', function () {
const onInit = sinon.stub()
beforeEach(function () {
window._ide = {
socket: new MockedSocket(),
}
global.requestAnimationFrame = sinon.stub()
})
@ -23,7 +24,7 @@ describe('FileTree Rename Entity Flow', function () {
fetchMock.restore()
onSelect.reset()
onInit.reset()
delete window._ide
cleanUpContext()
})
beforeEach(function () {
@ -46,7 +47,7 @@ describe('FileTree Rename Entity Flow', function () {
fileRefs: [],
},
]
render(
renderWithEditorContext(
<FileTreeRoot
rootFolder={rootFolder}
projectId="123abc"
@ -59,7 +60,8 @@ describe('FileTree Rename Entity Flow', function () {
onSelect={onSelect}
onInit={onInit}
isConnected
/>
/>,
{ socket: new MockedSocket() }
)
})