PLT-12 adding log viewer
Этот коммит содержится в:
@@ -4,6 +4,7 @@
|
||||
var AdminSidebar = require('./admin_sidebar.jsx');
|
||||
var EmailTab = require('./email_settings.jsx');
|
||||
var JobsTab = require('./jobs_settings.jsx');
|
||||
var LogsTab = require('./logs.jsx');
|
||||
var Navbar = require('../../components/navbar.jsx');
|
||||
|
||||
export default class AdminController extends React.Component {
|
||||
@@ -28,6 +29,8 @@ export default class AdminController extends React.Component {
|
||||
tab = <EmailTab />;
|
||||
} else if (this.state.selected === 'job_settings') {
|
||||
tab = <JobsTab />;
|
||||
} else if (this.state.selected === 'logs') {
|
||||
tab = <LogsTab />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -83,7 +83,15 @@ export default class AdminSidebar extends React.Component {
|
||||
{'Email Settings'}
|
||||
</a>
|
||||
</li>
|
||||
<li><a href='#'>{'Other Settings'}</a></li>
|
||||
<li>
|
||||
<a
|
||||
href='#'
|
||||
className={this.isSelected('logs')}
|
||||
onClick={this.handleClick.bind(null, 'logs')}
|
||||
>
|
||||
{'Logs'}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
98
web/react/components/admin_console/logs.jsx
Обычный файл
98
web/react/components/admin_console/logs.jsx
Обычный файл
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
var AdminStore = require('../../stores/admin_store.jsx');
|
||||
var LoadingScreen = require('../loading_screen.jsx');
|
||||
var AsyncClient = require('../../utils/async_client.jsx');
|
||||
|
||||
export default class Logs extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onLogListenerChange = this.onLogListenerChange.bind(this);
|
||||
this.reload = this.reload.bind(this);
|
||||
|
||||
this.state = {
|
||||
logs: AdminStore.getLogs()
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
AdminStore.addLogChangeListener(this.onLogListenerChange);
|
||||
AsyncClient.getLogs();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
AdminStore.removeLogChangeListener(this.onLogListenerChange);
|
||||
}
|
||||
onLogListenerChange() {
|
||||
this.setState({
|
||||
logs: AdminStore.getLogs()
|
||||
});
|
||||
}
|
||||
|
||||
reload() {
|
||||
AdminStore.saveLogs(null);
|
||||
this.setState({
|
||||
logs: null
|
||||
});
|
||||
|
||||
AsyncClient.getLogs();
|
||||
}
|
||||
|
||||
render() {
|
||||
var content = null;
|
||||
|
||||
if (this.state.logs === null) {
|
||||
content = <LoadingScreen />;
|
||||
} else {
|
||||
content = [];
|
||||
|
||||
for (var i = 0; i < this.state.logs.length; i++) {
|
||||
var style = {
|
||||
whiteSpace: 'nowrap',
|
||||
fontFamily: 'monospace'
|
||||
};
|
||||
|
||||
if (this.state.logs[i].indexOf('[EROR]') > 0) {
|
||||
style.color = 'red';
|
||||
}
|
||||
|
||||
content.push(<br key={'br_' + i} />);
|
||||
content.push(
|
||||
<span
|
||||
key={'log_' + i}
|
||||
style={style}
|
||||
>
|
||||
{this.state.logs[i]}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var divStyle = {
|
||||
overflow: 'scroll',
|
||||
width: '100%',
|
||||
height: '800px',
|
||||
border: '1px solid #ddd',
|
||||
marginTop: '10px',
|
||||
padding: '5px',
|
||||
backgroundColor: 'white'
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='panel'>
|
||||
<h3>{'Server Logs'}</h3>
|
||||
<button
|
||||
type='submit'
|
||||
className='btn btn-primary'
|
||||
onClick={this.reload}
|
||||
>
|
||||
{'Reload'}
|
||||
</button>
|
||||
<div style={divStyle}>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
67
web/react/stores/admin_store.jsx
Обычный файл
67
web/react/stores/admin_store.jsx
Обычный файл
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
var BrowserStore = require('../stores/browser_store.jsx');
|
||||
|
||||
var Constants = require('../utils/constants.jsx');
|
||||
var ActionTypes = Constants.ActionTypes;
|
||||
|
||||
var LOG_CHANGE_EVENT = 'log_change';
|
||||
|
||||
class AdminStoreClass extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.logs = null;
|
||||
|
||||
this.emitLogChange = this.emitLogChange.bind(this);
|
||||
this.addLogChangeListener = this.addLogChangeListener.bind(this);
|
||||
this.removeLogChangeListener = this.removeLogChangeListener.bind(this);
|
||||
}
|
||||
|
||||
emitLogChange() {
|
||||
this.emit(LOG_CHANGE_EVENT);
|
||||
}
|
||||
|
||||
addLogChangeListener(callback) {
|
||||
this.on(LOG_CHANGE_EVENT, callback);
|
||||
}
|
||||
|
||||
removeLogChangeListener(callback) {
|
||||
this.removeListener(LOG_CHANGE_EVENT, callback);
|
||||
}
|
||||
|
||||
getLogs() {
|
||||
//return BrowserStore.getItem('logs');
|
||||
return this.logs;
|
||||
}
|
||||
|
||||
saveLogs(logs) {
|
||||
// if (logs === null) {
|
||||
// BrowserStore.removeItem('logs');
|
||||
// } else {
|
||||
// BrowserStore.setItem('logs', logs);
|
||||
// }
|
||||
|
||||
this.logs = logs;
|
||||
}
|
||||
}
|
||||
|
||||
var AdminStore = new AdminStoreClass();
|
||||
|
||||
AdminStoreClass.dispatchToken = AppDispatcher.register((payload) => {
|
||||
var action = payload.action;
|
||||
|
||||
switch (action.type) {
|
||||
case ActionTypes.RECIEVED_LOGS:
|
||||
AdminStore.saveLogs(action.logs);
|
||||
AdminStore.emitLogChange();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
export default AdminStore;
|
||||
@@ -319,6 +319,32 @@ export function getAudits() {
|
||||
);
|
||||
}
|
||||
|
||||
export function getLogs() {
|
||||
if (isCallInProgress('getLogs')) {
|
||||
return;
|
||||
}
|
||||
|
||||
callTracker.getLogs = utils.getTimestamp();
|
||||
client.getLogs(
|
||||
(data, textStatus, xhr) => {
|
||||
callTracker.getLogs = 0;
|
||||
|
||||
if (xhr.status === 304 || !data) {
|
||||
return;
|
||||
}
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECIEVED_LOGS,
|
||||
logs: data
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
callTracker.getLogs = 0;
|
||||
dispatchError(err, 'getLogs');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function findTeams(email) {
|
||||
if (isCallInProgress('findTeams_' + email)) {
|
||||
return;
|
||||
|
||||
@@ -294,6 +294,20 @@ export function getAudits(userId, success, error) {
|
||||
});
|
||||
}
|
||||
|
||||
export function getLogs(success, error) {
|
||||
$.ajax({
|
||||
url: '/api/v1/admin/logs',
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'GET',
|
||||
success: success,
|
||||
error: function onError(xhr, status, err) {
|
||||
var e = handleError('getLogs', xhr, status, err);
|
||||
error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function getMeSynchronous(success, error) {
|
||||
var currentUser = null;
|
||||
$.ajax({
|
||||
|
||||
@@ -34,7 +34,9 @@ module.exports = {
|
||||
CLICK_TEAM: null,
|
||||
RECIEVED_TEAM: null,
|
||||
|
||||
RECIEVED_CONFIG: null
|
||||
RECIEVED_CONFIG: null,
|
||||
|
||||
RECIEVED_LOGS: null
|
||||
}),
|
||||
|
||||
PayloadSources: keyMirror({
|
||||
|
||||
10
web/web.go
10
web/web.go
@@ -643,12 +643,10 @@ func loginCompleteOAuth(c *api.Context, w http.ResponseWriter, r *http.Request)
|
||||
|
||||
func adminConsole(c *api.Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if !c.IsSystemAdmin() {
|
||||
c.Err = model.NewAppError("adminConsole", "You do not have permission to access the admin console.", "")
|
||||
c.Err.StatusCode = http.StatusForbidden
|
||||
if !c.HasSystemAdminPermissions("adminConsole") {
|
||||
return
|
||||
} else {
|
||||
page := NewHtmlTemplatePage("admin_console", "Admin Console")
|
||||
page.Render(c, w)
|
||||
}
|
||||
|
||||
page := NewHtmlTemplatePage("admin_console", "Admin Console")
|
||||
page.Render(c, w)
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user