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

updated upstream into a topic branch.
This commit is contained in:
Henry Oswald 2014-07-24 13:57:49 +01:00
commit 7255231abc
11 changed files with 177 additions and 54 deletions

View file

@ -14,6 +14,7 @@ SubscriptionHandler = require('../Subscription/SubscriptionHandler')
projectEntityHandler = require('../Project/ProjectEntityHandler')
TpdsPollingBackgroundTasks = require("../ThirdPartyDataStore/TpdsPollingBackgroundTasks")
EditorRealTimeController = require("../Editor/EditorRealTimeController")
SystemMessageManager = require("../SystemMessages/SystemMessageManager")
oneMinInMs = 60 * 1000
@ -29,66 +30,20 @@ setTimeout updateOpenConnetionsMetrics, oneMinInMs
module.exports = AdminController =
index : (req, res)=>
index : (req, res, next)=>
http = require('http')
openSockets = {}
for url, agents of require('http').globalAgent.sockets
openSockets["http://#{url}"] = (agent._httpMessage.path for agent in agents)
for url, agents of require('https').globalAgent.sockets
openSockets["https://#{url}"] = (agent._httpMessage.path for agent in agents)
memory = process.memoryUsage()
io = require("../../infrastructure/Server").io
allUsers = io.sockets.clients()
users = []
allUsers.forEach (user)->
u = {}
user.get "email", (err, email)->
u.email = email
user.get "first_name", (err, first_name)->
u.first_name = first_name
user.get "last_name", (err, last_name)->
u.last_name = last_name
user.get "project_id", (err, project_id)->
u.project_id = project_id
user.get "user_id", (err, user_id)->
u.user_id = user_id
user.get "signup_date", (err, signup_date)->
u.signup_date = signup_date
user.get "login_count", (err, login_count)->
u.login_count = login_count
user.get "connected_time", (err, connected_time)->
now = new Date()
connected_mins = (((now - new Date(connected_time))/1000)/60).toFixed(2)
u.connected_mins = connected_mins
users.push u
d = new Date()
today = d.getDate()+":"+(d.getMonth()+1)+":"+d.getFullYear()+":"
yesterday = (d.getDate()-1)+":"+(d.getMonth()+1)+":"+d.getFullYear()+":"
multi = rclient.multi()
multi.get today+"docsets"
multi.get yesterday+"docsets"
multi.exec (err, replys)->
redisstats =
today:
docsets: replys[0]
compiles: replys[1]
yesterday:
docsets: replys[2]
compiles: replys[3]
DocumentUpdaterHandler.getNumberOfDocsInMemory (err, numberOfInMemoryDocs)=>
User.count (err, totalUsers)->
Project.count (err, totalProjects)->
res.render 'admin',
title: 'System Admin'
currentConnectedUsers:allUsers.length
users: users
numberOfAceDocs : numberOfInMemoryDocs
totalUsers: totalUsers
totalProjects: totalProjects
openSockets: openSockets
redisstats: redisstats
SystemMessageManager.getMessagesFromDB (error, systemMessages) ->
return next(error) if error?
res.render 'admin',
title: 'System Admin'
openSockets: openSockets
systemMessages: systemMessages
dissconectAllUsers: (req, res)=>
logger.warn "disconecting everyone"
@ -122,3 +77,13 @@ module.exports = AdminController =
pollUsersWithDropbox: (req, res)->
TpdsPollingBackgroundTasks.pollUsersWithDropbox ->
res.send 200
createMessage: (req, res, next) ->
SystemMessageManager.createMessage req.body.content, (error) ->
return next(error) if error?
res.send 200
clearMessages: (req, res, next) ->
SystemMessageManager.clearMessages (error) ->
return next(error) if error?
res.send 200

View file

@ -0,0 +1,29 @@
SystemMessage = require("../../models/SystemMessage").SystemMessage
module.exports = SystemMessageManager =
getMessages: (callback = (error, messages) ->) ->
if @_cachedMessages?
return callback null, @_cachedMessages
else
@getMessagesFromDB (error, messages) =>
return callback(error) if error?
@_cachedMessages = messages
return callback null, messages
getMessagesFromDB: (callback = (error, messages) ->) ->
SystemMessage.find {}, callback
clearMessages: (callback = (error) ->) ->
SystemMessage.remove {}, callback
createMessage: (content, callback = (error) ->) ->
message = new SystemMessage { content: content }
message.save callback
clearCache: () ->
delete @_cachedMessages
CACHE_TIMEOUT = 5 * 60 * 1000 # 5 minutes
setInterval () ->
SystemMessageManager.clearCache()
, CACHE_TIMEOUT

View file

@ -4,6 +4,7 @@ crypto = require 'crypto'
Settings = require('settings-sharelatex')
SubscriptionFormatters = require('../Features/Subscription/SubscriptionFormatters')
querystring = require('querystring')
SystemMessageManager = require("../Features/SystemMessages/SystemMessageManager")
fingerprints = {}
Path = require 'path'
@ -125,4 +126,9 @@ module.exports = (app)->
app.use (req, res, next) ->
res.locals.nav = Settings.nav
next()
app.use (req, res, next) ->
SystemMessageManager.getMessages (error, messages = []) ->
res.locals.systemMessages = messages
next()

View file

@ -0,0 +1,12 @@
mongoose = require 'mongoose'
Settings = require 'settings-sharelatex'
Schema = mongoose.Schema
ObjectId = Schema.ObjectId
SystemMessageSchema = new Schema
content : type: String, default:''
conn = mongoose.createConnection(Settings.mongo.url, server: poolSize: Settings.mongo.poolSize || 10)
exports.SystemMessage = conn.model('SystemMessage', SystemMessageSchema)

View file

@ -170,6 +170,8 @@ module.exports = class Router
app.post '/admin/syncUserToSubscription', SecurityManager.requestIsAdmin, AdminController.syncUserToSubscription
app.post '/admin/flushProjectToTpds', SecurityManager.requestIsAdmin, AdminController.flushProjectToTpds
app.post '/admin/pollUsersWithDropbox', SecurityManager.requestIsAdmin, AdminController.pollUsersWithDropbox
app.post '/admin/messages', SecurityManager.requestIsAdmin, AdminController.createMessage
app.post '/admin/messages/clear', SecurityManager.requestIsAdmin, AdminController.clearMessages
app.get '/perfTest', (req,res)->
res.send("hello")

View file

@ -59,6 +59,21 @@ block content
.row-spaced
form(enctype='multipart/form-data', method='post',action='/admin/pollUsersWithDropbox')
input(name="_csrf", type="hidden", value=csrfToken)
button.btn.btn-primary(type="submit") Poll users with dropbox
button.btn.btn-primary(type="submit") Poll users with dropbox
tab(heading="System Messages")
each message in systemMessages
.alert.alert-info.row-spaced !{message.content}
hr
form(enctype='multipart/form-data', method='post', action='/admin/messages')
input(name="_csrf", type="hidden", value=csrfToken)
.form-group
label(for="content")
input.form-control(name="content", type="text", placeholder="Message...", required)
button.btn.btn-primary(type="submit") Post Message
hr
form(enctype='multipart/form-data', method='post', action='/admin/messages/clear')
input(name="_csrf", type="hidden", value=csrfToken)
button.btn.btn-danger(type="submit") Clear all messages

View file

@ -40,6 +40,7 @@ html(itemscope, itemtype='http://schema.org/Product')
siteUrl: '#{settings.siteUrl}',
jsPath: '#{jsPath}'
};
window.systemMessages = !{JSON.stringify(systemMessages).replace(/\//g, '\\/')};
- if (typeof(settings.algolia) != "undefined")
script.
@ -58,6 +59,19 @@ html(itemscope, itemtype='http://schema.org/Product')
}
body
- if(typeof(suppressSystemMessages) == "undefined")
.system-messages(
ng-cloak
ng-controller="SystemMessagesController"
)
.system-message(
ng-repeat="message in messages"
ng-controller="SystemMessageController"
ng-hide="hidden"
)
a(href, ng-click="hide()").pull-right ×
.system-message-content(ng-bind-html="htmlContent")
- if(typeof(suppressNavbar) == "undefined")
include layout/navbar

View file

@ -8,6 +8,7 @@ define [
"main/scribtex-popup"
"main/event-tracking"
"main/bonus"
"main/system-messages"
"directives/asyncForm"
"directives/stopPropagation"
"directives/focus"

View file

@ -0,0 +1,13 @@
define [
"base"
], (App) ->
App.controller "SystemMessagesController", ($scope) ->
$scope.messages = window.systemMessages;
App.controller "SystemMessageController", ($scope, $sce) ->
$scope.hidden = $.localStorage("systemMessage.hide.#{$scope.message._id}")
$scope.htmlContent = $sce.trustAsHtml $scope.message.content
$scope.hide = () ->
$scope.hidden = true
$.localStorage("systemMessage.hide.#{$scope.message._id}", true)

View file

@ -2,6 +2,13 @@
display: none !important;
}
.system-message {
padding: (@line-height-computed / 4) (@line-height-computed / 2);
background-color: @state-warning-bg;
color: #333;
border-bottom: 1px solid @toolbar-border-color;
}
.clickable {
cursor: pointer;
}

View file

@ -0,0 +1,59 @@
SandboxedModule = require('sandboxed-module')
assert = require('assert')
require('chai').should()
sinon = require('sinon')
modulePath = require('path').join __dirname, '../../../../app/js/Features/SystemMessages/SystemMessageManager.js'
describe 'SystemMessageManager', ->
beforeEach ->
@SystemMessage = {}
@SystemMessageManager = SandboxedModule.require modulePath, requires:
"../../models/SystemMessage": SystemMessage: @SystemMessage
@callback = sinon.stub()
describe "getMessage", ->
beforeEach ->
@messages = ["messages-stub"]
@SystemMessage.find = sinon.stub().callsArgWith(1, null, @messages)
describe "when the messages are not cached", ->
beforeEach ->
@SystemMessageManager.getMessages @callback
it "should look the messages up in the database", ->
@SystemMessage.find
.calledWith({})
.should.equal true
it "should return the messages", ->
@callback.calledWith(null, @messages).should.equal true
it "should cache the messages", ->
@SystemMessageManager._cachedMessages.should.equal @messages
describe "when the messages are cached", ->
beforeEach ->
@SystemMessageManager._cachedMessages = @messages
@SystemMessageManager.getMessages @callback
it "should not look the messages up in the database", ->
@SystemMessage.find.called.should.equal false
it "should return the messages", ->
@callback.calledWith(null, @messages).should.equal true
describe "clearMessages", ->
beforeEach ->
@SystemMessage.remove = sinon.stub().callsArg(1)
@SystemMessageManager.clearMessages @callback
it "should remove the messages from the database", ->
@SystemMessage.remove
.calledWith({})
.should.equal true
it "should return the callback", ->
@callback.called.should.equal true