mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Add modules hook for contacts and support groups in auto complete
This commit is contained in:
parent
78c5741d06
commit
c4e4f2c77a
5 changed files with 70 additions and 16 deletions
|
@ -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,6 +25,10 @@ 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)
|
||||||
|
|
||||||
|
Modules.hooks.fire "getContacts", user_id, contacts, (error, additional_contacts) ->
|
||||||
|
return next(error) if error?
|
||||||
|
contacts = contacts.concat(additional_contacts...)
|
||||||
res.send({
|
res.send({
|
||||||
contacts: contacts
|
contacts: contacts
|
||||||
})
|
})
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -36,4 +38,25 @@ 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()
|
|
@ -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'}")
|
div(ng-if="data.type == 'user'")
|
||||||
|
i.fa.fa-user
|
||||||
|
|
|
|
||||||
span(ng-bind-html="$highlight(data.email)")
|
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.name", ng-bind-html="$highlight(data.name)")
|
||||||
div.subdued.small(ng-show="data.memberCount") {{ data.memberCount }} members
|
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
|
||||||
|
|
|
@ -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) ->
|
return $scope.autocompleteContacts.filter (contact) ->
|
||||||
for text in [user.name, user.email]
|
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
|
||||||
|
|
|
@ -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-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" }
|
{ id: "contact-3", email: "jim@example.com", first_name: "Jim", last_name: "Example", type: "user" }
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue