diff --git a/services/web/app/coffee/Features/Blog/BlogController.coffee b/services/web/app/coffee/Features/Blog/BlogController.coffee index d5c5279fd8..f4c0b2b811 100644 --- a/services/web/app/coffee/Features/Blog/BlogController.coffee +++ b/services/web/app/coffee/Features/Blog/BlogController.coffee @@ -2,12 +2,13 @@ request = require("request") settings = require("settings-sharelatex") logger = require("logger-sharelatex") _ = require("underscore") +ErrorController = require "../Errors/ErrorController" extensionsToProxy = [".png", ".xml", ".jpeg", ".json", ".zip", ".eps"] module.exports = BlogController = - getPage: (req, res)-> + getPage: (req, res, next)-> url = req.url?.toLowerCase() blogUrl = "#{settings.apis.blog.url}#{url}" @@ -19,6 +20,8 @@ module.exports = BlogController = logger.log url:url, "proxying request to blog api" request.get blogUrl, (err, r, data)-> + if r?.statusCode == 404 + return ErrorController.notFound(req, res, next) data = data.trim() try data = JSON.parse(data) diff --git a/services/web/app/coffee/Features/Templates/TemplatesWebController.coffee b/services/web/app/coffee/Features/Templates/TemplatesWebController.coffee index ea0a36058a..aaca34a52c 100644 --- a/services/web/app/coffee/Features/Templates/TemplatesWebController.coffee +++ b/services/web/app/coffee/Features/Templates/TemplatesWebController.coffee @@ -70,7 +70,7 @@ module.exports = TemplatesWebController = if err? logger.err err:err, user_id:user_id, tag_name:tag_name, "something went wrong in _renderCanonicalPage" return res.send 500 - data.title = data.tag.name + data.title = data?.tag?.name res.render "templates/tag", data _getDataFromTemplatesApi: (path, callback)-> diff --git a/services/web/app/views/project/editor/file-tree.jade b/services/web/app/views/project/editor/file-tree.jade index 506fec5040..0d1b012f1f 100644 --- a/services/web/app/views/project/editor/file-tree.jade +++ b/services/web/app/views/project/editor/file-tree.jade @@ -39,11 +39,26 @@ aside#file-tree(ng-controller="FileTreeController") ) i.fa.fa-trash-o + .file-tree-inner( ng-if="rootFolder", ng-controller="FileTreeRootFolderController", ng-class="{ 'no-toolbar': !permissions.write }" ) + + div(ng-show="ui.pdfLayout == 'flat' && (ui.view == 'editor' || ui.view == 'pdf')") + ul.list-unstyled.file-tree-list + li( + ng-class="{ 'selected': ui.view == 'pdf' }" + ) + .entity + .entity-name( + ng-click="ui.view = 'pdf'" + ) + i.fa.fa-fw.toggle + i.fa.fa-fw.fa-file-pdf-o + | PDF + ul.list-unstyled.file-tree-list( droppable="permissions.write" accept=".entity-name" @@ -74,18 +89,7 @@ aside#file-tree(ng-controller="FileTreeController") span {{ entity.name }} - div(ng-show="ui.pdfLayout == 'flat' && (ui.view == 'editor' || ui.view == 'pdf')") - ul.list-unstyled.file-tree-list - li( - ng-class="{ 'selected': ui.view == 'pdf' }" - ) - .entity - .entity-name( - ng-click="ui.view = 'pdf'" - ) - i.fa.fa-fw.toggle - i.fa.fa-fw.fa-file-pdf-o - | PDF + script(type='text/ng-template', id='entityListItemTemplate') li( diff --git a/services/web/app/views/templates/template.jade b/services/web/app/views/templates/template.jade index 195658e4da..4f922fa0a9 100644 --- a/services/web/app/views/templates/template.jade +++ b/services/web/app/views/templates/template.jade @@ -8,8 +8,9 @@ block content h2 a(href="/templates") Templates | › - a(href=tag.tagPagePath) #{tag.name} - | › + - if(tag) + a(href=tag.tagPagePath) #{tag.name} + | › | #{template.name} .row .col-md-6 @@ -24,7 +25,7 @@ block content .template-details-section h3 About div !{template.description} - div(ng-controller="openInSlController") + div(ng-controller="openInSlController").download-buttons a.btn.btn-primary.btn-large(href=template.open_in_sharelatex_url, ng-click='open()', ng-disabled="isDisabled", rel='nofollow') {{openInSlText}} |   diff --git a/services/web/public/coffee/ide/hotkeys/BackspaceHighjack.coffee b/services/web/public/coffee/ide/hotkeys/BackspaceHighjack.coffee new file mode 100644 index 0000000000..b3fcf1cce1 --- /dev/null +++ b/services/web/public/coffee/ide/hotkeys/BackspaceHighjack.coffee @@ -0,0 +1,9 @@ +define [ +], () -> + rx = /INPUT|SELECT|TEXTAREA/i + + $(document).bind "keydown keypress", (e)-> + if e.which == 8 + # 8 == backspace + if !rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly + e.preventDefault() \ No newline at end of file diff --git a/services/web/public/coffee/ide/hotkeys/index.coffee b/services/web/public/coffee/ide/hotkeys/index.coffee index acc7577c6d..7de8bd990f 100644 --- a/services/web/public/coffee/ide/hotkeys/index.coffee +++ b/services/web/public/coffee/ide/hotkeys/index.coffee @@ -1,3 +1,4 @@ define [ + "ide/hotkeys/BackspaceHighjack" "ide/hotkeys/controllers/HotkeysController" ], () -> \ No newline at end of file diff --git a/services/web/public/js/ace/theme-kr.js b/services/web/public/js/ace/theme-kr.js deleted file mode 100644 index 876f23b774..0000000000 --- a/services/web/public/js/ace/theme-kr.js +++ /dev/null @@ -1,105 +0,0 @@ -ace.define("ace/theme/kr",["require","exports","module","ace/lib/dom"], function(require, exports, module) { - -exports.isDark = true; -exports.cssClass = "ace-kr"; -exports.cssText = ".ace-kr .ace_gutter {\ -background: #1c1917;\ -color: #FCFFE0\ -}\ -.ace-kr .ace_print-margin {\ -width: 1px;\ -background: #1c1917\ -}\ -.ace-kr {\ -background-color: #0B0A09;\ -color: #FCFFE0\ -}\ -.ace-kr .ace_cursor {\ -color: #FF9900\ -}\ -.ace-kr .ace_marker-layer .ace_selection {\ -background: rgba(170, 0, 255, 0.45)\ -}\ -.ace-kr.ace_multiselect .ace_selection.ace_start {\ -box-shadow: 0 0 3px 0px #0B0A09;\ -border-radius: 2px\ -}\ -.ace-kr .ace_marker-layer .ace_step {\ -background: rgb(102, 82, 0)\ -}\ -.ace-kr .ace_marker-layer .ace_bracket {\ -margin: -1px 0 0 -1px;\ -border: 1px solid rgba(255, 177, 111, 0.32)\ -}\ -.ace-kr .ace_marker-layer .ace_active-line {\ -background: #38403D\ -}\ -.ace-kr .ace_gutter-active-line {\ -background-color : #38403D\ -}\ -.ace-kr .ace_marker-layer .ace_selected-word {\ -border: 1px solid rgba(170, 0, 255, 0.45)\ -}\ -.ace-kr .ace_invisible {\ -color: rgba(255, 177, 111, 0.32)\ -}\ -.ace-kr .ace_keyword,\ -.ace-kr .ace_meta {\ -color: #949C8B\ -}\ -.ace-kr .ace_constant,\ -.ace-kr .ace_constant.ace_character,\ -.ace-kr .ace_constant.ace_character.ace_escape,\ -.ace-kr .ace_constant.ace_other {\ -color: rgba(210, 117, 24, 0.76)\ -}\ -.ace-kr .ace_invalid {\ -color: #F8F8F8;\ -background-color: #A41300\ -}\ -.ace-kr .ace_support {\ -color: #9FC28A\ -}\ -.ace-kr .ace_support.ace_constant {\ -color: #C27E66\ -}\ -.ace-kr .ace_fold {\ -background-color: #949C8B;\ -border-color: #FCFFE0\ -}\ -.ace-kr .ace_support.ace_function {\ -color: #85873A\ -}\ -.ace-kr .ace_storage {\ -color: #FFEE80\ -}\ -.ace-kr .ace_string {\ -color: rgba(164, 161, 181, 0.8)\ -}\ -.ace-kr .ace_string.ace_regexp {\ -color: rgba(125, 255, 192, 0.65)\ -}\ -.ace-kr .ace_comment {\ -font-style: italic;\ -color: #706D5B\ -}\ -.ace-kr .ace_variable {\ -color: #D1A796\ -}\ -.ace-kr .ace_list,\ -.ace-kr .ace_markup.ace_list {\ -background-color: #0F0040\ -}\ -.ace-kr .ace_variable.ace_language {\ -color: #FF80E1\ -}\ -.ace-kr .ace_meta.ace_tag {\ -color: #BABD9C\ -}\ -.ace-kr .ace_indent-guide {\ -background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYFBXV/8PAAJoAXX4kT2EAAAAAElFTkSuQmCC) right repeat-y\ -}"; - -var dom = require("../lib/dom"); -dom.importCssString(exports.cssText, exports.cssClass); -}); diff --git a/services/web/public/js/ace/theme-kr_theme.js b/services/web/public/js/ace/theme-kr_theme.js new file mode 100644 index 0000000000..8e7d8d6548 --- /dev/null +++ b/services/web/public/js/ace/theme-kr_theme.js @@ -0,0 +1,105 @@ +ace.define("ace/theme/kr_theme",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-kr-theme"; +exports.cssText = ".ace-kr-theme .ace_gutter {\ +background: #1c1917;\ +color: #FCFFE0\ +}\ +.ace-kr-theme .ace_print-margin {\ +width: 1px;\ +background: #1c1917\ +}\ +.ace-kr-theme {\ +background-color: #0B0A09;\ +color: #FCFFE0\ +}\ +.ace-kr-theme .ace_cursor {\ +color: #FF9900\ +}\ +.ace-kr-theme .ace_marker-layer .ace_selection {\ +background: rgba(170, 0, 255, 0.45)\ +}\ +.ace-kr-theme.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #0B0A09;\ +border-radius: 2px\ +}\ +.ace-kr-theme .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-kr-theme .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(255, 177, 111, 0.32)\ +}\ +.ace-kr-theme .ace_marker-layer .ace_active-line {\ +background: #38403D\ +}\ +.ace-kr-theme .ace_gutter-active-line {\ +background-color : #38403D\ +}\ +.ace-kr-theme .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(170, 0, 255, 0.45)\ +}\ +.ace-kr-theme .ace_invisible {\ +color: rgba(255, 177, 111, 0.32)\ +}\ +.ace-kr-theme .ace_keyword,\ +.ace-kr-theme .ace_meta {\ +color: #949C8B\ +}\ +.ace-kr-theme .ace_constant,\ +.ace-kr-theme .ace_constant.ace_character,\ +.ace-kr-theme .ace_constant.ace_character.ace_escape,\ +.ace-kr-theme .ace_constant.ace_other {\ +color: rgba(210, 117, 24, 0.76)\ +}\ +.ace-kr-theme .ace_invalid {\ +color: #F8F8F8;\ +background-color: #A41300\ +}\ +.ace-kr-theme .ace_support {\ +color: #9FC28A\ +}\ +.ace-kr-theme .ace_support.ace_constant {\ +color: #C27E66\ +}\ +.ace-kr-theme .ace_fold {\ +background-color: #949C8B;\ +border-color: #FCFFE0\ +}\ +.ace-kr-theme .ace_support.ace_function {\ +color: #85873A\ +}\ +.ace-kr-theme .ace_storage {\ +color: #FFEE80\ +}\ +.ace-kr-theme .ace_string {\ +color: rgba(164, 161, 181, 0.8)\ +}\ +.ace-kr-theme .ace_string.ace_regexp {\ +color: rgba(125, 255, 192, 0.65)\ +}\ +.ace-kr-theme .ace_comment {\ +font-style: italic;\ +color: #706D5B\ +}\ +.ace-kr-theme .ace_variable {\ +color: #D1A796\ +}\ +.ace-kr-theme .ace_list,\ +.ace-kr-theme .ace_markup.ace_list {\ +background-color: #0F0040\ +}\ +.ace-kr-theme .ace_variable.ace_language {\ +color: #FF80E1\ +}\ +.ace-kr-theme .ace_meta.ace_tag {\ +color: #BABD9C\ +}\ +.ace-kr-theme .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYFBXV/8PAAJoAXX4kT2EAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); \ No newline at end of file diff --git a/services/web/public/stylesheets/app/templates.less b/services/web/public/stylesheets/app/templates.less index c1463584cc..ffd3c6cf85 100644 --- a/services/web/public/stylesheets/app/templates.less +++ b/services/web/public/stylesheets/app/templates.less @@ -33,7 +33,9 @@ margin-top: 0px; } -.social_buttons { + + +.download-buttons, .social_buttons { padding-top: 20px; } @@ -47,6 +49,9 @@ } .searchResult { + h1 { + color:@link-color; + } img { max-width: 100%; height: auto; diff --git a/services/web/test/UnitTests/coffee/Blog/BlogControllerTests.coffee b/services/web/test/UnitTests/coffee/Blog/BlogControllerTests.coffee index c13a89baea..5c17f6d939 100644 --- a/services/web/test/UnitTests/coffee/Blog/BlogControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Blog/BlogControllerTests.coffee @@ -1,4 +1,3 @@ - should = require('chai').should() SandboxedModule = require('sandboxed-module') assert = require('assert') @@ -17,9 +16,11 @@ describe "BlogController", -> url:"http://blog.sharelatex.env" @request = get: sinon.stub() + @ErrorController = {} @BlogController = SandboxedModule.require modulePath, requires: "settings-sharelatex":@settings "logger-sharelatex": log:-> + "../Errors/ErrorController": @ErrorController "request": @request @req = {} @@ -41,6 +42,17 @@ describe "BlogController", -> @BlogController.getPage @req, @res + it "should send to the error controller if the blog responds 404", (done)-> + @req.url = "/blog/something.html" + @request.get.callsArgWith(1, null, {statusCode:404}) + + @ErrorController.notFound = (req, res)=> + assert.deepEqual req, @req + assert.deepEqual res, @res + done() + + @BlogController.getPage @req, @res + it "should proxy the image urls", (done)-> @BlogController._directProxy = sinon.stub() @req.url = "/something.png"