diff --git a/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee b/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
index ebaaec8d7e..6de2ce7110 100644
--- a/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
+++ b/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
@@ -16,9 +16,9 @@ module.exports = AuthenticationController =
if !isAllowed
logger.log email:email, "too many login requests"
res.statusCode = 429
- return res.send
+ return res.send
message:
- text: 'This account has had too many login requests,
please wait 2 minutes before trying to log in again',
+ text: 'This account has had too many login requests. Please wait 2 minutes before trying to log in again',
type: 'error'
AuthenticationManager.authenticate email: email, password, (error, user) ->
return next(error) if error?
@@ -100,7 +100,7 @@ module.exports = AuthenticationController =
callback()
_establishUserSession: (req, user, callback = (error) ->) ->
- lightUser =
+ lightUser =
_id: user._id
first_name: user.first_name
last_name: user.last_name
@@ -110,7 +110,3 @@ module.exports = AuthenticationController =
req.session.user = lightUser
req.session.justLoggedIn = true
req.session.save callback
-
-
-
-
diff --git a/services/web/app/views/project/editor/file-tree.jade b/services/web/app/views/project/editor/file-tree.jade
index d54af53327..8983994438 100644
--- a/services/web/app/views/project/editor/file-tree.jade
+++ b/services/web/app/views/project/editor/file-tree.jade
@@ -1,5 +1,5 @@
aside#file-tree(ng-controller="FileTreeController")
- .toolbar.toolbar-small(ng-if="permissions.write")
+ .toolbar.toolbar-small.toolbar-alt(ng-if="permissions.write")
a(
href,
ng-click="openNewDocModal()",
@@ -40,7 +40,7 @@ aside#file-tree(ng-controller="FileTreeController")
i.fa.fa-trash-o
.file-tree-inner(
- ng-if="rootFolder",
+ ng-if="rootFolder",
ng-controller="FileTreeRootFolderController",
ng-class="{ 'no-toolbar': !permissions.write }"
)
@@ -284,7 +284,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
permissions="permissions",
ng-repeat="child in entity.children | orderBy:[orderByFoldersFirst, 'name']"
)
-
+
script(type='text/ng-template', id='newDocModalTemplate')
.modal-header
h3 New File
diff --git a/services/web/app/views/project/editor/track-changes.jade b/services/web/app/views/project/editor/track-changes.jade
index 936bb58313..40b16231e9 100644
--- a/services/web/app/views/project/editor/track-changes.jade
+++ b/services/web/app/views/project/editor/track-changes.jade
@@ -80,22 +80,41 @@ div#trackChanges(ng-show="ui.view == 'track-changes'")
i.fa.fa-spin.fa-refresh
| Loading...
- .diff.full-size(ng-controller="TrackChangesDiffController")
- .diff-editor.hide-ace-cursor(
- ace-editor="track-changes",
- ng-show="!!trackChanges.diff && !trackChanges.diff.loading && !trackChanges.diff.deleted && !trackChanges.diff.error",
- theme="settings.theme",
- font-size="settings.fontSize",
- text="trackChanges.diff.text",
- highlights="trackChanges.diff.highlights",
- read-only="true",
- resize-on="layout:main:resize"
+ .diff-panel.full-size(ng-controller="TrackChangesDiffController")
+ .diff(
+ ng-show="!!trackChanges.diff && !trackChanges.diff.loading && !trackChanges.diff.deleted && !trackChanges.diff.error"
)
+ .toolbar.toolbar-alt
+ span.name
+ | {{trackChanges.diff.highlights.length}}
+ ng-pluralize(
+ count="trackChanges.diff.highlights.length",
+ when="{\
+ 'one': 'change',\
+ 'other': 'changes'\
+ }"
+ )
+ | in {{trackChanges.diff.doc.name}}
+ .toolbar-right
+ a.btn.btn-danger.btn-sm(
+ href,
+ ng-click="openRestoreDiffModal()"
+ ) Restore to before these changes
+ .diff-editor.hide-ace-cursor(
+ ace-editor="track-changes",
+ theme="settings.theme",
+ font-size="settings.fontSize",
+ text="trackChanges.diff.text",
+ highlights="trackChanges.diff.highlights",
+ read-only="true",
+ resize-on="layout:main:resize",
+ navigate-highlights="true"
+ )
.diff-deleted.text-centered(
ng-show="trackChanges.diff.deleted"
)
p.text-serif {{ trackChanges.diff.doc.name }} has been deleted.
- p
+ p
a.btn.btn-primary.btn-lg(
href,
ng-click="restoreDeletedDoc()"
@@ -104,4 +123,26 @@ div#trackChanges(ng-show="ui.view == 'track-changes'")
i.fa.fa-spin.fa-refresh
| Loading...
.error-panel(ng-show="trackChanges.diff.error")
- .alert.alert-danger Sorry, something went wrong :(
\ No newline at end of file
+ .alert.alert-danger Sorry, something went wrong :(
+
+script(type="text/ng-template", id="trackChangesRestoreDiffModalTemplate")
+ .modal-header
+ button.close(
+ type="button"
+ data-dismiss="modal"
+ ng-click="cancel()"
+ ) ×
+ h3 Restore {{diff.doc.name}}
+ .modal-body.modal-body-share
+ p Are you sure you want to restore {{diff.doc.name}} to before the changes on {{diff.start_ts | formatDate}}?
+ .modal-footer
+ button.btn.btn-default(
+ ng-click="cancel()",
+ ng-disabled="state.inflight"
+ ) Cancel
+ button.btn.btn-danger(
+ ng-click="restore()",
+ ng-disabled="state.inflight"
+ )
+ span(ng-show="!state.inflight") Restore
+ span(ng-show="state.inflight") Restoring...
diff --git a/services/web/app/views/user/login.jade b/services/web/app/views/user/login.jade
index cc3d3b099b..c0b8827d89 100644
--- a/services/web/app/views/user/login.jade
+++ b/services/web/app/views/user/login.jade
@@ -35,7 +35,9 @@ block content
| Required
.actions
button.btn-primary.btn(
- type='submit'
- ng-disabled="loginForm.$invalid"
- ) Login
+ type='submit',
+ ng-disabled="loginForm.inflight"
+ )
+ span(ng-show="!loginForm.inflight") Login
+ span(ng-show="loginForm.inflight") Logging in...
a.pull-right(href='/user/password/reset') Forgot your password?
diff --git a/services/web/app/views/user/register.jade b/services/web/app/views/user/register.jade
index ed180047f3..da6f5064a7 100644
--- a/services/web/app/views/user/register.jade
+++ b/services/web/app/views/user/register.jade
@@ -10,7 +10,7 @@ block content
div Join ShareLaTeX to view this project
else if newTemplateData.templateName !== undefined
h1 Please register to edit the '#{newTemplateData.templateName}' template
- div Already have a ShareLaTeX account?
+ div Already have a ShareLaTeX account?
a(href="/login") Login here
.row
@@ -18,12 +18,12 @@ block content
.card
.page-header
h1 Register
- form(async-form="register", name="registerForm", action="/register", novalidate, ng-cloak)
+ form(async-form="register", name="registerForm", action="/register", ng-cloak)
input(name='_csrf', type='hidden', value=csrfToken)
input(name='redir', type='hidden', value=redir)
form-messages(for="registerForm")
.form-group
- label(for='email') Email
+ label(for='email') Email
input.form-control(
type='email',
name='email',
@@ -36,7 +36,7 @@ block content
span.small.text-primary(ng-show="registerForm.email.$invalid && registerForm.email.$dirty")
| Must be an email address
.form-group
- label(for='password') Password
+ label(for='password') Password
input.form-control(
type='password',
name='password',
@@ -49,6 +49,7 @@ block content
.actions
button.btn-primary.btn(
type='submit'
- ng-disabled="register.$invalid"
- ) Register
-
+ ng-disabled="registerForm.inflight"
+ )
+ span(ng-show="!registerForm.inflight") Register
+ span(ng-show="registerForm.inflight") Registering...
diff --git a/services/web/public/coffee/directives/asyncForm.coffee b/services/web/public/coffee/directives/asyncForm.coffee
index 72702cf347..f38dc40e6e 100644
--- a/services/web/public/coffee/directives/asyncForm.coffee
+++ b/services/web/public/coffee/directives/asyncForm.coffee
@@ -7,6 +7,7 @@ define [
formName = attrs.asyncForm
scope[attrs.name].response = response = {}
+ scope[attrs.name].inflight = false
element.on "submit", (e) ->
e.preventDefault()
@@ -15,9 +16,12 @@ define [
for data in element.serializeArray()
formData[data.name] = data.value
+ scope[attrs.name].inflight = true
+
$http
.post(element.attr('action'), formData)
.success (data, status, headers, config) ->
+ scope[attrs.name].inflight = false
response.success = true
response.error = false
@@ -33,12 +37,13 @@ define [
ga('send', 'event', formName, 'failure', data.message)
else
ga('send', 'event', formName, 'success')
-
+
.error (data, status, headers, config) ->
+ scope[attrs.name].inflight = false
response.success = false
response.error = true
response.message =
- text: data.message or "Something went wrong talking to the server :(. Please try again."
+ text: data.message?.text or "Something went wrong talking to the server :(. Please try again."
type: 'error'
ga('send', 'event', formName, 'failure', data.message)
}
@@ -60,4 +65,4 @@ define [
form: "=for"
}
- }
\ No newline at end of file
+ }
diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee
index 0166bbd89e..c2c79b862d 100644
--- a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee
+++ b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee
@@ -1,15 +1,18 @@
define [
"base"
"ace/ace"
+ "ace/ext-searchbox"
"ide/editor/directives/aceEditor/undo/UndoManager"
"ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager"
"ide/editor/directives/aceEditor/spell-check/SpellCheckManager"
"ide/editor/directives/aceEditor/highlights/HighlightsManager"
"ide/editor/directives/aceEditor/cursor-position/CursorPositionManager"
-], (App, Ace, UndoManager, AutoCompleteManager, SpellCheckManager, HighlightsManager, CursorPositionManager) ->
+], (App, Ace, SearchBox, UndoManager, AutoCompleteManager, SpellCheckManager, HighlightsManager, CursorPositionManager) ->
EditSession = require('ace/edit_session').EditSession
- App.directive "aceEditor", ["$timeout", ($timeout) ->
+ App.directive "aceEditor", ["$timeout", "$compile", "$rootScope", ($timeout, $compile, $rootScope) ->
+ monkeyPatchSearch($rootScope, $compile)
+
return {
scope: {
theme: "="
@@ -24,6 +27,7 @@ define [
readOnly: "="
gotoLine: "="
annotations: "="
+ navigateHighlights: "="
}
link: (scope, element, attrs) ->
# Don't freak out if we're already in an apply callback
@@ -57,6 +61,20 @@ define [
editor.commands.removeCommand "showSettingsMenu"
editor.commands.removeCommand "foldall"
+ # Trigger search AND replace on CMD+F
+ editor.commands.addCommand
+ name: "find",
+ bindKey: win: "Ctrl-F", mac: "Command-F"
+ exec: (editor) ->
+ Ace.require("ace/ext/searchbox").Search(editor, true)
+ readOnly: true
+ editor.commands.removeCommand "replace"
+
+ # Make '/' work for search in vim mode.
+ editor.showCommandLine = (arg) =>
+ if arg == "/"
+ Ace.require("ace/ext/searchbox").Search(editor, true)
+
if attrs.resizeOn?
for event in attrs.resizeOn.split(",")
scope.$on event, () ->
@@ -95,7 +113,7 @@ define [
scope.$watch "annotations", (annotations) ->
if annotations?
- session = editor.getSession()
+ session = editor.getSession()
session.setAnnotations annotations
scope.$watch "readOnly", (value) ->
@@ -107,11 +125,11 @@ define [
session.setMode("ace/mode/latex")
session.setAnnotations scope.annotations
- emitChange = () ->
+ emitChange = () ->
scope.$emit "#{scope.name}:change"
attachToAce = (sharejs_doc) ->
- lines = sharejs_doc.getSnapshot().split("\n")
+ lines = sharejs_doc.getSnapshot().split("\n")
editor.setSession(new EditSession(lines))
resetSession()
session = editor.getSession()
@@ -149,7 +167,7 @@ define [
>Dismiss