diff --git a/LICENSE b/LICENSE index e38f275..bd3fb18 100644 --- a/LICENSE +++ b/LICENSE @@ -1,58 +1,58 @@ -Copyright 2013 Zendesk - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Capitalized terms used herein have the meaning set forth in the Zendesk, Inc. -(“Zendesk”) Terms of Service (available at www.zendesk.com/company/terms) (the “Terms”). -The software made available herein constitutes “ZendeskLabs Software” which may be -implemented to enable features or functionality to be utilized in connection with a -subscription to the Service. -Notwithstanding anything to the contrary set forth in the Terms or any other -agreement by and between you and Zendesk, ZendeskLabs Software is provided -“AS IS” and on an “AS AVAILABLE” basis, and that Zendesk makes no warranty -as to the ZendeskLabs Software. - -ZENDESK DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, -NONINFRINGEMENT AND THOSE ARISING FROM A COURSE OF DEALING OR USAGE OF TRADE -RELATED TO THE ZENDESKLABS SOFTWARE, ITS USE OR ANY INABILITY TO USE IT OR -THE RESULTS OF ITS USE. - -Use of ZendeskLabs Software is subject to the following risks and conditions: -(i) the ZendeskLabs Software is not an component of the Service that -has been designed for commercial release for by Zendesk; - -(ii) the ZendeskLabs Software may not be in final form and may contain errors, -design flaws or other problems; (iii) the ZendeskLabs Software is not expected to -function fully or adequately upon installation, and it is expected and anticipated that -further testing, modification and development may be necessary to make the -ZendeskLabs Software functional; - -(iv) it may not be possible to make the ZendeskLabs Software functional; - -(v) use of the ZendeskLabs Software may result in unexpected results, loss of data, -project delays or other unpredictable damage or loss; and - -(vi) Zendesk is under no obligation to release and/or offer for sale commercial -versions of the ZendeskLabs Software, and Zendesk has the right to unilaterally -abandon development or availability of the ZendeskLabs Software at any time and -without any obligation or liability to You. You further agree that Zendesk shall -have no obligation to correct any bugs, defects or errors in the ZendeskLabs Software -or otherwise to support or maintain the ZendeskLabs Software. - -If you elect to utilize any ZendeskLabs Software, you are agreeing to release Zendesk -from any claim with regard to the ZendeskLabs Software, its operation, availability or -its failure to operate or be available. Without limiting the generality of the foregoing, - -You acknowledge and agree that neither the use, availability nor operation of any -ZendeskLabs Software shall be subject to any service level commitment applicable to the Service. +Copyright 2013 Zendesk + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Capitalized terms used herein have the meaning set forth in the Zendesk, Inc. +(“Zendesk”) Terms of Service (available at www.zendesk.com/company/terms) (the “Terms”). +The software made available herein constitutes “ZendeskLabs Software” which may be +implemented to enable features or functionality to be utilized in connection with a +subscription to the Service. +Notwithstanding anything to the contrary set forth in the Terms or any other +agreement by and between you and Zendesk, ZendeskLabs Software is provided +“AS IS” and on an “AS AVAILABLE” basis, and that Zendesk makes no warranty +as to the ZendeskLabs Software. + +ZENDESK DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, +NONINFRINGEMENT AND THOSE ARISING FROM A COURSE OF DEALING OR USAGE OF TRADE +RELATED TO THE ZENDESKLABS SOFTWARE, ITS USE OR ANY INABILITY TO USE IT OR +THE RESULTS OF ITS USE. + +Use of ZendeskLabs Software is subject to the following risks and conditions: +(i) the ZendeskLabs Software is not an component of the Service that +has been designed for commercial release for by Zendesk; + +(ii) the ZendeskLabs Software may not be in final form and may contain errors, +design flaws or other problems; (iii) the ZendeskLabs Software is not expected to +function fully or adequately upon installation, and it is expected and anticipated that +further testing, modification and development may be necessary to make the +ZendeskLabs Software functional; + +(iv) it may not be possible to make the ZendeskLabs Software functional; + +(v) use of the ZendeskLabs Software may result in unexpected results, loss of data, +project delays or other unpredictable damage or loss; and + +(vi) Zendesk is under no obligation to release and/or offer for sale commercial +versions of the ZendeskLabs Software, and Zendesk has the right to unilaterally +abandon development or availability of the ZendeskLabs Software at any time and +without any obligation or liability to You. You further agree that Zendesk shall +have no obligation to correct any bugs, defects or errors in the ZendeskLabs Software +or otherwise to support or maintain the ZendeskLabs Software. + +If you elect to utilize any ZendeskLabs Software, you are agreeing to release Zendesk +from any claim with regard to the ZendeskLabs Software, its operation, availability or +its failure to operate or be available. Without limiting the generality of the foregoing, + +You acknowledge and agree that neither the use, availability nor operation of any +ZendeskLabs Software shall be subject to any service level commitment applicable to the Service. diff --git a/README.md b/README.md index 2f82abe..74aca6c 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,112 @@ -:warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: - -# URL Builder App - -## Description: - -A Zendesk App to help you generate links for agents. - -## Instructions: - -1. Download a [.zip of this app](https://github.com/zendesklabs/url_builder_app/archive/master.zip) -2. Navigate to your Zendesk Admin's Apps -> Manage page -3. Click `Upload App` -4. Enter a descriptive name of your choosing, and upload this .zip -5. Click `Upload` -6. Confirm the title, the second box is for the `json`, described below. -7. Optionally enable role restrictions if these URLs are not appropriate for all agents. -8. Once your .json is in place, click `Install`. -9. Open a new browser to test your results. - -## JSON Array of URLs: - -The following is an example of what can be entered into this app's settings: - -```javascript -[ - { - "title": "First Title", - "url": "http://example.com/?name={{ticket.requester.name}}" - }, - { - "title": "Second Title (with custom field)", - "url": "http://example.com/?custom={{ticket.custom_field_424242}}" - } -] -``` - -This example will generate the following HTML inside the app: -```html - -``` - -### Available Placeholders -* {{ticket.id}} //not available for new tickets -* {{ticket.description}} -* {{ticket.requester.id}} -* {{ticket.requester.name}} -* {{ticket.requester.email}} -* {{ticket.requester.externalId}} -* {{ticket.requester.firstname}} -* {{ticket.requester.lastname}} -* {{ticket.requester.user_fields.YYY}} = custom user fields can be used -* {{ticket.assignee.user.id}} -* {{ticket.assignee.user.name}} -* {{ticket.assignee.user.email}} -* {{ticket.assignee.user.externalId}} -* {{ticket.assignee.user.firstname}} -* {{ticket.assignee.user.lastname}} -* {{ticket.assignee.group.id}} -* {{ticket.assignee.group.name}} -* {{ticket.custom_field_XXXXXXX}} // XXXXXXX = custom field id -* {{ticket.organization.organization_fields.XXXXXXX}} // XXXXXXX = Field key, default is field name -* {{current_user.id}} -* {{current_user.name}} -* {{current_user.email}} -* {{current_user.externalId}} -* {{current_user.firstname}} -* {{current_user.lastname}} - -### Making changes - -If you wish to change the output, locate the app by looking for the name you choose in step 4 above. Use the widget to `Change Settings` - - - - -## Contribution - -Improvements are always welcome. To contribute, please submit detailed Pull Requests. - -## Screenshot(s): -![screenshot-1](/assets/screenshot.png) +:warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: + +# URL Builder App + +## Description: + +A Zendesk App to help you generate links for agents. + +## Instructions: + +1. Download a [.zip of this app](https://github.com/zendesklabs/url_builder_app/archive/master.zip) +2. Navigate to your Zendesk Admin's Apps -> Manage page +3. Click `Upload App` +4. Enter a descriptive name of your choosing, and upload this .zip +5. Click `Upload` +6. Confirm the title, the second box is for the `json`, described below. +7. Optionally enable role restrictions if these URLs are not appropriate for all agents. +8. Once your .json is in place, click `Install`. +9. Open a new browser to test your results. + +## JSON Array of URLs: + +The following is an example of what can be entered into this app's settings: + +```javascript +[ + { + "title": "First Title", + "url": "http://example.com/?name={{ticket.requester.name}}" + }, + { + "title": "Second Title (with custom field)", + "url": "http://example.com/?custom={{ticket.custom_field_424242}}" + } +] +``` + +This example will generate the following HTML inside the app: +```html + +``` + +### Available Placeholders + +#### Ticket sidebar + +* {{ticket.id}} //not available for new tickets +* {{ticket.description}} +* {{ticket.requester.id}} +* {{ticket.requester.name}} +* {{ticket.requester.email}} +* {{ticket.requester.external_id}} +* {{ticket.requester.firstname}} +* {{ticket.requester.lastname}} +* {{ticket.requester.user_fields.YYY}} = custom user fields can be used +* {{ticket.assignee.user.id}} +* {{ticket.assignee.user.name}} +* {{ticket.assignee.user.email}} +* {{ticket.assignee.user.external_id}} +* {{ticket.assignee.user.firstname}} +* {{ticket.assignee.user.lastname}} +* {{ticket.assignee.group.id}} +* {{ticket.assignee.group.name}} +* {{ticket.custom_field_XXXXXXX}} // XXXXXXX = custom field id +* {{ticket.organization.organization_fields.XXXXXXX}} // XXXXXXX = Field key, default is field name +* {{current_user.id}} +* {{current_user.name}} +* {{current_user.email}} +* {{current_user.external_id}} +* {{current_user.firstname}} +* {{current_user.lastname}} + +#### User sidebar + +* {{user.id}} +* {{user.name}} +* {{user.email}} +* {{user.phone}} +* {{user.external_id}} +* {{user.firstname}} +* {{user.lastname}} +* {{user.user_fields.YYY}} = custom user fields can be used +* {{user.organization.id}} (if user belongs to multiple organizations, only the default one will be used) +* {{user.organization.name}} +* {{user.organization.external_id}} +* {{user.organization.organization_fields.XXXXXXX}} = custom organization fields can be used + + +### Screenshots + +![](/assets/screenshot.png) + +### Making changes + +If you wish to change the output, locate the app by looking for the name you choose in step 4 above. Use the widget to `Change Settings` + + + + +## Contribution + +Improvements are always welcome. To contribute, please submit detailed Pull Requests. + +## Screenshot(s): +![screenshot-1](/assets/screenshot.png) diff --git a/app.css b/app.css index a5a27f3..f3a14ac 100644 --- a/app.css +++ b/app.css @@ -1,3 +1,3 @@ -.btn { - width: 85%; +.btn { + width: 85%; } \ No newline at end of file diff --git a/app.js b/app.js index a15df64..b1d7a60 100644 --- a/app.js +++ b/app.js @@ -1,102 +1,134 @@ -(function() { - return { - requests: { - fetchUsers: function(ids) { - return { - url: helpers.fmt('/api/v2/users/show_many.json?ids=%@&include=organizations,groups', ids.join(',')), - type: 'GET', - dataType: 'json' - }; - } - }, - - events: { - 'app.created' : 'onAppCreated', - '*.changed' : function(e) { - if (_.contains(this.fieldsToWatch(), e.propertyName)) - return this.onAppActivated(); - }, - 'fetchUsers.done' : 'onFetchUsersDone' - }, - - onAppCreated: function() { - var userIds = _.compact(_.uniq([ - (this.ticket().assignee().user() && this.ticket().assignee().user().id()), - this.currentUser().id(), - (this.ticket().requester() && this.ticket().requester().id()) - ])); - - this.ajax('fetchUsers', userIds); - }, - - onFetchUsersDone: function(data) { - var templateUris = this.getUriTemplatesFromSettings(), - templateOptions = { interpolate : /\{\{(.+?)\}\}/g }, - context = this.getContext(data), - uris = _.map(templateUris, function(uri){ - try { - uri.url = _.template(uri.url, templateOptions)(context); - uri.title = _.template(uri.title, templateOptions)(context); - } catch(e) { - console.log('[URL_BUILDER_APP] ' + e); - } - return uri; - }, this); - - this.switchTo('list', { uris: uris }); - }, - - getUriTemplatesFromSettings: function(){ - return JSON.parse(this.settings.uri_templates); - }, - - getContext: function(data){ - var context = _.clone(this.containerContext()); - - if (context.ticket.requester.id) { - context.ticket.requester = this.decorateUser(this.findUserById(data.users, context.ticket.requester.id)); - - if (context.ticket.requester.organization_id) { - context.ticket.organization = _.find(data.organizations, function(org) { - return org.id == context.ticket.requester.organization_id; - }); - } - } - - if (context.ticket.assignee.user.id) { - context.ticket.assignee.user = this.decorateUser(this.findUserById(data.users, context.ticket.assignee.user.id)); - } - - //copying data not available on this.containerContext() - context.ticket.id = this.ticket().id(); - context.ticket.description = this.ticket().description(); - - context.current_user = this.decorateUser(this.findUserById(data.users, this.currentUser().id())); - - return context; - }, - - findUserById: function(users, user_id) { - return _.find(users, function(user) { - return user.id == user_id; - }, this); - }, - - decorateUser: function(user){ - var name = (user.name || '').split(' '); - - user.firstname = name[0] || ''; - user.lastname = name[1] || ''; - - return user; - }, - - fieldsToWatch: _.memoize(function(){ - return _.reduce(this.getUriTemplatesFromSettings(), function(memo, uri){ - var fields = _.map(uri.url.match(/\{\{(.+?)\}\}/g), function(f){ return f.slice(2,-2); }); - - return _.union(memo, fields); - }, []); - }) - }; -}()); +(function() { + return { + requests: { + fetchUsers: function(ids) { + return { + url: helpers.fmt('/api/v2/users/show_many.json?ids=%@&include=organizations', ids.join(',')), + type: 'GET', + dataType: 'json' + }; + } + }, + + events: { + 'app.created': 'onAppCreated', + '*.changed' : function(e) { + if (_.contains(this.fieldsToWatch(), e.propertyName)) + return this.onAppCreated(); + } + }, + + onAppCreated: function() { + switch (this.currentLocation()) { + case "user_sidebar": + this.prepareTemplateForUser(); + break; + case "ticket_sidebar": + this.prepareTemplateForTicket(); + break; + } + }, + + prepareTemplateForUser: function() { + this.ajax('fetchUsers', [this.user().id()]).done(function(data) { + var context = this.getUserContext(data); + this.prepareTemplate(context); + }); + }, + + prepareTemplateForTicket: function() { + var userIds = _.compact(_.uniq([ + (this.ticket().assignee().user() && this.ticket().assignee().user().id()), + this.currentUser().id(), + (this.ticket().requester() && this.ticket().requester().id()) + ])); + + this.ajax('fetchUsers', userIds).done(function(data) { + var context = this.getTicketContext(data); + this.prepareTemplate(context); + }); + }, + + prepareTemplate: function(context) { + var templateUris = this.getUriTemplatesFromSettings(), + templateOptions = { interpolate : /\{\{(.+?)\}\}/g }, + uris = _.map(templateUris, function(uri){ + try { + uri.url = _.template(uri.url, templateOptions)(context); + uri.title = _.template(uri.title, templateOptions)(context); + } catch(e) { + console.log('[URL_BUILDER_APP] ' + e); + } + return uri; + }, this); + + this.switchTo('list', { uris: uris }); + }, + + getUriTemplatesFromSettings: function(){ + return JSON.parse(this.settings.uri_templates); + }, + + getUserContext: function(data) { + var context = _.clone(this.containerContext()); + context.user = this.decorateUser(data.users[0]); + + if (context.user.organization_id) { + context.user.organization = _.find(data.organizations, function(org) { + return org.id == context.user.organization_id; + }); + } + + return context; + }, + + getTicketContext: function(data) { + var context = _.clone(this.containerContext()); + + if (context.ticket.requester.id) { + context.ticket.requester = this.decorateUser(this.findUserById(data.users, context.ticket.requester.id)); + + if (context.ticket.requester.organization_id) { + context.ticket.organization = _.find(data.organizations, function(org) { + return org.id == context.ticket.requester.organization_id; + }); + } + } + + if (context.ticket.assignee.user.id) { + context.ticket.assignee.user = this.decorateUser(this.findUserById(data.users, context.ticket.assignee.user.id)); + } + + //copying data not available on this.containerContext() + context.ticket.id = this.ticket().id(); + context.ticket.description = this.ticket().description(); + + context.current_user = this.decorateUser(this.findUserById(data.users, this.currentUser().id())); + + return context; + }, + + findUserById: function(users, user_id) { + return _.find(users, function(user) { + return user.id == user_id; + }, this); + }, + + decorateUser: function(user) { + var name = (user.name || '').split(' '); + + user.firstname = name[0] || ''; + user.lastname = name[1] || ''; + + return user; + }, + + fieldsToWatch: _.memoize(function() { + return _.reduce(this.getUriTemplatesFromSettings(), function(memo, uri){ + var fields = _.map(uri.url.match(/\{\{(.+?)\}\}/g), function(f){ return f.slice(2,-2); }); + + return _.union(memo, fields); + }, []); + }) + }; +}()); diff --git a/manifest.json b/manifest.json index 1f99866..4409f32 100644 --- a/manifest.json +++ b/manifest.json @@ -1,21 +1,21 @@ -{ - "name": "Url Builder App", - "author": { - "name": "Zendesk Services", - "email": "services@zendesk.com" - }, - - "defaultLocale": "en", - "private": true, - "location": ["ticket_sidebar", "new_ticket_sidebar"], - "frameworkVersion": "1.0", - "version": "1.0.1", - - "parameters": [ - { - "name": "uri_templates", - "type": "multiline", - "required": true - } - ] -} +{ + "name": "URL Builder App", + "author": { + "name": "Zendesk Services", + "email": "services@zendesk.com" + }, + + "defaultLocale": "en", + "private": true, + "location": ["ticket_sidebar", "new_ticket_sidebar", "user_sidebar"], + "frameworkVersion": "1.0", + "version": "1.0.2", + + "parameters": [ + { + "name": "uri_templates", + "type": "multiline", + "required": true + } + ] +} diff --git a/templates/layout.hdbs b/templates/layout.hdbs index 58d03f6..4a256e7 100644 --- a/templates/layout.hdbs +++ b/templates/layout.hdbs @@ -1,6 +1,6 @@ -
-
-
- +
+
+
+ diff --git a/templates/list.hdbs b/templates/list.hdbs index c6a9210..ad1efc4 100644 --- a/templates/list.hdbs +++ b/templates/list.hdbs @@ -1,9 +1,9 @@ -
- -
+
+ +
diff --git a/translations/en.json b/translations/en.json index 94c622b..b40a493 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1,13 +1,13 @@ -{ - "app": { - "description": "Simple url generator", - "name": "Simple Url", - - "parameters": { - "uri_templates": { - "label": "A JSON Array of urls.", - "helpText": "See https://github.com/zendesklabs/url_builder_app/blob/master/README.md for more information." - } - } - } -} +{ + "app": { + "description": "Simple URL generator", + "name": "Simple URL generator", + + "parameters": { + "uri_templates": { + "label": "A JSON Array of URLs.", + "helpText": "See https://github.com/zendesklabs/url_builder_app/blob/master/README.md for more information." + } + } + } +}