Merge pull request #18898 from overleaf/jpa-no-window

[web] migrate from window attributes to getMeta

GitOrigin-RevId: 3dcf1ab6b01155e5e4abeb3e78d0fa9053e055bc
This commit is contained in:
Jakob Ackermann 2024-06-18 12:01:37 +02:00 committed by Copybot
parent 9b1c703f6b
commit aa480a2663
240 changed files with 1089 additions and 1126 deletions

View file

@ -195,9 +195,6 @@ module.exports = {
$: true,
angular: true,
ga: true,
// Injected in layout.pug
user_id: true,
ExposedSettings: true,
},
rules: {
// TODO: remove once https://github.com/standard/eslint-config-standard-react/issues/68 (support eslint@8) is fixed.

View file

@ -9,11 +9,82 @@ import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
// @ts-ignore
import en from '../../../services/web/locales/en.json'
import { ExposedSettings } from '../types/exposed-settings'
import { User } from '../types/user'
window.i18n = window.i18n || {}
window.i18n.currentLangCode = window.i18n.currentLangCode || 'en'
function resetMeta() {
window.metaAttributesCache = new Map()
window.metaAttributesCache.set('ol-i18n', { currentLangCode: 'en' })
window.metaAttributesCache.set('ol-ExposedSettings', {
adminEmail: 'placeholder@example.com',
appName: 'Overleaf',
cookieDomain: '.overleaf.stories',
dropboxAppName: 'Overleaf-Stories',
emailConfirmationDisabled: false,
enableSubscriptions: true,
hasAffiliationsFeature: false,
hasLinkUrlFeature: true,
hasLinkedProjectFileFeature: true,
hasLinkedProjectOutputFileFeature: true,
hasSamlFeature: true,
ieeeBrandId: 15,
isOverleaf: true,
labsEnabled: true,
maxEntitiesPerProject: 10,
maxUploadSize: 5 * 1024 * 1024,
recaptchaDisabled: {
invite: true,
login: true,
passwordReset: true,
register: true,
addEmail: true,
},
sentryAllowedOriginRegex: '',
siteUrl: 'http://localhost',
templateLinks: [],
textExtensions: [
'tex',
'latex',
'sty',
'cls',
'bst',
'bib',
'bibtex',
'txt',
'tikz',
'mtx',
'rtex',
'md',
'asy',
'lbx',
'bbx',
'cbx',
'm',
'lco',
'dtx',
'ins',
'ist',
'def',
'clo',
'ldf',
'rmd',
'lua',
'gv',
'mf',
'lhs',
'mk',
'xmpdata',
'cfg',
'rnw',
'ltx',
'inc',
],
editableFilenames: ['latexmkrc', '.latexmkrc', 'makefile', 'gnumakefile'],
validRootDocExtensions: ['tex', 'Rtex', 'ltx', 'Rnw'],
fileIgnorePattern:
'**/{{__MACOSX,.git,.texpadtmp,.R}{,/**},.!(latexmkrc),*.{dvi,aux,log,toc,out,pdfsync,synctex,synctex(busy),fdb_latexmk,fls,nlo,ind,glo,gls,glg,bbl,blg,doc,docx,gz,swp}}',
projectUploadTimeout: 12000,
})
}
i18n.use(initReactI18next).init({
lng: 'en',
@ -41,10 +112,6 @@ i18n.use(initReactI18next).init({
},
})
// avoid some errors by creating these objects in advance
window.user = {} as User
window.ExposedSettings = {} as ExposedSettings
const preview: Preview = {
parameters: {
// Automatically mark prop-types like onClick, onToggle, etc as Storybook
@ -98,6 +165,8 @@ const preview: Preview = {
? bootstrap5Style
: bootstrap3Style
resetMeta()
return (
<>
{activeStyle && <style>{activeStyle.default}</style>}
@ -109,3 +178,6 @@ const preview: Preview = {
}
export default preview
// Populate meta for top-level access in modules on import
resetMeta()

View file

@ -18,6 +18,10 @@ const {
const {
addOptionalCleanupHandlerAfterDrainingConnections,
} = require('./GracefulShutdown')
const { expressify } = require('@overleaf/promise-utils')
const {
loadAssignmentsInLocals,
} = require('../Features/SplitTests/SplitTestMiddleware')
const IEEE_BRAND_ID = Settings.ieeeBrandId
@ -76,6 +80,10 @@ function getWebpackAssets(entrypoint, section) {
}
module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
webRouter.use(
expressify(loadAssignmentsInLocals(['remove-window-attributes']))
)
if (process.env.NODE_ENV === 'development') {
// In the dev-env, delay requests until we fetched the manifest once.
webRouter.use(function (req, res, next) {

View file

@ -39,9 +39,6 @@ meta(name="ol-projectTags" data-type="json" content=projectTags)
meta(name="ol-loadingText", data-type="string" content=translate("loading"))
meta(name="ol-translationLoadErrorMessage", data-type="string" content=translate("could_not_load_translations"))
- var fileActionI18n = ['edited', 'renamed', 'created', 'deleted'].reduce((acc, i) => {acc[i] = translate('file_action_' + i); return acc}, {})
meta(name="ol-fileActionI18n" data-type="json" content=fileActionI18n)
if (settings.overleaf != null)
meta(name="ol-overallThemes" data-type="json" content=overallThemes)

View file

@ -1,19 +1,11 @@
import 'cypress-plugin-tab'
import '../../frontend/stylesheets/main-style.less'
import './ct/window' // needs to be before i18n
import { resetMeta } from './ct/window' // needs to be before i18n
import '../../frontend/js/i18n'
import './shared/commands'
import './shared/exceptions'
import './ct/commands'
beforeEach(function () {
cy.window().then(win => {
win.metaAttributesCache = new Map()
})
})
afterEach(function () {
cy.window().then(win => {
win.metaAttributesCache?.clear()
})
resetMeta()
})

View file

@ -1,10 +1,16 @@
window.i18n = { currentLangCode: 'en' }
window.ExposedSettings = {
appName: 'Overleaf',
validRootDocExtensions: ['tex', 'Rtex', 'ltx', 'Rnw'],
fileIgnorePattern:
'**/{{__MACOSX,.git,.texpadtmp,.R}{,/**},.!(latexmkrc),*.{dvi,aux,log,toc,out,pdfsync,synctex,synctex(busy),fdb_latexmk,fls,nlo,ind,glo,gls,glg,bbl,blg,doc,docx,gz,swp}}',
hasLinkedProjectFileFeature: true,
hasLinkedProjectOutputFileFeature: true,
hasLinkUrlFeature: true,
} as typeof window.ExposedSettings
export function resetMeta() {
window.metaAttributesCache = new Map()
window.metaAttributesCache.set('ol-i18n', { currentLangCode: 'en' })
window.metaAttributesCache.set('ol-ExposedSettings', {
appName: 'Overleaf',
validRootDocExtensions: ['tex', 'Rtex', 'ltx', 'Rnw'],
fileIgnorePattern:
'**/{{__MACOSX,.git,.texpadtmp,.R}{,/**},.!(latexmkrc),*.{dvi,aux,log,toc,out,pdfsync,synctex,synctex(busy),fdb_latexmk,fls,nlo,ind,glo,gls,glg,bbl,blg,doc,docx,gz,swp}}',
hasLinkedProjectFileFeature: true,
hasLinkedProjectOutputFileFeature: true,
hasLinkUrlFeature: true,
})
}
// Populate meta for top-level access in modules on import
resetMeta()

View file

@ -1,3 +1,5 @@
import getMeta from '@/utils/meta'
function loadGA() {
if (window.olLoadGA) {
window.olLoadGA()
@ -6,7 +8,7 @@ function loadGA() {
function setConsent(value) {
document.querySelector('.cookie-banner').classList.add('hidden')
const cookieDomain = window.ExposedSettings.cookieDomain
const cookieDomain = getMeta('ol-ExposedSettings').cookieDomain
const oneYearInSeconds = 60 * 60 * 24 * 365
const cookieAttributes =
'; path=/' +
@ -23,7 +25,10 @@ function setConsent(value) {
}
}
if (window.ExposedSettings.gaToken || window.ExposedSettings.gaTokenV4) {
if (
getMeta('ol-ExposedSettings').gaToken ||
getMeta('ol-ExposedSettings').gaTokenV4
) {
document
.querySelectorAll('[data-ol-cookie-banner-set-consent]')
.forEach(el => {

View file

@ -12,9 +12,9 @@ const components = importOverleafModules('editorLeftMenuManageTemplate') as {
export default function ActionsMenu() {
const { t } = useTranslation()
const anonymous = getMeta('ol-anonymous') as boolean | undefined
const anonymous = getMeta('ol-anonymous')
if (anonymous === true || anonymous === undefined) {
if (anonymous) {
return null
}

View file

@ -6,7 +6,7 @@ import HelpShowHotkeys from './help-show-hotkeys'
export default function HelpMenu() {
const { t } = useTranslation()
const showSupport = getMeta('ol-showSupport') as boolean | undefined
const showSupport = getMeta('ol-showSupport')
return (
<>

View file

@ -19,9 +19,9 @@ import SettingsSyntaxValidation from './settings/settings-syntax-validation'
export default function SettingsMenu() {
const { t } = useTranslation()
const anonymous = getMeta('ol-anonymous') as boolean | undefined
const anonymous = getMeta('ol-anonymous')
if (anonymous === true || anonymous === undefined) {
if (anonymous) {
return null
}

View file

@ -7,10 +7,8 @@ import type { Option } from './settings-menu-select'
export default function SettingsEditorTheme() {
const { t } = useTranslation()
const editorThemes = getMeta('ol-editorThemes') as string[] | undefined
const legacyEditorThemes = getMeta('ol-legacyEditorThemes') as
| string[]
| undefined
const editorThemes = getMeta('ol-editorThemes')
const legacyEditorThemes = getMeta('ol-legacyEditorThemes')
const { editorTheme, setEditorTheme } = useProjectSettingsContext()
const options = useMemo(() => {

View file

@ -4,26 +4,26 @@ import getMeta from '../../../../utils/meta'
import SettingsMenuSelect from './settings-menu-select'
import type { Option } from './settings-menu-select'
import { useProjectSettingsContext } from '../../context/project-settings-context'
import type { AllowedImageName } from '../../../../../../types/project-settings'
export default function SettingsImageName() {
const { t } = useTranslation()
const { imageName, setImageName } = useProjectSettingsContext()
const allowedImageNames = getMeta('ol-allowedImageNames') as
| AllowedImageName[]
| undefined
const allowedImageNames = useMemo(
() => getMeta('ol-allowedImageNames') || [],
[]
)
const options: Array<Option> = useMemo(
() =>
allowedImageNames?.map(({ imageName, imageDesc }) => ({
allowedImageNames.map(({ imageName, imageDesc }) => ({
value: imageName,
label: imageDesc,
})) ?? [],
})),
[allowedImageNames]
)
if ((allowedImageNames?.length ?? 0) === 0) {
if (allowedImageNames.length === 0) {
return null
}

View file

@ -6,7 +6,6 @@ import SettingsMenuSelect, { Option } from './settings-menu-select'
import { useProjectSettingsContext } from '../../context/project-settings-context'
import type { OverallThemeMeta } from '../../../../../../types/project-settings'
import type { OverallTheme } from '../../../source-editor/extensions/theme'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
export default function SettingsOverallTheme() {
const { t } = useTranslation()
@ -25,8 +24,8 @@ export default function SettingsOverallTheme() {
[overallThemes]
)
const brandVariation = getMeta('ol-brandVariation') as any
const { ieeeBrandId } = getMeta('ol-ExposedSettings') as ExposedSettings
const brandVariation = getMeta('ol-brandVariation')
const { ieeeBrandId } = getMeta('ol-ExposedSettings')
const isIEEEBranded = brandVariation?.brand_id === ieeeBrandId
if (!overallThemes || isIEEEBranded) {

View file

@ -4,11 +4,10 @@ import getMeta from '../../../../utils/meta'
import { useProjectSettingsContext } from '../../context/project-settings-context'
import SettingsMenuSelect from './settings-menu-select'
import type { Optgroup } from './settings-menu-select'
import type { SpellCheckLanguage } from '../../../../../../types/project-settings'
export default function SettingsSpellCheckLanguage() {
const { t } = useTranslation()
const languages = getMeta('ol-languages') as SpellCheckLanguage[] | undefined
const languages = getMeta('ol-languages')
const { spellCheckLanguage, setSpellCheckLanguage } =
useProjectSettingsContext()

View file

@ -10,10 +10,10 @@ const components = importOverleafModules('editorLeftMenuSync') as {
export default function SyncMenu() {
const { t } = useTranslation()
const anonymous = getMeta('ol-anonymous') as boolean | undefined
const gitBridgeEnabled = getMeta('ol-gitBridgeEnabled', false) as boolean
const anonymous = getMeta('ol-anonymous')
const gitBridgeEnabled = getMeta('ol-gitBridgeEnabled')
if (anonymous === true || anonymous === undefined) {
if (anonymous) {
return null
}

View file

@ -5,6 +5,7 @@ import type { OverallThemeMeta } from '../../../../../types/project-settings'
import { saveUserSettings } from '../utils/api'
import { UserSettings } from '../../../../../types/user-settings'
import { useUserSettingsContext } from '@/shared/context/user-settings-context'
import getMeta from '@/utils/meta'
export default function useSetOverallTheme() {
const [chosenTheme, setChosenTheme] = useState<OverallThemeMeta | null>(null)
@ -56,7 +57,7 @@ export default function useSetOverallTheme() {
(newOverallTheme: UserSettings['overallTheme']) => {
if (overallTheme !== newOverallTheme) {
const chosenTheme = _.find(
window.overallThemes,
getMeta('ol-overallThemes'),
theme => theme.val === newOverallTheme
)

View file

@ -14,6 +14,7 @@ import HistoryToggleButton from './history-toggle-button'
import ShareProjectButton from './share-project-button'
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
import BackToEditorButton from './back-to-editor-button'
import getMeta from '@/utils/meta'
const [publishModalModules] = importOverleafModules('publishModal')
const PublishButton = publishModalModules?.import.default
@ -54,7 +55,7 @@ const ToolbarHeader = React.memo(function ToolbarHeader({
)}
<BackToProjectsButton />
</div>
{window.showUpgradePrompt && <UpgradePrompt />}
{getMeta('ol-showUpgradePrompt') && <UpgradePrompt />}
<ProjectNameEditableLabel
className="toolbar-center"
projectName={projectName}

View file

@ -10,6 +10,7 @@ import { useFileTreeData } from '../../../../shared/context/file-tree-data-conte
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
import { lazy, Suspense } from 'react'
import { FullSizeLoadingSpinner } from '@/shared/components/loading-spinner'
import getMeta from '@/utils/meta'
const createFileModeModules = importOverleafModules('createFileModes')
@ -20,6 +21,11 @@ export default function FileTreeModalCreateFileBody() {
const { newFileCreateMode } = useFileTreeActionable()
const { fileCount } = useFileTreeData()
const {
hasLinkedProjectFileFeature,
hasLinkedProjectOutputFileFeature,
hasLinkUrlFeature,
} = getMeta('ol-ExposedSettings')
if (!fileCount || fileCount.status === 'error') {
return null
@ -43,8 +49,8 @@ export default function FileTreeModalCreateFileBody() {
label={t('upload')}
/>
{(window.ExposedSettings.hasLinkedProjectFileFeature ||
window.ExposedSettings.hasLinkedProjectOutputFileFeature) && (
{(hasLinkedProjectFileFeature ||
hasLinkedProjectOutputFileFeature) && (
<FileTreeModalCreateFileMode
mode="project"
icon="folder-open"
@ -52,7 +58,7 @@ export default function FileTreeModalCreateFileBody() {
/>
)}
{window.ExposedSettings.hasLinkUrlFeature && (
{hasLinkUrlFeature && (
<FileTreeModalCreateFileMode
mode="url"
icon="globe"

View file

@ -20,12 +20,13 @@ import ErrorMessage from '../error-message'
import * as eventTracking from '../../../../../infrastructure/event-tracking'
import { File } from '@/features/source-editor/utils/file'
import { Project } from '../../../../../../../types/project'
import getMeta from '@/utils/meta'
export default function FileTreeImportFromProject() {
const { t } = useTranslation()
const { hasLinkedProjectFileFeature, hasLinkedProjectOutputFileFeature } =
window.ExposedSettings
getMeta('ol-ExposedSettings')
const canSwitchOutputFilesMode =
hasLinkedProjectFileFeature && hasLinkedProjectOutputFileFeature

View file

@ -16,6 +16,7 @@ import { findByNameInFolder } from '@/features/file-tree/util/is-name-unique-in-
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import { FileTreeEntity } from '../../../../../../../types/file-tree-entity'
import { UploadConflicts } from '@/features/file-tree/components/file-tree-create/file-tree-upload-conflicts'
import getMeta from '@/utils/meta'
export default function FileTreeUploadDoc() {
const { parentFolderId, cancel, droppedFiles, setDroppedFiles } =
@ -30,7 +31,7 @@ export default function FileTreeUploadDoc() {
const [overwrite, setOverwrite] = useState(false)
const maxNumberOfFiles = 180
const maxFileSize = window.ExposedSettings.maxUploadSize
const maxFileSize = getMeta('ol-ExposedSettings').maxUploadSize
// calculate conflicts
const buildConflicts = (files: Record<string, any>) => {
@ -130,7 +131,7 @@ export default function FileTreeUploadDoc() {
.use(XHRUpload, {
endpoint,
headers: {
'X-CSRF-TOKEN': window.csrfToken,
'X-CSRF-TOKEN': getMeta('ol-csrfToken'),
},
// limit: maxConnections || 1,
limit: 1,

View file

@ -24,7 +24,7 @@ export const FileTreePathContext = createContext<
export const FileTreePathProvider: FC = ({ children }) => {
const { fileTreeData }: { fileTreeData: Folder } = useFileTreeData()
const projectId = getMeta('ol-project_id') as string
const projectId = getMeta('ol-project_id')
const pathInFileTree = useCallback(
(id: string) => pathInFolder(fileTreeData, id),

View file

@ -1,3 +1,5 @@
import getMeta from '@/utils/meta'
export function countFiles(fileTreeData) {
if (!fileTreeData) {
return 0
@ -5,7 +7,7 @@ export function countFiles(fileTreeData) {
const value = _countElements(fileTreeData)
const limit = window.ExposedSettings.maxEntitiesPerProject
const limit = getMeta('ol-ExposedSettings').maxEntitiesPerProject
const status = fileCountStatus(value, limit, Math.ceil(limit / 20))
return { value, status, limit }

View file

@ -1,11 +1,12 @@
import { Minimatch } from 'minimatch'
import getMeta from '@/utils/meta'
let fileIgnoreMatcher: Minimatch
export const isAcceptableFile = (name?: string, relativePath?: string) => {
if (!fileIgnoreMatcher) {
fileIgnoreMatcher = new Minimatch(
window.ExposedSettings.fileIgnorePattern,
getMeta('ol-ExposedSettings').fileIgnorePattern,
{ nocase: true, dot: true }
)
}

View file

@ -7,6 +7,7 @@ import FileViewImage from './file-view-image'
import FileViewPdf from './file-view-pdf'
import FileViewText from './file-view-text'
import Icon from '../../../shared/components/icon'
import getMeta from '@/utils/meta'
const imageExtensions = ['png', 'jpg', 'jpeg', 'gif']
@ -16,7 +17,7 @@ export default function FileView({ file }) {
const { t } = useTranslation()
const { textExtensions, editableFilenames } = window.ExposedSettings
const { textExtensions, editableFilenames } = getMeta('ol-ExposedSettings')
const extension = file.name.split('.').pop().toLowerCase()

View file

@ -8,8 +8,8 @@ export default function GroupManagers() {
const { isReady } = useWaitForI18n()
const { t } = useTranslation()
const groupId: string = getMeta('ol-groupId')
const groupName: string = getMeta('ol-groupName')
const groupId = getMeta('ol-groupId')
const groupName = getMeta('ol-groupName')
const paths = useMemo(
() => ({

View file

@ -24,9 +24,9 @@ export default function GroupMembers() {
} = useGroupMembersContext()
const [emailString, setEmailString] = useState<string>('')
const groupId: string = getMeta('ol-groupId')
const groupName: string = getMeta('ol-groupName')
const groupSize: number = getMeta('ol-groupSize')
const groupId = getMeta('ol-groupId')
const groupName = getMeta('ol-groupName')
const groupSize = getMeta('ol-groupSize')
const handleEmailsChange = useCallback(
e => {

View file

@ -8,8 +8,8 @@ export default function InstitutionManagers() {
const { isReady } = useWaitForI18n()
const { t } = useTranslation()
const groupId: string = getMeta('ol-groupId')
const groupName: string = getMeta('ol-groupName')
const groupId = getMeta('ol-groupId')
const groupName = getMeta('ol-groupName')
const paths = useMemo(
() => ({

View file

@ -42,7 +42,7 @@ export function ManagersTable({
unselectAllUsers,
selectUser,
unselectUser,
} = useUserSelection(getMeta('ol-users', []))
} = useUserSelection(getMeta('ol-users') || [])
const [emailString, setEmailString] = useState<string>('')
const [inviteUserInflightCount, setInviteUserInflightCount] = useState(0)

View file

@ -27,7 +27,7 @@ export default function MemberRow({
groupId,
}: ManagedUserRowProps) {
const { t } = useTranslation()
const managedUsersActive: any = getMeta('ol-managedUsersActive')
const managedUsersActive = getMeta('ol-managedUsersActive')
const groupSSOActive = getMeta('ol-groupSSOActive')
return (

View file

@ -26,7 +26,7 @@ export default function MembersList({ groupId }: ManagedUsersListProps) {
useState<GroupUserAlert>(undefined)
const [userToUnlink, setUserToUnlink] = useState<User | undefined>(undefined)
const { users } = useGroupMembersContext()
const managedUsersActive: any = getMeta('ol-managedUsersActive')
const managedUsersActive = getMeta('ol-managedUsersActive')
const groupSSOActive = getMeta('ol-groupSSOActive')
return (

View file

@ -8,8 +8,8 @@ export default function PublisherManagers() {
const { isReady } = useWaitForI18n()
const { t } = useTranslation()
const groupId: string = getMeta('ol-groupId')
const groupName: string = getMeta('ol-groupName')
const groupId = getMeta('ol-groupId')
const groupName = getMeta('ol-groupName')
const paths = useMemo(
() => ({

View file

@ -52,14 +52,14 @@ export function GroupMembersProvider({ children }: GroupMembersProviderProps) {
selectAllNonManagedUsers,
selectUser,
unselectUser,
} = useUserSelection(getMeta('ol-users', []))
} = useUserSelection(getMeta('ol-users') || [])
const [inviteUserInflightCount, setInviteUserInflightCount] = useState(0)
const [inviteError, setInviteError] = useState<APIError>()
const [removeMemberInflightCount, setRemoveMemberInflightCount] = useState(0)
const [removeMemberError, setRemoveMemberError] = useState<APIError>()
const groupId: string = getMeta('ol-groupId')
const groupId = getMeta('ol-groupId')
const paths = useMemo(
() => ({

View file

@ -54,7 +54,7 @@ export const Loading: FC<{
}
}, [projectJoined])
const LoadingScreenError = () => {
const getLoadingScreenError = (): string => {
if (connectionState.error) {
// NOTE: translations not ready yet
return connectionState.error === 'io-not-loaded'
@ -82,9 +82,7 @@ export const Loading: FC<{
hasError={hasError}
/>
{hasError && (
<p className="loading-screen-error">
<LoadingScreenError />
</p>
<p className="loading-screen-error">{getLoadingScreenError()}</p>
)}
</div>
)

View file

@ -86,9 +86,8 @@ export function createReactScopeValueStore(projectId: string) {
return scopeStore
}
const projectId = window.project_id
export const IdeReactProvider: FC = ({ children }) => {
const projectId = getMeta('ol-project_id')
const [scopeStore] = useState(() => createReactScopeValueStore(projectId))
const [eventEmitter] = useState(createIdeEventEmitter)
const [scopeEventEmitter] = useState(
@ -129,11 +128,10 @@ export const IdeReactProvider: FC = ({ children }) => {
body: {
error: errorObj,
meta: metadata,
_csrf: window.csrfToken,
},
})
},
[socket.socket, release]
[socket.socket, release, projectId]
)
// Populate scope values when joining project, then fire project:joined event
@ -175,7 +173,14 @@ export const IdeReactProvider: FC = ({ children }) => {
reportError,
projectJoined,
}),
[eventEmitter, eventLog, projectJoined, reportError, startedFreeTrial]
[
eventEmitter,
eventLog,
projectId,
projectJoined,
reportError,
startedFreeTrial,
]
)
return (

View file

@ -47,7 +47,7 @@ export const PermissionsProvider: React.FC = ({ children }) => {
const { permissionsLevel } = useEditorContext() as {
permissionsLevel: PermissionsLevel
}
const anonymous = getMeta('ol-anonymous') as boolean | undefined
const anonymous = getMeta('ol-anonymous')
useEffect(() => {
const activePermissionsMap = anonymous

View file

@ -65,6 +65,7 @@ import {
EditOperation,
} from '../../../../../../../types/change'
import { RangesTrackerWithResolvedThreadIds } from '@/features/ide-react/editor/document-container'
import getMeta from '@/utils/meta'
const dispatchReviewPanelEvent = (type: string, payload?: any) => {
window.dispatchEvent(
@ -89,7 +90,7 @@ const formatUser = (user: any): any => {
avatar_text: 'A',
}
}
if (id === window.user_id) {
if (id === getMeta('ol-user_id')) {
name = 'You'
isSelf = true
} else {

View file

@ -28,6 +28,7 @@ import {
Version,
} from '@/features/ide-react/editor/types/document'
import { ThreadId } from '../../../../../types/review-panel/review-panel'
import getMeta from '@/utils/meta'
const MAX_PENDING_OP_SIZE = 64
@ -737,7 +738,7 @@ export class DocumentContainer extends EventEmitter {
private filterOps(ops: AnyOperation[]) {
// Read-only token users can't see/edit comment, so we filter out comment
// ops to avoid highlighting comment ranges.
if (window.isRestrictedTokenMember) {
if (getMeta('ol-isRestrictedTokenMember')) {
return ops.filter(op => !isCommentOperation(op))
} else {
return ops

View file

@ -17,6 +17,7 @@ import {
} from '@/features/ide-react/editor/types/document'
import { EditorFacade } from '@/features/source-editor/extensions/realtime'
import { recordDocumentFirstChangeEvent } from '@/features/event-tracking/document-first-change-event'
import getMeta from '@/utils/meta'
// All times below are in milliseconds
const SINGLE_USER_FLUSH_DELAY = 2000
@ -327,8 +328,7 @@ export class ShareJsDoc extends EventEmitter {
attachToCM6(cm6: EditorFacade) {
this.attachToEditor(cm6, () => {
// @ts-ignore
cm6.attachShareJs(this._doc, window.maxDocLength)
cm6.attachShareJs(this._doc, getMeta('ol-maxDocLength'))
})
}

View file

@ -3,6 +3,7 @@ import * as eventTracking from '@/infrastructure/event-tracking'
import { useDetachCompileContext } from '@/shared/context/detach-compile-context'
import usePersistedState from '@/shared/hooks/use-persisted-state'
import { CompileTimeWarningUpgradePromptInner } from '@/features/pdf-preview/components/compile-time-warning-upgrade-prompt-inner'
import getMeta from '@/utils/meta'
function CompileTimeWarningUpgradePrompt() {
const { isProjectOwner, deliveryLatencies, compiling, showLogs, error } =
@ -50,7 +51,7 @@ function CompileTimeWarningUpgradePrompt() {
handleNewCompile(deliveryLatencies.compileTimeServerE2E)
}, [compiling, error, showLogs, deliveryLatencies, handleNewCompile])
if (!window.ExposedSettings.enableSubscriptions) {
if (!getMeta('ol-ExposedSettings').enableSubscriptions) {
return null
}

View file

@ -7,6 +7,7 @@ import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-err
import { Button } from 'react-bootstrap'
import * as eventTracking from '../../../infrastructure/event-tracking'
import { useFeatureFlag } from '@/shared/context/split-test-context'
import getMeta from '@/utils/meta'
function TimeoutUpgradePromptNew() {
const {
@ -29,7 +30,7 @@ function TimeoutUpgradePromptNew() {
return (
<>
<CompileTimeout isProjectOwner={isProjectOwner} />
{window.ExposedSettings.enableSubscriptions && (
{getMeta('ol-ExposedSettings').enableSubscriptions && (
<PreventTimeoutHelpMessage
handleEnableStopOnFirstErrorClick={handleEnableStopOnFirstErrorClick}
lastCompileOptions={lastCompileOptions}
@ -55,7 +56,7 @@ const CompileTimeout = memo(function CompileTimeout({
<PdfLogEntry
headerTitle={t('your_compile_timed_out')}
formattedContent={
window.ExposedSettings.enableSubscriptions && (
getMeta('ol-ExposedSettings').enableSubscriptions && (
<>
<p>
{isProjectOwner

View file

@ -65,7 +65,7 @@ async function importPDFJS213() {
}
async function importPDFJS() {
const variant = getMeta('ol-pdfjsVariant', 'default')
const variant = getMeta('ol-pdfjsVariant') || 'default'
// NOTE: split test variants must have at least 3 characters
switch (variant) {

View file

@ -20,7 +20,7 @@ export function createLocalizedGroupPlanPrice({
licenseSize,
currency,
usage,
locale = window.i18n.currentLangCode || 'en',
locale = getMeta('ol-i18n').currentLangCode || 'en',
formatCurrency,
}) {
const groupPlans = getMeta('ol-groupPlans')

View file

@ -2,14 +2,12 @@ import { useTranslation } from 'react-i18next'
import { Button } from 'react-bootstrap'
import { useProjectListContext } from '../context/project-list-context'
import getMeta from '../../../utils/meta'
import { Affiliation } from '../../../../../types/affiliation'
import { ExposedSettings } from '../../../../../types/exposed-settings'
import classNames from 'classnames'
export function useAddAffiliation() {
const { totalProjectsCount } = useProjectListContext()
const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings
const userAffiliations = getMeta('ol-userAffiliations', []) as Affiliation[]
const { isOverleaf } = getMeta('ol-ExposedSettings')
const userAffiliations = getMeta('ol-userAffiliations') || []
return {
show: isOverleaf && totalProjectsCount > 0 && !userAffiliations.length,

View file

@ -3,12 +3,9 @@ import IndividualPlan from './individual-plan'
import GroupPlan from './group-plan'
import CommonsPlan from './commons-plan'
import getMeta from '../../../../utils/meta'
import { Subscription } from '../../../../../../types/project/dashboard/subscription'
function CurrentPlanWidget() {
const usersBestSubscription: Subscription | undefined = getMeta(
'ol-usersBestSubscription'
)
const usersBestSubscription = getMeta('ol-usersBestSubscription')
if (!usersBestSubscription) {
return null

View file

@ -103,10 +103,7 @@ type ErrorNotificationProps = {
}
function ErrorNotification({ error }: ErrorNotificationProps) {
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const newNotificationStyle = getMeta('ol-newNotificationStyle')
if (newNotificationStyle) {
return (

View file

@ -36,10 +36,7 @@ function RenameProjectModal({
const { error, isError, isLoading, runAsync } = useAsync()
const { toggleSelectedProject, updateProjectViewData } =
useProjectListContext()
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const newNotificationStyle = getMeta('ol-newNotificationStyle')
useEffect(() => {
if (showModal) {

View file

@ -1,8 +1,6 @@
import { type JSXElementConstructor, useCallback, useState } from 'react'
import { Dropdown, MenuItem } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { ExposedSettings } from '../../../../../types/exposed-settings'
import type { PortalTemplate } from '../../../../../types/portal-template'
import ControlledDropdown from '../../../shared/components/controlled-dropdown'
import getMeta from '../../../utils/meta'
import NewProjectButtonModal, {
@ -46,10 +44,10 @@ function NewProjectButton({
showAddAffiliationWidget,
}: NewProjectButtonProps) {
const { t } = useTranslation()
const { templateLinks } = getMeta('ol-ExposedSettings') as ExposedSettings
const { templateLinks } = getMeta('ol-ExposedSettings')
const [modal, setModal] =
useState<Nullable<NewProjectButtonModalVariant>>(null)
const portalTemplates = getMeta('ol-portalTemplates') as PortalTemplate[]
const portalTemplates = getMeta('ol-portalTemplates') || []
const { show: enableAddAffiliationWidget } = useAddAffiliation()
const sendTrackingEvent = useCallback(
@ -202,7 +200,7 @@ function NewProjectButton({
}
/>
)}
{portalTemplates?.length > 0 ? (
{portalTemplates.length > 0 ? (
<>
<MenuItem divider />
<MenuItem header>

View file

@ -42,16 +42,12 @@ function ModalContentNewProjectForm({ onCancel, template = 'none' }: Props) {
const [projectName, setProjectName] = useState('')
const { isLoading, isError, error, runAsync } = useAsync<NewProjectData>()
const location = useLocation()
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const newNotificationStyle = getMeta('ol-newNotificationStyle')
const createNewProject = () => {
runAsync(
postJSON('/project/new', {
body: {
_csrf: window.csrfToken,
projectName,
template,
},

View file

@ -11,7 +11,6 @@ import Uppy from '@uppy/core'
import { Dashboard } from '@uppy/react'
import XHRUpload from '@uppy/xhr-upload'
import getMeta from '../../../../utils/meta'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
import '@uppy/core/dist/style.css'
import '@uppy/dashboard/dist/style.css'
@ -27,9 +26,7 @@ type UploadProjectModalProps = {
function UploadProjectModal({ onHide, openProject }: UploadProjectModalProps) {
const { t } = useTranslation()
const { maxUploadSize, projectUploadTimeout } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { maxUploadSize, projectUploadTimeout } = getMeta('ol-ExposedSettings')
const [ableToUpload, setAbleToUpload] = useState(false)
const [uppy] = useState(() => {
@ -44,7 +41,7 @@ function UploadProjectModal({ onHide, openProject }: UploadProjectModalProps) {
.use(XHRUpload, {
endpoint: '/project/new/upload',
headers: {
'X-CSRF-TOKEN': window.csrfToken,
'X-CSRF-TOKEN': getMeta('ol-csrfToken'),
},
limit: 1,
fieldName: 'qqfile', // "qqfile" is needed for our express multer middleware

View file

@ -4,9 +4,9 @@ import INRBanner from './ads/inr-banner'
import LATAMBanner from './ads/latam-banner'
function GeoBanners() {
const showInrGeoBanner = getMeta('ol-showInrGeoBanner', false)
const showBrlGeoBanner = getMeta('ol-showBrlGeoBanner', false)
const showLATAMBanner = getMeta('ol-showLATAMBanner', false)
const showInrGeoBanner = getMeta('ol-showInrGeoBanner')
const showBrlGeoBanner = getMeta('ol-showBrlGeoBanner')
const showLATAMBanner = getMeta('ol-showLATAMBanner')
return (
<>
{showBrlGeoBanner && <BRLBanner />}

View file

@ -5,12 +5,13 @@ import getMeta from '../../../../utils/meta'
import customLocalStorage from '../../../../infrastructure/local-storage'
import { useProjectListContext } from '../../context/project-list-context'
import { useTranslation } from 'react-i18next'
type variantsType = 'on-premise' | 'FOMO'
const variants = ['on-premise', 'FOMO'] as variantsType[]
import {
GroupsAndEnterpriseBannerVariant,
GroupsAndEnterpriseBannerVariants,
} from '../../../../../../types/project/dashboard/notification'
type urlForVariantsType = {
[key in variantsType]: string // eslint-disable-line no-unused-vars
[key in GroupsAndEnterpriseBannerVariant]: string // eslint-disable-line no-unused-vars
}
const urlForVariants: urlForVariantsType = {
@ -18,23 +19,19 @@ const urlForVariants: urlForVariantsType = {
FOMO: '/for/contact-sales-4',
}
type GroupsAndEnterpriseBannerVariant = (typeof variants)[number]
let viewEventSent = false
export default function GroupsAndEnterpriseBanner() {
const { t } = useTranslation()
const { totalProjectsCount } = useProjectListContext()
const showGroupsAndEnterpriseBanner: boolean = getMeta(
const showGroupsAndEnterpriseBanner = getMeta(
'ol-showGroupsAndEnterpriseBanner'
)
const groupsAndEnterpriseBannerVariant: GroupsAndEnterpriseBannerVariant =
getMeta('ol-groupsAndEnterpriseBannerVariant')
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const groupsAndEnterpriseBannerVariant = getMeta(
'ol-groupsAndEnterpriseBannerVariant'
)
const newNotificationStyle = getMeta('ol-newNotificationStyle')
const hasDismissedGroupsAndEnterpriseBanner = hasRecentlyDismissedBanner()
@ -99,7 +96,7 @@ export default function GroupsAndEnterpriseBanner() {
}
function isVariantValid(variant: GroupsAndEnterpriseBannerVariant) {
return variants.includes(variant)
return GroupsAndEnterpriseBannerVariants.includes(variant)
}
function BannerContent({

View file

@ -9,7 +9,6 @@ import {
postJSON,
} from '../../../../../../infrastructure/fetch-json'
import { UserEmailData } from '../../../../../../../../types/user-email'
import { ExposedSettings } from '../../../../../../../../types/exposed-settings'
import { Institution } from '../../../../../../../../types/institution'
import { useLocation } from '../../../../../../shared/hooks/use-location'
import { debugConsole } from '@/utils/debugging'
@ -24,11 +23,8 @@ function ReconfirmAffiliation({
institution,
}: ReconfirmAffiliationProps) {
const { t } = useTranslation()
const { samlInitPath } = getMeta('ol-ExposedSettings') as ExposedSettings
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const { samlInitPath } = getMeta('ol-ExposedSettings')
const newNotificationStyle = getMeta('ol-newNotificationStyle')
const { error, isLoading, isError, isSuccess, runAsync } = useAsync()
const [hasSent, setHasSent] = useState(false)
const [isPending, setIsPending] = useState(false)

View file

@ -1,16 +1,13 @@
import Notification from '../../notification'
import ReconfirmAffiliation from './reconfirm-affiliation'
import getMeta from '../../../../../../utils/meta'
import { UserEmailData } from '../../../../../../../../types/user-email'
import ReconfirmationInfoSuccess from '../../../../../settings/components/emails/reconfirmation-info/reconfirmation-info-success'
function ReconfirmationInfo() {
const allInReconfirmNotificationPeriods = getMeta(
'ol-allInReconfirmNotificationPeriods',
[]
) as UserEmailData[]
const userEmails = getMeta('ol-userEmails', []) as UserEmailData[]
const reconfirmedViaSAML = getMeta('ol-reconfirmedViaSAML') as string
const allInReconfirmNotificationPeriods =
getMeta('ol-allInReconfirmNotificationPeriods') || []
const userEmails = getMeta('ol-userEmails') || []
const reconfirmedViaSAML = getMeta('ol-reconfirmedViaSAML')
return (
<>
{allInReconfirmNotificationPeriods.map(userEmail =>

View file

@ -6,18 +6,16 @@ import getMeta from '../../../../../utils/meta'
import useAsyncDismiss from '../hooks/useAsyncDismiss'
import useAsync from '../../../../../shared/hooks/use-async'
import { FetchError, postJSON } from '../../../../../infrastructure/fetch-json'
import { ExposedSettings } from '../../../../../../../types/exposed-settings'
import {
NotificationProjectInvite,
Notification as NotificationType,
} from '../../../../../../../types/project/dashboard/notification'
import { User } from '../../../../../../../types/user'
import GroupInvitationNotification from './group-invitation/group-invitation'
import IEEERetirementBanner from '../ieee-retirement-banner'
import { debugConsole } from '@/utils/debugging'
function Common() {
const notifications = getMeta('ol-notifications', []) as NotificationType[]
const notifications = getMeta('ol-notifications') || []
if (!notifications.length) {
return null
}
@ -37,12 +35,9 @@ type CommonNotificationProps = {
function CommonNotification({ notification }: CommonNotificationProps) {
const { t } = useTranslation()
const { samlInitPath } = getMeta('ol-ExposedSettings') as ExposedSettings
const user = getMeta('ol-user', []) as Pick<User, 'features'>
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const { samlInitPath } = getMeta('ol-ExposedSettings')
const user = getMeta('ol-user')
const newNotificationStyle = getMeta('ol-newNotificationStyle')
const { isLoading, isSuccess, error, runAsync } = useAsync<
never,
FetchError

View file

@ -9,15 +9,11 @@ import {
postJSON,
getUserFacingMessage,
} from '../../../../../infrastructure/fetch-json'
import { ExposedSettings } from '../../../../../../../types/exposed-settings'
import { UserEmailData } from '../../../../../../../types/user-email'
import { debugConsole } from '@/utils/debugging'
import { Subscription } from '../../../../../../../types/project/dashboard/subscription'
const ssoAvailable = ({ samlProviderId, affiliation }: UserEmailData) => {
const { hasSamlFeature, hasSamlBeta } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { hasSamlFeature, hasSamlBeta } = getMeta('ol-ExposedSettings')
if (!hasSamlFeature) {
return false
@ -60,9 +56,7 @@ function emailHasLicenceAfterConfirming(emailData: UserEmailData) {
}
function isOnFreeOrIndividualPlan() {
const subscription: Subscription | undefined = getMeta(
'ol-usersBestSubscription'
)
const subscription = getMeta('ol-usersBestSubscription')
if (!subscription) {
return false
}
@ -71,9 +65,7 @@ function isOnFreeOrIndividualPlan() {
}
const showConfirmEmail = (userEmail: UserEmailData) => {
const { emailConfirmationDisabled } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { emailConfirmationDisabled } = getMeta('ol-ExposedSettings')
return (
!emailConfirmationDisabled &&
@ -179,7 +171,7 @@ function ConfirmEmailNotification({ userEmail }: { userEmail: UserEmailData }) {
function ConfirmEmail() {
const { totalProjectsCount } = useProjectListContext()
const userEmails = getMeta('ol-userEmails', []) as UserEmailData[]
const userEmails = getMeta('ol-userEmails') || []
if (!totalProjectsCount || !userEmails.length) {
return null

View file

@ -20,10 +20,7 @@ export default function GroupInvitationCancelIndividualSubscriptionNotification(
notification,
}: GroupInvitationCancelIndividualSubscriptionNotificationProps) {
const { t } = useTranslation()
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const newNotificationStyle = getMeta('ol-newNotificationStyle')
const {
messageOpts: { inviterName },
} = notification

View file

@ -18,10 +18,7 @@ export default function GroupInvitationNotificationJoin({
dismissGroupInviteNotification,
}: GroupInvitationNotificationProps) {
const { t } = useTranslation()
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const newNotificationStyle = getMeta('ol-newNotificationStyle')
const {
messageOpts: { inviterName },
} = notification

View file

@ -11,10 +11,7 @@ export default function GroupInvitationSuccessfulNotification({
hideNotification,
}: GroupInvitationSuccessfulNotificationProps) {
const { t } = useTranslation()
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const newNotificationStyle = getMeta('ol-newNotificationStyle')
return (
<Notification

View file

@ -59,7 +59,7 @@ export function useGroupInvitationNotification(
const hasIndividualRecurlySubscription = getMeta(
'ol-hasIndividualRecurlySubscription'
) as boolean | undefined
)
useEffect(() => {
if (hasIndividualRecurlySubscription) {

View file

@ -5,22 +5,12 @@ import Notification from '../notification'
import Icon from '../../../../../shared/components/icon'
import getMeta from '../../../../../utils/meta'
import useAsyncDismiss from '../hooks/useAsyncDismiss'
import { ExposedSettings } from '../../../../../../../types/exposed-settings'
import { Institution as InstitutionType } from '../../../../../../../types/project/dashboard/notification'
function Institution() {
const { t } = useTranslation()
const { samlInitPath, appName } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const notificationsInstitution = getMeta(
'ol-notificationsInstitution',
[]
) as InstitutionType[]
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const { samlInitPath, appName } = getMeta('ol-ExposedSettings')
const notificationsInstitution = getMeta('ol-notificationsInstitution') || []
const newNotificationStyle = getMeta('ol-newNotificationStyle')
const { handleDismiss } = useAsyncDismiss()
if (!notificationsInstitution.length) {

View file

@ -40,8 +40,7 @@ function Notification({
...props
}: NotificationProps) {
newNotificationStyle =
newNotificationStyle ??
(getMeta('ol-newNotificationStyle', false) as boolean)
newNotificationStyle ?? getMeta('ol-newNotificationStyle')
const [show, setShow] = useState(true)

View file

@ -14,11 +14,6 @@ import classNames from 'classnames'
import GeoBanners from './geo-banners'
import AccessibilitySurveyBanner from './accessibility-survey-banner'
type Subscription = {
groupId: string
groupName: string
}
const [enrollmentNotificationModule] = importOverleafModules(
'managedGroupSubscriptionEnrollmentNotification'
)
@ -28,14 +23,9 @@ const EnrollmentNotification: JSXElementConstructor<{
}> = enrollmentNotificationModule?.import.default
function UserNotifications() {
const newNotificationStyle = getMeta(
'ol-newNotificationStyle',
false
) as boolean
const groupSubscriptionsPendingEnrollment: Subscription[] = getMeta(
'ol-groupSubscriptionsPendingEnrollment',
[]
)
const newNotificationStyle = getMeta('ol-newNotificationStyle')
const groupSubscriptionsPendingEnrollment =
getMeta('ol-groupSubscriptionsPendingEnrollment') || []
const user = getMeta('ol-user')
// Temporary workaround to prevent also showing groups/enterprise banner

View file

@ -1,11 +1,10 @@
import usePersistedState from '../../../shared/hooks/use-persisted-state'
import getMeta from '../../../utils/meta'
import { Survey } from '../../../../../types/project/dashboard/survey'
import { useCallback } from 'react'
import Close from '@/shared/components/close'
export default function SurveyWidget() {
const survey: Survey = getMeta('ol-survey')
const survey = getMeta('ol-survey')
const [dismissedSurvey, setDismissedSurvey] = usePersistedState(
`dismissed-${survey?.name}`,
false

View file

@ -7,6 +7,7 @@ import DeleteProjectModal from '../../../modals/delete-project-modal'
import useIsMounted from '../../../../../../shared/hooks/use-is-mounted'
import { deleteProject } from '../../../../util/api'
import { useProjectListContext } from '../../../../context/project-list-context'
import getMeta from '@/utils/meta'
type DeleteProjectButtonProps = {
project: Project
@ -31,7 +32,7 @@ function DeleteProjectButton({ project, children }: DeleteProjectButtonProps) {
}, [isMounted])
const isOwner = useMemo(() => {
return project.owner && window.user_id === project.owner.id
return project.owner && getMeta('ol-user_id') === project.owner.id
}, [project])
const handleDeleteProject = useCallback(async () => {

View file

@ -7,6 +7,7 @@ import { useProjectListContext } from '../../../../context/project-list-context'
import useIsMounted from '../../../../../../shared/hooks/use-is-mounted'
import { leaveProject } from '../../../../util/api'
import { Project } from '../../../../../../../../types/project/dashboard/api'
import getMeta from '@/utils/meta'
type LeaveProjectButtonProps = {
project: Project
@ -18,7 +19,7 @@ function LeaveProjectButton({ project, children }: LeaveProjectButtonProps) {
const { t } = useTranslation()
const text = t('leave')
const isOwner = useMemo(() => {
return project.owner && window.user_id === project.owner.id
return project.owner && getMeta('ol-user_id') === project.owner.id
}, [project])
const [showModal, setShowModal] = useState(false)
const isMounted = useIsMounted()

View file

@ -1,10 +1,8 @@
import { useCallback, useState, forwardRef } from 'react'
import { useTranslation } from 'react-i18next'
import type { PortalTemplate } from '../../../../../../types/portal-template'
import { sendMB } from '../../../../infrastructure/event-tracking'
import getMeta from '../../../../utils/meta'
import { NewProjectButtonModalVariant } from '../new-project-button/new-project-button-modal'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
import {
Dropdown,
DropdownDivider,
@ -61,11 +59,9 @@ function WelcomeMessageCreateNewProjectDropdown({
}: WelcomeMessageCreateNewProjectDropdownProps) {
const [showDropdown, setShowDropdown] = useState(false)
const { t } = useTranslation()
const portalTemplates = getMeta('ol-portalTemplates') as
| PortalTemplate[]
| undefined
const portalTemplates = getMeta('ol-portalTemplates') || []
const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings
const { isOverleaf } = getMeta('ol-ExposedSettings')
const handleClick = useCallback(() => {
sendMB('welcome-page-create-first-project-click', {
@ -184,7 +180,7 @@ function WelcomeMessageCreateNewProjectDropdown({
{t('import_from_github')}
</button>
)}
{(portalTemplates?.length ?? 0) > 0 ? (
{portalTemplates.length > 0 ? (
<>
<hr />
<div className="dropdown-header">

View file

@ -6,7 +6,6 @@ import type { Nullable } from '../../../../../types/utils'
import WelcomeMessageLink from './welcome-message-new/welcome-message-link'
import WelcomeMessageCreateNewProjectDropdown from './welcome-message-new/welcome-message-create-new-project-dropdown'
import getMeta from '@/utils/meta'
import { ExposedSettings } from '../../../../../types/exposed-settings'
import OLCard from '@/features/ui/components/ol/ol-card'
export default function WelcomeMessage() {
@ -14,9 +13,7 @@ export default function WelcomeMessage() {
const [activeModal, setActiveModal] =
useState<Nullable<NewProjectButtonModalVariant>>(null)
const { wikiEnabled, templatesEnabled } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { wikiEnabled, templatesEnabled } = getMeta('ol-ExposedSettings')
return (
<>

View file

@ -145,7 +145,7 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) {
>('project-list-selected-tag-id', undefined)
const [showCustomPicker, setShowCustomPicker] = useState(false)
const olTags: Tag[] = getMeta('ol-tags', [])
const olTags = getMeta('ol-tags') || []
const [tags, setTags] = useState<Tag[]>(() =>
// `tag.name` data may be null for some old users

View file

@ -1,7 +1,8 @@
import { UserRef } from '../../../../../types/project/dashboard/api'
import getMeta from '@/utils/meta'
export function getUserName(user: UserRef) {
if (user?.id === window.user_id) {
if (user?.id === getMeta('ol-user_id')) {
return 'You'
}

View file

@ -5,7 +5,6 @@ import {
postJSON,
} from '../../../infrastructure/fetch-json'
import getMeta from '../../../utils/meta'
import { ExposedSettings } from '../../../../../types/exposed-settings'
import useAsync from '../../../shared/hooks/use-async'
import { useUserContext } from '../../../shared/context/user-context'
import OLButton from '@/features/ui/components/ol/ol-button'
@ -17,15 +16,11 @@ import FormText from '@/features/ui/components/bootstrap-5/form/form-text'
function AccountInfoSection() {
const { t } = useTranslation()
const { hasAffiliationsFeature } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { hasAffiliationsFeature } = getMeta('ol-ExposedSettings')
const isExternalAuthenticationSystemUsed = getMeta(
'ol-isExternalAuthenticationSystemUsed'
) as boolean
const shouldAllowEditingDetails = getMeta(
'ol-shouldAllowEditingDetails'
) as boolean
)
const shouldAllowEditingDetails = getMeta('ol-shouldAllowEditingDetails')
const {
first_name: initialFirstName,
last_name: initialLastName,

View file

@ -10,7 +10,6 @@ import EmailsRow from './emails/row'
import AddEmail from './emails/add-email'
import Icon from '../../../shared/components/icon'
import OLNotification from '@/features/ui/components/ol/ol-notification'
import { ExposedSettings } from '../../../../../types/exposed-settings'
import { LeaversSurveyAlert } from './leavers-survey-alert'
function EmailsSectionContent() {
@ -24,9 +23,7 @@ function EmailsSectionContent() {
const userEmails = Object.values(userEmailsData.byId)
// Only show the "add email" button if the user has permission to add a secondary email
const hideAddSecondaryEmail = getMeta(
'ol-cannot-add-secondary-email'
) as boolean
const hideAddSecondaryEmail = getMeta('ol-cannot-add-secondary-email')
return (
<>
@ -82,9 +79,7 @@ function EmailsSectionContent() {
}
function EmailsSection() {
const { hasAffiliationsFeature } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { hasAffiliationsFeature } = getMeta('ol-ExposedSettings')
if (!hasAffiliationsFeature) {
return null
}

View file

@ -46,7 +46,7 @@ function Remove({ userEmailData, deleteEmailAsync }: RemoveProps) {
const { t } = useTranslation()
const { state, deleteEmail, resetLeaversSurveyExpiration } =
useUserEmailsContext()
const isManaged = getMeta('ol-isManagedAccount', false)
const isManaged = getMeta('ol-isManagedAccount')
const getTooltipText = () => {
if (isManaged) {

View file

@ -42,7 +42,7 @@ function AddEmail() {
getEmails,
} = useUserEmailsContext()
const emailAddressLimit = getMeta('ol-emailAddressLimit', 10)
const emailAddressLimit = getMeta('ol-emailAddressLimit') || 10
const { ref: recaptchaRef, getReCaptchaToken } = useRecaptcha()
useEffect(() => {

View file

@ -1,7 +1,6 @@
import { useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { DomainInfo } from './input'
import { ExposedSettings } from '../../../../../../../types/exposed-settings'
import getMeta from '../../../../../utils/meta'
import { useLocation } from '../../../../../shared/hooks/use-location'
import OLButton from '@/features/ui/components/ol/ol-button'
@ -12,7 +11,7 @@ type SSOLinkingInfoProps = {
}
function SsoLinkingInfo({ domainInfo, email }: SSOLinkingInfoProps) {
const { samlInitPath } = getMeta('ol-ExposedSettings') as ExposedSettings
const { samlInitPath } = getMeta('ol-ExposedSettings')
const { t } = useTranslation()
const location = useLocation()

View file

@ -14,7 +14,6 @@ import { debugConsole } from '@/utils/debugging'
import { ssoAvailableForInstitution } from '@/features/settings/utils/sso'
import { Trans, useTranslation } from 'react-i18next'
import useAsync from '@/shared/hooks/use-async'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
import { useLocation } from '@/shared/hooks/use-location'
import OLButton from '@/features/ui/components/ol/ol-button'
import classnames from 'classnames'
@ -24,13 +23,11 @@ type ReconfirmationInfoProps = {
}
function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
const reconfirmationRemoveEmail = getMeta(
'ol-reconfirmationRemoveEmail'
) as string
const reconfirmedViaSAML = getMeta('ol-reconfirmedViaSAML') as string
const reconfirmationRemoveEmail = getMeta('ol-reconfirmationRemoveEmail')
const reconfirmedViaSAML = getMeta('ol-reconfirmedViaSAML')
const { t } = useTranslation()
const { samlInitPath } = getMeta('ol-ExposedSettings') as ExposedSettings
const { samlInitPath } = getMeta('ol-ExposedSettings')
const { error, isLoading, isError, isSuccess, runAsync } = useAsync()
const { state, setLoading: setUserEmailsContextLoading } =
useUserEmailsContext()

View file

@ -8,7 +8,6 @@ import Actions from './actions'
import { institutionAlreadyLinked } from '../../utils/selectors'
import { useUserEmailsContext } from '../../context/user-email-context'
import getMeta from '../../../../utils/meta'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
import { ssoAvailableForInstitution } from '../../utils/sso'
import ReconfirmationInfo from './reconfirmation-info'
import { useLocation } from '../../../../shared/hooks/use-location'
@ -61,7 +60,7 @@ type SSOAffiliationInfoProps = {
}
function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) {
const { samlInitPath } = getMeta('ol-ExposedSettings') as ExposedSettings
const { samlInitPath } = getMeta('ol-ExposedSettings')
const { t } = useTranslation()
const { state } = useUserEmailsContext()
const location = useLocation()

View file

@ -4,27 +4,14 @@ import Icon from '../../../../shared/components/icon'
import getMeta from '../../../../utils/meta'
import OLNotification from '@/features/ui/components/ol/ol-notification'
type InstitutionLink = {
universityName: string
hasEntitlement?: boolean
}
type SAMLError = {
translatedMessage?: string
message?: string
tryAgain?: boolean
}
export function SSOAlert() {
const { t } = useTranslation()
const institutionLinked: InstitutionLink | undefined = getMeta(
'ol-institutionLinked'
)
const institutionEmailNonCanonical: string | undefined = getMeta(
const institutionLinked = getMeta('ol-institutionLinked')
const institutionEmailNonCanonical = getMeta(
'ol-institutionEmailNonCanonical'
)
const samlError: SAMLError | undefined = getMeta('ol-samlError')
const samlError = getMeta('ol-samlError')
const [infoClosed, setInfoClosed] = useState(false)
const [warningClosed, setWarningClosed] = useState(false)

View file

@ -2,7 +2,6 @@ import { useState, Dispatch, SetStateAction } from 'react'
import { useTranslation, Trans } from 'react-i18next'
import getMeta from '../../../../utils/meta'
import LeaveModalForm, { LeaveModalFormProps } from './modal-form'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
import OLButton from '@/features/ui/components/ol/ol-button'
import {
OLModalBody,
@ -23,8 +22,8 @@ function LeaveModalContentBlock({
setIsFormValid,
}: LeaveModalFormProps) {
const { t } = useTranslation()
const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings
const hasPassword = getMeta('ol-hasPassword') as boolean
const { isOverleaf } = getMeta('ol-ExposedSettings')
const hasPassword = getMeta('ol-hasPassword')
if (isOverleaf && !hasPassword) {
return (

View file

@ -1,7 +1,6 @@
import { useTranslation, Trans } from 'react-i18next'
import getMeta from '../../../../utils/meta'
import { FetchError } from '../../../../infrastructure/fetch-json'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
import OLNotification from '@/features/ui/components/ol/ol-notification'
type LeaveModalFormErrorProps = {
@ -10,7 +9,7 @@ type LeaveModalFormErrorProps = {
function LeaveModalFormError({ error }: LeaveModalFormErrorProps) {
const { t } = useTranslation()
const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings
const { isOverleaf } = getMeta('ol-ExposedSettings')
let errorMessage
let errorTip = null

View file

@ -21,7 +21,7 @@ function LeaveModalForm({
setIsFormValid,
}: LeaveModalFormProps) {
const { t } = useTranslation()
const userDefaultEmail = getMeta('ol-usersEmail') as string
const userDefaultEmail = getMeta('ol-usersEmail')!
const location = useLocation()
const [email, setEmail] = useState('')

View file

@ -1,4 +1,4 @@
import { useState, ElementType } from 'react'
import { ElementType } from 'react'
import { useTranslation } from 'react-i18next'
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
import { useSSOContext, SSOSubscription } from '../context/sso-context'
@ -8,29 +8,33 @@ import { useBroadcastUser } from '@/shared/hooks/user-channel/use-broadcast-user
import { useFeatureFlag } from '@/shared/context/split-test-context'
import OLNotification from '@/features/ui/components/ol/ol-notification'
const availableIntegrationLinkingWidgets = importOverleafModules(
'integrationLinkingWidgets'
) as any[]
const availableReferenceLinkingWidgets = importOverleafModules(
'referenceLinkingWidgets'
) as any[]
const availableLangFeedbackLinkingWidgets = importOverleafModules(
'langFeedbackLinkingWidgets'
) as any[]
function LinkingSection() {
useBroadcastUser()
const { t } = useTranslation()
const { subscriptions } = useSSOContext()
const ssoErrorMessage = getMeta('ol-ssoErrorMessage') as string
const projectSyncSuccessMessage = getMeta(
'ol-projectSyncSuccessMessage'
) as string
const [integrationLinkingWidgets] = useState<any[]>(
() =>
getMeta('integrationLinkingWidgets') ||
importOverleafModules('integrationLinkingWidgets')
)
const [referenceLinkingWidgets] = useState<any[]>(
() =>
getMeta('referenceLinkingWidgets') ||
importOverleafModules('referenceLinkingWidgets')
)
const [langFeedbackLinkingWidgets] = useState<any[]>(
() =>
getMeta('langFeedbackLinkingWidgets') ||
importOverleafModules('langFeedbackLinkingWidgets')
)
const ssoErrorMessage = getMeta('ol-ssoErrorMessage')
const projectSyncSuccessMessage = getMeta('ol-projectSyncSuccessMessage')
// hide linking widgets in CI
const integrationLinkingWidgets = getMeta('ol-hideLinkingWidgets')
? []
: availableIntegrationLinkingWidgets
const referenceLinkingWidgets = getMeta('ol-hideLinkingWidgets')
? []
: availableReferenceLinkingWidgets
const langFeedbackLinkingWidgets = getMeta('ol-hideLinkingWidgets')
? []
: availableLangFeedbackLinkingWidgets
const oauth2ServerComponents = importOverleafModules('oauth2Server') as {
import: { default: ElementType }
@ -40,7 +44,7 @@ function LinkingSection() {
const renderSyncSection =
getMeta('ol-isSaas') || getMeta('ol-gitBridgeEnabled')
const showPersonalAccessTokenComponents: boolean =
const showPersonalAccessTokenComponents =
getMeta('ol-showPersonalAccessToken') ||
getMeta('ol-optionalPersonalAccessToken')

View file

@ -4,10 +4,9 @@ import Notification from '@/shared/components/notification'
export default function ManagedAccountAlert() {
const { t } = useTranslation()
const isManaged = getMeta('ol-isManagedAccount', false)
const currentManagedUserAdminEmail: string = getMeta(
'ol-currentManagedUserAdminEmail',
''
const isManaged = getMeta('ol-isManagedAccount')
const currentManagedUserAdminEmail = getMeta(
'ol-currentManagedUserAdminEmail'
)
if (!isManaged) {

View file

@ -6,8 +6,6 @@ import {
postJSON,
} from '../../../infrastructure/fetch-json'
import getMeta from '../../../utils/meta'
import { ExposedSettings } from '../../../../../types/exposed-settings'
import { PasswordStrengthOptions } from '../../../../../types/password-strength-options'
import useAsync from '../../../shared/hooks/use-async'
import OLButton from '@/features/ui/components/ol/ol-button'
import OLNotification from '@/features/ui/components/ol/ol-notification'
@ -24,7 +22,7 @@ type PasswordUpdateResult = {
function PasswordSection() {
const { t } = useTranslation()
const hideChangePassword = getMeta('ol-cannot-change-password') as boolean
const hideChangePassword = getMeta('ol-cannot-change-password')
return (
<>
<h3>{t('change_password')}</h3>
@ -53,11 +51,11 @@ function CanOnlyLogInThroughSSO() {
function PasswordInnerSection() {
const { t } = useTranslation()
const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings
const { isOverleaf } = getMeta('ol-ExposedSettings')
const isExternalAuthenticationSystemUsed = getMeta(
'ol-isExternalAuthenticationSystemUsed'
) as boolean
const hasPassword = getMeta('ol-hasPassword') as boolean
)
const hasPassword = getMeta('ol-hasPassword')
if (isExternalAuthenticationSystemUsed && !isOverleaf) {
return <p>{t('password_managed_externally')}</p>
@ -78,9 +76,7 @@ function PasswordInnerSection() {
function PasswordForm() {
const { t } = useTranslation()
const passwordStrengthOptions = getMeta(
'ol-passwordStrengthOptions'
) as PasswordStrengthOptions
const passwordStrengthOptions = getMeta('ol-passwordStrengthOptions')
const [currentPassword, setCurrentPassword] = useState('')
const [newPassword1, setNewPassword1] = useState('')

View file

@ -18,7 +18,6 @@ import { SSOProvider } from '../context/sso-context'
import { SplitTestProvider } from '@/shared/context/split-test-context'
import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
import useScrollToIdOnLoad from '../../../shared/hooks/use-scroll-to-id-on-load'
import { ExposedSettings } from '../../../../../types/exposed-settings'
import { SSOAlert } from './emails/sso-alert'
import OLRow from '@/features/ui/components/ol/ol-row'
import OLCol from '@/features/ui/components/ol/ol-col'
@ -45,9 +44,7 @@ function SettingsPageRoot() {
function SettingsPageContent() {
const { t } = useTranslation()
const { isOverleaf, labsEnabled } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { isOverleaf, labsEnabled } = getMeta('ol-ExposedSettings')
return (
<UserProvider>

View file

@ -7,14 +7,11 @@ import OLButton from '@/features/ui/components/ol/ol-button'
function SecuritySection() {
const { t } = useTranslation()
const memberOfSSOEnabledGroups = getMeta(
'ol-memberOfSSOEnabledGroups',
[]
) as GroupSSOLinkingStatus[]
const memberOfSSOEnabledGroups = getMeta('ol-memberOfSSOEnabledGroups') || []
return (
<>
{memberOfSSOEnabledGroups?.length > 0 ? (
{memberOfSSOEnabledGroups.length > 0 ? (
<>
<h3>{t('security')}</h3>
{memberOfSSOEnabledGroups.map(

View file

@ -10,11 +10,7 @@ import { postJSON } from '../../../infrastructure/fetch-json'
import useIsMounted from '../../../shared/hooks/use-is-mounted'
import { set, cloneDeep } from 'lodash'
import getMeta from '../../../utils/meta'
import type {
OAuthProviders,
OAuthProvider,
} from '../../../../../types/oauth-providers'
import type { ThirdPartyIds } from '../../../../../types/third-party-ids'
import type { OAuthProvider } from '../../../../../types/oauth-providers'
export type SSOSubscription = {
providerId: string
@ -35,8 +31,8 @@ type SSOProviderProps = {
export function SSOProvider({ children }: SSOProviderProps) {
const isMounted = useIsMounted()
const oauthProviders = getMeta('ol-oauthProviders', {}) as OAuthProviders
const thirdPartyIds = getMeta('ol-thirdPartyIds') as ThirdPartyIds
const oauthProviders = getMeta('ol-oauthProviders') || {}
const thirdPartyIds = getMeta('ol-thirdPartyIds')
const [subscriptions, setSubscriptions] = useState<
Record<string, SSOSubscription>

View file

@ -1,14 +1,11 @@
import getMeta from '../../../utils/meta'
import { DomainInfo } from '../components/emails/add-email/input'
import { ExposedSettings } from '../../../../../types/exposed-settings'
import { Institution } from '../../../../../types/institution'
export const ssoAvailableForDomain = (
domain: DomainInfo | null
): domain is DomainInfo => {
const { hasSamlBeta, hasSamlFeature } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { hasSamlBeta, hasSamlFeature } = getMeta('ol-ExposedSettings')
if (!hasSamlFeature || !domain || !domain.confirmed || !domain.university) {
return false
}
@ -19,9 +16,7 @@ export const ssoAvailableForDomain = (
}
export const ssoAvailableForInstitution = (institution: Institution | null) => {
const { hasSamlBeta, hasSamlFeature } = getMeta(
'ol-ExposedSettings'
) as ExposedSettings
const { hasSamlBeta, hasSamlFeature } = getMeta('ol-ExposedSettings')
if (
!hasSamlFeature ||
!institution ||

View file

@ -14,6 +14,7 @@ import { sendMB } from '../../../infrastructure/event-tracking'
import { getJSON } from '../../../infrastructure/fetch-json'
import useAbortController from '../../../shared/hooks/use-abort-controller'
import { debugConsole } from '@/utils/debugging'
import getMeta from '@/utils/meta'
export default function LinkSharing() {
const [inflight, setInflight] = useState(false)
@ -249,7 +250,7 @@ function AccessToken({ token, tokenHashPrefix, path, tooltipId }) {
let origin = window.location.origin
if (isAdmin) {
origin = window.ExposedSettings.siteUrl
origin = getMeta('ol-ExposedSettings').siteUrl
}
const link = `${origin}${path}${token}${
tokenHashPrefix ? `#${tokenHashPrefix}` : ''

View file

@ -9,6 +9,7 @@ import { useEditorContext } from '../../../shared/context/editor-context'
import { useProjectContext } from '../../../shared/context/project-context'
import { useMemo } from 'react'
import RecaptchaConditions from '../../../shared/components/recaptcha-conditions'
import getMeta from '@/utils/meta'
export default function ShareModalBody() {
const { members, invites, features } = useProjectContext()
@ -56,7 +57,7 @@ export default function ShareModalBody() {
<SendInvitesNotice />
)}
{!window.ExposedSettings.recaptchaDisabled?.invite && (
{!getMeta('ol-ExposedSettings').recaptchaDisabled?.invite && (
<RecaptchaConditions />
)}
</>

View file

@ -5,10 +5,11 @@ import {
putJSON,
} from '../../../infrastructure/fetch-json'
import { executeV2Captcha } from './captcha'
import getMeta from '@/utils/meta'
export function sendInvite(projectId, email, privileges) {
return executeV2Captcha(
window.ExposedSettings.recaptchaDisabled?.invite
getMeta('ol-ExposedSettings').recaptchaDisabled?.invite
).then(grecaptchaResponse => {
return postJSON(`/project/${projectId}/invite`, {
body: {

View file

@ -6,6 +6,7 @@ import {
import Icon from '../../../../shared/components/icon'
import { Button } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import getMeta from '@/utils/meta'
export const FigureModalSourcePicker: FC = () => {
const { t } = useTranslation()
@ -13,7 +14,7 @@ export const FigureModalSourcePicker: FC = () => {
hasLinkedProjectFileFeature,
hasLinkedProjectOutputFileFeature,
hasLinkUrlFeature,
} = window.ExposedSettings
} = getMeta('ol-ExposedSettings')
return (
<div className="figure-modal-source-selector">
<div className="figure-modal-source-button-grid">

View file

@ -22,6 +22,7 @@ import { FileRelocator } from '../file-relocator'
import { useTranslation } from 'react-i18next'
import { waitForFileTreeUpdate } from '../../../extensions/figure-modal'
import { useCodeMirrorViewContext } from '../../codemirror-editor'
import getMeta from '@/utils/meta'
function suggestName(path: string) {
const parts = path.split('/')
@ -36,7 +37,7 @@ export const FigureModalOtherProjectSource: FC = () => {
const { loading: projectsLoading, data: projects, error } = useUserProjects()
const [selectedProject, setSelectedProject] = useState<null | Project>(null)
const { hasLinkedProjectFileFeature, hasLinkedProjectOutputFileFeature } =
window.ExposedSettings
getMeta('ol-ExposedSettings')
const [usingOutputFiles, setUsingOutputFiles] = useState<boolean>(
!hasLinkedProjectFileFeature
)

View file

@ -16,8 +16,7 @@ import { FileRelocator } from '../file-relocator'
import { useTranslation } from 'react-i18next'
import { useCodeMirrorViewContext } from '../../codemirror-editor'
import { waitForFileTreeUpdate } from '../../../extensions/figure-modal'
const maxFileSize = window.ExposedSettings.maxUploadSize
import getMeta from '@/utils/meta'
/* eslint-disable no-unused-vars */
export enum FileUploadStatus {
@ -46,7 +45,7 @@ export const FigureModalUploadFileSource: FC = () => {
allowMultipleUploadBatches: false,
restrictions: {
maxNumberOfFiles: 1,
maxFileSize: maxFileSize || null,
maxFileSize: getMeta('ol-ExposedSettings').maxUploadSize,
allowedFileTypes: ['image/*', '.pdf'],
},
autoProceed: false,
@ -55,7 +54,7 @@ export const FigureModalUploadFileSource: FC = () => {
.use(XHRUpload, {
endpoint: `/project/${projectId}/upload?folder_id=${rootFile.id}`,
headers: {
'X-CSRF-TOKEN': window.csrfToken,
'X-CSRF-TOKEN': getMeta('ol-csrfToken'),
},
// limit: maxConnections || 1,
limit: 1,

View file

@ -7,10 +7,9 @@ import GrammarlyLogo from '@/shared/svgs/grammarly-logo'
import * as eventTracking from '../../../infrastructure/event-tracking'
import useWaitForGrammarlyCheck from '@/shared/hooks/use-wait-for-grammarly-check'
import getMeta from '@/utils/meta'
import { ExposedSettings } from '../../../../../types/exposed-settings'
export default function GrammarlyAdvert() {
const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings
const { isOverleaf } = getMeta('ol-ExposedSettings')
const [show, setShow] = useState(false)
const { t } = useTranslation()

View file

@ -7,6 +7,7 @@ import { useTranslation } from 'react-i18next'
import { emitToolbarEvent } from '../../extensions/toolbar/utils/analytics'
import { useCodeMirrorViewContext } from '../codemirror-editor'
import { insertFigure } from '../../extensions/toolbar/commands'
import getMeta from '@/utils/meta'
export const InsertFigureDropdown = memo(function InsertFigureDropdown() {
const { t } = useTranslation()
@ -26,7 +27,7 @@ export const InsertFigureDropdown = memo(function InsertFigureDropdown() {
hasLinkedProjectFileFeature,
hasLinkedProjectOutputFileFeature,
hasLinkUrlFeature,
} = window.ExposedSettings
} = getMeta('ol-ExposedSettings')
return (
<ToolbarButtonMenu
id="toolbar-figure"

View file

@ -59,6 +59,7 @@ import { DocumentContainer } from '@/features/ide-react/editor/document-containe
import { useLayoutContext } from '@/shared/context/layout-context'
import { debugConsole } from '@/utils/debugging'
import { useMetadataContext } from '@/features/ide-react/context/metadata-context'
import { useUserContext } from '@/shared/context/user-context'
function useCodeMirrorScope(view: EditorView) {
const { fileTreeData } = useFileTreeData()
@ -82,6 +83,7 @@ function useCodeMirrorScope(view: EditorView) {
const [docName] = useScopeValue<string>('editor.open_doc_name')
const [trackChanges] = useScopeValue<boolean>('editor.trackChanges')
const { id: userId } = useUserContext()
const { userSettings } = useUserSettingsContext()
const {
fontFamily,
@ -175,12 +177,12 @@ function useCodeMirrorScope(view: EditorView) {
if (currentDoc) {
if (trackChanges) {
currentDoc.track_changes_as = window.user.id || 'anonymous'
currentDoc.track_changes_as = userId || 'anonymous'
} else {
currentDoc.track_changes_as = null
}
}
}, [currentDoc, trackChanges])
}, [userId, currentDoc, trackChanges])
useEffect(() => {
if (lineHeight && fontSize) {

View file

@ -1,7 +1,6 @@
import { RowLink } from '@/features/subscription/components/dashboard/row-link'
import getMeta from '@/utils/meta'
import { useTranslation } from 'react-i18next'
import { ExposedSettings } from '../../../../../../types/exposed-settings'
import { ManagedGroupSubscription } from '../../../../../../types/subscription/dashboard/subscription'
export default function GroupSettingsButton({
@ -11,10 +10,7 @@ export default function GroupSettingsButton({
}) {
const { t } = useTranslation()
const { groupSSOEnabled } = getMeta(
'ol-ExposedSettings',
{}
) as ExposedSettings
const { groupSSOEnabled } = getMeta('ol-ExposedSettings')
const subscriptionHasManagedUsers =
subscription.features?.managedUsers !== false

View file

@ -22,9 +22,7 @@ export default function GroupSubscriptionMembership({
}
// Hide leave group button for managed users
const hideLeaveButton = getMeta(
'ol-cannot-leave-group-subscription'
) as boolean
const hideLeaveButton = getMeta('ol-cannot-leave-group-subscription')
return (
<div>

View file

@ -10,7 +10,7 @@ function ManagedGroupAdministrator({
}: {
subscription: ManagedGroupSubscription
}) {
const usersEmail = getMeta('ol-usersEmail') as string
const usersEmail = getMeta('ol-usersEmail')
const values = {
planName: subscription.planLevelName,
groupName: subscription.teamName || '',
@ -90,10 +90,7 @@ export default function ManagedGroupSubscriptions() {
return null
}
const groupSettingsEnabledFor = getMeta(
'ol-groupSettingsEnabledFor',
[]
) as string[]
const groupSettingsEnabledFor = getMeta('ol-groupSettingsEnabledFor') || []
return (
<>

View file

@ -2,9 +2,10 @@ import { useCallback, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { postJSON } from '../../../../infrastructure/fetch-json'
import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context'
import { Institution } from './managed-institutions'
import { ManagedInstitution as Institution } from '../../../../../../types/subscription/dashboard/managed-institution'
import { RowLink } from './row-link'
import { debugConsole } from '@/utils/debugging'
import getMeta from '@/utils/meta'
type ManagedInstitutionProps = {
institution: Institution
@ -84,7 +85,7 @@ export default function ManagedInstitution({
}
>
{institution.metricsEmail.optedOutUserIds.includes(
window.user_id!
getMeta('ol-user_id')!
)
? t('subscribe')
: t('unsubscribe')}

Some files were not shown because too many files have changed in this diff Show more