insomnia/packages/insomnia-app/app/ui/components/settings/plugins.js
2018-12-12 12:36:11 -05:00

212 lines
6.2 KiB
JavaScript

// @flow
import type { Plugin } from '../../../plugins/index';
import { getPlugins } from '../../../plugins/index';
import * as React from 'react';
import autobind from 'autobind-decorator';
import * as electron from 'electron';
import Button from '../base/button';
import CopyButton from '../base/copy-button';
import { reload } from '../../../templating/index';
import installPlugin from '../../../plugins/install';
import HelpTooltip from '../help-tooltip';
import Link from '../base/link';
import { delay } from '../../../common/misc';
import { PLUGIN_PATH } from '../../../common/constants';
type State = {
plugins: Array<Plugin>,
npmPluginValue: string,
error: string,
isInstallingFromNpm: boolean,
isRefreshingPlugins: boolean,
};
@autobind
class Plugins extends React.PureComponent<void, State> {
_isMounted: boolean;
constructor(props: any) {
super(props);
this.state = {
plugins: [],
npmPluginValue: '',
error: '',
isInstallingFromNpm: false,
isRefreshingPlugins: false,
};
}
_handleClearError() {
this.setState({ error: '' });
}
_handleAddNpmPluginChange(e: Event) {
if (e.target instanceof HTMLInputElement) {
this.setState({ npmPluginValue: e.target.value });
}
}
async _handleAddFromNpm(e: Event): Promise<void> {
e.preventDefault();
this.setState({ isInstallingFromNpm: true });
const newState = { isInstallingFromNpm: false, error: '' };
try {
await installPlugin(this.state.npmPluginValue.trim());
await this._handleRefreshPlugins();
} catch (err) {
newState.error = err.message;
}
this.setState(newState);
}
static _handleOpenDirectory(directory: string): void {
electron.remote.shell.showItemInFolder(directory);
}
async _handleRefreshPlugins(): Promise<void> {
const start = Date.now();
this.setState({ isRefreshingPlugins: true });
// Get and reload plugins
const plugins = await getPlugins(true);
reload();
// Delay loading for at least 500ms. UX FTW!
const delta = Date.now() - start;
await delay(500 - delta);
if (this._isMounted) {
this.setState({ plugins, isRefreshingPlugins: false });
}
}
async _handleClickRefreshPlugins() {
await this._handleRefreshPlugins();
}
static _handleClickShowPluginsFolder() {
electron.remote.shell.showItemInFolder(PLUGIN_PATH);
}
componentDidMount() {
this._isMounted = true;
this._handleRefreshPlugins();
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
const { plugins, error, isInstallingFromNpm, isRefreshingPlugins } = this.state;
return (
<div>
<p className="notice info no-margin-top">
Plugins is still an experimental feature. See{' '}
<Link href="https://support.insomnia.rest/article/26-plugins">Documentation</Link> for
more info.
</p>
{plugins.length === 0 ? (
<div className="text-center faint italic pad">No Plugins Added</div>
) : (
<table className="table--fancy table--striped margin-top margin-bottom">
<thead>
<tr>
<th>Name</th>
<th>Version</th>
<th>Folder</th>
</tr>
</thead>
<tbody>
{plugins.map(
plugin =>
!plugin.directory ? null : (
<tr key={plugin.name}>
<td>
{plugin.name}
{plugin.description && (
<HelpTooltip info className="space-left">
{plugin.description}
</HelpTooltip>
)}
</td>
<td>{plugin.version}</td>
<td className="no-wrap" style={{ width: '10rem' }}>
<CopyButton
className="btn btn--outlined btn--super-duper-compact"
title={plugin.directory}
content={plugin.directory}>
Copy Path
</CopyButton>{' '}
<Button
className="btn btn--outlined btn--super-duper-compact"
onClick={Plugins._handleOpenDirectory}
value={plugin.directory}>
Show Folder
</Button>
</td>
</tr>
),
)}
</tbody>
</table>
)}
{error && (
<div className="notice error text-left margin-bottom">
<button className="pull-right icon" onClick={this._handleClearError}>
<i className="fa fa-times" />
</button>
<div className="selectable force-pre-wrap">{error}</div>
</div>
)}
<form onSubmit={this._handleAddFromNpm}>
<div className="form-row">
<div className="form-control form-control--outlined">
<input
onChange={this._handleAddNpmPluginChange}
disabled={isInstallingFromNpm}
type="text"
placeholder="npm-package-name"
/>
</div>
<div className="form-control width-auto">
<button className="btn btn--clicky" disabled={isInstallingFromNpm}>
{isInstallingFromNpm && <i className="fa fa-refresh fa-spin space-right" />}
Install Plugin
</button>
</div>
</div>
</form>
<hr />
<div className="text-right">
<button
type="button"
className="btn btn--clicky"
onClick={Plugins._handleClickShowPluginsFolder}>
Show Plugins Folder
</button>
<button
type="button"
disabled={isRefreshingPlugins}
className="btn btn--clicky space-left"
onClick={this._handleClickRefreshPlugins}>
Reload Plugin List
{isRefreshingPlugins && <i className="fa fa-refresh fa-spin space-left" />}
</button>
</div>
</div>
);
}
}
export default Plugins;