mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
[ReactNavToolbar] Project name + pdf and share project buttons (#3709)
* Added project name, pdf toggle and share project buttons to navigation toolbar * Added PropTypes check to `useChatContext()` * React context updates for project name/rename, pdf view and share moda * Hide PDF button when pdfLayout != 'flat' GitOrigin-RevId: 3f4a1b072259df7148d3417cd22116702bdd79ac
This commit is contained in:
parent
c3a6ac320b
commit
a555f0d309
16 changed files with 328 additions and 47 deletions
|
@ -1,6 +1,7 @@
|
|||
div(ng-controller="EditorNavigationToolbarController")
|
||||
|
||||
editor-navigation-toolbar-root(
|
||||
open-doc="openDoc"
|
||||
online-users-array="onlineUsersArray"
|
||||
)
|
||||
div(ng-controller="ShareController")
|
||||
div(ng-controller="EditorNavigationToolbarController")
|
||||
editor-navigation-toolbar-root(
|
||||
open-doc="openDoc"
|
||||
online-users-array="onlineUsersArray"
|
||||
open-share-project-modal="openShareProjectModal"
|
||||
)
|
|
@ -109,6 +109,7 @@
|
|||
"run_syntax_check_now": "",
|
||||
"send_first_message": "",
|
||||
"server_error": "",
|
||||
"share": "",
|
||||
"show_outline": "",
|
||||
"something_went_wrong_rendering_pdf": "",
|
||||
"somthing_went_wrong_compiling": "",
|
||||
|
|
|
@ -113,6 +113,8 @@ ChatProvider.propTypes = {
|
|||
children: PropTypes.any
|
||||
}
|
||||
|
||||
export function useChatContext() {
|
||||
return useContext(ChatContext)
|
||||
export function useChatContext(propTypes) {
|
||||
const data = useContext(ChatContext)
|
||||
PropTypes.checkPropTypes(propTypes, data, 'data', 'ChatContext.Provider')
|
||||
return data
|
||||
}
|
||||
|
|
|
@ -8,7 +8,10 @@ import { useLayoutContext } from '../../../shared/context/layout-context'
|
|||
const editorContextPropTypes = {
|
||||
cobranding: PropTypes.object,
|
||||
loading: PropTypes.bool,
|
||||
isRestrictedTokenMember: PropTypes.bool
|
||||
isRestrictedTokenMember: PropTypes.bool,
|
||||
projectName: PropTypes.string.isRequired,
|
||||
renameProject: PropTypes.func.isRequired,
|
||||
isProjectOwner: PropTypes.bool
|
||||
}
|
||||
|
||||
const layoutContextPropTypes = {
|
||||
|
@ -18,13 +21,28 @@ const layoutContextPropTypes = {
|
|||
setReviewPanelOpen: PropTypes.func.isRequired,
|
||||
view: PropTypes.string,
|
||||
setView: PropTypes.func.isRequired,
|
||||
setLeftMenuShown: PropTypes.func.isRequired
|
||||
setLeftMenuShown: PropTypes.func.isRequired,
|
||||
pdfLayout: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
function EditorNavigationToolbarRoot({ onlineUsersArray, openDoc }) {
|
||||
const { cobranding, loading, isRestrictedTokenMember } = useEditorContext(
|
||||
editorContextPropTypes
|
||||
)
|
||||
const chatContextPropTypes = {
|
||||
resetUnreadMessageCount: PropTypes.func.isRequired,
|
||||
unreadMessageCount: PropTypes.number.isRequired
|
||||
}
|
||||
|
||||
function EditorNavigationToolbarRoot({
|
||||
onlineUsersArray,
|
||||
openDoc,
|
||||
openShareProjectModal
|
||||
}) {
|
||||
const {
|
||||
cobranding,
|
||||
loading,
|
||||
isRestrictedTokenMember,
|
||||
projectName,
|
||||
renameProject,
|
||||
isProjectOwner
|
||||
} = useEditorContext(editorContextPropTypes)
|
||||
|
||||
const {
|
||||
chatIsOpen,
|
||||
|
@ -33,10 +51,13 @@ function EditorNavigationToolbarRoot({ onlineUsersArray, openDoc }) {
|
|||
setReviewPanelOpen,
|
||||
view,
|
||||
setView,
|
||||
setLeftMenuShown
|
||||
setLeftMenuShown,
|
||||
pdfLayout
|
||||
} = useLayoutContext(layoutContextPropTypes)
|
||||
|
||||
const { resetUnreadMessageCount, unreadMessageCount } = useChatContext()
|
||||
const { resetUnreadMessageCount, unreadMessageCount } = useChatContext(
|
||||
chatContextPropTypes
|
||||
)
|
||||
|
||||
const toggleChatOpen = useCallback(() => {
|
||||
if (!chatIsOpen) {
|
||||
|
@ -54,6 +75,14 @@ function EditorNavigationToolbarRoot({ onlineUsersArray, openDoc }) {
|
|||
setView(view === 'history' ? 'editor' : 'history')
|
||||
}, [view, setView])
|
||||
|
||||
const togglePdfView = useCallback(() => {
|
||||
setView(view === 'pdf' ? 'editor' : 'pdf')
|
||||
}, [view, setView])
|
||||
|
||||
const openShareModal = useCallback(() => {
|
||||
openShareProjectModal(isProjectOwner)
|
||||
}, [openShareProjectModal, isProjectOwner])
|
||||
|
||||
const onShowLeftMenuClick = useCallback(
|
||||
() => setLeftMenuShown(value => !value),
|
||||
[setLeftMenuShown]
|
||||
|
@ -82,13 +111,20 @@ function EditorNavigationToolbarRoot({ onlineUsersArray, openDoc }) {
|
|||
onlineUsers={onlineUsersArray}
|
||||
goToUser={goToUser}
|
||||
isRestrictedTokenMember={isRestrictedTokenMember}
|
||||
projectName={projectName}
|
||||
renameProject={renameProject}
|
||||
openShareModal={openShareModal}
|
||||
pdfViewIsOpen={view === 'pdf'}
|
||||
pdfButtonIsVisible={pdfLayout === 'flat'}
|
||||
togglePdfView={togglePdfView}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
EditorNavigationToolbarRoot.propTypes = {
|
||||
onlineUsersArray: PropTypes.array.isRequired,
|
||||
openDoc: PropTypes.func.isRequired
|
||||
openDoc: PropTypes.func.isRequired,
|
||||
openShareProjectModal: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
export default EditorNavigationToolbarRoot
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { OverlayTrigger, Tooltip } from 'react-bootstrap'
|
||||
import classNames from 'classnames'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
|
||||
function PdfToggleButton({ onClick, pdfViewIsOpen }) {
|
||||
const classes = classNames(
|
||||
'btn',
|
||||
'btn-full-height',
|
||||
'btn-full-height-no-border',
|
||||
{
|
||||
active: pdfViewIsOpen
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<OverlayTrigger
|
||||
placement="bottom"
|
||||
trigger={['hover', 'focus']}
|
||||
overlay={<Tooltip id="tooltip-online-user">PDF</Tooltip>}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid,jsx-a11y/click-events-have-key-events,jsx-a11y/interactive-supports-focus */}
|
||||
<a role="button" className={classes} onClick={onClick}>
|
||||
<Icon type="file-pdf-o" modifier="fw" />
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
}
|
||||
|
||||
PdfToggleButton.propTypes = {
|
||||
onClick: PropTypes.func.isRequired,
|
||||
pdfViewIsOpen: PropTypes.bool
|
||||
}
|
||||
|
||||
export default PdfToggleButton
|
|
@ -0,0 +1,82 @@
|
|||
import React, { useEffect, useState, useRef } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classNames from 'classnames'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
|
||||
function ProjectNameEditableLabel({
|
||||
projectName,
|
||||
userIsAdmin,
|
||||
onChange,
|
||||
className
|
||||
}) {
|
||||
const [isRenaming, setIsRenaming] = useState(false)
|
||||
|
||||
const canRename = userIsAdmin && !isRenaming
|
||||
|
||||
const [inputContent, setInputContent] = useState(projectName)
|
||||
|
||||
const inputRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (isRenaming) {
|
||||
inputRef.current.select()
|
||||
}
|
||||
}, [isRenaming])
|
||||
|
||||
function startRenaming() {
|
||||
setInputContent(projectName)
|
||||
setIsRenaming(true)
|
||||
}
|
||||
|
||||
function handleKeyDown(event) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault()
|
||||
setIsRenaming(false)
|
||||
onChange(event.target.value)
|
||||
}
|
||||
}
|
||||
|
||||
function handleOnChange(event) {
|
||||
setInputContent(event.target.value)
|
||||
}
|
||||
|
||||
function handleBlur() {
|
||||
setIsRenaming(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames('project-name', className)}>
|
||||
{!isRenaming && (
|
||||
<span className="name" onDoubleClick={startRenaming}>
|
||||
{projectName}
|
||||
</span>
|
||||
)}
|
||||
{isRenaming && (
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
className="form-control"
|
||||
onKeyDown={handleKeyDown}
|
||||
onChange={handleOnChange}
|
||||
onBlur={handleBlur}
|
||||
value={inputContent}
|
||||
/>
|
||||
)}
|
||||
{canRename && (
|
||||
// eslint-disable-next-line jsx-a11y/anchor-is-valid, jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus
|
||||
<a className="rename" role="button" onClick={startRenaming}>
|
||||
<Icon type="pencil" modifier="fw" />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ProjectNameEditableLabel.propTypes = {
|
||||
projectName: PropTypes.string.isRequired,
|
||||
userIsAdmin: PropTypes.bool,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
className: PropTypes.string
|
||||
}
|
||||
|
||||
export default ProjectNameEditableLabel
|
|
@ -0,0 +1,22 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
|
||||
function ShareProjectButton({ onClick }) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
// eslint-disable-next-line jsx-a11y/anchor-is-valid,jsx-a11y/click-events-have-key-events,jsx-a11y/interactive-supports-focus
|
||||
<a role="button" className="btn btn-full-height" onClick={onClick}>
|
||||
<Icon type="fw" modifier="group" />
|
||||
<p className="toolbar-label">{t('share')}</p>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
ShareProjectButton.propTypes = {
|
||||
onClick: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
export default ShareProjectButton
|
|
@ -5,8 +5,11 @@ import CobrandingLogo from './cobranding-logo'
|
|||
import BackToProjectsButton from './back-to-projects-button'
|
||||
import ChatToggleButton from './chat-toggle-button'
|
||||
import OnlineUsersWidget from './online-users-widget'
|
||||
import ProjectNameEditableLabel from './project-name-editable-label'
|
||||
import TrackChangesToggleButton from './track-changes-toggle-button'
|
||||
import HistoryToggleButton from './history-toggle-button'
|
||||
import ShareProjectButton from './share-project-button'
|
||||
import PdfToggleButton from './pdf-toggle-button'
|
||||
|
||||
function ToolbarHeader({
|
||||
cobranding,
|
||||
|
@ -20,7 +23,13 @@ function ToolbarHeader({
|
|||
unreadMessageCount,
|
||||
onlineUsers,
|
||||
goToUser,
|
||||
isRestrictedTokenMember
|
||||
isRestrictedTokenMember,
|
||||
projectName,
|
||||
renameProject,
|
||||
openShareModal,
|
||||
pdfViewIsOpen,
|
||||
pdfButtonIsVisible,
|
||||
togglePdfView
|
||||
}) {
|
||||
return (
|
||||
<header className="toolbar toolbar-header toolbar-with-labels">
|
||||
|
@ -29,8 +38,22 @@ function ToolbarHeader({
|
|||
{cobranding ? <CobrandingLogo {...cobranding} /> : null}
|
||||
<BackToProjectsButton />
|
||||
</div>
|
||||
{pdfButtonIsVisible && (
|
||||
<PdfToggleButton
|
||||
onClick={togglePdfView}
|
||||
pdfViewIsOpen={pdfViewIsOpen}
|
||||
/>
|
||||
)}
|
||||
<ProjectNameEditableLabel
|
||||
className="toolbar-center"
|
||||
projectName={projectName}
|
||||
userIsAdmin
|
||||
onChange={renameProject}
|
||||
/>
|
||||
|
||||
<div className="toolbar-right">
|
||||
<OnlineUsersWidget onlineUsers={onlineUsers} goToUser={goToUser} />
|
||||
<ShareProjectButton onClick={openShareModal} />
|
||||
{!isRestrictedTokenMember && (
|
||||
<>
|
||||
<TrackChangesToggleButton
|
||||
|
@ -66,7 +89,13 @@ ToolbarHeader.propTypes = {
|
|||
unreadMessageCount: PropTypes.number.isRequired,
|
||||
onlineUsers: PropTypes.array.isRequired,
|
||||
goToUser: PropTypes.func.isRequired,
|
||||
isRestrictedTokenMember: PropTypes.bool
|
||||
isRestrictedTokenMember: PropTypes.bool,
|
||||
projectName: PropTypes.string.isRequired,
|
||||
renameProject: PropTypes.func.isRequired,
|
||||
openShareModal: PropTypes.func.isRequired,
|
||||
pdfViewIsOpen: PropTypes.bool,
|
||||
pdfButtonIsVisible: PropTypes.bool,
|
||||
togglePdfView: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
export default ToolbarHeader
|
||||
|
|
|
@ -16,6 +16,11 @@ App.component(
|
|||
// `$scope.onlineUsersArray` is already populated by `OnlineUsersManager`, which also creates
|
||||
// a new array instance every time the list of online users change (which should refresh the
|
||||
// value passed to React as a prop, triggering a re-render)
|
||||
'onlineUsersArray'
|
||||
'onlineUsersArray',
|
||||
|
||||
// We're still including ShareController as part fo the React navigation toolbar. The reason is
|
||||
// the coupling between ShareController's $scope and Angular's ShareProjectModal. Once ShareProjectModal
|
||||
// is fully ported to React we should be able to repli
|
||||
'openShareProjectModal'
|
||||
])
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@ let titleIsFlashing = false
|
|||
let originalTitle
|
||||
let flashIntervalHandle
|
||||
|
||||
export function flashTitle(message) {
|
||||
function flashTitle(message) {
|
||||
if (document.hasFocus() || titleIsFlashing) {
|
||||
return
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export function flashTitle(message) {
|
|||
flashIntervalHandle = setInterval(swapTitle, 800)
|
||||
}
|
||||
|
||||
export function stopFlashingTitle() {
|
||||
function stopFlashingTitle() {
|
||||
if (!titleIsFlashing) {
|
||||
return
|
||||
}
|
||||
|
@ -34,6 +34,14 @@ export function stopFlashingTitle() {
|
|||
titleIsFlashing = false
|
||||
}
|
||||
|
||||
function setTitle(title) {
|
||||
if (titleIsFlashing) {
|
||||
originalTitle = title
|
||||
} else {
|
||||
window.document.title = title
|
||||
}
|
||||
}
|
||||
|
||||
function useBrowserWindow() {
|
||||
const [hasFocus, setHasFocus] = useState(document.hasFocus())
|
||||
|
||||
|
@ -54,7 +62,7 @@ function useBrowserWindow() {
|
|||
}
|
||||
}, [])
|
||||
|
||||
return { hasFocus, flashTitle, stopFlashingTitle }
|
||||
return { hasFocus, flashTitle, stopFlashingTitle, setTitle }
|
||||
}
|
||||
|
||||
export default useBrowserWindow
|
||||
|
|
|
@ -4,5 +4,5 @@ import { rootContext } from '../root-context'
|
|||
|
||||
App.component(
|
||||
'sharedContextReact',
|
||||
react2angular(rootContext.component, [], ['ide'])
|
||||
react2angular(rootContext.component, [], ['ide', 'settings'])
|
||||
)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import React, { createContext, useContext } from 'react'
|
||||
import React, { createContext, useCallback, useContext } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import useScopeValue from './util/scope-value-hook'
|
||||
import { useApplicationContext } from './application-context'
|
||||
import useBrowserWindow from '../../infrastructure/browser-window-hook'
|
||||
|
||||
export const EditorContext = createContext()
|
||||
|
||||
|
@ -13,12 +15,21 @@ EditorContext.Provider.propTypes = {
|
|||
}),
|
||||
loading: PropTypes.bool,
|
||||
projectId: PropTypes.string.isRequired,
|
||||
projectName: PropTypes.string.isRequired,
|
||||
renameProject: PropTypes.func.isRequired,
|
||||
isProjectOwner: PropTypes.bool,
|
||||
isRestrictedTokenMember: PropTypes.bool
|
||||
})
|
||||
}
|
||||
|
||||
export function EditorProvider({ children, $scope }) {
|
||||
export function EditorProvider({ children, ide, settings }) {
|
||||
const {
|
||||
exposedSettings: { appName }
|
||||
} = useApplicationContext({
|
||||
exposedSettings: PropTypes.shape({ appName: PropTypes.string.isRequired })
|
||||
.isRequired
|
||||
})
|
||||
|
||||
const cobranding = window.brandVariation
|
||||
? {
|
||||
logoImgUrl: window.brandVariation.logo_url,
|
||||
|
@ -28,30 +39,68 @@ export function EditorProvider({ children, $scope }) {
|
|||
: undefined
|
||||
|
||||
const ownerId =
|
||||
window._ide.$scope.project && window._ide.$scope.project.owner
|
||||
? window._ide.$scope.project.owner._id
|
||||
ide.$scope.project && ide.$scope.project.owner
|
||||
? ide.$scope.project.owner._id
|
||||
: null
|
||||
|
||||
const [loading] = useScopeValue('state.loading', $scope)
|
||||
const [loading] = useScopeValue('state.loading', ide.$scope)
|
||||
|
||||
const [projectName, setProjectName] = useScopeValue(
|
||||
'project.name',
|
||||
ide.$scope
|
||||
)
|
||||
|
||||
const renameProject = useCallback(
|
||||
newName => {
|
||||
setProjectName(oldName => {
|
||||
if (oldName !== newName) {
|
||||
settings.saveProjectSettings({ name: newName }).catch(response => {
|
||||
setProjectName(oldName)
|
||||
const { data, status } = response
|
||||
if (status === 400) {
|
||||
return ide.showGenericMessageModal('Error renaming project', data)
|
||||
} else {
|
||||
return ide.showGenericMessageModal(
|
||||
'Error renaming project',
|
||||
'Please try again in a moment'
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
return newName
|
||||
})
|
||||
},
|
||||
[settings, ide, setProjectName]
|
||||
)
|
||||
|
||||
const { setTitle } = useBrowserWindow()
|
||||
setTitle(
|
||||
`${projectName ? projectName + ' - ' : ''}Online LaTeX Editor ${appName}`
|
||||
)
|
||||
|
||||
const editorContextValue = {
|
||||
cobranding,
|
||||
loading,
|
||||
projectId: window.project_id,
|
||||
projectName: projectName || '', // initially might be empty in Angular
|
||||
renameProject,
|
||||
isProjectOwner: ownerId === window.user.id,
|
||||
isRestrictedTokenMember: window.isRestrictedTokenMember
|
||||
}
|
||||
|
||||
return (
|
||||
<EditorContext.Provider value={editorContextValue}>
|
||||
{children}
|
||||
</EditorContext.Provider>
|
||||
<>
|
||||
<EditorContext.Provider value={editorContextValue}>
|
||||
{children}
|
||||
</EditorContext.Provider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
EditorProvider.propTypes = {
|
||||
children: PropTypes.any,
|
||||
$scope: PropTypes.any.isRequired
|
||||
ide: PropTypes.any.isRequired,
|
||||
settings: PropTypes.any.isRequired
|
||||
}
|
||||
|
||||
export function useEditorContext(propTypes) {
|
||||
|
|
|
@ -13,7 +13,8 @@ LayoutContext.Provider.propTypes = {
|
|||
reviewPanelOpen: PropTypes.bool,
|
||||
setReviewPanelOpen: PropTypes.func.isRequired,
|
||||
leftMenuShown: PropTypes.bool,
|
||||
setLeftMenuShown: PropTypes.func.isRequired
|
||||
setLeftMenuShown: PropTypes.func.isRequired,
|
||||
pdfLayout: PropTypes.oneOf(['sideBySide', 'flat', 'split']).isRequired
|
||||
}).isRequired
|
||||
}
|
||||
|
||||
|
@ -29,6 +30,8 @@ export function LayoutProvider({ children, $scope }) {
|
|||
$scope
|
||||
)
|
||||
|
||||
const [pdfLayout] = useScopeValue('ui.pdfLayout', $scope)
|
||||
|
||||
const layoutContextValue = {
|
||||
view,
|
||||
setView,
|
||||
|
@ -37,7 +40,8 @@ export function LayoutProvider({ children, $scope }) {
|
|||
reviewPanelOpen,
|
||||
setReviewPanelOpen,
|
||||
leftMenuShown,
|
||||
setLeftMenuShown
|
||||
setLeftMenuShown,
|
||||
pdfLayout
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -6,10 +6,10 @@ import createSharedContext from 'react2angular-shared-context'
|
|||
import { ChatProvider } from '../../features/chat/context/chat-context'
|
||||
import { LayoutProvider } from './layout-context'
|
||||
|
||||
export function ContextRoot({ children, ide }) {
|
||||
export function ContextRoot({ children, ide, settings }) {
|
||||
return (
|
||||
<ApplicationProvider>
|
||||
<EditorProvider $scope={ide.$scope}>
|
||||
<EditorProvider ide={ide} settings={settings}>
|
||||
<LayoutProvider $scope={ide.$scope}>
|
||||
<ChatProvider>{children}</ChatProvider>
|
||||
</LayoutProvider>
|
||||
|
@ -20,7 +20,8 @@ export function ContextRoot({ children, ide }) {
|
|||
|
||||
ContextRoot.propTypes = {
|
||||
children: PropTypes.any,
|
||||
ide: PropTypes.any.isRequired
|
||||
ide: PropTypes.any.isRequired,
|
||||
settings: PropTypes.any.isRequired
|
||||
}
|
||||
|
||||
export const rootContext = createSharedContext(ContextRoot)
|
||||
|
|
|
@ -29,11 +29,18 @@ export default {
|
|||
title: 'EditorNavigationToolbar',
|
||||
component: ToolbarHeader,
|
||||
argTypes: {
|
||||
goToUser: { action: 'goToUser' }
|
||||
goToUser: { action: 'goToUser' },
|
||||
renameProject: { action: 'renameProject' },
|
||||
toggleHistoryOpen: { action: 'toggleHistoryOpen' },
|
||||
toggleReviewPanelOpen: { action: 'toggleReviewPanelOpen' },
|
||||
toggleChatOpen: { action: 'toggleChatOpen' },
|
||||
togglePdfView: { action: 'togglePdfView' },
|
||||
openShareModal: { action: 'openShareModal' },
|
||||
onShowLeftMenuClick: { action: 'onShowLeftMenuClick' }
|
||||
},
|
||||
args: {
|
||||
projectName: 'Overleaf Project',
|
||||
onlineUsers: [{ user_id: 'abc', name: 'overleaf' }],
|
||||
goToUser: () => {},
|
||||
onShowLeftMenuClick: () => {}
|
||||
unreadMessageCount: 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ export function renderWithEditorContext(
|
|||
{ user = { id: '123abd' }, projectId = 'project123' } = {}
|
||||
) {
|
||||
window.user = user || window.user
|
||||
window.ExposedSettings.appName = 'test'
|
||||
window.project_id = projectId != null ? projectId : window.project_id
|
||||
window._ide = {
|
||||
$scope: {
|
||||
|
@ -20,7 +21,8 @@ export function renderWithEditorContext(
|
|||
}
|
||||
},
|
||||
ui: {
|
||||
chatOpen: true
|
||||
chatOpen: true,
|
||||
pdfLayout: 'flat'
|
||||
},
|
||||
$watch: () => {}
|
||||
},
|
||||
|
@ -31,11 +33,7 @@ export function renderWithEditorContext(
|
|||
}
|
||||
return render(
|
||||
<ApplicationProvider>
|
||||
<EditorProvider
|
||||
openDoc={() => {}}
|
||||
onlineUsersArray={[]}
|
||||
$scope={window._ide.$scope}
|
||||
>
|
||||
<EditorProvider ide={window._ide} settings={{}}>
|
||||
<LayoutProvider $scope={window._ide.$scope}>{children}</LayoutProvider>
|
||||
</EditorProvider>
|
||||
</ApplicationProvider>
|
||||
|
|
Loading…
Reference in a new issue