Эх сурвалжийг харах

Add modules hook for contacts and support groups in auto complete

James Allen 11 жил өмнө
parent
commit
c4e4f2c77a

+ 9 - 3
services/web/app/coffee/Features/Contacts/ContactController.coffee

@@ -2,6 +2,7 @@ AuthenticationController = require "../Authentication/AuthenticationController"
 ContactManager = require "./ContactManager"
 ContactManager = require "./ContactManager"
 UserGetter = require "../User/UserGetter"
 UserGetter = require "../User/UserGetter"
 logger = require "logger-sharelatex"
 logger = require "logger-sharelatex"
+Modules = require "../../infrastructure/Modules"
 
 
 module.exports = ContactsController =
 module.exports = ContactsController =
 	getContacts: (req, res, next) ->
 	getContacts: (req, res, next) ->
@@ -24,9 +25,13 @@ module.exports = ContactsController =
 					contacts = contacts.filter (c) -> !c.holdingAccount
 					contacts = contacts.filter (c) -> !c.holdingAccount
 					
 					
 					contacts = contacts.map(ContactsController._formatContact)
 					contacts = contacts.map(ContactsController._formatContact)
-					res.send({
-						contacts: contacts
-					})
+					
+					Modules.hooks.fire "getContacts", user_id, contacts, (error, additional_contacts) ->
+						return next(error) if error?
+						contacts = contacts.concat(additional_contacts...)
+						res.send({
+							contacts: contacts
+						})
 	
 	
 	_formatContact: (contact) ->
 	_formatContact: (contact) ->
 		return  {
 		return  {
@@ -34,4 +39,5 @@ module.exports = ContactsController =
 			email: contact.email
 			email: contact.email
 			first_name: contact.first_name
 			first_name: contact.first_name
 			last_name: contact.last_name
 			last_name: contact.last_name
+			type: "user"
 		}
 		}

+ 23 - 0
services/web/app/coffee/infrastructure/Modules.coffee

@@ -1,6 +1,7 @@
 fs   = require "fs"
 fs   = require "fs"
 Path = require "path"
 Path = require "path"
 jade = require "jade"
 jade = require "jade"
+async = require "async"
 
 
 MODULE_BASE_PATH = Path.resolve(__dirname + "/../../../modules")
 MODULE_BASE_PATH = Path.resolve(__dirname + "/../../../modules")
 
 
@@ -12,6 +13,7 @@ module.exports = Modules =
 				loadedModule = require(Path.join(MODULE_BASE_PATH, moduleName, "index"))
 				loadedModule = require(Path.join(MODULE_BASE_PATH, moduleName, "index"))
 				loadedModule.name = moduleName
 				loadedModule.name = moduleName
 				@modules.push loadedModule
 				@modules.push loadedModule
+		Modules.attachHooks()
 
 
 	applyRouter: (webRouter, apiRouter) ->
 	applyRouter: (webRouter, apiRouter) ->
 		for module in @modules
 		for module in @modules
@@ -35,5 +37,26 @@ module.exports = Modules =
 
 
 	moduleIncludesAvailable: (view) ->
 	moduleIncludesAvailable: (view) ->
 		return (Modules.viewIncludes[view] or []).length > 0
 		return (Modules.viewIncludes[view] or []).length > 0
+	
+	attachHooks: () ->
+		for module in @modules
+			if module.hooks?
+				for hook, method of module.hooks
+					Modules.hooks.attach hook, method
+			
+	hooks:
+		_hooks: {}
+		attach: (name, method) ->
+			console.log "attaching hook", name, method
+			@_hooks[name] ?= []
+			@_hooks[name].push method
+			
+		fire: (name, args..., callback) ->
+			methods = @_hooks[name] or []
+			call_methods = methods.map (method) ->
+				return (cb) -> method(args..., cb)
+			async.series call_methods, (error, results) ->
+				return callback(error) if error?
+				return callback null, results
 		
 		
 Modules.loadModules()
 Modules.loadModules()

+ 11 - 6
services/web/app/views/project/editor/share.jade

@@ -52,7 +52,7 @@ script(type='text/ng-template', id='shareProjectModalTemplate')
 							placeholder="joe@example.com, sue@example.com, ..."
 							placeholder="joe@example.com, sue@example.com, ..."
 							ng-model="inputs.contacts"
 							ng-model="inputs.contacts"
 							focus-on="open"
 							focus-on="open"
-							display-property="email"
+							display-property="display"
 							key-property="id"
 							key-property="id"
 							add-on-paste="true"
 							add-on-paste="true"
 						)
 						)
@@ -145,8 +145,13 @@ script(type="text/ng-template", id="shareTagTemplate")
 
 
 script(type="text/ng-template", id="shareAutocompleteTemplate")
 script(type="text/ng-template", id="shareAutocompleteTemplate")
 	.autocomplete-template
 	.autocomplete-template
-		i.fa(ng-class="{'fa-user': data.type == 'user', 'fa-group': data.type == 'group'}")
-		| 
-		span(ng-bind-html="$highlight(data.email)")
-		div.subdued.small(ng-show="data.name", ng-bind-html="$highlight(data.name)")
-		div.subdued.small(ng-show="data.memberCount") {{ data.memberCount }} members
+		div(ng-if="data.type == 'user'")
+			i.fa.fa-user
+			| 
+			span(ng-bind-html="$highlight(data.email)")
+			div.subdued.small(ng-show="data.name", ng-bind-html="$highlight(data.name)")
+		div(ng-if="data.type == 'group'")
+			i.fa.fa-group
+			| 
+			span(ng-bind-html="$highlight(data.name)")
+			div.subdued.small(ng-show="data.member_count") {{ data.memberCount }} members

+ 18 - 5
services/web/public/coffee/ide/share/controllers/ShareProjectModalController.coffee

@@ -29,12 +29,23 @@ define [
 		do loadAutocompleteUsers = () ->
 		do loadAutocompleteUsers = () ->
 			$http.get "/user/contacts"
 			$http.get "/user/contacts"
 				.success (data) ->
 				.success (data) ->
-					console.log "Got contacts", data
 					$scope.autocompleteContacts = data.contacts or []
 					$scope.autocompleteContacts = data.contacts or []
-		
+					for contact in $scope.autocompleteContacts
+						if contact.type == "user"
+							if contact.last_name == "" and contact.first_name = contact.email.split("@")[0]
+								# User has not set their proper name so use email as canonical display property
+								contact.name = ""
+								contact.display = contact.email
+							else
+								contact.name = "#{contact.first_name} #{contact.last_name}"
+								contact.display = "#{contact.name} <#{contact.email}>"
+						else
+							# Must be a group
+							contact.display = contact.name
+
 		$scope.filterAutocompleteUsers = ($query) ->
 		$scope.filterAutocompleteUsers = ($query) ->
-			return $scope.autocompleteContacts.filter (user) ->
-				for text in [user.name, user.email]
+			return $scope.autocompleteContacts.filter (contact) ->
+				for text in [contact.name, contact.email]
 					if text?.toLowerCase().indexOf($query.toLowerCase()) > -1
 					if text?.toLowerCase().indexOf($query.toLowerCase()) > -1
 						return true
 						return true
 				return false
 				return false
@@ -43,7 +54,9 @@ define [
 			$timeout -> # Give email list a chance to update
 			$timeout -> # Give email list a chance to update
 				return if $scope.inputs.contacts.length == 0
 				return if $scope.inputs.contacts.length == 0
 
 
-				emails = $scope.inputs.contacts.map (contact) -> contact.email
+				console.warn "Ignoring groups for now"
+				emails = $scope.inputs.contacts.filter (contact) -> contact.type == "user"
+				emails = emails.map (contact) -> contact.email
 				$scope.inputs.contacts = []
 				$scope.inputs.contacts = []
 				$scope.state.error = null
 				$scope.state.error = null
 				$scope.state.inflight = true
 				$scope.state.inflight = true

+ 9 - 2
services/web/test/UnitTests/coffee/Contact/ContactControllerTests.coffee

@@ -13,6 +13,7 @@ describe "ContactController", ->
 			"../User/UserGetter": @UserGetter = {}
 			"../User/UserGetter": @UserGetter = {}
 			"./ContactManager": @ContactManager = {}
 			"./ContactManager": @ContactManager = {}
 			"../Authentication/AuthenticationController": @AuthenticationController = {}
 			"../Authentication/AuthenticationController": @AuthenticationController = {}
+			"../../infrastructure/Modules": @Modules = { hooks: {} }
 
 
 		@next = sinon.stub()
 		@next = sinon.stub()
 		@req = {}
 		@req = {}
@@ -32,6 +33,7 @@ describe "ContactController", ->
 			@AuthenticationController.getLoggedInUserId = sinon.stub().callsArgWith(1, null, @user_id)
 			@AuthenticationController.getLoggedInUserId = sinon.stub().callsArgWith(1, null, @user_id)
 			@ContactManager.getContactIds = sinon.stub().callsArgWith(2, null, @contact_ids)
 			@ContactManager.getContactIds = sinon.stub().callsArgWith(2, null, @contact_ids)
 			@UserGetter.getUsers = sinon.stub().callsArgWith(2, null, @contacts)
 			@UserGetter.getUsers = sinon.stub().callsArgWith(2, null, @contacts)
+			@Modules.hooks.fire = sinon.stub().callsArg(3)
 			
 			
 			@ContactController.getContacts @req, @res, @next
 			@ContactController.getContacts @req, @res, @next
 			
 			
@@ -50,8 +52,13 @@ describe "ContactController", ->
 				.calledWith(@contact_ids, { email: 1, first_name: 1, last_name: 1, holdingAccount: 1 })
 				.calledWith(@contact_ids, { email: 1, first_name: 1, last_name: 1, holdingAccount: 1 })
 				.should.equal true
 				.should.equal true
 		
 		
+		it "should fire the getContact module hook", ->
+			@Modules.hooks.fire
+				.calledWith("getContacts", @user_id)
+				.should.equal true
+		
 		it "should return a formatted list of contacts in contact list order, without holding accounts", ->
 		it "should return a formatted list of contacts in contact list order, without holding accounts", ->
 			@res.send.args[0][0].contacts.should.deep.equal [
 			@res.send.args[0][0].contacts.should.deep.equal [
-				{ id: "contact-1", email: "joe@example.com", first_name: "Joe", last_name: "Example" }
-				{ id: "contact-3", email: "jim@example.com", first_name: "Jim", last_name: "Example" }
+				{ id: "contact-1", email: "joe@example.com", first_name: "Joe", last_name: "Example", type: "user" }
+				{ id: "contact-3", email: "jim@example.com", first_name: "Jim", last_name: "Example", type: "user" }
 			]
 			]