",
"license": "MIT",
+ "jest": {
+ "automock": false,
+ "testEnvironment": "node"
+ },
"dependencies": {
"application-config-path": "^0.1.0",
"co": "^4.6.0",
diff --git a/app/renderer-jsx/app.jsx b/app/renderer-jsx/app.jsx
index 9b23cc46..8b50b9d0 100644
--- a/app/renderer-jsx/app.jsx
+++ b/app/renderer-jsx/app.jsx
@@ -7,6 +7,7 @@ const lo_map = require('lodash.map');
const lo_reject = require('lodash.reject');
const lo_clamp = require('lodash.clamp');
const lo_isString = require('lodash.isstring');
+const lo_assign = require('lodash.assign');
const React = require('react');
const ReactDOM = require('react-dom');
@@ -19,7 +20,7 @@ const Ticket = require('./ticket');
const searchTicket = new Ticket();
const previewTicket = new Ticket();
-import { TextField, Avatar, SelectableContainerEnhance, List, ListItem, Subheader, FontIcon } from 'material-ui';
+import { TextField, Avatar, SelectableContainerEnhance, List, ListItem, Subheader, FontIcon, IconButton } from 'material-ui';
import MuiThemeProvider from 'material-ui/lib/MuiThemeProvider';
import getMuiTheme from 'material-ui/lib/styles/getMuiTheme';
import { Notification } from 'react-notification';
@@ -314,6 +315,39 @@ class AppContainer extends React.Component {
this.refs.query.focus();
}
+ displayRightButton(i) {
+ const defaultConfig = {
+ className: 'fa fa-info',
+ color: '#009688',
+ hoverColor: '#00695c',
+ tooltip: ''
+ };
+ const result = this.state.results[i];
+ if (!result.button) {
+ return null;
+ }
+ const btnConfig = lo_assign({}, defaultConfig, result.button);
+ const fontIcon =
+ ;
+ return ;
+ }
+
+ handleRightButtonClick(result, evt) {
+ evt.stopPropagation();
+ const pluginId = result.pluginId;
+ const id = result.id;
+ const payload = result.payload;
+ rpc.send('buttonAction', { pluginId, id, payload });
+ }
+
parseIconUrl(iconUrl) {
if (!lo_isString(iconUrl)) {
return null;
@@ -335,6 +369,7 @@ class AppContainer extends React.Component {
for (let i = 0; i < results.length; ++i) {
const result = results[i];
const avatar = this.parseIconUrl(result.icon);
+ const rightIcon = this.displayRightButton(i);
if (result.group !== lastGroup) {
const headerId = `header.${i}`;
list.push(
@@ -357,6 +392,7 @@ class AppContainer extends React.Component {
onClick={this.handleItemClick.bind(this, i)}
onKeyDown={this.handleKeyDown.bind(this)}
leftAvatar={avatar}
+ rightIconButton={rightIcon}
/>
);
}
diff --git a/app/renderer-jsx/schema-form/component-selector.js b/app/renderer-jsx/schema-form/component-selector.js
index a3467841..011166db 100644
--- a/app/renderer-jsx/schema-form/component-selector.js
+++ b/app/renderer-jsx/schema-form/component-selector.js
@@ -1,13 +1,30 @@
'use strict';
-const components = {};
+const lo_isString = require('lodash.isstring');
+const componentInfos = [];
-function select(type) {
- return components[type];
+function select(schema) {
+ for (const componentInfo of componentInfos) {
+ const filter = componentInfo.filter;
+ const componentClass = componentInfo.componentClass;
+ // String matching
+ if (lo_isString(filter)) {
+ if (filter === schema.type)
+ return componentClass;
+ continue;
+ }
+ // Function matching
+ if (filter(schema))
+ return componentClass;
+ }
+ return null;
}
-function inject(type, componentClass) {
- components[type] = componentClass;
+function inject(filter, componentClass) {
+ componentInfos.push({
+ filter,
+ componentClass
+ });
}
module.exports = {
diff --git a/app/renderer-jsx/schema-form/components/array.jsx b/app/renderer-jsx/schema-form/components/array.jsx
index 3fff2299..75fc8731 100644
--- a/app/renderer-jsx/schema-form/components/array.jsx
+++ b/app/renderer-jsx/schema-form/components/array.jsx
@@ -39,7 +39,7 @@ class ArrayComponent extends React.Component {
}
const childSchema = schema.items;
- const ChildComponent = componentSelector.select(childSchema.type);
+ const ChildComponent = componentSelector.select(childSchema);
if (ChildComponent === undefined)
return (Error
);
diff --git a/app/renderer-jsx/schema-form/components/enum.jsx b/app/renderer-jsx/schema-form/components/enum.jsx
new file mode 100644
index 00000000..cba713d3
--- /dev/null
+++ b/app/renderer-jsx/schema-form/components/enum.jsx
@@ -0,0 +1,43 @@
+'use strict';
+
+import React from 'react';
+import { SelectField, MenuItem } from 'material-ui';
+
+const utils = require('../utils');
+
+class EnumComponent extends React.Component {
+ handleChange(evt, idx, val) {
+ const { onChange, path } = this.props;
+ onChange(path, val);
+ }
+
+ render() {
+ const { schema, model, name, path, errors } = this.props;
+ let title = schema.title || name;
+ const description = utils.wrapDescription(schema.description);
+ const items = [];
+
+ if (title !== undefined) {
+ title = ({title}
);
+ }
+
+ for (const itemData of schema.enum) {
+ const item = ();
+ items.push(item);
+ }
+
+ return (
+
+ {title}
+ {description}
+
+ {items}
+
+
+ );
+ }
+}
+
+module.exports = EnumComponent;
diff --git a/app/renderer-jsx/schema-form/components/object.jsx b/app/renderer-jsx/schema-form/components/object.jsx
index b10dfb5d..b0913755 100644
--- a/app/renderer-jsx/schema-form/components/object.jsx
+++ b/app/renderer-jsx/schema-form/components/object.jsx
@@ -21,7 +21,7 @@ class ObjectComponent extends React.Component {
for (const childName in properties) {
const property = properties[childName];
const type = property.type;
- const Component = componentSelector.select(type);
+ const Component = componentSelector.select(property);
if (Component === undefined)
continue;
diff --git a/app/renderer-jsx/schema-form/schema-form.jsx b/app/renderer-jsx/schema-form/schema-form.jsx
index 80fb2ae5..493f64d9 100644
--- a/app/renderer-jsx/schema-form/schema-form.jsx
+++ b/app/renderer-jsx/schema-form/schema-form.jsx
@@ -9,6 +9,7 @@ import { Validator } from 'jsonschema';
const validator = new Validator();
const componentSelector = require('./component-selector');
+componentSelector.inject((schema) => schema.enum !== undefined, require('./components/enum'));
componentSelector.inject('object', require('./components/object'));
componentSelector.inject('array', require('./components/array'));
componentSelector.inject('string', require('./components/string'));
@@ -43,7 +44,7 @@ class SchemaForm extends React.Component {
render() {
const { title, schema, model } = this.state;
- const FormComponent = componentSelector.select(schema.type);
+ const FormComponent = componentSelector.select(schema);
const errors = validator.validate(model, schema).errors;
let headerComponent = null;
diff --git a/app/utils/__tests__/schema-defaults.spec.js b/app/utils/__tests__/schema-defaults.spec.js
index 0d840079..e23397c6 100644
--- a/app/utils/__tests__/schema-defaults.spec.js
+++ b/app/utils/__tests__/schema-defaults.spec.js
@@ -1,7 +1,6 @@
-/* global jest, describe, it, expect */
'use strict';
-const defaults = require.requireActual('../schema-defaults');
+const defaults = require('../schema-defaults');
describe('schema-defaults.js', () => {
@@ -27,6 +26,14 @@ describe('schema-defaults.js', () => {
expect(defaults({ default: objVal })).toBe(objVal);
});
+ it('should return first enum value if enum has provided', () => {
+ const schema_str = {
+ type: 'string',
+ enum: ['enum0', 'enum1']
+ };
+ expect(defaults(schema_str)).toBe(schema_str.enum[0]);
+ });
+
it('should return 0 if integer type has provided', () => {
const schema = {
type: 'integer'
diff --git a/app/utils/schema-defaults.js b/app/utils/schema-defaults.js
index 4d51b60a..98eb3609 100644
--- a/app/utils/schema-defaults.js
+++ b/app/utils/schema-defaults.js
@@ -6,6 +6,9 @@ function defaults(schema) {
if (schema.default)
return schema.default;
+ if (schema.enum && schema.enum.length > 0)
+ return schema.enum[0];
+
const type = schema.type;
if (type === 'string')
return '';
diff --git a/docs/plugin-docs.md b/docs/plugin-docs.md
index 272e91e1..b1e67c36 100644
--- a/docs/plugin-docs.md
+++ b/docs/plugin-docs.md
@@ -33,6 +33,9 @@ Current API Version: `hain-0.3.0`
* [hain-plugin-naverdictionary](https://github.com/appetizermonster/hain-plugin-naverdictionary)
* [hain-plugin-best-torrent](https://github.com/kamahl19/hain-plugin-best-torrent)
* [hain-plugin-npm](https://github.com/kamahl19/hain-plugin-npm)
+ * [hain-plugin-http-codes](https://github.com/quinnjn/hain-plugin-http-codes)
+- `hain-0.3.0`
+ * [hain-plugin-material-colors](https://github.com/aouerfelli/hain-plugin-material-colors)
## Guides
diff --git a/docs/share-your-plugins.md b/docs/share-your-plugins.md
index 53acb050..efee2c13 100644
--- a/docs/share-your-plugins.md
+++ b/docs/share-your-plugins.md
@@ -4,7 +4,7 @@ In short, you can share your plugin by publishing it on public npmjs registry.
But there are few rules.
1. You should name your plugin prefixed with `hain-plugin-`, then hpm(hain-package-manager) can find your plugin in npmjs registry.
-2. You should add `hain0` keyword in your package.json, then hpm can decide api compatibility.
+2. You should add `hain-0.3.0` keyword in your package.json, then hpm can decide api compatibility.
## Publishing
In your plugin directory:
@@ -15,4 +15,4 @@ Done.
You can find your plugin in few seconds then if you read rules above properly.
## Related Docs
-- [package.json Format](package-json-format.md)
\ No newline at end of file
+- [package.json Format](package-json-format.md)
diff --git a/package.json b/package.json
index 96352f23..8fad31dd 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,6 @@
"gulp-sourcemaps": "^1.6.0",
"gulp-util": "^3.0.7",
"gulp-zip": "^3.2.0",
- "jest-cli": "^0.10.0"
+ "jest-cli": "^12.0.2"
}
}