From c4e4f2c77af356614df993fbdc353ae3ab46446f Mon Sep 17 00:00:00 2001 From: James Allen Date: Thu, 8 Oct 2015 18:17:53 +0100 Subject: [PATCH] Add modules hook for contacts and support groups in auto complete --- .../Contacts/ContactController.coffee | 12 +++++++--- .../app/coffee/infrastructure/Modules.coffee | 23 +++++++++++++++++++ .../web/app/views/project/editor/share.jade | 17 +++++++++----- .../ShareProjectModalController.coffee | 23 +++++++++++++++---- .../Contact/ContactControllerTests.coffee | 11 +++++++-- 5 files changed, 70 insertions(+), 16 deletions(-) diff --git a/services/web/app/coffee/Features/Contacts/ContactController.coffee b/services/web/app/coffee/Features/Contacts/ContactController.coffee index 3fc2160f59..a62c22bbf2 100644 --- a/services/web/app/coffee/Features/Contacts/ContactController.coffee +++ b/services/web/app/coffee/Features/Contacts/ContactController.coffee @@ -2,6 +2,7 @@ AuthenticationController = require "../Authentication/AuthenticationController" ContactManager = require "./ContactManager" UserGetter = require "../User/UserGetter" logger = require "logger-sharelatex" +Modules = require "../../infrastructure/Modules" module.exports = ContactsController = getContacts: (req, res, next) -> @@ -24,9 +25,13 @@ module.exports = ContactsController = contacts = contacts.filter (c) -> !c.holdingAccount 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) -> return { @@ -34,4 +39,5 @@ module.exports = ContactsController = email: contact.email first_name: contact.first_name last_name: contact.last_name + type: "user" } diff --git a/services/web/app/coffee/infrastructure/Modules.coffee b/services/web/app/coffee/infrastructure/Modules.coffee index 720819e503..f45e29ea8e 100644 --- a/services/web/app/coffee/infrastructure/Modules.coffee +++ b/services/web/app/coffee/infrastructure/Modules.coffee @@ -1,6 +1,7 @@ fs = require "fs" Path = require "path" jade = require "jade" +async = require "async" MODULE_BASE_PATH = Path.resolve(__dirname + "/../../../modules") @@ -12,6 +13,7 @@ module.exports = Modules = loadedModule = require(Path.join(MODULE_BASE_PATH, moduleName, "index")) loadedModule.name = moduleName @modules.push loadedModule + Modules.attachHooks() applyRouter: (webRouter, apiRouter) -> for module in @modules @@ -35,5 +37,26 @@ module.exports = Modules = moduleIncludesAvailable: (view) -> 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() \ No newline at end of file diff --git a/services/web/app/views/project/editor/share.jade b/services/web/app/views/project/editor/share.jade index 00a3c6f9b4..fa771f6141 100644 --- a/services/web/app/views/project/editor/share.jade +++ b/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, ..." ng-model="inputs.contacts" focus-on="open" - display-property="email" + display-property="display" key-property="id" add-on-paste="true" ) @@ -145,8 +145,13 @@ script(type="text/ng-template", id="shareTagTemplate") script(type="text/ng-template", id="shareAutocompleteTemplate") .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 diff --git a/services/web/public/coffee/ide/share/controllers/ShareProjectModalController.coffee b/services/web/public/coffee/ide/share/controllers/ShareProjectModalController.coffee index 74243948ab..d502ff4caa 100644 --- a/services/web/public/coffee/ide/share/controllers/ShareProjectModalController.coffee +++ b/services/web/public/coffee/ide/share/controllers/ShareProjectModalController.coffee @@ -29,12 +29,23 @@ define [ do loadAutocompleteUsers = () -> $http.get "/user/contacts" .success (data) -> - console.log "Got contacts", data $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) -> - 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 return true return false @@ -43,7 +54,9 @@ define [ $timeout -> # Give email list a chance to update 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.state.error = null $scope.state.inflight = true diff --git a/services/web/test/UnitTests/coffee/Contact/ContactControllerTests.coffee b/services/web/test/UnitTests/coffee/Contact/ContactControllerTests.coffee index 468a97e8e7..aa01ff1a0f 100644 --- a/services/web/test/UnitTests/coffee/Contact/ContactControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Contact/ContactControllerTests.coffee @@ -13,6 +13,7 @@ describe "ContactController", -> "../User/UserGetter": @UserGetter = {} "./ContactManager": @ContactManager = {} "../Authentication/AuthenticationController": @AuthenticationController = {} + "../../infrastructure/Modules": @Modules = { hooks: {} } @next = sinon.stub() @req = {} @@ -32,6 +33,7 @@ describe "ContactController", -> @AuthenticationController.getLoggedInUserId = sinon.stub().callsArgWith(1, null, @user_id) @ContactManager.getContactIds = sinon.stub().callsArgWith(2, null, @contact_ids) @UserGetter.getUsers = sinon.stub().callsArgWith(2, null, @contacts) + @Modules.hooks.fire = sinon.stub().callsArg(3) @ContactController.getContacts @req, @res, @next @@ -50,8 +52,13 @@ describe "ContactController", -> .calledWith(@contact_ids, { email: 1, first_name: 1, last_name: 1, holdingAccount: 1 }) .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", -> @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" } ]