فهرست منبع

Merge branch 'master' into dcl-olsl760b

Douglas Lovell 8 سال پیش
والد
کامیت
229626a368
53فایلهای تغییر یافته به همراه422 افزوده شده و 268 حذف شده
  1. 1 0
      services/web/.gitignore
  2. 18 2
      services/web/Gruntfile.coffee
  3. 1 1
      services/web/Makefile
  4. 1 1
      services/web/app/coffee/Features/Email/EmailBuilder.coffee
  5. 15 0
      services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee
  6. 4 0
      services/web/app/coffee/Features/Newsletter/NewsletterManager.coffee
  7. 4 3
      services/web/app/coffee/Features/Project/ProjectController.coffee
  8. 4 2
      services/web/app/coffee/Features/User/UserController.coffee
  9. 17 0
      services/web/app/coffee/infrastructure/ExpressLocals.coffee
  10. 1 0
      services/web/app/coffee/models/User.coffee
  11. 3 0
      services/web/app/coffee/router.coffee
  12. 4 0
      services/web/app/views/_mixins/links.pug
  13. 1 1
      services/web/app/views/layout.pug
  14. 4 0
      services/web/app/views/project/editor.pug
  15. 1 1
      services/web/app/views/project/editor/editor.pug
  16. 1 1
      services/web/app/views/project/editor/history/diffPanelV1.pug
  17. 2 2
      services/web/app/views/project/editor/history/previewPanelV2.pug
  18. 7 0
      services/web/app/views/project/editor/history/toolbarV2.pug
  19. 20 6
      services/web/app/views/project/editor/left-menu.pug
  20. 1 63
      services/web/app/views/project/editor/pdf.pug
  21. 32 59
      services/web/app/views/project/list/modals.pug
  22. 4 3
      services/web/app/views/project/list/side-bar.pug
  23. 21 1
      services/web/config/settings.defaults.coffee
  24. 1 1
      services/web/public/coffee/ide.coffee
  25. 2 2
      services/web/public/coffee/ide/editor/directives/toggleSwitch.coffee
  26. 4 18
      services/web/public/coffee/ide/pdf/controllers/PdfController.coffee
  27. 29 4
      services/web/public/coffee/ide/settings/controllers/SettingsController.coffee
  28. 1 1
      services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee
  29. 0 4
      services/web/public/coffee/main/project-list/modal-controllers.coffee
  30. 0 58
      services/web/public/coffee/services/log-hints-feedback.coffee
  31. 0 0
      services/web/public/img/ol-brand/overleaf.svg
  32. BIN
      services/web/public/img/review-icon-sprite-ol.png
  33. BIN
      services/web/public/img/review-icon-sprite-ol@2x.png
  34. BIN
      services/web/public/img/v1-import/v2-editor.png
  35. 7 1
      services/web/public/stylesheets/app/blog-posts.less
  36. 2 1
      services/web/public/stylesheets/app/editor.less
  37. 2 2
      services/web/public/stylesheets/app/editor/chat.less
  38. 2 1
      services/web/public/stylesheets/app/editor/file-tree.less
  39. 13 3
      services/web/public/stylesheets/app/editor/history-v2.less
  40. 2 1
      services/web/public/stylesheets/app/editor/left-menu.less
  41. 15 11
      services/web/public/stylesheets/app/editor/pdf.less
  42. 9 0
      services/web/public/stylesheets/app/editor/review-panel.less
  43. 2 2
      services/web/public/stylesheets/app/editor/toolbar.less
  44. 4 0
      services/web/public/stylesheets/app/list/v1-import-modal.less
  45. 3 3
      services/web/public/stylesheets/app/project-list.less
  46. 3 3
      services/web/public/stylesheets/app/sidebar-v2-dash-pane.less
  47. 3 1
      services/web/public/stylesheets/components/navbar.less
  48. 6 1
      services/web/public/stylesheets/core/_common-variables.less
  49. 122 0
      services/web/public/stylesheets/core/ol-light-variables.less
  50. 11 2
      services/web/public/stylesheets/core/ol-variables.less
  51. 2 0
      services/web/public/stylesheets/ol-light-style.less
  52. 1 1
      services/web/test/unit/coffee/Project/ProjectControllerTests.coffee
  53. 9 1
      services/web/test/unit/coffee/User/UserControllerTests.coffee

+ 1 - 0
services/web/.gitignore

@@ -67,6 +67,7 @@ public/js/utils/
 
 
 public/stylesheets/style.css
 public/stylesheets/style.css
 public/stylesheets/ol-style.css
 public/stylesheets/ol-style.css
+public/stylesheets/ol-light-style.css
 public/stylesheets/*.map
 public/stylesheets/*.map
 public/brand/
 public/brand/
 public/minjs/
 public/minjs/

+ 18 - 2
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"
 				command:"node_modules/clean-css/bin/cleancss --s0 --source-map -o public/stylesheets/style.css public/stylesheets/style.css"
 			cssmin_ol:
 			cssmin_ol:
 				command:"node_modules/clean-css/bin/cleancss --s0 --source-map -o public/stylesheets/ol-style.css public/stylesheets/ol-style.css"
 				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:
 		forever:
 			app:
 			app:
@@ -154,6 +156,7 @@ module.exports = (grunt) ->
 					sourceMapBasepath: "public/stylesheets"
 					sourceMapBasepath: "public/stylesheets"
 					globalVars:
 					globalVars:
 						'is-overleaf': false
 						'is-overleaf': false
+						'is-overleaf-light': false
 						'show-rich-text': Settings.showRichText
 						'show-rich-text': Settings.showRichText
 				files:
 				files:
 					"public/stylesheets/style.css": "public/stylesheets/style.less"
 					"public/stylesheets/style.css": "public/stylesheets/style.less"
@@ -164,10 +167,23 @@ module.exports = (grunt) ->
 					sourceMapBasepath: "public/stylesheets"
 					sourceMapBasepath: "public/stylesheets"
 					globalVars:
 					globalVars:
 						'is-overleaf': true
 						'is-overleaf': true
+						'is-overleaf-light': false
 						'show-rich-text': Settings.showRichText
 						'show-rich-text': Settings.showRichText
 				files:
 				files:
 					"public/stylesheets/ol-style.css": "public/stylesheets/ol-style.less"
 					"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:
 		postcss:
 			options:
 			options:
 				map: 
 				map: 
@@ -178,7 +194,7 @@ module.exports = (grunt) ->
 					require('autoprefixer')({browsers: [ 'last 2 versions', 'ie >= 10' ]})
 					require('autoprefixer')({browsers: [ 'last 2 versions', 'ie >= 10' ]})
 				]
 				]
 			dist:
 			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:
 		env:
 			run:
 			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: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: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: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: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:acceptance_tests', 'Compile the acceptance tests', ['clean:acceptance_tests', 'coffee:acceptance_tests']
 	grunt.registerTask 'compile:smoke_tests', 'Compile the smoke tests', ['coffee:smoke_tests']
 	grunt.registerTask 'compile:smoke_tests', 'Compile the smoke tests', ['coffee:smoke_tests']

+ 1 - 1
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/ace.coffee \
 	public/coffee/ide/editor/sharejs/vendor/client/cm.coffee
 	public/coffee/ide/editor/sharejs/vendor/client/cm.coffee
 LESS_FILES := $(shell find public/stylesheets -name '*.less')
 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
 # The automatic variable $(@D) is the target directory name
 app.js: app.coffee
 app.js: app.coffee

+ 1 - 1
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!"
 	secondaryMessage: () -> "Thank you in advance!"
 	ctaText: () -> "Leave Feedback"
 	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({
 templates.passwordResetRequested = CTAEmailTemplate({

+ 15 - 0
services/web/app/coffee/Features/HealthCheck/HealthCheckController.coffee

@@ -5,6 +5,7 @@ rclient = RedisWrapper.client("health_check")
 settings = require("settings-sharelatex")
 settings = require("settings-sharelatex")
 logger = require "logger-sharelatex"
 logger = require "logger-sharelatex"
 domain = require "domain"
 domain = require "domain"
+UserGetter = require("../User/UserGetter")
 
 
 module.exports = HealthCheckController =
 module.exports = HealthCheckController =
 	check: (req, res, next = (error) ->) ->
 	check: (req, res, next = (error) ->) ->
@@ -37,6 +38,20 @@ module.exports = HealthCheckController =
 				res.sendStatus 500
 				res.sendStatus 500
 			else
 			else
 				res.sendStatus 200
 				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) ->
 Reporter = (res) ->
 	(runner) ->
 	(runner) ->

+ 4 - 0
services/web/app/coffee/Features/Newsletter/NewsletterManager.coffee

@@ -47,6 +47,10 @@ module.exports =
 				logger.log {oldEmail, newEmail}, 
 				logger.log {oldEmail, newEmail}, 
 					"unable to change email in newsletter, user has previously unsubscribed or new email already exist on list"
 					"unable to change email in newsletter, user has previously unsubscribed or new email already exist on list"
 				return callback(err)
 				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?
 			else if err?
 				logger.err {err, oldEmail, newEmail}, "error changing email in newsletter"
 				logger.err {err, oldEmail, newEmail}, "error changing email in newsletter"
 				return callback(err)
 				return callback(err)

+ 4 - 3
services/web/app/coffee/Features/Project/ProjectController.coffee

@@ -294,7 +294,7 @@ module.exports = ProjectController =
 			project = results.project
 			project = results.project
 			user = results.user
 			user = results.user
 			subscription = results.subscription
 			subscription = results.subscription
-
+			
 			daysSinceLastUpdated =  (new Date() - project.lastUpdated) / 86400000
 			daysSinceLastUpdated =  (new Date() - project.lastUpdated) / 86400000
 			logger.log project_id:project_id, daysSinceLastUpdated:daysSinceLastUpdated, "got db results for loading editor"
 			logger.log project_id:project_id, daysSinceLastUpdated:daysSinceLastUpdated, "got db results for loading editor"
 
 
@@ -330,7 +330,7 @@ module.exports = ProjectController =
 					}
 					}
 					userSettings: {
 					userSettings: {
 						mode  : user.ace.mode
 						mode  : user.ace.mode
-						theme : user.ace.theme
+						editorTheme : user.ace.theme
 						fontSize : user.ace.fontSize
 						fontSize : user.ace.fontSize
 						autoComplete: user.ace.autoComplete
 						autoComplete: user.ace.autoComplete
 						autoPairDelimiters: user.ace.autoPairDelimiters
 						autoPairDelimiters: user.ace.autoPairDelimiters
@@ -338,6 +338,7 @@ module.exports = ProjectController =
 						syntaxValidation: user.ace.syntaxValidation
 						syntaxValidation: user.ace.syntaxValidation
 						fontFamily: user.ace.fontFamily
 						fontFamily: user.ace.fontFamily
 						lineHeight: user.ace.lineHeight
 						lineHeight: user.ace.lineHeight
+						overallTheme: user.ace.overallTheme
 					}
 					}
 					trackChangesState: project.track_changes
 					trackChangesState: project.track_changes
 					privilegeLevel: privilegeLevel
 					privilegeLevel: privilegeLevel
@@ -346,7 +347,7 @@ module.exports = ProjectController =
 					anonymousAccessToken: req._anonymousAccessToken
 					anonymousAccessToken: req._anonymousAccessToken
 					isTokenMember: isTokenMember
 					isTokenMember: isTokenMember
 					languages: Settings.languages
 					languages: Settings.languages
-					themes: THEME_LIST
+					editorThemes: THEME_LIST
 					maxDocLength: Settings.max_doc_length
 					maxDocLength: Settings.max_doc_length
 					useV2History: !!project.overleaf?.history?.display
 					useV2History: !!project.overleaf?.history?.display
 					richTextEnabled: Features.hasFeature('rich-text')
 					richTextEnabled: Features.hasFeature('rich-text')

+ 4 - 2
services/web/app/coffee/Features/User/UserController.coffee

@@ -68,8 +68,10 @@ module.exports = UserController =
 				user.institution = req.body.institution.trim()
 				user.institution = req.body.institution.trim()
 			if req.body.mode?
 			if req.body.mode?
 				user.ace.mode = 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?
 			if req.body.fontSize?
 				user.ace.fontSize = req.body.fontSize
 				user.ace.fontSize = req.body.fontSize
 			if req.body.autoComplete?
 			if req.body.autoComplete?

+ 17 - 0
services/web/app/coffee/infrastructure/ExpressLocals.coffee

@@ -44,6 +44,7 @@ pathList = [
 	"#{jsPath}libraries.js"
 	"#{jsPath}libraries.js"
 	"/stylesheets/style.css"
 	"/stylesheets/style.css"
 	"/stylesheets/ol-style.css"
 	"/stylesheets/ol-style.css"
+	"/stylesheets/ol-light-style.css"
 ].concat(Modules.moduleAssetFiles(jsPath))
 ].concat(Modules.moduleAssetFiles(jsPath))
 
 
 if !Settings.useMinifiedJs 
 if !Settings.useMinifiedJs 
@@ -163,6 +164,14 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)->
 				return Url.resolve(staticFilesBase, hashedPath)
 				return Url.resolve(staticFilesBase, hashedPath)
 			return Url.resolve(staticFilesBase, path)
 			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)->
 		res.locals.buildImgPath = (imgFile)->
 			path = Path.join("/img/", imgFile)
 			path = Path.join("/img/", imgFile)
 			return Url.resolve(staticFilesBase, path)
 			return Url.resolve(staticFilesBase, path)
@@ -334,6 +343,14 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)->
 			renderAnnouncements        : !isOl
 			renderAnnouncements        : !isOl
 		next()
 		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) ->
 	webRouter.use (req, res, next) ->
 		res.locals.ExposedSettings =
 		res.locals.ExposedSettings =
 			isOverleaf: Settings.overleaf?
 			isOverleaf: Settings.overleaf?

+ 1 - 0
services/web/app/coffee/models/User.coffee

@@ -27,6 +27,7 @@ UserSchema = new Schema
 	ace               : {
 	ace               : {
 		mode               : {type : String, default: 'none'}
 		mode               : {type : String, default: 'none'}
 		theme              : {type : String, default: 'textmate'}
 		theme              : {type : String, default: 'textmate'}
+		overallTheme       : {type: String, default: "" }
 		fontSize           : {type : Number, default:'12'}
 		fontSize           : {type : Number, default:'12'}
 		autoComplete       : {type : Boolean, default: true}
 		autoComplete       : {type : Boolean, default: true}
 		autoPairDelimiters : {type : Boolean, default: true}
 		autoPairDelimiters : {type : Boolean, default: true}

+ 3 - 0
services/web/app/coffee/router.coffee

@@ -359,6 +359,9 @@ module.exports = class Router
 		publicApiRouter.get '/health_check/redis', HealthCheckController.checkRedis
 		publicApiRouter.get '/health_check/redis', HealthCheckController.checkRedis
 		privateApiRouter.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) ->
 		webRouter.get "/status/compiler/:Project_id", AuthorizationMiddlewear.ensureUserCanReadProject, (req, res) ->
 			project_id = req.params.Project_id
 			project_id = req.params.Project_id
 			sendRes = _.once (statusCode, message)->
 			sendRes = _.once (statusCode, message)->

+ 4 - 0
services/web/app/views/_mixins/links.pug

@@ -31,6 +31,10 @@ mixin linkContact(linkText, linkClass)
 	a(href="/contact" class=linkClass ? linkClass : '')
 	a(href="/contact" class=linkClass ? linkClass : '')
 		| #{linkText ? linkText : 'contact'}
 		| #{linkText ? linkText : 'contact'}
 
 
+mixin linkDash(linkText, linkClass)
+	a(href="/project" class=linkClass ? linkClass : '')
+		| #{linkText ? linkText : 'project dashboard'}
+
 mixin linkEducation(linkText, linkClass)
 mixin linkEducation(linkText, linkClass)
 	//- To Do: verify path
 	//- To Do: verify path
 	a(href="/plans" class=linkClass ? linkClass : '')
 	a(href="/plans" class=linkClass ? linkClass : '')

+ 1 - 1
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")
 		link(rel="mask-icon", href="/" + settings.brandPrefix + "mask-favicon.svg", color=settings.brandPrefix === 'ol-' ? "#4f9c45" : "#a93529")
 
 
 		//- Stylesheet
 		//- 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
 		block _headLinks
 
 

+ 4 - 0
services/web/app/views/project/editor.pug

@@ -173,6 +173,10 @@ block requirejs
 		window.pdfCMapsPath = "#{pdfCMapsPath}"
 		window.pdfCMapsPath = "#{pdfCMapsPath}"
 		window.uiConfig = JSON.parse('!{JSON.stringify(uiConfig).replace(/\//g, "\\/")}');
 		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(
 	script(
 		data-main=buildJsPath("ide.js", {hashedPath:false}),
 		data-main=buildJsPath("ide.js", {hashedPath:false}),
 		baseurl=fullJsPath,
 		baseurl=fullJsPath,

+ 1 - 1
services/web/app/views/project/editor/editor.pug

@@ -44,7 +44,7 @@ div.full-size(
 			ng-if="!editor.showRichText",
 			ng-if="!editor.showRichText",
 			ng-show="!!editor.sharejs_doc && !editor.opening",
 			ng-show="!!editor.sharejs_doc && !editor.opening",
 			style=richTextEnabled ? "top: 32px" : "",
 			style=richTextEnabled ? "top: 32px" : "",
-			theme="settings.theme",
+			theme="settings.editorTheme",
 			keybindings="settings.mode",
 			keybindings="settings.mode",
 			font-size="settings.fontSize",
 			font-size="settings.fontSize",
 			auto-complete="settings.autoComplete",
 			auto-complete="settings.autoComplete",

+ 1 - 1
services/web/app/views/project/editor/history/diffPanelV1.pug

@@ -20,7 +20,7 @@
 				) #{translate("restore_to_before_these_changes")}
 				) #{translate("restore_to_before_these_changes")}
 		.diff-editor.hide-ace-cursor(
 		.diff-editor.hide-ace-cursor(
 			ace-editor="history",
 			ace-editor="history",
-			theme="settings.theme",
+			theme="settings.editorTheme",
 			font-size="settings.fontSize",
 			font-size="settings.fontSize",
 			text="history.diff.text",
 			text="history.diff.text",
 			highlights="history.diff.highlights",
 			highlights="history.diff.highlights",

+ 2 - 2
services/web/app/views/project/editor/history/previewPanelV2.pug

@@ -40,7 +40,7 @@
 		.diff-editor.hide-ace-cursor(
 		.diff-editor.hide-ace-cursor(
 			ng-if="!history.diff.binary"
 			ng-if="!history.diff.binary"
 			ace-editor="history",
 			ace-editor="history",
-			theme="settings.theme",
+			theme="settings.editorTheme",
 			font-size="settings.fontSize",
 			font-size="settings.fontSize",
 			text="history.diff.text",
 			text="history.diff.text",
 			highlights="history.diff.highlights",
 			highlights="history.diff.highlights",
@@ -66,7 +66,7 @@
 		.hide-ace-cursor(
 		.hide-ace-cursor(
 			ng-if="!history.selectedFile.binary"
 			ng-if="!history.selectedFile.binary"
 			ace-editor="history-pointintime",
 			ace-editor="history-pointintime",
-			theme="settings.theme",
+			theme="settings.editorTheme",
 			font-size="settings.fontSize",
 			font-size="settings.fontSize",
 			text="history.selectedFile.text",
 			text="history.selectedFile.text",
 			read-only="true",
 			read-only="true",

+ 7 - 0
services/web/app/views/project/editor/history/toolbarV2.pug

@@ -30,6 +30,13 @@
 			i.fa.fa-exchange
 			i.fa.fa-exchange
 			|  #{translate("compare_to_another_version")}
 			|  #{translate("compare_to_another_version")}
 
 
+		button.history-toolbar-btn-danger.pull-right(
+			tooltip-html="'<p>This feature is still in progress. Please use copy and paste to restore your files.</p><p>More restore options are coming soon.</p>'"
+			tooltip-placement="bottom"
+		) 
+			i.fa.fa-undo
+			| &nbsp;#{translate("restore_to_before_these_changes")}
+
 	.history-toolbar-entries-list(
 	.history-toolbar-entries-list(
 		ng-if="!history.error"
 		ng-if="!history.error"
 	)
 	)

+ 20 - 6
services/web/app/views/project/editor/left-menu.pug

@@ -131,13 +131,27 @@ aside#left-menu.full-size(
 				)
 				)
 
 
 			.form-controls
 			.form-controls
-				label(for="theme") #{translate("theme")}
+				label(for="editorTheme") #{translate("editor_theme")}
 				select(
 				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")
 			.form-controls(ng-show="!anonymous")
 				label(for="mode") #{translate("keybindings")}
 				label(for="mode") #{translate("keybindings")}
@@ -156,7 +170,7 @@ aside#left-menu.full-size(
 					ng-model="fontSizeAsStr"
 					ng-model="fontSizeAsStr"
 					ng-model-options="{ getterSetter: true }"
 					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
 						option(value=size) #{size}px
 
 
 			.form-controls
 			.form-controls

+ 1 - 63
services/web/app/views/project/editor/pdf.pug

@@ -161,7 +161,6 @@ div.full-size.pdf(ng-controller="PdfController")
 					'alert-info':    entry.level == 'typesetting'\
 					'alert-info':    entry.level == 'typesetting'\
 				}"
 				}"
 				ng-click="openInEditor(entry)"
 				ng-click="openInEditor(entry)"
-				ng-init="feedbackSent = false; showNegFeedbackUI = false; negFeedbackReason = ''; negFeedbackReasonFreeText = ''"
 			)
 			)
 				span.line-no
 				span.line-no
 					i.fa.fa-link(aria-hidden="true")
 					i.fa.fa-link(aria-hidden="true")
@@ -179,7 +178,7 @@ div.full-size.pdf(ng-controller="PdfController")
 					p.card-hint-text(
 					p.card-hint-text(
 						ng-show="entry.humanReadableHint",
 						ng-show="entry.humanReadableHint",
 						ng-bind-html="wikiEnabled ? entry.humanReadableHint : stripHTMLFromString(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")
 						.card-hint-ext-link(ng-if="wikiEnabled && entry.extraInfoURL")
 							a(
 							a(
 								ng-href="{{ entry.extraInfoURL }}",
 								ng-href="{{ entry.extraInfoURL }}",
@@ -188,67 +187,6 @@ div.full-size.pdf(ng-controller="PdfController")
 							)
 							)
 								i.fa.fa-external-link
 								i.fa.fa-external-link
 								|&nbsp;#{translate("log_hint_extra_info")}
 								|&nbsp;#{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 &nbsp;/&nbsp;
-							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() }}
 				p.entry-content(ng-show="entry.content") {{ entry.content.trim() }}
 
 

+ 32 - 59
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
 		h3 Move Project to Overleaf v2
 
 
 	.modal-body.v1-import-wrapper
 	.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 <strong>Labelled versions</strong> yet
-						li There are <strong>no Zotero and CiteULike</strong> integrations yet
-						li Some <strong>Journals and Services in the Submit menu</strong> don't support direct submissions yet
-					p.row-spaced-small
-						| If you currently use the <strong>Overleaf Git bridge</strong> 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
+						| <strong>Direct git access to your projects</strong> 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.
 						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 <strong>no Zotero and CiteULike</strong> integrations yet
+					li Some <strong>Journals and Services in the Submit menu</strong> 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
 	.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
 			if settings.overleaf && settings.overleaf.host
 				a.btn.btn-primary.v1-import-btn(
 				a.btn.btn-primary.v1-import-btn(
 					ng-href=settings.overleaf.host + "/{{project.id}}"
 					ng-href=settings.overleaf.host + "/{{project.id}}"
+					ng-class="{disabled: v1ImportForm.inflight || v1ImportForm.response.success}"
 				) No thanks, open in v1
 				) 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"
-				)

+ 4 - 3
services/web/app/views/project/list/side-bar.pug

@@ -131,9 +131,10 @@
 			p.small #{translate("on_free_sl")}
 			p.small #{translate("on_free_sl")}
 			p
 			p
 				a(href="/user/subscription/plans").btn.btn-primary #{translate("upgrade")}
 				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.
 script.

+ 21 - 1
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:2016.1', imageDesc: 'Legacy SL TeXLive 2016'}
 	# 	{imageName: 'texlive-full:2015.1', imageDesc: 'Legacy SL TeXLive 2015'}
 	# 	{imageName: 'texlive-full:2015.1', imageDesc: 'Legacy SL TeXLive 2015'}
 	# 	{imageName: 'texlive-full:2014.2', imageDesc: 'Legacy SL TeXLive 2014.2'}
 	# 	{imageName: 'texlive-full:2014.2', imageDesc: 'Legacy SL TeXLive 2014.2'}
-	# ]
+	# ]
+
+	# 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' ]

+ 1 - 1
services/web/public/coffee/ide.coffee

@@ -185,7 +185,7 @@ define [
 			"twilight", "vibrant_ink"
 			"twilight", "vibrant_ink"
 		]
 		]
 		$scope.darkTheme = false
 		$scope.darkTheme = false
-		$scope.$watch "settings.theme", (theme) ->
+		$scope.$watch "settings.editorTheme", (theme) ->
 			if theme in DARK_THEMES
 			if theme in DARK_THEMES
 				$scope.darkTheme = true
 				$scope.darkTheme = true
 			else
 			else

+ 2 - 2
services/web/public/coffee/ide/editor/directives/toggleSwitch.coffee

@@ -14,7 +14,7 @@ define [
 
 
     <input
     <input
       type="radio"
       type="radio"
-      name="editor-mode"
+      name="toggle-switch-{{$id}}"
       class="toggle-switch-input"
       class="toggle-switch-input"
       id="toggle-switch-false-{{$id}}"
       id="toggle-switch-false-{{$id}}"
       ng-value="false"
       ng-value="false"
@@ -25,7 +25,7 @@ define [
     <input
     <input
       type="radio"
       type="radio"
       class="toggle-switch-input"
       class="toggle-switch-input"
-      name="editor-mode"
+      name="toggle-switch-{{$id}}"
       id="toggle-switch-true-{{$id}}"
       id="toggle-switch-true-{{$id}}"
       ng-value="true"
       ng-value="true"
       ng-model="ngModel"
       ng-model="ngModel"

+ 4 - 18
services/web/public/coffee/ide/pdf/controllers/PdfController.coffee

@@ -3,7 +3,6 @@ define [
 	"ace/ace"
 	"ace/ace"
 	"ide/human-readable-logs/HumanReadableLogs"
 	"ide/human-readable-logs/HumanReadableLogs"
 	"libs/bib-log-parser"
 	"libs/bib-log-parser"
-	"services/log-hints-feedback"
 ], (App, Ace, HumanReadableLogs, BibLogParser) ->
 ], (App, Ace, HumanReadableLogs, BibLogParser) ->
 	AUTO_COMPILE_MAX_WAIT = 5000
 	AUTO_COMPILE_MAX_WAIT = 5000
 	# We add a 1 second debounce to sending user changes to server if they aren't
 	# 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);
 		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
 		# enable per-user containers by default
 		perUserCompile = true
 		perUserCompile = true
 		autoCompile = true
 		autoCompile = true
@@ -42,22 +41,9 @@ define [
 				$scope.$applyAsync () ->
 				$scope.$applyAsync () ->
 					$scope.shouldDropUp = getFilesDropdownTopCoordAsRatio() > 0.65
 					$scope.shouldDropUp = getFilesDropdownTopCoordAsRatio() > 0.65
 
 
-		# log hints tracking
-		$scope.logHintsNegFeedbackValues = logHintsFeedback.feedbackOpts
-
 		$scope.trackLogHintsLearnMore = () ->
 		$scope.trackLogHintsLearnMore = () ->
 			event_tracking.sendMB "logs-hints-learn-more"
 			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
 		if ace.require("ace/lib/useragent").isMac
 			$scope.modifierKey = "Cmd"
 			$scope.modifierKey = "Cmd"
 		else
 		else
@@ -69,9 +55,9 @@ define [
 			if qs_args.length then "?" + qs_args.join("&") else ""
 			if qs_args.length then "?" + qs_args.join("&") else ""
 
 
 		$scope.stripHTMLFromString = (htmlStr) ->
 		$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", () ->
 		$scope.$on "project:joined", () ->
 			return if !autoCompile
 			return if !autoCompile

+ 29 - 4
services/web/public/coffee/ide/settings/controllers/SettingsController.coffee

@@ -1,7 +1,25 @@
 define [
 define [
 	"base"
 	"base"
 ], (App) ->
 ], (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"]
 		if $scope.settings.mode not in ["default", "vim", "emacs"]
 			$scope.settings.mode = "default"
 			$scope.settings.mode = "default"
 			
 			
@@ -19,9 +37,16 @@ define [
 				$scope.settings.fontSize = newVal
 				$scope.settings.fontSize = newVal
 			return $scope.settings.fontSize.toString()
 			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) =>
 		$scope.$watch "settings.fontSize", (fontSize, oldFontSize) =>
 			if fontSize != oldFontSize
 			if fontSize != oldFontSize

+ 1 - 1
services/web/public/coffee/main/affiliations/controllers/UserAffiliationsController.coffee

@@ -5,7 +5,7 @@ define [
 		$scope.userEmails = []
 		$scope.userEmails = []
 
 
 		LOCAL_AND_DOMAIN_REGEX = /([^@]+)@(.+)/
 		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) ->
 		_matchLocalAndDomain = (userEmailInput) ->
 			match = userEmailInput?.match LOCAL_AND_DOMAIN_REGEX
 			match = userEmailInput?.match LOCAL_AND_DOMAIN_REGEX

+ 0 - 4
services/web/public/coffee/main/project-list/modal-controllers.coffee

@@ -134,10 +134,6 @@ define [
 
 
 	App.controller 'V1ImportModalController', ($scope, $modalInstance, project) ->
 	App.controller 'V1ImportModalController', ($scope, $modalInstance, project) ->
 		$scope.project = project
 		$scope.project = project
-		$scope.step = 1
 
 
 		$scope.dismiss = () ->
 		$scope.dismiss = () ->
 			$modalInstance.dismiss('cancel')
 			$modalInstance.dismiss('cancel')
-
-		$scope.moveToConfirmation = () ->
-			$scope.step = 2

+ 0 - 58
services/web/public/coffee/services/log-hints-feedback.coffee

@@ -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

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
services/web/public/img/ol-brand/overleaf.svg


BIN
services/web/public/img/review-icon-sprite-ol.png


BIN
services/web/public/img/review-icon-sprite-ol@2x.png


BIN
services/web/public/img/v1-import/v2-editor.png


+ 7 - 1
services/web/public/stylesheets/app/blog-posts.less

@@ -11,7 +11,7 @@
     list-style: none;
     list-style: none;
     margin: 0;
     margin: 0;
     padding: 0;
     padding: 0;
-    li {
+    .blog-post {
       margin: 0 0 @margin-lg 0;
       margin: 0 0 @margin-lg 0;
     }
     }
     .card-header {
     .card-header {
@@ -38,4 +38,10 @@
       font-size: small;
       font-size: small;
     }
     }
   }
   }
+
+  pre {
+    border: 1px solid @ol-blue-gray-2;
+    border-radius: @border-radius-base;
+    padding: @padding-sm;
+  }
 }
 }

+ 2 - 1
services/web/public/stylesheets/app/editor.less

@@ -33,7 +33,7 @@
 .editor-menu-icon when (@is-overleaf = true) {
 .editor-menu-icon when (@is-overleaf = true) {
 	&.fa {
 	&.fa {
 		width: 1em;
 		width: 1em;
-		background: url(/img/ol-brand/overleaf-o-white.svg) center / contain no-repeat;
+		background: @editor-header-logo-background;
 		
 		
 		&::before {
 		&::before {
 			// Disable the font-awesome icon when in Overleaf by replacing it with a
 			// Disable the font-awesome icon when in Overleaf by replacing it with a
@@ -92,6 +92,7 @@
 .toolbar-editor {
 .toolbar-editor {
 	height: @editor-toolbar-height;
 	height: @editor-toolbar-height;
 	background-color: @editor-toolbar-bg;
 	background-color: @editor-toolbar-bg;
+	padding: 0 5px;
 	overflow: hidden;
 	overflow: hidden;
 	position: relative;
 	position: relative;
 	z-index: 10; // Prevent track changes showing over toolbar
 	z-index: 10; // Prevent track changes showing over toolbar

+ 2 - 2
services/web/public/stylesheets/app/editor/chat.less

@@ -133,12 +133,12 @@
 		height: @new-message-height;
 		height: @new-message-height;
 		background-color: @chat-new-message-bg;
 		background-color: @chat-new-message-bg;
 		padding: @line-height-computed / 4;
 		padding: @line-height-computed / 4;
-		border-top: 1px solid @editor-border-color;
+		border-top: 1px solid @chat-new-message-border-color;
 		textarea {
 		textarea {
 			overflow: auto;
 			overflow: auto;
 			resize: none;
 			resize: none;
 			border-radius: @border-radius-base;
 			border-radius: @border-radius-base;
-			border: 1px solid @editor-border-color;
+			border: 1px solid @chat-new-message-border-color;
 			height: 100%;
 			height: 100%;
 			width: 100%;
 			width: 100%;
 			color: @chat-new-message-textarea-color;
 			color: @chat-new-message-textarea-color;

+ 2 - 1
services/web/public/stylesheets/app/editor/file-tree.less

@@ -201,10 +201,11 @@
 
 
 			> .entity when (@is-overleaf = true) {
 			> .entity when (@is-overleaf = true) {
 				> .entity-name {
 				> .entity-name {
+					color: @file-tree-item-selected-color;
 					> div > i.fa,
 					> div > i.fa,
 					> i.fa,
 					> i.fa,
 					.entity-menu-toggle i.fa {
 					.entity-menu-toggle i.fa {
-						color: #FFF;
+						color: @file-tree-item-selected-color;
 					}
 					}
 					> i.fa i.linked-file-highlight {
 					> i.fa i.linked-file-highlight {
 						color: @blue;
 						color: @blue;

+ 13 - 3
services/web/public/stylesheets/app/editor/history-v2.less

@@ -12,9 +12,11 @@
 	color: @history-toolbar-color;
 	color: @history-toolbar-color;
 	padding-left: (@line-height-computed / 2);
 	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;
 	border-bottom: @toolbar-border-bottom;
 }
 }
+
 	.history-toolbar-selected-version {
 	.history-toolbar-selected-version {
 		white-space: nowrap;
 		white-space: nowrap;
 		overflow: hidden;
 		overflow: hidden;
@@ -27,15 +29,23 @@
 		}
 		}
 	.history-toolbar-actions {
 	.history-toolbar-actions {
 		flex-grow: 1;
 		flex-grow: 1;
+		flex-shrink: 0;
 	}
 	}
-		.history-toolbar-btn {
+		.history-toolbar-btn,
+		.history-toolbar-btn-danger {
 			.btn;
 			.btn;
-			.btn-info;
 			.btn-xs;
 			.btn-xs;
 			padding-left: @padding-small-horizontal;
 			padding-left: @padding-small-horizontal;
 			padding-right: @padding-small-horizontal;
 			padding-right: @padding-small-horizontal;
 			margin-right: (@line-height-computed / 2);
 			margin-right: (@line-height-computed / 2);
 		}
 		}
+		.history-toolbar-btn {
+			.btn-info;
+		}
+		.history-toolbar-btn-danger {
+			.btn-danger;
+			opacity: 0.65;
+		}
 	.history-toolbar-entries-list {
 	.history-toolbar-entries-list {
 		flex: 0 0 @changesListWidth;
 		flex: 0 0 @changesListWidth;
 		padding: 0 10px;
 		padding: 0 10px;

+ 2 - 1
services/web/public/stylesheets/app/editor/left-menu.less

@@ -100,7 +100,8 @@
 				// select.form-control {
 				// select.form-control {
 				// 	color: white;
 				// 	color: white;
 				// }
 				// }
-				label {
+				label,
+				i.fa {
 					color: white;
 					color: white;
 				}
 				}
 			}
 			}

+ 15 - 11
services/web/public/stylesheets/app/editor/pdf.less

@@ -7,7 +7,6 @@
 .pdf .toolbar.toolbar-pdf when (@is-overleaf = true) {
 .pdf .toolbar.toolbar-pdf when (@is-overleaf = true) {
 	.toolbar-small-mixin;
 	.toolbar-small-mixin;
 	.toolbar-alt-mixin;
 	.toolbar-alt-mixin;
-	border-bottom: 0;
 	padding-right: 5px;
 	padding-right: 5px;
 	&.uncompiled-changes {
 	&.uncompiled-changes {
 		#gradient > .striped(@color: rgba(255,255,255,.10), @angle: -45deg);
 		#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) {
 .pdf .toolbar.toolbar-pdf when (@is-overleaf = false) {
 	.toolbar-tall-mixin;
 	.toolbar-tall-mixin;
 	padding: 0 (@line-height-computed / 2);
 	padding: 0 (@line-height-computed / 2);
@@ -305,25 +309,25 @@
 		line-height: 1.3;
 		line-height: 1.3;
 		padding: 0 2px;
 		padding: 0 2px;
 	}
 	}
-	
+
 	.synctex-control-goto-pdf > .synctex-control-icon when (@is-overleaf = true) {
 	.synctex-control-goto-pdf > .synctex-control-icon when (@is-overleaf = true) {
 		text-indent: 1px; // "Optical" adjustment.
 		text-indent: 1px; // "Optical" adjustment.
 		&::before {
 		&::before {
-			content: "\f061";		
+			content: "\f061";
 		}
 		}
 	}
 	}
 	.synctex-control-goto-code > .synctex-control-icon when (@is-overleaf = true) {
 	.synctex-control-goto-code > .synctex-control-icon when (@is-overleaf = true) {
 		text-indent: -1px; // "Optical" adjustment.
 		text-indent: -1px; // "Optical" adjustment.
 		&::before {
 		&::before {
-			content: "\f060";		
+			content: "\f060";
 		}
 		}
 	}
 	}
-	
+
 	.synctex-control-goto-pdf > .synctex-control-icon::before when (@is-overleaf = false) {
 	.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) {
 	.synctex-control-goto-code > .synctex-control-icon::before when (@is-overleaf = false) {
-		content: "\f177";		
+		content: "\f177";
 	}
 	}
 
 
 .editor-dark {
 .editor-dark {
@@ -401,7 +405,7 @@
 
 
 	}
 	}
 
 
-	&-text, 
+	&-text,
 	&-feedback-label {
 	&-feedback-label {
 		color: @log-hints-color;
 		color: @log-hints-color;
 		font-size: 0.9rem;
 		font-size: 0.9rem;
@@ -424,8 +428,8 @@
 		display: inline-block;
 		display: inline-block;
 		font-size: 0.8rem;
 		font-size: 0.8rem;
 	}
 	}
-	
-	&-actions a,
+
+	&-footer a,
 	&-text a {
 	&-text a {
 		.alert-danger & {
 		.alert-danger & {
 			color: @state-danger-text;
 			color: @state-danger-text;
@@ -492,7 +496,7 @@
 .plv-text-layer {
 .plv-text-layer {
 	display: none;
 	display: none;
 	user-select: text;
 	user-select: text;
-	
+
 	.pdf-page-container:hover &,
 	.pdf-page-container:hover &,
 	.pdfjs-viewer-show-text & {
 	.pdfjs-viewer-show-text & {
 		display: block;
 		display: block;

+ 9 - 0
services/web/public/stylesheets/app/editor/review-panel.less

@@ -949,6 +949,7 @@
 	display: inline-block;
 	display: inline-block;
 	background: url('/img/review-icon-sprite-ol.png') top/30px no-repeat;
 	background: url('/img/review-icon-sprite-ol.png') top/30px no-repeat;
 	width: 30px;
 	width: 30px;
+	background-position-y: -30px;
 
 
 	&::before {
 	&::before {
 		content: '\00a0'; // Non-breakable space. A non-breakable character here makes this icon work like font-awesome.
 		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 {
 .resolved-comments-toggle {
 	font-size: 14px;
 	font-size: 14px;
 	color: lighten(@rp-type-blue, 25%);
 	color: lighten(@rp-type-blue, 25%);

+ 2 - 2
services/web/public/stylesheets/app/editor/toolbar.less

@@ -58,7 +58,7 @@
 	.btn-full-height {
 	.btn-full-height {
 		border: none;
 		border: none;
 		border-radius: 0;
 		border-radius: 0;
-		border-right: 1px solid @toolbar-border-color;
+		border-right: 1px solid @toolbar-header-btn-border-color;
 		color: @toolbar-btn-color;
 		color: @toolbar-btn-color;
 		padding: 3px 10px 5px;
 		padding: 3px 10px 5px;
 		font-size: 20px;
 		font-size: 20px;
@@ -96,7 +96,7 @@
 		justify-content: flex-end;
 		justify-content: flex-end;
 		.btn-full-height {
 		.btn-full-height {
 			border-right: 0;
 			border-right: 0;
-			border-left: 1px solid @toolbar-border-color;
+			border-left: 1px solid @toolbar-header-btn-border-color;
 		}
 		}
 	}
 	}
 
 

+ 4 - 0
services/web/public/stylesheets/app/list/v1-import-modal.less

@@ -17,6 +17,10 @@
 		margin-bottom: 0;
 		margin-bottom: 0;
 	}
 	}
 
 
+.v1-import-col--left {
+	flex-shrink: 1.1;
+}
+
 .v1-import-img {
 .v1-import-img {
 	width: 100%;
 	width: 100%;
 	margin-top: 30px;
 	margin-top: 30px;

+ 3 - 3
services/web/public/stylesheets/app/project-list.less

@@ -169,10 +169,10 @@ ul.folders-menu {
 		border-radius: @sidebar-active-border-radius;
 		border-radius: @sidebar-active-border-radius;
 		> a {
 		> a {
 			background-color: @sidebar-active-bg;
 			background-color: @sidebar-active-bg;
-			font-weight: 700;
-			color: white;
+			font-weight: @sidebar-active-font-weight;
+			color: @sidebar-active-color;
 			.subdued {
 			.subdued {
-				color: white;
+				color: @sidebar-active-color;
 			}
 			}
 		}
 		}
 	}
 	}

+ 3 - 3
services/web/public/stylesheets/app/sidebar-v2-dash-pane.less

@@ -17,7 +17,7 @@
 	flex-shrink: 0;
 	flex-shrink: 0;
 	text-align: center;
 	text-align: center;
 	background-color: @v2-dash-pane-bg;
 	background-color: @v2-dash-pane-bg;
-	color: white;
+	color: @v2-dash-pane-color;
 	font-size: 13px;
 	font-size: 13px;
 	padding: @line-height-computed / 2;
 	padding: @line-height-computed / 2;
 }
 }
@@ -32,10 +32,10 @@
 	}
 	}
 
 
 		.project-list-sidebar-v2-pane-toggle {
 		.project-list-sidebar-v2-pane-toggle {
-			color: white;
+			color: @v2-dash-pane-toggle-color;
 			padding: 0;
 			padding: 0;
 			line-height: 1;
 			line-height: 1;
 			&:hover, &:active, &:focus {
 			&:hover, &:active, &:focus {
-				color: white;
+				color: @v2-dash-pane-toggle-color;
 			}
 			}
 		}
 		}

+ 3 - 1
services/web/public/stylesheets/components/navbar.less

@@ -436,6 +436,7 @@
       font-weight: @navbar-btn-font-weight;
       font-weight: @navbar-btn-font-weight;
       line-height: @navbar-btn-line-height;
       line-height: @navbar-btn-line-height;
       padding: @navbar-btn-padding;
       padding: @navbar-btn-padding;
+      background-color: @navbar-default-link-bg;
 
 
       &:hover,
       &:hover,
       &:focus {
       &:focus {
@@ -466,6 +467,7 @@
       color: @navbar-subdued-color;
       color: @navbar-subdued-color;
       padding: @navbar-subdued-padding;
       padding: @navbar-subdued-padding;
       margin-left: 0;
       margin-left: 0;
+      background-color: transparent;
       &:hover {
       &:hover {
         color: @navbar-subdued-hover-color;
         color: @navbar-subdued-hover-color;
         background-color: @navbar-subdued-hover-bg;
         background-color: @navbar-subdued-hover-bg;
@@ -478,7 +480,7 @@
 
 
     @media (min-width: @grid-float-breakpoint) {
     @media (min-width: @grid-float-breakpoint) {
       > li > a {
       > li > a {
-        border-color: @navbar-default-link-color;
+        border-color: @navbar-default-link-border-color;
         margin-left: 1rem;
         margin-left: 1rem;
       }
       }
     }
     }

+ 6 - 1
services/web/public/stylesheets/core/_common-variables.less

@@ -327,6 +327,7 @@
 
 
 // Navbar links
 // Navbar links
 @navbar-default-link-color:                @link-color;
 @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-color:          @link-hover-color;
 @navbar-default-link-hover-bg:             @link-hover-color;
 @navbar-default-link-hover-bg:             @link-hover-color;
 @navbar-default-link-active-color:         #fff;
 @navbar-default-link-active-color:         #fff;
@@ -796,6 +797,7 @@
 @left-menu-animation-duration: 0.35s;
 @left-menu-animation-duration: 0.35s;
 
 
 @toolbar-border-color: @gray-lighter;
 @toolbar-border-color: @gray-lighter;
+@toolbar-header-btn-border-color: @toolbar-border-color;
 @common-border-color: @gray-lighter;
 @common-border-color: @gray-lighter;
 @editor-border-color: @gray-lighter;
 @editor-border-color: @gray-lighter;
 @file-tree-droppable-bg-color: rgb(252, 231, 199);
 @file-tree-droppable-bg-color: rgb(252, 231, 199);
@@ -834,7 +836,7 @@
 
 
 @dropdown-divider-margin    :((@line-height-computed / 2) - 1) 0;
 @dropdown-divider-margin    :((@line-height-computed / 2) - 1) 0;
 @dropdown-item-padding      : 3px 20px;
 @dropdown-item-padding      : 3px 20px;
-
+@navbar-default-link-bg     : transparent;
 
 
 // Button colors and sizing
 // Button colors and sizing
 @btn-border-radius-large : @border-radius-large;
 @btn-border-radius-large : @border-radius-large;
@@ -859,6 +861,8 @@
 @sidebar-link-color            : #333;
 @sidebar-link-color            : #333;
 @sidebar-active-border-radius  : @border-radius-small;
 @sidebar-active-border-radius  : @border-radius-small;
 @sidebar-active-bg             : @link-color;
 @sidebar-active-bg             : @link-color;
+@sidebar-active-color          : #FFF;
+@sidebar-active-font-weight    : 700;
 @sidebar-hover-bg              : transparent;
 @sidebar-hover-bg              : transparent;
 @sidebar-hover-text-decoration : underline;
 @sidebar-hover-text-decoration : underline;
 
 
@@ -966,6 +970,7 @@
 @chat-new-message-bg              : @gray-lightest;
 @chat-new-message-bg              : @gray-lightest;
 @chat-new-message-textarea-bg     : #FFF;
 @chat-new-message-textarea-bg     : #FFF;
 @chat-new-message-textarea-color  : @gray-dark;
 @chat-new-message-textarea-color  : @gray-dark;
+@chat-new-message-border-color    : @editor-border-color;
 
 
 // PDF
 // PDF
 @pdf-top-offset                  : @toolbar-tall-height;
 @pdf-top-offset                  : @toolbar-tall-height;

+ 122 - 0
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;

+ 11 - 2
services/web/public/stylesheets/core/ol-variables.less

@@ -6,7 +6,7 @@
 @footer-height: 50px;
 @footer-height: 50px;
 
 
 // Styleguide colors
 // Styleguide colors
-@ol-blue-gray-0 : #f4f5f8;
+@ol-blue-gray-0 : #F4F5F8;
 @ol-blue-gray-1 : #E4E8EE;
 @ol-blue-gray-1 : #E4E8EE;
 @ol-blue-gray-2 : #9DA7B7;
 @ol-blue-gray-2 : #9DA7B7;
 @ol-blue-gray-3 : #5D6879;
 @ol-blue-gray-3 : #5D6879;
@@ -33,7 +33,7 @@
 @navbar-default-bg        : @ol-blue-gray-6;
 @navbar-default-bg        : @ol-blue-gray-6;
 @navbar-default-border    : transparent;
 @navbar-default-border    : transparent;
 @navbar-brand-image-url   : url(/img/ol-brand/overleaf-white.svg);
 @navbar-brand-image-url   : url(/img/ol-brand/overleaf-white.svg);
-
+@navbar-default-link-bg   : transparent;
 // Backgrounds
 // Backgrounds
 @body-bg                : #FFF;
 @body-bg                : #FFF;
 @content-alt-bg-color   : @ol-blue-gray-1;
 @content-alt-bg-color   : @ol-blue-gray-1;
@@ -110,6 +110,7 @@
 @navbar-default-padding-h         : 10px;
 @navbar-default-padding-h         : 10px;
 @navbar-default-padding           : @navbar-default-padding-v @navbar-default-padding-h;
 @navbar-default-padding           : @navbar-default-padding-v @navbar-default-padding-h;
 @navbar-default-link-color        : #FFF;
 @navbar-default-link-color        : #FFF;
+@navbar-default-link-border-color : @navbar-default-link-color;
 @navbar-default-link-hover-bg     : @ol-green;
 @navbar-default-link-hover-bg     : @ol-green;
 @navbar-default-link-active-bg    : @ol-green;
 @navbar-default-link-active-bg    : @ol-green;
 @navbar-default-link-hover-color  : @ol-green;
 @navbar-default-link-hover-color  : @ol-green;
@@ -149,10 +150,14 @@
 @sidebar-link-color             : #FFF;
 @sidebar-link-color             : #FFF;
 @sidebar-active-border-radius   : 0;
 @sidebar-active-border-radius   : 0;
 @sidebar-active-bg              : @ol-blue-gray-6;
 @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-bg               : @ol-blue-gray-4;
 @sidebar-hover-text-decoration  : none;
 @sidebar-hover-text-decoration  : none;
 @v2-dash-pane-bg                : @ol-blue-gray-4;
 @v2-dash-pane-bg                : @ol-blue-gray-4;
 @v2-dash-pane-link-color        : #FFF;
 @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-bg            : @ol-blue-gray-5;
 @v2-dash-pane-btn-hover-bg      : @ol-blue-gray-6;
 @v2-dash-pane-btn-hover-bg      : @ol-blue-gray-6;
 
 
@@ -214,6 +219,7 @@
 @toolbar-btn-active-bg-color      : @ol-green;
 @toolbar-btn-active-bg-color      : @ol-green;
 @toolbar-btn-active-shadow        : none;
 @toolbar-btn-active-shadow        : none;
 @toolbar-border-color             : @ol-blue-gray-5;
 @toolbar-border-color             : @ol-blue-gray-5;
+@toolbar-header-btn-border-color  : @toolbar-border-color;
 @toolbar-alt-bg-color             : @ol-blue-gray-5;
 @toolbar-alt-bg-color             : @ol-blue-gray-5;
 @toolbar-icon-btn-color           : #FFF;
 @toolbar-icon-btn-color           : #FFF;
 @toolbar-icon-btn-hover-color     : #FFF;
 @toolbar-icon-btn-hover-color     : #FFF;
@@ -230,6 +236,7 @@
 @file-tree-bg                   : @ol-blue-gray-4;
 @file-tree-bg                   : @ol-blue-gray-4;
 @file-tree-line-height          : 2.05;
 @file-tree-line-height          : 2.05;
 @file-tree-item-color           : #FFF;
 @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-input-color     : @ol-blue-gray-5;
 @file-tree-item-toggle-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-icon-color      : @ol-blue-gray-2;
@@ -276,6 +283,7 @@
 @chat-new-message-bg              : @ol-blue-gray-4;
 @chat-new-message-bg              : @ol-blue-gray-4;
 @chat-new-message-textarea-bg     : @ol-blue-gray-1;
 @chat-new-message-textarea-bg     : @ol-blue-gray-1;
 @chat-new-message-textarea-color  : @ol-blue-gray-6;
 @chat-new-message-textarea-color  : @ol-blue-gray-6;
+@chat-new-message-border-color    : @editor-border-color;
 
 
 // Pagination
 // Pagination
 @pagination-active-bg             : @ol-dark-green;
 @pagination-active-bg             : @ol-dark-green;
@@ -357,6 +365,7 @@
 @brand-warning:         @orange;
 @brand-warning:         @orange;
 @brand-danger:          @ol-red;
 @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-padding-top: 115.44%;
 @editor-loading-logo-background-url: url(/img/ol-brand/overleaf-o-grey.svg);
 @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);
 @editor-loading-logo-foreground-url: url(/img/ol-brand/overleaf-o.svg);

+ 2 - 0
services/web/public/stylesheets/ol-light-style.less

@@ -0,0 +1,2 @@
+@import "ol-style.less";
+@import "core/ol-light-variables.less";

+ 1 - 1
services/web/test/unit/coffee/Project/ProjectControllerTests.coffee

@@ -524,7 +524,7 @@ describe "ProjectController", ->
 		it "should add on userSettings", (done)->
 		it "should add on userSettings", (done)->
 			@res.render = (pageName, opts)=>
 			@res.render = (pageName, opts)=>
 				opts.userSettings.fontSize.should.equal @user.ace.fontSize
 				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()
 				done()
 			@ProjectController.loadEditor @req, @res
 			@ProjectController.loadEditor @req, @res
 
 

+ 9 - 1
services/web/test/unit/coffee/User/UserControllerTests.coffee

@@ -224,12 +224,20 @@ describe "UserController", ->
 
 
 		it "should set some props on ace", (done)->
 		it "should set some props on ace", (done)->
 			@req.body =
 			@req.body =
-				theme: "something"
+				editorTheme: "something"
 			@res.sendStatus = (code)=>
 			@res.sendStatus = (code)=>
 				@user.ace.theme.should.equal "something"
 				@user.ace.theme.should.equal "something"
 				done()
 				done()
 			@UserController.updateUserSettings @req, @res
 			@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)->
 		it "should send an error if the email is 0 len", (done)->
 			@req.body.email = ""
 			@req.body.email = ""
 			@res.sendStatus = (code)->
 			@res.sendStatus = (code)->

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است