diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2015-10-16 18:41:43 +0200 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2015-10-16 18:41:43 +0200 |
commit | be6bb0b97dc41ca7e21238a34abcd17e7facd480 (patch) | |
tree | 3f6043867f92d855ca94c33c84cfefff39f8ce7e /server/sonar-web/src/main/js/apps/system | |
parent | e1bd4555bd70c6a7997de8a4c1a04225a3fef639 (diff) | |
download | sonarqube-be6bb0b97dc41ca7e21238a34abcd17e7facd480.tar.gz sonarqube-be6bb0b97dc41ca7e21238a34abcd17e7facd480.zip |
SONAR-6928 Rewrite the System Info page
Diffstat (limited to 'server/sonar-web/src/main/js/apps/system')
7 files changed, 153 insertions, 53 deletions
diff --git a/server/sonar-web/src/main/js/apps/system/app.js b/server/sonar-web/src/main/js/apps/system/app.js index 391c313d9ec..b4b9a61c4a6 100644 --- a/server/sonar-web/src/main/js/apps/system/app.js +++ b/server/sonar-web/src/main/js/apps/system/app.js @@ -1,57 +1,9 @@ -import $ from 'jquery'; -import {setLogLevel} from '../../api/system'; +import React from 'react'; +import Main from './main'; -const LOG_LEVELS = ['INFO', 'DEBUG', 'TRACE']; - -window.sonarqube.appStarted.then(() => { - let cell = $('#sonarqube-logs-level').find('td:last-child'); - if (cell.length) { - let currentValue = cell.text().trim(); - cell.empty(); - - let select = $('<select>'); - cell.append(select); - - LOG_LEVELS.forEach(logLevel => { - let option = $('<option>'); - option.prop('value', logLevel); - option.text(logLevel); - option.prop('selected', logLevel === currentValue); - select.append(option); - }); - - let format = (state) => { - let className = state.id !== 'INFO' ? 'text-danger' : ''; - return `<span class="${className}">${state.id}</span>`; - }; - - let warning = $('<div>') - .addClass('spacer-top text-danger') - .text(window.t('system.log_level.warning')); - - let placeWarning = function () { - if (select.val() === 'INFO') { - warning.detach(); - } else { - warning.insertAfter(select); - } - }; - - placeWarning(); - - $(select) - .select2({ - width: '120px', - minimumResultsForSearch: 999, - formatResult: format, - formatSelection: format - }) - .on('change', () => { - let newValue = select.val(); - setLogLevel(newValue); - placeWarning(); - }); - } +window.sonarqube.appStarted.then(options => { + var el = document.querySelector(options.el); + React.render(<Main/>, el); }); diff --git a/server/sonar-web/src/main/js/apps/system/item-boolean.js b/server/sonar-web/src/main/js/apps/system/item-boolean.js new file mode 100644 index 00000000000..58f6dd7d9b8 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/system/item-boolean.js @@ -0,0 +1,11 @@ +import React from 'react'; + +export default React.createClass({ + render() { + if (this.props.value) { + return <i className="icon-check"/>; + } else { + return <i className="icon-delete"/>; + } + } +}); diff --git a/server/sonar-web/src/main/js/apps/system/item-log-level.js b/server/sonar-web/src/main/js/apps/system/item-log-level.js new file mode 100644 index 00000000000..2f888d7100b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/system/item-log-level.js @@ -0,0 +1,20 @@ +import React from 'react'; +import { setLogLevel } from '../../api/system'; + +const LOG_LEVELS = ['INFO', 'DEBUG', 'TRACE']; + +export default React.createClass({ + onChange() { + let newValue = React.findDOMNode(this.refs.select).value; + setLogLevel(newValue); + }, + + render() { + let options = LOG_LEVELS.map(level => { + return <option key={level} value={level}>{level}</option>; + }); + return <select ref="select" + onChange={this.onChange} + defaultValue={this.props.value}>{options}</select>; + } +}); diff --git a/server/sonar-web/src/main/js/apps/system/item-object.js b/server/sonar-web/src/main/js/apps/system/item-object.js new file mode 100644 index 00000000000..15583def4bb --- /dev/null +++ b/server/sonar-web/src/main/js/apps/system/item-object.js @@ -0,0 +1,14 @@ +import React from 'react'; +import ItemValue from './item-value'; + +export default React.createClass({ + render() { + let rows = Object.keys(this.props.value).map(key => { + return <tr key={key}> + <td className="thin nowrap">{key}</td> + <td><ItemValue value={this.props.value[key]}/></td> + </tr>; + }); + return <table className="data">{rows}</table>; + } +}); diff --git a/server/sonar-web/src/main/js/apps/system/item-value.js b/server/sonar-web/src/main/js/apps/system/item-value.js new file mode 100644 index 00000000000..a4d2da93154 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/system/item-value.js @@ -0,0 +1,26 @@ +import React from 'react'; +import ItemBoolean from './item-boolean'; +import ItemObject from './item-object'; +import ItemLogLevel from './item-log-level'; + +export default React.createClass({ + render() { + if (this.props.name === 'Logs Level') { + return <ItemLogLevel value={this.props.value}/>; + } + + let rawValue = this.props.value, + formattedValue; + switch (typeof this.props.value) { + case 'boolean': + formattedValue = <ItemBoolean value={rawValue}/>; + break; + case 'object': + formattedValue = <ItemObject value={rawValue}/>; + break; + default: + formattedValue = <code>{rawValue}</code>; + } + return formattedValue; + } +}); diff --git a/server/sonar-web/src/main/js/apps/system/main.js b/server/sonar-web/src/main/js/apps/system/main.js new file mode 100644 index 00000000000..fe69d83a6c0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/system/main.js @@ -0,0 +1,55 @@ +import _ from 'underscore'; +import React from 'react'; +import { getSystemInfo } from '../../api/system'; +import Section from './section'; + +const SECTIONS_ORDER = ['SonarQube', 'Database', 'Plugins', 'System', 'ElasticSearch', 'JvmProperties', + 'ComputeEngineQueue']; + +export default React.createClass({ + componentDidMount() { + getSystemInfo().then(info => this.setState({ sections: this.parseSections(info) })); + }, + + parseSections (data) { + let sections = Object.keys(data).map(section => { + return { name: section, items: this.parseItems(data[section]) }; + }); + return this.orderSections(sections); + }, + + orderSections (sections) { + return _.sortBy(sections, section => SECTIONS_ORDER.indexOf(section.name)); + }, + + parseItems (data) { + let items = Object.keys(data).map(item => { + return { name: item, value: data[item] }; + }); + return this.orderItems(items); + }, + + orderItems (items) { + return _.sortBy(items, 'name'); + }, + + render() { + let sections = null; + if (this.state && this.state.sections) { + sections = this.state.sections.map(section => { + return <Section key={section.name} section={section.name} items={section.items}/>; + }); + } + + return <div className="page"> + <header className="page-header"> + <h1 className="page-title">{window.t('system_info.page')}</h1> + <div className="page-actions"> + <a className="spacer-right" href={window.baseUrl + '/api/system/logs'} id="logs-link">Logs</a> + <a href={window.baseUrl + '/api/system/info'} id="download-link">Download</a> + </div> + </header> + {sections} + </div>; + } +}); diff --git a/server/sonar-web/src/main/js/apps/system/section.js b/server/sonar-web/src/main/js/apps/system/section.js new file mode 100644 index 00000000000..63b05a45520 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/system/section.js @@ -0,0 +1,22 @@ +import React from 'react'; +import ItemValue from './item-value'; + +export default React.createClass({ + render() { + let items = this.props.items.map(item => { + return <tr key={item.name}> + <td className="thin"> + <div style={{ width: '25vw', overflow: 'hidden', textOverflow: 'ellipsis' }}>{item.name}</div> + </td> + <td style={{ wordBreak: 'break-all' }}><ItemValue name={item.name} value={item.value}/></td> + </tr>; + }); + + return <div className="big-spacer-bottom"> + <h3 className="spacer-bottom">{this.props.section}</h3> + <table className="data zebra" id={this.props.section}> + <tbody>{items}</tbody> + </table> + </div>; + } +}); |