Skip to content

Commit 32aa9c7

Browse files
authored
Merge pull request #884 from ibrand/reset_button
Reset button
2 parents c3481bb + 895f9e0 commit 32aa9c7

10 files changed

Lines changed: 71 additions & 12 deletions

File tree

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
],
5151
"complexity": [
5252
2,
53-
{"max": 26}
53+
{"max": 27}
5454
],
5555
"computed-property-spacing": [
5656
2,

src/actions/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
stopDragColumnDivider,
2525
notificationTriggered,
2626
userDismissedNotification,
27+
refreshPreview,
2728
} from './ui';
2829

2930
import {
@@ -77,4 +78,5 @@ export {
7778
gistExportDisplayed,
7879
gistExportNotDisplayed,
7980
applicationLoaded,
81+
refreshPreview,
8082
};

src/actions/ui.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,8 @@ export const userDismissedNotification = createAction(
3737
'USER_DISMISSED_NOTIFICATION',
3838
type => ({type}),
3939
);
40+
41+
export const refreshPreview = createAction(
42+
'REFRESH_PREVIEW',
43+
timestamp => ({timestamp}),
44+
);

src/components/Output.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ class Output extends React.Component {
2525
return (
2626
<Preview
2727
isValid={this.props.validationState === 'passed'}
28+
lastRefreshTimestamp={this.props.lastRefreshTimestamp}
2829
project={this.props.project}
2930
onClearRuntimeErrors={this.props.onClearRuntimeErrors}
31+
onRefreshClick={this.props.onRefreshClick}
3032
onRuntimeError={this.props.onRuntimeError}
3133
/>
3234
);
@@ -99,6 +101,7 @@ Output.propTypes = {
99101
errors: PropTypes.object.isRequired,
100102
isDraggingColumnDivider: PropTypes.bool.isRequired,
101103
isHidden: PropTypes.bool.isRequired,
104+
lastRefreshTimestamp: PropTypes.number,
102105
project: PropTypes.object,
103106
runtimeErrors: PropTypes.array.isRequired,
104107
style: PropTypes.object.isRequired,
@@ -107,10 +110,12 @@ Output.propTypes = {
107110
onErrorClick: PropTypes.func.isRequired,
108111
onHide: PropTypes.func.isRequired,
109112
onRef: PropTypes.func.isRequired,
113+
onRefreshClick: PropTypes.func.isRequired,
110114
onRuntimeError: PropTypes.func.isRequired,
111115
};
112116

113117
Output.defaultProps = {
118+
lastRefreshTimestamp: null,
114119
project: null,
115120
};
116121

src/components/Preview.jsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class Preview extends React.Component {
1818
if (!this.props.isValid) {
1919
return '';
2020
}
21-
2221
const project = this.props.project;
2322

2423
if (project === undefined) {
@@ -32,6 +31,7 @@ class Preview extends React.Component {
3231
propagateErrorsToParent: isLivePreview,
3332
breakLoops: isLivePreview,
3433
nonBlockingAlertsAndPrompts: isLivePreview,
34+
lastRefreshTimestamp: isLivePreview && this.props.lastRefreshTimestamp,
3535
},
3636
);
3737
}
@@ -58,10 +58,14 @@ class Preview extends React.Component {
5858
{u__hidden: !this.props.isValid},
5959
)}
6060
>
61-
<div
62-
className="preview__pop-out-button"
61+
<span
62+
className="preview__button preview__button_reset"
63+
onClick={this.props.onRefreshClick}
64+
>&#xf021;</span>
65+
<span
66+
className="preview__button preview__button_pop-out"
6367
onClick={this._handlePopOutClick}
64-
/>
68+
>&#xf08e;</span>
6569
<PreviewFrame
6670
src={this._generateDocument(true)}
6771
onFrameWillRefresh={this.props.onClearRuntimeErrors}
@@ -74,9 +78,15 @@ class Preview extends React.Component {
7478

7579
Preview.propTypes = {
7680
isValid: PropTypes.bool.isRequired,
81+
lastRefreshTimestamp: PropTypes.number,
7782
project: PropTypes.object.isRequired,
7883
onClearRuntimeErrors: PropTypes.func.isRequired,
84+
onRefreshClick: PropTypes.func.isRequired,
7985
onRuntimeError: PropTypes.func.isRequired,
8086
};
8187

88+
Preview.defaultProps = {
89+
lastRefreshTimestamp: null,
90+
};
91+
8292
export default Preview;

src/components/Workspace.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
userDismissedNotification,
4848
exportGist,
4949
applicationLoaded,
50+
refreshPreview,
5051
} from '../actions';
5152

5253
import {getCurrentProject, isPristineProject} from '../util/projectUtils';
@@ -109,6 +110,7 @@ class Workspace extends React.Component {
109110
'_handleExportGist',
110111
'_storeDividerRef',
111112
'_storeColumnRef',
113+
'_handleRefreshClick',
112114
);
113115
this.columnRefs = [null, null];
114116
}
@@ -203,6 +205,10 @@ class Workspace extends React.Component {
203205
this.props.dispatch(clearRuntimeErrors());
204206
}
205207

208+
_handleRefreshClick() {
209+
this.props.dispatch(refreshPreview(Date.now()));
210+
}
211+
206212
_getOverallValidationState() {
207213
const errorStates = map(values(this.props.errors), 'state');
208214

@@ -234,6 +240,7 @@ class Workspace extends React.Component {
234240
errors={errors}
235241
isDraggingColumnDivider={isDraggingColumnDivider}
236242
isHidden={includes(hiddenUIComponents, 'output')}
243+
lastRefreshTimestamp={this.props.ui.lastRefreshTimestamp}
237244
project={currentProject}
238245
runtimeErrors={runtimeErrors}
239246
style={{flex: rowsFlex[1]}}
@@ -245,6 +252,7 @@ class Workspace extends React.Component {
245252
'output')
246253
}
247254
onRef={partial(this._storeColumnRef, 1)}
255+
onRefreshClick={this._handleRefreshClick}
248256
onRuntimeError={this._handleRuntimeError}
249257
/>
250258
);

src/css/application.css

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -501,22 +501,30 @@ body {
501501
flex: 1 0 100%;
502502
}
503503

504-
.preview__pop-out-button {
505-
background: url(../images/popout.png);
504+
.preview__button {
505+
font-family: 'FontAwesome';
506506
width: 16px;
507507
height: 18px;
508508
position: absolute;
509-
right: 10px;
510-
top: 10px;
511509
cursor: pointer;
512510
opacity: 0.25;
513511
z-index: 1;
514512
}
515513

516-
.preview__pop-out-button:hover {
514+
.preview__button:hover {
517515
opacity: 0.5;
518516
}
519517

518+
.preview__button_pop-out {
519+
right: 10px;
520+
top: 11px;
521+
}
522+
523+
.preview__button_reset {
524+
right: 35px;
525+
top: 10px;
526+
}
527+
520528
/** @define error-list */
521529

522530
.error-list {

src/reducers/ui.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ const defaultState = new Immutable.Map().
2525
new Immutable.Map().
2626
set('isOpen', false).
2727
set('activeSubmenu', null),
28-
);
28+
).
29+
set('lastRefreshTimestamp', null);
2930

3031
function addNotification(state, type, severity, payload = {}) {
3132
return state.update('notifications', notifications =>
@@ -161,6 +162,9 @@ export default function ui(stateIn, action) {
161162
}
162163
return addNotification(state, 'gist-export-error', 'error');
163164

165+
case 'REFRESH_PREVIEW':
166+
return state.set('lastRefreshTimestamp', action.payload.timestamp);
167+
164168
default:
165169
return state;
166170
}

src/util/generatePreview.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ class PreviewGenerator {
8282
if (options.nonBlockingAlertsAndPrompts) {
8383
this._addAlertAndPromptHandling();
8484
}
85+
if (options.lastRefreshTimestamp) {
86+
this._addRefreshTimestamp(options.lastRefreshTimestamp);
87+
}
8588

8689
this._addJavascript(pick(options, 'breakLoops'));
8790
}
@@ -121,6 +124,12 @@ class PreviewGenerator {
121124
this._previewHead.appendChild(styleTag);
122125
}
123126

127+
_addRefreshTimestamp(timestamp) {
128+
const dateString = `Last refresh on: ${String(new Date(timestamp))}`;
129+
const comment = this.previewDocument.createComment(dateString);
130+
this.previewBody.append(comment);
131+
}
132+
124133
_addJavascript({breakLoops = false}) {
125134
let source = `\n${sourceDelimiter}\n${this._project.sources.javascript}`;
126135
if (breakLoops) {
@@ -129,7 +138,6 @@ class PreviewGenerator {
129138
const scriptTag = this.previewDocument.createElement('script');
130139
scriptTag.innerHTML = source;
131140
this.previewBody.appendChild(scriptTag);
132-
133141
return this.previewDocument.documentElement.outerHTML;
134142
}
135143

test/unit/reducers/ui.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
editorFocusedRequestedLine,
1818
notificationTriggered,
1919
userDismissedNotification,
20+
refreshPreview,
2021
} from '../../../src/actions/ui';
2122
import {
2223
gistExportNotDisplayed,
@@ -36,6 +37,7 @@ const initialState = Immutable.fromJS({
3637
isOpen: false,
3738
activeSubmenu: null,
3839
},
40+
lastRefreshTimestamp: null,
3941
});
4042

4143
function withNotification(type, severity, payload = {}) {
@@ -237,3 +239,10 @@ test('userDismissedNotification', reducerTest(
237239
partial(userDismissedNotification, 'some-error'),
238240
initialState,
239241
));
242+
243+
test('refreshPreview', reducerTest(
244+
reducer,
245+
initialState,
246+
partial(refreshPreview, 1),
247+
initialState.set('lastRefreshTimestamp', 1),
248+
));

0 commit comments

Comments
 (0)