From 8abb8a824a8d01b82d70f1e5ffb1a85e251351ae Mon Sep 17 00:00:00 2001 From: Colin Yang Date: Fri, 20 Mar 2020 18:20:10 -0700 Subject: [PATCH 1/7] render calendar keys tab under settings page --- src/oncall/ui/static/js/oncall.js | 45 ++++++++++++++++++++++++++++++ src/oncall/ui/templates/index.html | 19 +++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/oncall/ui/static/js/oncall.js b/src/oncall/ui/static/js/oncall.js index fbce3f0..c2bf216 100644 --- a/src/oncall/ui/static/js/oncall.js +++ b/src/oncall/ui/static/js/oncall.js @@ -284,6 +284,12 @@ var oncall = { self.settings.notifications.init(); self.updateTitleTag("Notifications"); }, + '/user/:user/ical_key': function(){ + oncall.callbacks.onLogin = $.noop; + oncall.callbacks.onLogout = $.noop; + self.settings.ical_key.init(); + self.updateTitleTag("Public Calendar Keys"); + }, '/query/:query/:fields': function(params){ oncall.callbacks.onLogin = $.noop; oncall.callbacks.onLogout = $.noop; @@ -2830,6 +2836,45 @@ var oncall = { $form.remove(); } } + }, + ical_key: { + data: { + $page: $('.content-wrapper'), + url: '/api/v0/users/', + icalKeyUrl: '/api/v0/ical_key/', + pageSource: $('#ical-key-template').html(), + settingsSubheaderTemplate: $('#settings-subheader-template').html(), + subheaderWrapper: '.subheader-wrapper' + }, + init: function(){ + Handlebars.registerPartial('settings-subheader', this.data.settingsSubheaderTemplate); + this.getData(); + oncall.getModes(); + }, + events: function(){ + router.updatePageLinks(); + }, + getData: function(){ + var self = this; + + if (oncall.data.user) { + $.when( + // TODO: get ical_key here + oncall.data.modesPromise + ).done(function(){ + + self.renderPage.call(self, {}); + }) + } else { + router.navigate('/'); + } + }, + renderPage: function(data){ + var template = Handlebars.compile(this.data.pageSource); + + this.data.$page.html(template(data)); + this.events(); + } } }, modal: { diff --git a/src/oncall/ui/templates/index.html b/src/oncall/ui/templates/index.html index 08cb3af..9f97319 100644 --- a/src/oncall/ui/templates/index.html +++ b/src/oncall/ui/templates/index.html @@ -1416,6 +1416,7 @@ @@ -1693,6 +1694,24 @@ + + + + From e915a5eec7201f4625b3692b0d87bd14148d991e Mon Sep 17 00:00:00 2001 From: Colin Yang Date: Mon, 23 Mar 2020 18:14:38 -0700 Subject: [PATCH 2/7] display existing ical keys --- src/oncall/ui/static/js/oncall.js | 22 ++++++++++++++++--- src/oncall/ui/templates/index.html | 35 ++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/oncall/ui/static/js/oncall.js b/src/oncall/ui/static/js/oncall.js index c2bf216..d1b50f9 100644 --- a/src/oncall/ui/static/js/oncall.js +++ b/src/oncall/ui/static/js/oncall.js @@ -2859,12 +2859,28 @@ var oncall = { if (oncall.data.user) { $.when( - // TODO: get ical_key here + $.get(this.data.icalKeyUrl + 'requester/' + oncall.data.user), oncall.data.modesPromise - ).done(function(){ + ).done(function(icalKeys){ + icalKeys = icalKeys[0]; + var userKeys = [], + teamKeys = []; + for (var i = 0; i < icalKeys.length; i++) { + if (icalKeys[i].type === 'user') + userKeys.push(icalKeys[i]); + else if (icalKeys[i].type === 'team') { + teamKeys.push(icalKeys[i]); + } + } + icalKeys.userKeys = userKeys; + icalKeys.teamKeys = teamKeys; + icalKeys.name = oncall.data.user; + + self.renderPage.call(self, icalKeys); + }).fail(function(){ self.renderPage.call(self, {}); - }) + }); } else { router.navigate('/'); } diff --git a/src/oncall/ui/templates/index.html b/src/oncall/ui/templates/index.html index 9f97319..a266275 100644 --- a/src/oncall/ui/templates/index.html +++ b/src/oncall/ui/templates/index.html @@ -1703,11 +1703,42 @@ {{>settings-subheader username=name page="ical_key"}}
-

User Calendar

+

User Calendar

+ + + + + + + {{#each userKeys}} + + + + + {{/each}} + +
User NameKey
{{this.name}}{{this.key}}
-

Team Calendar

+

Team Calendar

+ + + + + + + {{#each teamKeys}} + + + + + {{/each}} + +
Team NameKey
{{this.name}}{{this.key}}
+
+

How to subscribe to your calendars

+
From 9faa4d6d92894fa1343f7675184c26a80ec4827f Mon Sep 17 00:00:00 2001 From: Colin Yang Date: Tue, 24 Mar 2020 16:26:17 -0700 Subject: [PATCH 3/7] add buttons to regenerate and delete ical keys --- src/oncall/ui/static/js/oncall.js | 71 +++++++++++++++++++++++++++++- src/oncall/ui/templates/index.html | 59 +++++++++++-------------- 2 files changed, 95 insertions(+), 35 deletions(-) diff --git a/src/oncall/ui/static/js/oncall.js b/src/oncall/ui/static/js/oncall.js index d1b50f9..4183f50 100644 --- a/src/oncall/ui/static/js/oncall.js +++ b/src/oncall/ui/static/js/oncall.js @@ -2844,15 +2844,23 @@ var oncall = { icalKeyUrl: '/api/v0/ical_key/', pageSource: $('#ical-key-template').html(), settingsSubheaderTemplate: $('#settings-subheader-template').html(), - subheaderWrapper: '.subheader-wrapper' + moduleIcalKeyTemplate: $('#module-ical-key-template').html(), + subheaderWrapper: '.subheader-wrapper', + icalKeyRow: '.ical-key-row', + requestIcalKey: '#request-ical-key' }, init: function(){ + Handlebars.registerHelper('capitalize', function(str){ + return str.charAt(0).toUpperCase() + str.slice(1); + }); Handlebars.registerPartial('settings-subheader', this.data.settingsSubheaderTemplate); + Handlebars.registerPartial('ical-key', this.data.moduleIcalKeyTemplate); this.getData(); oncall.getModes(); }, events: function(){ router.updatePageLinks(); + this.data.$page.on('click', this.data.requestIcalKey, this.requestIcalKey.bind(this)); }, getData: function(){ var self = this; @@ -2867,6 +2875,7 @@ var oncall = { var userKeys = [], teamKeys = []; for (var i = 0; i < icalKeys.length; i++) { + icalKeys[i].time_created = moment(icalKeys[i].time_created * 1000).format('YYYY/MM/DD hh:mm'); if (icalKeys[i].type === 'user') userKeys.push(icalKeys[i]); else if (icalKeys[i].type === 'team') { @@ -2890,6 +2899,66 @@ var oncall = { this.data.$page.html(template(data)); this.events(); + }, + requestIcalKey: function(e, data){ + console.log(e, data); + }, + updateIcalKey: function($modal, $caller){ + var self = this, + $cta = $modal.find('.modal-cta'), + ical_key = $caller.attr('data-ical-key'), + ical_type = $caller.attr('data-ical-type'), + ical_name = $caller.attr('data-ical-name'), + $icalKeyRow = this.data.$page.find(this.data.icalKeyRow + '[data-id="' + ical_key + '"]') + url = this.data.icalKeyUrl + ical_type + '/' + ical_name; + + if ((ical_type === 'user' || ical_type === 'team') && ical_name) { + $cta.addClass('loading disabled').prop('disabled', true); + + $.ajax({ + type: 'POST', + url: url, + dataType: 'html' + }).done(function(data){ + $modal.modal('hide'); + $icalKeyRow.find('span.ical-key').text(data.trim()); + $icalKeyRow.find('span.ical-key-time-created').text(moment().format('YYYY/MM/DD hh:mm')); + }).fail(function(data){ + var error = oncall.isJson(data.responseText) ? JSON.parse(data.responseText).description : data.responseText || 'Delete failed.'; + oncall.alerts.createAlert(error, 'danger'); + }).always(function(){ + $cta.removeClass('loading disabled').prop('disabled', false); + }); + } else { + $modal.modal('hide'); + } + }, + deleteIcalKey: function($modal, $caller){ + var self = this, + $cta = $modal.find('.modal-cta'), + key = $caller.attr('data-ical-key'), + $icalKeyRow = this.data.$page.find(this.data.icalKeyRow + '[data-id="' + key + '"]') + url = this.data.icalKeyUrl + 'key/' + key; + + if (key) { + $cta.addClass('loading disabled').prop('disabled', true); + + $.ajax({ + type: 'DELETE', + url: url, + dataType: 'html' + }).done(function(){ + $modal.modal('hide'); + $icalKeyRow.remove(); + }).fail(function(data){ + var error = oncall.isJson(data.responseText) ? JSON.parse(data.responseText).description : data.responseText || 'Delete failed.'; + oncall.alerts.createAlert(error, 'danger'); + }).always(function(){ + $cta.addClass('loading disabled').prop('disabled', false); + }); + } else { + $modal.modal('hide'); + } } } }, diff --git a/src/oncall/ui/templates/index.html b/src/oncall/ui/templates/index.html index a266275..70879e2 100644 --- a/src/oncall/ui/templates/index.html +++ b/src/oncall/ui/templates/index.html @@ -1703,46 +1703,37 @@ {{>settings-subheader username=name page="ical_key"}}
-

User Calendar

-
- - - - - - - {{#each userKeys}} - - - - - {{/each}} - -
User NameKey
{{this.name}}{{this.key}}
-
-

Team Calendar

-
- - - - - - - {{#each teamKeys}} - - - - - {{/each}} - -
Team NameKey
{{this.name}}{{this.key}}
-
+ + {{>ical-key key_type="user" keys=userKeys}} + + {{>ical-key key_type="team" keys=teamKeys}}

How to subscribe to your calendars

+ + + From a491cc6baba76325d9789ed03f9cd64569a4d7e6 Mon Sep 17 00:00:00 2001 From: Colin Yang Date: Tue, 24 Mar 2020 17:19:21 -0700 Subject: [PATCH 4/7] add instructions on how to subscribe to public oncall calendar --- configs/config.yaml | 5 +++++ src/oncall/ui/__init__.py | 3 +++ src/oncall/ui/static/js/oncall.js | 6 +++--- src/oncall/ui/templates/index.html | 8 ++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/configs/config.yaml b/configs/config.yaml index da1c499..7f697ee 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -148,6 +148,11 @@ index_content_setting: missing_number_note: 'No number' header_color: '#3a3a3a' +# The base url for the public oncall calendar. This url has to open to the public internet for most web calendar subscriptions to work. +# The public calendar url will be formatted as follows: "{public_calendar_base_url}/{ical_key}". +# Replace localhost with the hostname of the oncall or iris-relay instance. +public_calendar_base_url: 'http://localhost:8080/api/v0/ical' + # Integration with Iris, allowing for escalation from Oncall iris_plan_integration: activated: True diff --git a/src/oncall/ui/__init__.py b/src/oncall/ui/__init__.py index 1042b77..e3f6c00 100644 --- a/src/oncall/ui/__init__.py +++ b/src/oncall/ui/__init__.py @@ -88,6 +88,7 @@ def index(req, resp): header_color=HEADER_COLOR, iris_plan_settings=IRIS_PLAN_SETTINGS, usercontact_ui_readonly=USERCONTACT_UI_READONLY, + public_calendar_base_url=PUBLIC_CALENDAR_BASE_URL, footer=INDEX_CONTENT_SETTING['footer'], timezones=SUPPORTED_TIMEZONES ) @@ -134,11 +135,13 @@ def init(application, config): global HEADER_COLOR global IRIS_PLAN_SETTINGS global USERCONTACT_UI_READONLY + global PUBLIC_CALENDAR_BASE_URL global LOGIN_REQUIRED SLACK_INSTANCE = config.get('slack_instance') HEADER_COLOR = config.get('header_color', '#3a3a3a') IRIS_PLAN_SETTINGS = config.get('iris_plan_integration') USERCONTACT_UI_READONLY = config.get('usercontact_ui_readonly', True) + PUBLIC_CALENDAR_BASE_URL = config.get('public_calendar_base_url') LOGIN_REQUIRED = config.get('require_auth') application.add_sink(index, '/') diff --git a/src/oncall/ui/static/js/oncall.js b/src/oncall/ui/static/js/oncall.js index 4183f50..56b9628 100644 --- a/src/oncall/ui/static/js/oncall.js +++ b/src/oncall/ui/static/js/oncall.js @@ -2474,7 +2474,7 @@ var oncall = { if (context[key] == null){ continue; } else if (key === 'start' || key === 'end') { - context[key] = moment(context[key] * 1000).format('YYYY/MM/DD hh:mm') + context[key] = moment(context[key] * 1000).format('YYYY/MM/DD HH:mm') } else if (context[key].constructor === Array) { for (a in context[key]) { oncall.team.audit.formatContext(a); @@ -2875,7 +2875,7 @@ var oncall = { var userKeys = [], teamKeys = []; for (var i = 0; i < icalKeys.length; i++) { - icalKeys[i].time_created = moment(icalKeys[i].time_created * 1000).format('YYYY/MM/DD hh:mm'); + icalKeys[i].time_created = moment(icalKeys[i].time_created * 1000).format('YYYY/MM/DD HH:mm'); if (icalKeys[i].type === 'user') userKeys.push(icalKeys[i]); else if (icalKeys[i].type === 'team') { @@ -2922,7 +2922,7 @@ var oncall = { }).done(function(data){ $modal.modal('hide'); $icalKeyRow.find('span.ical-key').text(data.trim()); - $icalKeyRow.find('span.ical-key-time-created').text(moment().format('YYYY/MM/DD hh:mm')); + $icalKeyRow.find('span.ical-key-time-created').text(moment().format('YYYY/MM/DD HH:mm')); }).fail(function(data){ var error = oncall.isJson(data.responseText) ? JSON.parse(data.responseText).description : data.responseText || 'Delete failed.'; oncall.alerts.createAlert(error, 'danger'); diff --git a/src/oncall/ui/templates/index.html b/src/oncall/ui/templates/index.html index 70879e2..ea2e277 100644 --- a/src/oncall/ui/templates/index.html +++ b/src/oncall/ui/templates/index.html @@ -1709,6 +1709,14 @@ {{>ical-key key_type="team" keys=teamKeys}}

How to subscribe to your calendars

+

+ From your personal calendar application, subscribe to the following URL, followed by slash, and followed by one of the calendar key above. + {% endraw %}

{{public_calendar_base_url}}
{% raw %} +

+

+ For example, if the key is abc-123, then your calendar subscription URL will be: + {% endraw %}

{{public_calendar_base_url}}/abc-123
{% raw %} +

From fd9d176c02c9961937a96d43c145521b6a039a86 Mon Sep 17 00:00:00 2001 From: Colin Yang Date: Wed, 25 Mar 2020 11:55:07 -0700 Subject: [PATCH 5/7] make calendar keys links and add additional messages to FAQ --- configs/config.yaml | 2 ++ src/oncall/ui/__init__.py | 3 +++ src/oncall/ui/static/js/oncall.js | 20 ++++++++------------ src/oncall/ui/templates/index.html | 17 +++++++++++------ 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/configs/config.yaml b/configs/config.yaml index 7f697ee..9abfd74 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -152,6 +152,8 @@ header_color: '#3a3a3a' # The public calendar url will be formatted as follows: "{public_calendar_base_url}/{ical_key}". # Replace localhost with the hostname of the oncall or iris-relay instance. public_calendar_base_url: 'http://localhost:8080/api/v0/ical' +# Additional message you want to put here, could be a link to the FAQ +public_calendar_additional_message: 'Link to FAQ' # Integration with Iris, allowing for escalation from Oncall iris_plan_integration: diff --git a/src/oncall/ui/__init__.py b/src/oncall/ui/__init__.py index e3f6c00..6ed9500 100644 --- a/src/oncall/ui/__init__.py +++ b/src/oncall/ui/__init__.py @@ -89,6 +89,7 @@ def index(req, resp): iris_plan_settings=IRIS_PLAN_SETTINGS, usercontact_ui_readonly=USERCONTACT_UI_READONLY, public_calendar_base_url=PUBLIC_CALENDAR_BASE_URL, + public_calendar_additional_message=PUBLIC_CALENDAR_ADDITIONAL_MESSAGE, footer=INDEX_CONTENT_SETTING['footer'], timezones=SUPPORTED_TIMEZONES ) @@ -136,12 +137,14 @@ def init(application, config): global IRIS_PLAN_SETTINGS global USERCONTACT_UI_READONLY global PUBLIC_CALENDAR_BASE_URL + global PUBLIC_CALENDAR_ADDITIONAL_MESSAGE global LOGIN_REQUIRED SLACK_INSTANCE = config.get('slack_instance') HEADER_COLOR = config.get('header_color', '#3a3a3a') IRIS_PLAN_SETTINGS = config.get('iris_plan_integration') USERCONTACT_UI_READONLY = config.get('usercontact_ui_readonly', True) PUBLIC_CALENDAR_BASE_URL = config.get('public_calendar_base_url') + PUBLIC_CALENDAR_ADDITIONAL_MESSAGE = config.get('public_calendar_additional_message') LOGIN_REQUIRED = config.get('require_auth') application.add_sink(index, '/') diff --git a/src/oncall/ui/static/js/oncall.js b/src/oncall/ui/static/js/oncall.js index 56b9628..42d2905 100644 --- a/src/oncall/ui/static/js/oncall.js +++ b/src/oncall/ui/static/js/oncall.js @@ -2847,7 +2847,7 @@ var oncall = { moduleIcalKeyTemplate: $('#module-ical-key-template').html(), subheaderWrapper: '.subheader-wrapper', icalKeyRow: '.ical-key-row', - requestIcalKey: '#request-ical-key' + createIcalKey: '#create-ical-key' }, init: function(){ Handlebars.registerHelper('capitalize', function(str){ @@ -2856,11 +2856,10 @@ var oncall = { Handlebars.registerPartial('settings-subheader', this.data.settingsSubheaderTemplate); Handlebars.registerPartial('ical-key', this.data.moduleIcalKeyTemplate); this.getData(); - oncall.getModes(); }, events: function(){ router.updatePageLinks(); - this.data.$page.on('click', this.data.requestIcalKey, this.requestIcalKey.bind(this)); + this.data.$page.on('click', this.data.createIcalKey, this.createIcalKey.bind(this)); }, getData: function(){ var self = this; @@ -2868,8 +2867,8 @@ var oncall = { if (oncall.data.user) { $.when( $.get(this.data.icalKeyUrl + 'requester/' + oncall.data.user), - oncall.data.modesPromise - ).done(function(icalKeys){ + $.get(this.data.url + oncall.data.user + '/teams') + ).done(function(icalKeys, teamsData){ icalKeys = icalKeys[0]; var userKeys = [], @@ -2885,6 +2884,7 @@ var oncall = { icalKeys.userKeys = userKeys; icalKeys.teamKeys = teamKeys; icalKeys.name = oncall.data.user; + icalKeys.teams = teamsData[0]; self.renderPage.call(self, icalKeys); }).fail(function(){ @@ -2900,16 +2900,14 @@ var oncall = { this.data.$page.html(template(data)); this.events(); }, - requestIcalKey: function(e, data){ + createIcalKey: function(e, data){ console.log(e, data); }, updateIcalKey: function($modal, $caller){ var self = this, $cta = $modal.find('.modal-cta'), - ical_key = $caller.attr('data-ical-key'), ical_type = $caller.attr('data-ical-type'), ical_name = $caller.attr('data-ical-name'), - $icalKeyRow = this.data.$page.find(this.data.icalKeyRow + '[data-id="' + ical_key + '"]') url = this.data.icalKeyUrl + ical_type + '/' + ical_name; if ((ical_type === 'user' || ical_type === 'team') && ical_name) { @@ -2921,8 +2919,7 @@ var oncall = { dataType: 'html' }).done(function(data){ $modal.modal('hide'); - $icalKeyRow.find('span.ical-key').text(data.trim()); - $icalKeyRow.find('span.ical-key-time-created').text(moment().format('YYYY/MM/DD HH:mm')); + self.getData(); }).fail(function(data){ var error = oncall.isJson(data.responseText) ? JSON.parse(data.responseText).description : data.responseText || 'Delete failed.'; oncall.alerts.createAlert(error, 'danger'); @@ -2937,7 +2934,6 @@ var oncall = { var self = this, $cta = $modal.find('.modal-cta'), key = $caller.attr('data-ical-key'), - $icalKeyRow = this.data.$page.find(this.data.icalKeyRow + '[data-id="' + key + '"]') url = this.data.icalKeyUrl + 'key/' + key; if (key) { @@ -2949,7 +2945,7 @@ var oncall = { dataType: 'html' }).done(function(){ $modal.modal('hide'); - $icalKeyRow.remove(); + self.getData(); }).fail(function(data){ var error = oncall.isJson(data.responseText) ? JSON.parse(data.responseText).description : data.responseText || 'Delete failed.'; oncall.alerts.createAlert(error, 'danger'); diff --git a/src/oncall/ui/templates/index.html b/src/oncall/ui/templates/index.html index ea2e277..6f38abb 100644 --- a/src/oncall/ui/templates/index.html +++ b/src/oncall/ui/templates/index.html @@ -1710,30 +1710,31 @@

How to subscribe to your calendars

- From your personal calendar application, subscribe to the following URL, followed by slash, and followed by one of the calendar key above. + From your personal calendar application, subscribe to the following URL, followed by slash, and followed by a calendar key above. Or copy the link address of a key above. {% endraw %}

{{public_calendar_base_url}}
{% raw %}

For example, if the key is abc-123, then your calendar subscription URL will be: {% endraw %}

{{public_calendar_base_url}}/abc-123
{% raw %}

+ {% endraw %}

{{public_calendar_additional_message}}

{% raw %}
+ + + From 99ddd9d948192226e7097a2fd11eba5ea25a8b36 Mon Sep 17 00:00:00 2001 From: Colin Yang Date: Wed, 25 Mar 2020 20:18:25 -0700 Subject: [PATCH 6/7] make "+ ical key" buttons work --- src/oncall/ui/static/js/oncall.js | 100 +++++++++++++++++++++++------ src/oncall/ui/templates/index.html | 30 +++++++-- 2 files changed, 108 insertions(+), 22 deletions(-) diff --git a/src/oncall/ui/static/js/oncall.js b/src/oncall/ui/static/js/oncall.js index 42d2905..a3a1ace 100644 --- a/src/oncall/ui/static/js/oncall.js +++ b/src/oncall/ui/static/js/oncall.js @@ -2845,50 +2845,60 @@ var oncall = { pageSource: $('#ical-key-template').html(), settingsSubheaderTemplate: $('#settings-subheader-template').html(), moduleIcalKeyTemplate: $('#module-ical-key-template').html(), + moduleIcalKeyCreateTemplate: $('#module-ical-key-create-template').html(), + icalKeyCreateForm: '.module-ical-key-create', + icalKeyCreateCancel: '.ical-key-create-cancel', + icalKeyUserCreateContainer: '.ical-key-user-create-container', + icalKeyTeamCreateContainer: '.ical-key-team-create-container', subheaderWrapper: '.subheader-wrapper', icalKeyRow: '.ical-key-row', - createIcalKey: '#create-ical-key' + createIcalKeyUser: '#create-ical-key-user', + createIcalKeyTeam: '#create-ical-key-team' }, init: function(){ - Handlebars.registerHelper('capitalize', function(str){ - return str.charAt(0).toUpperCase() + str.slice(1); - }); Handlebars.registerPartial('settings-subheader', this.data.settingsSubheaderTemplate); Handlebars.registerPartial('ical-key', this.data.moduleIcalKeyTemplate); this.getData(); }, events: function(){ router.updatePageLinks(); - this.data.$page.on('click', this.data.createIcalKey, this.createIcalKey.bind(this)); + this.data.$page.on('submit', this.data.icalKeyCreateForm, this.createIcalKey.bind(this)); + this.data.$page.on('click', this.data.icalKeyCreateCancel, this.createIcalKeyCancel.bind(this)); + this.data.$page.on('click', this.data.createIcalKeyUser, this.createIcalKeyUser.bind(this)); + this.data.$page.on('click', this.data.createIcalKeyTeam, this.createIcalKeyTeam.bind(this)); }, getData: function(){ var self = this; + var icalKeyData = { + userKeys: [], + teamKeys: [], + name: oncall.data.user, + teams: [] + }; + this.data.icalKeyData = icalKeyData; + if (oncall.data.user) { $.when( $.get(this.data.icalKeyUrl + 'requester/' + oncall.data.user), $.get(this.data.url + oncall.data.user + '/teams') ).done(function(icalKeys, teamsData){ icalKeys = icalKeys[0]; - - var userKeys = [], - teamKeys = []; for (var i = 0; i < icalKeys.length; i++) { icalKeys[i].time_created = moment(icalKeys[i].time_created * 1000).format('YYYY/MM/DD HH:mm'); if (icalKeys[i].type === 'user') - userKeys.push(icalKeys[i]); + icalKeyData.userKeys.push(icalKeys[i]); else if (icalKeys[i].type === 'team') { - teamKeys.push(icalKeys[i]); + icalKeyData.teamKeys.push(icalKeys[i]); } } - icalKeys.userKeys = userKeys; - icalKeys.teamKeys = teamKeys; - icalKeys.name = oncall.data.user; - icalKeys.teams = teamsData[0]; - self.renderPage.call(self, icalKeys); + icalKeyData.teams = teamsData[0]; + + self.renderPage.call(self, icalKeyData); }).fail(function(){ - self.renderPage.call(self, {}); + // we need to handle failure because icalKeys promise return 404 when no key exists + self.renderPage.call(self, icalKeyData); }); } else { router.navigate('/'); @@ -2900,8 +2910,58 @@ var oncall = { this.data.$page.html(template(data)); this.events(); }, - createIcalKey: function(e, data){ - console.log(e, data); + createIcalKeyUser: function(e, data){ + var template = Handlebars.compile(this.data.moduleIcalKeyCreateTemplate), + $container = $(e.target).parents().find(this.data.icalKeyUserCreateContainer); + + var userCreateData = { + createType: 'user', + icalKeyOptions: [this.data.icalKeyData.name] + }; + $container.html(template(userCreateData)); + }, + createIcalKeyTeam: function(e, data){ + var template = Handlebars.compile(this.data.moduleIcalKeyCreateTemplate), + $container = $(e.target).parents().find(this.data.icalKeyTeamCreateContainer); + + var teamCreateData = { + createType: 'team', + icalKeyOptions: this.data.icalKeyData.teams + }; + $container.html(template(teamCreateData)); + }, + createIcalKey: function(e){ + e.preventDefault(); + + var self = this, + $form = $(e.target), + $cta = $form.find('.ical-key-create-save'), + createType = $form.data('type'), + // we cannot trim the name here because there are team names ending in space + createName = $form.find('.ical-key-create-name').val(), + url = this.data.icalKeyUrl + createType + '/' + createName; + + if ((createType === 'user' || createType === 'team') && createName) { + $cta.addClass('loading disabled').prop('disabled', true); + + $.ajax({ + type: 'POST', + url: url, + dataType: 'html' + }).done(function(data){ + $form.remove(); + self.getData(); + }).fail(function(data){ + var error = oncall.isJson(data.responseText) ? JSON.parse(data.responseText).description : data.responseText || 'Delete failed.'; + oncall.alerts.createAlert(error, 'danger'); + }).always(function(){ + $cta.removeClass('loading disabled').prop('disabled', false); + }); + } + }, + createIcalKeyCancel: function(e, $caller){ + var $form = $(e.target).parents(this.data.icalKeyCreateForm); + $form.remove(); }, updateIcalKey: function($modal, $caller){ var self = this, @@ -3162,6 +3222,10 @@ var oncall = { return str.replace('#', ''); }); + Handlebars.registerHelper('capitalize', function(str){ + return str.charAt(0).toUpperCase() + str.slice(1); + }); + Handlebars.registerHelper('friendlyScheduler', function(str){ if (str ==='no-skip-matching') { return 'Default (allow duplicate)'; diff --git a/src/oncall/ui/templates/index.html b/src/oncall/ui/templates/index.html index 6f38abb..3d9b534 100644 --- a/src/oncall/ui/templates/index.html +++ b/src/oncall/ui/templates/index.html @@ -1724,7 +1724,10 @@ - +