diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee index 764ae8afd6..0e550f6714 100644 --- a/services/web/app/coffee/router.coffee +++ b/services/web/app/coffee/router.coffee @@ -217,6 +217,11 @@ module.exports = class Router require("./models/Project").Project.findOne {}, () -> throw new Error("Test error") + app.post '/error/client', (req, res, next) -> + console.log req.body + logger.error err: req.body.error, meta: req.body.meta, "client side error" + res.send(204) + app.get '*', HomeController.notFound diff --git a/services/web/app/views/layout.jade b/services/web/app/views/layout.jade index 50d595cd89..396d8a4cb1 100644 --- a/services/web/app/views/layout.jade +++ b/services/web/app/views/layout.jade @@ -22,6 +22,9 @@ html(itemscope, itemtype='http://schema.org/Product') })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', '#{gaToken}', 'sharelatex.com'); ga('send', 'pageview'); + - else + script(type='text/javascript') + window.ga = function() {}; script window.csrfToken = "#{csrfToken}"; diff --git a/services/web/app/views/modals.jade b/services/web/app/views/modals.jade index ffd110760f..ef85ce7da9 100644 --- a/services/web/app/views/modals.jade +++ b/services/web/app/views/modals.jade @@ -77,15 +77,6 @@ .modal-body span.message -#genericServerErrorModal(style='display: none') - .modal - .modal-header - h3 There was a problem talking to the server - .modal-body - span.message Sorry, we couldn't complete your request right now. Please wait a few moments and try again. If the problem persists, please let us know. - .modal-footer - button.btn.btn-primary.cancel Ok - #projectUploadModal(style='display: none') .modal .modal-header diff --git a/services/web/app/views/templates.jade b/services/web/app/views/templates.jade index 586719a62d..4255d19b27 100644 --- a/services/web/app/views/templates.jade +++ b/services/web/app/views/templates.jade @@ -136,16 +136,6 @@ #subscribeForm .modal-footer - - script(type="text/template")#genericModalTemplateWithButton - .modal - .modal-header - h3 {{ title }} - .modal-body - .message {{ message }} - .modal-footer - button.btn.btn-primary ok - script(type="text/template")#genericModalButtonTemplate button(class="btn {{ class }}") {{ text }} diff --git a/services/web/public/coffee/editor/Document.coffee b/services/web/public/coffee/editor/Document.coffee index 41cf1f7e11..d08d4baca4 100644 --- a/services/web/public/coffee/editor/Document.coffee +++ b/services/web/public/coffee/editor/Document.coffee @@ -136,16 +136,18 @@ define [ @unBindFromSocketEvents() _bindToShareJsDocEvents: () -> - @doc.on "error", (error) => @_onError error + @doc.on "error", (error, meta) => @_onError error, meta @doc.on "externalUpdate", () => @trigger "externalUpdate" @doc.on "remoteop", () => @trigger "remoteop" @doc.on "op:sent", () => @trigger "op:sent" @doc.on "op:acknowledged", () => @trigger "op:acknowledged" - _onError: (error) -> - console.error "ShareJS error", error - ga('send', 'event', 'error', "shareJsError", "#{error.message} - #{ide.socket.socket.transport.name}" ) + _onError: (error, meta = {}) -> + console.error "ShareJS error", error, meta + ga?('send', 'event', 'error', "shareJsError", "#{error.message} - #{ide.socket.socket.transport.name}" ) @ide.socket.disconnect() + meta.doc_id = @doc_id + @ide.reportError(error, meta) @doc?.clearInflightAndPendingOps() @_cleanUp() @trigger "error", error diff --git a/services/web/public/coffee/editor/ShareJsDoc.coffee b/services/web/public/coffee/editor/ShareJsDoc.coffee index e887ddf588..60344ad235 100644 --- a/services/web/public/coffee/editor/ShareJsDoc.coffee +++ b/services/web/public/coffee/editor/ShareJsDoc.coffee @@ -95,13 +95,13 @@ define [ INFLIGHT_OP_TIMEOUT: 10000 _startInflightOpTimeout: (update) -> timer = setTimeout () => - @_handleError "Doc op was not acknowledged in time" + @_handleError new Error("Doc op was not acknowledged in time"), v: update.v , @INFLIGHT_OP_TIMEOUT @_doc.inflightCallbacks.push () => clearTimeout timer - _handleError: (error) -> - @trigger "error", error + _handleError: (error, meta = {}) -> + @trigger "error", error, meta _bindToDocChanges: (doc) -> submitOp = doc.submitOp diff --git a/services/web/public/coffee/ide.coffee b/services/web/public/coffee/ide.coffee index e98163f87d..fcc9d3ef4f 100644 --- a/services/web/public/coffee/ide.coffee +++ b/services/web/public/coffee/ide.coffee @@ -48,7 +48,7 @@ define [ SearchManager, Project, User, - StandaloneModal, + Modal, FileTreeManager, MessageManager, HelpManager, @@ -144,16 +144,33 @@ define [ setTimeout(joinProject, 100) showErrorModal: (title, message)-> - modalOptions = - templateId:'genericModalTemplate' - isStatic: false + new Modal { title: title - message:message - new Modal modalOptions + message: message + buttons: [ text: "OK" ] + } - showGenericServerErrorMessage: (message)-> - new Modal - templateId : "genericServerErrorModal" + showGenericServerErrorMessage: ()-> + new Modal { + title: "There was a problem talking to the server" + message: "Sorry, we couldn't complete your request right now. Please wait a few moments and try again. If the problem persists, please let us know." + buttons: [ text: "OK" ] + } + + reportError: (error, meta = {}) -> + meta.client_id = @socket.socket.sessionid + errorObj = {} + for key in Object.getOwnPropertyNames(error) + errorObj[key] = error[key] + $.ajax + url: "/error/client" + type: "POST" + data: JSON.stringify + error: errorObj + meta: meta + contentType: "application/json; charset=utf-8" + headers: + "X-Csrf-Token": window.csrfToken setLoadingMessage: (message) -> $("#loadingMessage").text(message) @@ -171,45 +188,6 @@ define [ ide.layoutManager.resizeAllSplitters() ide.tourManager = new IdeTour ide - class Modal - #templateId, title, message, isStatic, cancelCallback - constructor: (options, completeCallback = () -> {})-> - html = $("##{options.templateId}").html() - modal = "
" - $('body').append(modal) - $modal = $('#modal') - - if options.title? - $modal.find('h3').text(options.title) - if options.message? - $modal.find('.message').text(options.message) - if options.inputValue? - $modal.find('input').val(options.inputValue) - - backdrop = true - if options.backdrop? - backdrop = options.backdrop - - $modal.modal backdrop:backdrop, show:true, keyboard:true, isStatic:options.isStatic - $modal.find('input').focus() - - $modal.find('button').click (e)=> - e.preventDefault() - $modal.modal('hide') - if e.target.className.indexOf("cancel") == -1 - inputval = $modal.find('input').val() - completeCallback(inputval) - - $modal.find('input').keydown (event)=> - code = event.keyCode || event.which - if code == 13 - $modal.find('button.primary').click() - - $modal.bind 'hide', ()-> - if options.cancelCallback? - options.cancelCallback() - $('#modal').remove() - ide.savingAreaManager = $savingArea : $('#saving-area') timeOut: undefined @@ -220,7 +198,7 @@ define [ return if @timeOut? @clearTimeout() @timeOut = setTimeout((=> - ga('send', 'event', 'editor-interaction', 'notification-shown', "saving") + ga?('send', 'event', 'editor-interaction', 'notification-shown', "saving") $("#savingProblems").show() ), 1000)