mgr/dashboard: About modal proposed changes

Fixes: http://tracker.ceph.com/issues/35693
Signed-off-by: Kanika Murarka <kmurarka@redhat.com>
This commit is contained in:
Kanika Murarka 2018-12-02 23:19:54 +05:30
parent 38a99f04f4
commit 175b83c56e
13 changed files with 414 additions and 20 deletions

3
.gitignore vendored
View File

@ -65,3 +65,6 @@ GTAGS
.idea
# dashboard
/src/pybind/mgr/dashboard/frontend/src/environments/environment.ts
/src/pybind/mgr/dashboard/frontend/src/environments/environment.prod.ts

View File

@ -63,6 +63,11 @@ class Summary(BaseController):
result = self._has_permissions(Permission.DELETE, Scope.RBD_IMAGE)
return result
def _get_host(self):
mgr_map = mgr.get('mgr_map')
services = mgr_map['services']
return services['dashboard']
@Endpoint()
def __call__(self):
exe_t, fin_t = TaskManager.list_serializable()
@ -72,6 +77,7 @@ class Summary(BaseController):
result = {
'health_status': self._health_status(),
'mgr_id': mgr.get_mgr_id(),
'mgr_host': self._get_host(),
'have_mon_connection': mgr.have_mon_connection(),
'executing_tasks': executing_tasks,
'finished_tasks': finished_tasks,

View File

@ -0,0 +1,63 @@
var replace = require('replace-in-file');
var buildDate = new Date();
var copyrightYear = buildDate.getFullYear();
const optionsNewYear = {
files:[
'src/environments/environment.ts',
'src/environments/environment.prod.ts'
],
from: /{COPYRIGHT_YEAR}/g,
to: copyrightYear,
allowEmptyPaths: false,
};
const optionsOldYear = {
files:[
'src/environments/environment.ts',
'src/environments/environment.prod.ts'
],
from: /year: '(.*)'/g,
to: "year: '{COPYRIGHT_YEAR}'",
allowEmptyPaths: false,
};
const optionsNewProd = {
files:[
'src/environments/environment.prod.ts'
],
from: /'{PRODUCTION}'/g,
to: true,
allowEmptyPaths: false,
};
const optionsNewDev = {
files:[
'src/environments/environment.ts'
],
from: /'{PRODUCTION}'/g,
to: false,
allowEmptyPaths: false,
};
const optionsOldProd = {
files:[
'src/environments/environment.prod.ts',
'src/environments/environment.ts'
],
from: /production: (.*)/g,
to: "production: '{PRODUCTION}',",
allowEmptyPaths: false,
};
try {
let changeOldYearFiles = replace.sync(optionsOldYear);
let changeNewYearFiles = replace.sync(optionsNewYear);
let changeOldProdFiles = replace.sync(optionsOldProd);
let changeProdFiles = replace.sync(optionsNewProd);
let changeDevFiles = replace.sync(optionsNewDev);
console.log('Environement variables has been set');
}
catch (error) {
console.error('Error occurred:', error);
throw error
}

View File

@ -3708,6 +3708,11 @@
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
"dev": true
},
"detect-browser": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-3.0.1.tgz",
"integrity": "sha512-L6b76EfUxnoxGHM5Vz7nrshQPIbOHtitDWpGufrp5srQdJrEYi1xpUVZeFbfssWAJvUWo/iDIVlz8hOP4Z8OCw=="
},
"detect-indent": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
@ -10551,6 +10556,222 @@
"is-finite": "^1.0.0"
}
},
"replace-in-file": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-3.4.2.tgz",
"integrity": "sha512-wb2EU5MBBqUty+b1xSIqa0IKs5M2/a+4Ldw8KM5Gpe1btv16K0eii6nMxyNhAmRZhCEPrge0ss5Ij9f7vJEYcw==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
"glob": "^7.1.2",
"yargs": "^12.0.1"
},
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"camelcase": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
"dev": true
},
"chalk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"cliui": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
"dev": true,
"requires": {
"string-width": "^2.1.1",
"strip-ansi": "^4.0.0",
"wrap-ansi": "^2.0.0"
}
},
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true,
"requires": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"execa": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
"integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
"dev": true,
"requires": {
"cross-spawn": "^6.0.0",
"get-stream": "^3.0.0",
"is-stream": "^1.1.0",
"npm-run-path": "^2.0.0",
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"invert-kv": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"lcid": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
"integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
"dev": true,
"requires": {
"invert-kv": "^2.0.0"
}
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"mem": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz",
"integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==",
"dev": true,
"requires": {
"map-age-cleaner": "^0.1.1",
"mimic-fn": "^1.0.0",
"p-is-promise": "^1.1.0"
}
},
"os-locale": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz",
"integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==",
"dev": true,
"requires": {
"execa": "^0.10.0",
"lcid": "^2.0.0",
"mem": "^4.0.0"
}
},
"p-limit": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
"integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
"integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
"dev": true
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
"ansi-regex": "^3.0.0"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
"yargs": {
"version": "12.0.5",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
"integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
"dev": true,
"requires": {
"cliui": "^4.0.0",
"decamelize": "^1.2.0",
"find-up": "^3.0.0",
"get-caller-file": "^1.0.1",
"os-locale": "^3.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1 || ^4.0.0",
"yargs-parser": "^11.1.1"
}
},
"yargs-parser": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
"integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
"request": {
"version": "2.87.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",

View File

@ -4,8 +4,9 @@
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve --host 0.0.0.0",
"build": "ng build",
"start": "npm run env_build && ng serve --host 0.0.0.0",
"build": "npm run env_build && ng build",
"env_build": "cp src/environments/environment.tpl.ts src/environments/environment.prod.ts && cp src/environments/environment.tpl.ts src/environments/environment.ts && node ./environment.build.js",
"i18n": "ng xi18n --i18n-format xlf --i18n-locale en-US --output-path locale --progress=false && ngx-extractor -i 'src/**/*.ts' -f xlf -o src/locale/messages.xlf -l en-US",
"test": "jest --watch",
"test:ci": "JEST_SILENT_REPORTER_DOTS=true jest --coverage --reporters jest-silent-reporter",
@ -59,6 +60,7 @@
"bootstrap": "3.4.0",
"chart.js": "2.7.3",
"core-js": "2.6.1",
"detect-browser": "^3.0.1",
"fork-awesome": "1.1.5",
"lodash": "4.17.11",
"moment": "2.23.0",
@ -92,6 +94,7 @@
"jest-silent-reporter": "0.1.1",
"prettier": "1.14.3",
"protractor": "5.4.2",
"replace-in-file": "^3.4.2",
"ts-node": "7.0.1",
"tslint": "5.12.0",
"typescript": "3.2.2"

View File

@ -7,20 +7,54 @@
</button>
</div>
<div class="modal-body">
<h1>ceph</h1>
<h2>
<img src="assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png"
class="ceph-logo"
alt="{{ projectConstants.organization }}">
{{ projectConstants.organization }}
</h2>
<h3>
<strong>{{ projectConstants.projectName }}</strong>
</h3>
<div class="product-versions">
<strong>Ceph version</strong>
{{ versionNumber }}
<strong>Version</strong>
<br>
{{ versionNumber }}
{{ versionHash }}
<br>
{{ versionName }}
</div>
<br>
<ul class="list-unstyled">
<li class="row">
<strong class="col-xs-6 col-sm-4">Ceph Manager</strong>
<span class="col-xs-4 col-sm-4">{{ hostAddr }}</span>
</li>
<li class="row">
<strong class="col-xs-6 col-sm-4">User</strong>
<span class="col-xs-4 col-sm-4">{{ modalVariables.user }}</span>
</li>
<li class="row">
<strong class="col-xs-6 col-sm-4">User Role</strong>
<span class="col-xs-4 col-sm-4">{{ modalVariables.role }}</span>
</li>
<li class="row">
<strong class="col-xs-6 col-sm-4">Browser</strong>
<span class="col-xs-4 col-sm-4">{{ modalVariables.browserName }}</span>
</li>
<li class="row">
<strong class="col-xs-6 col-sm-4">Browser Version</strong>
<span class="col-xs-4 col-sm-4">{{ modalVariables.browserVersion }}</span>
</li>
<li class="row">
<strong class="col-xs-6 col-sm-4">Browser OS</strong>
<span class="col-xs-4 col-sm-4">{{ modalVariables.browserOS }}</span>
</li>
</ul>
</div>
<div class="modal-footer">
<div class="text-right">
<img src="assets/Ceph_Logo_Stacked_RGB_120411_fa_348x348.png"
class="ceph-logo"
alt="Ceph">
<div class="text-left">
{{ copyright }}
{{ projectConstants.license }}
</div>
</div>

View File

@ -14,9 +14,23 @@
.modal-footer {
border-top: none;
}
h1 {
font-size: 4em;
h2 {
font-size: 3em;
}
.ceph-logo {
width: 25%;
width: 10%;
}
.list-unstyled li {
margin-top: 5px;
}
.modal-footer {
padding: 15px 80px 35px 80px;
}
.modal-body {
margin-top: 0;
padding-top: 0;
h2 {
margin-top: 0;
}
}

View File

@ -13,7 +13,8 @@ export class SummaryServiceMock {
summaryDataSource = new BehaviorSubject({
version:
'ceph version 14.0.0-855-gb8193bb4cd ' +
'(b8193bb4cda16ccc5b028c3e1df62bc72350a15d) nautilus (dev)'
'(b8193bb4cda16ccc5b028c3e1df62bc72350a15d) nautilus (dev)',
mgr_host: 'http://localhost:11000/'
});
summaryData$ = this.summaryDataSource.asObservable();
@ -47,4 +48,8 @@ describe('AboutComponent', () => {
expect(component.versionHash).toBe('(b8193bb4cda16ccc5b028c3e1df62bc72350a15d)');
expect(component.versionName).toBe('nautilus (dev)');
});
it('should get host', () => {
expect(component.hostAddr).toBe('localhost:11000');
});
});

View File

@ -1,8 +1,13 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { detect } from 'detect-browser';
import { BsModalRef } from 'ngx-bootstrap/modal';
import { Subscription } from 'rxjs';
import { environment } from '../../../../environments/environment';
import { UserService } from '../../../shared/api/user.service';
import { AppConstants } from '../../../shared/constants/app.constants';
import { Permission } from '../../../shared/models/permissions';
import { AuthStorageService } from '../../../shared/services/auth-storage.service';
import { SummaryService } from '../../../shared/services/summary.service';
@Component({
@ -11,19 +16,36 @@ import { SummaryService } from '../../../shared/services/summary.service';
styleUrls: ['./about.component.scss']
})
export class AboutComponent implements OnInit, OnDestroy {
modalVariables: any;
versionNumber: string;
versionHash: string;
versionName: string;
subs: Subscription;
userPermission: Permission;
projectConstants: typeof AppConstants;
hostAddr: string;
copyright: string;
constructor(public modalRef: BsModalRef, private summaryService: SummaryService) {}
constructor(
public modalRef: BsModalRef,
private summaryService: SummaryService,
private userService: UserService,
private authStorageService: AuthStorageService
) {
this.userPermission = this.authStorageService.getPermissions().user;
}
ngOnInit() {
this.copyright = 'Copyright(c) ' + environment.year + ' Ceph contributors.';
this.projectConstants = AppConstants;
this.hostAddr = window.location.hostname;
this.modalVariables = this.setVariables();
this.subs = this.summaryService.subscribe((summary: any) => {
if (!summary) {
return;
}
const version = summary.version.replace('ceph version ', '').split(' ');
this.hostAddr = summary.mgr_host.replace(/(^\w+:|^)\/\//, '').replace(/\/$/, '');
this.versionNumber = version[0];
this.versionHash = version[1];
this.versionName = version.slice(2, version.length).join(' ');
@ -33,4 +55,20 @@ export class AboutComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {
this.subs.unsubscribe();
}
setVariables() {
const project = {} as any;
project.user = localStorage.getItem('dashboard_username');
project.role = 'user';
if (this.userPermission.read) {
this.userService.get(project.user).subscribe((data: any) => {
project.role = data.roles;
});
}
const browser = detect();
project.browserName = browser && browser.name ? browser.name : 'Not detected';
project.browserVersion = browser && browser.version ? browser.version : 'Not detected';
project.browserOS = browser && browser.os ? browser.os : 'Not detected';
return project;
}
}

View File

@ -0,0 +1,5 @@
export class AppConstants {
public static readonly organization = 'ceph';
public static readonly projectName = 'Ceph Manager Dashboard';
public static readonly license = 'Free software (LGPL 2.1).';
}

View File

@ -1,3 +0,0 @@
export const environment = {
production: true
};

View File

@ -4,5 +4,6 @@
// The list of which env maps to which file can be found in `.angular-cli.json`.
export const environment = {
production: false
production: '{PRODUCTION}',
year: '{COPYRIGHT_YEAR}'
};

View File

@ -54,7 +54,11 @@ class RbdMirroringSummaryControllerTest(ControllerTestCase):
'osd_map': mock_osd_map,
'health': {'json': '{"status": 1}'},
'fs_map': {'filesystems': []},
'mgr_map': {
'services': {
'dashboard': 'https://ceph.dev:11000/'
},
}
}[key]
mgr.url_prefix = ''
mgr.get_mgr_id.return_value = 0