Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/logreader.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--js/App.js42
-rw-r--r--js/Components/LogUploader.js40
-rw-r--r--js/Components/LogUploader.less3
-rw-r--r--js/Providers/LogFile.js16
-rw-r--r--js/Providers/LogProvider.js7
-rw-r--r--package.json1
6 files changed, 97 insertions, 12 deletions
diff --git a/js/App.js b/js/App.js
index d9fd46c..233a2cd 100644
--- a/js/App.js
+++ b/js/App.js
@@ -4,9 +4,11 @@ import ReactScrolla from 'react-scrolla';
import {LogProvider} from './Providers/LogProvider.js';
import {LogTable} from './Components/LogTable.js';
import {ToggleEntry} from './Components/ToggleEntry.js';
-import {App as AppContainer, SideBar, Content} from 'oc-react-components';
+import {LogUploader} from './Components/LogUploader.js';
+import {App as AppContainer, Entry, SideBar, Content, Separator} from 'oc-react-components';
import {LogSearch} from './Search.js';
+import {LogFile} from './Providers/LogFile.js'
import styles from '../css/app.css';
@@ -14,31 +16,36 @@ export class App extends Component {
state = {
'entries': [],
'loading': false,
- 'levels': [false, false, false, false, false]
+ 'levels': [false, false, false, false, false],
+ provider: null
};
constructor () {
super();
this.logProvider = new LogProvider(50);
this.logProvider.on('entries', entries => {
- this.setState({entries});
+ if (this.state.provider === this.logProvider) {
+ this.setState({entries});
+ }
});
OCA.Search.logreader = new LogSearch(this.logProvider);
this.saveLevels = _.debounce(this.logProvider.setLevels, 100);
}
- async componentDidMount() {
+ async componentDidMount () {
const levels = await this.logProvider.getLevels();
- this.setState({levels});
+ this.setState({levels, provider: this.logProvider});
this.logProvider.load();
}
- fetchNextPage = async() => {
- this.setState({loading: true});
- this.logProvider.limit += 25;
- await this.logProvider.load();
- this.setState({loading: false});
- };
+ fetchNextPage = _.throttle(async() => {
+ if (this.state.provider.hasMore) {
+ this.setState({loading: true});
+ this.state.provider.limit += 25;
+ await this.state.provider.load();
+ this.setState({loading: false});
+ }
+ }, 100);
setLevel (level, newState) {
let levels = this.state.levels;
@@ -53,6 +60,17 @@ export class App extends Component {
this.saveLevels(levels);
}
+ onLogFile = (content) => {
+ const logFile = new LogFile(content);
+ logFile.on('entries', entries => {
+ if (this.state.provider === logFile) {
+ this.setState({entries});
+ }
+ });
+ this.setState({provider: logFile, entries: []});
+ logFile.load();
+ };
+
render () {
let entries = this.state.entries.filter(entry=> {
return this.state.levels[entry.level];
@@ -70,6 +88,8 @@ export class App extends Component {
return (
<AppContainer appId="logreader">
<SideBar>
+ <Entry><LogUploader onLogFile={this.onLogFile}/></Entry>
+ <Separator/>
{filters}
</SideBar>
diff --git a/js/Components/LogUploader.js b/js/Components/LogUploader.js
new file mode 100644
index 0000000..de14340
--- /dev/null
+++ b/js/Components/LogUploader.js
@@ -0,0 +1,40 @@
+import {Component} from 'react/addons';
+import Dropzone from 'react-dropzone';
+
+import style from './LogUploader.less';
+
+export class LogUploader extends Component {
+ state = {
+ message: 'Load log file...'
+ };
+
+ isLog (content) {
+ return content[0] === '{' && content[content.length - 1] === '}';
+ }
+
+ onDrop = (files) => {
+ const file = files[0];
+ const reader = new FileReader();
+ reader.onload = (e) => {
+ const content = e.target.result.trim();
+ if (!this.isLog(content)) {
+ this.setState({message: 'Invalid log file'});
+ return;
+ }
+ this.props.onLogFile(content);
+ };
+ reader.readAsText(file);
+ };
+
+ render () {
+ const dropStyle = {
+ margin: '0 -12px',
+ padding: '0 12px'
+ };
+ return (
+ <Dropzone style={dropStyle} onDrop={this.onDrop}>
+ {this.state.message}
+ </Dropzone>
+ );
+ }
+}
diff --git a/js/Components/LogUploader.less b/js/Components/LogUploader.less
new file mode 100644
index 0000000..26bc244
--- /dev/null
+++ b/js/Components/LogUploader.less
@@ -0,0 +1,3 @@
+.logSelect {
+ margin: 0 -12px;
+}
diff --git a/js/Providers/LogFile.js b/js/Providers/LogFile.js
new file mode 100644
index 0000000..24a993b
--- /dev/null
+++ b/js/Providers/LogFile.js
@@ -0,0 +1,16 @@
+import {LogProvider} from './LogProvider.js'
+
+export class LogFile extends LogProvider {
+ constructor (content, limit) {
+ super(limit);
+ this.content = content;
+ this.lines = this.content.split('\n');
+ }
+
+ async loadEntries (offset, count = 50) {
+ const start = this.lines.length - offset;
+ const end = Math.max(start - count - 2, 0);
+ const entries = this.lines.slice(end, start).reverse().map(JSON.parse)
+ return {data: entries};
+ }
+}
diff --git a/js/Providers/LogProvider.js b/js/Providers/LogProvider.js
index c199005..622a15e 100644
--- a/js/Providers/LogProvider.js
+++ b/js/Providers/LogProvider.js
@@ -3,7 +3,9 @@ import {EventEmitter} from 'events';
export class LogProvider extends EventEmitter {
static levels = ['Debug', 'Info', 'Warning', 'Error', 'Fatal'];
+ fromFile = false;
cachedEntries = [];
+ hasMore = true;
constructor (limit = 50) {
super();
@@ -37,10 +39,13 @@ export class LogProvider extends EventEmitter {
async load () {
this.loading = true;
- if (this.cachedEntries.length >= this.limit) {
+ if (this.cachedEntries.length >= this.limit || this.fromFile || !this.hasMore) {
return;
}
var newData = await this.loadEntries(this.cachedEntries.length, this.limit - this.cachedEntries.length);
+ if(newData.data.length === 0) {
+ this.hasMore = false;
+ }
this.cachedEntries = this.cachedEntries.concat(newData.data);
this.loading = false;
this.emit('entries', this.cachedEntries);
diff --git a/package.json b/package.json
index 47b16cd..ddf5c3c 100644
--- a/package.json
+++ b/package.json
@@ -60,6 +60,7 @@
"less-loader": "^2.2.0",
"oc-react-components": "^0.1.5",
"react": "^0.13.3",
+ "react-dropzone": "^2.1.0",
"react-responsive": "0.0.8",
"react-scrolla": "^0.1.0",
"react-time": "^3.0.0"