Skip to content

Commit f7530a5

Browse files
committed
implement app and alert-area
1 parent 1743ba5 commit f7530a5

File tree

9 files changed

+224
-8
lines changed

9 files changed

+224
-8
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React, { Component } from 'react';
2+
3+
class BugTrackingNagScreen extends Component {
4+
render() {
5+
return (
6+
<div className="alert alert-info clearfix">
7+
<button type="button" className="close" data-bind="click: dismissBugtrackingNagscreen">&times;</button>
8+
<p><strong>Help make ungit better with the press of a button!</strong></p>
9+
<button className="btn btn-primary" data-bind="click: enableBugtrackingAndStatistics">Enable automatic bug reports + anonymous usage statistics</button>
10+
<button className="btn btn-primary" data-bind="click: enableBugtracking">Enable automatic bug reports</button>
11+
<button className="btn btn-default" data-bind="click: dismissBugtrackingNagscreen">Naah, I&#39;ll skip that</button>
12+
</div>
13+
);
14+
}
15+
}
16+
17+
export default BugTrackingNagScreen;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React, { Component, PropTypes } from 'react';
2+
3+
class GitVersionError extends Component {
4+
static propTypes = {
5+
gitVersionError: PropTypes.string
6+
}
7+
8+
render() {
9+
return (
10+
<div class="alert alert-danger">
11+
<span>{ this.props.gitVersionError }</span>
12+
<button type="button" className="close" data-bind="click: dismissGitVersionError">&times;</button>
13+
</div>
14+
);
15+
}
16+
}
17+
18+
export default GitVersionError;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React, { Component, PropTypes } from 'react';
2+
3+
import GitVersionError from './git-version-error';
4+
import NewVersionAvailable from './new-version-available';
5+
import BugTrackingNagScreen from './bug-tracking-nag-screen';
6+
import NPSSurvey from './nps-survey';
7+
8+
class AlertArea extends Component {
9+
static propTypes = {
10+
config: PropTypes.object.isRequired,
11+
gitVersionErrorVisible: PropTypes.bool.isRequired,
12+
showNewVersionAvailable: PropTypes.bool.isRequired,
13+
showBugtrackingNagscreen: PropTypes.bool.isRequired,
14+
showNPSSurvey: PropTypes.bool.isRequired
15+
}
16+
17+
render() {
18+
const {
19+
config: {
20+
ungitConfig: { platform },
21+
versions: {
22+
gitVersion: { error },
23+
latestVersion: {
24+
latestVersion
25+
}
26+
}
27+
},
28+
gitVersionErrorVisible,
29+
showNewVersionAvailable,
30+
showBugtrackingNagscreen,
31+
showNPSSurvey
32+
} = this.props;
33+
return (
34+
<div className="container" data-ta-container="app">
35+
{
36+
gitVersionErrorVisible ? (
37+
<GitVersionError gitVersionError={ error }/>
38+
) : null
39+
}
40+
{
41+
showNewVersionAvailable ? (
42+
<NewVersionAvailable
43+
latestVersion={ latestVersion }
44+
platform={ platform }/>
45+
) : null
46+
}
47+
{
48+
showBugtrackingNagscreen ? (
49+
<BugTrackingNagScreen />
50+
) : null
51+
}
52+
{
53+
showNPSSurvey ? (
54+
<NPSSurvey />
55+
) : null
56+
}
57+
</div>
58+
);
59+
}
60+
}
61+
62+
export default AlertArea;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React, { Component, PropTypes } from 'react';
2+
3+
class NewVersionAvailable extends Component {
4+
static propTypes = {
5+
latestVersion: PropTypes.string,
6+
platform: PropTypes.string
7+
}
8+
9+
render() {
10+
const newVersionInstallCommand = `#{this.props.platform ? '' : 'sudo -H'}npm update -g ungit`;
11+
return (
12+
<div className="alert alert-info">
13+
A new version of ungit (<span>{ this.props.latestVersion }</span>) is
14+
<a href="https://github.com/FredrikNoren/ungit">available</a>! Run
15+
<code>{ newVersionInstallCommand }</code> to install.
16+
See what's new in the
17+
<a href="https://github.com/FredrikNoren/ungit/blob/master/CHANGELOG.md">changelog</a>.
18+
<button type="button" className="close" data-bind="click: dismissNewVersion">&times;</button>
19+
</div>
20+
);
21+
}
22+
}
23+
24+
export default NewVersionAvailable;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React, { Component } from 'react';
2+
3+
class NPSSurvey extends Component {
4+
static propTypes = {
5+
}
6+
7+
render() {
8+
return (
9+
<div className="alert alert-info clearfix" data-bind="visible: showNPSSurvey">
10+
<button type="button" className="close" data-bind="click: dismissNPSSurvey">&times;</button>
11+
<span className="text-dimmed">Hi! This is a one-question survey to learn more about how people use Ungit. You can dismiss it by clicking the x in the upper right corner.</span>
12+
<p><h4>Question: How likely are you to recommend Ungit to your friends and colleagues?</h4></p>
13+
<p>
14+
<div className="btn-group btn-group-justified">
15+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 0)">0</a>
16+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 1)">1</a>
17+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 2)">2</a>
18+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 3)">3</a>
19+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 4)">4</a>
20+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 5)">5</a>
21+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 6)">6</a>
22+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 7)">7</a>
23+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 8)">8</a>
24+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 9)">9</a>
25+
<a className="btn btn-default" role="button" data-bind="click: sendNPS.bind(null, 10)">10</a>
26+
</div>
27+
<div className="clearfix">
28+
Not at all likely
29+
<div className="pull-right">Extremely likely</div>
30+
</div>
31+
</p>
32+
</div>
33+
);
34+
}
35+
}
36+
37+
export default NPSSurvey;

src-react/containers/path.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class Path extends Component {
3131
<AlerArea config={ this.props.config }
3232
gitVersionErrorVisible={ app.gitVersionErrorVisible }
3333
showNewVersionAvailable={ app.showNewVersionAvailable }
34-
showBugtrackingNagscreen={ app.showBugtrackingNagscreen } />
34+
showBugtrackingNagscreen={ app.showBugtrackingNagscreen }
35+
showNPSSurvey={ app.showNPSSurvey } />
3536
) : null
3637
}
3738
</div>

src-react/reducers/app.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as types from 'constants/action-types';
2+
3+
function app(state, action, config) {
4+
5+
switch(action.type) {
6+
case types.RECEIVE_UNGIT_CONFIG: {
7+
const { ungitConfig } = config;
8+
const bugtrackingNagscreenDismissed = localStorage.getItem('bugtrackingNagscreenDismissed');
9+
const showBugtrackingNagscreen = !ungitConfig.config.bugtracking && !bugtrackingNagscreenDismissed;
10+
11+
return { ...state, showBugtrackingNagscreen };
12+
}
13+
14+
case types.RECEIVE_GIT_VERSION: {
15+
const { ungitConfig, versions: { gitVersion } } = config;
16+
const gitVersionCheckOverride = ungitConfig.config && ungitConfig.config.gitVersionCheckOverride;
17+
const gitVersionErrorDismissed = localStorage.getItem('gitVersionErrorDismissed');
18+
const gitVersionError = gitVersion && !gitVersion.satisfied && gitVersion.error;
19+
const gitVersionErrorVisible = !gitVersionCheckOverride && gitVersionError && gitVersionErrorDismissed;
20+
21+
return { ...state, gitVersionErrorVisible };
22+
}
23+
24+
case types.RECEIVE_LATEST_VERSION: {
25+
const { ungitConfig, versions: { latestVersion } } = config;
26+
const gitVersionCheckOverride = ungitConfig.config && ungitConfig.config.gitVersionCheckOverride;
27+
const outdated = latestVersion && latestVersion.outdated;
28+
const showNewVersionAvailable = !gitVersionCheckOverride && outdated;
29+
30+
return { ...state, showNewVersionAvailable };
31+
}
32+
33+
case types.RECEIVE_USER_CONFIG: {
34+
const { userConfig } = config;
35+
const bugtrackingNagscreenDismissed = localStorage.getItem('bugtrackingNagscreenDismissed');
36+
const showBugtrackingNagscreen = !userConfig.bugtracking && !bugtrackingNagscreenDismissed;
37+
38+
return { ...state, showBugtrackingNagscreen };
39+
}
40+
default:
41+
const NPSSurveyLastDismissed = parseInt(localStorage.getItem('NPSSurveyLastDismissed') || '0', 10);
42+
const monthsSinceNPSLastDismissed = (Date.now() - NPSSurveyLastDismissed) / (1000 * 60 * 60 * 24 * 30);
43+
const showNPSSurvey = monthsSinceNPSLastDismissed >= 6 && Math.random() < 0.01;
44+
return { ...state, showNPSSurvey };
45+
}
46+
}
47+
48+
export default app;

src-react/reducers/index.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
import { combineReducers } from 'redux';
2-
3-
import path from './path';
41
import config from './config';
2+
import app from './app';
3+
import path from './path';
54

6-
const ungitApp = combineReducers({
7-
config,
8-
path
9-
});
5+
function ungitApp(state, action) {
6+
const _config = config(state.config, action);
7+
return {
8+
config: _config,
9+
app: app(state.app, action, _config),
10+
path: path(state.path, action, _config),
11+
};
12+
}
1013

1114
export default ungitApp;

src-react/store.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ const initialState = {
1111
latestVersion: null
1212
}
1313
},
14+
app: {
15+
gitVersionErrorVisible: false,
16+
showNewVersionAvailable: false,
17+
showBugtrackingNagscreen: false,
18+
showNPSSurvey: false
19+
},
1420
path: {
1521
pending: null,
1622
errMessage: []

0 commit comments

Comments
 (0)