Skip to content

Commit d0eb54c

Browse files
committed
Refactoring 'current' reducer
1 parent 49d000b commit d0eb54c

File tree

8 files changed

+155
-100
lines changed

8 files changed

+155
-100
lines changed

src/backend/controllers/categories.js renamed to src/backend/controllers/algorithms.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,10 @@ router.route('/:categoryKey/:algorithmKey')
112112
const algorithm = category.algorithms.find(algorithm => algorithm.key === algorithmKey);
113113
if (!algorithm) return next(new NotFoundError());
114114

115-
const titles = [category.name, algorithm.name];
115+
const categoryName = category.name;
116+
const algorithmName = algorithm.name;
116117
const files = algorithm.files.map(({ name, content, contributors }) => ({ name, content, contributors }));
117-
res.json({ algorithm: { titles, files } });
118+
res.json({ algorithm: { categoryKey, categoryName, algorithmKey, algorithmName, files } });
118119
});
119120

120-
export default router;
121+
export default router;

src/backend/controllers/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export { default as auth } from './auth';
2-
export { default as categories } from './categories';
2+
export { default as algorithms } from './algorithms';
33
export { default as tracers } from './tracers';

src/frontend/apis/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ const PATCH = URL => {
5656
});
5757
};
5858

59-
const CategoryApi = {
60-
getCategories: GET('/categories'),
61-
getAlgorithm: GET('/categories/:categoryKey/:algorithmKey'),
59+
const AlgorithmApi = {
60+
getCategories: GET('/algorithms'),
61+
getAlgorithm: GET('/algorithms/:categoryKey/:algorithmKey'),
6262
};
6363

6464
const GitHubApi = {
@@ -95,7 +95,7 @@ const TracerApi = {
9595
};
9696

9797
export {
98-
CategoryApi,
98+
AlgorithmApi,
9999
GitHubApi,
100100
TracerApi,
101101
};

src/frontend/common/util.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,29 @@ const extension = fileName => /(?:\.([^.]+))?$/.exec(fileName)[1];
1010

1111
const refineGist = gist => {
1212
const gistId = gist.id;
13-
const titles = ['Scratch Paper', gist.description];
13+
const title = gist.description;
1414
delete gist.files['algorithm-visualizer'];
1515
const { login, avatar_url } = gist.owner;
1616
const files = Object.values(gist.files).map(file => ({
1717
name: file.filename,
1818
content: file.content,
1919
contributors: [{ login, avatar_url }],
2020
}));
21-
return { gistId, titles, files, gist };
21+
return { gistId, title, files, gist };
22+
};
23+
24+
const getFiles = current => {
25+
const { algorithm, scratchPaper } = current;
26+
if (algorithm) return algorithm.files;
27+
if (scratchPaper) return scratchPaper.files;
28+
return [];
29+
};
30+
31+
const getTitleArray = current => {
32+
const { algorithm, scratchPaper } = current;
33+
if (algorithm) return [algorithm.categoryName, algorithm.algorithmName];
34+
if (scratchPaper) return ['Scratch Paper', scratchPaper.title];
35+
return ['Algorithm Visualizer'];
2236
};
2337

2438
const handleError = function (error) {
@@ -31,5 +45,7 @@ export {
3145
distance,
3246
extension,
3347
refineGist,
48+
getFiles,
49+
getTitleArray,
3450
handleError,
3551
};

src/frontend/components/App/index.jsx

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ import {
1717
ToastContainer,
1818
VisualizationViewer,
1919
} from '/components';
20-
import { CategoryApi, GitHubApi } from '/apis';
20+
import { AlgorithmApi, GitHubApi } from '/apis';
2121
import { actions } from '/reducers';
22-
import { extension, handleError, refineGist } from '/common/util';
22+
import { extension, getFiles, getTitleArray, handleError, refineGist } from '/common/util';
2323
import { exts, languages, us } from '/common/config';
2424
import { README_MD, SCRATCH_PAPER_MD } from '/skeletons';
2525
import styles from './stylesheet.scss';
@@ -49,7 +49,7 @@ class App extends React.Component {
4949
const accessToken = Cookies.get('access_token');
5050
if (accessToken) this.signIn(accessToken);
5151

52-
CategoryApi.getCategories()
52+
AlgorithmApi.getCategories()
5353
.then(({ categories }) => this.props.setCategories(categories))
5454
.catch(handleError.bind(this));
5555

@@ -65,7 +65,12 @@ class App extends React.Component {
6565

6666
componentWillReceiveProps(nextProps) {
6767
const { params } = nextProps.match;
68-
const { categoryKey, algorithmKey, gistId } = nextProps.current;
68+
const { algorithm, scratchPaper } = nextProps.current;
69+
70+
const categoryKey = algorithm && algorithm.categoryKey;
71+
const algorithmKey = algorithm && algorithm.algorithmKey;
72+
const gistId = scratchPaper && scratchPaper.gistId;
73+
6974
if (params.categoryKey !== categoryKey ||
7075
params.algorithmKey !== algorithmKey ||
7176
params.gistId !== gistId) {
@@ -135,13 +140,14 @@ class App extends React.Component {
135140
const { ext } = this.props.env;
136141
let fetchPromise = null;
137142
if (categoryKey && algorithmKey) {
138-
fetchPromise = CategoryApi.getAlgorithm(categoryKey, algorithmKey)
139-
.then(({ algorithm }) => algorithm);
143+
fetchPromise = AlgorithmApi.getAlgorithm(categoryKey, algorithmKey)
144+
.then(({ algorithm }) => this.props.setAlgorithm(algorithm));
140145
} else if (['new', 'forked'].includes(gistId)) {
141146
gistId = 'new';
142147
const language = languages.find(language => language.ext === ext);
143-
fetchPromise = Promise.resolve({
144-
titles: ['Scratch Paper', 'Untitled'],
148+
fetchPromise = Promise.resolve(this.props.setScratchPaper({
149+
gistId,
150+
title: 'Untitled',
145151
files: [{
146152
name: 'README.md',
147153
content: SCRATCH_PAPER_MD,
@@ -151,24 +157,29 @@ class App extends React.Component {
151157
content: language.skeleton,
152158
contributors: undefined,
153159
}],
154-
});
160+
}));
155161
} else if (gistId) {
156-
fetchPromise = GitHubApi.getGist(gistId, { timestamp: Date.now() }).then(refineGist);
162+
fetchPromise = GitHubApi.getGist(gistId, { timestamp: Date.now() })
163+
.then(refineGist)
164+
.then(this.props.setScratchPaper);
157165
} else {
158166
fetchPromise = Promise.reject(new Error());
159167
}
160168
fetchPromise
161-
.then(algorithm => this.props.setCurrent(categoryKey, algorithmKey, gistId, algorithm.titles, algorithm.files, algorithm.gist))
162169
.catch(error => {
163170
if (error.message) handleError.bind(this)(error);
164-
this.props.setCurrent(undefined, undefined, undefined, ['Algorithm Visualizer'], [{
165-
name: 'README.md',
166-
content: README_MD,
167-
contributors: [us],
168-
}], undefined);
171+
this.props.setAlgorithm({
172+
categoryName: 'Algorithm Visualizer',
173+
algorithmName: 'Home',
174+
files: [{
175+
name: 'README.md',
176+
content: README_MD,
177+
contributors: [us],
178+
}],
179+
});
169180
})
170181
.finally(() => {
171-
const { files } = this.props.current;
182+
const files = getFiles(this.props.current);
172183
let editorTabIndex = files.findIndex(file => extension(file.name) === ext);
173184
if (!~editorTabIndex) editorTabIndex = files.findIndex(file => exts.includes(extension(file.name)));
174185
if (!~editorTabIndex) editorTabIndex = Math.min(0, files.length - 1);
@@ -182,15 +193,15 @@ class App extends React.Component {
182193
}
183194

184195
handleChangeEditorTabIndex(editorTabIndex) {
185-
const { files } = this.props.current;
196+
const files = getFiles(this.props.current);
186197
if (editorTabIndex === files.length) this.handleAddFile();
187198
this.setState({ editorTabIndex });
188199
this.props.shouldBuild();
189200
}
190201

191202
handleAddFile() {
192203
const { ext } = this.props.env;
193-
const { files } = this.props.current;
204+
const files = getFiles(this.props.current);
194205
let name = `code.${ext}`;
195206
let count = 0;
196207
while (files.some(file => file.name === name)) name = `code-${++count}.${ext}`;
@@ -210,7 +221,7 @@ class App extends React.Component {
210221

211222
handleDeleteFile() {
212223
const { editorTabIndex } = this.state;
213-
const { files } = this.props.current;
224+
const files = getFiles(this.props.current);
214225
this.handleChangeEditorTabIndex(Math.min(editorTabIndex, files.length - 2));
215226
this.props.deleteFile(editorTabIndex);
216227
}
@@ -220,15 +231,15 @@ class App extends React.Component {
220231
}
221232

222233
isGistSaved() {
223-
const { titles, files, lastTitles, lastFiles } = this.props.current;
224-
const serializeTitles = titles => JSON.stringify(titles);
234+
const { scratchPaper } = this.props.current;
235+
if (!scratchPaper) return true;
236+
const { title, files, lastTitle, lastFiles } = scratchPaper;
225237
const serializeFiles = files => JSON.stringify(files.map(({ name, content }) => ({ name, content })));
226-
return serializeTitles(titles) === serializeTitles(lastTitles) &&
227-
serializeFiles(files) === serializeFiles(lastFiles);
238+
return title === lastTitle && serializeFiles(files) === serializeFiles(lastFiles);
228239
}
229240

230241
getDescription() {
231-
const { files } = this.props.current;
242+
const files = getFiles(this.props.current);
232243
const readmeFile = files.find(file => file.name === 'README.md');
233244
if (!readmeFile) return '';
234245
const groups = /^\s*# .*\n+([^\n]+)/.exec(readmeFile.content);
@@ -237,7 +248,8 @@ class App extends React.Component {
237248

238249
render() {
239250
const { navigatorOpened, workspaceWeights, editorTabIndex } = this.state;
240-
const { titles, files } = this.props.current;
251+
const files = getFiles(this.props.current);
252+
const titleArray = getTitleArray(this.props.current);
241253

242254
const gistSaved = this.isGistSaved();
243255
const description = this.getDescription();
@@ -257,7 +269,7 @@ class App extends React.Component {
257269
return (
258270
<div className={styles.app}>
259271
<Helmet>
260-
<title>{gistSaved ? '' : '(Unsaved) '}{titles.join(' - ')}</title>
272+
<title>{gistSaved ? '' : '(Unsaved) '}{titleArray.join(' - ')}</title>
261273
<meta name="description" content={description} />
262274
</Helmet>
263275
<Header className={styles.header} onClickTitleBar={() => this.toggleNavigatorOpened()}

src/frontend/components/Header/index.jsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { actions } from '/reducers';
1919
import { languages } from '/common/config';
2020
import { Button, Ellipsis, ListItem, Player } from '/components';
2121
import styles from './stylesheet.scss';
22+
import { getTitleArray } from '../../common/util';
2223

2324
@connect(({ current, env }) => ({ current, env }), actions)
2425
class Header extends React.Component {
@@ -34,14 +35,15 @@ class Header extends React.Component {
3435

3536
handleChangeTitle(e) {
3637
const { value } = e.target;
37-
this.props.renameScratchPaper(value);
38+
this.props.modifyTitle(value);
3839
}
3940

4041
saveGist() {
4142
const { user } = this.props.env;
42-
const { categoryKey, algorithmKey, gistId, titles, files, lastFiles, lastGist } = this.props.current;
43+
const { scratchPaper } = this.props.current;
44+
const { gistId, title, files, lastFiles, lastGist } = scratchPaper;
4345
const gist = {
44-
description: titles[1],
46+
description: title,
4547
files: {},
4648
};
4749
files.forEach(file => {
@@ -67,13 +69,14 @@ class Header extends React.Component {
6769
};
6870
save(gist)
6971
.then(refineGist)
70-
.then(algorithm => this.props.setCurrent(categoryKey, algorithmKey, algorithm.gistId, algorithm.titles, algorithm.files, algorithm.gist))
72+
.then(this.props.setScratchPaper)
7173
.then(this.props.loadScratchPapers)
7274
.catch(handleError.bind(this));
7375
}
7476

7577
deleteGist() {
76-
const { gistId } = this.props.current;
78+
const { scratchPaper } = this.props.current;
79+
const { gistId } = scratchPaper;
7780
const deletePromise = ['new', 'forked'].includes(gistId) ? Promise.resolve() : GitHubApi.deleteGist(gistId);
7881
deletePromise
7982
.then(() => this.props.loadAlgorithm({}, true))
@@ -83,7 +86,8 @@ class Header extends React.Component {
8386

8487
render() {
8588
const { className, onClickTitleBar, navigatorOpened, gistSaved, file } = this.props;
86-
const { gistId, titles } = this.props.current;
89+
const { scratchPaper } = this.props.current;
90+
const titleArray = getTitleArray(this.props.current);
8791
const { ext, user } = this.props.env;
8892

8993
return (
@@ -92,12 +96,12 @@ class Header extends React.Component {
9296
<div className={styles.section}>
9397
<Button className={styles.title_bar} onClick={onClickTitleBar}>
9498
{
95-
titles.map((title, i) => [
96-
gistId && i === 1 ?
99+
titleArray.map((title, i) => [
100+
scratchPaper && i === 1 ?
97101
<AutosizeInput className={styles.input_title} key={`title-${i}`} value={title}
98102
onClick={e => e.stopPropagation()} onChange={e => this.handleChangeTitle(e)} /> :
99103
<Ellipsis key={`title-${i}`}>{title}</Ellipsis>,
100-
i < titles.length - 1 &&
104+
i < titleArray.length - 1 &&
101105
<FontAwesomeIcon className={styles.nav_arrow} fixedWidth icon={faAngleRight} key={`arrow-${i}`} />,
102106
])
103107
}
@@ -106,11 +110,11 @@ class Header extends React.Component {
106110
</Button>
107111
</div>
108112
<div className={styles.section}>
109-
<Button icon={faSave} primary disabled={!gistId || gistSaved}
113+
<Button icon={faSave} primary disabled={!scratchPaper || gistSaved}
110114
onClick={() => this.saveGist()}>Save</Button>
111-
<Button icon={faTrashAlt} primary disabled={!gistId} onClick={() => this.deleteGist()}
115+
<Button icon={faTrashAlt} primary disabled={!scratchPaper} onClick={() => this.deleteGist()}
112116
confirmNeeded>Delete</Button>
113-
<Button icon={faFacebook} primary disabled={['new', 'forked'].includes(gistId)}
117+
<Button icon={faFacebook} primary disabled={scratchPaper && ['new', 'forked'].includes(scratchPaper.gistId)}
114118
href={`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(window.location.href)}`}>Share</Button>
115119
<Button icon={faExpandArrowsAlt} primary
116120
onClick={() => this.handleClickFullScreen()}>Fullscreen</Button>

src/frontend/components/Navigator/index.jsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ class Navigator extends React.Component {
2323
}
2424

2525
componentDidMount() {
26-
const { categoryKey } = this.props.current;
27-
if (categoryKey) {
28-
this.toggleCategory(categoryKey, true);
26+
const { algorithm } = this.props.current;
27+
if (algorithm) {
28+
this.toggleCategory(algorithm.categoryKey, true);
2929
}
3030
}
3131

3232
componentWillReceiveProps(nextProps) {
33-
const { categoryKey } = nextProps.current;
34-
if (categoryKey) {
35-
this.toggleCategory(categoryKey, true);
33+
const { algorithm } = nextProps.current;
34+
if (algorithm) {
35+
this.toggleCategory(algorithm.categoryKey, true);
3636
}
3737
}
3838

@@ -69,8 +69,11 @@ class Navigator extends React.Component {
6969
const { categoriesOpened, scratchPaperOpened, query } = this.state;
7070
const { className, loadAlgorithm } = this.props;
7171
const { categories, scratchPapers } = this.props.directory;
72-
const { categoryKey, algorithmKey, gistId } = this.props.current;
73-
const { user } = this.props.env;
72+
const { algorithm, scratchPaper } = this.props.current;
73+
74+
const categoryKey = algorithm && algorithm.categoryKey;
75+
const algorithmKey = algorithm && algorithm.algorithmKey;
76+
const gistId = scratchPaper && scratchPaper.gistId;
7477

7578
return (
7679
<nav className={classes(styles.navigator, className)}>
@@ -128,4 +131,4 @@ class Navigator extends React.Component {
128131
}
129132
}
130133

131-
export default Navigator;
134+
export default Navigator;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy