mirror of
https://github.com/overleaf/overleaf.git
synced 2024-09-16 02:52:31 -04:00
Handle PDF rendering errors in the new logs UI (#4280)
* Handle PDF rendering errors in the new logs UI * Remove new logs UI specific code from the PDFController * Only change view with errors and validation issues in the new logs UI GitOrigin-RevId: 0761ac224db39fdacbb61692c1aa35c3da82a76b
This commit is contained in:
parent
966013f58a
commit
51c6d90c17
3 changed files with 100 additions and 78 deletions
|
@ -12,9 +12,22 @@ div.full-size.pdf(ng-controller="PdfController")
|
||||||
lastCompileTimestamp: pdf.lastCompileTimestamp,
|
lastCompileTimestamp: pdf.lastCompileTimestamp,
|
||||||
logEntries: pdf.logEntries,
|
logEntries: pdf.logEntries,
|
||||||
validationIssues: pdf.validation,
|
validationIssues: pdf.validation,
|
||||||
errors: clsiErrors,
|
|
||||||
rawLog: pdf.rawLog,
|
rawLog: pdf.rawLog,
|
||||||
compileFailed: pdf.compileFailed
|
compileFailed: pdf.compileFailed,
|
||||||
|
errors: {
|
||||||
|
error: pdf.error,
|
||||||
|
renderingError: pdf.renderingError,
|
||||||
|
clsiMaintenance: pdf.clsiMaintenance,
|
||||||
|
clsiUnavailable: pdf.clsiUnavailable,
|
||||||
|
tooRecentlyCompiled: pdf.tooRecentlyCompiled,
|
||||||
|
compileTerminated: pdf.compileTerminated,
|
||||||
|
rateLimited: pdf.rateLimited,
|
||||||
|
compileInProgress: pdf.compileInProgress,
|
||||||
|
timedout: pdf.timedout,
|
||||||
|
projectTooLarge: pdf.projectTooLarge,
|
||||||
|
autoCompileDisabled: pdf.autoCompileDisabled,
|
||||||
|
failure: pdf.failure
|
||||||
|
}
|
||||||
}`
|
}`
|
||||||
on-clear-cache="clearCache"
|
on-clear-cache="clearCache"
|
||||||
on-recompile="recompile"
|
on-recompile="recompile"
|
||||||
|
|
|
@ -23,51 +23,17 @@ function PreviewLogsPane({
|
||||||
onClearCache,
|
onClearCache,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const nowTS = Date.now()
|
|
||||||
const {
|
const {
|
||||||
all: allCompilerIssues = [],
|
all: allCompilerIssues = [],
|
||||||
errors: compilerErrors = [],
|
errors: compilerErrors = [],
|
||||||
warnings: compilerWarnings = [],
|
warnings: compilerWarnings = [],
|
||||||
typesetting: compilerTypesettingIssues = [],
|
typesetting: compilerTypesettingIssues = [],
|
||||||
} = logEntries
|
} = logEntries
|
||||||
|
const allLogEntries = [
|
||||||
const errorsUI = Object.keys(errors).map((name, index) => (
|
|
||||||
<PreviewError key={`${nowTS}-${index}`} name={name} />
|
|
||||||
))
|
|
||||||
|
|
||||||
const validationIssuesUI = Object.keys(
|
|
||||||
validationIssues
|
|
||||||
).map((name, index) => (
|
|
||||||
<PreviewValidationIssue
|
|
||||||
key={`${nowTS}-${index}`}
|
|
||||||
name={name}
|
|
||||||
details={validationIssues[name]}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
const logEntriesUI = [
|
|
||||||
...compilerErrors,
|
...compilerErrors,
|
||||||
...compilerWarnings,
|
...compilerWarnings,
|
||||||
...compilerTypesettingIssues,
|
...compilerTypesettingIssues,
|
||||||
].map((logEntry, index) => (
|
]
|
||||||
<PreviewLogsPaneEntry
|
|
||||||
key={`${nowTS}-${index}`}
|
|
||||||
headerTitle={logEntry.message}
|
|
||||||
rawContent={logEntry.content}
|
|
||||||
logType={logEntry.type}
|
|
||||||
formattedContent={logEntry.humanReadableHintComponent}
|
|
||||||
extraInfoURL={logEntry.extraInfoURL}
|
|
||||||
level={logEntry.level}
|
|
||||||
entryAriaLabel={t('log_entry_description', {
|
|
||||||
level: logEntry.level,
|
|
||||||
})}
|
|
||||||
sourceLocation={{
|
|
||||||
file: logEntry.file,
|
|
||||||
line: logEntry.line,
|
|
||||||
column: logEntry.column,
|
|
||||||
}}
|
|
||||||
onSourceLocationClick={onLogEntryLocationClick}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
|
|
||||||
const actionsUI = (
|
const actionsUI = (
|
||||||
<div className="logs-pane-actions">
|
<div className="logs-pane-actions">
|
||||||
|
@ -118,9 +84,16 @@ function PreviewLogsPane({
|
||||||
variantWithFirstErrorPopup={variantWithFirstErrorPopup}
|
variantWithFirstErrorPopup={variantWithFirstErrorPopup}
|
||||||
/>
|
/>
|
||||||
{autoCompileHasLintingError ? <AutoCompileLintingErrorEntry /> : null}
|
{autoCompileHasLintingError ? <AutoCompileLintingErrorEntry /> : null}
|
||||||
{errors ? errorsUI : null}
|
{errors ? <PreviewErrors errors={errors} /> : null}
|
||||||
{validationIssues ? validationIssuesUI : null}
|
{validationIssues ? (
|
||||||
{allCompilerIssues.length > 0 ? logEntriesUI : null}
|
<PreviewValidationIssues validationIssues={validationIssues} />
|
||||||
|
) : null}
|
||||||
|
{allCompilerIssues.length > 0 ? (
|
||||||
|
<PreviewLogEntries
|
||||||
|
logEntries={allLogEntries}
|
||||||
|
onLogEntryLocationClick={onLogEntryLocationClick}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
{rawLog && rawLog !== '' ? rawLogUI : null}
|
{rawLog && rawLog !== '' ? rawLogUI : null}
|
||||||
{actionsUI}
|
{actionsUI}
|
||||||
</div>
|
</div>
|
||||||
|
@ -128,6 +101,48 @@ function PreviewLogsPane({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PreviewErrors = ({ errors }) => {
|
||||||
|
const nowTS = Date.now()
|
||||||
|
return Object.entries(errors).map(([name, exists], index) => {
|
||||||
|
return exists && <PreviewError key={`${nowTS}-${index}`} name={name} />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const PreviewValidationIssues = ({ validationIssues }) => {
|
||||||
|
const nowTS = Date.now()
|
||||||
|
return Object.keys(validationIssues).map((name, index) => (
|
||||||
|
<PreviewValidationIssue
|
||||||
|
key={`${nowTS}-${index}`}
|
||||||
|
name={name}
|
||||||
|
details={validationIssues[name]}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
const PreviewLogEntries = ({ logEntries, onLogEntryLocationClick }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const nowTS = Date.now()
|
||||||
|
return logEntries.map((logEntry, index) => (
|
||||||
|
<PreviewLogsPaneEntry
|
||||||
|
key={`${nowTS}-${index}`}
|
||||||
|
headerTitle={logEntry.message}
|
||||||
|
rawContent={logEntry.content}
|
||||||
|
logType={logEntry.type}
|
||||||
|
formattedContent={logEntry.humanReadableHintComponent}
|
||||||
|
extraInfoURL={logEntry.extraInfoURL}
|
||||||
|
level={logEntry.level}
|
||||||
|
entryAriaLabel={t('log_entry_description', {
|
||||||
|
level: logEntry.level,
|
||||||
|
})}
|
||||||
|
sourceLocation={{
|
||||||
|
file: logEntry.file,
|
||||||
|
line: logEntry.line,
|
||||||
|
column: logEntry.column,
|
||||||
|
}}
|
||||||
|
onSourceLocationClick={onLogEntryLocationClick}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
function AutoCompileLintingErrorEntry() {
|
function AutoCompileLintingErrorEntry() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
return (
|
return (
|
||||||
|
@ -190,6 +205,19 @@ function LogsPaneInfoNotice({ variantWithFirstErrorPopup }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreviewErrors.propTypes = {
|
||||||
|
errors: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewValidationIssues.propTypes = {
|
||||||
|
validationIssues: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewLogEntries.propTypes = {
|
||||||
|
logEntries: PropTypes.array.isRequired,
|
||||||
|
onLogEntryLocationClick: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
LogsPaneInfoNotice.propTypes = {
|
LogsPaneInfoNotice.propTypes = {
|
||||||
variantWithFirstErrorPopup: PropTypes.bool,
|
variantWithFirstErrorPopup: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -357,9 +357,7 @@ App.controller(
|
||||||
$scope.pdf.failedCheck = false
|
$scope.pdf.failedCheck = false
|
||||||
$scope.pdf.compileInProgress = false
|
$scope.pdf.compileInProgress = false
|
||||||
$scope.pdf.autoCompileDisabled = false
|
$scope.pdf.autoCompileDisabled = false
|
||||||
if (window.showNewLogsUI) {
|
$scope.pdf.compileFailed = false
|
||||||
$scope.clsiErrors = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make a cache to look up files by name
|
// make a cache to look up files by name
|
||||||
const fileByPath = {}
|
const fileByPath = {}
|
||||||
|
@ -504,35 +502,6 @@ App.controller(
|
||||||
$scope.pdf.error = true
|
$scope.pdf.error = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.showNewLogsUI) {
|
|
||||||
$scope.pdf.compileFailed = false
|
|
||||||
// `$scope.clsiErrors` stores the error states nested within `$scope.pdf`
|
|
||||||
// for use with React's <PreviewPane errors={$scope.clsiErrors}/>
|
|
||||||
$scope.clsiErrors = Object.assign(
|
|
||||||
{},
|
|
||||||
$scope.pdf.error ? { error: true } : null,
|
|
||||||
$scope.pdf.renderingError ? { renderingError: true } : null,
|
|
||||||
$scope.pdf.clsiMaintenance ? { clsiMaintenance: true } : null,
|
|
||||||
$scope.pdf.clsiUnavailable ? { clsiUnavailable: true } : null,
|
|
||||||
$scope.pdf.tooRecentlyCompiled ? { tooRecentlyCompiled: true } : null,
|
|
||||||
$scope.pdf.compileTerminated ? { compileTerminated: true } : null,
|
|
||||||
$scope.pdf.rateLimited ? { rateLimited: true } : null,
|
|
||||||
$scope.pdf.compileInProgress ? { compileInProgress: true } : null,
|
|
||||||
$scope.pdf.timedout ? { timedout: true } : null,
|
|
||||||
$scope.pdf.projectTooLarge ? { projectTooLarge: true } : null,
|
|
||||||
$scope.pdf.autoCompileDisabled ? { autoCompileDisabled: true } : null,
|
|
||||||
$scope.pdf.failure ? { failure: true } : null
|
|
||||||
)
|
|
||||||
|
|
||||||
if (
|
|
||||||
$scope.pdf.view === 'errors' ||
|
|
||||||
$scope.pdf.view === 'validation-problems'
|
|
||||||
) {
|
|
||||||
$scope.shouldShowLogs = true
|
|
||||||
$scope.pdf.compileFailed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const IGNORE_FILES = ['output.fls', 'output.fdb_latexmk']
|
const IGNORE_FILES = ['output.fls', 'output.fdb_latexmk']
|
||||||
$scope.pdf.outputFiles = []
|
$scope.pdf.outputFiles = []
|
||||||
|
|
||||||
|
@ -567,6 +536,23 @@ App.controller(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In the existing compile UI, errors and validation problems are shown in the PDF pane, whereas in the new
|
||||||
|
// one they're shown in the logs pane. This `$watch`er makes sure we change the view in the new logs UI.
|
||||||
|
// This should be removed once we stop supporting the two different log UIs.
|
||||||
|
if (window.showNewLogsUI) {
|
||||||
|
$scope.$watch(
|
||||||
|
() =>
|
||||||
|
$scope.pdf.view === 'errors' ||
|
||||||
|
$scope.pdf.view === 'validation-problems',
|
||||||
|
newVal => {
|
||||||
|
if (newVal) {
|
||||||
|
$scope.shouldShowLogs = true
|
||||||
|
$scope.pdf.compileFailed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function fetchLogs(fileByPath, options) {
|
function fetchLogs(fileByPath, options) {
|
||||||
let blgFile, chktexFile, logFile
|
let blgFile, chktexFile, logFile
|
||||||
|
|
||||||
|
@ -836,11 +822,6 @@ App.controller(
|
||||||
$scope.pdf.renderingError = false
|
$scope.pdf.renderingError = false
|
||||||
$scope.pdf.error = true
|
$scope.pdf.error = true
|
||||||
$scope.pdf.view = 'errors'
|
$scope.pdf.view = 'errors'
|
||||||
if (window.showNewLogsUI) {
|
|
||||||
$scope.clsiErrors = { error: true }
|
|
||||||
$scope.shouldShowLogs = true
|
|
||||||
$scope.pdf.compileFailed = true
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
$scope.lastFinishedCompileAt = Date.now()
|
$scope.lastFinishedCompileAt = Date.now()
|
||||||
|
|
Loading…
Reference in a new issue