Skip to content

Commit

Permalink
Refactor options page (OctoLinker#386)
Browse files Browse the repository at this point in the history
* Add preact

* Refactor options page to Preact

* Fix link state

* Remove unused container div
  • Loading branch information
stefanbuck authored Oct 19, 2017
1 parent 0501d5b commit fd662b5
Show file tree
Hide file tree
Showing 11 changed files with 337 additions and 115 deletions.
1 change: 1 addition & 0 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"polyfill": false
}
],
["transform-react-jsx", { "pragma": "h" }],
"transform-object-rest-spread"
],
"presets": [
Expand Down
18 changes: 16 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
module.exports = {
extends: ['airbnb-base', 'plugin:import/errors', 'prettier'],
plugins: ['prettier', 'mocha'],
parser: 'babel-eslint',
extends: ['airbnb', 'prettier'],
plugins: ['prettier', 'react', 'mocha'],
env: {
browser: true,
mocha: true
},
settings: {
react: {
pragma: 'h'
}
},
parserOptions: {
ecmaFeatures: {
modules: true,
jsx: true
}
},
rules: {
'prettier/prettier': ['error', {
singleQuote: true,
trailingComma: 'all',
}],
'react/jsx-filename-extension': [1, { 'extensions': ['.js', '.jsx'] }],
'react/prop-types': 0,
'func-names': 0,
'id-length': [1, {'exceptions': ['$']}],
'new-cap': [2, {'capIsNewExceptions': ['Deferred']}],
Expand Down
1 change: 0 additions & 1 deletion assets/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<title></title>
</head>
<body>
<div id="options"></div>
<script src="options.js"></script>
</body>
</html>
26 changes: 16 additions & 10 deletions lib/options/components/checkbox.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
export default ({ name, label, value, defaultValue, description }) => {
const val = value === undefined ? defaultValue : value;
const note = description ? `<p class="note">${description}</p>` : '';
import { h } from 'preact';

return `<div class="form-checkbox">
<label>
<input type="checkbox" name="${name}" ${val ? 'checked' : ''}>
${label}
</label>${note}
</div>`;
};
export default ({ name, label, description, checked, onClick }) => (
<div className="form-checkbox">
<label htmlFor={name}>
<input
id={name}
name={name}
type="checkbox"
checked={checked}
onClick={onClick}
/>
{label}
</label>
<p className="note">{description}</p>
</div>
);
13 changes: 4 additions & 9 deletions lib/options/components/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import checkbox from './checkbox';
import input from './input';
import 'primer-core/build/build.css';
import 'primer-forms/build/build.css';

export default function({ type, ...rest }) {
if (type === 'checkbox') {
return checkbox(rest);
} else if (type === 'text' || type === 'password') {
return input({ type, ...rest });
}
}
export { default as Input } from './input';
export { default as Checkbox } from './checkbox';
32 changes: 24 additions & 8 deletions lib/options/components/input.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
export default ({ type, name, label, value, defaultValue, description }) => {
const val = value === undefined ? defaultValue : value;
const note = description ? `<p class="note">${description}</p>` : '';
import { h } from 'preact';

return `<dl class="form-group">
<dt><label>${label}</label></dt>
<dd><input class="form-control" type="${type}" name="${name}" value="${val}">${note}</dd>
</dl>`;
};
export default ({
name,
label,
description,
value,
onInput,
type = 'text',
}) => (
<div className="form-group">
<label htmlFor={name}>
{label}
<input
className="form-control"
type={type}
id={name}
name={name}
value={value}
onInput={onInput}
/>
</label>
<p className="note">{description}</p>
</div>
);
46 changes: 0 additions & 46 deletions lib/options/options.js

This file was deleted.

94 changes: 73 additions & 21 deletions lib/options/page.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,80 @@
import 'primer-core/build/build.css';
import 'primer-forms/build/build.css';
import './options.css';
import { h, render, Component } from 'preact';
import linkState from 'linkstate';

import components from './components';
import './options.css';
import { Input, Checkbox } from './components';
import * as storage from './storage';
import { options } from './options';

const formEl = document.querySelector('#options');
const githubTokenDescription = () => (
<span>
If you want better <strong>Sass, Less or Haskell support</strong> for
private repositories, you&apos;ll need to{' '}
<a href="https://github.com/settings/tokens/new?scopes=repo&description=OctoLinker%20browser%20extension">
create a token
</a>{' '}
with the repo permissions.
</span>
);

storage.load().then(() => {
options.forEach(item => {
formEl.innerHTML += components({
...item,
value: storage.get(item.name),
});
});
});
class App extends Component {
async componentWillMount() {
const store = { ...(await storage.load()) };
this.setState(store);
}

formEl.addEventListener('change', ({ target }) => {
const tag = target.tagName.toLowerCase();
componentWillUpdate(nextProps, nextState) {
storage.save(nextState);
}

if (tag === 'input' && target.type === 'checkbox') {
storage.set(target.name, target.checked);
} else {
storage.set(target.name, target.value);
render(props, state) {
return (
<div>
<Input
type="password"
name="githubToken"
label="Access token"
description={githubTokenDescription()}
value={state.githubToken}
onInput={linkState(this, 'githubToken')}
/>
<Checkbox
name="newWindow"
label="New tab"
description="Open link in a new tab."
checked={state.newWindow}
onClick={linkState(this, 'newWindow')}
/>
<Checkbox
name="newWindowActive"
label="Focus new tab"
description="Focus new tab when opening a link."
checked={state.newWindowActive}
onClick={linkState(this, 'newWindowActive')}
/>
<Checkbox
name="showLinkIndicator"
label="Line indicator"
description="Show an indicator if line contains OctoLinker links."
checked={state.showLinkIndicator}
onClick={linkState(this, 'showLinkIndicator')}
/>
<Checkbox
name="showUpdateNotification"
label="Update notification"
description="Show a notification if a new version is available."
checked={state.showUpdateNotification}
onClick={linkState(this, 'showUpdateNotification')}
/>
<Checkbox
name="doTrack"
label="Usage reports"
description="Send anonymous usage reports to Google Analytics."
checked={state.doTrack}
onClick={linkState(this, 'doTrack')}
/>
</div>
);
}
});
}

render(<App />, document.body);
26 changes: 17 additions & 9 deletions lib/options/storage.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import uuid from 'uuid';
import ChromePromise from 'chrome-promise';
import { options } from './options';

const chromep = new ChromePromise();
const store = {};
const defaults = {};

options.forEach(item => {
if (item.sensitiveData) {
return;
}

defaults[item.name] = item.defaultValue;
});
const defaults = {
newWindow: false,
newWindowActive: true,
showLinkIndicator: true,
showUpdateNotification: true,
doTrack: true,
};

export const get = key => store[key];

Expand All @@ -28,6 +26,14 @@ export const set = async (key, value) => {
}
};

export const save = async data => {
try {
return await chromep.storage.sync.set(data);
} catch (err) {
return chromep.storage.local.set(data);
}
};

export const load = async () => {
let data;

Expand Down Expand Up @@ -56,4 +62,6 @@ export const load = async () => {
});
}
}

return store;
};
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@
"core-js": "^2.5.1",
"css-loader": "^0.28.7",
"escape-regex-string": "^1.0.4",
"eslint-config-airbnb": "^16.0.0",
"eslint-plugin-react": "^7.4.0",
"findandreplacedomtext": "^0.4.5",
"github-injection": "^1.0.1",
"github-url-from-git": "^1.5.0",
"github-url-from-username-repo": "^1.0.2",
"giturl": "^1.0.0",
"jquery": "^3.2.1",
"linkstate": "^1.1.0",
"path-parse": "^1.0.5",
"pop-zip": "^1.0.0",
"preact": "^8.2.5",
"primer-core": "^6.4.0",
"primer-forms": "^1.4.0",
"querystring": "^0.2.0",
Expand All @@ -57,15 +61,16 @@
"babel-eslint": "^8.0.1",
"babel-loader": "^7.1.2",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.0",
"chrome-launch": "^1.1.4",
"chrome-webstore-upload-cli": "^1.1.1",
"copy-webpack-plugin": "^4.1.0",
"eslint": "^4.8.0",
"eslint-config-airbnb-base": "^12.0.1",
"eslint-config-prettier": "^2.6.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jsx-a11y": "^6.0.2",
"eslint-plugin-mocha": "^4.11.0",
"eslint-plugin-prettier": "^2.3.1",
"json": "^9.0.4",
Expand Down
Loading

0 comments on commit fd662b5

Please sign in to comment.