Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ test_logs

# AI tools
.claude
.worktrees
45 changes: 41 additions & 4 deletions src/dashboard/Data/Logs/Logs.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*/
import Button from 'components/Button/Button.react';
import CategoryList from 'components/CategoryList/CategoryList.react';
import DashboardView from 'dashboard/DashboardView.react';
import EmptyState from 'components/EmptyState/EmptyState.react';
Expand Down Expand Up @@ -32,6 +33,8 @@ class Logs extends DashboardView {
this.state = {
logs: undefined,
release: undefined,
loading: false,
hasMore: false,
};
}

Expand All @@ -47,14 +50,38 @@ class Logs extends DashboardView {
}
}

fetchLogs(app, type) {
fetchLogs(app, type, until) {
const PAGE_SIZE = 100;
const typeParam = (type || 'INFO').toUpperCase();
app.getLogs(typeParam).then(
logs => this.setState({ logs }),
() => this.setState({ logs: [] })
const options = { size: PAGE_SIZE };
if (until) {
options.until = until;
}
this.setState({ loading: true });
app.getLogs(typeParam, options).then(
newLogs => {
this.setState(prevState => ({
logs: until && Array.isArray(prevState.logs)
? prevState.logs.concat(newLogs)
: newLogs,
hasMore: newLogs.length >= PAGE_SIZE,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
loading: false,
}));
},
() => this.setState({ logs: [], hasMore: false, loading: false })
);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}

handleLoadMore() {
const logs = this.state.logs;
if (!logs || logs.length === 0) {
return;
}
const oldestLog = logs[logs.length - 1];
const oldestTimestamp = oldestLog.timestamp.iso || oldestLog.timestamp;
this.fetchLogs(this.context, this.props.params.type, oldestTimestamp);
}
Comment thread
dblythy marked this conversation as resolved.

// As parse-server doesn't support (yet?) versioning, we are disabling
// this call in the meantime.

Expand Down Expand Up @@ -115,6 +142,16 @@ class Logs extends DashboardView {
<LogViewEntry key={timestamp} text={message} timestamp={timestamp} />
))}
</LogView>
{this.state.hasMore && (
<div className={styles.showMore}>
<Button
progress={this.state.loading}
color="blue"
value="Load more logs"
onClick={() => this.handleLoadMore()}
/>
</div>
)}
</div>
);
}
Expand Down
5 changes: 5 additions & 0 deletions src/dashboard/Data/Logs/Logs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@
right: 0;
bottom: 0;
}

.showMore {
padding: 20px;
text-align: center;
}
25 changes: 17 additions & 8 deletions src/lib/ParseApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,24 @@ export default class ParseApp {

/**
* Fetches scriptlogs from api.parse.com
* lines - maximum number of lines to fetch
* since - only fetch lines since this Date
* level - log level (info or error)
* options.from - only fetch logs after this date
* options.until - only fetch logs before this date
* options.size - maximum number of logs to fetch (default 100)
* options.order - sort order (asc or desc)
*/
getLogs(level, since) {
const path =
'scriptlog?level=' +
encodeURIComponent(level.toLowerCase()) +
'&n=100' +
(since ? '&startDate=' + encodeURIComponent(since.getTime()) : '');
getLogs(level, { from, until, size = 100, order } = {}) {
let path = 'scriptlog?level=' + encodeURIComponent(level.toLowerCase());
path += '&size=' + encodeURIComponent(size);
if (from) {
path += '&from=' + encodeURIComponent(from);
}
if (until) {
path += '&until=' + encodeURIComponent(until);
}
if (order) {
path += '&order=' + encodeURIComponent(order);
}
return this.apiRequest('GET', path, {}, { useMasterKey: true });
}

Expand Down
Loading