Skip to content

Commit 4244d91

Browse files
committed
MB-47110: Upgrade Logs Collect Info page to Angular.
"Start Collecting" button is disabled now until the form is valid for starting collecting logs. "Get Cluster Summary" modal is closing after the text is copied with a success/error message. A new plugin is added for copying text in Angular code: "ngx-clipboard". A new Angular component is added for the selectable list of nodes: "mn-selectable-nodes". A new implementation for "mnStripPortHTML" filter is added in both Angular and AngularJS. Change-Id: I513772664baeb5a81d3ab6acdb31d7647fc0d895 Reviewed-on: http://review.couchbase.org/c/ns_server/+/156485 Well-Formed: Build Bot <[email protected]> Tested-by: Raluca Lupu <[email protected]> Reviewed-by: Pavel Blagodov <[email protected]>
1 parent 57637bf commit 4244d91

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1570
-645
lines changed

priv/public/ui/app/components/directives/mn_selectable_nodes_list.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
ng-attr-id="collected_node_list_{{node.otpNode}}"
3939
ng-disabled="mnThisCtl.mnIsNodeDisabled({node:node})">
4040
<label
41-
title="{{node.hostname | mnStripPortHTML:mnThisCtl.nodes}}"
41+
title="{{node.hostname | mnStripPortHTML}}"
4242
for="collected_node_list_{{node.otpNode}}">
43-
{{ node.hostname | mnStripPortHTML:mnThisCtl.nodes }}
43+
{{node.hostname | mnStripPortHTML}}
4444
</label>
4545
</span>
4646
<span

priv/public/ui/app/components/mn_filters.js

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import angular from "/ui/web_modules/angular.js";
2+
import mnPoolDefault from "/ui/app/components/mn_pool_default.js";
23
import lodash from "/ui/web_modules/lodash.js";
34
let _ = lodash;
45

56
export default 'mnFilters';
67

78
angular
8-
.module('mnFilters', [])
9+
.module('mnFilters', [mnPoolDefault])
910
.filter('mnCount', mnCount)
1011
.filter('removeEmptyValue', removeEmptyValue)
1112
.filter('formatProgressMessage', formatProgressMessage)
@@ -483,34 +484,12 @@ function mnMakeSafeForCSS() {
483484
});
484485
};
485486
}
486-
function mnStripPortHTML() {
487-
var cachedAllServers;
488-
var cachedIsStripping;
489-
var strippingRE = /:8091$/;
490-
491-
return function (value, allServers) {
492-
if (allServers === undefined) {
493-
throw new Error("second argument is required!");
494-
}
495-
let allNames;
496-
let isStripping;
497-
if (cachedAllServers === allServers) {
498-
isStripping = cachedIsStripping;
499-
} else {
500-
if (allServers.length == 0 || _.isString(allServers[0])) {
501-
allNames = allServers;
502-
} else {
503-
allNames = _.pluck(allServers, 'hostname');
504-
}
505-
isStripping = _.all(allNames, function (h) {return h.match(strippingRE);});
506-
cachedIsStripping = isStripping;
507-
cachedAllServers = allServers;
508-
}
509-
if (isStripping) {
510-
var match = value.match(strippingRE);
511-
return match ? value.slice(0, match.index) : value;
487+
function mnStripPortHTML(mnPoolDefault) {
488+
return function (hostname) {
489+
if (mnPoolDefault.export.isStrippingPort) {
490+
return hostname.replace(/:8091$/, '');
512491
}
513-
return value;
492+
return hostname;
514493
};
515494
}
516495
function mnTruncateTo3Digits() {

priv/public/ui/app/components/mn_pool_default.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@ licenses/APL2.txt.
1111
import angular from "/ui/web_modules/angular.js";
1212
import _ from "/ui/web_modules/lodash.js";
1313
import mnPools from "/ui/app/components/mn_pools.js";
14-
import mnFilters from "/ui/app/components/mn_filters.js";
1514
import mnHelper from "/ui/app/components/mn_helper.js";
1615

1716
export default 'mnPoolDefault';
1817

1918
angular
20-
.module('mnPoolDefault', [mnPools, mnFilters, mnHelper])
19+
.module('mnPoolDefault', [mnPools, mnHelper])
2120
.factory('mnPoolDefault', mnPoolDefaultFactory);
2221

2322
function mnPoolDefaultFactory(mnPools, mnHelper, $http, $q, $window, $location, $httpParamSerializerJQLike, $state) {
@@ -87,6 +86,9 @@ function mnPoolDefaultFactory(mnPools, mnHelper, $http, $q, $window, $location,
8786
poolDefault.thisNode = _.detect(poolDefault.nodes, function (n) {
8887
return n.thisNode;
8988
});
89+
90+
poolDefault.isStrippingPort = poolDefault.nodes.every(node => node.hostname.includes(':8091'));
91+
9092
poolDefault.compat = {
9193
atLeast51: poolDefault.thisNode.clusterCompatibility >= version51,
9294
atLeast55: poolDefault.thisNode.clusterCompatibility >= version55,

priv/public/ui/app/components/mn_tasks_details.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ function mnTasksDetailsFactory($http, $cacheFactory, mnTasksService) {
5858

5959
rv.tasks = tasks;
6060
rv.tasksXDCR = _.filter(tasks, detectXDCRTask);
61+
rv.tasksCollectInfo = _.filter(tasks, detectCollectInfoTask);
6162
rv.tasksRecovery = _.detect(tasks, detectRecoveryTasks);
6263
rv.tasksRebalance = _.detect(tasks, detectRebalanceTasks);
6364
rv.tasksWarmingUp = _.filter(tasks, detectWarmupTask);
@@ -73,6 +74,14 @@ function mnTasksDetailsFactory($http, $cacheFactory, mnTasksService) {
7374

7475
mnTasksService.stream.tasksXDCRPlug.next(rv.tasksXDCR);
7576

77+
let noCollectInfoTask = {
78+
nodesByStatus: {},
79+
nodeErrors: [],
80+
status: 'idle',
81+
perNode: {}
82+
};
83+
mnTasksService.stream.taskCollectInfoPlug.next(rv.tasksCollectInfo[0] || noCollectInfoTask);
84+
7685
return rv;
7786
});
7887
}
@@ -81,6 +90,10 @@ function mnTasksDetailsFactory($http, $cacheFactory, mnTasksService) {
8190
return taskInfo.type === 'xdcr';
8291
}
8392

93+
function detectCollectInfoTask(taskInfo) {
94+
return taskInfo.type === 'clusterLogsCollection';
95+
}
96+
8497
function detectOrphanBucketTask(taskInfo) {
8598
return taskInfo.type === "orphanBucket";
8699
}

priv/public/ui/app/constants/constants.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ let IEC = {
7878
Gi: 1073741824
7979
};
8080

81+
let servicesEnterprise = ["kv", "n1ql", "index", "fts", "cbas", "eventing", "backup"];
82+
let servicesCE = ["kv", "index", "fts", "n1ql"];
83+
8184
class MnHttpRequestRestricted {
8285
constructor(){}
8386
}
@@ -92,5 +95,7 @@ export {
9295
docBytesLimit,
9396
viewsPerPageLimit,
9497
IEC,
98+
servicesEnterprise,
99+
servicesCE,
95100
MN_HTTP_REQUEST_RESTRICTED
96101
};

priv/public/ui/app/mn.admin.service.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ class MnAdminService {
8080
this.stream.getNodes =
8181
this.stream.getPoolsDefault.pipe(pluck("nodes"));
8282

83+
this.stream.nodesByOtp = this.stream.getNodes
84+
.pipe(map(R.groupBy(R.prop('otpNode'))));
85+
86+
this.stream.isGroupsAvailable =
87+
this.stream.getPoolsDefault.pipe(pluck("isGroupsAvailable"), distinctUntilChanged());
88+
89+
this.stream.isStrippingPort =
90+
this.stream.getPoolsDefault.pipe(pluck("isStrippingPort"), distinctUntilChanged());
91+
8392
this.stream.failedOverNodes = this.stream.getNodes.pipe(
8493
map(nodes => nodes.filter(node => node.clusterMembership === "inactiveFailed")));
8594

priv/public/ui/app/mn.app.imports.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ let logsListState = {
7979
lazyLoad: mnLoadNgModule('./mn.logs.list.module.js', "MnLogsListModule")
8080
};
8181

82+
let logsCollectInfo = {
83+
name: "app.admin.logs.collectInfo.**",
84+
url: "/collectInfo",
85+
lazyLoad: mnLoadNgModule('./mn.logs.collectInfo.module.js', "MnLogsCollectInfoModule")
86+
}
87+
8288
let groupsState = {
8389
name: 'app.admin.groups.**',
8490
url: '/groups',
@@ -208,6 +214,7 @@ let mnAppImports = [
208214
bucketsState,
209215
logsState,
210216
logsListState,
217+
logsCollectInfo,
211218
alertsState,
212219
groupsState,
213220
gsiState,

priv/public/ui/app/mn.app.module.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { MnHelperService } from './mn.helper.service.js';
1515
import { MnTasksService } from './mn.tasks.service.js';
1616

1717
import { MnSecurityService } from './mn.security.service.js';
18+
import { MnServerGroupsService } from './mn.server.groups.service.js';
1819
import { mnAppImports } from './mn.app.imports.js';
1920
import { MnFormService } from './mn.form.service.js';
2021
import { MnHttpInterceptor } from './mn.http.interceptor.js';
@@ -42,6 +43,7 @@ class MnAppModule {
4243
providers: [
4344
...ajsUpgradedProviders,
4445
MnSecurityService,
46+
MnServerGroupsService,
4547
MnAppService,
4648
MnTasksService,
4749
MnFormService,
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
Copyright 2021-Present Couchbase, Inc.
3+
4+
Use of this software is governed by the Business Source License included in
5+
the file licenses/BSL-Couchbase.txt. As of the Change Date specified in that
6+
file, in accordance with the Business Source License, use of this software will
7+
be governed by the Apache License, Version 2.0, included in the file
8+
licenses/APL2.txt.
9+
*/
10+
11+
import {ChangeDetectionStrategy, Component} from '../web_modules/@angular/core.js';
12+
import {MnLifeCycleHooksToStream} from './mn.core.js';
13+
import {NgbActiveModal} from '../web_modules/@ng-bootstrap/ng-bootstrap.js';
14+
import {ClipboardService} from '../web_modules/ngx-clipboard.js';
15+
import {MnAlertsService} from './ajs.upgraded.providers.js';
16+
import {MnLogsCollectInfoService} from './mn.logs.collectInfo.service.js';
17+
import {takeUntil, filter, map} from '../web_modules/rxjs/operators.js';
18+
19+
export { MnClusterSummaryDialogComponent };
20+
21+
class MnClusterSummaryDialogComponent extends MnLifeCycleHooksToStream {
22+
23+
static get annotations() { return [
24+
new Component({
25+
selector: "mn-cluster-summary-dialog",
26+
templateUrl: "/ui/app/mn.cluster.summary.dialog.html",
27+
providers: [
28+
ClipboardService
29+
],
30+
changeDetection: ChangeDetectionStrategy.OnPush
31+
})
32+
]}
33+
34+
static get parameters() { return [
35+
NgbActiveModal,
36+
ClipboardService,
37+
MnAlertsService,
38+
MnLogsCollectInfoService
39+
]}
40+
41+
constructor(activeModal, clipboardService, mnAlertsService, mnLogsCollectInfoService) {
42+
super();
43+
44+
this.activeModal = activeModal;
45+
this.mnAlertsService = mnAlertsService;
46+
47+
this.clusterInfo = mnLogsCollectInfoService.stream.clusterInfo
48+
.pipe(map(v => JSON.stringify(v, null, 2)));
49+
50+
clipboardService.copyResponse$
51+
.pipe(filter(response => response.isSuccess),
52+
takeUntil(this.mnOnDestroy))
53+
.subscribe(this.handleSuccessMessage.bind(this));
54+
55+
clipboardService.copyResponse$
56+
.pipe(filter(response => !response.isSuccess),
57+
takeUntil(this.mnOnDestroy))
58+
.subscribe(this.handleErrorMessage.bind(this));
59+
}
60+
61+
handleSuccessMessage() {
62+
this.activeModal.close();
63+
this.mnAlertsService.formatAndSetAlerts('Text copied successfully!',
64+
'success',
65+
2500);
66+
}
67+
68+
handleErrorMessage() {
69+
this.activeModal.close();
70+
this.mnAlertsService.formatAndSetAlerts('Unable to copy text!',
71+
'error',
72+
2500);
73+
}
74+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!--
2+
Copyright 2021-Present Couchbase, Inc.
3+
4+
Use of this software is governed by the Business Source License included in
5+
the file licenses/BSL-Couchbase.txt. As of the Change Date specified in that
6+
file, in accordance with the Business Source License, use of this software will
7+
be governed by the Apache License, Version 2.0, included in the file
8+
licenses/APL2.txt.
9+
-->
10+
11+
<div class="dialog-med height-85vh">
12+
<div class="panel-header">
13+
<h2>Cluster Summary Info</h2>
14+
<a class="ui-dialog-titlebar-close modal-close" (click)="activeModal.dismiss()">X</a>
15+
</div>
16+
17+
<div style="height:calc(100% - 112px);overflow:auto;scroll:auto;margin:.5rem 0 0 0" class="show-scrollbar">
18+
<div class="panel-content">
19+
<pre id="cluster_info" class="text-small">{{clusterInfo | async}}</pre>
20+
</div>
21+
</div>
22+
23+
<div class="panel-footer spaced scroll-shadow margin-top-quarter">
24+
<button
25+
class="outline ng-isolate-scope"
26+
[disabled]="!(clusterInfo | async)"
27+
ngxClipboard
28+
[cbContent]="clusterInfo | async">
29+
Copy to Clipboard
30+
</button>
31+
<a (click)="activeModal.dismiss()">Close</a>
32+
</div>
33+
</div>

0 commit comments

Comments
 (0)