Skip to content

Commit 18d608a

Browse files
MB-12222: update notifications section
In this implementation the launchpad will be called each time when we call reloadState. This is not exactly how the launchpad working in cell based implementation, but ability to set the descendant depth of the reload would be very useful for the lunchpad functionality and for mnApp in general. Next release of ui-router has all chance to contain what we need. angular-ui/ui-router#1612. Change-Id: If25a8f98dfe5aaea1be7eaff5b398802fb6d122c Reviewed-on: http://review.couchbase.org/46940 Reviewed-by: Pavel Blagodov <[email protected]> Tested-by: Pavel Blagodov <[email protected]>
1 parent f1ec8c5 commit 18d608a

13 files changed

+211
-7
lines changed

priv/public/angular/app/app.js

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ angular.module('mnHelper', [
44
'mnTasksDetails'
55
]);
66
angular.module('mnBarUsage', []);
7+
angular.module('mnLaunchpad', []);
78
angular.module('mnWarmupProgress', []);
89
angular.module('mnFocus', []);
910
angular.module('mnSpinner', []);
@@ -83,9 +84,16 @@ angular.module('mnSettingsCluster', [
8384
'mnSettingsClusterService',
8485
'mnHelper'
8586
]);
87+
angular.module('mnSettingsNotifications', [
88+
'mnSettingsNotificationsService',
89+
'mnHelper'
90+
]);
8691
angular.module('mnSettingsClusterService', [
8792
'mnHttp'
8893
]);
94+
angular.module('mnSettingsNotificationsService', [
95+
'mnHttp'
96+
]);
8997
angular.module('mnSettingsAutoFailoverService', [
9098
'mnHttp'
9199
]);
@@ -181,6 +189,7 @@ angular.module('app', [
181189
'mnWarmupProgress',
182190
'mnCompaction',
183191
'mnBucketsForm',
192+
'mnLaunchpad',
184193

185194
'mnPoolDefault',
186195
'mnTasksDetails',
@@ -195,6 +204,7 @@ angular.module('app', [
195204
'mnAuth',
196205
'mnAdmin',
197206
'mnSettingsCluster',
207+
'mnSettingsNotifications',
198208
'mnServers',
199209
'mnOverview',
200210
'mnBuckets',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
angular.module('mnLaunchpad').directive('mnLaunchpad', function ($timeout) {
2+
3+
return {
4+
scope: {
5+
launchpadSource: "=",
6+
launchpadId: "="
7+
},
8+
link: function ($scope, $element, $attrs) {
9+
$scope.$watch('launchpadSource', function (launchpadSource) {
10+
if (!launchpadSource) {
11+
return;
12+
}
13+
var iframe = document.createElement("iframe");
14+
iframe.style.display = 'none'
15+
$element.append(iframe);
16+
var idoc = iframe.contentWindow.document;
17+
idoc.body.innerHTML = "<form id=\"launchpad\" method=\"POST\"><textarea id=\"sputnik\" name=\"stats\"></textarea></form>";
18+
var form = idoc.getElementById("launchpad");
19+
var textarea = idoc.getElementById("sputnik");
20+
form['action'] = "http://ph.couchbase.net/v2?launchID=" + $scope.launchpadId;
21+
textarea.innerText = JSON.stringify(launchpadSource);
22+
form.submit();
23+
$scope.launchpadSource = undefined;
24+
25+
$timeout(function () {
26+
$element.empty();
27+
}, 30000);
28+
});
29+
}
30+
};
31+
});

priv/public/angular/app/components/mn_helper.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ angular.module('mnHelper').factory('mnHelper',
7575
});
7676
return this;
7777
},
78-
catchGlobalErrors: function () {
78+
catchGlobalErrors: function (errorMessage) {
7979
promise.then(null, function (resp) {
80-
mnAlertsService.formatAndSetAlerts(resp.data, 'danger');
80+
mnAlertsService.formatAndSetAlerts(resp.data || errorMessage, 'danger');
8181
});
8282
return this;
8383
}

priv/public/angular/app/components/mn_http.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ angular.module('mnHttp').factory('mnHttp',
2424
switch (config.method.toLowerCase()) {
2525
case 'post':
2626
if (!config.notForm) {
27-
config.headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'};
27+
config.headers = _.extend({
28+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
29+
}, config.headers);
2830
} else {
2931
delete config.notForm;
3032
}

priv/public/angular/app/components/mn_pools.js

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ angular.module('mnPools').factory('mnPools',
22
function (mnHttp, $cacheFactory) {
33
var mnPools = {};
44

5+
var launchID = (new Date()).valueOf() + '-' + ((Math.random() * 65536) >> 0);
6+
57
mnPools.get = function () {
68
return mnHttp({
79
method: 'GET',
@@ -13,6 +15,7 @@ angular.module('mnPools').factory('mnPools',
1315
var rv = {};
1416
pools.isInitialized = !!pools.pools.length;
1517
pools.isAuthenticated = pools.isAdminCreds && pools.isInitialized;
18+
pools.launchID = pools.uuid + '-' + launchID;
1619
return pools;
1720
}, function (resp) {
1821
if (resp.status === 401) {

priv/public/angular/app/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060

6161
<script src="mn_admin/mn_settings/cluster/mn_settings_cluster_service.js"></script>
6262
<script src="mn_admin/mn_settings/cluster/mn_settings_cluster_controller.js"></script>
63+
<script src="mn_admin/mn_settings/notifications/mn_settings_notifications_service.js"></script>
64+
<script src="mn_admin/mn_settings/notifications/mn_settings_notifications_controller.js"></script>
6365

6466
<script src="mn_admin/mn_xdcr/mn_xdcr_service.js"></script>
6567
<script src="mn_admin/mn_xdcr/mn_xdcr_controller.js"></script>
@@ -100,6 +102,7 @@
100102
<script src="components/directives/mn_focus.js"></script>
101103
<script src="components/directives/mn_spinner.js"></script>
102104
<script src="components/directives/mn_plot.js"></script>
105+
<script src="components/directives/mn_launchpad.js"></script>
103106

104107
<script src="components/mn_filters.js"></script>
105108

priv/public/angular/app/mn_admin/mn_admin.html

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<div id="container">
2+
<div mn-launchpad launchpad-source="launchpadSource" launchpad-id="launchpadId"></div>
23
<div class="page-header">
34
<div class="cnt_holder main_holder">
45
<div class="topper_nav">
@@ -52,8 +53,11 @@
5253
<li class="line" ng-class="{currentNav: ('app.admin.logs' | includedByState)}">
5354
<a class="switch_log" ui-sref="app.admin.logs.list">Log</a>
5455
</li>
55-
<li class="line" ui-sref-active="currentNav" id="nav_settings_container">
56-
<a href="#?section=settings" ui-sref="app.admin.settings.cluster" class="switch_settings">Settings</a>
56+
<li class="line" ng-class="{currentNav: ('app.admin.settings' | includedByState)}" id="nav_settings_container">
57+
<a href="#?section=settings" ui-sref="app.admin.settings.cluster" class="switch_settings">Settings
58+
<span ng-show="updates.sendStats && !!updates.newVersion" class="badge notify"><span>!</span></span>
59+
</a>
60+
</a>
5761
</li>
5862
</ul>
5963
</div>

priv/public/angular/app/mn_admin/mn_admin_config.js

+11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ angular.module('mnAdmin').config(function ($stateProvider, $urlRouterProvider) {
88
resolve: {
99
tasks: function (mnTasksDetails) {
1010
return mnTasksDetails.getFresh();
11+
},
12+
updates: function (mnSettingsNotificationsService) {
13+
return mnSettingsNotificationsService.maybeCheckUpdates();
14+
},
15+
launchpadSource: function (updates, mnSettingsNotificationsService) {
16+
return updates.sendStats && mnSettingsNotificationsService.buildPhoneHomeThingy();
1117
}
1218
}
1319
})
@@ -144,5 +150,10 @@ angular.module('mnAdmin').config(function ($stateProvider, $urlRouterProvider) {
144150
return mnPoolDefault.getFresh();
145151
}
146152
}
153+
})
154+
.state('app.admin.settings.notifications', {
155+
url: '/notifications',
156+
controller: 'mnSettingsNotificationsController',
157+
templateUrl: 'mn_admin/mn_settings/notifications/mn_settings_notifications.html'
147158
});
148159
});

priv/public/angular/app/mn_admin/mn_admin_controller.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
angular.module('mnAdmin').controller('mnAdminController',
2-
function ($scope, $rootScope, $q, mnHelper, mnAuthService, tasks, mnTasksDetails, mnAlertsService, mnPoolDefault) {
2+
function ($scope, $rootScope, $q, mnHelper, pools, mnAuthService, tasks, updates, mnTasksDetails, mnAlertsService, mnPoolDefault, launchpadSource) {
3+
$scope.launchpadId = pools.launchID;
4+
$scope.launchpadSource = launchpadSource;
5+
$scope.updates = updates;
36
$scope.alerts = mnAlertsService.alerts;
47
$scope.closeAlert = mnAlertsService.closeAlert;
58

priv/public/angular/app/mn_admin/mn_settings/mn_settings.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ <h1>Settings</h1>
55
<div class="header_2">
66
<ul class="tabs">
77
<li class="tab_left"><a id="settings_cluster" ui-sref="app.admin.settings.cluster" ui-sref-active="selected">Cluster</a></li>
8-
<li><a id="settings_update_notifications" class="casper_settings_update_notifications">Update Notifications</a></li>
8+
<li><a id="settings_update_notifications" ui-sref="app.admin.settings.notifications" ui-sref-active="selected" class="casper_settings_update_notifications">Update Notifications</a></li>
99
<li><a id="settings_auto_failover" class="casper_settings_auto_failover">Auto-Failover</a></li>
1010
<li><a id="settings_alerts" class="casper_settings_alerts">Alerts</a></li>
1111
<li><a id="settings_compaction" class="casper_settings_compaction">Auto-Compaction</a></li>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<div mn-spinner="viewLoading">
2+
<h2>Update Notifications</h2>
3+
<form ng-submit="submit()">
4+
<div class="sub_section" >
5+
<p>You are running version {{implementationVersion | mnPrettyVersion}}.</p>
6+
<div ng-if="updates.sendStats">
7+
<p ng-if="updates.newVersion === undefined" class="warning"><strong>Warning</strong> – There was a problem with retreiving the update information.</p>
8+
<p ng-if="updates.newVersion === false">No updates available.</p>
9+
<p ng-if="updates.newVersion">A new version ({{updates.newVersion}}) is available:</p>
10+
<ul ng-if="updates.newVersion">
11+
<li>
12+
<a href="{{updates.links.release}}">Release notes</a>
13+
</li>
14+
<li>
15+
<a href="{{updates.links.download}}">Download</a>
16+
the new version
17+
</li>
18+
</ul>
19+
<p ng-if="updates.info">{{updates.info}}</p>
20+
</div>
21+
<label class="for-enable-replicas">
22+
<input type="checkbox" id="notification-updates" ng-model="enabled">
23+
<span>Enable software update notifications.</span>
24+
<a class="tooltip text_11 casper_settings_software_update_tooltip"><span>What's this?</span>
25+
<span class="tooltip_msg text_11" style="width:310px;"><span>
26+
Enabling software update notifications allows notification in
27+
the Couchbase web console when a new version of Couchbase Server
28+
is available. Configuration information transferred in the
29+
update check is anonymous and does not include any stored
30+
key-value data.
31+
</span></span>
32+
</a>
33+
</label>
34+
</div>
35+
<div class="save_cancel when-roadmin-hide-me">
36+
<button class="save_button float_right" type="submit">Save</button>
37+
</div>
38+
</form>
39+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
angular.module('mnSettingsNotifications').controller('mnSettingsNotificationsController',
2+
function ($scope, mnHelper, mnSettingsNotificationsService) {
3+
$scope.enabled = $scope.updates.sendStats;
4+
$scope.submit = function () {
5+
mnHelper
6+
.promiseHelper($scope, mnSettingsNotificationsService.saveSendStatsFlag($scope.enabled))
7+
.showErrorsSensitiveSpinner()
8+
.catchGlobalErrors('An error occured, update notifications settings were not saved.')
9+
.reloadState();
10+
};
11+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
angular.module('mnSettingsNotificationsService').factory('mnSettingsNotificationsService',
2+
function (mnHttp, mnPoolDefault, mnBucketsService, mnPools, $q, $window, $rootScope) {
3+
var mnSettingsNotificationsService = {};
4+
5+
function buildPhoneHomeThingy(infos) {
6+
var buckets = infos[1];
7+
var poolsDefault = infos[0];
8+
var pools = infos[2];
9+
10+
return {
11+
version: pools.implementationVersion,
12+
componentsVersion: pools.componentsVersion,
13+
uuid: pools.uuid,
14+
numNodes: poolsDefault.nodes.length,
15+
ram: {
16+
total: poolsDefault.storageTotals.ram.total,
17+
quotaTotal: poolsDefault.storageTotals.ram.quotaTotal,
18+
quotaUsed: poolsDefault.storageTotals.ram.quotaUsed
19+
},
20+
hdd: {
21+
total: poolsDefault.storageTotals.hdd.total,
22+
quotaTotal: poolsDefault.storageTotals.hdd.quotaTotal,
23+
used: poolsDefault.storageTotals.hdd.used,
24+
usedByData: poolsDefault.storageTotals.hdd.usedByData
25+
},
26+
buckets: {
27+
total: buckets.length,
28+
membase: buckets.byType.membase.length,
29+
memcached: buckets.byType.memcached.length
30+
},
31+
counters: poolsDefault.counters,
32+
nodes: {
33+
os: _.pluck(poolsDefault.nodes, 'os'),
34+
uptime: _.pluck(poolsDefault.nodes, 'uptime'),
35+
istats: _.pluck(poolsDefault.nodes, 'interestingStats')
36+
},
37+
browser: $window.navigator.userAgent
38+
};
39+
}
40+
41+
mnSettingsNotificationsService.buildPhoneHomeThingy = function () {
42+
return $q.all([
43+
mnPoolDefault.getFresh(),
44+
mnBucketsService.getBucketsByType(),
45+
mnPools.get()
46+
]).then(buildPhoneHomeThingy);
47+
};
48+
49+
mnSettingsNotificationsService.getUpdates = function (data) {
50+
return mnHttp({
51+
method: 'JSONP',
52+
url: 'http://ph.couchbase.net/v2',
53+
params: {launchID: data.launchID, version: data.version, callback: 'JSON_CALLBACK'}
54+
});
55+
};
56+
57+
mnSettingsNotificationsService.maybeCheckUpdates = function () {
58+
return mnSettingsNotificationsService.getSendStatsFlag().then(function (sendStatsData) {
59+
if (!sendStatsData.sendStats) {
60+
return sendStatsData;
61+
} else {
62+
return mnPools.get().then(function (pools) {
63+
return mnSettingsNotificationsService.getUpdates({
64+
launchID: pools.launchID,
65+
version: pools.version
66+
}).then(function (resp) {
67+
return _.extend(_.clone(resp.data), sendStatsData);
68+
}, function (resp) {
69+
return sendStatsData;
70+
});
71+
});
72+
}
73+
})
74+
};
75+
76+
mnSettingsNotificationsService.saveSendStatsFlag = function (flag) {
77+
return mnHttp.post("/settings/stats", {sendStats: flag});
78+
};
79+
mnSettingsNotificationsService.getSendStatsFlag = function () {
80+
return mnHttp.get("/settings/stats").then(function (resp) {
81+
return resp.data;
82+
});
83+
};
84+
85+
86+
return mnSettingsNotificationsService;
87+
});

0 commit comments

Comments
 (0)