mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-31 12:51:35 +02:00
Merge pull request #3470 from overleaf/eslint
Upgrade and configure ESLint GitOrigin-RevId: ad5aeaf85e72c847a125ff3a9db99a12855e38aa
This commit is contained in:
@@ -1,24 +1,36 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:jsx-a11y/recommended",
|
||||
"standard",
|
||||
"standard-jsx",
|
||||
"standard-react",
|
||||
"prettier",
|
||||
"plugin:prettier/recommended",
|
||||
"prettier/prettier",
|
||||
"prettier/react",
|
||||
"prettier/standard",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:jsx-a11y/recommended"
|
||||
"prettier/standard"
|
||||
],
|
||||
"plugins": [
|
||||
"prettier",
|
||||
"jsx-a11y",
|
||||
"mocha",
|
||||
"chai-expect",
|
||||
"chai-friendly"
|
||||
],
|
||||
"parser": "babel-eslint",
|
||||
"env": {
|
||||
"browser": true,
|
||||
"mocha": true
|
||||
"mocha": true,
|
||||
"node": true,
|
||||
"es2020": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
// Tell eslint-plugin-react to detect which version of React we are using
|
||||
@@ -27,12 +39,31 @@
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"dot-notation": "off",
|
||||
"node/no-callback-literal": "off",
|
||||
"node/no-deprecated-api": "off",
|
||||
"node/handle-callback-err": "off",
|
||||
"node/no-path-concat": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
// Swap the no-unused-expressions rule with a more chai-friendly one
|
||||
"no-unused-expressions": 0,
|
||||
"no-unused-expressions": "off",
|
||||
"no-unused-vars": "off",
|
||||
"no-var": "off",
|
||||
"prefer-const": "off",
|
||||
"prefer-regex-literals": "off",
|
||||
"react/jsx-curly-brace-presence": ["error", {
|
||||
"props": "never",
|
||||
"children": "never"
|
||||
}],
|
||||
"react/display-name": "off",
|
||||
"react/no-unescaped-entities": "off",
|
||||
"react/no-unused-prop-types": "off",
|
||||
"react/jsx-no-target-blank": "off",
|
||||
"react/jsx-handler-names": "off",
|
||||
"array-callback-return": "off",
|
||||
"no-empty": "off",
|
||||
"no-unreachable-loop": "off",
|
||||
"no-loss-of-precision": "off",
|
||||
"chai-friendly/no-unused-expressions": "error"
|
||||
},
|
||||
"overrides": [
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"jsxSingleQuote": false,
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@ WITH_NODE_MODULES_PATH = \
|
||||
format_backend \
|
||||
format_frontend \
|
||||
format_misc \
|
||||
format_styles \
|
||||
format_test \
|
||||
$(TEST_SUITES) \
|
||||
|
||||
@@ -168,41 +169,47 @@ $(WITH_NODE_MODULES_PATH): export PATH=$(NODE_MODULES_PATH)
|
||||
|
||||
format: format_backend
|
||||
format_backend:
|
||||
prettier-eslint \
|
||||
eslint \
|
||||
app.js \
|
||||
'app/**/*.js' \
|
||||
'modules/*/index.js' \
|
||||
'modules/*/app/**/*.js' \
|
||||
--list-different
|
||||
--max-warnings=0
|
||||
|
||||
format: format_frontend
|
||||
format_frontend:
|
||||
prettier-eslint \
|
||||
'frontend/**/*.{js,less}' \
|
||||
'modules/*/frontend/**/*.{js,less}' \
|
||||
eslint \
|
||||
'frontend/**/*.js' \
|
||||
'modules/*/frontend/**/*.js' \
|
||||
--max-warnings=0
|
||||
|
||||
format: format_styles
|
||||
format_styles:
|
||||
prettier \
|
||||
'frontend/**/*.less' \
|
||||
'modules/*/frontend/**/*.less' \
|
||||
--list-different
|
||||
|
||||
format: format_test
|
||||
format_test:
|
||||
prettier-eslint \
|
||||
eslint \
|
||||
'test/**/*.js' \
|
||||
'modules/*/test/**/*.js' \
|
||||
--list-different
|
||||
--max-warnings=0
|
||||
|
||||
format: format_misc
|
||||
# migrations, scripts, webpack config, karma config
|
||||
format_misc:
|
||||
prettier-eslint \
|
||||
'**/*.{js,less}' \
|
||||
eslint . \
|
||||
--ignore app.js \
|
||||
--ignore 'app/**/*.js' \
|
||||
--ignore 'modules/*/app/**/*.js' \
|
||||
--ignore 'modules/*/index.js' \
|
||||
--ignore 'frontend/**/*.{js,less}' \
|
||||
--ignore 'modules/*/frontend/**/*.{js,less}' \
|
||||
--ignore 'frontend/**/*.js' \
|
||||
--ignore 'modules/*/frontend/**/*.js' \
|
||||
--ignore 'test/**/*.js' \
|
||||
--ignore 'modules/*/test/**/*.js' \
|
||||
--list-different
|
||||
--max-warnings=0
|
||||
|
||||
format_in_docker:
|
||||
$(RUN_LINT_FORMAT) make format -j --output-sync
|
||||
@@ -210,12 +217,6 @@ format_in_docker:
|
||||
format_fix:
|
||||
npm run --silent format:fix
|
||||
|
||||
lint:
|
||||
npm run --silent lint
|
||||
|
||||
lint_in_docker:
|
||||
$(RUN_LINT_FORMAT) make lint
|
||||
|
||||
#
|
||||
# Build & publish
|
||||
#
|
||||
@@ -291,5 +292,5 @@ $(MODULE_TARGETS):
|
||||
test test_module test_unit test_unit_app \
|
||||
test_unit_modules test_unit_module test_karma test_karma_run \
|
||||
test_karma_build_run test_frontend test_acceptance test_acceptance_app \
|
||||
test_acceptance_modules test_acceptance_module ci format format_fix lint \
|
||||
test_acceptance_modules test_acceptance_module ci format format_fix \
|
||||
build build_test_karma publish tar
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-return-assign,
|
||||
no-unused-vars,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
@@ -41,9 +41,7 @@ module.exports = ChatApiHandler = {
|
||||
sendGlobalMessage(project_id, user_id, content, callback) {
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.chat.internal_url
|
||||
}/project/${project_id}/messages`,
|
||||
url: `${settings.apis.chat.internal_url}/project/${project_id}/messages`,
|
||||
method: 'POST',
|
||||
json: { user_id, content }
|
||||
},
|
||||
@@ -62,9 +60,7 @@ module.exports = ChatApiHandler = {
|
||||
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.chat.internal_url
|
||||
}/project/${project_id}/messages`,
|
||||
url: `${settings.apis.chat.internal_url}/project/${project_id}/messages`,
|
||||
method: 'GET',
|
||||
qs,
|
||||
json: true
|
||||
@@ -79,9 +75,7 @@ module.exports = ChatApiHandler = {
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.chat.internal_url
|
||||
}/project/${project_id}/thread/${thread_id}/messages`,
|
||||
url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/messages`,
|
||||
method: 'POST',
|
||||
json: { user_id, content }
|
||||
},
|
||||
@@ -109,9 +103,7 @@ module.exports = ChatApiHandler = {
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.chat.internal_url
|
||||
}/project/${project_id}/thread/${thread_id}/resolve`,
|
||||
url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/resolve`,
|
||||
method: 'POST',
|
||||
json: { user_id }
|
||||
},
|
||||
@@ -125,9 +117,7 @@ module.exports = ChatApiHandler = {
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.chat.internal_url
|
||||
}/project/${project_id}/thread/${thread_id}/reopen`,
|
||||
url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/reopen`,
|
||||
method: 'POST'
|
||||
},
|
||||
callback
|
||||
@@ -140,9 +130,7 @@ module.exports = ChatApiHandler = {
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.chat.internal_url
|
||||
}/project/${project_id}/thread/${thread_id}`,
|
||||
url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}`,
|
||||
method: 'DELETE'
|
||||
},
|
||||
callback
|
||||
@@ -155,9 +143,7 @@ module.exports = ChatApiHandler = {
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.chat.internal_url
|
||||
}/project/${project_id}/thread/${thread_id}/messages/${message_id}/edit`,
|
||||
url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/messages/${message_id}/edit`,
|
||||
method: 'POST',
|
||||
json: {
|
||||
content
|
||||
@@ -173,9 +159,7 @@ module.exports = ChatApiHandler = {
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.chat.internal_url
|
||||
}/project/${project_id}/thread/${thread_id}/messages/${message_id}`,
|
||||
url: `${settings.apis.chat.internal_url}/project/${project_id}/thread/${thread_id}/messages/${message_id}`,
|
||||
method: 'DELETE'
|
||||
},
|
||||
callback
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-undef,
|
||||
no-unused-vars,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
@@ -18,9 +18,7 @@ const Settings = require('settings-sharelatex')
|
||||
module.exports = CollaboratorsEmailHandler = {
|
||||
_buildInviteUrl(project, invite) {
|
||||
return (
|
||||
`${Settings.siteUrl}/project/${project._id}/invite/token/${
|
||||
invite.token
|
||||
}?` +
|
||||
`${Settings.siteUrl}/project/${project._id}/invite/token/${invite.token}?` +
|
||||
[
|
||||
`project_name=${encodeURIComponent(project.name)}`,
|
||||
`user_first_name=${encodeURIComponent(project.owner_ref.first_name)}`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -584,9 +584,7 @@ const ClsiManager = {
|
||||
},
|
||||
|
||||
getOutputFileStream(projectId, userId, buildId, outputFilePath, callback) {
|
||||
const url = `${
|
||||
Settings.apis.clsi.url
|
||||
}/project/${projectId}/user/${userId}/build/${buildId}/output/${outputFilePath}`
|
||||
const url = `${Settings.apis.clsi.url}/project/${projectId}/user/${userId}/build/${buildId}/output/${outputFilePath}`
|
||||
ClsiCookieManager.getCookieJar(projectId, (err, jar) => {
|
||||
if (err != null) {
|
||||
return callback(
|
||||
@@ -766,9 +764,7 @@ const ClsiManager = {
|
||||
path = path.replace(/^\//, '') // Remove leading /
|
||||
resources.push({
|
||||
path,
|
||||
url: `${Settings.apis.filestore.url}/project/${project._id}/file/${
|
||||
file._id
|
||||
}`,
|
||||
url: `${Settings.apis.filestore.url}/project/${project._id}/file/${file._id}`,
|
||||
modified: file.created != null ? file.created.getTime() : undefined
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-undef,
|
||||
no-unused-vars,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
@@ -26,9 +26,7 @@ const DocstoreManager = {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
}
|
||||
const url = `${
|
||||
settings.apis.docstore.url
|
||||
}/project/${project_id}/doc/${doc_id}`
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
|
||||
return request.del({ url: url, timeout: TIMEOUT }, function(
|
||||
error,
|
||||
res,
|
||||
@@ -128,9 +126,7 @@ const DocstoreManager = {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
let url = `${
|
||||
settings.apis.docstore.url
|
||||
}/project/${project_id}/doc/${doc_id}`
|
||||
let url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
|
||||
if (options.include_deleted) {
|
||||
url += '?include_deleted=true'
|
||||
}
|
||||
@@ -177,9 +173,7 @@ const DocstoreManager = {
|
||||
if (callback == null) {
|
||||
callback = function(error, modified, rev) {}
|
||||
}
|
||||
const url = `${
|
||||
settings.apis.docstore.url
|
||||
}/project/${project_id}/doc/${doc_id}`
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
|
||||
return request.post(
|
||||
{
|
||||
url,
|
||||
|
||||
@@ -132,9 +132,7 @@ function getProjectDocsIfMatch(projectId, projectStateHash, callback) {
|
||||
// docs from redis via the docupdater. Otherwise we will need to
|
||||
// fall back to getting them from mongo.
|
||||
const timer = new metrics.Timer('get-project-docs')
|
||||
const url = `${
|
||||
settings.apis.documentupdater.url
|
||||
}/project/${projectId}/get_and_flush_if_old?state=${projectStateHash}`
|
||||
const url = `${settings.apis.documentupdater.url}/project/${projectId}/get_and_flush_if_old?state=${projectStateHash}`
|
||||
request.post(url, function(error, res, body) {
|
||||
timer.done()
|
||||
if (error) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-undef,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-dupe-keys,
|
||||
no-unused-vars,
|
||||
|
||||
@@ -146,9 +146,7 @@ templates.registered = ctaTemplate({
|
||||
},
|
||||
secondaryMessage() {
|
||||
return [
|
||||
`If you have any questions or problems, please contact ${
|
||||
settings.adminEmail
|
||||
}`
|
||||
`If you have any questions or problems, please contact ${settings.adminEmail}`
|
||||
]
|
||||
},
|
||||
ctaText() {
|
||||
@@ -165,9 +163,7 @@ templates.canceledSubscription = ctaTemplate({
|
||||
},
|
||||
message() {
|
||||
return [
|
||||
`We are sorry to see you cancelled your ${
|
||||
settings.appName
|
||||
} premium subscription. Would you mind giving us some feedback on what the site is lacking at the moment via this quick survey?`
|
||||
`We are sorry to see you cancelled your ${settings.appName} premium subscription. Would you mind giving us some feedback on what the site is lacking at the moment via this quick survey?`
|
||||
]
|
||||
},
|
||||
secondaryMessage() {
|
||||
@@ -292,9 +288,7 @@ templates.verifyEmailToJoinTeam = ctaTemplate({
|
||||
},
|
||||
message(opts) {
|
||||
return [
|
||||
`Please click the button below to join the team and enjoy the benefits of an upgraded ${
|
||||
settings.appName
|
||||
} account.`
|
||||
`Please click the button below to join the team and enjoy the benefits of an upgraded ${settings.appName} account.`
|
||||
]
|
||||
},
|
||||
ctaText(opts) {
|
||||
@@ -348,9 +342,7 @@ templates.ownershipTransferConfirmationPreviousOwner = NoCTAEmailTemplate({
|
||||
: `<b>${projectName}</b>`
|
||||
return [
|
||||
`As per your request, we have made ${nameAndEmail} the owner of ${projectNameDisplay}.`,
|
||||
`If you haven't asked to change the owner of ${projectNameDisplay}, please get in touch with us via ${
|
||||
settings.adminEmail
|
||||
}.`
|
||||
`If you haven't asked to change the owner of ${projectNameDisplay}, please get in touch with us via ${settings.adminEmail}.`
|
||||
]
|
||||
}
|
||||
})
|
||||
@@ -403,23 +395,17 @@ templates.userOnboardingEmail = NoCTAEmailTemplate({
|
||||
message(opts, isPlainText) {
|
||||
const learnLatexLink = EmailMessageHelper.displayLink(
|
||||
'Learn LaTeX in 30 minutes',
|
||||
`${
|
||||
settings.siteUrl
|
||||
}/learn/latex/Learn_LaTeX_in_30_minutes?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
|
||||
`${settings.siteUrl}/learn/latex/Learn_LaTeX_in_30_minutes?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
|
||||
isPlainText
|
||||
)
|
||||
const templatesLinks = EmailMessageHelper.displayLink(
|
||||
'Find a beautiful template',
|
||||
`${
|
||||
settings.siteUrl
|
||||
}/latex/templates?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
|
||||
`${settings.siteUrl}/latex/templates?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
|
||||
isPlainText
|
||||
)
|
||||
const collaboratorsLink = EmailMessageHelper.displayLink(
|
||||
'Work with your collaborators',
|
||||
`${
|
||||
settings.siteUrl
|
||||
}/learn/how-to/Sharing_a_project?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
|
||||
`${settings.siteUrl}/learn/how-to/Sharing_a_project?utm_source=overleaf&utm_medium=email&utm_campaign=onboarding`,
|
||||
isPlainText
|
||||
)
|
||||
const siteLink = EmailMessageHelper.displayLink(
|
||||
@@ -438,9 +424,7 @@ templates.userOnboardingEmail = NoCTAEmailTemplate({
|
||||
isPlainText
|
||||
)
|
||||
return [
|
||||
`Thanks for signing up for ${
|
||||
settings.appName
|
||||
} recently. We hope you've been finding it useful! Here are some key features to help you get the most out of the service:`,
|
||||
`Thanks for signing up for ${settings.appName} recently. We hope you've been finding it useful! Here are some key features to help you get the most out of the service:`,
|
||||
`${learnLatexLink}: In this tutorial we provide a quick and easy first introduction to LaTeX with no prior knowledge required. By the time you are finished, you will have written your first LaTeX document!`,
|
||||
`${templatesLinks}: If you're looking for a template or example to get started, we've a large selection available in our template gallery, including CVs, project reports, journal articles and more.`,
|
||||
`${collaboratorsLink}: One of the key features of Overleaf is the ability to share projects and collaborate on them with other users. Find out how to share your projecs with your colleagues in this quick how-to guide.`,
|
||||
@@ -485,12 +469,8 @@ templates.securityAlert = NoCTAEmailTemplate({
|
||||
`We are writing to let you know that ${actionDescribed} on ${dateFormatted} at ${timeFormatted} GMT.`,
|
||||
...message,
|
||||
`If this was you, you can ignore this email.`,
|
||||
`If this was not you, we recommend getting in touch with our support team at ${
|
||||
settings.adminEmail
|
||||
} to report this as potentially suspicious activity on your account.`,
|
||||
`We also encourage you to read our ${helpLink} to keeping your ${
|
||||
settings.appName
|
||||
} account safe.`
|
||||
`If this was not you, we recommend getting in touch with our support team at ${settings.adminEmail} to report this as potentially suspicious activity on your account.`,
|
||||
`We also encourage you to read our ${helpLink} to keeping your ${settings.appName} account safe.`
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -105,9 +105,7 @@ class SAMLSessionDataMissing extends BackwardCompatibleError {
|
||||
samlSession.userEmailAttributeUnreliable
|
||||
) {
|
||||
this.tryAgain = false
|
||||
this.message = `Your account settings at your institution prevent us from accessing your email address. You will need to make your email address public at your institution in order to link with ${
|
||||
settings.appName
|
||||
}. Please contact your IT department if you have any questions.`
|
||||
this.message = `Your account settings at your institution prevent us from accessing your email address. You will need to make your email address public at your institution in order to link with ${settings.appName}. Please contact your IT department if you have any questions.`
|
||||
} else if (!institutionEmail) {
|
||||
this.message =
|
||||
'Unable to confirm your institutional email address. The institutional identity provider did not provide an email address in the expected attribute. Please contact us if this keeps happening.'
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
standard/no-callback-literal,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
@@ -202,9 +201,7 @@ module.exports = ExportsHandler = self = {
|
||||
}
|
||||
return request.get(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.project_history.url
|
||||
}/project/${project_id}/version`,
|
||||
url: `${settings.apis.project_history.url}/project/${project_id}/version`,
|
||||
json: true
|
||||
},
|
||||
function(err, res, body) {
|
||||
@@ -217,9 +214,7 @@ module.exports = ExportsHandler = self = {
|
||||
return callback(null, body.version)
|
||||
} else {
|
||||
err = new OError(
|
||||
`project history version returned a failure status code: ${
|
||||
res.statusCode
|
||||
}`,
|
||||
`project history version returned a failure status code: ${res.statusCode}`,
|
||||
{ project_id }
|
||||
)
|
||||
return callback(err)
|
||||
@@ -262,9 +257,7 @@ module.exports = ExportsHandler = self = {
|
||||
}
|
||||
return request.get(
|
||||
{
|
||||
url: `${
|
||||
settings.apis.v1.url
|
||||
}/api/v1/sharelatex/exports/${export_id}/${type}_url`,
|
||||
url: `${settings.apis.v1.url}/api/v1/sharelatex/exports/${export_id}/${type}_url`,
|
||||
auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass }
|
||||
},
|
||||
function(err, res, body) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -97,9 +97,7 @@ const FileStoreHandler = {
|
||||
writeStream.on('response', function(response) {
|
||||
if (![200, 201].includes(response.statusCode)) {
|
||||
err = new OError(
|
||||
`non-ok response from filestore for upload: ${
|
||||
response.statusCode
|
||||
}`,
|
||||
`non-ok response from filestore for upload: ${response.statusCode}`,
|
||||
{ statusCode: response.statusCode }
|
||||
)
|
||||
return callbackOnce(err)
|
||||
|
||||
@@ -179,9 +179,7 @@ module.exports = HistoryController = {
|
||||
HistoryController._makeRequest(
|
||||
{
|
||||
method: 'POST',
|
||||
url: `${
|
||||
settings.apis.project_history.url
|
||||
}/project/${projectId}/user/${userId}/labels`,
|
||||
url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels`,
|
||||
json: { comment, version }
|
||||
},
|
||||
function(err, label) {
|
||||
@@ -274,9 +272,7 @@ module.exports = HistoryController = {
|
||||
HistoryController._makeRequest(
|
||||
{
|
||||
method: 'DELETE',
|
||||
url: `${
|
||||
settings.apis.project_history.url
|
||||
}/project/${projectId}/user/${userId}/labels/${labelId}`
|
||||
url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels/${labelId}`
|
||||
},
|
||||
function(err) {
|
||||
if (err) {
|
||||
@@ -338,9 +334,7 @@ module.exports = HistoryController = {
|
||||
}
|
||||
// increase timeout to 6 minutes
|
||||
res.setTimeout(6 * 60 * 1000)
|
||||
const url = `${
|
||||
settings.apis.v1_history.url
|
||||
}/projects/${v1ProjectId}/version/${version}/zip`
|
||||
const url = `${settings.apis.v1_history.url}/projects/${v1ProjectId}/version/${version}/zip`
|
||||
const options = {
|
||||
auth: {
|
||||
user: settings.apis.v1_history.user,
|
||||
|
||||
@@ -106,8 +106,8 @@ async function injectUserDetails(data) {
|
||||
const entries = Array.isArray(data.diff)
|
||||
? data.diff
|
||||
: Array.isArray(data.updates)
|
||||
? data.updates
|
||||
: []
|
||||
? data.updates
|
||||
: []
|
||||
for (const entry of entries) {
|
||||
for (const user of (entry.meta && entry.meta.users) || []) {
|
||||
if (typeof user === 'string') {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -207,9 +207,7 @@ var makeAffiliationRequest = function(requestOptions, callback) {
|
||||
if (body && body.errors) {
|
||||
errorMessage = `${response.statusCode}: ${body.errors}`
|
||||
} else {
|
||||
errorMessage = `${requestOptions.defaultErrorMessage}: ${
|
||||
response.statusCode
|
||||
}`
|
||||
errorMessage = `${requestOptions.defaultErrorMessage}: ${response.statusCode}`
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
|
||||
@@ -132,9 +132,7 @@ module.exports = LinkedFilesController = {
|
||||
},
|
||||
|
||||
handleError(error, req, res, next) {
|
||||
if (error instanceof BadDataError) {
|
||||
return res.status(400).send('The submitted data is not valid')
|
||||
} else if (error instanceof AccessDeniedError) {
|
||||
if (error instanceof AccessDeniedError) {
|
||||
return res.status(403).send('You do not have access to this project')
|
||||
} else if (error instanceof BadDataError) {
|
||||
return res.status(400).send('The submitted data is not valid')
|
||||
@@ -156,9 +154,7 @@ module.exports = LinkedFilesController = {
|
||||
return res
|
||||
.status(422)
|
||||
.send(
|
||||
`Your URL could not be reached (${
|
||||
error.statusCode
|
||||
} status code). Please check it and try again.`
|
||||
`Your URL could not be reached (${error.statusCode} status code). Please check it and try again.`
|
||||
)
|
||||
} else if (error instanceof InvalidUrlError) {
|
||||
return res
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
@@ -100,9 +100,7 @@ module.exports = ProjectOutputFileAgent = {
|
||||
) // Created
|
||||
} else {
|
||||
err = new OutputFileFetchFailedError(
|
||||
`Output file fetch failed: ${linkedFileData.build_id}, ${
|
||||
linkedFileData.source_output_file_path
|
||||
}`
|
||||
`Output file fetch failed: ${linkedFileData.build_id}, ${linkedFileData.source_output_file_path}`
|
||||
)
|
||||
err.statusCode = response.statusCode
|
||||
return callback(err)
|
||||
@@ -158,9 +156,7 @@ module.exports = ProjectOutputFileAgent = {
|
||||
) // Created
|
||||
} else {
|
||||
err = new OutputFileFetchFailedError(
|
||||
`Output file fetch failed: ${linkedFileData.build_id}, ${
|
||||
linkedFileData.source_output_file_path
|
||||
}`
|
||||
`Output file fetch failed: ${linkedFileData.build_id}, ${linkedFileData.source_output_file_path}`
|
||||
)
|
||||
err.statusCode = response.statusCode
|
||||
return callback(err)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-cond-assign,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -751,8 +751,7 @@ const ProjectController = {
|
||||
} else if (
|
||||
Settings.wsUrlV2 &&
|
||||
Settings.wsUrlV2Percentage > 0 &&
|
||||
(ObjectId(projectId).getTimestamp() / 1000) %
|
||||
100 <
|
||||
(ObjectId(projectId).getTimestamp() / 1000) % 100 <
|
||||
Settings.wsUrlV2Percentage
|
||||
) {
|
||||
wsUrl = Settings.wsUrlV2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-path-concat,
|
||||
*/
|
||||
|
||||
@@ -226,8 +226,8 @@ async function deleteProject(projectId, options = {}) {
|
||||
deletedProjectLastUpdatedAt: project.lastUpdated
|
||||
}
|
||||
|
||||
Object.keys(deleterData).forEach(
|
||||
key => (deleterData[key] === undefined ? delete deleterData[key] : '')
|
||||
Object.keys(deleterData).forEach(key =>
|
||||
deleterData[key] === undefined ? delete deleterData[key] : ''
|
||||
)
|
||||
|
||||
await DeletedProject.updateOne(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -198,11 +198,7 @@ const ProjectLocator = {
|
||||
if (!found) {
|
||||
cb(
|
||||
new Error(
|
||||
`not found project: ${
|
||||
project._id
|
||||
} search path: ${needlePath}, folder ${
|
||||
foldersList[level]
|
||||
} could not be found`
|
||||
`not found project: ${project._id} search path: ${needlePath}, folder ${foldersList[level]} could not be found`
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -242,9 +238,7 @@ const ProjectLocator = {
|
||||
} else {
|
||||
cb(
|
||||
new Error(
|
||||
`not found project: ${
|
||||
project._id
|
||||
} search path: ${needlePath}, entity ${entityName} could not be found`
|
||||
`not found project: ${project._id} search path: ${needlePath}, entity ${entityName} could not be found`
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
no-useless-escape,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
@@ -87,9 +87,7 @@ const ProjectTokenGenerator = {
|
||||
if (response.statusCode !== 200) {
|
||||
return cb(
|
||||
new Error(
|
||||
`non-200 response from v1 read-token-exists api: ${
|
||||
response.statusCode
|
||||
}`
|
||||
`non-200 response from v1 read-token-exists api: ${response.statusCode}`
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
no-unused-vars,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
@@ -204,9 +204,7 @@ module.exports = ReferencesHandler = {
|
||||
return callback(null, data)
|
||||
} else {
|
||||
err = new Error(
|
||||
`references api responded with non-success code: ${
|
||||
res.statusCode
|
||||
}`
|
||||
`references api responded with non-success code: ${res.statusCode}`
|
||||
)
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-path-concat,
|
||||
no-unused-vars,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
standard/no-callback-literal,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
node/no-deprecated-api,
|
||||
standard/no-callback-literal,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-return-assign,
|
||||
no-unused-vars,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-return-assign,
|
||||
no-unused-vars,
|
||||
@@ -98,9 +98,7 @@ module.exports = {
|
||||
if (plan == null) {
|
||||
return cb(
|
||||
new Error(
|
||||
`No plan found for planCode '${
|
||||
personalSubscription.planCode
|
||||
}'`
|
||||
`No plan found for planCode '${personalSubscription.planCode}'`
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -190,9 +190,7 @@ var createInvite = function(subscription, email, inviter, callback) {
|
||||
const opts = {
|
||||
to: email,
|
||||
inviter,
|
||||
acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${
|
||||
invite.token
|
||||
}/`,
|
||||
acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${invite.token}/`,
|
||||
appName: settings.appName
|
||||
}
|
||||
EmailHandler.sendEmail('verifyEmailToJoinTeam', opts, error => {
|
||||
@@ -273,9 +271,7 @@ var checkIfInviteIsPossible = function(subscription, email, callback) {
|
||||
var getInviterName = function(inviter) {
|
||||
let inviterName
|
||||
if (inviter.first_name && inviter.last_name) {
|
||||
inviterName = `${inviter.first_name} ${inviter.last_name} (${
|
||||
inviter.email
|
||||
})`
|
||||
inviterName = `${inviter.first_name} ${inviter.last_name} (${inviter.email})`
|
||||
} else {
|
||||
inviterName = inviter.email
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
|
||||
@@ -41,9 +41,7 @@ const TemplatesManager = {
|
||||
_callback
|
||||
) {
|
||||
const callback = _.once(_callback)
|
||||
const zipUrl = `${
|
||||
settings.apis.v1.url
|
||||
}/api/v1/sharelatex/templates/${templateVersionId}`
|
||||
const zipUrl = `${settings.apis.v1.url}/api/v1/sharelatex/templates/${templateVersionId}`
|
||||
const zipReq = request(zipUrl, {
|
||||
auth: {
|
||||
user: settings.apis.v1.user,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-return-assign,
|
||||
*/
|
||||
|
||||
@@ -132,9 +132,7 @@ async function _sendLinkedEmail(userId, providerName, institutionEmail) {
|
||||
const user = await UserGetter.promises.getUser(userId, { email: 1 })
|
||||
const emailOptions = {
|
||||
to: user.email,
|
||||
actionDescribed: `an Institutional SSO account at ${providerName} was linked to your account ${
|
||||
user.email
|
||||
}`,
|
||||
actionDescribed: `an Institutional SSO account at ${providerName} was linked to your account ${user.email}`,
|
||||
action: 'institutional SSO account linked',
|
||||
message: [
|
||||
`<span style="display:inline-block;padding: 0 20px;width:100%;">Linked: <br/><b>${institutionEmail}</b></span>`
|
||||
|
||||
@@ -23,9 +23,7 @@ const { expressify } = require('../../util/promises')
|
||||
async function _sendSecurityAlertClearedSessions(user) {
|
||||
const emailOptions = {
|
||||
to: user.email,
|
||||
actionDescribed: `active sessions were cleared on your account ${
|
||||
user.email
|
||||
}`,
|
||||
actionDescribed: `active sessions were cleared on your account ${user.email}`,
|
||||
action: 'active sessions cleared'
|
||||
}
|
||||
try {
|
||||
@@ -42,9 +40,7 @@ async function _sendSecurityAlertClearedSessions(user) {
|
||||
function _sendSecurityAlertPasswordChanged(user) {
|
||||
const emailOptions = {
|
||||
to: user.email,
|
||||
actionDescribed: `your password has been changed on your account ${
|
||||
user.email
|
||||
}`,
|
||||
actionDescribed: `your password has been changed on your account ${user.email}`,
|
||||
action: 'password changed'
|
||||
}
|
||||
EmailHandler.sendEmail('securityAlert', emailOptions, error => {
|
||||
|
||||
@@ -36,9 +36,7 @@ function sendConfirmationEmail(userId, email, emailTemplate, callback) {
|
||||
}
|
||||
const emailOptions = {
|
||||
to: email,
|
||||
confirmEmailUrl: `${
|
||||
settings.siteUrl
|
||||
}/user/emails/confirm?token=${token}`,
|
||||
confirmEmailUrl: `${settings.siteUrl}/user/emails/confirm?token=${token}`,
|
||||
sendingUser_id: userId
|
||||
}
|
||||
EmailHandler.sendEmail(emailTemplate, emailOptions, callback)
|
||||
|
||||
@@ -14,9 +14,7 @@ const { expressify } = require('../../util/promises')
|
||||
async function _sendSecurityAlertEmail(user, email) {
|
||||
const emailOptions = {
|
||||
to: user.email,
|
||||
actionDescribed: `a secondary email address has been added to your account ${
|
||||
user.email
|
||||
}`,
|
||||
actionDescribed: `a secondary email address has been added to your account ${user.email}`,
|
||||
message: [
|
||||
`<span style="display:inline-block;padding: 0 20px;width:100%;">Added: <br/><b>${email}</b></span>`
|
||||
],
|
||||
|
||||
@@ -129,9 +129,7 @@ const UserRegistrationHandler = {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
const setNewPasswordUrl = `${
|
||||
settings.siteUrl
|
||||
}/user/activate?token=${token}&user_id=${user._id}`
|
||||
const setNewPasswordUrl = `${settings.siteUrl}/user/activate?token=${token}&user_id=${user._id}`
|
||||
|
||||
EmailHandler.sendEmail(
|
||||
'registered',
|
||||
|
||||
@@ -93,36 +93,37 @@ UserSessionsManager = {
|
||||
return callback(null, [])
|
||||
}
|
||||
|
||||
Async.mapSeries(sessionKeys, (k, cb) => rclient.get(k, cb), function(
|
||||
err,
|
||||
sessions
|
||||
) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error getting all sessions for user from redis', {
|
||||
user_id: user._id
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
const result = []
|
||||
for (let session of Array.from(sessions)) {
|
||||
if (!session) {
|
||||
continue
|
||||
}
|
||||
session = JSON.parse(session)
|
||||
let sessionUser = session.passport && session.passport.user
|
||||
if (!sessionUser) {
|
||||
sessionUser = session.user
|
||||
Async.mapSeries(
|
||||
sessionKeys,
|
||||
(k, cb) => rclient.get(k, cb),
|
||||
function(err, sessions) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error getting all sessions for user from redis', {
|
||||
user_id: user._id
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
result.push({
|
||||
ip_address: sessionUser.ip_address,
|
||||
session_created: sessionUser.session_created
|
||||
})
|
||||
}
|
||||
const result = []
|
||||
for (let session of Array.from(sessions)) {
|
||||
if (!session) {
|
||||
continue
|
||||
}
|
||||
session = JSON.parse(session)
|
||||
let sessionUser = session.passport && session.passport.user
|
||||
if (!sessionUser) {
|
||||
sessionUser = session.user
|
||||
}
|
||||
|
||||
callback(null, result)
|
||||
})
|
||||
result.push({
|
||||
ip_address: sessionUser.ip_address,
|
||||
session_created: sessionUser.session_created
|
||||
})
|
||||
}
|
||||
|
||||
callback(null, result)
|
||||
}
|
||||
)
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
standard/no-callback-literal,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -86,17 +86,13 @@ const V1Api = {
|
||||
return callback(error)
|
||||
} else if (response.statusCode === 404) {
|
||||
error = new Errors.NotFoundError(
|
||||
`overleaf v1 returned non-success code: ${response.statusCode} ${
|
||||
options.method
|
||||
} ${options.uri}`
|
||||
`overleaf v1 returned non-success code: ${response.statusCode} ${options.method} ${options.uri}`
|
||||
)
|
||||
error.statusCode = response.statusCode
|
||||
return callback(error)
|
||||
} else {
|
||||
error = new Error(
|
||||
`overleaf v1 returned non-success code: ${response.statusCode} ${
|
||||
options.method
|
||||
} ${options.uri}`
|
||||
`overleaf v1 returned non-success code: ${response.statusCode} ${options.method} ${options.uri}`
|
||||
)
|
||||
error.statusCode = response.statusCode
|
||||
return callback(error)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable
|
||||
camelcase,
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
@@ -93,9 +93,7 @@ module.exports = V1Handler = {
|
||||
return callback(null, true)
|
||||
} else {
|
||||
err = new Error(
|
||||
`Unexpected status from v1 password reset api: ${
|
||||
response.statusCode
|
||||
}`
|
||||
`Unexpected status from v1 password reset api: ${response.statusCode}`
|
||||
)
|
||||
return callback(err, false)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
max-len,
|
||||
no-return-assign,
|
||||
no-unused-vars,
|
||||
standard/no-callback-literal,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
node/handle-callback-err,
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
|
||||
@@ -66,7 +66,10 @@ const App = angular
|
||||
processEscapes: true,
|
||||
// Dollar delimiters are added by the mathjax directive
|
||||
inlineMath: [['\\(', '\\)']],
|
||||
displayMath: [['$$', '$$'], ['\\[', '\\]']]
|
||||
displayMath: [
|
||||
['$$', '$$'],
|
||||
['\\[', '\\]']
|
||||
]
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
@@ -80,9 +80,7 @@ App.directive('complexPassword', () => ({
|
||||
}
|
||||
if (opts.length.min != null && modelValue.length < opts.length.min) {
|
||||
isValid = false
|
||||
scope.complexPasswordErrorMessage = `Password too short, minimum ${
|
||||
opts.length.min
|
||||
}`
|
||||
scope.complexPasswordErrorMessage = `Password too short, minimum ${opts.length.min}`
|
||||
}
|
||||
ngModelCtrl.$setValidity('complexPassword', isValid)
|
||||
return modelValue
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
*/
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
@@ -14,7 +14,7 @@ export default App.directive('equals', () => ({
|
||||
link(scope, elem, attrs, ctrl) {
|
||||
const firstField = `#${attrs.equals}`
|
||||
return elem.add(firstField).on('keyup', () =>
|
||||
scope.$apply(function() {
|
||||
scope.$apply(function () {
|
||||
const equal = elem.val() === $(firstField).val()
|
||||
return ctrl.$setValidity('areEqual', equal)
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
*/
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
@@ -12,7 +12,7 @@ import App from '../base'
|
||||
export default App.directive('expandableTextArea', () => ({
|
||||
restrict: 'A',
|
||||
link(scope, el) {
|
||||
const resetHeight = function() {
|
||||
const resetHeight = function () {
|
||||
const curHeight = el.outerHeight()
|
||||
const fitHeight = el.prop('scrollHeight')
|
||||
// clear height if text area is empty
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
*/
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
@@ -42,12 +42,12 @@ export default App.directive('fineUpload', $timeout => ({
|
||||
validation.sizeLimit = scope.sizeLimit
|
||||
}
|
||||
const maxConnections = scope.maxConnections || 1
|
||||
const onComplete = scope.onCompleteCallback || function() {}
|
||||
const onUpload = scope.onUploadCallback || function() {}
|
||||
const onError = scope.onErrorCallback || function() {}
|
||||
const onValidateBatch = scope.onValidateBatch || function() {}
|
||||
const onSubmit = scope.onSubmitCallback || function() {}
|
||||
const onCancel = scope.onCancelCallback || function() {}
|
||||
const onComplete = scope.onCompleteCallback || function () {}
|
||||
const onUpload = scope.onUploadCallback || function () {}
|
||||
const onError = scope.onErrorCallback || function () {}
|
||||
const onValidateBatch = scope.onValidateBatch || function () {}
|
||||
const onSubmit = scope.onSubmitCallback || function () {}
|
||||
const onCancel = scope.onCancelCallback || function () {}
|
||||
if (scope.autoUpload == null) {
|
||||
autoUpload = true
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
*/
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
@@ -13,7 +13,7 @@ import App from '../base'
|
||||
export default App.directive('maxHeight', () => ({
|
||||
restrict: 'A',
|
||||
link(scope, element, attrs) {
|
||||
return scope.$watch(attrs.maxHeight, function(value) {
|
||||
return scope.$watch(attrs.maxHeight, function (value) {
|
||||
if (value != null) {
|
||||
return element.css({ 'max-height': value })
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
*/
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
@@ -10,7 +10,7 @@
|
||||
import App from '../base'
|
||||
|
||||
export default App.directive('onEnter', () => (scope, element, attrs) =>
|
||||
element.bind('keydown keypress', function(event) {
|
||||
element.bind('keydown keypress', function (event) {
|
||||
if (event.which === 13) {
|
||||
scope.$apply(() => scope.$eval(attrs.onEnter, { event }))
|
||||
return event.preventDefault()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable
|
||||
*/
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
@@ -12,7 +12,7 @@ import App from '../base'
|
||||
export default App.directive('rightClick', () => ({
|
||||
restrict: 'A',
|
||||
link(scope, element, attrs) {
|
||||
return element.bind('contextmenu', function(e) {
|
||||
return element.bind('contextmenu', function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return scope.$eval(attrs.rightClick)
|
||||
|
||||
@@ -14,15 +14,16 @@ export default App.directive('videoPlayState', $parse => ({
|
||||
restrict: 'A',
|
||||
link(scope, element, attrs) {
|
||||
const videoDOMEl = element[0]
|
||||
return scope.$watch(() => $parse(attrs.videoPlayState)(scope), function(
|
||||
shouldPlay
|
||||
) {
|
||||
if (shouldPlay) {
|
||||
videoDOMEl.currentTime = 0
|
||||
return videoDOMEl.play()
|
||||
} else {
|
||||
return videoDOMEl.pause()
|
||||
return scope.$watch(
|
||||
() => $parse(attrs.videoPlayState)(scope),
|
||||
function(shouldPlay) {
|
||||
if (shouldPlay) {
|
||||
videoDOMEl.currentTime = 0
|
||||
return videoDOMEl.play()
|
||||
} else {
|
||||
return videoDOMEl.pause()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -20,23 +20,20 @@ function MessageContent({ content }) {
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
// adds attributes to all the links generated by <Linkify/>, required due to https://github.com/tasti/react-linkify/issues/99
|
||||
for (let a of root.current.getElementsByTagName('a')) {
|
||||
a.setAttribute('target', '_blank')
|
||||
a.setAttribute('rel', 'noreferrer noopener')
|
||||
}
|
||||
useEffect(() => {
|
||||
// adds attributes to all the links generated by <Linkify/>, required due to https://github.com/tasti/react-linkify/issues/99
|
||||
for (let a of root.current.getElementsByTagName('a')) {
|
||||
a.setAttribute('target', '_blank')
|
||||
a.setAttribute('rel', 'noreferrer noopener')
|
||||
}
|
||||
|
||||
// MathJax typesetting
|
||||
const MJHub = window.MathJax.Hub
|
||||
const timeoutHandler = setTimeout(() => {
|
||||
MJHub.Queue(['Typeset', MJHub, root.current])
|
||||
}, 0)
|
||||
return () => clearTimeout(timeoutHandler)
|
||||
},
|
||||
[content]
|
||||
)
|
||||
// MathJax typesetting
|
||||
const MJHub = window.MathJax.Hub
|
||||
const timeoutHandler = setTimeout(() => {
|
||||
MJHub.Queue(['Typeset', MJHub, root.current])
|
||||
}, 0)
|
||||
return () => clearTimeout(timeoutHandler)
|
||||
}, [content])
|
||||
|
||||
return (
|
||||
<p ref={root}>
|
||||
|
||||
@@ -13,19 +13,16 @@ export function useChatStore() {
|
||||
const [loading, setLoading] = useState(chatStoreRef.current.loading)
|
||||
const [messages, setMessages] = useState(chatStoreRef.current.messages)
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
const chatStore = chatStoreRef.current
|
||||
function handleStoreUpdated() {
|
||||
setAtEnd(chatStore.atEnd)
|
||||
setLoading(chatStore.loading)
|
||||
setMessages(chatStore.messages)
|
||||
}
|
||||
chatStore.on('updated', handleStoreUpdated)
|
||||
return () => chatStore.destroy()
|
||||
},
|
||||
[chatStoreRef]
|
||||
)
|
||||
useEffect(() => {
|
||||
const chatStore = chatStoreRef.current
|
||||
function handleStoreUpdated() {
|
||||
setAtEnd(chatStore.atEnd)
|
||||
setLoading(chatStore.loading)
|
||||
setMessages(chatStore.messages)
|
||||
}
|
||||
chatStore.on('updated', handleStoreUpdated)
|
||||
return () => chatStore.destroy()
|
||||
}, [chatStoreRef])
|
||||
|
||||
return {
|
||||
userId: user.id,
|
||||
|
||||
@@ -20,16 +20,13 @@ function FileTreeItemInner({ id, name, isSelected, icons }) {
|
||||
|
||||
const itemRef = createRef()
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (isSelected && itemRef.current) {
|
||||
scrollIntoViewIfNeeded(itemRef.current, {
|
||||
scrollMode: 'if-needed'
|
||||
})
|
||||
}
|
||||
},
|
||||
[isSelected, itemRef]
|
||||
)
|
||||
useEffect(() => {
|
||||
if (isSelected && itemRef.current) {
|
||||
scrollIntoViewIfNeeded(itemRef.current, {
|
||||
scrollMode: 'if-needed'
|
||||
})
|
||||
}
|
||||
}, [isSelected, itemRef])
|
||||
|
||||
function handleContextMenu(ev) {
|
||||
ev.preventDefault()
|
||||
|
||||
@@ -28,12 +28,10 @@ function FileTreeRoot({
|
||||
}) {
|
||||
const isReady = projectId && rootFolder
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (isReady) onInit()
|
||||
},
|
||||
[isReady]
|
||||
)
|
||||
useEffect(() => {
|
||||
if (isReady) onInit()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isReady])
|
||||
if (!isReady) return null
|
||||
|
||||
return (
|
||||
|
||||
@@ -61,12 +61,9 @@ export function useDraggable(draggedEntityId) {
|
||||
|
||||
// remove the automatic preview as we're using a custom preview via
|
||||
// FileTreeDraggablePreviewLayer
|
||||
useEffect(
|
||||
() => {
|
||||
preview(getEmptyImage())
|
||||
},
|
||||
[preview]
|
||||
)
|
||||
useEffect(() => {
|
||||
preview(getEmptyImage())
|
||||
}, [preview])
|
||||
|
||||
return {
|
||||
dragRef,
|
||||
|
||||
@@ -76,15 +76,13 @@ export function FileTreeSelectableProvider({
|
||||
const { fileTreeData } = useFileTreeMutable()
|
||||
|
||||
// calls `onSelect` on entities selection
|
||||
useEffect(
|
||||
() => {
|
||||
const selectedEntities = Array.from(selectedEntityIds).map(id =>
|
||||
findInTree(fileTreeData, id)
|
||||
)
|
||||
onSelect(selectedEntities)
|
||||
},
|
||||
[fileTreeData, selectedEntityIds]
|
||||
)
|
||||
useEffect(() => {
|
||||
const selectedEntities = Array.from(selectedEntityIds).map(id =>
|
||||
findInTree(fileTreeData, id)
|
||||
)
|
||||
onSelect(selectedEntities)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [fileTreeData, selectedEntityIds])
|
||||
|
||||
useEffect(() => {
|
||||
// listen for `editor.openDoc` and selected that doc
|
||||
|
||||
@@ -55,7 +55,9 @@ App.controller('ReactFileTreeController', function(
|
||||
// multi-selected entity" so here we pass a count of 0
|
||||
$scope.$emit('entities:multiSelected', { count: 0 })
|
||||
} else if (selectedEntities.length > 1) {
|
||||
$scope.$emit('entities:multiSelected', { count: selectedEntities.length })
|
||||
$scope.$emit('entities:multiSelected', {
|
||||
count: selectedEntities.length
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,41 +10,35 @@ export function useFileTreeAngularListener() {
|
||||
finishCreatingLinkedFile
|
||||
} = useFileTreeActionable()
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
function handleDispatchCreateDoc(ev) {
|
||||
const { ...doc } = ev.detail
|
||||
finishCreatingDoc(doc)
|
||||
}
|
||||
window.addEventListener(
|
||||
useEffect(() => {
|
||||
function handleDispatchCreateDoc(ev) {
|
||||
const { ...doc } = ev.detail
|
||||
finishCreatingDoc(doc)
|
||||
}
|
||||
window.addEventListener(
|
||||
'FileTreeReactBridge.createDoc',
|
||||
handleDispatchCreateDoc
|
||||
)
|
||||
return () =>
|
||||
window.removeEventListener(
|
||||
'FileTreeReactBridge.createDoc',
|
||||
handleDispatchCreateDoc
|
||||
)
|
||||
return () =>
|
||||
window.removeEventListener(
|
||||
'FileTreeReactBridge.createDoc',
|
||||
handleDispatchCreateDoc
|
||||
)
|
||||
},
|
||||
[finishCreatingDoc]
|
||||
)
|
||||
}, [finishCreatingDoc])
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
function handleDispatchCreateLinkedFile(ev) {
|
||||
const { ...file } = ev.detail
|
||||
finishCreatingLinkedFile(file)
|
||||
}
|
||||
window.addEventListener(
|
||||
useEffect(() => {
|
||||
function handleDispatchCreateLinkedFile(ev) {
|
||||
const { ...file } = ev.detail
|
||||
finishCreatingLinkedFile(file)
|
||||
}
|
||||
window.addEventListener(
|
||||
'FileTreeReactBridge.createLinkedFile',
|
||||
handleDispatchCreateLinkedFile
|
||||
)
|
||||
return () =>
|
||||
window.removeEventListener(
|
||||
'FileTreeReactBridge.createLinkedFile',
|
||||
handleDispatchCreateLinkedFile
|
||||
)
|
||||
return () =>
|
||||
window.removeEventListener(
|
||||
'FileTreeReactBridge.createLinkedFile',
|
||||
handleDispatchCreateLinkedFile
|
||||
)
|
||||
},
|
||||
[finishCreatingLinkedFile]
|
||||
)
|
||||
}, [finishCreatingLinkedFile])
|
||||
}
|
||||
|
||||
@@ -15,87 +15,67 @@ export function useFileTreeSocketListener() {
|
||||
const { unselect } = useFileTreeSelectable()
|
||||
const socket = window._ide && window._ide.socket
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
function handleDispatchRename(entityId, name) {
|
||||
dispatchRename(entityId, name)
|
||||
}
|
||||
if (socket) socket.on('reciveEntityRename', handleDispatchRename)
|
||||
return () => {
|
||||
if (socket)
|
||||
socket.removeListener('reciveEntityRename', handleDispatchRename)
|
||||
}
|
||||
},
|
||||
[socket, dispatchRename]
|
||||
)
|
||||
useEffect(() => {
|
||||
function handleDispatchRename(entityId, name) {
|
||||
dispatchRename(entityId, name)
|
||||
}
|
||||
if (socket) socket.on('reciveEntityRename', handleDispatchRename)
|
||||
return () => {
|
||||
if (socket)
|
||||
socket.removeListener('reciveEntityRename', handleDispatchRename)
|
||||
}
|
||||
}, [socket, dispatchRename])
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
function handleDispatchDelete(entityId) {
|
||||
unselect(entityId)
|
||||
dispatchDelete(entityId)
|
||||
}
|
||||
if (socket) socket.on('removeEntity', handleDispatchDelete)
|
||||
return () => {
|
||||
if (socket) socket.removeListener('removeEntity', handleDispatchDelete)
|
||||
}
|
||||
},
|
||||
[socket, unselect, dispatchDelete]
|
||||
)
|
||||
useEffect(() => {
|
||||
function handleDispatchDelete(entityId) {
|
||||
unselect(entityId)
|
||||
dispatchDelete(entityId)
|
||||
}
|
||||
if (socket) socket.on('removeEntity', handleDispatchDelete)
|
||||
return () => {
|
||||
if (socket) socket.removeListener('removeEntity', handleDispatchDelete)
|
||||
}
|
||||
}, [socket, unselect, dispatchDelete])
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
function handleDispatchMove(entityId, toFolderId) {
|
||||
dispatchMove(entityId, toFolderId)
|
||||
}
|
||||
if (socket) socket.on('reciveEntityMove', handleDispatchMove)
|
||||
return () => {
|
||||
if (socket)
|
||||
socket.removeListener('reciveEntityMove', handleDispatchMove)
|
||||
}
|
||||
},
|
||||
[socket, dispatchMove]
|
||||
)
|
||||
useEffect(() => {
|
||||
function handleDispatchMove(entityId, toFolderId) {
|
||||
dispatchMove(entityId, toFolderId)
|
||||
}
|
||||
if (socket) socket.on('reciveEntityMove', handleDispatchMove)
|
||||
return () => {
|
||||
if (socket) socket.removeListener('reciveEntityMove', handleDispatchMove)
|
||||
}
|
||||
}, [socket, dispatchMove])
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
function handleDispatchCreateFolder(parentFolderId, folder) {
|
||||
dispatchCreateFolder(parentFolderId, folder)
|
||||
}
|
||||
if (socket) socket.on('reciveNewFolder', handleDispatchCreateFolder)
|
||||
return () => {
|
||||
if (socket)
|
||||
socket.removeListener('reciveNewFolder', handleDispatchCreateFolder)
|
||||
}
|
||||
},
|
||||
[socket, dispatchCreateFolder]
|
||||
)
|
||||
useEffect(() => {
|
||||
function handleDispatchCreateFolder(parentFolderId, folder) {
|
||||
dispatchCreateFolder(parentFolderId, folder)
|
||||
}
|
||||
if (socket) socket.on('reciveNewFolder', handleDispatchCreateFolder)
|
||||
return () => {
|
||||
if (socket)
|
||||
socket.removeListener('reciveNewFolder', handleDispatchCreateFolder)
|
||||
}
|
||||
}, [socket, dispatchCreateFolder])
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
function handleDispatchCreateDoc(parentFolderId, doc) {
|
||||
dispatchCreateDoc(parentFolderId, doc)
|
||||
}
|
||||
if (socket) socket.on('reciveNewDoc', handleDispatchCreateDoc)
|
||||
return () => {
|
||||
if (socket)
|
||||
socket.removeListener('reciveNewDoc', handleDispatchCreateDoc)
|
||||
}
|
||||
},
|
||||
[socket, dispatchCreateDoc]
|
||||
)
|
||||
useEffect(() => {
|
||||
function handleDispatchCreateDoc(parentFolderId, doc) {
|
||||
dispatchCreateDoc(parentFolderId, doc)
|
||||
}
|
||||
if (socket) socket.on('reciveNewDoc', handleDispatchCreateDoc)
|
||||
return () => {
|
||||
if (socket) socket.removeListener('reciveNewDoc', handleDispatchCreateDoc)
|
||||
}
|
||||
}, [socket, dispatchCreateDoc])
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
function handleDispatchCreateFile(parentFolderId, file) {
|
||||
dispatchCreateFile(parentFolderId, file)
|
||||
}
|
||||
if (socket) socket.on('reciveNewFile', handleDispatchCreateFile)
|
||||
return () => {
|
||||
if (socket)
|
||||
socket.removeListener('reciveNewFile', handleDispatchCreateFile)
|
||||
}
|
||||
},
|
||||
[socket, dispatchCreateFile]
|
||||
)
|
||||
useEffect(() => {
|
||||
function handleDispatchCreateFile(parentFolderId, file) {
|
||||
dispatchCreateFile(parentFolderId, file)
|
||||
}
|
||||
if (socket) socket.on('reciveNewFile', handleDispatchCreateFile)
|
||||
return () => {
|
||||
if (socket)
|
||||
socket.removeListener('reciveNewFile', handleDispatchCreateFile)
|
||||
}
|
||||
}, [socket, dispatchCreateFile])
|
||||
}
|
||||
|
||||
@@ -48,20 +48,17 @@ function OutlineItem({ outlineItem, jumpToLine, highlightedLine }) {
|
||||
jumpToLine(outlineItem.line, true)
|
||||
}
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
const wasHighlighted = isHighlightedRef.current
|
||||
isHighlightedRef.current = isHighlighted
|
||||
useEffect(() => {
|
||||
const wasHighlighted = isHighlightedRef.current
|
||||
isHighlightedRef.current = isHighlighted
|
||||
|
||||
if (!wasHighlighted && isHighlighted) {
|
||||
scrollIntoViewIfNeeded(titleElementRef.current, {
|
||||
scrollMode: 'if-needed',
|
||||
block: 'center'
|
||||
})
|
||||
}
|
||||
},
|
||||
[isHighlighted, titleElementRef, isHighlightedRef]
|
||||
)
|
||||
if (!wasHighlighted && isHighlighted) {
|
||||
scrollIntoViewIfNeeded(titleElementRef.current, {
|
||||
scrollMode: 'if-needed',
|
||||
block: 'center'
|
||||
})
|
||||
}
|
||||
}, [isHighlighted, titleElementRef, isHighlightedRef])
|
||||
|
||||
// don't set the aria-expanded attribute when there are no children
|
||||
const ariaExpandedValue = outlineItem.children ? expanded : undefined
|
||||
|
||||
@@ -28,12 +28,10 @@ function OutlinePane({
|
||||
})
|
||||
const isOpen = isTexFile && expanded
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
onToggle(isOpen)
|
||||
},
|
||||
[isOpen]
|
||||
)
|
||||
useEffect(() => {
|
||||
onToggle(isOpen)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isOpen])
|
||||
|
||||
const headerClasses = classNames('outline-pane', {
|
||||
'outline-pane-disabled': !isTexFile
|
||||
|
||||
@@ -31,15 +31,15 @@ function PreviewLogsPane({
|
||||
<PreviewError key={index} name={name} />
|
||||
))
|
||||
|
||||
const validationIssuesUI = Object.keys(validationIssues).map(
|
||||
(name, index) => (
|
||||
<PreviewValidationIssue
|
||||
key={index}
|
||||
name={name}
|
||||
details={validationIssues[name]}
|
||||
/>
|
||||
)
|
||||
)
|
||||
const validationIssuesUI = Object.keys(
|
||||
validationIssues
|
||||
).map((name, index) => (
|
||||
<PreviewValidationIssue
|
||||
key={index}
|
||||
name={name}
|
||||
details={validationIssues[name]}
|
||||
/>
|
||||
))
|
||||
|
||||
const logEntriesUI = [
|
||||
...compilerErrors,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user