Przeglądaj źródła

Add in system messages

James Allen 12 lat temu
rodzic
commit
1128b45b17

+ 18 - 53
services/web/app/coffee/Features/ServerAdmin/AdminController.coffee

@@ -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

+ 29 - 0
services/web/app/coffee/Features/SystemMessages/SystemMessageManager.coffee

@@ -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

+ 6 - 0
services/web/app/coffee/infrastructure/ExpressLocals.coffee

@@ -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()
 

+ 12 - 0
services/web/app/coffee/models/SystemMessage.coffee

@@ -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)

+ 2 - 0
services/web/app/coffee/router.coffee

@@ -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")

+ 16 - 1
services/web/app/views/admin.jade

@@ -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
 
 

+ 14 - 0
services/web/app/views/layout.jade

@@ -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
 

+ 1 - 0
services/web/public/coffee/main.coffee

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

+ 13 - 0
services/web/public/coffee/main/system-messages.coffee

@@ -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)

+ 7 - 0
services/web/public/stylesheets/app/base.less

@@ -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;
 }

+ 59 - 0
services/web/test/UnitTests/coffee/SystemMessages/SystemMessageManagerTests.coffee

@@ -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
+			
+