Этот коммит содержится в:
=Corey Hulen
2015-09-10 18:32:22 -07:00
родитель 41439eb801
Коммит e06e292be7
14 изменённых файлов: 338 добавлений и 15 удалений

Просмотреть файл

@@ -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 Обычный файл
Просмотреть файл

@@ -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 Обычный файл
Просмотреть файл

@@ -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({

Просмотреть файл

@@ -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)
}