diff --git a/services/web/.eslintrc b/services/web/.eslintrc index 05775e78e3..4edc2a311f 100644 --- a/services/web/.eslintrc +++ b/services/web/.eslintrc @@ -94,9 +94,6 @@ // Backend specific rules "files": ["**/app/src/**/*.js", "app.js"], "rules": { - // don't allow console.log in backend code - "no-console": "error", - // do not allow importing of implicit dependencies. "import/no-extraneous-dependencies": ["error", { // do not allow importing of devDependencies. @@ -179,8 +176,6 @@ "angular": true, "ace": true, "ga": true, - "sl_console": true, - "sl_debugging": true, // Injected in layout.pug "user_id": true, "ExposedSettings": true @@ -274,6 +269,28 @@ "packageDir": [".", "../../"] }] } + }, + { + "files": [ + // Backend: Use @overleaf/logger + // Docs: https://manual.dev-overleaf.com/development/code/logging/#structured-logging + "**/app/**/*.{js,cjs,mjs}", "app.js", "modules/*/*.js", + // Frontend: Prefer debugConsole over bare console + // Docs: https://manual.dev-overleaf.com/development/code/logging/#frontend + "**/frontend/**/*.{js,ts,tsx}" + ], + "excludedFiles": [ + // Allow console logs in scripts + "**/scripts/**/*.js", + // Allow console logs in stories + "**/stories/**/*.{js,ts,tsx}", + // Workers do not have access to the search params for enabling ?debug=true. + // self.location.url is the URL of the worker script. + "*.worker.{js,ts}" + ], + "rules": { + "no-console": "error" + } } ] } diff --git a/services/web/docker-compose.cypress.yml b/services/web/docker-compose.cypress.yml index ee98edd71b..b5d6414e1e 100644 --- a/services/web/docker-compose.cypress.yml +++ b/services/web/docker-compose.cypress.yml @@ -8,5 +8,6 @@ services: entrypoint: npm user: "${DOCKER_USER:-1000:1000}" environment: - - "DISPLAY=${DISPLAY:-:0}" -# - "DEBUG=cypress.*" + VERBOSE_LOGGING: + DISPLAY: ${DISPLAY:-:0} +# DEBUG: cypress.* diff --git a/services/web/docker-compose.yml b/services/web/docker-compose.yml index 7149907c34..b135f4f38a 100644 --- a/services/web/docker-compose.yml +++ b/services/web/docker-compose.yml @@ -72,6 +72,7 @@ services: environment: MOCHA_GREP: ${MOCHA_GREP} NODE_OPTIONS: "--unhandled-rejections=strict" + VERBOSE_LOGGING: command: npm run --silent test:frontend user: node @@ -80,6 +81,8 @@ services: volumes: - ../../:/overleaf working_dir: /overleaf/services/web + environment: + VERBOSE_LOGGING: entrypoint: npm command: - "run" diff --git a/services/web/frontend/js/base.js b/services/web/frontend/js/base.js index ca3e882532..b327f3bcdb 100644 --- a/services/web/frontend/js/base.js +++ b/services/web/frontend/js/base.js @@ -56,8 +56,4 @@ App.run(($rootScope, $templateCache) => { ) }) -const sl_debugging = window.location.search.match(/debug=true/) -window.sl_debugging = sl_debugging // make a global flag for debugging code -window.sl_console = sl_debugging ? console : { log() {} } - export default App diff --git a/services/web/frontend/js/features/chat/components/message-content.tsx b/services/web/frontend/js/features/chat/components/message-content.tsx index c76eaaf511..3f64a0d07e 100644 --- a/services/web/frontend/js/features/chat/components/message-content.tsx +++ b/services/web/frontend/js/features/chat/components/message-content.tsx @@ -4,6 +4,7 @@ import Linkify from 'react-linkify' import useIsMounted from '../../../shared/hooks/use-is-mounted' import { configureMathJax } from '../../mathjax/configure' import { loadMathJax } from '../../mathjax/load-mathjax' +import { debugConsole } from '@/utils/debugging' const MessageContent: FC<{ content: string }> = ({ content }) => { const root = useRef(null) @@ -33,14 +34,10 @@ const MessageContent: FC<{ content: string }> = ({ content }) => { loadMathJax() .then(MathJax => { if (mounted.current) { - MathJax.typesetPromise([root.current]).catch((error: Error) => { - console.error(error) - }) + MathJax.typesetPromise([root.current]).catch(debugConsole.error) } }) - .catch(error => { - console.error(error) - }) + .catch(debugConsole.error) } }, [content, mounted]) diff --git a/services/web/frontend/js/features/dictionary/components/dictionary-modal-content.tsx b/services/web/frontend/js/features/dictionary/components/dictionary-modal-content.tsx index 210d163e7e..cd0af3cd77 100644 --- a/services/web/frontend/js/features/dictionary/components/dictionary-modal-content.tsx +++ b/services/web/frontend/js/features/dictionary/components/dictionary-modal-content.tsx @@ -6,6 +6,7 @@ import Tooltip from '../../../shared/components/tooltip' import useAsync from '../../../shared/hooks/use-async' import { postJSON } from '../../../infrastructure/fetch-json' import ignoredWords from '../ignored-words' +import { debugConsole } from '@/utils/debugging' type DictionaryModalContentProps = { handleHide: () => void @@ -29,7 +30,7 @@ export default function DictionaryModalContent({ word, }, }) - ).catch(console.error) + ).catch(debugConsole.error) }, [runAsync] ) diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-project-wide-settings.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-project-wide-settings.tsx index 46ec402ae1..c5960fc21e 100644 --- a/services/web/frontend/js/features/editor-left-menu/hooks/use-project-wide-settings.tsx +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-project-wide-settings.tsx @@ -4,6 +4,7 @@ import type { ProjectSettings } from '../utils/api' import useRootDocId from './use-root-doc-id' import useSaveProjectSettings from './use-save-project-settings' import useSetSpellCheckLanguage from './use-set-spell-check-language' +import { debugConsole } from '@/utils/debugging' export default function useProjectWideSettings() { // The value will be undefined on mount @@ -12,14 +13,14 @@ export default function useProjectWideSettings() { const setCompiler = useCallback( (newCompiler: ProjectSettings['compiler']) => { - saveProjectSettings('compiler', newCompiler).catch(console.error) + saveProjectSettings('compiler', newCompiler).catch(debugConsole.error) }, [saveProjectSettings] ) const setImageName = useCallback( (newImageName: ProjectSettings['imageName']) => { - saveProjectSettings('imageName', newImageName).catch(console.error) + saveProjectSettings('imageName', newImageName).catch(debugConsole.error) }, [saveProjectSettings] ) diff --git a/services/web/frontend/js/features/editor-left-menu/utils/api.ts b/services/web/frontend/js/features/editor-left-menu/utils/api.ts index c573542b84..f888bc61f6 100644 --- a/services/web/frontend/js/features/editor-left-menu/utils/api.ts +++ b/services/web/frontend/js/features/editor-left-menu/utils/api.ts @@ -10,6 +10,7 @@ import type { } from '../../../../../types/project-settings' import { sendMB } from '../../../infrastructure/event-tracking' import { postJSON } from '../../../infrastructure/fetch-json' +import { debugConsole } from '@/utils/debugging' export type UserSettings = { pdfViewer: PdfViewer @@ -50,7 +51,7 @@ export function saveUserSettings( body: { [key]: value, }, - }).catch(console.error) + }).catch(debugConsole.error) } export const saveProjectSettings = async ( diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.js index e63a571d1d..4fbda08c3c 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.js +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.js @@ -13,6 +13,7 @@ import '@uppy/core/dist/style.css' import '@uppy/dashboard/dist/style.css' import { refreshProjectMetadata } from '../../../util/api' import ErrorMessage from '../error-message' +import { debugConsole } from '@/utils/debugging' export default function FileTreeUploadDoc() { const { parentFolderId, cancel, isDuplicate, droppedFiles, setDroppedFiles } = @@ -114,7 +115,7 @@ export default function FileTreeUploadDoc() { break default: - console.error(error) + debugConsole.error(error) setError(response?.body?.error || 'generic_something_went_wrong') break } diff --git a/services/web/frontend/js/features/file-view/components/file-view-header.js b/services/web/frontend/js/features/file-view/components/file-view-header.js index 154860390e..5a7d8bb3d3 100644 --- a/services/web/frontend/js/features/file-view/components/file-view-header.js +++ b/services/web/frontend/js/features/file-view/components/file-view-header.js @@ -11,6 +11,7 @@ import { useProjectContext } from '../../../shared/context/project-context' import importOverleafModules from '../../../../macros/import-overleaf-module.macro' import useAbortController from '../../../shared/hooks/use-abort-controller' import { LinkedFileIcon } from './file-view-icons' +import { debugConsole } from '@/utils/debugging' const tprLinkedFileInfo = importOverleafModules('tprLinkedFileInfo') const tprLinkedFileRefreshError = importOverleafModules( 'tprLinkedFileRefreshError' @@ -102,9 +103,7 @@ export default function FileViewHeader({ file, storeReferencesKeys }) { // Later updated by the socket but also updated here for immediate use storeReferencesKeys(response.keys) }) - .catch(error => { - console.log(error) - }) + .catch(debugConsole.error) } }, [file, projectId, signal, storeReferencesKeys]) diff --git a/services/web/frontend/js/features/file-view/components/file-view-text.js b/services/web/frontend/js/features/file-view/components/file-view-text.js index 022c6f4591..6df85ff3c3 100644 --- a/services/web/frontend/js/features/file-view/components/file-view-text.js +++ b/services/web/frontend/js/features/file-view/components/file-view-text.js @@ -1,6 +1,7 @@ import { useState, useEffect } from 'react' import PropTypes from 'prop-types' import { useProjectContext } from '../../../shared/context/project-context' +import { debugConsole } from '@/utils/debugging' const MAX_FILE_SIZE = 2 * 1024 * 1024 @@ -47,7 +48,7 @@ export default function FileViewText({ file, onLoad, onError }) { }) }) .catch(err => { - console.error(err) + debugConsole.error(err) onError() }) .finally(() => { diff --git a/services/web/frontend/js/features/form-helpers/captcha.js b/services/web/frontend/js/features/form-helpers/captcha.js index dab36d197d..50812f59d9 100644 --- a/services/web/frontend/js/features/form-helpers/captcha.js +++ b/services/web/frontend/js/features/form-helpers/captcha.js @@ -1,5 +1,6 @@ import 'abort-controller/polyfill' import { postJSON } from '../../infrastructure/fetch-json' +import { debugConsole } from '@/utils/debugging' const grecaptcha = window.grecaptcha @@ -50,7 +51,7 @@ function emitError(err, src) { `captcha check failed: ${getMessage(err)}, please retry again` ) // Keep a record of this error. 2nd line might request a screenshot of it. - console.error(err, src) + debugConsole.error(err, src) recaptchaCallbacks.splice(0).forEach(({ reject, resetTimeout }) => { resetTimeout() diff --git a/services/web/frontend/js/features/group-management/components/managed-users/offboard-managed-user-modal.tsx b/services/web/frontend/js/features/group-management/components/managed-users/offboard-managed-user-modal.tsx index d640374426..2750da822a 100644 --- a/services/web/frontend/js/features/group-management/components/managed-users/offboard-managed-user-modal.tsx +++ b/services/web/frontend/js/features/group-management/components/managed-users/offboard-managed-user-modal.tsx @@ -15,6 +15,7 @@ import useAsync from '../../../../shared/hooks/use-async' import { useTranslation } from 'react-i18next' import { useLocation } from '../../../../shared/hooks/use-location' import { FetchError, postJSON } from '../../../../infrastructure/fetch-json' +import { debugConsole } from '@/utils/debugging' type OffboardManagedUserModalProps = { user: User @@ -59,7 +60,7 @@ export default function OffboardManagedUserModal({ location.reload() }) .catch(err => { - console.error(err) + debugConsole.error(err) setError( err instanceof FetchError ? err.getUserFacingMessage() : err.message ) diff --git a/services/web/frontend/js/features/group-management/components/managers-table.tsx b/services/web/frontend/js/features/group-management/components/managers-table.tsx index a21704c642..6faebc985d 100644 --- a/services/web/frontend/js/features/group-management/components/managers-table.tsx +++ b/services/web/frontend/js/features/group-management/components/managers-table.tsx @@ -14,6 +14,7 @@ import ErrorAlert, { APIError } from './error-alert' import GroupMemberRow from './group-member-row' import useUserSelection from '../hooks/use-user-selection' import { User } from '../../../../../types/group-management/user' +import { debugConsole } from '@/utils/debugging' type ManagersPaths = { addMember: string @@ -77,7 +78,7 @@ export function ManagersTable({ } setEmailString('') } catch (error: unknown) { - console.error(error) + debugConsole.error(error) setInviteError((error as FetchError)?.data?.error || {}) } setInviteUserInflightCount(count => count - 1) @@ -105,7 +106,7 @@ export function ManagersTable({ setUsers(users => users.filter(u => u !== user)) unselectUser(user) } catch (error: unknown) { - console.error(error) + debugConsole.error(error) setRemoveMemberError((error as FetchError)?.data?.error || {}) } setRemoveMemberInflightCount(count => count - 1) diff --git a/services/web/frontend/js/features/group-management/context/group-members-context.tsx b/services/web/frontend/js/features/group-management/context/group-members-context.tsx index 34b78be24e..069ea629bc 100644 --- a/services/web/frontend/js/features/group-management/context/group-members-context.tsx +++ b/services/web/frontend/js/features/group-management/context/group-members-context.tsx @@ -17,6 +17,7 @@ import getMeta from '../../../utils/meta' import { APIError } from '../components/error-alert' import useUserSelection from '../hooks/use-user-selection' import { parseEmails } from '../utils/emails' +import { debugConsole } from '@/utils/debugging' export type GroupMembersContextValue = { users: User[] @@ -94,7 +95,7 @@ export function GroupMembersProvider({ children }: GroupMembersProviderProps) { } } } catch (error: unknown) { - console.error(error) + debugConsole.error(error) setInviteError((error as FetchError)?.data?.error || {}) } setInviteUserInflightCount(count => count - 1) @@ -119,7 +120,7 @@ export function GroupMembersProvider({ children }: GroupMembersProviderProps) { setUsers(users => users.filter(u => u !== user)) unselectUser(user) } catch (error: unknown) { - console.error(error) + debugConsole.error(error) setRemoveMemberError((error as FetchError)?.data?.error || {}) } setRemoveMemberInflightCount(count => count - 1) diff --git a/services/web/frontend/js/features/history/components/change-list/add-label-modal.tsx b/services/web/frontend/js/features/history/components/change-list/add-label-modal.tsx index 15196c8b7a..92cc4f35de 100644 --- a/services/web/frontend/js/features/history/components/change-list/add-label-modal.tsx +++ b/services/web/frontend/js/features/history/components/change-list/add-label-modal.tsx @@ -10,6 +10,7 @@ import { useHistoryContext } from '../../context/history-context' import { addLabel } from '../../services/api' import { Label } from '../../services/types/label' import { useRefWithAutoFocus } from '../../../../shared/hooks/use-ref-with-auto-focus' +import { debugConsole } from '@/utils/debugging' type AddLabelModalProps = { show: boolean @@ -59,7 +60,7 @@ function AddLabelModal({ show, setShow, version }: AddLabelModalProps) { runAsync(addLabel(projectId, { comment, version }, signal)) .then(() => setShow(false)) - .catch(console.error) + .catch(debugConsole.error) } const responseError = error as unknown as { diff --git a/services/web/frontend/js/features/history/components/change-list/all-history-list.tsx b/services/web/frontend/js/features/history/components/change-list/all-history-list.tsx index 15ab7c08ca..055ef90cf9 100644 --- a/services/web/frontend/js/features/history/components/change-list/all-history-list.tsx +++ b/services/web/frontend/js/features/history/components/change-list/all-history-list.tsx @@ -14,6 +14,7 @@ import { Trans, useTranslation } from 'react-i18next' import MaterialIcon from '@/shared/components/material-icon' import useAsync from '@/shared/hooks/use-async' import { completeHistoryTutorial } from '../../services/api' +import { debugConsole } from '@/utils/debugging' type CompletedTutorials = { 'react-history-buttons-tutorial': Date @@ -135,7 +136,7 @@ function AllHistoryList() { ) { const dismissModal = () => { completeTutorial() - runAsync(completeHistoryTutorial()).catch(console.error) + runAsync(completeHistoryTutorial()).catch(debugConsole.error) } popover = ( diff --git a/services/web/frontend/js/features/history/components/change-list/tag-tooltip.tsx b/services/web/frontend/js/features/history/components/change-list/tag-tooltip.tsx index 4af7345ab0..5fc9ae3a0b 100644 --- a/services/web/frontend/js/features/history/components/change-list/tag-tooltip.tsx +++ b/services/web/frontend/js/features/history/components/change-list/tag-tooltip.tsx @@ -14,6 +14,7 @@ import { deleteLabel } from '../../services/api' import { isPseudoLabel } from '../../utils/label' import { formatDate } from '../../../../utils/dates' import { LoadedLabel } from '../../services/types/label' +import { debugConsole } from '@/utils/debugging' type TagProps = { label: LoadedLabel @@ -50,7 +51,7 @@ function Tag({ label, currentUserId, ...props }: TagProps) { const localDeleteHandler = () => { runAsync(deleteLabel(projectId, label.id, signal)) .then(() => setShowDeleteModal(false)) - .catch(console.error) + .catch(debugConsole.error) } const responseError = error as unknown as { diff --git a/services/web/frontend/js/features/history/utils/wait-for.ts b/services/web/frontend/js/features/history/utils/wait-for.ts index f7ef2cdd21..253fd1f276 100644 --- a/services/web/frontend/js/features/history/utils/wait-for.ts +++ b/services/web/frontend/js/features/history/utils/wait-for.ts @@ -1,3 +1,5 @@ +import { debugConsole } from '@/utils/debugging' + export function waitFor( testFunction: () => T, timeout: number, @@ -12,7 +14,7 @@ export function waitFor( const err = new Error( `waiting too long, ${JSON.stringify({ timeout, pollInterval })}` ) - console.error(err) + debugConsole.error(err) reject(err) return } diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js b/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js index 20a98081c2..6232f4bb70 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js @@ -12,6 +12,7 @@ import { useDetachCompileContext as useCompileContext } from '../../../shared/co import { captureException } from '../../../infrastructure/error-reporter' import * as eventTracking from '../../../infrastructure/event-tracking' import { getPdfCachingMetrics } from '../util/metrics' +import { debugConsole } from '@/utils/debugging' function PdfJsViewer({ url, pdfFile }) { const { _id: projectId } = useProjectContext() @@ -136,7 +137,7 @@ function PdfJsViewer({ url, pdfFile }) { .loadDocument({ url, pdfFile, abortController, handleFetchError }) .catch(error => { if (abortController.signal.aborted) return - console.error(error) + debugConsole.error(error) setError('rendering-error') }) return () => { @@ -161,7 +162,7 @@ function PdfJsViewer({ url, pdfFile }) { try { setPosition(pdfViewer.currentPosition) } catch (error) { - // console.error(error) + // debugConsole.error(error) } }, 500) diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js b/services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js index ae0e6d01f4..145adf12eb 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-synctex-controls.js @@ -19,6 +19,7 @@ import localStorage from '../../../infrastructure/local-storage' import { useFileTreeData } from '../../../shared/context/file-tree-data-context' import useScopeEventListener from '../../../shared/hooks/use-scope-event-listener' import * as eventTracking from '../../../infrastructure/event-tracking' +import { debugConsole } from '@/utils/debugging' function GoToCodeButton({ position, @@ -209,9 +210,7 @@ function PdfSynctexControls() { setShowLogs(false) setHighlights(data.pdf) }) - .catch(error => { - console.error(error) - }) + .catch(debugConsole.error) .finally(() => { if (isMounted.current) { setSyncToPdfInFlight(false) @@ -297,9 +296,7 @@ function PdfSynctexControls() { const [{ file, line }] = data.code goToCodeLine(file, line) }) - .catch(error => { - console.error(error) - }) + .catch(debugConsole.error) .finally(() => { if (isMounted.current) { setSyncToCodeInFlight(false) diff --git a/services/web/frontend/js/features/pdf-preview/util/compiler.js b/services/web/frontend/js/features/pdf-preview/util/compiler.js index 5ac589cbae..9d43bc23c5 100644 --- a/services/web/frontend/js/features/pdf-preview/util/compiler.js +++ b/services/web/frontend/js/features/pdf-preview/util/compiler.js @@ -4,6 +4,7 @@ import { deleteJSON, postJSON } from '../../../infrastructure/fetch-json' import { debounce } from 'lodash' import { trackPdfDownload } from './metrics' import { enablePdfCaching } from './pdf-caching-flags' +import { debugConsole } from '@/utils/debugging' const AUTO_COMPILE_MAX_WAIT = 5000 // We add a 2 second debounce to sending user changes to server if they aren't @@ -127,7 +128,7 @@ export default class DocumentCompiler { } this.setData(data) } catch (error) { - console.error(error) + debugConsole.error(error) this.cleanupCompileResult() this.setError(error.info?.statusCode === 429 ? 'rate-limited' : 'error') } finally { @@ -206,7 +207,7 @@ export default class DocumentCompiler { signal: this.signal, }) .catch(error => { - console.error(error) + debugConsole.error(error) this.setError('error') }) .finally(() => { @@ -221,7 +222,7 @@ export default class DocumentCompiler { return deleteJSON(`/project/${this.projectId}/output?${params}`, { signal: this.signal, }).catch(error => { - console.error(error) + debugConsole.error(error) this.setError('clear-cache') }) } diff --git a/services/web/frontend/js/features/pdf-preview/util/metrics.js b/services/web/frontend/js/features/pdf-preview/util/metrics.js index ce683cb128..e80c2138a5 100644 --- a/services/web/frontend/js/features/pdf-preview/util/metrics.js +++ b/services/web/frontend/js/features/pdf-preview/util/metrics.js @@ -1,6 +1,7 @@ import { v4 as uuid } from 'uuid' import { sendMB } from '../../../infrastructure/event-tracking' import { trackPdfDownloadEnabled } from './pdf-caching-flags' +import { debugConsole } from '@/utils/debugging' // VERSION should get incremented when making changes to caching behavior or // adjusting metrics collection. @@ -60,6 +61,6 @@ function submitCompileMetrics(metrics) { ...metrics, id: EDITOR_SESSION_ID, } - sl_console.log('/event/compile-metrics', JSON.stringify(leanMetrics)) + debugConsole.log('/event/compile-metrics', JSON.stringify(leanMetrics)) sendMB('compile-metrics-v6', leanMetrics) } diff --git a/services/web/frontend/js/features/pdf-preview/util/output-files.js b/services/web/frontend/js/features/pdf-preview/util/output-files.js index e04a33c0e9..fa25ce1aab 100644 --- a/services/web/frontend/js/features/pdf-preview/util/output-files.js +++ b/services/web/frontend/js/features/pdf-preview/util/output-files.js @@ -3,6 +3,7 @@ import HumanReadableLogs from '../../../ide/human-readable-logs/HumanReadableLog import BibLogParser from '../../../ide/log-parser/bib-log-parser' import { v4 as uuid } from 'uuid' import { enablePdfCaching } from './pdf-caching-flags' +import { debugConsole } from '@/utils/debugging' // Warnings that may disappear after a second LaTeX pass const TRANSIENT_WARNING_REGEX = /^(Reference|Citation).+undefined on input line/ @@ -91,7 +92,7 @@ export const handleLogFiles = async (outputFiles, data, signal) => { accumulateResults({ errors, warnings, typesetting }) } catch (e) { - console.warn(e) // ignore failure to fetch/parse the log file, but log a warning + debugConsole.warn(e) // ignore failure to fetch/parse the log file, but log a warning } } @@ -119,7 +120,7 @@ export const handleLogFiles = async (outputFiles, data, signal) => { // BibLog parsing errors are ignored } } catch (e) { - console.warn(e) // ignore failure to fetch/parse the log file, but log a warning + debugConsole.warn(e) // ignore failure to fetch/parse the log file, but log a warning } } diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-flags.js b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-flags.js index 0e9968d470..8c15dc4550 100644 --- a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-flags.js +++ b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-flags.js @@ -1,15 +1,16 @@ import getMeta from '../../../utils/meta' +import { debugConsole } from '@/utils/debugging' const hasTextEncoder = typeof TextEncoder !== 'undefined' if (!hasTextEncoder) { - console.warn('TextEncoder is not available. Disabling pdf-caching.') + debugConsole.warn('TextEncoder is not available. Disabling pdf-caching.') } const isOpera = Array.isArray(navigator.userAgentData?.brands) && navigator.userAgentData.brands.some(b => b.brand === 'Opera') if (isOpera) { - console.warn('Browser cache is limited in Opera. Disabling pdf-caching.') + debugConsole.warn('Browser cache is limited in Opera. Disabling pdf-caching.') } function isFlagEnabled(flag) { diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js index 017d488eb0..4630b0f77a 100644 --- a/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js +++ b/services/web/frontend/js/features/pdf-preview/util/pdf-caching-transport.js @@ -10,6 +10,7 @@ import { trackPdfDownloadEnabled, } from './pdf-caching-flags' import { isNetworkError } from '../../../utils/isNetworkError' +import { debugConsole } from '@/utils/debugging' // 30 seconds: The shutdown grace period of a clsi pre-emp instance. const STALE_OUTPUT_REQUEST_THRESHOLD_MS = 30 * 1000 @@ -130,7 +131,7 @@ export function generatePdfCachingTransportFactory(PDFJS) { throw err // This was a fallback request already. Do not retry. } err = OError.tag(err, 'optimized pdf download error', getDebugInfo()) - console.error(err) + debugConsole.error(err) captureException(err, { tags: { fromPdfCaching: true, @@ -160,7 +161,7 @@ export function generatePdfCachingTransportFactory(PDFJS) { .catch(err => { if (abortSignal.aborted) return err = OError.tag(err, 'fatal pdf download error', getDebugInfo()) - console.error(err) + debugConsole.error(err) if (!(err instanceof PDFJS.MissingPDFException)) { captureException(err, { tags: { diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js b/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js index bbfba43777..9b419b1397 100644 --- a/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js +++ b/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js @@ -1,5 +1,6 @@ import { captureException } from '../../../infrastructure/error-reporter' import { generatePdfCachingTransportFactory } from './pdf-caching-transport' +import { debugConsole } from '@/utils/debugging' const params = new URLSearchParams(window.location.search) const disableFontFace = params.get('disable-font-face') === 'true' @@ -112,7 +113,7 @@ export default class PDFJSWrapper { resolve(doc) if (previousDoc) { - previousDoc.cleanup().catch(console.error) + previousDoc.cleanup().catch(debugConsole.error) previousDoc.destroy() } }) diff --git a/services/web/frontend/js/features/project-list/components/modals/create-tag-modal.tsx b/services/web/frontend/js/features/project-list/components/modals/create-tag-modal.tsx index b9e86dcab2..4469495415 100644 --- a/services/web/frontend/js/features/project-list/components/modals/create-tag-modal.tsx +++ b/services/web/frontend/js/features/project-list/components/modals/create-tag-modal.tsx @@ -10,6 +10,7 @@ import useSelectColor from '../../hooks/use-select-color' import { createTag } from '../../util/api' import { MAX_TAG_LENGTH } from '../../util/tag' import { ColorPicker } from '../color-picker/color-picker' +import { debugConsole } from '@/utils/debugging' type CreateTagModalProps = { id: string @@ -39,7 +40,7 @@ export default function CreateTagModal({ if (tagName) { runAsync(createTag(tagName, selectedColor)) .then(tag => onCreate(tag)) - .catch(console.error) + .catch(debugConsole.error) } }, [runAsync, tagName, selectedColor, onCreate]) diff --git a/services/web/frontend/js/features/project-list/components/modals/delete-tag-modal.tsx b/services/web/frontend/js/features/project-list/components/modals/delete-tag-modal.tsx index b4fffe6b77..0fa2e8c4eb 100644 --- a/services/web/frontend/js/features/project-list/components/modals/delete-tag-modal.tsx +++ b/services/web/frontend/js/features/project-list/components/modals/delete-tag-modal.tsx @@ -5,6 +5,7 @@ import { Tag } from '../../../../../../app/src/Features/Tags/types' import AccessibleModal from '../../../../shared/components/accessible-modal' import useAsync from '../../../../shared/hooks/use-async' import { deleteTag } from '../../util/api' +import { debugConsole } from '@/utils/debugging' type DeleteTagModalProps = { id: string @@ -28,7 +29,7 @@ export default function DeleteTagModal({ .then(() => { onDelete(tagId) }) - .catch(console.error) + .catch(debugConsole.error) }, [runAsync, onDelete] ) diff --git a/services/web/frontend/js/features/project-list/components/modals/edit-tag-modal.tsx b/services/web/frontend/js/features/project-list/components/modals/edit-tag-modal.tsx index 35c3e09b0b..31593d1df2 100644 --- a/services/web/frontend/js/features/project-list/components/modals/edit-tag-modal.tsx +++ b/services/web/frontend/js/features/project-list/components/modals/edit-tag-modal.tsx @@ -10,6 +10,7 @@ import useSelectColor from '../../hooks/use-select-color' import { editTag } from '../../util/api' import { getTagColor, MAX_TAG_LENGTH } from '../../util/tag' import { ColorPicker } from '../color-picker/color-picker' +import { debugConsole } from '@/utils/debugging' type EditTagModalProps = { id: string @@ -39,7 +40,7 @@ export function EditTagModal({ id, tag, onEdit, onClose }: EditTagModalProps) { const color = selectedColor runAsync(editTag(tagId, newTagName, color)) .then(() => onEdit(tagId, newTagName, color)) - .catch(console.error) + .catch(debugConsole.error) } }, [runAsync, newTagName, selectedColor, onEdit] diff --git a/services/web/frontend/js/features/project-list/components/modals/manage-tag-modal.tsx b/services/web/frontend/js/features/project-list/components/modals/manage-tag-modal.tsx index 8fcc4361a9..f8b0597226 100644 --- a/services/web/frontend/js/features/project-list/components/modals/manage-tag-modal.tsx +++ b/services/web/frontend/js/features/project-list/components/modals/manage-tag-modal.tsx @@ -9,6 +9,7 @@ import { deleteTag, editTag } from '../../util/api' import { Tag } from '../../../../../../app/src/Features/Tags/types' import { getTagColor } from '../../util/tag' import { ColorPicker } from '../color-picker/color-picker' +import { debugConsole } from '@/utils/debugging' type ManageTagModalProps = { id: string @@ -46,7 +47,7 @@ export function ManageTagModal({ .then(() => { onDelete(tagId) }) - .catch(console.error) + .catch(debugConsole.error) }, [runDeleteAsync, onDelete] ) @@ -56,7 +57,7 @@ export function ManageTagModal({ if (newTagName) { runEditAsync(editTag(tagId, newTagName, selectedColor)) .then(() => onEdit(tagId, newTagName, selectedColor)) - .catch(console.error) + .catch(debugConsole.error) } }, [runEditAsync, newTagName, selectedColor, onEdit] diff --git a/services/web/frontend/js/features/project-list/components/modals/rename-project-modal.tsx b/services/web/frontend/js/features/project-list/components/modals/rename-project-modal.tsx index bad4e26e61..07cac6cbf7 100644 --- a/services/web/frontend/js/features/project-list/components/modals/rename-project-modal.tsx +++ b/services/web/frontend/js/features/project-list/components/modals/rename-project-modal.tsx @@ -15,6 +15,7 @@ import { renameProject } from '../../util/api' import useAsync from '../../../../shared/hooks/use-async' import { useProjectListContext } from '../../context/project-list-context' import { getUserFacingMessage } from '../../../../infrastructure/fetch-json' +import { debugConsole } from '@/utils/debugging' type RenameProjectModalProps = { handleCloseModal: () => void @@ -60,7 +61,7 @@ function RenameProjectModal({ }) handleCloseModal() }) - .catch(console.error) + .catch(debugConsole.error) }, [ handleCloseModal, diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx index 306763b087..d801228104 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx @@ -12,6 +12,7 @@ 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' type ReconfirmAffiliationProps = { email: UserEmailData['email'] @@ -47,7 +48,7 @@ function ReconfirmAffiliation({ postJSON('/user/emails/send-reconfirmation', { body: { email }, }) - ).catch(console.error) + ).catch(debugConsole.error) } } diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/common.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/common.tsx index 5b1a4fcd61..46ac43a03c 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/common.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/common.tsx @@ -13,6 +13,7 @@ import { } from '../../../../../../../types/project/dashboard/notification' import { User } from '../../../../../../../types/user' import GroupInvitationNotification from './group-invitation/group-invitation' +import { debugConsole } from '@/utils/debugging' function Common() { const notifications = getMeta('ol-notifications', []) as NotificationType[] @@ -53,7 +54,7 @@ function CommonNotification({ notification }: CommonNotificationProps) { runAsync( postJSON(`/project/${projectId}/invite/token/${token}/accept`) - ).catch(console.error) + ).catch(debugConsole.error) } const { _id: id, templateKey, html } = notification diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx index 7e9708c453..09409c3924 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx @@ -11,6 +11,7 @@ import { } from '../../../../../infrastructure/fetch-json' import { ExposedSettings } from '../../../../../../../types/exposed-settings' import { UserEmailData } from '../../../../../../../types/user-email' +import { debugConsole } from '@/utils/debugging' const ssoAvailable = ({ samlProviderId, affiliation }: UserEmailData) => { const { hasSamlFeature, hasSamlBeta } = getMeta( @@ -78,7 +79,7 @@ function ConfirmEmailNotification({ userEmail }: { userEmail: UserEmailData }) { postJSON('/user/emails/resend_confirmation', { body: { email }, }) - ).catch(console.error) + ).catch(debugConsole.error) } if (isSuccess) { diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/hooks/use-group-invitation-notification.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/hooks/use-group-invitation-notification.tsx index 0d14c34f28..1c4a79835d 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/hooks/use-group-invitation-notification.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/hooks/use-group-invitation-notification.tsx @@ -15,6 +15,7 @@ import { import { useLocation } from '../../../../../../../shared/hooks/use-location' import getMeta from '../../../../../../../utils/meta' import useAsyncDismiss from '../../../hooks/useAsyncDismiss' +import { debugConsole } from '@/utils/debugging' const SUCCESSFUL_NOTIF_TIME_BEFORE_HIDDEN = 10 * 1000 @@ -85,9 +86,8 @@ export function useGroupInvitationNotification( setGroupInvitationStatus(GroupInvitationStatus.SuccessfullyJoined) }) .catch(err => { + debugConsole.error(err) setGroupInvitationStatus(GroupInvitationStatus.Error) - - console.error(err) }) .finally(() => { // remove notification automatically in the browser @@ -107,7 +107,7 @@ export function useGroupInvitationNotification( _csrf: getMeta('ol-csrfToken'), }, }) - ).catch(console.error) + ).catch(debugConsole.error) }, [runAsync]) const dismissGroupInviteNotification = useCallback(() => { diff --git a/services/web/frontend/js/features/project-list/components/notifications/hooks/useAsyncDismiss.ts b/services/web/frontend/js/features/project-list/components/notifications/hooks/useAsyncDismiss.ts index acfee3b9f5..c7f0c1ba98 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/hooks/useAsyncDismiss.ts +++ b/services/web/frontend/js/features/project-list/components/notifications/hooks/useAsyncDismiss.ts @@ -1,11 +1,12 @@ import useAsync from '../../../../../shared/hooks/use-async' import { deleteJSON } from '../../../../../infrastructure/fetch-json' +import { debugConsole } from '@/utils/debugging' function useAsyncDismiss() { const { runAsync, ...rest } = useAsync() const handleDismiss = (id: number | string) => { - runAsync(deleteJSON(`/notifications/${id}`)).catch(console.error) + runAsync(deleteJSON(`/notifications/${id}`)).catch(debugConsole.error) } return { handleDismiss, ...rest } diff --git a/services/web/frontend/js/features/project-list/components/notifications/system-messages.tsx b/services/web/frontend/js/features/project-list/components/notifications/system-messages.tsx index f33fae3dfa..6133349862 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/system-messages.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/system-messages.tsx @@ -8,6 +8,7 @@ import { SystemMessage as TSystemMessage, SuggestedLanguage, } from '../../../../../../types/project/dashboard/system-message' +import { debugConsole } from '@/utils/debugging' const MESSAGE_POLL_INTERVAL = 15 * 60 * 1000 @@ -24,7 +25,7 @@ function SystemMessages() { return } - runAsync(getJSON('/system/messages')).catch(console.error) + runAsync(getJSON('/system/messages')).catch(debugConsole.error) } pollMessages() diff --git a/services/web/frontend/js/features/project-list/context/project-list-context.tsx b/services/web/frontend/js/features/project-list/context/project-list-context.tsx index 48054c8c05..596e8c206f 100644 --- a/services/web/frontend/js/features/project-list/context/project-list-context.tsx +++ b/services/web/frontend/js/features/project-list/context/project-list-context.tsx @@ -34,6 +34,7 @@ import { isDeletableProject, isLeavableProject, } from '../util/project' +import { debugConsole } from '@/utils/debugging' const MAX_PROJECT_PER_PAGE = 20 @@ -168,7 +169,7 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) { setLoadedProjects(data.projects) setTotalProjectsCount(data.totalSize) }) - .catch(error => console.error(error)) + .catch(debugConsole.error) .finally(() => { setLoadProgress(100) }) diff --git a/services/web/frontend/js/features/settings/components/emails/add-email/input.tsx b/services/web/frontend/js/features/settings/components/emails/add-email/input.tsx index 2a723f2e26..478dc06812 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email/input.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email/input.tsx @@ -10,6 +10,7 @@ import { Nullable } from '../../../../../../../types/utils' import { getJSON } from '../../../../../infrastructure/fetch-json' import useAbortController from '../../../../../shared/hooks/use-abort-controller' import domainBlocklist from '../../../domain-blocklist' +import { debugConsole } from '@/utils/debugging' const LOCAL_AND_DOMAIN_REGEX = /([^@]+)@(.+)/ @@ -109,9 +110,9 @@ function Input({ onChange, handleAddNewEmail }: InputProps) { } }) .catch(error => { + debugConsole.error(error) setSuggestion(null) setMatchedDomain(null) - console.error(error) }) }, [signal, matchedDomain] diff --git a/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt.tsx b/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt.tsx index 773a776ff4..fe3026e4f6 100644 --- a/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt.tsx +++ b/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt.tsx @@ -10,6 +10,7 @@ import { ExposedSettings } from '../../../../../../../types/exposed-settings' import { ssoAvailableForInstitution } from '../../../utils/sso' import Icon from '../../../../../shared/components/icon' import { useLocation } from '../../../../../shared/hooks/use-location' +import { debugConsole } from '@/utils/debugging' type ReconfirmationInfoPromptProps = { email: string @@ -55,7 +56,7 @@ function ReconfirmationInfoPrompt({ email, }, }) - ).catch(console.error) + ).catch(debugConsole.error) } } diff --git a/services/web/frontend/js/features/share-project-modal/components/link-sharing.js b/services/web/frontend/js/features/share-project-modal/components/link-sharing.js index 3fd796494c..13dda1e38e 100644 --- a/services/web/frontend/js/features/share-project-modal/components/link-sharing.js +++ b/services/web/frontend/js/features/share-project-modal/components/link-sharing.js @@ -13,6 +13,7 @@ import { useUserContext } from '../../../shared/context/user-context' 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' export default function LinkSharing({ canAddCollaborators }) { const [inflight, setInflight] = useState(false) @@ -125,7 +126,7 @@ function TokenBasedSharing({ setAccessLevel, inflight, canAddCollaborators }) { useEffect(() => { getJSON(`/project/${projectId}/tokens`, { signal }) .then(data => setTokens(data)) - .catch(error => console.error(error)) + .catch(debugConsole.error) }, [projectId, signal]) return ( @@ -223,7 +224,7 @@ export function ReadOnlyTokenLink() { useEffect(() => { getJSON(`/project/${projectId}/tokens`, { signal }) .then(data => setTokens(data)) - .catch(error => console.error(error)) + .catch(debugConsole.error) }, [projectId, signal]) return ( diff --git a/services/web/frontend/js/features/share-project-modal/controllers/react-share-project-modal-controller.js b/services/web/frontend/js/features/share-project-modal/controllers/react-share-project-modal-controller.js index 5b88a169cb..ef69cd248b 100644 --- a/services/web/frontend/js/features/share-project-modal/controllers/react-share-project-modal-controller.js +++ b/services/web/frontend/js/features/share-project-modal/controllers/react-share-project-modal-controller.js @@ -4,6 +4,7 @@ import { react2angular } from 'react2angular' import ShareProjectModal from '../components/share-project-modal' import { rootContext } from '../../../shared/context/root-context' import { listProjectInvites, listProjectMembers } from '../utils/api' +import { debugConsole } from '@/utils/debugging' App.component( 'shareProjectModal', @@ -41,8 +42,8 @@ export default App.controller( }) } }) - .catch(() => { - console.error('Error fetching members for project') + .catch(err => { + debugConsole.error('Error fetching members for project', err) }) } @@ -55,8 +56,8 @@ export default App.controller( }) } }) - .catch(() => { - console.error('Error fetching invites for project') + .catch(err => { + debugConsole.error('Error fetching invites for project', err) }) } }) diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/contexts/editing-context.tsx b/services/web/frontend/js/features/source-editor/components/table-generator/contexts/editing-context.tsx index 32b188e0aa..eee2d40a4c 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/contexts/editing-context.tsx +++ b/services/web/frontend/js/features/source-editor/components/table-generator/contexts/editing-context.tsx @@ -2,6 +2,7 @@ import { FC, createContext, useCallback, useContext, useState } from 'react' import { useCodeMirrorViewContext } from '../../codemirror-editor' import { useTableContext } from './table-context' import { TableSelection } from './selection-context' +import { debugConsole } from '@/utils/debugging' type EditingContextData = { rowIndex: number @@ -50,7 +51,9 @@ export const EditingContextProvider: FC = ({ children }) => { const currentText = view.state.sliceDoc(from, to) if (currentText !== initialContent && initialContent !== undefined) { // The cell has changed since we started editing, so we don't want to overwrite it - console.error('Cell has changed since editing started, not overwriting') + debugConsole.error( + 'Cell has changed since editing started, not overwriting' + ) return } setInitialContent(undefined) diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts index 52c608fe17..8581f80124 100644 --- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts +++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts @@ -13,6 +13,7 @@ import { extendBackwardsOverEmptyLines, extendForwardsOverEmptyLines, } from '../../../extensions/visual/selection' +import { debugConsole } from '@/utils/debugging' /* eslint-disable no-unused-vars */ export enum BorderTheme { @@ -284,7 +285,7 @@ export const removeRowOrColumns = ( const from = cellPosition.from const to = cellSeparators[row][cellIndex].to if (from === undefined || to === undefined) { - console.error('Failed to remove column') + debugConsole.error('Failed to remove column') return selection } changes.push({ @@ -298,7 +299,7 @@ export const removeRowOrColumns = ( const from = cellSeparators[row][cellIndex - 1].from const to = cellPosition.to if (from === undefined || to === undefined) { - console.error('Failed to remove column') + debugConsole.error('Failed to remove column') return selection } changes.push({ diff --git a/services/web/frontend/js/features/source-editor/extensions/annotations.ts b/services/web/frontend/js/features/source-editor/extensions/annotations.ts index e9c33119d4..d99ef399d3 100644 --- a/services/web/frontend/js/features/source-editor/extensions/annotations.ts +++ b/services/web/frontend/js/features/source-editor/extensions/annotations.ts @@ -10,6 +10,7 @@ import { Text, } from '@codemirror/state' import { Annotation } from '../../../../../types/annotation' +import { debugConsole } from '@/utils/debugging' const compileLintSourceConf = new Compartment() @@ -115,7 +116,7 @@ export const setAnnotations = (doc: Text, annotations: Annotation[]) => { diagnostics.push(convertAnnotationToDiagnostic(doc, annotation)) } catch (error) { // ignore invalid annotations - console.debug('invalid annotation position', error) + debugConsole.debug('invalid annotation position', error) } } } diff --git a/services/web/frontend/js/features/source-editor/extensions/cursor-highlights.ts b/services/web/frontend/js/features/source-editor/extensions/cursor-highlights.ts index 7928e6dc31..1f9ca1aed3 100644 --- a/services/web/frontend/js/features/source-editor/extensions/cursor-highlights.ts +++ b/services/web/frontend/js/features/source-editor/extensions/cursor-highlights.ts @@ -17,6 +17,7 @@ import { import { findValidPosition } from '../utils/position' import { Highlight } from '../../../../../types/highlight' import { fullHeightCoordsAtPos, getBase } from '../utils/layer' +import { debugConsole } from '@/utils/debugging' /** * A custom extension that displays collaborator cursors in a separate layer. @@ -100,7 +101,7 @@ const cursorHighlightsState = StateField.define>({ ) } catch (error) { // ignore invalid highlights - console.debug('invalid highlight position', error) + debugConsole.debug('invalid highlight position', error) } } } diff --git a/services/web/frontend/js/features/source-editor/extensions/cursor-position.ts b/services/web/frontend/js/features/source-editor/extensions/cursor-position.ts index 6a61e0c5aa..eafa407dce 100644 --- a/services/web/frontend/js/features/source-editor/extensions/cursor-position.ts +++ b/services/web/frontend/js/features/source-editor/extensions/cursor-position.ts @@ -8,6 +8,7 @@ import { import { EditorView, ViewPlugin } from '@codemirror/view' import { findValidPosition } from '../utils/position' import customLocalStorage from '../../../infrastructure/local-storage' +import { debugConsole } from '@/utils/debugging' const buildStorageKey = (docId: string) => `doc.position.${docId}` @@ -112,7 +113,7 @@ export const restoreCursorPosition = ( } } catch (error) { // ignore invalid cursor position - console.debug('invalid cursor position', error) + debugConsole.debug('invalid cursor position', error) return {} } } @@ -142,7 +143,7 @@ export const setCursorLineAndScroll = ( selectionRange = EditorSelection.cursor(pos) } catch (error) { // ignore invalid cursor position - console.debug('invalid cursor position', error) + debugConsole.debug('invalid cursor position', error) } if (selectionRange) { @@ -157,7 +158,7 @@ export const setCursorPositionAndScroll = (view: EditorView, pos: number) => { selectionRange = EditorSelection.cursor(pos) } catch (error) { // ignore invalid cursor position - console.debug('invalid cursor position', error) + debugConsole.debug('invalid cursor position', error) } if (selectionRange) { diff --git a/services/web/frontend/js/features/source-editor/extensions/figure-modal.ts b/services/web/frontend/js/features/source-editor/extensions/figure-modal.ts index 00e2a00f09..325bd74397 100644 --- a/services/web/frontend/js/features/source-editor/extensions/figure-modal.ts +++ b/services/web/frontend/js/features/source-editor/extensions/figure-modal.ts @@ -8,6 +8,7 @@ import { EditorView } from '@codemirror/view' import { addEffectListener, removeEffectListener } from './effect-listeners' import { setMetadataEffect } from './language' import getMeta from '../../../utils/meta' +import { debugConsole } from '@/utils/debugging' type NestedReadonly = { readonly [P in keyof T]: NestedReadonly @@ -136,7 +137,7 @@ export function waitForFileTreeUpdate(view: EditorView) { const abortController = new AbortController() const promise = new Promise(resolve => { const abort = () => { - console.warn('Aborting wait for file tree update') + debugConsole.warn('Aborting wait for file tree update') removeEffectListener(view, setMetadataEffect, listener) resolve() } diff --git a/services/web/frontend/js/features/source-editor/extensions/realtime.ts b/services/web/frontend/js/features/source-editor/extensions/realtime.ts index 548316a764..a2946b57bf 100644 --- a/services/web/frontend/js/features/source-editor/extensions/realtime.ts +++ b/services/web/frontend/js/features/source-editor/extensions/realtime.ts @@ -3,6 +3,7 @@ import { EditorView, ViewPlugin } from '@codemirror/view' import { EventEmitter } from 'events' import { CurrentDoc } from '../../../../../types/current-doc' import { ShareDoc } from '../../../../../types/share-doc' +import { debugConsole } from '@/utils/debugging' /* * Integrate CodeMirror 6 with the real-time system, via ShareJS. @@ -51,7 +52,7 @@ export const realtime = ( const ensureRealtimePlugin = EditorView.updateListener.of(update => { if (!update.view.plugin(realtimePlugin)) { const message = 'The realtime extension has been destroyed!!' - console.log(message) + debugConsole.warn(message) if (currentDoc.doc) { // display the "out of sync" modal currentDoc.doc.emit('error', message) @@ -119,9 +120,9 @@ export class EditorFacade extends EventEmitter { if (editorText !== otText) { shareDoc.emit('error', 'Text does not match in CodeMirror 6') - console.error('Text does not match!') - console.error('editor: ' + editorText) - return console.error('ot: ' + otText) + debugConsole.error('Text does not match!') + debugConsole.error('editor: ' + editorText) + debugConsole.error('ot: ' + otText) } }, 0) } diff --git a/services/web/frontend/js/features/source-editor/extensions/scroll-position.ts b/services/web/frontend/js/features/source-editor/extensions/scroll-position.ts index 132481e5a3..98bea6c7ad 100644 --- a/services/web/frontend/js/features/source-editor/extensions/scroll-position.ts +++ b/services/web/frontend/js/features/source-editor/extensions/scroll-position.ts @@ -8,6 +8,7 @@ import { TransactionSpec, } from '@codemirror/state' import { toggleVisualEffect } from './visual/visual' +import { debugConsole } from '@/utils/debugging' const buildStorageKey = (docId: string) => `doc.position.${docId}` @@ -157,7 +158,7 @@ const scrollStoredLineToTop = (doc: Text, docId: string): TransactionSpec => { } } catch (e) { // ignore invalid line number - console.error(e) + debugConsole.error(e) return {} } } diff --git a/services/web/frontend/js/features/source-editor/extensions/spelling/context-menu.ts b/services/web/frontend/js/features/source-editor/extensions/spelling/context-menu.ts index f87fe2a800..e0d516f06c 100644 --- a/services/web/frontend/js/features/source-editor/extensions/spelling/context-menu.ts +++ b/services/web/frontend/js/features/source-editor/extensions/spelling/context-menu.ts @@ -8,6 +8,7 @@ import { EditorView, showTooltip, Tooltip, keymap } from '@codemirror/view' import { addIgnoredWord } from './ignored-words' import { learnWordRequest } from './backend' import { Word, Mark, getMarkAtPosition } from './spellchecker' +import { debugConsole } from '@/utils/debugging' const ITEMS_TO_SHOW = 8 @@ -54,7 +55,7 @@ const handleContextMenuEvent = (event: MouseEvent, view: EditorView) => { const targetWord = value.spec.word if (!targetWord) { - console.debug( + debugConsole.debug( '>> spelling no word associated with decorated range, stopping' ) return @@ -286,7 +287,7 @@ const handleLearnWord = async function (word: Word, view: EditorView) { effects: [addIgnoredWord.of(word), hideSpellingMenu.of(null)], }) } catch (err) { - console.error(err) + debugConsole.error(err) } } @@ -303,7 +304,7 @@ const handleCorrectWord = (word: Word, text: string, view: EditorView) => { // Defend against erroneous replacement, if the word at this // position is not actually what we think it is if (existingText !== word.text) { - console.debug( + debugConsole.debug( '>> spelling word-to-correct does not match, stopping', tooltip.pos, tooltip.end, diff --git a/services/web/frontend/js/features/source-editor/extensions/spelling/spellchecker.ts b/services/web/frontend/js/features/source-editor/extensions/spelling/spellchecker.ts index 57331689dc..410edfae5c 100644 --- a/services/web/frontend/js/features/source-editor/extensions/spelling/spellchecker.ts +++ b/services/web/frontend/js/features/source-editor/extensions/spelling/spellchecker.ts @@ -13,13 +13,10 @@ import { NormalTextSpan, } from '../../utils/tree-query' import { waitForParser } from '../wait-for-parser' - -const DEBUG = window ? window.sl_debugging : false +import { debugConsole } from '@/utils/debugging' const _log = (...args: any) => { - if (DEBUG) { - console.debug('[SpellChecker]: ', ...args) - } + debugConsole.debug('[SpellChecker]: ', ...args) } /* diff --git a/services/web/frontend/js/features/source-editor/extensions/track-changes.ts b/services/web/frontend/js/features/source-editor/extensions/track-changes.ts index f8a2f18b4b..2a2c64c46d 100644 --- a/services/web/frontend/js/features/source-editor/extensions/track-changes.ts +++ b/services/web/frontend/js/features/source-editor/extensions/track-changes.ts @@ -30,6 +30,7 @@ import { Operation, } from '../../../../../types/change' import { ChangeManager } from './changes/change-manager' +import { debugConsole } from '@/utils/debugging' const clearChangesEffect = StateEffect.define() const buildChangesEffect = StateEffect.define() @@ -192,7 +193,7 @@ const buildChangeDecorations = (currentDoc: CurrentDoc) => { decorations.push(...createChangeRange(change, currentDoc)) } catch (error) { // ignore invalid changes - console.debug('invalid change position', error) + debugConsole.debug('invalid change position', error) } } diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts b/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts index 822ea19365..48ffdeb20a 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts @@ -5,6 +5,7 @@ import { pastedContent, storePastedContent, } from './pasted-content' +import { debugConsole } from '@/utils/debugging' export const pasteHtml = [ Prec.highest( @@ -65,7 +66,7 @@ export const pasteHtml = [ return true } catch (error) { - console.error(error) + debugConsole.error(error) // fall back to the default paste handler return false diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts index af66a436d5..bf639fbf59 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts @@ -2,6 +2,7 @@ import { EditorView, WidgetType } from '@codemirror/view' import { placeSelectionInsideBlock } from '../selection' import { isEqual } from 'lodash' import { FigureData } from '../../figure-modal' +import { debugConsole } from '@/utils/debugging' export class GraphicsWidget extends WidgetType { destroyed = false @@ -99,9 +100,7 @@ export class GraphicsWidget extends WidgetType { { const canvas = document.createElement('canvas') canvas.classList.add('ol-cm-graphics') - this.renderPDF(view, canvas, preview.url).catch(error => { - console.error(error) - }) + this.renderPDF(view, canvas, preview.url).catch(debugConsole.error) element.append(canvas) } break diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tabular.tsx b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tabular.tsx index c4e2c6e043..7ec606570b 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tabular.tsx +++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tabular.tsx @@ -7,6 +7,7 @@ import { ParsedTableData, generateTable, } from '../../../components/table-generator/utils' +import { debugConsole } from '@/utils/debugging' export class TabularWidget extends WidgetType { private element: HTMLElement | undefined @@ -23,7 +24,7 @@ export class TabularWidget extends WidgetType { try { this.parseResult = generateTable(tabularNode, state) } catch (e) { - console.error(e) + debugConsole.error(e) this.parseResult = null } } diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual.ts b/services/web/frontend/js/features/source-editor/extensions/visual/visual.ts index 29008c3888..e33c4ba584 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/visual.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual.ts @@ -26,6 +26,7 @@ import { selectDecoratedArgument } from './select-decorated-argument' import { pasteHtml } from './paste-html' import { commandTooltip } from '../command-tooltip' import { tableGeneratorTheme } from './table-generator' +import { debugConsole } from '@/utils/debugging' type Options = { visual: boolean @@ -163,9 +164,7 @@ const showContentWhenParsed = [ window.clearTimeout(fallbackTimer) // show the content, in a timeout so the decorations can build first window.setTimeout(showContent) - }).catch(error => { - console.error(error) - }) + }).catch(debugConsole.error) }) } }, diff --git a/services/web/frontend/js/features/source-editor/languages/latex/debug-print.ts b/services/web/frontend/js/features/source-editor/languages/latex/debug-print.ts index bb4bf0b7f7..77b7b9fe3a 100644 --- a/services/web/frontend/js/features/source-editor/languages/latex/debug-print.ts +++ b/services/web/frontend/js/features/source-editor/languages/latex/debug-print.ts @@ -25,6 +25,7 @@ import { Text } from '@codemirror/state' import { Input, NodeType, SyntaxNode, Tree, TreeCursor } from '@lezer/common' +import { debugConsole } from '@/utils/debugging' class StringInput implements Input { private input: string @@ -278,5 +279,5 @@ export function logTree( input: string, options?: PrintTreeOptions ): void { - console.log(printTree(tree, input, options)) + debugConsole.warn(printTree(tree, input, options)) } diff --git a/services/web/frontend/js/features/source-editor/languages/latex/latex-indent-service.ts b/services/web/frontend/js/features/source-editor/languages/latex/latex-indent-service.ts index e4d6c05867..627895adc4 100644 --- a/services/web/frontend/js/features/source-editor/languages/latex/latex-indent-service.ts +++ b/services/web/frontend/js/features/source-editor/languages/latex/latex-indent-service.ts @@ -1,4 +1,5 @@ import { indentService } from '@codemirror/language' +import { debugConsole } from '@/utils/debugging' export const latexIndentService = () => { return indentService.of((indentContext, pos) => { @@ -10,7 +11,7 @@ export const latexIndentService = () => { return whitespace[0].length } } catch (err) { - console.error('Error in CM indentService', err) + debugConsole.error('Error in CM indentService', err) } return null }) diff --git a/services/web/frontend/js/features/source-editor/lezer-latex/print-tree.mjs b/services/web/frontend/js/features/source-editor/lezer-latex/print-tree.mjs index eed79404f4..a1caf9e9be 100644 --- a/services/web/frontend/js/features/source-editor/lezer-latex/print-tree.mjs +++ b/services/web/frontend/js/features/source-editor/lezer-latex/print-tree.mjs @@ -23,6 +23,7 @@ // SOFTWARE. import { Text } from '@codemirror/state' import { Tree, TreeCursor } from '@lezer/common' +import { debugConsole } from '@/utils/debugging' class StringInput { constructor(input) { @@ -211,5 +212,5 @@ function locAt(text, pos) { } export function logTree(tree, input, options) { - console.log(printTree(tree, input, options)) + debugConsole.warn(printTree(tree, input, options)) } diff --git a/services/web/frontend/js/features/source-editor/themes/convert.js b/services/web/frontend/js/features/source-editor/themes/scripts/convert.js similarity index 98% rename from services/web/frontend/js/features/source-editor/themes/convert.js rename to services/web/frontend/js/features/source-editor/themes/scripts/convert.js index 2a3fbce577..ee3ccfef6f 100644 --- a/services/web/frontend/js/features/source-editor/themes/convert.js +++ b/services/web/frontend/js/features/source-editor/themes/scripts/convert.js @@ -20,9 +20,9 @@ const overrides = require('./overrides.json') const { merge } = require('lodash') // CSS files from https://github.com/overleaf/ace/tree/overleaf/lib/ace/theme copied into the "ace" folder -const themePaths = globby.sync(['ace/*.css'], { cwd: __dirname }) +const themePaths = globby.sync(['ace/*.css'], { cwd: path.dirname(__dirname) }) -const outputDir = path.join(__dirname, 'cm6') +const outputDir = path.join(path.dirname(__dirname), 'cm6') // from js/ide.js const darkThemes = [ diff --git a/services/web/frontend/js/features/source-editor/themes/overrides.json b/services/web/frontend/js/features/source-editor/themes/scripts/overrides.json similarity index 100% rename from services/web/frontend/js/features/source-editor/themes/overrides.json rename to services/web/frontend/js/features/source-editor/themes/scripts/overrides.json diff --git a/services/web/frontend/js/features/subscription/components/dashboard/leave-group-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/leave-group-modal.tsx index 0386cc86cc..542181a2f7 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/leave-group-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/leave-group-modal.tsx @@ -5,6 +5,7 @@ import { deleteJSON } from '../../../../infrastructure/fetch-json' import AccessibleModal from '../../../../shared/components/accessible-modal' import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context' import { useLocation } from '../../../../shared/hooks/use-location' +import { debugConsole } from '@/utils/debugging' export const LEAVE_GROUP_MODAL_ID = 'leave-group' @@ -26,7 +27,7 @@ export default function LeaveGroupModal() { await deleteJSON(`/subscription/group/user?${params}`) location.reload() } catch (error) { - console.log('something went wrong', error) + debugConsole.error('something went wrong', error) setInflight(false) } }, [location, leavingGroupId]) diff --git a/services/web/frontend/js/features/subscription/components/dashboard/managed-institution.tsx b/services/web/frontend/js/features/subscription/components/dashboard/managed-institution.tsx index 1f069ccb9a..2837b909e2 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/managed-institution.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/managed-institution.tsx @@ -4,6 +4,7 @@ import { postJSON } from '../../../../infrastructure/fetch-json' import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context' import { Institution } from './managed-institutions' import { RowLink } from './row-link' +import { debugConsole } from '@/utils/debugging' type ManagedInstitutionProps = { institution: Institution @@ -27,7 +28,7 @@ export default function ManagedInstitution({ institution.metricsEmail.optedOutUserIds = data updateManagedInstitution(institution) } catch (error) { - console.error(error) + debugConsole.error(error) } setSubscriptionChanging(false) } diff --git a/services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx b/services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx index faf11245c4..9ec0a1f9cc 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx @@ -4,6 +4,7 @@ import { reactivateSubscriptionUrl } from '../../data/subscription-url' import useAsync from '../../../../shared/hooks/use-async' import { useLocation } from '../../../../shared/hooks/use-location' import getMeta from '../../../../utils/meta' +import { debugConsole } from '@/utils/debugging' function ReactivateSubscription() { const { t } = useTranslation() @@ -11,7 +12,7 @@ function ReactivateSubscription() { const location = useLocation() const handleReactivate = () => { - runAsync(postJSON(reactivateSubscriptionUrl)).catch(console.error) + runAsync(postJSON(reactivateSubscriptionUrl)).catch(debugConsole.error) } if (isSuccess) { diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/cancel-subscription.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/cancel-subscription.tsx index 8d90d2f2e4..b1c6d45622 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/cancel-subscription.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/cancel-subscription.tsx @@ -15,6 +15,7 @@ import GenericErrorAlert from '../../../generic-error-alert' import DowngradePlanButton from './downgrade-plan-button' import ExtendTrialButton from './extend-trial-button' import { useLocation } from '../../../../../../../shared/hooks/use-location' +import { debugConsole } from '@/utils/debugging' const planCodeToDowngradeTo = 'paid-personal' @@ -180,7 +181,7 @@ export function CancelSubscription() { await runAsyncCancel(postJSON(cancelSubscriptionUrl)) location.assign(redirectAfterCancelSubscriptionUrl) } catch (e) { - console.error(e) + debugConsole.error(e) } } diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/downgrade-plan-button.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/downgrade-plan-button.tsx index faef9a8c48..4fcac209d7 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/downgrade-plan-button.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/downgrade-plan-button.tsx @@ -4,6 +4,7 @@ import { postJSON } from '../../../../../../../infrastructure/fetch-json' import { subscriptionUpdateUrl } from '../../../../../data/subscription-url' import ActionButtonText from '../../../action-button-text' import { useLocation } from '../../../../../../../shared/hooks/use-location' +import { debugConsole } from '@/utils/debugging' export default function DowngradePlanButton({ isButtonDisabled, @@ -31,7 +32,7 @@ export default function DowngradePlanButton({ ) location.reload() } catch (e) { - console.error(e) + debugConsole.error(e) } } diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/extend-trial-button.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/extend-trial-button.tsx index f9b94f3804..116436610d 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/extend-trial-button.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/extend-trial-button.tsx @@ -3,6 +3,7 @@ import { putJSON } from '../../../../../../../infrastructure/fetch-json' import { extendTrialUrl } from '../../../../../data/subscription-url' import ActionButtonText from '../../../action-button-text' import { useLocation } from '../../../../../../../shared/hooks/use-location' +import { debugConsole } from '@/utils/debugging' export default function ExtendTrialButton({ isButtonDisabled, @@ -24,7 +25,7 @@ export default function ExtendTrialButton({ await runAsyncSecondaryAction(putJSON(extendTrialUrl)) location.reload() } catch (e) { - console.error(e) + debugConsole.error(e) } } diff --git a/services/web/frontend/js/features/subscription/context/subscription-dashboard-context.tsx b/services/web/frontend/js/features/subscription/context/subscription-dashboard-context.tsx index f3ab2f3048..fbb13885ee 100644 --- a/services/web/frontend/js/features/subscription/context/subscription-dashboard-context.tsx +++ b/services/web/frontend/js/features/subscription/context/subscription-dashboard-context.tsx @@ -27,6 +27,7 @@ import { } from '../util/recurly-pricing' import { isRecurlyLoaded } from '../util/is-recurly-loaded' import { SubscriptionDashModalIds } from '../../../../../types/subscription/dashboard/modal-ids' +import { debugConsole } from '@/utils/debugging' type SubscriptionDashboardContextValue = { groupPlanToChangeToCode: string @@ -166,13 +167,13 @@ export function SubscriptionDashboardProvider({ plan.displayPrice = priceData.totalForDisplay } } catch (error) { - console.error(error) + debugConsole.error(error) } } setPlans(plansWithoutDisplayPrice) setQueryingIndividualPlansData(false) } - fetchPlansDisplayPrices().catch(console.error) + fetchPlansDisplayPrices().catch(debugConsole.error) } }, [personalSubscription, plansWithoutDisplayPrice]) @@ -199,7 +200,7 @@ export function SubscriptionDashboardProvider({ groupPlanToChangeToUsage ) } catch (e) { - console.error(e) + debugConsole.error(e) setGroupPlanToChangeToPriceError(true) } setQueryingGroupPlanToChangeToPrice(false) diff --git a/services/web/frontend/js/features/subscription/util/recurly-pricing.ts b/services/web/frontend/js/features/subscription/util/recurly-pricing.ts index 21625c53a5..d4bec39a5b 100644 --- a/services/web/frontend/js/features/subscription/util/recurly-pricing.ts +++ b/services/web/frontend/js/features/subscription/util/recurly-pricing.ts @@ -2,15 +2,14 @@ import { SubscriptionPricingState } from '@recurly/recurly-js' import { PriceForDisplayData } from '../../../../../types/subscription/plan' import { currencies, CurrencyCode } from '../data/currency' import { getRecurlyGroupPlanCode } from './recurly-group-plan-code' +import { debugConsole } from '@/utils/debugging' function queryRecurlyPlanPrice(planCode: string, currency: CurrencyCode) { return new Promise(resolve => { recurly.Pricing.Subscription() .plan(planCode, { quantity: 1 }) .currency(currency) - .catch(function (error) { - console.error(error) - }) + .catch(debugConsole.error) .done(response => { if (response) { resolve(response) diff --git a/services/web/frontend/js/ide.js b/services/web/frontend/js/ide.js index 19d114a7bd..614f525d2f 100644 --- a/services/web/frontend/js/ide.js +++ b/services/web/frontend/js/ide.js @@ -71,6 +71,7 @@ import './features/history/controllers/history-file-tree-controller' import { cleanupServiceWorker } from './utils/service-worker-cleanup' import { reportCM6Perf } from './infrastructure/cm6-performance' import { reportAcePerf } from './ide/editor/ace-performance' +import { debugConsole } from '@/utils/debugging' App.controller( 'IdeController', @@ -427,7 +428,7 @@ If the project has been renamed please look in your project list for a new proje !/.*Chromium\/.*/.test(userAgent) } catch (error) { err = error - console.error(err) + debugConsole.error(err) } if (ide.browserIsSafari) { @@ -448,7 +449,7 @@ If the project has been renamed please look in your project list for a new proje } } catch (error1) { err = error1 - console.error(err) + debugConsole.error(err) } // User can append ?ft=somefeature to url to activate a feature toggle diff --git a/services/web/frontend/js/ide/connection/ConnectionManager.js b/services/web/frontend/js/ide/connection/ConnectionManager.js index 957a534e77..a327710fc9 100644 --- a/services/web/frontend/js/ide/connection/ConnectionManager.js +++ b/services/web/frontend/js/ide/connection/ConnectionManager.js @@ -12,6 +12,7 @@ import SocketIoShim from './SocketIoShim' import getMeta from '../../utils/meta' +import { debugConsole, debugging } from '@/utils/debugging' let ConnectionManager const ONEHOUR = 1000 * 60 * 60 @@ -42,7 +43,7 @@ export default ConnectionManager = (function () { // try reloading and falling back to the siteUrl window.location = window.location.href + '?ws=fallback' } - console.error( + debugConsole.error( 'Socket.io javascript not loaded. Please check that the real-time service is running and accessible.' ) this.ide.socket = SocketIoShim.stub() @@ -59,7 +60,7 @@ export default ConnectionManager = (function () { // trigger a reconnect immediately if network comes back online window.addEventListener('online', () => { - sl_console.log('[online] browser notified online') + debugConsole.log('[online] browser notified online') if (!this.connected) { return this.tryReconnectWithRateLimit({ force: true }) } @@ -78,7 +79,7 @@ export default ConnectionManager = (function () { this.joinProjectRetryInterval = this.JOIN_PROJECT_RETRY_INTERVAL this.$scope.connection = { - debug: sl_debugging, + debug: debugging, reconnecting: false, stillReconnecting: false, // If we need to force everyone to reload the editor @@ -157,7 +158,7 @@ export default ConnectionManager = (function () { ) } this.updateConnectionManagerState('error') - sl_console.log('socket.io error', err) + debugConsole.log('socket.io error', err) if (this.wsUrl && !window.location.href.match(/ws=fallback/)) { // if we tried to load a custom websocket location and failed // try reloading and falling back to the siteUrl @@ -180,7 +181,7 @@ export default ConnectionManager = (function () { // state should be 'connecting'... // remove connection error handler when connected, avoid unwanted fallbacks this.ide.socket.removeListener('error', connectionErrorHandler) - sl_console.log('[socket.io connect] Connected') + debugConsole.log('[socket.io connect] Connected') this.updateConnectionManagerState('authenticating') }) @@ -192,7 +193,7 @@ export default ConnectionManager = (function () { this.ide.socket.on('connectionAccepted', (_, publicId) => { this.ide.socket.publicId = publicId || this.ide.socket.socket.sessionid // state should be 'authenticating'... - sl_console.log('[socket.io connectionAccepted] allowed to connect') + debugConsole.log('[socket.io connectionAccepted] allowed to connect') this.connected = true this.gracefullyReconnecting = false this.ide.pushEvent('connected') @@ -215,7 +216,7 @@ export default ConnectionManager = (function () { 'joinProjectResponse', ({ publicId, project, permissionsLevel, protocolVersion }) => { this.ide.socket.publicId = publicId - sl_console.log('[socket.io bootstrap] ready for joinDoc') + debugConsole.log('[socket.io bootstrap] ready for joinDoc') this.connected = true this.gracefullyReconnecting = false this.ide.pushEvent('connected') @@ -240,7 +241,7 @@ export default ConnectionManager = (function () { this.ide.socket.on('connectionRejected', err => { // state should be 'authenticating'... - sl_console.log( + debugConsole.log( '[socket.io connectionRejected] session not valid or other connection error' ) // real-time sends a 'retry' message if the process was shutting down @@ -279,7 +280,7 @@ export default ConnectionManager = (function () { // "connect" event. this.ide.socket.on('disconnect', () => { - sl_console.log('[socket.io disconnect] Disconnected') + debugConsole.log('[socket.io disconnect] Disconnected') this.connected = false this.ide.pushEvent('disconnected') @@ -320,7 +321,7 @@ The editor will refresh automatically in ${delay} seconds.\ }) this.ide.socket.on('reconnectGracefully', () => { - sl_console.log('Reconnect gracefully') + debugConsole.log('Reconnect gracefully') this.reconnectGracefully() }) } @@ -329,7 +330,7 @@ The editor will refresh automatically in ${delay} seconds.\ this.$scope.$apply(() => { this.$scope.connection.jobId += 1 const jobId = this.$scope.connection.jobId - sl_console.log( + debugConsole.log( `[updateConnectionManagerState ${jobId}] from ${this.$scope.connection.state} to ${state}` ) this.$scope.connection.state = state @@ -376,7 +377,7 @@ The editor will refresh automatically in ${delay} seconds.\ } else if (state === 'error') { // something is wrong } else { - sl_console.log( + debugConsole.log( `[WARN] [updateConnectionManagerState ${jobId}] got unrecognised state ${state}` ) } @@ -391,7 +392,7 @@ The editor will refresh automatically in ${delay} seconds.\ return true } - sl_console.log( + debugConsole.log( `[WARN] [state mismatch] expected state ${state}${ jobId ? '/' + jobId : '' } when in ${this.$scope.connection.state}/${ @@ -404,7 +405,7 @@ The editor will refresh automatically in ${delay} seconds.\ // Error reporting, which can reload the page if appropriate reportConnectionError(err) { - sl_console.log('[socket.io] reporting connection error') + debugConsole.log('[socket.io] reporting connection error') this.updateConnectionManagerState('error') if ( (err != null ? err.message : undefined) === 'not authorized' || @@ -425,12 +426,12 @@ Something went wrong connecting to your project. Please refresh if this continue } joinProject(connectionId) { - sl_console.log(`[joinProject ${connectionId}] joining...`) + debugConsole.log(`[joinProject ${connectionId}] joining...`) // Note: if the "joinProject" message doesn't reach the server // (e.g. if we are in a disconnected state at this point) the // callback will never be executed if (!this.expectConnectionManagerState('joining', connectionId)) { - sl_console.log( + debugConsole.log( `[joinProject ${connectionId}] aborting with stale connection` ) return @@ -477,7 +478,7 @@ Something went wrong connecting to your project. Please refresh if this continue return } if (err.code === 'TooManyRequests') { - sl_console.log( + debugConsole.log( `[joinProject ${connectionId}] retrying: ${err.message}` ) setTimeout( @@ -525,16 +526,16 @@ Something went wrong connecting to your project. Please refresh if this continue disconnect(options) { if (options && options.permanent) { - sl_console.log('[disconnect] shutting down ConnectionManager') + debugConsole.log('[disconnect] shutting down ConnectionManager') this.updateConnectionManagerState('inactive') this.shuttingDown = true // prevent reconnection attempts } else if (this.ide.socket.socket && !this.ide.socket.socket.connected) { - sl_console.log( + debugConsole.log( '[socket.io] skipping disconnect because socket.io has not connected' ) return } - sl_console.log('[socket.io] disconnecting client') + debugConsole.log('[socket.io] disconnecting client') return this.ide.socket.disconnect() } @@ -542,7 +543,7 @@ Something went wrong connecting to your project. Please refresh if this continue this.updateConnectionManagerState('waitingCountdown') const connectionId = this.$scope.connection.jobId let countdown - sl_console.log('[ConnectionManager] starting autoreconnect countdown') + debugConsole.log('[ConnectionManager] starting autoreconnect countdown') const twoMinutes = 2 * 60 * 1000 if ( this.lastUserAction != null && @@ -579,7 +580,7 @@ Something went wrong connecting to your project. Please refresh if this continue stopReconnectCountdownTimer() { // clear timeout and set to null so we know there is no countdown running if (this.countdownTimeoutId != null) { - sl_console.log( + debugConsole.log( '[ConnectionManager] cancelling existing reconnect timer' ) clearTimeout(this.countdownTimeoutId) @@ -595,13 +596,13 @@ Something went wrong connecting to your project. Please refresh if this continue if ( !this.expectConnectionManagerState('waitingCountdown', connectionId) ) { - sl_console.log( + debugConsole.log( `[ConnectionManager] Aborting stale countdown ${connectionId}` ) return } - sl_console.log( + debugConsole.log( '[ConnectionManager] decreasing countdown', this.$scope.connection.reconnection_countdown ) @@ -623,7 +624,7 @@ Something went wrong connecting to your project. Please refresh if this continue } tryReconnect() { - sl_console.log('[ConnectionManager] tryReconnect') + debugConsole.log('[ConnectionManager] tryReconnect') if ( this.connected || this.shuttingDown || @@ -632,20 +633,20 @@ Something went wrong connecting to your project. Please refresh if this continue return } this.updateConnectionManagerState('reconnecting') - sl_console.log('[ConnectionManager] Starting new connection') + debugConsole.log('[ConnectionManager] Starting new connection') const removeHandler = () => { this.ide.socket.removeListener('error', handleFailure) this.ide.socket.removeListener('connect', handleSuccess) } const handleFailure = () => { - sl_console.log('[ConnectionManager] tryReconnect: failed') + debugConsole.log('[ConnectionManager] tryReconnect: failed') removeHandler() this.updateConnectionManagerState('reconnectFailed') this.tryReconnectWithRateLimit({ force: true }) } const handleSuccess = () => { - sl_console.log('[ConnectionManager] tryReconnect: success') + debugConsole.log('[ConnectionManager] tryReconnect: success') removeHandler() } this.ide.socket.on('error', handleFailure) @@ -703,7 +704,7 @@ Something went wrong connecting to your project. Please refresh if this continue this.reconnectGracefullyStarted = new Date() } else { if (!force) { - sl_console.log( + debugConsole.log( '[reconnectGracefully] reconnection is already in process, so skipping' ) return @@ -716,12 +717,12 @@ Something went wrong connecting to your project. Please refresh if this continue new Date() - this.reconnectGracefullyStarted > this.MAX_RECONNECT_GRACEFULLY_INTERVAL if (userIsInactive || maxIntervalReached) { - sl_console.log( + debugConsole.log( "[reconnectGracefully] User didn't do anything for last 5 seconds, reconnecting" ) this._reconnectGracefullyNow() } else { - sl_console.log( + debugConsole.log( '[reconnectGracefully] User is working, will try again in 5 seconds' ) this.updateConnectionManagerState('waitingGracefully') diff --git a/services/web/frontend/js/ide/connection/EditorWatchdogManager.js b/services/web/frontend/js/ide/connection/EditorWatchdogManager.js index 60c51d30b0..206c84167d 100644 --- a/services/web/frontend/js/ide/connection/EditorWatchdogManager.js +++ b/services/web/frontend/js/ide/connection/EditorWatchdogManager.js @@ -75,6 +75,8 @@ See also: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now */ +import { debugConsole } from '@/utils/debugging' + // TIMEOUT specifies the timeout for edits into a single ShareJsDoc. const TIMEOUT = 60 * 1000 // GLOBAL_TIMEOUT specifies the timeout for edits into any ShareJSDoc. @@ -229,6 +231,6 @@ export default class EditorWatchdogManager { } _log() { - sl_console.log(`[EditorWatchdogManager] ${this.scope}:`, ...arguments) + debugConsole.log(`[EditorWatchdogManager] ${this.scope}:`, ...arguments) } } diff --git a/services/web/frontend/js/ide/connection/SocketIoShim.js b/services/web/frontend/js/ide/connection/SocketIoShim.js index 7000bec859..c27e01b795 100644 --- a/services/web/frontend/js/ide/connection/SocketIoShim.js +++ b/services/web/frontend/js/ide/connection/SocketIoShim.js @@ -1,5 +1,7 @@ /* global io */ +import { debugConsole } from '@/utils/debugging' + class SocketShimBase { static connect(url, options) { return new SocketShimBase() @@ -205,14 +207,14 @@ class SocketShimV2 extends SocketShimBase { let current if (typeof io === 'undefined' || !io) { - sl_console.log('[socket.io] Shim: socket.io is not loaded, returning noop') + debugConsole.log('[socket.io] Shim: socket.io is not loaded, returning noop') current = SocketShimNoop } else if (typeof io.version === 'string' && io.version.slice(0, 1) === '0') { - sl_console.log('[socket.io] Shim: detected v0') + debugConsole.log('[socket.io] Shim: detected v0') current = SocketShimV0 } else { // socket.io v2 does not have a global io.version attribute. - sl_console.log('[socket.io] Shim: detected v2') + debugConsole.log('[socket.io] Shim: detected v2') current = SocketShimV2 } diff --git a/services/web/frontend/js/ide/editor/Document.js b/services/web/frontend/js/ide/editor/Document.js index acf89abe9a..07640c62ce 100644 --- a/services/web/frontend/js/ide/editor/Document.js +++ b/services/web/frontend/js/ide/editor/Document.js @@ -19,6 +19,7 @@ import RangesTracker from '@overleaf/ranges-tracker' import EventEmitter from '../../utils/EventEmitter' import ShareJsDoc from './ShareJsDoc' +import { debugConsole } from '@/utils/debugging' let Document export default Document = (function () { @@ -37,18 +38,18 @@ export default Document = (function () { // joinDoc:existing code path on an existing doc that doesn't have any // local changes and getting an error if its version is too old. if (this.openDocs[doc_id]) { - sl_console.log( + debugConsole.log( `[getDocument] Cleaning up existing document instance for ${doc_id}` ) this.openDocs[doc_id]._cleanUp() } if (this.openDocs[doc_id] == null) { - sl_console.log( + debugConsole.log( `[getDocument] Creating new document instance for ${doc_id}` ) this.openDocs[doc_id] = new Document(ide, doc_id) } else { - sl_console.log( + debugConsole.log( `[getDocument] Returning existing document instance for ${doc_id}` ) } @@ -286,7 +287,7 @@ export default Document = (function () { this.wantToBeJoined = false this._cancelJoin() if (this.doc != null && this.doc.hasBufferedOps()) { - sl_console.log( + debugConsole.log( '[leave] Doc has buffered ops, pushing callback for later' ) if (!this._leaveCallbacks) { @@ -294,10 +295,10 @@ export default Document = (function () { } return this._leaveCallbacks.push(callback) } else if (!this.connected) { - sl_console.log('[leave] Not connected, returning now') + debugConsole.log('[leave] Not connected, returning now') return callback() } else { - sl_console.log('[leave] Leaving now') + debugConsole.log('[leave] Leaving now') return this._leaveDoc(callback) } } @@ -366,12 +367,12 @@ export default Document = (function () { if (inflightOp == null && pendingOp == null) { // there's nothing going on, this is ok. saved = true - sl_console.log('[pollSavedStatus] no inflight or pending ops') + debugConsole.log('[pollSavedStatus] no inflight or pending ops') } else if (inflightOp != null && inflightOp === this.oldInflightOp) { // The same inflight op has been sitting unacked since we // last checked, this is bad. saved = false - sl_console.log('[pollSavedStatus] inflight op is same as before') + debugConsole.log('[pollSavedStatus] inflight op is same as before') } else if ( pendingOp != null && recentAck && @@ -380,7 +381,7 @@ export default Document = (function () { // There is an op waiting to go to server but it is small and // within the flushDelay, this is ok for now. saved = true - sl_console.log( + debugConsole.log( '[pollSavedStatus] pending op (small with recent ack) assume ok', pendingOp, pendingOpSize @@ -388,7 +389,7 @@ export default Document = (function () { } else { // In any other situation, assume the document is unsaved. saved = false - sl_console.log( + debugConsole.log( `[pollSavedStatus] assuming not saved (inflightOp?: ${ inflightOp != null }, pendingOp?: ${pendingOp != null})` @@ -424,7 +425,7 @@ export default Document = (function () { window.disconnectOnAck != null && Math.random() < window.disconnectOnAck ) { - sl_console.log('Disconnecting on ack', update) + debugConsole.log('Disconnecting on ack', update) window._ide.socket.socket.disconnect() // Pretend we never received the ack return @@ -433,7 +434,7 @@ export default Document = (function () { if (window.dropAcks != null && Math.random() < window.dropAcks) { if (update.op == null) { // Only drop our own acks, not collaborator updates - sl_console.log('Simulating a lost ack', update) + debugConsole.log('Simulating a lost ack', update) return } } @@ -455,7 +456,7 @@ export default Document = (function () { } _onDisconnect() { - sl_console.log('[onDisconnect] disconnecting') + debugConsole.log('[onDisconnect] disconnecting') this.connected = false this.joined = false return this.doc != null @@ -464,7 +465,7 @@ export default Document = (function () { } _onReconnect() { - sl_console.log('[onReconnect] reconnected (joined project)') + debugConsole.log('[onReconnect] reconnected (joined project)') this.ide.pushEvent('reconnected:afterJoinProject') this.connected = true @@ -472,7 +473,7 @@ export default Document = (function () { this.wantToBeJoined || (this.doc != null ? this.doc.hasBufferedOps() : undefined) ) { - sl_console.log( + debugConsole.log( `[onReconnect] Rejoining (wantToBeJoined: ${ this.wantToBeJoined } OR hasBufferedOps: ${ @@ -584,7 +585,7 @@ export default Document = (function () { return result })() } catch (err) { - return console.log(err) + debugConsole.error(err) } } @@ -595,14 +596,14 @@ export default Document = (function () { this.ide.pushEvent('leaveDoc', { doc_id: this.doc_id, }) - sl_console.log('[_leaveDoc] Sending leaveDoc request') + debugConsole.log('[_leaveDoc] Sending leaveDoc request') return this.ide.socket.emit('leaveDoc', this.doc_id, error => { if (error != null) { return callback(error) } this.joined = false for (callback of Array.from(this._leaveCallbacks || [])) { - sl_console.log('[_leaveDoc] Calling buffered callback', callback) + debugConsole.log('[_leaveDoc] Calling buffered callback', callback) callback(error) } delete this._leaveCallbacks @@ -613,12 +614,12 @@ export default Document = (function () { _cleanUp() { // if we arrive here from _onError the pending and inflight ops will have been cleared if (this.hasBufferedOps()) { - sl_console.log( + debugConsole.log( `[_cleanUp] Document (${this.doc_id}) has buffered ops, refusing to remove from openDocs` ) return // return immediately, do not unbind from events } else if (Document.openDocs[this.doc_id] === this) { - sl_console.log( + debugConsole.log( `[_cleanUp] Removing self (${this.doc_id}) from in openDocs` ) delete Document.openDocs[this.doc_id] @@ -626,7 +627,7 @@ export default Document = (function () { // It's possible that this instance has error, and the doc has been reloaded. // This creates a new instance in Document.openDoc with the same id. We shouldn't // clear it because it's not this instance. - sl_console.log( + debugConsole.log( `[_cleanUp] New instance of (${this.doc_id}) created. Not removing` ) } @@ -716,9 +717,9 @@ export default Document = (function () { meta = {} } meta.doc_id = this.doc_id - sl_console.log('ShareJS error', error, meta) + debugConsole.log('ShareJS error', error, meta) if (error.message === 'no project_id found on client') { - sl_console.log('ignoring error, will wait to join project') + debugConsole.log('ignoring error, will wait to join project') return } if (this.doc != null) { diff --git a/services/web/frontend/js/ide/editor/EditorManager.js b/services/web/frontend/js/ide/editor/EditorManager.js index f279b2a36d..b96208b247 100644 --- a/services/web/frontend/js/ide/editor/EditorManager.js +++ b/services/web/frontend/js/ide/editor/EditorManager.js @@ -24,6 +24,7 @@ import './controllers/CompileButton' import './controllers/SwitchToPDFButton' import getMeta from '../../utils/meta' import { hasSeenCM6SwitchAwaySurvey } from '../../features/source-editor/utils/switch-away-survey' +import { debugConsole } from '@/utils/debugging' let EditorManager @@ -120,7 +121,7 @@ export default EditorManager = (function () { // sync: we can use any new version of the doc that the server may // present us. There should be no need to insert local changes into // the doc history as the user comes back. - sl_console.log('[EditorManager] forcing flush onblur') + debugConsole.log('[EditorManager] forcing flush onblur') Document.flushAll() }) @@ -237,7 +238,7 @@ export default EditorManager = (function () { if (options == null) { options = {} } - sl_console.log(`[openDoc] Opening ${doc.id}`) + debugConsole.log(`[openDoc] Opening ${doc.id}`) if (this.$scope.ui.view === 'editor') { // store position of previous doc before switching docs this.$scope.$broadcast('store-doc-position') @@ -292,7 +293,7 @@ export default EditorManager = (function () { this.$scope.editor.opening = true return this._openNewDocument(doc, (error, sharejs_doc) => { if (error && error.message === 'another document was loaded') { - sl_console.log( + debugConsole.log( `[openDoc] another document was loaded while ${doc.id} was loading` ) return @@ -330,7 +331,7 @@ export default EditorManager = (function () { current_sharejs_doc && current_sharejs_doc.hasBufferedOps() const changingDoc = current_sharejs_doc && currentDocId !== doc.id if (changingDoc || hasBufferedOps) { - sl_console.log('[_openNewDocument] Leaving existing open doc...') + debugConsole.log('[_openNewDocument] Leaving existing open doc...') // Do not trigger any UI changes from remote operations this._unbindFromDocumentEvents(current_sharejs_doc) @@ -344,14 +345,14 @@ export default EditorManager = (function () { const editorOpenDocEpoch = ++this.editorOpenDocEpoch current_sharejs_doc.leaveAndCleanUp(error => { if (error) { - sl_console.log( + debugConsole.log( `[_openNewDocument] error leaving doc ${currentDocId}`, error ) return callback(error) } if (this.editorOpenDocEpoch !== editorOpenDocEpoch) { - sl_console.log( + debugConsole.log( `[openNewDocument] editorOpenDocEpoch mismatch ${this.editorOpenDocEpoch} vs ${editorOpenDocEpoch}` ) return callback(new Error('another document was loaded')) @@ -367,19 +368,19 @@ export default EditorManager = (function () { if (callback == null) { callback = function () {} } - sl_console.log('[_doOpenNewDocument] Opening...') + debugConsole.log('[_doOpenNewDocument] Opening...') const new_sharejs_doc = Document.getDocument(this.ide, doc.id) const editorOpenDocEpoch = ++this.editorOpenDocEpoch return new_sharejs_doc.join(error => { if (error != null) { - sl_console.log( + debugConsole.log( `[_doOpenNewDocument] error joining doc ${doc.id}`, error ) return callback(error) } if (this.editorOpenDocEpoch !== editorOpenDocEpoch) { - sl_console.log( + debugConsole.log( `[openNewDocument] editorOpenDocEpoch mismatch ${this.editorOpenDocEpoch} vs ${editorOpenDocEpoch}` ) new_sharejs_doc.leaveAndCleanUp() diff --git a/services/web/frontend/js/ide/editor/ShareJsDoc.js b/services/web/frontend/js/ide/editor/ShareJsDoc.js index fd8691d92b..28836bc4a6 100644 --- a/services/web/frontend/js/ide/editor/ShareJsDoc.js +++ b/services/web/frontend/js/ide/editor/ShareJsDoc.js @@ -19,6 +19,7 @@ import EventEmitter from '../../utils/EventEmitter' import ShareJs from '../../vendor/libs/sharejs' import EditorWatchdogManager from '../connection/EditorWatchdogManager' +import { debugConsole } from '@/utils/debugging' let ShareJsDoc const SINGLE_USER_FLUSH_DELAY = 2000 // ms @@ -59,14 +60,14 @@ export default ShareJsDoc = (function () { window.disconnectOnUpdate != null && Math.random() < window.disconnectOnUpdate ) { - sl_console.log('Disconnecting on update', update) + debugConsole.log('Disconnecting on update', update) window._ide.socket.socket.disconnect() } if ( window.dropUpdates != null && Math.random() < window.dropUpdates ) { - sl_console.log('Simulating a lost update', update) + debugConsole.log('Simulating a lost update', update) return } if (this.track_changes) { @@ -141,7 +142,7 @@ export default ShareJsDoc = (function () { }) let nextPos while ((nextPos = doc.snapshot.indexOf('\r')) !== -1) { - sl_console.log('[ShareJsDoc] remove-carriage-return-char', nextPos) + debugConsole.log('[ShareJsDoc] remove-carriage-return-char', nextPos) doc.del(nextPos, 1) } } @@ -159,11 +160,13 @@ export default ShareJsDoc = (function () { } _pushOntoQueue(message) { - sl_console.log(`[processUpdate] push onto queue ${message.v}`) + debugConsole.log(`[processUpdate] push onto queue ${message.v}`) // set a timer so that we never leave messages in the queue indefinitely if (!this.queuedMessageTimer) { this.queuedMessageTimer = setTimeout(() => { - sl_console.log(`[processUpdate] queue timeout fired for ${message.v}`) + debugConsole.log( + `[processUpdate] queue timeout fired for ${message.v}` + ) // force the message to be processed after the timeout, // it will cause an error if the missing update has not arrived this.processUpdateFromServer(message) @@ -187,13 +190,13 @@ export default ShareJsDoc = (function () { // there are updates we still can't apply yet } else { // there's a version we can accept on the queue, apply it - sl_console.log( + debugConsole.log( `[processUpdate] taken from queue ${nextAvailableVersion}` ) this.processUpdateFromServerInOrder(this.queuedMessages.shift()) // clear the pending timer if the queue has now been cleared if (this.queuedMessages.length === 0 && this.queuedMessageTimer) { - sl_console.log('[processUpdate] queue is empty, cleared timeout') + debugConsole.log('[processUpdate] queue is empty, cleared timeout') clearTimeout(this.queuedMessageTimer) this.queuedMessageTimer = null } @@ -235,7 +238,7 @@ export default ShareJsDoc = (function () { this._doc._onMessage(message) } catch (error) { // Version mismatches are thrown as errors - console.log(error) + debugConsole.error(error) this._handleError(error) return error // return the error for queue handling } @@ -288,7 +291,7 @@ export default ShareJsDoc = (function () { } updateConnectionState(state) { - sl_console.log(`[updateConnectionState] Setting state to ${state}`) + debugConsole.log(`[updateConnectionState] Setting state to ${state}`) this.connection.state = state this.connection.id = this.socket.publicId this._doc.autoOpen = false @@ -385,7 +388,7 @@ export default ShareJsDoc = (function () { // Only send the update again if inflightOp is still populated // This can be cleared when hard reloading the document in which // case we don't want to keep trying to send it. - sl_console.log('[inflightOpTimeout] Trying op again') + debugConsole.log('[inflightOpTimeout] Trying op again') if (this._doc.inflightOp != null) { // When there is a socket.io disconnect, @_doc.inflightSubmittedIds // is updated with the socket.io client id of the current op in flight @@ -403,7 +406,7 @@ export default ShareJsDoc = (function () { // when we've joined the project if (this.connection.state !== 'ok') { let timer - sl_console.log( + debugConsole.log( '[inflightOpTimeout] Not connected, retrying in 0.5s' ) return (timer = setTimeout( @@ -411,7 +414,7 @@ export default ShareJsDoc = (function () { this.WAIT_FOR_CONNECTION_TIMEOUT )) } else { - sl_console.log('[inflightOpTimeout] Sending') + debugConsole.log('[inflightOpTimeout] Sending') return this.connection.send(update) } } diff --git a/services/web/frontend/js/ide/editor/ace-performance.ts b/services/web/frontend/js/ide/editor/ace-performance.ts index 444f6ef886..49c29df49c 100644 --- a/services/web/frontend/js/ide/editor/ace-performance.ts +++ b/services/web/frontend/js/ide/editor/ace-performance.ts @@ -1,6 +1,7 @@ import { round } from 'lodash' import grammarlyExtensionPresent from '../../shared/utils/grammarly' import getMeta from '../../utils/meta' +import { debugConsole } from '@/utils/debugging' const TIMER_DOM_UPDATE_NAME = 'Ace-DomUpdate' const TIMER_MEASURE_NAME = 'Ace-Keypress-Measure' @@ -154,5 +155,5 @@ export function reportAcePerf() { } window._reportAcePerf = () => { - console.log(reportAcePerf()) + debugConsole.warn(reportAcePerf()) } diff --git a/services/web/frontend/js/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.js b/services/web/frontend/js/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.js index a8c9f0e609..5808b10ae1 100644 --- a/services/web/frontend/js/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.js +++ b/services/web/frontend/js/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.js @@ -1,4 +1,5 @@ import ignoredWords from '../../../../../features/dictionary/ignored-words' +import { debugConsole } from '@/utils/debugging' // eslint-disable-next-line prefer-regex-literals const BLACKLISTED_COMMAND_REGEX = new RegExp( @@ -352,7 +353,7 @@ class SpellCheckManager { if (callback == null) { callback = function (error, result) { if (error) { - console.error(error) + debugConsole.error(error) } } } diff --git a/services/web/frontend/js/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.js b/services/web/frontend/js/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.js index f3002b1142..2a6fb0504c 100644 --- a/services/web/frontend/js/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.js +++ b/services/web/frontend/js/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.js @@ -6,6 +6,7 @@ import EditorShareJsCodec from '../../../EditorShareJsCodec' import 'ace/ace' import '../../../../../utils/EventEmitter' import '../../../../colors/ColorManager' +import { debugConsole } from '@/utils/debugging' const { Range } = ace.require('ace/range') class TrackChangesManager { constructor($scope, editor, element, adapter) { @@ -547,7 +548,7 @@ class TrackChangesManager { marker.range.end.row !== end.row || marker.range.end.column !== end.column ) { - console.error("Change doesn't match marker anymore", { + debugConsole.error("Change doesn't match marker anymore", { marker, start, end, @@ -560,7 +561,7 @@ class TrackChangesManager { for (const marker_id in markers) { marker = markers[marker_id] if (/track-changes/.test(marker.clazz)) { - result.push(console.error('Orphaned ace marker', marker)) + result.push(debugConsole.error('Orphaned ace marker', marker)) } else { result.push(undefined) } diff --git a/services/web/frontend/js/ide/file-tree/FileTreeManager.js b/services/web/frontend/js/ide/file-tree/FileTreeManager.js index b669f64079..74ca791d5b 100644 --- a/services/web/frontend/js/ide/file-tree/FileTreeManager.js +++ b/services/web/frontend/js/ide/file-tree/FileTreeManager.js @@ -23,6 +23,7 @@ import './controllers/FileTreeController' import './controllers/FileTreeEntityController' import './controllers/FileTreeFolderController' import '../../features/file-tree/controllers/file-tree-controller' +import { debugConsole } from '@/utils/debugging' let FileTreeManager export default FileTreeManager = class FileTreeManager { @@ -631,7 +632,7 @@ export default FileTreeManager = class FileTreeManager { const provider = file.linkedFileData != null ? file.linkedFileData.provider : undefined if (provider == null) { - console.warn(`>> no provider for ${file.name}`, file) + debugConsole.warn(`>> no provider for ${file.name}`, file) return } return this.ide.$http.post( diff --git a/services/web/frontend/js/ide/history/controllers/HistoryV2ToolbarController.js b/services/web/frontend/js/ide/history/controllers/HistoryV2ToolbarController.js index 9014486715..87d31c7bcc 100644 --- a/services/web/frontend/js/ide/history/controllers/HistoryV2ToolbarController.js +++ b/services/web/frontend/js/ide/history/controllers/HistoryV2ToolbarController.js @@ -11,6 +11,7 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ import App from '../../../base' +import { debugConsole } from '@/utils/debugging' export default App.controller( 'HistoryV2ToolbarController', @@ -117,7 +118,7 @@ export default App.controller( }, 0) } }) - .catch(err => console.warn(err)) + .catch(debugConsole.error) } } ) diff --git a/services/web/frontend/js/ide/references/ReferencesManager.js b/services/web/frontend/js/ide/references/ReferencesManager.js index d7f7a708aa..37bff9da7d 100644 --- a/services/web/frontend/js/ide/references/ReferencesManager.js +++ b/services/web/frontend/js/ide/references/ReferencesManager.js @@ -59,7 +59,6 @@ export default ReferencesManager = class ReferencesManager { } _storeReferencesKeys(newKeys) { - // console.log '>> storing references keys' const oldKeys = this.$scope.$root._references.keys const keys = _.union(oldKeys, newKeys) window.dispatchEvent( diff --git a/services/web/frontend/js/ide/review-panel/directives/reviewPanelSorted.js b/services/web/frontend/js/ide/review-panel/directives/reviewPanelSorted.js index 3f353f48b7..9d5a4cce99 100644 --- a/services/web/frontend/js/ide/review-panel/directives/reviewPanelSorted.js +++ b/services/web/frontend/js/ide/review-panel/directives/reviewPanelSorted.js @@ -14,6 +14,7 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ import App from '../../../base' +import { debugConsole } from '@/utils/debugging' export default App.directive('reviewPanelSorted', $timeout => ({ link(scope, element, attrs) { @@ -109,7 +110,7 @@ export default App.directive('reviewPanelSorted', $timeout => ({ : [] previous_focused_entry_index = focused_entry_index - sl_console.log('focused_entry_index', focused_entry_index) + debugConsole.log('focused_entry_index', focused_entry_index) const positionLayoutEl = function ( $callout_el, @@ -180,7 +181,7 @@ export default App.directive('reviewPanelSorted', $timeout => ({ screenPosHeight ) } - sl_console.log('ENTRY', { entry: entry.scope.entry, top }) + debugConsole.log('ENTRY', { entry: entry.scope.entry, top }) } let previousTop = focused_entry_top @@ -210,7 +211,7 @@ export default App.directive('reviewPanelSorted', $timeout => ({ screenPosHeight ) } - sl_console.log('ENTRY', { entry: entry.scope.entry, top }) + debugConsole.log('ENTRY', { entry: entry.scope.entry, top }) } const lastTop = top @@ -268,7 +269,6 @@ export default App.directive('reviewPanelSorted', $timeout => ({ return (ignoreNextAceEvent = false) } else { list.height(height) - // console.log({height, scrollTop, top: height - scrollTop}) return list.css({ top: -scrollTop }) } } diff --git a/services/web/frontend/js/ide/services/ide.js b/services/web/frontend/js/ide/services/ide.js index baf0cc73c5..c79ccd9d72 100644 --- a/services/web/frontend/js/ide/services/ide.js +++ b/services/web/frontend/js/ide/services/ide.js @@ -14,6 +14,7 @@ */ import App from '../../base' import EditorWatchdogManager from '../connection/EditorWatchdogManager' +import { debugConsole } from '@/utils/debugging' // We create and provide this as service so that we can access the global ide // from within other parts of the angular app. App.factory( @@ -38,7 +39,7 @@ App.factory( if (meta == null) { meta = {} } - sl_console.log('event', type, meta) + debugConsole.log('event', type, meta) this.recentEvents.push({ type, meta, date: new Date() }) if (this.recentEvents.length > 100) { return this.recentEvents.shift() diff --git a/services/web/frontend/js/infrastructure/cm6-performance.ts b/services/web/frontend/js/infrastructure/cm6-performance.ts index 0b743c4f86..e3a4d3ec51 100644 --- a/services/web/frontend/js/infrastructure/cm6-performance.ts +++ b/services/web/frontend/js/infrastructure/cm6-performance.ts @@ -3,6 +3,7 @@ import { EditorView } from '@codemirror/view' import { round } from 'lodash' import grammarlyExtensionPresent from '../shared/utils/grammarly' import getMeta from '../utils/meta' +import { debugConsole } from '@/utils/debugging' const TIMER_START_NAME = 'CM6-BeforeUpdate' const TIMER_END_NAME = 'CM6-AfterUpdate' @@ -326,5 +327,5 @@ export function reportCM6Perf() { } window._reportCM6Perf = () => { - console.log(reportCM6Perf()) + debugConsole.warn(reportCM6Perf()) } diff --git a/services/web/frontend/js/infrastructure/error-reporter.js b/services/web/frontend/js/infrastructure/error-reporter.js index 878a92b6b8..2e5c8a46c8 100644 --- a/services/web/frontend/js/infrastructure/error-reporter.js +++ b/services/web/frontend/js/infrastructure/error-reporter.js @@ -1,6 +1,7 @@ // Conditionally enable Sentry based on whether the DSN token is set import getMeta from '../utils/meta' import OError from '@overleaf/o-error' +import { debugConsole } from '@/utils/debugging' const reporterPromise = window.ExposedSettings?.sentryDsn ? sentryReporter() @@ -81,7 +82,7 @@ function sentryReporter() { }) // If Sentry fails to load, use the null reporter instead .catch(error => { - console.error(error) + debugConsole.error(error) return nullReporter() }) ) @@ -89,8 +90,8 @@ function sentryReporter() { function nullReporter() { return Promise.resolve({ - captureException: console.error, - captureMessage: console.error, + captureException: debugConsole.error, + captureMessage: debugConsole.error, }) } diff --git a/services/web/frontend/js/infrastructure/local-storage.js b/services/web/frontend/js/infrastructure/local-storage.js index ccc2d70ae0..4ae017f82f 100644 --- a/services/web/frontend/js/infrastructure/local-storage.js +++ b/services/web/frontend/js/infrastructure/local-storage.js @@ -3,6 +3,8 @@ * use localStorage for anything critical, so in that case just fail gracefully. */ +import { debugConsole } from '@/utils/debugging' + /** * Catch, log and otherwise ignore errors. * @@ -14,7 +16,7 @@ const callSafe = function (fn, key, value) { try { return fn(key, value) } catch (e) { - console.error('localStorage exception', e) + debugConsole.error('localStorage exception', e) return null } } diff --git a/services/web/frontend/js/infrastructure/session-storage.js b/services/web/frontend/js/infrastructure/session-storage.js index 59accfb121..1e2757874f 100644 --- a/services/web/frontend/js/infrastructure/session-storage.js +++ b/services/web/frontend/js/infrastructure/session-storage.js @@ -3,6 +3,8 @@ * We don't use sessionStorage for anything critical, so in that case just fail gracefully. */ +import { debugConsole } from '@/utils/debugging' + /** * Catch, log and otherwise ignore errors. * @@ -14,7 +16,7 @@ const callSafe = function (fn, key, value) { try { return fn(key, value) } catch (e) { - console.error('sessionStorage exception', e) + debugConsole.error('sessionStorage exception', e) return null } } diff --git a/services/web/frontend/js/main.js b/services/web/frontend/js/main.js index f3cfdb6cb1..cbf22343ec 100644 --- a/services/web/frontend/js/main.js +++ b/services/web/frontend/js/main.js @@ -41,6 +41,7 @@ import './filters/formatDate' import './features/cookie-banner' import '../../modules/modules-main.js' import './cdn-load-test' +import { debugConsole } from '@/utils/debugging' angular.module('SharelatexApp').config(function ($locationProvider) { try { return $locationProvider.html5Mode({ @@ -49,7 +50,7 @@ angular.module('SharelatexApp').config(function ($locationProvider) { rewriteLinks: false, }) } catch (e) { - return console.error("Error while trying to fix '#' links: ", e) + debugConsole.error("Error while trying to fix '#' links: ", e) } }) export default angular.bootstrap(document.body, ['SharelatexApp']) diff --git a/services/web/frontend/js/main/annual-upgrade.js b/services/web/frontend/js/main/annual-upgrade.js index a137cd4c1d..7c5a474a1f 100644 --- a/services/web/frontend/js/main/annual-upgrade.js +++ b/services/web/frontend/js/main/annual-upgrade.js @@ -10,6 +10,7 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ import App from '../base' +import { debugConsole } from '@/utils/debugging' export default App.controller( 'AnnualUpgradeController', @@ -38,7 +39,9 @@ export default App.controller( return $http .post(MESSAGES_URL, body) .then(() => ($scope.upgradeComplete = true)) - .catch(() => console.log('something went wrong changing plan')) + .catch(err => + debugConsole.error('something went wrong changing plan', err) + ) }) } ) diff --git a/services/web/frontend/js/main/clear-sessions.js b/services/web/frontend/js/main/clear-sessions.js index 9fc8ce8f36..ad73fba0ee 100644 --- a/services/web/frontend/js/main/clear-sessions.js +++ b/services/web/frontend/js/main/clear-sessions.js @@ -22,7 +22,6 @@ export default App.controller( } return ($scope.clearSessions = function () { - console.log('>> clearing all sessions') return $http({ method: 'POST', url: '/user/sessions/clear', diff --git a/services/web/frontend/js/main/event.js b/services/web/frontend/js/main/event.js index d06391fcf1..90d883252a 100644 --- a/services/web/frontend/js/main/event.js +++ b/services/web/frontend/js/main/event.js @@ -16,6 +16,7 @@ import moment from 'moment' import App from '../base' import '../modules/localStorage' import { sendMB } from '../infrastructure/event-tracking' +import { debugConsole } from '@/utils/debugging' const CACHE_KEY = 'mbEvents' // keep track of how many heartbeats we've sent so we can calculate how @@ -71,14 +72,14 @@ App.factory('eventTracking', function ($http, localStorage) { }, editingSessionHeartbeat(segmentationCb = () => {}) { - sl_console.log('[Event] heartbeat trigger') + debugConsole.log('[Event] heartbeat trigger') // If the next heartbeat is in the future, stop if (nextHeartbeat > new Date()) return const segmentation = segmentationCb() - sl_console.log('[Event] send heartbeat request', segmentation) + debugConsole.log('[Event] send heartbeat request', segmentation) _sendEditingSessionHeartbeat(segmentation) heartbeatsSent++ diff --git a/services/web/frontend/js/main/subscription/team-invite-controller.js b/services/web/frontend/js/main/subscription/team-invite-controller.js index d806aae361..7a13803357 100644 --- a/services/web/frontend/js/main/subscription/team-invite-controller.js +++ b/services/web/frontend/js/main/subscription/team-invite-controller.js @@ -11,6 +11,7 @@ */ import App from '../../base' import getMeta from '../../utils/meta' +import { debugConsole } from '@/utils/debugging' export default App.controller('TeamInviteController', function ($scope, $http) { $scope.inflight = false @@ -42,7 +43,7 @@ export default App.controller('TeamInviteController', function ($scope, $http) { return request.catch(() => { $scope.inflight = false $scope.cancel_error = true - console.log('the request failed') + debugConsole.error('the request failed') }) } @@ -61,6 +62,6 @@ export default App.controller('TeamInviteController', function ($scope, $http) { return ($scope.requestSent = false) } }) - return request.catch(() => console.log('the request failed')) + return request.catch(() => debugConsole.error('the request failed')) }) }) diff --git a/services/web/frontend/js/main/token-access.js b/services/web/frontend/js/main/token-access.js index 1d1b11ec62..234ff8f918 100644 --- a/services/web/frontend/js/main/token-access.js +++ b/services/web/frontend/js/main/token-access.js @@ -1,4 +1,5 @@ import App from '../base' +import { debugConsole } from '@/utils/debugging' App.controller( 'TokenAccessPageController', ($scope, $http, $location, localStorage) => { @@ -56,7 +57,7 @@ App.controller( if (data.redirect) { const redirect = response.data.redirect if (!redirect) { - console.warn( + debugConsole.warn( 'no redirect supplied in success response data', response ) @@ -71,7 +72,7 @@ App.controller( $scope.mode = 'requireAccept' $scope.requireAccept = data.requireAccept } else { - console.warn( + debugConsole.warn( 'invalid data from server in success response', response ) @@ -79,7 +80,7 @@ App.controller( } }, function errorCallback(response) { - console.warn('error response from server', response) + debugConsole.warn('error response from server', response) $scope.accessInFlight = false $scope.accessError = response.status === 404 ? 'not_found' : 'error' } diff --git a/services/web/frontend/js/modules/localStorage.js b/services/web/frontend/js/modules/localStorage.js index e155dd6c2a..4b41f732b8 100644 --- a/services/web/frontend/js/modules/localStorage.js +++ b/services/web/frontend/js/modules/localStorage.js @@ -1,3 +1,5 @@ +import { debugConsole } from '@/utils/debugging' + angular.module('localStorage', []).value('localStorage', localStorage) /* @@ -9,7 +11,7 @@ function localStorage(...args) { try { return $.localStorage(...args) } catch (e) { - console.error('localStorage exception', e) + debugConsole.error('localStorage exception', e) return null } } diff --git a/services/web/frontend/js/modules/sessionStorage.js b/services/web/frontend/js/modules/sessionStorage.js index 532c3e179b..94a363dbce 100644 --- a/services/web/frontend/js/modules/sessionStorage.js +++ b/services/web/frontend/js/modules/sessionStorage.js @@ -1,3 +1,5 @@ +import { debugConsole } from '@/utils/debugging' + angular.module('sessionStorage', []).value('sessionStorage', sessionStorage) /* @@ -9,7 +11,7 @@ function sessionStorage(...args) { try { return $.sessionStorage(...args) } catch (e) { - console.error('sessionStorage exception', e) + debugConsole.error('sessionStorage exception', e) return null } } diff --git a/services/web/frontend/js/shared/context/detach-context.js b/services/web/frontend/js/shared/context/detach-context.js index ea558fbcdf..9263dafc07 100644 --- a/services/web/frontend/js/shared/context/detach-context.js +++ b/services/web/frontend/js/shared/context/detach-context.js @@ -10,6 +10,7 @@ import PropTypes from 'prop-types' import getMeta from '../../utils/meta' import { buildUrlWithDetachRole } from '../utils/url-helper' import useCallbackHandlers from '../hooks/use-callback-handlers' +import { debugConsole } from '@/utils/debugging' export const DetachContext = createContext() @@ -43,7 +44,7 @@ export function DetachProvider({ children }) { useEffect(() => { if (debugPdfDetach) { - console.log('Effect', { role }) + debugConsole.warn('Effect', { role }) } window.history.replaceState({}, '', buildUrlWithDetachRole(role).toString()) }, [role]) @@ -52,7 +53,7 @@ export function DetachProvider({ children }) { if (detachChannel) { const listener = event => { if (debugPdfDetach) { - console.log(`Receiving:`, event.data) + debugConsole.warn(`Receiving:`, event.data) } callEventHandlers(event.data) } @@ -69,7 +70,7 @@ export function DetachProvider({ children }) { (event, data) => { if (!role) { if (debugPdfDetach) { - console.log('Not Broadcasting (no role)', { + debugConsole.warn('Not Broadcasting (no role)', { role, event, data, @@ -78,7 +79,7 @@ export function DetachProvider({ children }) { return } if (debugPdfDetach) { - console.log('Broadcasting', { + debugConsole.warn('Broadcasting', { role, event, data, diff --git a/services/web/frontend/js/shared/context/layout-context.js b/services/web/frontend/js/shared/context/layout-context.js index 9edf8febcb..d876fe4c4f 100644 --- a/services/web/frontend/js/shared/context/layout-context.js +++ b/services/web/frontend/js/shared/context/layout-context.js @@ -11,6 +11,7 @@ import useDetachLayout from '../hooks/use-detach-layout' import { useIdeContext } from './ide-context' import localStorage from '../../infrastructure/local-storage' import getMeta from '../../utils/meta' +import { debugConsole } from '@/utils/debugging' const debugPdfDetach = getMeta('ol-debugPdfDetach') @@ -122,7 +123,7 @@ export function LayoutProvider({ children }) { useEffect(() => { if (debugPdfDetach) { - console.log('Layout Effect', { + debugConsole.warn('Layout Effect', { detachIsRedundant, detachRole, detachIsLinking, diff --git a/services/web/frontend/js/shared/hooks/use-detach-action.js b/services/web/frontend/js/shared/hooks/use-detach-action.js index e9376d85ab..ed7f22095f 100644 --- a/services/web/frontend/js/shared/hooks/use-detach-action.js +++ b/services/web/frontend/js/shared/hooks/use-detach-action.js @@ -1,6 +1,7 @@ import { useCallback, useEffect } from 'react' import { useDetachContext } from '../context/detach-context' import getMeta from '../../utils/meta' +import { debugConsole } from '@/utils/debugging' const debugPdfDetach = getMeta('ol-debugPdfDetach') @@ -35,7 +36,7 @@ export default function useDetachAction( return } if (debugPdfDetach) { - console.log(`Do ${actionFunction.name} on event ${eventName}`) + debugConsole.warn(`Do ${actionFunction.name} on event ${eventName}`) } actionFunction(...message.data.args) }, diff --git a/services/web/frontend/js/shared/hooks/use-detach-layout.ts b/services/web/frontend/js/shared/hooks/use-detach-layout.ts index be54207e36..3b9bad8b7d 100644 --- a/services/web/frontend/js/shared/hooks/use-detach-layout.ts +++ b/services/web/frontend/js/shared/hooks/use-detach-layout.ts @@ -4,6 +4,7 @@ import getMeta from '../../utils/meta' import { buildUrlWithDetachRole } from '../utils/url-helper' import * as eventTracking from '../../infrastructure/event-tracking' import usePreviousValue from './use-previous-value' +import { debugConsole } from '@/utils/debugging' const debugPdfDetach = getMeta('ol-debugPdfDetach') @@ -28,14 +29,14 @@ export default function useDetachLayout() { useEffect(() => { if (debugPdfDetach) { - console.log('Effect', { isLinked }) + debugConsole.warn('Effect', { isLinked }) } setIsLinking(false) }, [isLinked, setIsLinking]) useEffect(() => { if (debugPdfDetach) { - console.log('Effect', { role, isLinked }) + debugConsole.warn('Effect', { role, isLinked }) } if (role === 'detached' && isLinked) { eventTracking.sendMB('project-layout-detached') @@ -62,7 +63,7 @@ export default function useDetachLayout() { useEffect(() => { if (debugPdfDetach) { - console.log('Effect', { isLinking }) + debugConsole.warn('Effect', { isLinking }) } }, [isLinking]) @@ -89,7 +90,7 @@ export default function useDetachLayout() { const handleEventForDetacherFromDetacher = useCallback(() => { if (debugPdfDetach) { - console.log( + debugConsole.warn( 'Duplicate detacher detected, turning into a regular editor again' ) } diff --git a/services/web/frontend/js/shared/hooks/use-detach-state.js b/services/web/frontend/js/shared/hooks/use-detach-state.js index 6b9cbf7f00..d1062cd07d 100644 --- a/services/web/frontend/js/shared/hooks/use-detach-state.js +++ b/services/web/frontend/js/shared/hooks/use-detach-state.js @@ -1,6 +1,7 @@ import { useEffect, useState, useCallback } from 'react' import { useDetachContext } from '../context/detach-context' import getMeta from '../../utils/meta' +import { debugConsole } from '@/utils/debugging' const debugPdfDetach = getMeta('ol-debugPdfDetach') @@ -46,7 +47,7 @@ export default function useDetachState( return } if (debugPdfDetach) { - console.log(`Set ${message.data.value} for ${eventName}`) + debugConsole.warn(`Set ${message.data.value} for ${eventName}`) } setValue(message.data.value) }, diff --git a/services/web/frontend/js/utils/debugging.ts b/services/web/frontend/js/utils/debugging.ts index 454be4f879..f35830f631 100644 --- a/services/web/frontend/js/utils/debugging.ts +++ b/services/web/frontend/js/utils/debugging.ts @@ -1,7 +1,13 @@ -type DebugConsole = { log(...data: any[]): void } +/* eslint-disable no-console */ +type DebugConsole = { + debug(...data: any[]): void + log(...data: any[]): void + warn(...data: any[]): void + error(...data: any[]): void +} export const debugging = new URLSearchParams(window.location.search).get('debug') === 'true' export const debugConsole: DebugConsole = debugging ? console - : { log: () => {} } + : { debug() {}, log() {}, warn: console.warn, error: console.error } diff --git a/services/web/frontend/js/vendor/libs/sharejs.js b/services/web/frontend/js/vendor/libs/sharejs.js index f6c9cf82ba..ca8a4e23ca 100644 --- a/services/web/frontend/js/vendor/libs/sharejs.js +++ b/services/web/frontend/js/vendor/libs/sharejs.js @@ -26,7 +26,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) { +define(['ace/ace','crypto-js/sha1', '@/utils/debugging'], function (_ignore, CryptoJSSHA1, { debugging, debugConsole }) { var append = void 0, bootstrapTransform = void 0, exports = void 0, @@ -1013,7 +1013,7 @@ define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) { }, { key: '_onMessage', value: function _onMessage(msg) { - // console.warn 's->c', msg + // debugConsole.warn('s->c', msg) if (msg.open === true) { // The document has been successfully opened. this.state = 'open'; @@ -1063,9 +1063,7 @@ define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) { // The document has either been closed, or an open request has failed. if (msg.error) { // An error occurred opening the document. - if (typeof console !== 'undefined' && console !== null) { - console.error('Could not open document: ' + msg.error); - } + debugConsole.error('Could not open document: ' + msg.error); this.emit('error', msg.error); if (typeof this._openCallback === 'function') { this._openCallback(msg.error); @@ -1246,10 +1244,10 @@ define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) { case 'shout': return this.emit('shout', value); default: - return typeof console !== 'undefined' && console !== null ? console.warn('Unhandled meta op:', msg) : undefined; + return debugConsole.warn('Unhandled meta op:', msg); } } else { - return typeof console !== 'undefined' && console !== null ? console.warn('Unhandled document message:', msg) : undefined; + return debugConsole.warn('Unhandled document message:', msg); } } @@ -1277,13 +1275,13 @@ define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) { this.emit('flipped_pending_to_inflight'); - if (window.useShareJsHash || window.sl_debugging) { + if (window.useShareJsHash || debugging) { var now = Date.now() var age = this.__lastSubmitTimestamp && (now - this.__lastSubmitTimestamp) var RECOMPUTE_HASH_INTERVAL = 5000 // check the document hash regularly (but not if we have checked in the last 5 seconds) var needToRecomputeHash = !this.__lastSubmitTimestamp || (age > RECOMPUTE_HASH_INTERVAL) || (age < 0) - if (needToRecomputeHash || window.sl_debugging) { + if (needToRecomputeHash || debugging) { // send git hash of current snapshot var sha1 = CryptoJSSHA1("blob " + this.snapshot.length + "\x00" + this.snapshot).toString() this.__lastSubmitTimestamp = now; @@ -1476,9 +1474,9 @@ define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) { if (editorText !== otText) { doc.emit('error','Text does not match in ace') - console.error('Text does not match!'); - console.error('editor: ' + editorText); - return console.error('ot: ' + otText); + debugConsole.error('Text does not match!'); + debugConsole.error('editor: ' + editorText); + debugConsole.error('ot: ' + otText); } } // Should probably also replace the editor text with the doc snapshot. diff --git a/services/web/package.json b/services/web/package.json index 9354b3f090..6c4d888e49 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -31,7 +31,7 @@ "type-check": "tsc --noEmit", "extract-translations": "i18next-scanner", "migrations": "east", - "convert-themes": "node frontend/js/features/source-editor/themes/convert.js", + "convert-themes": "node frontend/js/features/source-editor/themes/scripts/convert.js", "cypress:open-ct": "SHARELATEX_CONFIG=$PWD/config/settings.webpack.js cypress open --component", "cypress:run-ct": "SHARELATEX_CONFIG=$PWD/config/settings.webpack.js cypress run --component --browser chrome", "cypress:docker:open-ct": "DOCKER_USER=\"$(id -u):$(id -g)\" docker compose -f docker-compose.cypress.yml run --rm cypress run cypress:open-ct", diff --git a/services/web/test/frontend/cut-log-noise.js b/services/web/test/frontend/cut-log-noise.js new file mode 100644 index 0000000000..feba2e2383 --- /dev/null +++ b/services/web/test/frontend/cut-log-noise.js @@ -0,0 +1,10 @@ +/* eslint-disable no-console */ +import { debugConsole } from '@/utils/debugging' + +if (process.env.VERBOSE_LOGGING === 'true') { + debugConsole.debug = console.debug + debugConsole.log = console.log +} else { + debugConsole.warn = () => {} + debugConsole.error = () => {} +} diff --git a/services/web/test/frontend/features/file-tree/helpers/render-with-context.js b/services/web/test/frontend/features/file-tree/helpers/render-with-context.js index 4f2a6049c6..5ae9bd0061 100644 --- a/services/web/test/frontend/features/file-tree/helpers/render-with-context.js +++ b/services/web/test/frontend/features/file-tree/helpers/render-with-context.js @@ -1,5 +1,6 @@ import FileTreeContext from '../../../../../frontend/js/features/file-tree/components/file-tree-context' import { renderWithEditorContext } from '../../../helpers/render-with-context' +import { debugConsole } from '@/utils/debugging' export default (children, options = {}) => { let { contextProps = {}, ...renderOptions } = options @@ -16,13 +17,13 @@ export default (children, options = {}) => { ], refProviders: {}, reindexReferences: () => { - console.log('reindex references') + debugConsole.warn('reindex references') }, setRefProviderEnabled: provider => { - console.log(`ref provider ${provider} enabled`) + debugConsole.warn(`ref provider ${provider} enabled`) }, setStartedFreeTrial: () => { - console.log('started free trial') + debugConsole.warn('started free trial') }, onSelect: () => {}, ...contextProps, diff --git a/services/web/test/frontend/infrastructure/local-storage.test.js b/services/web/test/frontend/infrastructure/local-storage.test.js index 7e843332d8..c8a35337b3 100644 --- a/services/web/test/frontend/infrastructure/local-storage.test.js +++ b/services/web/test/frontend/infrastructure/local-storage.test.js @@ -2,6 +2,7 @@ import { expect } from 'chai' import sinon from 'sinon' import customLocalStorage from '../../../frontend/js/infrastructure/local-storage' +import { debugConsole } from '@/utils/debugging' describe('localStorage', function () { let originalLocalStorage @@ -15,6 +16,7 @@ describe('localStorage', function () { }) }) + let spyOnDebugConsoleError beforeEach(function () { Object.defineProperty(global, 'localStorage', { value: { @@ -25,11 +27,11 @@ describe('localStorage', function () { }, }) - global.console.error = sinon.stub() + spyOnDebugConsoleError = sinon.spy(debugConsole, 'error') }) afterEach(function () { - global.console.error.reset() + spyOnDebugConsoleError.restore() Object.defineProperty(global, 'localStorage', { value: undefined }) }) @@ -44,7 +46,7 @@ describe('localStorage', function () { global.localStorage.getItem.throws(new Error('Nope')) expect(customLocalStorage.getItem('foo')).to.be.null - expect(global.console.error).to.be.calledOnce + expect(debugConsole.error).to.be.calledOnce }) it('setItem', function () { @@ -62,7 +64,7 @@ describe('localStorage', function () { global.localStorage.setItem.throws(new Error('Nope')) expect(customLocalStorage.setItem('foo', 'bar')).to.be.null - expect(global.console.error).to.be.calledOnce + expect(debugConsole.error).to.be.calledOnce }) it('clear', function () { @@ -71,7 +73,7 @@ describe('localStorage', function () { global.localStorage.clear.throws(new Error('Nope')) expect(customLocalStorage.clear()).to.be.null - expect(global.console.error).to.be.calledOnce + expect(debugConsole.error).to.be.calledOnce }) it('removeItem', function () { @@ -81,6 +83,6 @@ describe('localStorage', function () { global.localStorage.removeItem.throws(new Error('Nope')) expect(customLocalStorage.removeItem('foo')).to.be.null - expect(global.console.error).to.be.calledOnce + expect(debugConsole.error).to.be.calledOnce }) }) diff --git a/services/web/test/frontend/shared/hooks/use-async.test.ts b/services/web/test/frontend/shared/hooks/use-async.test.ts index 1538ca8774..ee0d033372 100644 --- a/services/web/test/frontend/shared/hooks/use-async.test.ts +++ b/services/web/test/frontend/shared/hooks/use-async.test.ts @@ -2,6 +2,7 @@ import { renderHook, act } from '@testing-library/react-hooks' import { expect } from 'chai' import sinon from 'sinon' import useAsync from '../../../../frontend/js/shared/hooks/use-async' +import { debugConsole } from '@/utils/debugging' function deferred() { let res!: ( @@ -50,14 +51,13 @@ const rejectedState = { } describe('useAsync', function () { + let spyOnDebugConsoleError: sinon.SinonSpy beforeEach(function () { - global.console.error = sinon.stub() + spyOnDebugConsoleError = sinon.spy(debugConsole, 'error') }) afterEach(function () { - // eslint-disable-next-line - // @ts-ignore - global.console.error.reset() + spyOnDebugConsoleError.restore() }) it('exposes the methods', function () { @@ -177,6 +177,6 @@ describe('useAsync', function () { await p }) - expect(global.console.error).not.to.have.been.called + expect(debugConsole.error).not.to.have.been.called }) }) diff --git a/services/web/types/window.ts b/services/web/types/window.ts index f9dd073ffa..68290269ae 100644 --- a/services/web/types/window.ts +++ b/services/web/types/window.ts @@ -8,10 +8,6 @@ declare global { // eslint-disable-next-line no-unused-vars interface Window { csrfToken: string - sl_console: { - log: (message: string) => void - } - sl_debugging: boolean user: User user_id?: string oauthProviders: OAuthProviders