diff --git a/services/web/.gitignore b/services/web/.gitignore index 26e9f30502..b8a57d9cd2 100644 --- a/services/web/.gitignore +++ b/services/web/.gitignore @@ -67,6 +67,7 @@ public/js/utils/ public/stylesheets/style.css public/stylesheets/ol-style.css +public/stylesheets/ol-light-style.css public/stylesheets/*.map public/brand/ public/minjs/ diff --git a/services/web/Gruntfile.coffee b/services/web/Gruntfile.coffee index 4104352e3d..5e71b83f7a 100644 --- a/services/web/Gruntfile.coffee +++ b/services/web/Gruntfile.coffee @@ -35,6 +35,8 @@ module.exports = (grunt) -> command:"node_modules/clean-css/bin/cleancss --s0 --source-map -o public/stylesheets/style.css public/stylesheets/style.css" cssmin_ol: command:"node_modules/clean-css/bin/cleancss --s0 --source-map -o public/stylesheets/ol-style.css public/stylesheets/ol-style.css" + cssmin_ol_light: + command:"node_modules/clean-css/bin/cleancss --s0 --source-map -o public/stylesheets/ol-light-style.css public/stylesheets/ol-light-style.css" forever: app: @@ -154,6 +156,7 @@ module.exports = (grunt) -> sourceMapBasepath: "public/stylesheets" globalVars: 'is-overleaf': false + 'is-overleaf-light': false 'show-rich-text': Settings.showRichText files: "public/stylesheets/style.css": "public/stylesheets/style.less" @@ -164,10 +167,23 @@ module.exports = (grunt) -> sourceMapBasepath: "public/stylesheets" globalVars: 'is-overleaf': true + 'is-overleaf-light': false 'show-rich-text': Settings.showRichText files: "public/stylesheets/ol-style.css": "public/stylesheets/ol-style.less" + 'ol-light': + options: + sourceMap: true + sourceMapFilename: "public/stylesheets/ol-light-style.css.map" + sourceMapBasepath: "public/stylesheets" + globalVars: + 'is-overleaf': true + 'is-overleaf-light': true + 'show-rich-text': Settings.showRichText + files: + "public/stylesheets/ol-light-style.css": "public/stylesheets/ol-light-style.less" + postcss: options: map: @@ -178,7 +194,7 @@ module.exports = (grunt) -> require('autoprefixer')({browsers: [ 'last 2 versions', 'ie >= 10' ]}) ] dist: - src: [ "public/stylesheets/style.css", "public/stylesheets/ol-style.css" ] + src: [ "public/stylesheets/style.css", "public/stylesheets/ol-style.css", "public/stylesheets/ol-light-style.css" ] env: run: @@ -413,7 +429,7 @@ module.exports = (grunt) -> grunt.registerTask 'compile:server', 'Compile the server side coffee script', ['clean:app', 'coffee:app', 'coffee:app_dir', 'compile:modules:server'] grunt.registerTask 'compile:client', 'Compile the client side coffee script', ['coffee:client', 'coffee:sharejs', 'wrap_sharejs', "compile:modules:client", 'compile:modules:inject_clientside_includes'] grunt.registerTask 'compile:css', 'Compile the less files to css', ['less', 'postcss:dist'] - grunt.registerTask 'compile:minify', 'Concat and minify the client side js and css', ['requirejs', "file_append", "exec:cssmin_sl", "exec:cssmin_ol"] + grunt.registerTask 'compile:minify', 'Concat and minify the client side js and css', ['requirejs', "file_append", "exec:cssmin_sl", "exec:cssmin_ol", "exec:cssmin_ol_light"] grunt.registerTask 'compile:unit_tests', 'Compile the unit tests', ['clean:unit_tests', 'coffee:unit_tests'] grunt.registerTask 'compile:acceptance_tests', 'Compile the acceptance tests', ['clean:acceptance_tests', 'coffee:acceptance_tests'] grunt.registerTask 'compile:smoke_tests', 'Compile the smoke tests', ['coffee:smoke_tests'] diff --git a/services/web/Makefile b/services/web/Makefile index 26534b8612..169031be07 100644 --- a/services/web/Makefile +++ b/services/web/Makefile @@ -24,7 +24,7 @@ SHAREJS_COFFEE_FILES := \ public/coffee/ide/editor/sharejs/vendor/client/ace.coffee \ public/coffee/ide/editor/sharejs/vendor/client/cm.coffee LESS_FILES := $(shell find public/stylesheets -name '*.less') -CSS_FILES := public/stylesheets/style.css public/stylesheets/ol-style.css +CSS_FILES := public/stylesheets/style.css public/stylesheets/ol-style.css public/stylesheets/ol-light-style.css # The automatic variable $(@D) is the target directory name app.js: app.coffee diff --git a/services/web/app/coffee/Features/Email/EmailBuilder.coffee b/services/web/app/coffee/Features/Email/EmailBuilder.coffee index a33f02e695..e2e8311286 100644 --- a/services/web/app/coffee/Features/Email/EmailBuilder.coffee +++ b/services/web/app/coffee/Features/Email/EmailBuilder.coffee @@ -59,7 +59,7 @@ I'm sorry to see you cancelled your #{settings.appName} premium account. Would y """ secondaryMessage: () -> "Thank you in advance!" ctaText: () -> "Leave Feedback" - ctaURL: (opts) -> "https://sharelatex.typeform.com/to/f5lBiZ" + ctaURL: (opts) -> "https://docs.google.com/forms/d/e/1FAIpQLScqU6Je1r4Afz6ul6oY0RAfN7RabdWv_oL1u7Rj1YBmXS4fiQ/viewform?usp=sf_link" }) templates.passwordResetRequested = CTAEmailTemplate({ diff --git a/services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee b/services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee index 489995559c..79163ded48 100644 --- a/services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee +++ b/services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee @@ -5,6 +5,7 @@ rclient = RedisWrapper.client("health_check") settings = require("settings-sharelatex") logger = require "logger-sharelatex" domain = require "domain" +UserGetter = require("../User/UserGetter") module.exports = HealthCheckController = check: (req, res, next = (error) ->) -> @@ -37,6 +38,20 @@ module.exports = HealthCheckController = res.sendStatus 500 else res.sendStatus 200 + + checkMongo: (req, res, next)-> + logger.log "running mongo health check" + UserGetter.getUserEmail settings.smokeTest.userId, (err, email)-> + if err? + logger.err err:err, "mongo health check failed, error present" + return res.sendStatus 500 + else if !email? + logger.err err:err, "mongo health check failed, no emai present in find result" + return res.sendStatus 500 + else + logger.log email:email, "mongo health check passed" + res.sendStatus 200 + Reporter = (res) -> (runner) -> diff --git a/services/web/app/coffee/Features/Newsletter/NewsletterManager.coffee b/services/web/app/coffee/Features/Newsletter/NewsletterManager.coffee index dba4919496..5debc762b0 100644 --- a/services/web/app/coffee/Features/Newsletter/NewsletterManager.coffee +++ b/services/web/app/coffee/Features/Newsletter/NewsletterManager.coffee @@ -47,6 +47,10 @@ module.exports = logger.log {oldEmail, newEmail}, "unable to change email in newsletter, user has previously unsubscribed or new email already exist on list" return callback(err) + else if err? and err.message.indexOf("is already a list member") != -1 + logger.log {oldEmail, newEmail}, + "unable to change email in newsletter, new email is already on mailing list" + return callback() else if err? logger.err {err, oldEmail, newEmail}, "error changing email in newsletter" return callback(err) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index fc96c9c21b..039a193921 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -294,7 +294,7 @@ module.exports = ProjectController = project = results.project user = results.user subscription = results.subscription - + daysSinceLastUpdated = (new Date() - project.lastUpdated) / 86400000 logger.log project_id:project_id, daysSinceLastUpdated:daysSinceLastUpdated, "got db results for loading editor" @@ -330,7 +330,7 @@ module.exports = ProjectController = } userSettings: { mode : user.ace.mode - theme : user.ace.theme + editorTheme : user.ace.theme fontSize : user.ace.fontSize autoComplete: user.ace.autoComplete autoPairDelimiters: user.ace.autoPairDelimiters @@ -338,6 +338,7 @@ module.exports = ProjectController = syntaxValidation: user.ace.syntaxValidation fontFamily: user.ace.fontFamily lineHeight: user.ace.lineHeight + overallTheme: user.ace.overallTheme } trackChangesState: project.track_changes privilegeLevel: privilegeLevel @@ -346,7 +347,7 @@ module.exports = ProjectController = anonymousAccessToken: req._anonymousAccessToken isTokenMember: isTokenMember languages: Settings.languages - themes: THEME_LIST + editorThemes: THEME_LIST maxDocLength: Settings.max_doc_length useV2History: !!project.overleaf?.history?.display richTextEnabled: Features.hasFeature('rich-text') diff --git a/services/web/app/coffee/Features/User/UserController.coffee b/services/web/app/coffee/Features/User/UserController.coffee index 823919f999..a9c4e2a00d 100644 --- a/services/web/app/coffee/Features/User/UserController.coffee +++ b/services/web/app/coffee/Features/User/UserController.coffee @@ -68,8 +68,10 @@ module.exports = UserController = user.institution = req.body.institution.trim() if req.body.mode? user.ace.mode = req.body.mode - if req.body.theme? - user.ace.theme = req.body.theme + if req.body.editorTheme? + user.ace.theme = req.body.editorTheme + if req.body.overallTheme? + user.ace.overallTheme = req.body.overallTheme if req.body.fontSize? user.ace.fontSize = req.body.fontSize if req.body.autoComplete? diff --git a/services/web/app/coffee/infrastructure/ExpressLocals.coffee b/services/web/app/coffee/infrastructure/ExpressLocals.coffee index d4444b3542..0dbf56ff51 100644 --- a/services/web/app/coffee/infrastructure/ExpressLocals.coffee +++ b/services/web/app/coffee/infrastructure/ExpressLocals.coffee @@ -44,6 +44,7 @@ pathList = [ "#{jsPath}libraries.js" "/stylesheets/style.css" "/stylesheets/ol-style.css" + "/stylesheets/ol-light-style.css" ].concat(Modules.moduleAssetFiles(jsPath)) if !Settings.useMinifiedJs @@ -163,6 +164,14 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)-> return Url.resolve(staticFilesBase, hashedPath) return Url.resolve(staticFilesBase, path) + res.locals.buildCssFileNameForUser = (userSettings) -> + if userSettings?.overallTheme? and Settings.overleaf? + themeModifier = userSettings.overallTheme + return res.locals.buildCssFileName(themeModifier) + + res.locals.buildCssFileName = (themeModifier) -> + return "/" + Settings.brandPrefix + (if themeModifier then themeModifier else "") + "style.css" + res.locals.buildImgPath = (imgFile)-> path = Path.join("/img/", imgFile) return Url.resolve(staticFilesBase, path) @@ -334,6 +343,14 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)-> renderAnnouncements : !isOl next() + webRouter.use (req, res, next) -> + if Settings.overleaf? + res.locals.overallThemes = [ + { name: "Default", val: "", path: res.locals.buildCssPath(res.locals.buildCssFileName()) } + { name: "Light", val: "light-", path: res.locals.buildCssPath(res.locals.buildCssFileName("light-")) } + ] + next() + webRouter.use (req, res, next) -> res.locals.ExposedSettings = isOverleaf: Settings.overleaf? diff --git a/services/web/app/coffee/models/User.coffee b/services/web/app/coffee/models/User.coffee index 730b3668c6..95bedebbf4 100644 --- a/services/web/app/coffee/models/User.coffee +++ b/services/web/app/coffee/models/User.coffee @@ -27,6 +27,7 @@ UserSchema = new Schema ace : { mode : {type : String, default: 'none'} theme : {type : String, default: 'textmate'} + overallTheme : {type: String, default: "" } fontSize : {type : Number, default:'12'} autoComplete : {type : Boolean, default: true} autoPairDelimiters : {type : Boolean, default: true} diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee index b590e58f5d..b196c56870 100644 --- a/services/web/app/coffee/router.coffee +++ b/services/web/app/coffee/router.coffee @@ -359,6 +359,9 @@ module.exports = class Router publicApiRouter.get '/health_check/redis', HealthCheckController.checkRedis privateApiRouter.get '/health_check/redis', HealthCheckController.checkRedis + publicApiRouter.get '/health_check/mongo', HealthCheckController.checkMongo + privateApiRouter.get '/health_check/mongo', HealthCheckController.checkMongo + webRouter.get "/status/compiler/:Project_id", AuthorizationMiddlewear.ensureUserCanReadProject, (req, res) -> project_id = req.params.Project_id sendRes = _.once (statusCode, message)-> diff --git a/services/web/app/views/_mixins/links.pug b/services/web/app/views/_mixins/links.pug index bad56ffc25..d73c4772ce 100644 --- a/services/web/app/views/_mixins/links.pug +++ b/services/web/app/views/_mixins/links.pug @@ -31,6 +31,10 @@ mixin linkContact(linkText, linkClass) a(href="/contact" class=linkClass ? linkClass : '') | #{linkText ? linkText : 'contact'} +mixin linkDash(linkText, linkClass) + a(href="/project" class=linkClass ? linkClass : '') + | #{linkText ? linkText : 'project dashboard'} + mixin linkEducation(linkText, linkClass) //- To Do: verify path a(href="/plans" class=linkClass ? linkClass : '') diff --git a/services/web/app/views/layout.pug b/services/web/app/views/layout.pug index 15d3150035..27398e45db 100644 --- a/services/web/app/views/layout.pug +++ b/services/web/app/views/layout.pug @@ -21,7 +21,7 @@ html(itemscope, itemtype='http://schema.org/Product') link(rel="mask-icon", href="/" + settings.brandPrefix + "mask-favicon.svg", color=settings.brandPrefix === 'ol-' ? "#4f9c45" : "#a93529") //- Stylesheet - link(rel='stylesheet', href=buildCssPath("/" + settings.brandPrefix + "style.css", {hashedPath:true})) + link(rel='stylesheet', href=buildCssPath(buildCssFileNameForUser(userSettings), {hashedPath:true}), id="main-stylesheet") block _headLinks diff --git a/services/web/app/views/project/editor.pug b/services/web/app/views/project/editor.pug index ea10ede8b8..980f578210 100644 --- a/services/web/app/views/project/editor.pug +++ b/services/web/app/views/project/editor.pug @@ -173,6 +173,10 @@ block requirejs window.pdfCMapsPath = "#{pdfCMapsPath}" window.uiConfig = JSON.parse('!{JSON.stringify(uiConfig).replace(/\//g, "\\/")}'); + - if (settings.overleaf != null) + script(type='text/javascript'). + window.overallThemes = JSON.parse('!{JSON.stringify(overallThemes).replace(/\//g, "\\/")}'); + script( data-main=buildJsPath("ide.js", {hashedPath:false}), baseurl=fullJsPath, diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 69a874cc05..fda0fa6446 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -44,7 +44,7 @@ div.full-size( ng-if="!editor.showRichText", ng-show="!!editor.sharejs_doc && !editor.opening", style=richTextEnabled ? "top: 32px" : "", - theme="settings.theme", + theme="settings.editorTheme", keybindings="settings.mode", font-size="settings.fontSize", auto-complete="settings.autoComplete", diff --git a/services/web/app/views/project/editor/history/diffPanelV1.pug b/services/web/app/views/project/editor/history/diffPanelV1.pug index 369f3703b0..cae58b56f2 100644 --- a/services/web/app/views/project/editor/history/diffPanelV1.pug +++ b/services/web/app/views/project/editor/history/diffPanelV1.pug @@ -20,7 +20,7 @@ ) #{translate("restore_to_before_these_changes")} .diff-editor.hide-ace-cursor( ace-editor="history", - theme="settings.theme", + theme="settings.editorTheme", font-size="settings.fontSize", text="history.diff.text", highlights="history.diff.highlights", diff --git a/services/web/app/views/project/editor/history/previewPanelV2.pug b/services/web/app/views/project/editor/history/previewPanelV2.pug index e75af8db90..31f08956a6 100644 --- a/services/web/app/views/project/editor/history/previewPanelV2.pug +++ b/services/web/app/views/project/editor/history/previewPanelV2.pug @@ -40,7 +40,7 @@ .diff-editor.hide-ace-cursor( ng-if="!history.diff.binary" ace-editor="history", - theme="settings.theme", + theme="settings.editorTheme", font-size="settings.fontSize", text="history.diff.text", highlights="history.diff.highlights", @@ -66,7 +66,7 @@ .hide-ace-cursor( ng-if="!history.selectedFile.binary" ace-editor="history-pointintime", - theme="settings.theme", + theme="settings.editorTheme", font-size="settings.fontSize", text="history.selectedFile.text", read-only="true", diff --git a/services/web/app/views/project/editor/history/toolbarV2.pug b/services/web/app/views/project/editor/history/toolbarV2.pug index 2acb93854b..8abe329b01 100644 --- a/services/web/app/views/project/editor/history/toolbarV2.pug +++ b/services/web/app/views/project/editor/history/toolbarV2.pug @@ -30,6 +30,13 @@ i.fa.fa-exchange |  #{translate("compare_to_another_version")} + button.history-toolbar-btn-danger.pull-right( + tooltip-html="'

This feature is still in progress. Please use copy and paste to restore your files.

More restore options are coming soon.

'" + tooltip-placement="bottom" + ) + i.fa.fa-undo + |  #{translate("restore_to_before_these_changes")} + .history-toolbar-entries-list( ng-if="!history.error" ) diff --git a/services/web/app/views/project/editor/left-menu.pug b/services/web/app/views/project/editor/left-menu.pug index bbfa4c480c..de64b7c54a 100644 --- a/services/web/app/views/project/editor/left-menu.pug +++ b/services/web/app/views/project/editor/left-menu.pug @@ -131,13 +131,27 @@ aside#left-menu.full-size( ) .form-controls - label(for="theme") #{translate("theme")} + label(for="editorTheme") #{translate("editor_theme")} select( - name="theme" - ng-model="settings.theme" + name="editorTheme" + ng-model="settings.editorTheme" ) - each theme in themes - option(value=theme) #{theme.replace(/_/g, ' ')} + each editorTheme in editorThemes + option(value=editorTheme) #{editorTheme.replace(/_/g, ' ')} + + - if (settings.overleaf != null) + .form-controls + label(for="overallTheme") #{translate("overall_theme")} + select( + name="overallTheme" + ng-if="!ui.loadingStyleSheet" + ng-model="settings.overallTheme" + ng-options="overallTheme.val as overallTheme.name for overallTheme in overallThemesList" + ) + p.loading.pull-right( + ng-if="ui.loadingStyleSheet" + ) + i.fa.fa-fw.fa-spin.fa-refresh .form-controls(ng-show="!anonymous") label(for="mode") #{translate("keybindings")} @@ -156,7 +170,7 @@ aside#left-menu.full-size( ng-model="fontSizeAsStr" ng-model-options="{ getterSetter: true }" ) - each size in ['10','11','12','13','14','16','20','24'] + each size in ['10','11','12','13','14','16','18','20','22','24'] option(value=size) #{size}px .form-controls diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index d485d24700..44410a44a8 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -161,7 +161,6 @@ div.full-size.pdf(ng-controller="PdfController") 'alert-info': entry.level == 'typesetting'\ }" ng-click="openInEditor(entry)" - ng-init="feedbackSent = false; showNegFeedbackUI = false; negFeedbackReason = ''; negFeedbackReasonFreeText = ''" ) span.line-no i.fa.fa-link(aria-hidden="true") @@ -179,7 +178,7 @@ div.full-size.pdf(ng-controller="PdfController") p.card-hint-text( ng-show="entry.humanReadableHint", ng-bind-html="wikiEnabled ? entry.humanReadableHint : stripHTMLFromString(entry.humanReadableHint)") - .card-hint-actions.clearfix + .card-hint-footer.clearfix .card-hint-ext-link(ng-if="wikiEnabled && entry.extraInfoURL") a( ng-href="{{ entry.extraInfoURL }}", @@ -188,67 +187,6 @@ div.full-size.pdf(ng-controller="PdfController") ) i.fa.fa-external-link | #{translate("log_hint_extra_info")} - .card-hint-feedback( - ng-hide="feedbackSent || showNegFeedbackUI" - ng-class="entry.ruleId" - ) - label.card-hint-feedback-label #{translate("log_hint_feedback_label")} - a.card-hint-feedback-positive( - ng-click="trackLogHintsPositiveFeedback(entry.ruleId); feedbackSent = true;" - href - ) #{translate("answer_yes")} - span  /  - a.card-hint-feedback-negative( - ng-click="trackLogHintsNegativeFeedback(entry.ruleId); showNegFeedbackUI = true;" - href - ) #{translate("answer_no")} - .card-hint-extra-feedback(ng-hide="!showNegFeedbackUI || feedbackSent") - p.card-hint-extra-feedback-label #{translate("log_hint_ask_extra_feedback")} - .radio: label - input( - type="radio" - name="{{ 'neg-feedback-reason-' + $index }}" - ng-model="negFeedbackReason" - value="{{ logHintsNegFeedbackValues.DIDNT_UNDERSTAND }}" - ) - | #{translate("log_hint_extra_feedback_didnt_understand")} - .radio: label - input( - type="radio" - name="{{ 'neg-feedback-reason-' + $index }}" - ng-model="negFeedbackReason" - value="{{ logHintsNegFeedbackValues.NOT_APPLICABLE }}" - ) - | #{translate("log_hint_extra_feedback_not_applicable")} - .radio: label - input( - type="radio" - name="{{ 'neg-feedback-reason-' + $index }}" - ng-model="negFeedbackReason" - value="{{ logHintsNegFeedbackValues.INCORRECT }}" - ) - | #{translate("log_hint_extra_feedback_incorrect")} - .radio: label - input( - type="radio" - name="{{ 'neg-feedback-reason-' + $index }}" - ng-model="negFeedbackReason" - value="{{ logHintsNegFeedbackValues.OTHER }}" - ) - | #{translate("log_hint_extra_feedback_other")} - textarea.form-control( - ng-show="negFeedbackReason === logHintsNegFeedbackValues.OTHER" - ng-model="negFeedbackReasonFreeText" - rows="2" - ) - .clearfix - button.btn.btn-default.btn-sm.pull-right( - ng-disabled="!negFeedbackReason" - ng-click="trackLogHintsNegFeedbackDetails(entry.ruleId, negFeedbackReason, negFeedbackReasonFreeText); feedbackSent = true;" - ) #{translate("log_hint_extra_feedback_submit")} - - .card-hint-feedback(ng-show="feedbackSent") - label.card-hint-feedback-label #{translate("log_hint_feedback_gratitude")} p.entry-content(ng-show="entry.content") {{ entry.content.trim() }} diff --git a/services/web/app/views/project/list/modals.pug b/services/web/app/views/project/list/modals.pug index d3d8e25f23..2c1f30bbbb 100644 --- a/services/web/app/views/project/list/modals.pug +++ b/services/web/app/views/project/list/modals.pug @@ -323,71 +323,44 @@ script(type="text/ng-template", id="v1ImportModalTemplate") h3 Move Project to Overleaf v2 .modal-body.v1-import-wrapper - .v1-import-step-1(ng-show="step === 1") - .v1-import-row - .v1-import-col - img.v1-import-img( - src="/img/v1-import/v2-editor.png" - alt="The new V2 Editor." - ) - .v1-import-col - h2.v1-import-title Try the Overleaf v2 Editor - p The Overleaf v2 editor has many great new features including: - ul - li Faster real-time collaboration - li See your coauthors’ cursors - li Chat with math support - li Tracked changes and commenting - li Improved LaTeX autocomplete - li Two-way Dropbox sync - p.v1-import-cta Would you like to move #[strong {{project.name}}] into Overleaf v2? - - .v1-import-step-2(ng-show="step === 2") - .v1-import-row - .v1-import-warning.v1-import-col(aria-label="Warning symbol.") - i.fa.fa-flask - .v1-import-col - h2.v1-import-title #[strong Warning:] Overleaf v2 is Experimental - p We are still working hard to bring some Overleaf v1 features to the v2 editor. In v2: - ul - li You may not be able to access all of your Labelled versions yet - li There are no Zotero and CiteULike integrations yet - li Some Journals and Services in the Submit menu don't support direct submissions yet - p.row-spaced-small - | If you currently use the Overleaf Git bridge with your v1 project, you can migrate your project to the Overleaf v2 GitHub integration. + .v1-import-row + .v1-import-col.v1-import-col--left + img.v1-import-img( + src="/img/v1-import/v2-editor.png" + alt="The new V2 editor." + ) + .v1-import-col + h2.v1-import-title #[strong Warning:] Some Overleaf v1 features aren't supported yet + p We are still working hard to bring some Overleaf v1 features to the v2 editor. In v2: + ul + li + | Direct git access to your projects is not yet available, but you can migrate your project to the Overleaf v2 GitHub integration | a(href='https://www.overleaf.com/help/343-working-offline-in-overleaf-v2', target='_blank') Read More. - .v1-import-cta - p - strong Please note: you cannot move this project back to v1 once you have moved it to v2. If this is an important project, please consider making a clone in v1 before you move the project to v2. - p Are you sure you want to move #[strong {{project.name}}] into Overleaf v2? + li There are no Zotero and CiteULike integrations yet + li Some Journals and Services in the Submit menu don't support direct submissions yet + .v1-import-cta + p + strong Please note: you cannot move this project back to v1 once you have moved it to v2. + p Are you sure you want to move #[strong {{project.name}}] into Overleaf v2? .modal-footer.v1-import-footer - div(ng-show="step === 1") + form( + async-form="v1Import", + name="v1ImportForm", + action="{{'/overleaf/project/'+ project.id + '/import'}}" + method="POST" + ng-cloak + ) + input(name='_csrf', type='hidden', value=csrfToken) + form-messages(for="v1ImportForm") if settings.overleaf && settings.overleaf.host a.btn.btn-primary.v1-import-btn( ng-href=settings.overleaf.host + "/{{project.id}}" + ng-class="{disabled: v1ImportForm.inflight || v1ImportForm.response.success}" ) No thanks, open in v1 - button.btn.btn-primary.v1-import-btn( - ng-click="moveToConfirmation()" - ) Yes, move project to v2 - div(ng-show="step === 2") - form( - async-form="v1Import", - name="v1ImportForm", - action="{{'/overleaf/project/'+ project.id + '/import'}}" - method="POST" - ng-cloak + input.btn.btn-primary.v1-import-btn( + type="submit", + value="Yes, move project to v2" + ng-disabled="v1ImportForm.inflight || v1ImportForm.response.success" ) - input(name='_csrf', type='hidden', value=csrfToken) - form-messages(for="v1ImportForm") - if settings.overleaf && settings.overleaf.host - a.btn.btn-primary.v1-import-btn( - ng-href=settings.overleaf.host + "/{{project.id}}" - ng-class="{disabled: v1ImportForm.inflight || v1ImportForm.response.success}" - ) No thanks, open in v1 - input.btn.btn-primary.v1-import-btn( - type="submit", - value="Yes, move project to v2" - ng-disabled="v1ImportForm.inflight || v1ImportForm.response.success" - ) diff --git a/services/web/app/views/project/list/side-bar.pug b/services/web/app/views/project/list/side-bar.pug index e342b792a5..ab8db43877 100644 --- a/services/web/app/views/project/list/side-bar.pug +++ b/services/web/app/views/project/list/side-bar.pug @@ -131,9 +131,10 @@ p.small #{translate("on_free_sl")} p a(href="/user/subscription/plans").btn.btn-primary #{translate("upgrade")} - p.small.text-centered - | #{translate("or_unlock_features_bonus")} - a(href="/user/bonus") #{translate("sharing_sl")} . + if (!settings.overleaf) + p.small.text-centered + | #{translate("or_unlock_features_bonus")} + a(href="/user/bonus") #{translate("sharing_sl")} . script. diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 59d6e0aa89..6572b01875 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -484,4 +484,24 @@ module.exports = settings = # {imageName: 'texlive-full:2016.1', imageDesc: 'Legacy SL TeXLive 2016'} # {imageName: 'texlive-full:2015.1', imageDesc: 'Legacy SL TeXLive 2015'} # {imageName: 'texlive-full:2014.2', imageDesc: 'Legacy SL TeXLive 2014.2'} - # ] \ No newline at end of file + # ] + + # module options + # ---------- + modules: + sanitize: + options: + allowedTags: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', 'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'iframe', 'img', 'figure', 'figcaption' ] + allowedAttributes: + 'a': [ 'href', 'name', 'target', 'class' ] + 'div': [ 'class', 'id', 'style' ] + 'h1': [ 'class', 'id' ] + 'h2': [ 'class', 'id' ] + 'h3': [ 'class', 'id' ] + 'h4': [ 'class', 'id' ] + 'h5': [ 'class', 'id' ] + 'h6': [ 'class', 'id' ] + 'figure': [ 'class', 'id', 'style'] + 'figcaption': [ 'class', 'id', 'style'] + 'iframe': [ 'allowfullscreen', 'frameborder', 'height', 'src', 'width' ] + 'img': [ 'alt', 'class', 'src', 'style' ] \ No newline at end of file diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index cf4ab08e2b..c9764418c7 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -185,7 +185,7 @@ define [ "twilight", "vibrant_ink" ] $scope.darkTheme = false - $scope.$watch "settings.theme", (theme) -> + $scope.$watch "settings.editorTheme", (theme) -> if theme in DARK_THEMES $scope.darkTheme = true else diff --git a/services/web/public/coffee/ide/editor/directives/toggleSwitch.coffee b/services/web/public/coffee/ide/editor/directives/toggleSwitch.coffee index 095be6dc1e..ff1fc82214 100644 --- a/services/web/public/coffee/ide/editor/directives/toggleSwitch.coffee +++ b/services/web/public/coffee/ide/editor/directives/toggleSwitch.coffee @@ -14,7 +14,7 @@ define [ AUTO_COMPILE_MAX_WAIT = 5000 # We add a 1 second debounce to sending user changes to server if they aren't @@ -16,7 +15,7 @@ define [ return (url)-> return $sce.trustAsResourceUrl(url); ]) - App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, logHintsFeedback, localStorage) -> + App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, localStorage) -> # enable per-user containers by default perUserCompile = true autoCompile = true @@ -42,22 +41,9 @@ define [ $scope.$applyAsync () -> $scope.shouldDropUp = getFilesDropdownTopCoordAsRatio() > 0.65 - # log hints tracking - $scope.logHintsNegFeedbackValues = logHintsFeedback.feedbackOpts - $scope.trackLogHintsLearnMore = () -> event_tracking.sendMB "logs-hints-learn-more" - trackLogHintsFeedback = (isPositive, hintId) -> - event_tracking.send "log-hints", (if isPositive then "feedback-positive" else "feedback-negative"), hintId - event_tracking.sendMB (if isPositive then "log-hints-feedback-positive" else "log-hints-feedback-negative"), { hintId } - - $scope.trackLogHintsNegFeedbackDetails = (hintId, feedbackOpt, feedbackOtherVal) -> - logHintsFeedback.submitFeedback hintId, feedbackOpt, feedbackOtherVal - - $scope.trackLogHintsPositiveFeedback = (hintId) -> trackLogHintsFeedback true, hintId - $scope.trackLogHintsNegativeFeedback = (hintId) -> trackLogHintsFeedback false, hintId - if ace.require("ace/lib/useragent").isMac $scope.modifierKey = "Cmd" else @@ -69,9 +55,9 @@ define [ if qs_args.length then "?" + qs_args.join("&") else "" $scope.stripHTMLFromString = (htmlStr) -> - tmp = document.createElement("DIV") - tmp.innerHTML = htmlStr - return tmp.textContent || tmp.innerText || "" + tmp = document.createElement("DIV") + tmp.innerHTML = htmlStr + return tmp.textContent || tmp.innerText || "" $scope.$on "project:joined", () -> return if !autoCompile diff --git a/services/web/public/coffee/ide/settings/controllers/SettingsController.coffee b/services/web/public/coffee/ide/settings/controllers/SettingsController.coffee index 2e8c09739e..8eb3cff886 100644 --- a/services/web/public/coffee/ide/settings/controllers/SettingsController.coffee +++ b/services/web/public/coffee/ide/settings/controllers/SettingsController.coffee @@ -1,7 +1,25 @@ define [ "base" ], (App) -> - App.controller "SettingsController", ["$scope", "settings", "ide", ($scope, settings, ide) -> + App.controller "SettingsController", ["$scope", "settings", "ide", "_", ($scope, settings, ide, _) -> + $scope.overallThemesList = window.overallThemes + $scope.ui = + loadingStyleSheet: false + + _updateCSSFile = (theme) -> + $scope.ui.loadingStyleSheet = true + docHeadEl = document.querySelector "head" + oldStyleSheetEl = document.getElementById "main-stylesheet" + newStyleSheetEl = document.createElement "link" + newStyleSheetEl.addEventListener "load", (e) => + $scope.$applyAsync () => + $scope.ui.loadingStyleSheet = false + docHeadEl.removeChild oldStyleSheetEl + newStyleSheetEl.setAttribute "rel", "stylesheet" + newStyleSheetEl.setAttribute "id", "main-stylesheet" + newStyleSheetEl.setAttribute "href", theme.path + docHeadEl.appendChild newStyleSheetEl + if $scope.settings.mode not in ["default", "vim", "emacs"] $scope.settings.mode = "default" @@ -19,9 +37,16 @@ define [ $scope.settings.fontSize = newVal return $scope.settings.fontSize.toString() - $scope.$watch "settings.theme", (theme, oldTheme) => - if theme != oldTheme - settings.saveSettings({theme: theme}) + $scope.$watch "settings.editorTheme", (editorTheme, oldEditorTheme) => + if editorTheme != oldEditorTheme + settings.saveSettings({editorTheme}) + + $scope.$watch "settings.overallTheme", (overallTheme, oldOverallTheme) => + if overallTheme != oldOverallTheme + chosenTheme = _.find $scope.overallThemesList, (theme) -> theme.val == overallTheme + if chosenTheme? + _updateCSSFile chosenTheme + settings.saveSettings({overallTheme}) $scope.$watch "settings.fontSize", (fontSize, oldFontSize) => if fontSize != oldFontSize diff --git a/services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee b/services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee index 14ea1a7d29..b57e3a8f72 100644 --- a/services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee +++ b/services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee @@ -5,7 +5,7 @@ define [ $scope.userEmails = [] LOCAL_AND_DOMAIN_REGEX = /([^@]+)@(.+)/ - EMAIL_REGEX = /^([A-Za-z0-9_\-\.]+)@([^\.]+)\.([A-Za-z0-9_\-\.]+)([^\.])$/ + EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\ ".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA -Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ _matchLocalAndDomain = (userEmailInput) -> match = userEmailInput?.match LOCAL_AND_DOMAIN_REGEX diff --git a/services/web/public/coffee/main/project-list/modal-controllers.coffee b/services/web/public/coffee/main/project-list/modal-controllers.coffee index 42a11500cf..27124e0951 100644 --- a/services/web/public/coffee/main/project-list/modal-controllers.coffee +++ b/services/web/public/coffee/main/project-list/modal-controllers.coffee @@ -134,10 +134,6 @@ define [ App.controller 'V1ImportModalController', ($scope, $modalInstance, project) -> $scope.project = project - $scope.step = 1 $scope.dismiss = () -> $modalInstance.dismiss('cancel') - - $scope.moveToConfirmation = () -> - $scope.step = 2 diff --git a/services/web/public/coffee/services/log-hints-feedback.coffee b/services/web/public/coffee/services/log-hints-feedback.coffee deleted file mode 100644 index 104313e016..0000000000 --- a/services/web/public/coffee/services/log-hints-feedback.coffee +++ /dev/null @@ -1,58 +0,0 @@ -define [ - "base" -], (App) -> - App.factory "logHintsFeedback", ($http, $q) -> - hintsFeedbackFormAPIHash = "rl4xgvr1v5t64a" - idStampVal = "OPkEWEFHUFAm7hKlraQMhiOXQabafWo8NipRvLT397w=" - hintFieldAPIId = "3" - reasonFieldAPIId = "1" - reasonOtherFieldAPIId = "1_other_other" - submitEndpoint = "https://sharelatex.wufoo.eu/forms/#{ hintsFeedbackFormAPIHash }/#public" - - feedbackOpts = - DIDNT_UNDERSTAND: "didnt_understand" - NOT_APPLICABLE: "not_applicable" - INCORRECT: "incorrect" - OTHER: "other" - - createRequest = (hintId, feedbackOpt, feedbackOtherVal = "") -> - formData = new FormData() - - formData.append "Field#{ hintFieldAPIId }", hintId - formData.append "Field#{ reasonFieldAPIId }", feedbackOpt - formData.append "idstamp", idStampVal - - # Allow user to specify "other" without any extra details; an empty string - # would trigger an error submitting. - if feedbackOpt == feedbackOpts.OTHER and feedbackOtherVal == "" - formData.append "Field#{ reasonOtherFieldAPIId }", "#{ feedbackOpts.OTHER } empty" - else - formData.append "Field#{ reasonOtherFieldAPIId }", feedbackOtherVal - - req = - method: 'POST' - url: submitEndpoint - # This will effectively disable Angular's default serialization mechanisms, - # forcing the XHR to be done with whatever data we provide (in this case, - # form data). Without this, Angular will forcefully try to serialize data - # to JSON. - transformRequest: angular.identity - data: formData - headers : - # This will tell Angular to use the browser-provided value, which is - # computed according to the data being sent (in this case, multipart - # form + browser-specific multipart boundary). Without this, Angular - # will set JSON. - "Content-Type": undefined - - return req - - submitFeedback = (hintId, feedbackOpt, feedbackOtherVal = "") -> - submitRequest = createRequest hintId, feedbackOpt, feedbackOtherVal - $http(submitRequest) - - service = - feedbackOpts: feedbackOpts - submitFeedback: submitFeedback - - return service \ No newline at end of file diff --git a/services/web/public/img/ol-brand/overleaf.svg b/services/web/public/img/ol-brand/overleaf.svg index 73d2a9b4e0..a1ba347f3a 100644 --- a/services/web/public/img/ol-brand/overleaf.svg +++ b/services/web/public/img/ol-brand/overleaf.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/services/web/public/img/review-icon-sprite-ol.png b/services/web/public/img/review-icon-sprite-ol.png index 1e5c7192e4..17c79182b0 100644 Binary files a/services/web/public/img/review-icon-sprite-ol.png and b/services/web/public/img/review-icon-sprite-ol.png differ diff --git a/services/web/public/img/review-icon-sprite-ol@2x.png b/services/web/public/img/review-icon-sprite-ol@2x.png index 87aec7c163..5e145bce8e 100644 Binary files a/services/web/public/img/review-icon-sprite-ol@2x.png and b/services/web/public/img/review-icon-sprite-ol@2x.png differ diff --git a/services/web/public/img/v1-import/v2-editor.png b/services/web/public/img/v1-import/v2-editor.png index 5079d77158..3b38f9001d 100644 Binary files a/services/web/public/img/v1-import/v2-editor.png and b/services/web/public/img/v1-import/v2-editor.png differ diff --git a/services/web/public/stylesheets/app/blog-posts.less b/services/web/public/stylesheets/app/blog-posts.less index c337ed280c..c503e11f57 100644 --- a/services/web/public/stylesheets/app/blog-posts.less +++ b/services/web/public/stylesheets/app/blog-posts.less @@ -11,7 +11,7 @@ list-style: none; margin: 0; padding: 0; - li { + .blog-post { margin: 0 0 @margin-lg 0; } .card-header { @@ -38,4 +38,10 @@ font-size: small; } } + + pre { + border: 1px solid @ol-blue-gray-2; + border-radius: @border-radius-base; + padding: @padding-sm; + } } \ No newline at end of file diff --git a/services/web/public/stylesheets/app/editor.less b/services/web/public/stylesheets/app/editor.less index c0db61aef0..65041eeee8 100644 --- a/services/web/public/stylesheets/app/editor.less +++ b/services/web/public/stylesheets/app/editor.less @@ -33,7 +33,7 @@ .editor-menu-icon when (@is-overleaf = true) { &.fa { width: 1em; - background: url(/img/ol-brand/overleaf-o-white.svg) center / contain no-repeat; + background: @editor-header-logo-background; &::before { // Disable the font-awesome icon when in Overleaf by replacing it with a @@ -92,6 +92,7 @@ .toolbar-editor { height: @editor-toolbar-height; background-color: @editor-toolbar-bg; + padding: 0 5px; overflow: hidden; position: relative; z-index: 10; // Prevent track changes showing over toolbar diff --git a/services/web/public/stylesheets/app/editor/chat.less b/services/web/public/stylesheets/app/editor/chat.less index 6a08cfc304..46c3585d24 100644 --- a/services/web/public/stylesheets/app/editor/chat.less +++ b/services/web/public/stylesheets/app/editor/chat.less @@ -133,12 +133,12 @@ height: @new-message-height; background-color: @chat-new-message-bg; padding: @line-height-computed / 4; - border-top: 1px solid @editor-border-color; + border-top: 1px solid @chat-new-message-border-color; textarea { overflow: auto; resize: none; border-radius: @border-radius-base; - border: 1px solid @editor-border-color; + border: 1px solid @chat-new-message-border-color; height: 100%; width: 100%; color: @chat-new-message-textarea-color; diff --git a/services/web/public/stylesheets/app/editor/file-tree.less b/services/web/public/stylesheets/app/editor/file-tree.less index 845cc74a93..95bc0d38bf 100644 --- a/services/web/public/stylesheets/app/editor/file-tree.less +++ b/services/web/public/stylesheets/app/editor/file-tree.less @@ -201,10 +201,11 @@ > .entity when (@is-overleaf = true) { > .entity-name { + color: @file-tree-item-selected-color; > div > i.fa, > i.fa, .entity-menu-toggle i.fa { - color: #FFF; + color: @file-tree-item-selected-color; } > i.fa i.linked-file-highlight { color: @blue; diff --git a/services/web/public/stylesheets/app/editor/history-v2.less b/services/web/public/stylesheets/app/editor/history-v2.less index 35190cd662..56e9051997 100644 --- a/services/web/public/stylesheets/app/editor/history-v2.less +++ b/services/web/public/stylesheets/app/editor/history-v2.less @@ -12,9 +12,11 @@ color: @history-toolbar-color; padding-left: (@line-height-computed / 2); } -.history-toolbar when (@is-overleaf = false) { + +.history-toolbar when (@is-overleaf = false) or (@is-overleaf-light) { border-bottom: @toolbar-border-bottom; } + .history-toolbar-selected-version { white-space: nowrap; overflow: hidden; @@ -27,15 +29,23 @@ } .history-toolbar-actions { flex-grow: 1; + flex-shrink: 0; } - .history-toolbar-btn { + .history-toolbar-btn, + .history-toolbar-btn-danger { .btn; - .btn-info; .btn-xs; padding-left: @padding-small-horizontal; padding-right: @padding-small-horizontal; margin-right: (@line-height-computed / 2); } + .history-toolbar-btn { + .btn-info; + } + .history-toolbar-btn-danger { + .btn-danger; + opacity: 0.65; + } .history-toolbar-entries-list { flex: 0 0 @changesListWidth; padding: 0 10px; diff --git a/services/web/public/stylesheets/app/editor/left-menu.less b/services/web/public/stylesheets/app/editor/left-menu.less index 438ef9eb77..e1e918fa29 100644 --- a/services/web/public/stylesheets/app/editor/left-menu.less +++ b/services/web/public/stylesheets/app/editor/left-menu.less @@ -100,7 +100,8 @@ // select.form-control { // color: white; // } - label { + label, + i.fa { color: white; } } diff --git a/services/web/public/stylesheets/app/editor/pdf.less b/services/web/public/stylesheets/app/editor/pdf.less index af597933ea..b0002271a3 100644 --- a/services/web/public/stylesheets/app/editor/pdf.less +++ b/services/web/public/stylesheets/app/editor/pdf.less @@ -7,7 +7,6 @@ .pdf .toolbar.toolbar-pdf when (@is-overleaf = true) { .toolbar-small-mixin; .toolbar-alt-mixin; - border-bottom: 0; padding-right: 5px; &.uncompiled-changes { #gradient > .striped(@color: rgba(255,255,255,.10), @angle: -45deg); @@ -23,6 +22,11 @@ } } +.pdf .toolbar.toolbar-pdf when (@is-overleaf = true) and (@is-overleaf-light = false) { + border-bottom: 0; +} + + .pdf .toolbar.toolbar-pdf when (@is-overleaf = false) { .toolbar-tall-mixin; padding: 0 (@line-height-computed / 2); @@ -305,25 +309,25 @@ line-height: 1.3; padding: 0 2px; } - + .synctex-control-goto-pdf > .synctex-control-icon when (@is-overleaf = true) { text-indent: 1px; // "Optical" adjustment. &::before { - content: "\f061"; + content: "\f061"; } } .synctex-control-goto-code > .synctex-control-icon when (@is-overleaf = true) { text-indent: -1px; // "Optical" adjustment. &::before { - content: "\f060"; + content: "\f060"; } } - + .synctex-control-goto-pdf > .synctex-control-icon::before when (@is-overleaf = false) { - content: "\f178"; + content: "\f178"; } .synctex-control-goto-code > .synctex-control-icon::before when (@is-overleaf = false) { - content: "\f177"; + content: "\f177"; } .editor-dark { @@ -401,7 +405,7 @@ } - &-text, + &-text, &-feedback-label { color: @log-hints-color; font-size: 0.9rem; @@ -424,8 +428,8 @@ display: inline-block; font-size: 0.8rem; } - - &-actions a, + + &-footer a, &-text a { .alert-danger & { color: @state-danger-text; @@ -492,7 +496,7 @@ .plv-text-layer { display: none; user-select: text; - + .pdf-page-container:hover &, .pdfjs-viewer-show-text & { display: block; diff --git a/services/web/public/stylesheets/app/editor/review-panel.less b/services/web/public/stylesheets/app/editor/review-panel.less index a7e7d3fdbd..c1bf6d59d7 100644 --- a/services/web/public/stylesheets/app/editor/review-panel.less +++ b/services/web/public/stylesheets/app/editor/review-panel.less @@ -949,6 +949,7 @@ display: inline-block; background: url('/img/review-icon-sprite-ol.png') top/30px no-repeat; width: 30px; + background-position-y: -30px; &::before { content: '\00a0'; // Non-breakable space. A non-breakable character here makes this icon work like font-awesome. @@ -959,6 +960,14 @@ } } +.review-icon when (@is-overleaf-light = true) { + background-position-y: 0; + .toolbar .btn-full-height.active &, + .toolbar .btn-full-height:active & { + background-position-y: -30px; + } +} + .resolved-comments-toggle { font-size: 14px; color: lighten(@rp-type-blue, 25%); diff --git a/services/web/public/stylesheets/app/editor/toolbar.less b/services/web/public/stylesheets/app/editor/toolbar.less index c5499180e0..dcc0344c73 100644 --- a/services/web/public/stylesheets/app/editor/toolbar.less +++ b/services/web/public/stylesheets/app/editor/toolbar.less @@ -58,7 +58,7 @@ .btn-full-height { border: none; border-radius: 0; - border-right: 1px solid @toolbar-border-color; + border-right: 1px solid @toolbar-header-btn-border-color; color: @toolbar-btn-color; padding: 3px 10px 5px; font-size: 20px; @@ -96,7 +96,7 @@ justify-content: flex-end; .btn-full-height { border-right: 0; - border-left: 1px solid @toolbar-border-color; + border-left: 1px solid @toolbar-header-btn-border-color; } } diff --git a/services/web/public/stylesheets/app/list/v1-import-modal.less b/services/web/public/stylesheets/app/list/v1-import-modal.less index 21d64299e8..6a408bd8a3 100644 --- a/services/web/public/stylesheets/app/list/v1-import-modal.less +++ b/services/web/public/stylesheets/app/list/v1-import-modal.less @@ -17,6 +17,10 @@ margin-bottom: 0; } +.v1-import-col--left { + flex-shrink: 1.1; +} + .v1-import-img { width: 100%; margin-top: 30px; diff --git a/services/web/public/stylesheets/app/project-list.less b/services/web/public/stylesheets/app/project-list.less index a1a0dd9cd6..e5bc8da14c 100644 --- a/services/web/public/stylesheets/app/project-list.less +++ b/services/web/public/stylesheets/app/project-list.less @@ -169,10 +169,10 @@ ul.folders-menu { border-radius: @sidebar-active-border-radius; > a { background-color: @sidebar-active-bg; - font-weight: 700; - color: white; + font-weight: @sidebar-active-font-weight; + color: @sidebar-active-color; .subdued { - color: white; + color: @sidebar-active-color; } } } diff --git a/services/web/public/stylesheets/app/sidebar-v2-dash-pane.less b/services/web/public/stylesheets/app/sidebar-v2-dash-pane.less index a14f3b4d4a..3379aba577 100644 --- a/services/web/public/stylesheets/app/sidebar-v2-dash-pane.less +++ b/services/web/public/stylesheets/app/sidebar-v2-dash-pane.less @@ -17,7 +17,7 @@ flex-shrink: 0; text-align: center; background-color: @v2-dash-pane-bg; - color: white; + color: @v2-dash-pane-color; font-size: 13px; padding: @line-height-computed / 2; } @@ -32,10 +32,10 @@ } .project-list-sidebar-v2-pane-toggle { - color: white; + color: @v2-dash-pane-toggle-color; padding: 0; line-height: 1; &:hover, &:active, &:focus { - color: white; + color: @v2-dash-pane-toggle-color; } } diff --git a/services/web/public/stylesheets/components/navbar.less b/services/web/public/stylesheets/components/navbar.less index f88b7c651d..01f41b0507 100755 --- a/services/web/public/stylesheets/components/navbar.less +++ b/services/web/public/stylesheets/components/navbar.less @@ -436,6 +436,7 @@ font-weight: @navbar-btn-font-weight; line-height: @navbar-btn-line-height; padding: @navbar-btn-padding; + background-color: @navbar-default-link-bg; &:hover, &:focus { @@ -466,6 +467,7 @@ color: @navbar-subdued-color; padding: @navbar-subdued-padding; margin-left: 0; + background-color: transparent; &:hover { color: @navbar-subdued-hover-color; background-color: @navbar-subdued-hover-bg; @@ -478,7 +480,7 @@ @media (min-width: @grid-float-breakpoint) { > li > a { - border-color: @navbar-default-link-color; + border-color: @navbar-default-link-border-color; margin-left: 1rem; } } diff --git a/services/web/public/stylesheets/core/_common-variables.less b/services/web/public/stylesheets/core/_common-variables.less index 9112c1400c..5e166c85d6 100644 --- a/services/web/public/stylesheets/core/_common-variables.less +++ b/services/web/public/stylesheets/core/_common-variables.less @@ -327,6 +327,7 @@ // Navbar links @navbar-default-link-color: @link-color; +@navbar-default-link-border-color: @navbar-default-link-color; @navbar-default-link-hover-color: @link-hover-color; @navbar-default-link-hover-bg: @link-hover-color; @navbar-default-link-active-color: #fff; @@ -796,6 +797,7 @@ @left-menu-animation-duration: 0.35s; @toolbar-border-color: @gray-lighter; +@toolbar-header-btn-border-color: @toolbar-border-color; @common-border-color: @gray-lighter; @editor-border-color: @gray-lighter; @file-tree-droppable-bg-color: rgb(252, 231, 199); @@ -834,7 +836,7 @@ @dropdown-divider-margin :((@line-height-computed / 2) - 1) 0; @dropdown-item-padding : 3px 20px; - +@navbar-default-link-bg : transparent; // Button colors and sizing @btn-border-radius-large : @border-radius-large; @@ -859,6 +861,8 @@ @sidebar-link-color : #333; @sidebar-active-border-radius : @border-radius-small; @sidebar-active-bg : @link-color; +@sidebar-active-color : #FFF; +@sidebar-active-font-weight : 700; @sidebar-hover-bg : transparent; @sidebar-hover-text-decoration : underline; @@ -966,6 +970,7 @@ @chat-new-message-bg : @gray-lightest; @chat-new-message-textarea-bg : #FFF; @chat-new-message-textarea-color : @gray-dark; +@chat-new-message-border-color : @editor-border-color; // PDF @pdf-top-offset : @toolbar-tall-height; diff --git a/services/web/public/stylesheets/core/ol-light-variables.less b/services/web/public/stylesheets/core/ol-light-variables.less new file mode 100644 index 0000000000..7278c71297 --- /dev/null +++ b/services/web/public/stylesheets/core/ol-light-variables.less @@ -0,0 +1,122 @@ +// Styleguide colors +@ol-blue-gray-0 : #F4F5FB; +@ol-blue-gray-1 : #DFE2E8; +@ol-blue-gray-2 : #9DA7B7; +@ol-blue-gray-3 : #727E91; +@ol-blue-gray-4 : #455265; +@ol-blue-gray-5 : #2C3645; +@ol-blue-gray-6 : #1E2530; + +@ol-green : #4F9C45; +@ol-dark-green : #1C5B26; +@ol-blue : #4B7FD1; +@ol-dark-blue : #2857A1; +@ol-red : #C9453E; +@ol-dark-red : #A6312B; + +@ol-type-color : @ol-blue-gray-3; + +// Sidebar +@sidebar-bg : #FFF; +@sidebar-color : @ol-blue-gray-2; +@sidebar-link-color : @ol-blue-gray-3; +@sidebar-active-bg : @ol-green; +@sidebar-active-color : #FFF; +@sidebar-hover-bg : @ol-blue-gray-1; +@sidebar-active-font-weight : normal; +@sidebar-hover-text-decoration : none; + +@v2-dash-pane-bg : @ol-blue-gray-1; +@v2-dash-pane-link-color : @ol-blue; +@v2-dash-pane-toggle-color : @ol-blue-gray-3; +@v2-dash-pane-btn-bg : @ol-blue-gray-5; +@v2-dash-pane-btn-hover-bg : @ol-blue-gray-6; +@v2-dash-pane-color : @ol-blue-gray-3; + +@progress-bar-shadow : inset 0 -1px 0 rgba(0,0,0,.15); +@progress-bg : @ol-blue-gray-0; + +@input-border : @ol-blue-gray-1; +// Editor file-tree +@file-tree-bg : #FFF; +@file-tree-line-height : 2.05; +@file-tree-item-color : @ol-blue-gray-3; +@file-tree-item-selected-color : #FFF; +@file-tree-item-input-color : @ol-blue-gray-2; +@file-tree-item-toggle-color : @ol-blue-gray-2; +@file-tree-item-icon-color : @ol-blue-gray-2; +@file-tree-item-folder-color : @ol-blue-gray-2; +@file-tree-item-hover-bg : @ol-blue-gray-1; +@file-tree-item-selected-bg : @ol-green; +@file-tree-multiselect-bg : @ol-blue; +@file-tree-multiselect-hover-bg : @ol-dark-blue; +@file-tree-droppable-bg-color : tint(@ol-green, 5%); + +@content-alt-bg-color : @ol-blue-gray-0; + +// Editor resizers +@editor-resizer-bg-color : @ol-blue-gray-1; +@editor-resizer-bg-color-dragging: @ol-blue-gray-1; +@editor-toggler-bg-color : @ol-blue-gray-2; +@editor-toggler-hover-bg-color : @ol-green; +@synctex-controls-z-index : 6; +@synctex-controls-padding : 0; +@editor-border-color : @ol-blue-gray-1; + +@toolbar-border-color : @ol-blue-gray-1; +@toolbar-alt-bg-color : #FFF; +@editor-toolbar-bg : @toolbar-alt-bg-color; + +@toolbar-header-bg-color : #FFF; +@toolbar-header-btn-border-color : @ol-blue-gray-1; +@toolbar-btn-color : @ol-blue-gray-3; +@toolbar-btn-hover-color : @ol-blue-gray-3; +@toolbar-btn-hover-bg-color : @ol-blue-gray-0; +@toolbar-icon-btn-color : @ol-blue-gray-3; +@toolbar-icon-btn-hover-color : @ol-blue-gray-3; +@editor-header-logo-background : url(/img/ol-brand/overleaf-o.svg) center / contain no-repeat; +@project-name-color : @ol-blue-gray-3; +@pdf-bg : @ol-blue-gray-0; + +// Navbar +@navbar-default-bg : #FFF; +@navbar-default-border : @ol-blue-gray-1; +@navbar-default-link-bg : @ol-green; +@navbar-default-link-color : #FFF; +@navbar-default-link-border-color: transparent; +@navbar-default-link-hover-bg : @ol-green; +@navbar-default-link-active-bg : @ol-green; +@navbar-default-link-hover-color : @ol-green; + +@navbar-title-color : @ol-blue-gray-1; +@navbar-title-color-hover : @ol-blue-gray-2; +@navbar-default-color : @ol-blue-gray-3; +@navbar-brand-image-url : url(/img/ol-brand/overleaf.svg); + +@navbar-subdued-color : @ol-blue-gray-3; +@navbar-subdued-hover-bg : @ol-blue-gray-1; +@navbar-subdued-hover-color : @ol-blue-gray-3; + +@card-box-shadow : 0 0 0 1px @ol-blue-gray-1; + +// v2 History +@history-toolbar-color : @ol-blue-gray-3; +@history-entry-day-bg : @ol-blue-gray-2; +@history-base-bg : @ol-blue-gray-0; + +// Formatting buttons +@formatting-btn-color : @toolbar-icon-btn-color; +@formatting-btn-bg : transparent; +@formatting-btn-border : @ol-blue-gray-1; +@formatting-menu-bg : transparent; + + +// Chat +@chat-bg : #FFF; +@chat-message-color : #FFF; +@chat-message-name-color : @ol-blue-gray-3; +@chat-message-date-color : @ol-blue-gray-3; +@chat-new-message-bg : @ol-blue-gray-0; +@chat-new-message-textarea-bg : #FFF; +@chat-new-message-textarea-color : @ol-blue-gray-6; +@chat-new-message-border-color : @ol-blue-gray-1; diff --git a/services/web/public/stylesheets/core/ol-variables.less b/services/web/public/stylesheets/core/ol-variables.less index 7c22b1f01c..f5ca77cf04 100644 --- a/services/web/public/stylesheets/core/ol-variables.less +++ b/services/web/public/stylesheets/core/ol-variables.less @@ -6,7 +6,7 @@ @footer-height: 50px; // Styleguide colors -@ol-blue-gray-0 : #f4f5f8; +@ol-blue-gray-0 : #F4F5F8; @ol-blue-gray-1 : #E4E8EE; @ol-blue-gray-2 : #9DA7B7; @ol-blue-gray-3 : #5D6879; @@ -33,7 +33,7 @@ @navbar-default-bg : @ol-blue-gray-6; @navbar-default-border : transparent; @navbar-brand-image-url : url(/img/ol-brand/overleaf-white.svg); - +@navbar-default-link-bg : transparent; // Backgrounds @body-bg : #FFF; @content-alt-bg-color : @ol-blue-gray-1; @@ -110,6 +110,7 @@ @navbar-default-padding-h : 10px; @navbar-default-padding : @navbar-default-padding-v @navbar-default-padding-h; @navbar-default-link-color : #FFF; +@navbar-default-link-border-color : @navbar-default-link-color; @navbar-default-link-hover-bg : @ol-green; @navbar-default-link-active-bg : @ol-green; @navbar-default-link-hover-color : @ol-green; @@ -149,10 +150,14 @@ @sidebar-link-color : #FFF; @sidebar-active-border-radius : 0; @sidebar-active-bg : @ol-blue-gray-6; +@sidebar-active-color : #FFF; +@sidebar-active-font-weight : 700; @sidebar-hover-bg : @ol-blue-gray-4; @sidebar-hover-text-decoration : none; @v2-dash-pane-bg : @ol-blue-gray-4; @v2-dash-pane-link-color : #FFF; +@v2-dash-pane-color : #FFF; +@v2-dash-pane-toggle-color : #FFF; @v2-dash-pane-btn-bg : @ol-blue-gray-5; @v2-dash-pane-btn-hover-bg : @ol-blue-gray-6; @@ -214,6 +219,7 @@ @toolbar-btn-active-bg-color : @ol-green; @toolbar-btn-active-shadow : none; @toolbar-border-color : @ol-blue-gray-5; +@toolbar-header-btn-border-color : @toolbar-border-color; @toolbar-alt-bg-color : @ol-blue-gray-5; @toolbar-icon-btn-color : #FFF; @toolbar-icon-btn-hover-color : #FFF; @@ -230,6 +236,7 @@ @file-tree-bg : @ol-blue-gray-4; @file-tree-line-height : 2.05; @file-tree-item-color : #FFF; +@file-tree-item-selected-color : @file-tree-item-color; @file-tree-item-input-color : @ol-blue-gray-5; @file-tree-item-toggle-color : @ol-blue-gray-2; @file-tree-item-icon-color : @ol-blue-gray-2; @@ -276,6 +283,7 @@ @chat-new-message-bg : @ol-blue-gray-4; @chat-new-message-textarea-bg : @ol-blue-gray-1; @chat-new-message-textarea-color : @ol-blue-gray-6; +@chat-new-message-border-color : @editor-border-color; // Pagination @pagination-active-bg : @ol-dark-green; @@ -357,6 +365,7 @@ @brand-warning: @orange; @brand-danger: @ol-red; +@editor-header-logo-background: url(/img/ol-brand/overleaf-o-white.svg) center / contain no-repeat; @editor-loading-logo-padding-top: 115.44%; @editor-loading-logo-background-url: url(/img/ol-brand/overleaf-o-grey.svg); @editor-loading-logo-foreground-url: url(/img/ol-brand/overleaf-o.svg); \ No newline at end of file diff --git a/services/web/public/stylesheets/ol-light-style.less b/services/web/public/stylesheets/ol-light-style.less new file mode 100644 index 0000000000..14fc37b602 --- /dev/null +++ b/services/web/public/stylesheets/ol-light-style.less @@ -0,0 +1,2 @@ +@import "ol-style.less"; +@import "core/ol-light-variables.less"; diff --git a/services/web/test/unit/coffee/Project/ProjectControllerTests.coffee b/services/web/test/unit/coffee/Project/ProjectControllerTests.coffee index 46e54501c9..dc23107d66 100644 --- a/services/web/test/unit/coffee/Project/ProjectControllerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectControllerTests.coffee @@ -524,7 +524,7 @@ describe "ProjectController", -> it "should add on userSettings", (done)-> @res.render = (pageName, opts)=> opts.userSettings.fontSize.should.equal @user.ace.fontSize - opts.userSettings.theme.should.equal @user.ace.theme + opts.userSettings.editorTheme.should.equal @user.ace.theme done() @ProjectController.loadEditor @req, @res diff --git a/services/web/test/unit/coffee/User/UserControllerTests.coffee b/services/web/test/unit/coffee/User/UserControllerTests.coffee index d589852a37..becc26ef69 100644 --- a/services/web/test/unit/coffee/User/UserControllerTests.coffee +++ b/services/web/test/unit/coffee/User/UserControllerTests.coffee @@ -224,12 +224,20 @@ describe "UserController", -> it "should set some props on ace", (done)-> @req.body = - theme: "something" + editorTheme: "something" @res.sendStatus = (code)=> @user.ace.theme.should.equal "something" done() @UserController.updateUserSettings @req, @res + it "should set the overall theme", (done)-> + @req.body = + overallTheme: "green-ish" + @res.sendStatus = (code)=> + @user.ace.overallTheme.should.equal "green-ish" + done() + @UserController.updateUserSettings @req, @res + it "should send an error if the email is 0 len", (done)-> @req.body.email = "" @res.sendStatus = (code)->