Skip to content

Commit 9f5fa9e

Browse files
author
Stefan Buck
committed
Refine settings page
1 parent 1dcd29c commit 9f5fa9e

File tree

7 files changed

+172
-82
lines changed

7 files changed

+172
-82
lines changed

assets/manifest.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
},
2323
"options_ui": {
2424
"page": "options.html",
25+
"open_in_tab": true,
2526
"chrome_style": true
2627
},
2728
"content_scripts": [

assets/options.html

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<html>
2-
<head>
3-
<meta charset="UTF-8">
4-
<title></title>
5-
</head>
6-
<body>
7-
<script src="options.js"></script>
8-
</body>
2+
<head>
3+
<meta charset="UTF-8" />
4+
<title></title>
5+
</head>
6+
<body>
7+
<div id="app"></div>
8+
<script src="options.js"></script>
9+
</body>
910
</html>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/* eslint-disable react/no-unused-state */
2+
3+
import { h, render, Component } from 'preact';
4+
import linkState from 'linkstate';
5+
6+
import './style.css';
7+
import { Input, Checkbox } from './components';
8+
import * as storage from './index';
9+
10+
const githubTokenDescription = () => (
11+
<span>
12+
If you want better <strong>Sass, Less or Haskell support</strong> for
13+
private repositories, you&apos;ll need to{' '}
14+
<a href="https://github.com/settings/tokens/new?scopes=repo&description=OctoLinker%20browser%20extension">
15+
create a token
16+
</a>{' '}
17+
with the repo permissions.
18+
</span>
19+
);
20+
21+
export default class Form extends Component {
22+
async componentWillMount() {
23+
this.setState({ ...(await storage.load()) });
24+
}
25+
26+
componentWillUpdate(
27+
nextProps,
28+
{ tokenLoaded, githubToken, errorMessage, ...rest },
29+
) {
30+
storage.save(rest);
31+
}
32+
33+
onBlur(event) {
34+
if (event.target.name === 'githubToken') {
35+
this.validateToken();
36+
}
37+
}
38+
39+
async validateToken() {
40+
const { githubToken } = this.state;
41+
42+
if (!githubToken) {
43+
this.setState({
44+
errorMessage: undefined,
45+
tokenLoaded: false,
46+
});
47+
48+
storage.save({
49+
githubToken: undefined,
50+
});
51+
return;
52+
}
53+
54+
const response = await fetch('https://api.github.com/user', {
55+
headers: { Authorization: `token ${githubToken}` },
56+
}).then(r => r.json());
57+
58+
if (!response.login) {
59+
this.setState({
60+
tokenLoaded: false,
61+
errorMessage: response.message || 'Something went wrong',
62+
});
63+
return;
64+
}
65+
66+
this.setState({
67+
errorMessage: undefined,
68+
tokenLoaded: true,
69+
});
70+
71+
storage.save({
72+
githubToken,
73+
});
74+
}
75+
76+
tokenMessage() {
77+
return <div className="flash flash-success">Token successfuly added</div>;
78+
}
79+
80+
render(props, state) {
81+
const { errorMessage, tokenLoaded } = this.state;
82+
83+
return (
84+
<form
85+
onChange={this.onBlur.bind(this)}
86+
onSubmit={event => event.preventDefault()}
87+
>
88+
{tokenLoaded && this.tokenMessage()}
89+
<Input
90+
type="password"
91+
name="githubToken"
92+
label="Access token"
93+
description={githubTokenDescription()}
94+
value={state.githubToken}
95+
error={errorMessage}
96+
onInput={linkState(this, 'githubToken')}
97+
/>
98+
<Checkbox
99+
name="newWindow"
100+
label="New tab"
101+
description="Open link in a new tab."
102+
checked={state.newWindow}
103+
onClick={linkState(this, 'newWindow')}
104+
/>
105+
<Checkbox
106+
name="newWindowActive"
107+
label="Focus new tab"
108+
description="Focus new tab when opening a link."
109+
checked={state.newWindowActive}
110+
onClick={linkState(this, 'newWindowActive')}
111+
/>
112+
<Checkbox
113+
name="showLinkIndicator"
114+
label="Line indicator"
115+
description="Show an indicator if line contains OctoLinker links."
116+
checked={state.showLinkIndicator}
117+
onClick={linkState(this, 'showLinkIndicator')}
118+
/>
119+
<Checkbox
120+
name="showUpdateNotification"
121+
label="Update notification"
122+
description="Show a notification if a new version is available."
123+
checked={state.showUpdateNotification}
124+
onClick={linkState(this, 'showUpdateNotification')}
125+
/>
126+
</form>
127+
);
128+
}
129+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'primer-core/build/build.css';
22
import 'primer-forms/build/build.css';
3+
import 'primer-product/build/build.css';
34

45
export { default as Input } from './input';
56
export { default as Checkbox } from './checkbox';
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
import { h } from 'preact';
22

3+
const validationClassName = error => (error ? ' errored' : '');
4+
35
export default ({
46
name,
57
label,
68
description,
9+
error,
710
value,
811
onInput,
912
type = 'text',
1013
}) => (
11-
<div className="form-group">
12-
<label htmlFor={name}>
13-
{label}
14+
<dl className={`form-group${validationClassName(error)}`}>
15+
<dt>
16+
<label htmlFor={name}>{label}</label>
17+
</dt>
18+
<dd>
1419
<input
1520
className="form-control"
1621
type={type}
@@ -19,7 +24,8 @@ export default ({
1924
value={value}
2025
onInput={onInput}
2126
/>
22-
</label>
27+
</dd>
28+
{error && <dd className="error">{error}</dd>}
2329
<p className="note">{description}</p>
24-
</div>
30+
</dl>
2531
);

packages/helper-settings/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"linkstate": "^1.1.0",
1111
"preact": "^8.2.5",
1212
"primer-core": "^6.4.0",
13-
"primer-forms": "^1.4.0"
13+
"primer-forms": "^1.4.0",
14+
"primer-product": "^5.7.0"
1415
}
1516
}

packages/helper-settings/page.js

Lines changed: 20 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,24 @@
1-
import { h, render, Component } from 'preact';
2-
import linkState from 'linkstate';
1+
/* eslint-disable react/no-unused-state */
32

4-
import './style.css';
5-
import { Input, Checkbox } from './components';
6-
import * as storage from './index';
3+
import { h, render } from 'preact';
4+
import SettingsForm from './SettingsForm';
75

8-
const githubTokenDescription = () => (
9-
<span>
10-
If you want better <strong>Sass, Less or Haskell support</strong> for
11-
private repositories, you&apos;ll need to{' '}
12-
<a href="https://github.com/settings/tokens/new?scopes=repo&description=OctoLinker%20browser%20extension">
13-
create a token
14-
</a>{' '}
15-
with the repo permissions.
16-
</span>
17-
);
18-
19-
class App extends Component {
20-
async componentWillMount() {
21-
const store = { ...(await storage.load()) };
22-
this.setState(store);
23-
}
24-
25-
componentWillUpdate(nextProps, nextState) {
26-
storage.save(nextState);
27-
}
28-
29-
render(props, state) {
30-
return (
31-
<div>
32-
<Input
33-
type="password"
34-
name="githubToken"
35-
label="Access token"
36-
description={githubTokenDescription()}
37-
value={state.githubToken}
38-
onInput={linkState(this, 'githubToken')}
39-
/>
40-
<Checkbox
41-
name="newWindow"
42-
label="New tab"
43-
description="Open link in a new tab."
44-
checked={state.newWindow}
45-
onClick={linkState(this, 'newWindow')}
46-
/>
47-
<Checkbox
48-
name="newWindowActive"
49-
label="Focus new tab"
50-
description="Focus new tab when opening a link."
51-
checked={state.newWindowActive}
52-
onClick={linkState(this, 'newWindowActive')}
53-
/>
54-
<Checkbox
55-
name="showLinkIndicator"
56-
label="Line indicator"
57-
description="Show an indicator if line contains OctoLinker links."
58-
checked={state.showLinkIndicator}
59-
onClick={linkState(this, 'showLinkIndicator')}
60-
/>
61-
<Checkbox
62-
name="showUpdateNotification"
63-
label="Update notification"
64-
description="Show a notification if a new version is available."
65-
checked={state.showUpdateNotification}
66-
onClick={linkState(this, 'showUpdateNotification')}
67-
/>
6+
const App = () => (
7+
<div className="d-flex flex-justify-center p-6">
8+
<div className="Box box-shadow four-fifth column">
9+
<div className="Box-row">
10+
<div className="d-flex">
11+
<img height="54" alt="" src="icon.png" />
12+
<div className="pt-3 px-2">
13+
<h2>OctoLinker settings</h2>
14+
</div>
15+
</div>
16+
</div>
17+
<div className="Box-row">
18+
<SettingsForm />
6819
</div>
69-
);
70-
}
71-
}
20+
</div>
21+
</div>
22+
);
7223

73-
render(<App />, document.body);
24+
render(<App />, document.getElementById('app'));

0 commit comments

Comments
 (0)