1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-15 09:04:04 +02:00
joplin/ElectronClient/gui/StatusScreen.jsx
Laurent Cozic c63c6370b5 Desktop: Refactored command system
The goal is to make the command system more modular, so each command can
be defined as a single object that includes a declaration (name, label,
etc.) and a runtime (to execute the command, test if it should be
enabled, etc.)

Utility methods are provided to convert a command to a menu item or a
toolbar button, thus reducing duplicated and boiler plate code across the
codebase (often the menu item logic was duplicated in the toolbar
button logic and vice versa).

The goal is to make it easier to add new commands (and associated menu
item and toolbar buttons) and to call them from
anywhere. This is also useful for plugins, which can also easily define
new commands.

Could also allow creating a command palette.
2020-07-03 22:32:39 +01:00

160 lines
3.9 KiB
JavaScript

const React = require('react');
const { connect } = require('react-redux');
const Setting = require('lib/models/Setting.js');
const { bridge } = require('electron').remote.require('./bridge');
const { Header } = require('./Header/Header.min.js');
const { themeStyle } = require('lib/theme');
const { _ } = require('lib/locale.js');
const { ReportService } = require('lib/services/report.js');
const fs = require('fs-extra');
class StatusScreenComponent extends React.Component {
constructor() {
super();
this.state = {
report: [],
};
}
UNSAFE_componentWillMount() {
this.resfreshScreen();
}
async resfreshScreen() {
const service = new ReportService();
const report = await service.status(Setting.value('sync.target'));
this.setState({ report: report });
}
async exportDebugReportClick() {
const filename = `syncReport-${new Date().getTime()}.csv`;
const filePath = bridge().showSaveDialog({
title: _('Please select where the sync status should be exported to'),
defaultPath: filename,
});
if (!filePath) return;
const service = new ReportService();
const csv = await service.basicItemList({ format: 'csv' });
await fs.writeFileSync(filePath, csv);
}
render() {
const theme = themeStyle(this.props.theme);
const style = this.props.style;
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
const retryStyle = Object.assign({}, theme.urlStyle, { marginLeft: 5 });
const retryAllStyle = Object.assign({}, theme.urlStyle, { marginTop: 5, display: 'inline-block' });
const containerPadding = 10;
const containerStyle = Object.assign({}, theme.containerStyle, {
padding: containerPadding,
height: style.height - theme.headerHeight - containerPadding * 2,
});
function renderSectionTitleHtml(key, title) {
return (
<h2 key={`section_${key}`} style={theme.h2Style}>
{title}
</h2>
);
}
function renderSectionRetryAllHtml(key, retryAllHandler) {
return (
<a key={`retry_all_${key}`} href="#" onClick={retryAllHandler} style={retryAllStyle}>
{_('Retry All')}
</a>
);
}
const renderSectionHtml = (key, section) => {
const itemsHtml = [];
itemsHtml.push(renderSectionTitleHtml(section.title, section.title));
for (const n in section.body) {
if (!section.body.hasOwnProperty(n)) continue;
const item = section.body[n];
let text = '';
let retryLink = null;
if (typeof item === 'object') {
if (item.canRetry) {
const onClick = async () => {
await item.retryHandler();
this.resfreshScreen();
};
retryLink = (
<a href="#" onClick={onClick} style={retryStyle}>
{_('Retry')}
</a>
);
}
text = item.text;
} else {
text = item;
}
if (!text) text = '\xa0';
itemsHtml.push(
<div style={theme.textStyle} key={`item_${n}`}>
<span>{text}</span>
{retryLink}
</div>
);
}
if (section.canRetryAll) {
itemsHtml.push(renderSectionRetryAllHtml(section.title, section.retryAllHandler));
}
return <div key={key}>{itemsHtml}</div>;
};
function renderBodyHtml(report) {
const sectionsHtml = [];
for (let i = 0; i < report.length; i++) {
const section = report[i];
if (!section.body.length) continue;
sectionsHtml.push(renderSectionHtml(i, section));
}
return <div>{sectionsHtml}</div>;
}
const body = renderBodyHtml(this.state.report);
return (
<div style={style}>
<Header style={headerStyle} />
<div style={containerStyle}>
<a style={theme.textStyle} onClick={() => this.exportDebugReportClick()} href="#">
Export debug report
</a>
{body}
</div>
</div>
);
}
}
const mapStateToProps = state => {
return {
theme: state.settings.theme,
settings: state.settings,
locale: state.settings.locale,
};
};
const StatusScreen = connect(mapStateToProps)(StatusScreenComponent);
module.exports = { StatusScreen };