read infos from package.json
Summary: Adding the properties from a plugin's `package.json` as static properties to the class. The name from `package.json` is used as it's `id`. This allows us in the future to add meta information about a plugin to it's package.json and still use the data inside the app. Reviewed By: priteshrnandgaonkar Differential Revision: D13417288 fbshipit-source-id: 3d0a62d4cb0115153cce1aaee677b9680fefebf4
This commit is contained in:
committed by
Facebook Github Bot
parent
e23da69db9
commit
6ffc027051
@@ -472,7 +472,7 @@ class NotificationItem extends Component<ItemProps, ItemState> {
|
||||
const items = [];
|
||||
if (props.onHidePlugin && props.plugin) {
|
||||
items.push({
|
||||
label: `Hide ${props.plugin.title} plugin`,
|
||||
label: `Hide ${props.plugin.title || props.plugin.id} plugin`,
|
||||
click: this.props.onHidePlugin,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -120,9 +120,8 @@ class PluginContainer extends PureComponent<Props> {
|
||||
<React.Fragment>
|
||||
<Container key="plugin">
|
||||
<ErrorBoundary
|
||||
heading={`Plugin "${
|
||||
activePlugin.title
|
||||
}" encountered an error during render`}
|
||||
heading={`Plugin "${activePlugin.title ||
|
||||
'Unknown'}" encountered an error during render`}
|
||||
logger={this.props.logger}>
|
||||
{React.createElement(activePlugin, props)}
|
||||
</ErrorBoundary>
|
||||
|
||||
@@ -9,9 +9,6 @@ import {createTablePlugin} from '../createTablePlugin.js';
|
||||
import {FlipperPlugin} from '../plugin.js';
|
||||
|
||||
const PROPS = {
|
||||
title: 'Plugin Title',
|
||||
id: 'pluginID',
|
||||
icon: 'icon',
|
||||
method: 'method',
|
||||
resetMethod: 'resetMethod',
|
||||
columns: {},
|
||||
@@ -25,24 +22,6 @@ test('createTablePlugin returns FlipperPlugin', () => {
|
||||
expect(tablePlugin.prototype).toBeInstanceOf(FlipperPlugin);
|
||||
});
|
||||
|
||||
test('Plugin ID is set', () => {
|
||||
const id = 'pluginID';
|
||||
const tablePlugin = createTablePlugin({...PROPS, id});
|
||||
expect(tablePlugin.id).toBe(id);
|
||||
});
|
||||
|
||||
test('Plugin title is set', () => {
|
||||
const title = 'My Plugin Title';
|
||||
const tablePlugin = createTablePlugin({...PROPS, title});
|
||||
expect(tablePlugin.title).toBe(title);
|
||||
});
|
||||
|
||||
test('Plugin icon is set', () => {
|
||||
const icon = 'icon';
|
||||
const tablePlugin = createTablePlugin({...PROPS, icon});
|
||||
expect(tablePlugin.icon).toBe(icon);
|
||||
});
|
||||
|
||||
test('persistedStateReducer is resetting data', () => {
|
||||
const resetMethod = 'resetMethod';
|
||||
const tablePlugin = createTablePlugin({...PROPS, resetMethod});
|
||||
|
||||
@@ -146,11 +146,11 @@ class PluginSidebarListItem extends Component<{
|
||||
<ListItem active={isActive} onClick={this.props.onClick}>
|
||||
<PluginIcon
|
||||
isActive={isActive}
|
||||
name={plugin.icon}
|
||||
name={plugin.icon || 'apps'}
|
||||
backgroundColor={iconColor}
|
||||
color={colors.white}
|
||||
/>
|
||||
<PluginName>{plugin.title}</PluginName>
|
||||
<PluginName>{plugin.title || plugin.id}</PluginName>
|
||||
</ListItem>
|
||||
);
|
||||
}
|
||||
@@ -228,7 +228,11 @@ class MainSidebar extends PureComponent<MainSidebarProps> {
|
||||
}>
|
||||
<PluginIcon
|
||||
color={colors.light50}
|
||||
name={numNotifications > 0 ? NotificationsHub.icon : 'bell-null'}
|
||||
name={
|
||||
numNotifications > 0
|
||||
? NotificationsHub.icon || 'bell'
|
||||
: 'bell-null'
|
||||
}
|
||||
isActive={selectedPlugin === NotificationsHub.id}
|
||||
/>
|
||||
<PluginName
|
||||
|
||||
@@ -22,17 +22,14 @@ type RowData = {
|
||||
id: ID,
|
||||
};
|
||||
|
||||
type Props<T> = {|
|
||||
title: string,
|
||||
id: string,
|
||||
icon: string,
|
||||
type Props<T> = {
|
||||
method: string,
|
||||
resetMethod?: string,
|
||||
columns: TableColumns,
|
||||
columnSizes: TableColumnSizes,
|
||||
renderSidebar: (row: T) => any,
|
||||
buildRow: (row: T) => any,
|
||||
|};
|
||||
};
|
||||
|
||||
type PersistedState<T> = {|
|
||||
rows: TableRows,
|
||||
@@ -59,9 +56,6 @@ type State = {|
|
||||
export function createTablePlugin<T: RowData>(props: Props<T>) {
|
||||
// $FlowFixMe persistedStateReducer is fine to accept payload of type T, because it is of type RowData
|
||||
return class extends FlipperPlugin<State, *, PersistedState<T>> {
|
||||
static title = props.title;
|
||||
static id = props.id;
|
||||
static icon = props.icon;
|
||||
static keyboardActions = ['clear', 'createPaste'];
|
||||
|
||||
static defaultPersistedState: PersistedState<T> = {
|
||||
@@ -170,7 +164,7 @@ export function createTablePlugin<T: RowData>(props: Props<T>) {
|
||||
return (
|
||||
<FlexColumn grow={true}>
|
||||
<SearchableTable
|
||||
key={props.id}
|
||||
key={this.constructor.id}
|
||||
rowLineHeight={28}
|
||||
floating={false}
|
||||
multiline={true}
|
||||
|
||||
@@ -7,4 +7,6 @@
|
||||
|
||||
import {FlipperPlugin} from '../../plugin.js';
|
||||
|
||||
export default class extends FlipperPlugin {}
|
||||
export default class extends FlipperPlugin {
|
||||
static id = 'Static ID';
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import reducers from '../../reducers/index.js';
|
||||
import Logger from '../../fb-stubs/Logger.js';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import {TEST_PASSING_GK, TEST_FAILING_GK} from '../../fb-stubs/GK';
|
||||
import TestPlugin from './TestPlugin';
|
||||
|
||||
const mockStore = configureStore([])(reducers(undefined, {type: 'INIT'}));
|
||||
const logger = new Logger();
|
||||
@@ -111,11 +112,17 @@ test('requirePlugin returns null for invalid requires', () => {
|
||||
});
|
||||
|
||||
test('requirePlugin loads plugin', () => {
|
||||
const name = 'pluginID';
|
||||
const homepage = 'https://fb.workplace.com/groups/230455004101832/';
|
||||
const plugin = requirePlugin(require)({
|
||||
name: 'pluginID',
|
||||
name,
|
||||
homepage,
|
||||
out: path.join(__dirname, 'TestPlugin.js'),
|
||||
// $FlowFixMe Electron require returns default exports wrapped in an object
|
||||
}).default;
|
||||
|
||||
});
|
||||
// $FlowFixMe
|
||||
expect(plugin.prototype).toBeInstanceOf(FlipperPlugin);
|
||||
// $FlowFixMe
|
||||
expect(plugin.homepage).toBe(homepage);
|
||||
// $FlowFixMe
|
||||
expect(plugin.id).toBe(TestPlugin.id);
|
||||
});
|
||||
|
||||
@@ -32,6 +32,7 @@ export default (store: Store, logger: Logger) => {
|
||||
window.Flipper = Flipper;
|
||||
|
||||
const disabled = checkDisabled();
|
||||
|
||||
const initialPlugins: Array<
|
||||
Class<FlipperPlugin<> | FlipperDevicePlugin<>>,
|
||||
> = [...getBundledPlugins(), ...getDynamicPlugins()]
|
||||
@@ -113,10 +114,27 @@ export function requirePlugin(
|
||||
pluginDefinition: PluginDefinition,
|
||||
): ?Class<FlipperPlugin<> | FlipperDevicePlugin<>> => {
|
||||
try {
|
||||
const plugin = requireFunction(pluginDefinition.out);
|
||||
let plugin = requireFunction(pluginDefinition.out);
|
||||
if (plugin.default) {
|
||||
plugin = plugin.default;
|
||||
}
|
||||
if (!plugin.prototype instanceof FlipperBasePlugin) {
|
||||
throw new Error(`Plugin ${plugin.name} is not a FlipperBasePlugin`);
|
||||
}
|
||||
|
||||
// set values from package.json as static variables on class
|
||||
Object.keys(pluginDefinition).forEach(key => {
|
||||
if (key === 'name') {
|
||||
plugin.id = plugin.id || pluginDefinition.name;
|
||||
} else if (key === 'id') {
|
||||
throw new Error(
|
||||
'Field "id" not allowed in package.json. The plugin\'s name will be used as ID"',
|
||||
);
|
||||
} else {
|
||||
plugin[key] = plugin[key] || pluginDefinition[key];
|
||||
}
|
||||
});
|
||||
|
||||
return plugin;
|
||||
} catch (e) {
|
||||
console.error(pluginDefinition, e);
|
||||
|
||||
@@ -49,9 +49,13 @@ export class FlipperBasePlugin<
|
||||
Actions = *,
|
||||
PersistedState = *,
|
||||
> extends React.Component<Props<PersistedState>, State> {
|
||||
static title: string = 'Unknown';
|
||||
static id: string = 'Unknown';
|
||||
static icon: string = 'apps';
|
||||
static title: ?string = null;
|
||||
static id: string = '';
|
||||
static icon: ?string = null;
|
||||
static bugs: ?{
|
||||
email?: string,
|
||||
url?: string,
|
||||
} = null;
|
||||
static keyboardActions: ?KeyboardActions;
|
||||
static screenshot: ?string;
|
||||
static defaultPersistedState: PersistedState;
|
||||
@@ -78,7 +82,7 @@ export class FlipperBasePlugin<
|
||||
onKeyboardAction: ?(action: string) => void;
|
||||
|
||||
toJSON() {
|
||||
return `<${this.constructor.name}#${this.constructor.title}>`;
|
||||
return `<${this.constructor.name}#${this.constructor.id}>`;
|
||||
}
|
||||
|
||||
// methods to be overriden by plugins
|
||||
|
||||
Reference in New Issue
Block a user