Skip to content

Commit 98c4770

Browse files
authored
Merge pull request #107 from kube-js/develop
fix: introduced redux-persist
2 parents a8b771e + 3cc6f8f commit 98c4770

File tree

16 files changed

+2324
-1215
lines changed

16 files changed

+2324
-1215
lines changed

assets/jscpd-badge.svg

Lines changed: 2 additions & 2 deletions
Loading

k8s/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apiVersion: v1
22
description: A Helm chart for kube-ts-react-client
33
name: kube-ts-react-client
44
version: 1.0.0
5-
appVersion: 1.5.17
5+
appVersion: 1.5.21
66
home: https://cloud.docker.com/u/kubejs/repository/docker/kubejs/kube-ts-react-client
77
icon: https://avatars2.githubusercontent.com/u/47761918?s=200&v=4
88
sources:

k8s/templates/deployment.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ spec:
2424
containers:
2525
- name: {{ .Chart.Name }}
2626
# TODO: change image tag to use $CIRCLE_SHA1
27+
# TODO: https://stackoverflow.com/questions/54119399/expose-port-80-on-digital-oceans-managed-kubernetes-without-a-load-balancer/55968709#55968709
2728
# and replace via envsubst [https://www.digitalocean.com/community/tutorials/how-to-automate-deployments-to-digitalocean-kubernetes-with-circleci]
2829
# image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
2930
image: "{{ .Values.image.repository }}:latest"

k8s/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ replicaCount: 2
66

77
image:
88
repository: kubejs/kube-ts-react-client
9-
tag: 1.5.17
9+
tag: 1.5.21
1010
pullPolicy: Always
1111
containerPort: 80
1212

package-lock.json

Lines changed: 2118 additions & 1082 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"react-scripts": "2.1.8",
3636
"react-slick": "0.25.2",
3737
"redux": "4.0.4",
38+
"redux-persist": "6.0.0",
3839
"redux-saga": "1.1.1",
3940
"reselect": "4.0.0",
4041
"set-value": "3.0.1",
@@ -59,6 +60,7 @@
5960
"@types/react-router-dom": "5.1.0",
6061
"@types/react-slick": "0.23.4",
6162
"@types/redux-logger": "3.0.7",
63+
"@types/redux-persist": "^4.3.1",
6264
"@types/store": "2.0.2",
6365
"@types/uuid": "3.4.5",
6466
"@types/yup": "0.26.24",

src/atoms/Autocomplete/index.tsx

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,45 @@ import TextField from '@material-ui/core/TextField';
66
import CloseIcon from '@material-ui/icons/Close';
77
import SearchIcon from '@material-ui/icons/Search';
88
import Downshift from 'downshift';
9-
import React from 'react';
9+
import _isNil from 'ramda/src/isNil';
10+
import React, { useState } from 'react';
11+
import { useDispatch, useSelector } from 'react-redux';
12+
import { useHistory } from 'react-router-dom';
13+
import { autocompleteRequested } from '../../redux/autocomplete/actionCreators';
14+
import { State } from '../../redux/rootReducer';
15+
import Course from '../../types/items/Course';
16+
import User from '../../types/items/User';
1017
import useStyles from './styles';
1118

19+
export interface GetFormattedResultsOptions {
20+
readonly courses: Course[];
21+
readonly users: User[];
22+
}
23+
24+
const getFormattedResults = ({
25+
courses,
26+
users,
27+
}: GetFormattedResultsOptions) => {
28+
const updatedCourses = courses
29+
.map((course: Course) => ({
30+
...course,
31+
label: course.title,
32+
type: 'course',
33+
}))
34+
.slice(0, 4);
35+
const updatedUsers = users
36+
.map((user: User) => ({
37+
...user,
38+
label: [user.firstName, user.lastName].every(Boolean)
39+
? `${user.firstName} ${user.lastName}`
40+
: user.email,
41+
type: 'user',
42+
}))
43+
.slice(0, 2);
44+
45+
return [...updatedCourses, ...updatedUsers];
46+
};
47+
1248
function renderInput(inputProps: any) {
1349
const { InputProps, classes, ref, ...other } = inputProps;
1450

@@ -56,12 +92,47 @@ function renderSuggestion(suggestionProps: any) {
5692

5793
let popperNode: any;
5894

59-
const Autocomplete = ({value, onChange, suggestions}: any) => {
95+
const Autocomplete = () => {
6096
const classes = useStyles();
6197

98+
const [value, setValue] = useState('');
99+
const history = useHistory();
100+
const { courses, users } = useSelector((state: State) => state.autocomplete);
101+
102+
const dispatch = useDispatch();
103+
const results = getFormattedResults({ courses, users });
104+
105+
const handleChange = (changes: any) => {
106+
// TODO: abstract this operations
107+
if (
108+
changes.hasOwnProperty('selectedItem') &&
109+
!_isNil(changes.selectedItem)
110+
) {
111+
setValue(changes.selectedItem);
112+
113+
const item: any = results.filter(
114+
result => result.label === changes.selectedItem
115+
)[0];
116+
117+
const link =
118+
item.type === 'course'
119+
? `/courses/${item.slug}`
120+
: `/instructors/${item.email}`;
121+
122+
history.push(link);
123+
} else if (changes.hasOwnProperty('inputValue')) {
124+
setValue(changes.inputValue);
125+
dispatch(autocompleteRequested(changes.inputValue));
126+
}
127+
};
128+
62129
return (
63130
<div className={classes.root}>
64-
<Downshift id="downshift-popper" selectedItem={value} onStateChange={onChange}>
131+
<Downshift
132+
id="downshift-popper"
133+
selectedItem={value}
134+
onStateChange={handleChange}
135+
>
65136
{({
66137
clearSelection,
67138
getInputProps,
@@ -109,15 +180,14 @@ const Autocomplete = ({value, onChange, suggestions}: any) => {
109180
width: popperNode ? popperNode.clientWidth : undefined,
110181
}}
111182
>
112-
{suggestions.map(
113-
(suggestion: any, index: number) =>
114-
renderSuggestion({
115-
highlightedIndex,
116-
index,
117-
itemProps: getItemProps({ item: suggestion.label }),
118-
selectedItem,
119-
suggestion,
120-
})
183+
{results.map((suggestion: any, index: number) =>
184+
renderSuggestion({
185+
highlightedIndex,
186+
index,
187+
itemProps: getItemProps({ item: suggestion.label }),
188+
selectedItem,
189+
suggestion,
190+
})
121191
)}
122192
</Paper>
123193
</div>

src/components/CourseSlide/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import { Link } from 'react-router-dom';
1414
// tslint:disable:no-import-side-effect
1515
import 'slick-carousel/slick/slick-theme.css';
1616
import 'slick-carousel/slick/slick.css';
17-
import CourseRating from '../../atoms/CourseRating';
17+
// TODO: check slow rendering issue
18+
// import CourseRating from '../../atoms/CourseRating';
1819
import courseImagePlaceholder from '../../images/course_400x180.png';
1920
import { EnhancedCourse } from '../../redux/discoveryItems/actionCreators';
2021
import assetsUrl from '../../utils/helpers/assetsUrl';
@@ -27,7 +28,7 @@ const Slide = ({
2728
course: EnhancedCourse;
2829
}) => {
2930
// TODO: get real rating and price
30-
const courseRating = Number((Math.random() * 5).toFixed(1));
31+
// const courseRating = Number((Math.random() * 5).toFixed(1));
3132
// tslint:disable-next-line:no-magic-numbers
3233
const coursePrice = Number(Math.random() * 10 + 9).toFixed(2);
3334

@@ -59,7 +60,7 @@ const Slide = ({
5960
{course.user.firstName} {course.user.lastName}
6061
</Typography>
6162

62-
<CourseRating value={courseRating} />
63+
{/* <CourseRating value={courseRating} /> */}
6364

6465
<div className={classes.cardPrice}>{${coursePrice}`}</div>
6566
</CardContent>

src/components/CourseView/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,18 @@ const CourseView = ({ match }: RouteComponentProps<Params>) => {
2929
const dispatch = useDispatch();
3030

3131
useEffect(() => {
32-
dispatch(getCourseDetailsRequested(match.params.courseSlug));
32+
if(course === undefined || course.slug !== match.params.courseSlug){
33+
dispatch(getCourseDetailsRequested(match.params.courseSlug));
34+
}
3335
}, [match.params.courseSlug]);
3436

3537
if (getCourseDetailsLoading || course === undefined) {
3638
// TODO: make course placeholder
3739
return <div>Loading...</div>;
3840
}
39-
const imageUrl = !_isNil(course.imageUrl) ? assetsUrl(course.imageUrl) : courseImagePlaceholder;
41+
const imageUrl = !_isNil(course.imageUrl)
42+
? assetsUrl(course.imageUrl)
43+
: courseImagePlaceholder;
4044
const coursePrice = Number(Math.random() * 10 + 9).toFixed(2);
4145

4246
return (

src/components/HeroContent/index.tsx

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,73 +3,12 @@ import Container from '@material-ui/core/Container';
33
import Grid from '@material-ui/core/Grid';
44
import Typography from '@material-ui/core/Typography';
55
import _isNil from 'ramda/src/isNil';
6-
import React, { useState } from 'react';
7-
import { useDispatch, useSelector } from 'react-redux';
8-
import { useHistory } from 'react-router-dom';
6+
import React from 'react';
97
import Autocomplete from '../../atoms/Autocomplete';
10-
import { autocompleteRequested } from '../../redux/autocomplete/actionCreators';
11-
import { State } from '../../redux/rootReducer';
12-
import Course from '../../types/items/Course';
13-
import User from '../../types/items/User';
148
import useStyles from './styles';
15-
export interface GetFormattedResultsOptions {
16-
readonly courses: Course[];
17-
readonly users: User[];
18-
}
19-
20-
const getFormattedResults = ({
21-
courses,
22-
users,
23-
}: GetFormattedResultsOptions) => {
24-
const updatedCourses = courses
25-
.map((course: Course) => ({
26-
...course,
27-
label: course.title,
28-
type: 'course',
29-
}))
30-
.slice(0, 4);
31-
const updatedUsers = users
32-
.map((user: User) => ({
33-
...user,
34-
label: [user.firstName, user.lastName].every(Boolean)
35-
? `${user.firstName} ${user.lastName}`
36-
: user.email,
37-
type: 'user',
38-
}))
39-
.slice(0, 2);
40-
41-
return [...updatedCourses, ...updatedUsers];
42-
};
439

4410
const HeroContent = () => {
4511
const classes = useStyles();
46-
const [value, setValue] = useState('');
47-
const history = useHistory();
48-
const { courses, users } = useSelector((state: State) => state.autocomplete);
49-
50-
const dispatch = useDispatch();
51-
const results = getFormattedResults({ courses, users });
52-
53-
const handleChange = (changes: any) => {
54-
// TODO: abstract this operations
55-
if (changes.hasOwnProperty('selectedItem') && !_isNil(changes.selectedItem)) {
56-
setValue(changes.selectedItem);
57-
58-
const item: any = results.filter(
59-
result => result.label === changes.selectedItem
60-
)[0];
61-
62-
const link =
63-
item.type === 'course'
64-
? `/courses/${item.slug}`
65-
: `/instructors/${item.email}`;
66-
67-
history.push(link);
68-
} else if (changes.hasOwnProperty('inputValue')) {
69-
setValue(changes.inputValue);
70-
dispatch(autocompleteRequested(changes.inputValue));
71-
}
72-
};
7312

7413
return (
7514
<div className={classes.heroContainer}>
@@ -95,11 +34,7 @@ const HeroContent = () => {
9534
Find any course and topic and start learning today.
9635
</Typography>
9736
<div className={classes.searchBox}>
98-
<Autocomplete
99-
value={value}
100-
onChange={handleChange}
101-
suggestions={results}
102-
/>
37+
<Autocomplete />
10338
</div>
10439
</Grid>
10540
</Container>

0 commit comments

Comments
 (0)