Merge branch 'master-redesign' of https://github.com/sharelatex/web-sharelatex into master-redesign

This commit is contained in:
Henry Oswald
2014-07-16 11:02:53 +01:00
13 changed files with 176 additions and 144 deletions
@@ -18,7 +18,7 @@ module.exports =
getMessages: (req, res)->
project_id = req.params.Project_id
query = req.body
query = req.query
logger.log project_id:project_id, query:query, "getting messages"
ChatHandler.getMessages project_id, query, (err, messages)->
if err?
-29
View File
@@ -31,33 +31,4 @@ nav.navbar.navbar-default
else
| !{item.text}
//- li.dropdown
//- a.dropdown-toggle(href='#',data-toggle="dropdown")
//- | Help
//- b.caret
//- ul.dropdown-menu
//- li
//- a(href='/learn') Documentation
//- -if(typeof(tenderUrl) != "undefined")
//- li
//- a.js-tender-widget(href='#') Contact Support
//- -if(session && session.user)
//- li.dropdown
//- a.dropdown-toggle(href="#",data-toggle="dropdown")
//- | Account
//- b.caret
//- ul.dropdown-menu
//- li
//- a(href='/user/settings').userSettingsLink Account Settings
//- - if (settings.enableSubscriptions)
//- li
//- a(href='/user/subscription').subscriptionLink Subscription
//- li
//- a(href='/logout').logoutLink Logout
//- -else
//- li
//- a(href='/register') Register
//- li
//- a#loginLink(href='/login'+getRedirAsQueryString()) Login
+2 -1
View File
@@ -62,7 +62,7 @@ block content
include ./editor/publish-template
.ui-layout-east
//- include ./editor/chat
include ./editor/chat
script(type="text/ng-template", id="genericMessageModalTemplate")
.modal-header
@@ -120,4 +120,5 @@ block content
data-ace-base=jsPath+'ace',
src=jsPath+'libs/require.js?fingerprint='+fingerprint(jsPath + 'libs/require.js')
)
@@ -1,24 +1,25 @@
aside.chat(
ng-controller="ChatController"
infinite-scroll="loadMore()"
infinite-scroll-disabled="chat.loading || chat.atEnd"
infinite-scroll-initialize="ui.chatOpen"
)
.messages(
infinite-scroll="loadMore()"
infinite-scroll="loadMoreMessages()"
infinite-scroll-disabled="chat.loading || chat.atEnd"
infinite-scroll-initialize="ui.chatOpen"
scroll-glue
infinite-scroll-upwards="true"
update-scroll-bottom-on="updateScrollPosition"
)
.infinite-scroll-inner
.loading(ng-show="chat.loading")
i.fa.fa-fw.fa-spin.fa-refresh
| Loading...
ul.list-unstyled
li.message(
ng-repeat="message in chat.groupedMessages | orderBy:'timestamp':false"
ng-repeat="message in chat.messages"
ng-controller="ChatMessageController"
ng-class="{'self': message.user.id == user.id }"
)
div.date(ng-if="$index == 0 || (message.timestamp - chat.groupedMessages[$index - 1].timestamp) > 5 * 60 * 1000")
{{ message.timestamp | formatDate:'h:MMa' }} {{ message.timestamp | relativeDate }}
div.date(ng-if="$index == 0 || (message.timestamp - chat.messages[$index - 1].timestamp) > 5 * 60 * 1000")
{{ message.timestamp | formatDate:'h:mm a' }} {{ message.timestamp | relativeDate }}
span.avatar
img(ng-src="{{message.user.gravatar_url}}")
div.message-wrapper
@@ -30,7 +31,7 @@ aside.chat(
}"
)
.arrow(ng-style="{'border-color': 'hsl({{ hue(message.user) }}, 60%, 80%)'}")
p(ng-repeat="content in message.contents") {{ content }}
p(ng-repeat="content in message.contents track by $index") {{ content }}
.new-message
textarea(placeholder="Your message...", on-enter="sendMessage()", ng-model="newMessageContent")
@@ -6,6 +6,12 @@ header.toolbar.toolbar-header(ng-cloak, ng-hide="state.loading")
tooltip-placement="bottom"
)
i.fa.fa-fw.fa-bars
a(
href="/project"
tooltip="Back to projects",
tooltip-placement="bottom"
)
i.fa.fa-fw.fa-level-up
.toolbar-center.project-name(ng-controller="ProjectNameController")
span.name(
@@ -50,12 +56,12 @@ header.toolbar.toolbar-header(ng-cloak, ng-hide="state.loading")
tooltip-placement="bottom"
)
i.fa.fa-fw.fa-history
//- a.btn.btn-full-height(
//- href,
//- tooltip="Chat",
//- tooltip-placement="bottom",
//- ng-class="{ active: ui.chatOpen }",
//- ng-click="toggleChat()",
//- ng-controller="ChatButtonController"
//- )
//- i.fa.fa-fw.fa-comment
a.btn.btn-full-height(
href,
tooltip="Chat",
tooltip-placement="bottom",
ng-class="{ active: ui.chatOpen }",
ng-click="toggleChat()",
ng-controller="ChatButtonController"
)
i.fa.fa-fw.fa-comment
@@ -2,14 +2,6 @@ aside#left-menu.full-size(
ng-class="{ 'shown': ui.leftMenuShown }"
ng-cloak
)
ul.list-unstyled.nav
li
a(
href="/project"
)
i.fa.fa-list-alt.fa-fw
|   View All Projects
h4 Download
ul.list-unstyled.nav.nav-downloads
@@ -1,34 +1,36 @@
define [
"base"
], (App) ->
fakeNgModel = (initValue) ->
$setViewValue: (value) ->
@$viewValue = value
return
$viewValue: initValue
App.directive "scrollGlue", ->
App.directive "updateScrollBottomOn", ($timeout) ->
return {
priority: 1
require: ["?ngModel"]
restrict: "A"
link: (scope, $el, attrs, ctrls) ->
scrollToBottom = ->
el.scrollTop = el.scrollHeight
shouldActivateAutoScroll = ->
el.scrollTop + el.clientHeight + 10 >= el.scrollHeight
el = $el[0]
ngModel = ctrls[0] or fakeNgModel(true)
scope.$watch ->
scrollToBottom() if ngModel.$viewValue
$el.bind "scroll", ->
activate = shouldActivateAutoScroll()
scope.$apply ngModel.$setViewValue.bind(ngModel, activate) if activate isnt ngModel.$viewValue
link: (scope, element, attrs, ctrls) ->
# We keep the offset from the bottom fixed whenever the event fires
#
# ^ | ^
# | | | scrollTop
# | | v
# | |-----------
# | | ^
# | | |
# | | | clientHeight (viewable area)
# | | |
# | | |
# | | v
# | |-----------
# | | ^
# | | | scrollBottom
# v | v
# \
# scrollHeight
scrollBottom = 0
element.on "scroll", (e) ->
scrollBottom = element[0].scrollHeight - element[0].scrollTop - element[0].clientHeight
scope.$on attrs.updateScrollBottomOn, () ->
$timeout () ->
element.scrollTop(element[0].scrollHeight - element[0].clientHeight - scrollBottom)
, 0
}
@@ -1,48 +1,25 @@
define [
"base"
"ide/chat/services/chatMessages"
], (App) ->
App.controller "ChatController", ["$scope", "$http", "ide", "$location", ($scope, $http, @ide, $location) ->
MESSAGES_URL = "/project/#{$scope.project_id}/messages"
CONNECTED_USER_URL = "/project/#{$scope.project_id}/connected_users"
$scope.$on "project:joined", =>
@ide.socket.on "new-chat-message", (message) =>
$scope.chat.messages.push(message)
$http.get(MESSAGES_URL).success (data, status, headers, config)->
$scope.chat.messages = data
$http.get(CONNECTED_USER_URL).success (data)->
console.log data
$scope.$watchCollection "chat.messages", (messages) ->
App.controller "ChatController", ($scope, chatMessages, @ide, $location) ->
$scope.chat = chatMessages.state
$scope.$watch "chat.messages", (messages) ->
if messages?
console.log "grouping messages"
$scope.chat.groupedMessages = groupMessages(messages)
$scope.$emit "updateScrollPosition"
, true # Deep watch
$scope.$on "layout:chat:resize", () ->
$scope.$emit "updateScrollPosition"
$scope.sendMessage = ->
body =
content:$scope.newMessageContent
_csrf : window.csrfToken
$http.post(MESSAGES_URL, body).success (data, status, headers, config)->
$scope.newMessageContent = ""
TIMESTAMP_GROUP_SIZE = 5 * 60 * 1000 # 5 minutes
groupMessages = (messages) ->
previousMessage = null
groupedMessages = []
for message in messages
shouldGroup = previousMessage? and
previousMessage.user == message.user and
message.timestamp - previousMessage.timestamp < TIMESTAMP_GROUP_SIZE
if shouldGroup
previousMessage.timestamp = message.timestamp
previousMessage.contents.push message.content
else
groupedMessages.push(previousMessage = {
user: message.user
timestamp: message.timestamp
contents: [message.content]
})
return groupedMessages
]
chatMessages
.sendMessage $scope.newMessageContent
.then () ->
$scope.newMessageContent = ""
$scope.loadMoreMessages = ->
chatMessages.loadMoreMessages()
@@ -0,0 +1,80 @@
define [
"base"
], (App) ->
App.factory "chatMessages", ($http, ide) ->
MESSAGES_URL = "/project/#{ide.project_id}/messages"
MESSAGE_LIMIT = 50
CONNECTED_USER_URL = "/project/#{ide.project_id}/connected_users"
chat = {
state:
messages: []
loading: false
atEnd: false
nextBeforeTimestamp: null
}
ide.socket.on "new-chat-message", (message) =>
appendMessage(message)
chat.loadMoreMessages = () ->
return if chat.state.atEnd
url = MESSAGES_URL + "?limit=#{MESSAGE_LIMIT}"
if chat.state.nextBeforeTimestamp?
url += "&before=#{chat.state.nextBeforeTimestamp}"
chat.state.loading = true
return $http
.get(url)
.success (messages = [])->
chat.state.loading = false
if messages.length < MESSAGE_LIMIT
chat.state.atEnd = true
messages.reverse()
prependMessages(messages)
chat.state.nextBeforeTimestamp = chat.state.messages[0]?.timestamp
TIMESTAMP_GROUP_SIZE = 5 * 60 * 1000 # 5 minutes
prependMessage = (message) ->
firstMessage = chat.state.messages[0]
shouldGroup = firstMessage? and
firstMessage.user.id == message.user.id and
firstMessage.timestamp - message.timestamp < TIMESTAMP_GROUP_SIZE
if shouldGroup
firstMessage.timestamp = message.timestamp
firstMessage.contents.unshift message.content
else
chat.state.messages.unshift({
user: message.user
timestamp: message.timestamp
contents: [message.content]
})
prependMessages = (messages) ->
for message in messages.slice(0).reverse()
prependMessage(message)
appendMessage = (message) ->
lastMessage = chat.state.messages[chat.state.messages.length - 1]
shouldGroup = lastMessage? and
lastMessage.user.id == message.user.id and
message.timestamp - lastMessage.timestamp < TIMESTAMP_GROUP_SIZE
if shouldGroup
lastMessage.timestamp = message.timestamp
lastMessage.contents.push message.content
else
chat.state.messages.push({
user: message.user
timestamp: message.timestamp
contents: [message.content]
})
chat.sendMessage = (message) ->
body =
content: message
_csrf : window.csrfToken
return $http.post(MESSAGES_URL, body)
return chat
@@ -63,7 +63,7 @@ define [
@$scope.trackChanges.updates[indexOfLastUpdateNotByMe].selectedFrom = true
BATCH_SIZE: 4
BATCH_SIZE: 10
fetchNextBatchOfUpdates: () ->
url = "/project/#{@ide.project_id}/updates?min_count=#{@BATCH_SIZE}"
if @$scope.trackChanges.nextBeforeTimestamp?
@@ -8,29 +8,25 @@ define [
element.css 'overflow-y': 'auto'
atEndOfListView = () ->
if attrs.infiniteScrollUpwards?
atTopOfListView()
else
atBottomOfList()
atTopOfListView = () ->
element.scrollTop() < 30
atBottomOfListView = () ->
element.scrollTop() + element.height() >= innerElement.height() - 30
listShorterThanContainer = () ->
element.innerHeight() > @$(".change-list").outerHeight()
element.height() > innerElement.height()
loadUntilFull = () ->
if (listShorterThanContainer() or atEndOfListView()) and not scope.$eval(attrs.infiniteScrollDisabled)
promise = scope.$eval(attrs.infiniteScroll)
promise.then () ->
loadUntilFull()
# @collection.fetchNextBatch
# error: (error) =>
# @hideLoading()
# @showEmptyMessageIfCollectionEmpty()
# callback(error)
# success: (collection, response) =>
# @hideLoading()
# if @collection.isAtEnd()
# @atEndOfCollection = true
# @showEmptyMessageIfCollectionEmpty()
# callback()
# else
# @loadUntilFull(callback)
element.on "scroll", (event) ->
loadUntilFull()
@@ -1,6 +1,12 @@
@new-message-height: 80px;
.chat {
.loading {
font-family: @font-family-serif;
padding: @line-height-computed / 2;
text-align: center;
}
.messages {
position: absolute;
top: 0;
@@ -55,7 +55,7 @@ describe "ChatController", ->
describe "getMessages", ->
beforeEach ->
@req.body = @query
@req.query = @query
it "should ask the chat handler about the request", (done)->