feat: Partially transition Review to Redux
This commit is contained in:
		
							parent
							
								
									d94fa63ac7
								
							
						
					
					
						commit
						882ca5a9e3
					
				| @ -1,5 +1,7 @@ | ||||
| import { IVocab } from "../models/vocab"; | ||||
| import { IUser } from "../models/user"; | ||||
| import { ILevel } from "../models/level"; | ||||
| import { IReviewMetadata, IReviewCard } from "../models/review"; | ||||
| 
 | ||||
| export const SET_DRAWER = "SET_DRAWER"; | ||||
| export function setDrawer(state: boolean) { | ||||
| @ -89,3 +91,54 @@ export function setLevelLoading(state: boolean) { | ||||
|         state, | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| export const SET_LEVELS = "SET_LEVELS"; | ||||
| export function setLevels(levels: ILevel[]) { | ||||
|     return { | ||||
|         type: SET_LEVELS, | ||||
|         levels, | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| export const REVIEW_SET_POPOVER = "REVIEW_SET_POPOVER"; | ||||
| export function setReviewPopover(state: boolean, text: string, color: string) { | ||||
|     return { | ||||
|         type: REVIEW_SET_POPOVER, | ||||
|         state, | ||||
|         text, | ||||
|         color, | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| export const REVIEW_SET_SUMMARY = "REVIEW_SET_SUMMARY"; | ||||
| export function setReviewSummary(state: boolean) { | ||||
|     return { | ||||
|         type: REVIEW_SET_SUMMARY, | ||||
|         state, | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| export const REVIEW_SET_LOADING = "REVIEW_SET_LOADING"; | ||||
| export function setReviewLoading(state: boolean) { | ||||
|     return { | ||||
|         type: REVIEW_SET_LOADING, | ||||
|         state, | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| export const SET_LAST_REVIEW = "SET_LAST_REVIEW"; | ||||
| export function setLastReview(metadata: IReviewMetadata) { | ||||
|     return { | ||||
|         type: SET_LAST_REVIEW, | ||||
|         metadata, | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| export const SET_REVIEW = "SET_REVIEW"; | ||||
| export function setReview(current: IReviewCard, meta: IReviewMetadata) { | ||||
|     return { | ||||
|         type: SET_REVIEW, | ||||
|         current, | ||||
|         meta, | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| @ -6,9 +6,9 @@ import AuthRoute from "../security/AuthRoute"; | ||||
| 
 | ||||
| import Dashboard from "../pages/dashboard"; | ||||
| import LoginPage from "../containers/LoginPage"; | ||||
| import LevelListPage from "../pages/levelList"; | ||||
| import LevelListPage from "../containers/LevelList"; | ||||
| import LevelPage from "../containers/LevelPage"; | ||||
| import ReviewPage from "../pages/review"; | ||||
| import ReviewPage from "../containers/Review"; | ||||
| import SummaryPage from "../pages/summary"; | ||||
| import WelcomePage from "../pages/intro"; | ||||
| 
 | ||||
| @ -258,8 +258,7 @@ export default class Application extends React.Component<IProps> { | ||||
|                     <AuthRoute | ||||
|                         isAuth={this.isAuthenticated} | ||||
|                         path="/levelList" | ||||
|                         component={() => <LevelListPage | ||||
|                             levels={this.getLevels()} />} /> | ||||
|                         component={() => <LevelListPage />} /> | ||||
|                     {/*We cannot use AuthRoute here, because match is undefined otherwise*/} | ||||
|                     <Route | ||||
|                         path="/level/:id" | ||||
| @ -282,7 +281,6 @@ export default class Application extends React.Component<IProps> { | ||||
|                                     reviewType={ReviewType.LEVEL} | ||||
|                                     levelId={match.params.id} | ||||
|                                     vocabByLevel={this.getLevelVocab} | ||||
|                                     drawerButtonState={this.drawerButtonState} | ||||
|                                     setLastReview={this.setLastReview} />; | ||||
|                             } else { | ||||
|                                 return <Redirect to="/login" />; | ||||
|  | ||||
							
								
								
									
										14
									
								
								src/containers/LevelList.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/containers/LevelList.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| import { connect } from "react-redux"; | ||||
| 
 | ||||
| import LevelListPage from "../pages/levelList"; | ||||
| 
 | ||||
| const mapStateToProps = state => { | ||||
|     return { | ||||
|         levels: state.levels, | ||||
|     }; | ||||
| }; | ||||
| const mapDispatchToProps = dispatch => { return {} }; | ||||
| 
 | ||||
| const LevelListContainer = connect(mapStateToProps, | ||||
|     mapDispatchToProps)(LevelListPage); | ||||
| export default LevelListContainer; | ||||
							
								
								
									
										35
									
								
								src/containers/Review.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/containers/Review.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| import { connect } from "react-redux"; | ||||
| 
 | ||||
| import { | ||||
|     setDrawerButton, setReviewPopover, setReviewSummary, setLastReview, | ||||
|     setReview, setReviewLoading | ||||
| } from "../actions"; | ||||
| 
 | ||||
| import { IReviewMetadata } from "../models/review"; | ||||
| import { IVocab } from "../models/vocab"; | ||||
| import ReviewPage from "../pages/review"; | ||||
| 
 | ||||
| const mapStateToProps = state => { | ||||
|     return { | ||||
|         metadata: state.review.metadata, | ||||
|         vocab: state.review.vocab, | ||||
|         current: state.review.current, | ||||
|         popoverOpen: state.review.popoverOpen, | ||||
|         popoverText: state.review.popoverText, | ||||
|         popoverColor: state.review.popoverColor, | ||||
|         loading: state.review.loading, | ||||
|     }; | ||||
| }; | ||||
| const mapDispatchToProps = dispatch => { | ||||
|     return { | ||||
|         drawerButtonState: (state: boolean) => dispatch(setDrawerButton(state)), | ||||
|         setPopover: (state: boolean, text: string, color: string) => dispatch(setReviewPopover(state, text, color)), | ||||
|         setSummary: (state: boolean) => dispatch(setReviewSummary(state)), | ||||
|         setReview: (current: IVocab, meta: IReviewMetadata) => dispatch(setReview(current, meta)), | ||||
|         setLoading: (state: boolean) => dispatch(setReviewLoading(state)), | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| const ReviewContainer = connect(mapStateToProps, | ||||
|     mapDispatchToProps)(ReviewPage); | ||||
| export default ReviewContainer; | ||||
| @ -8,6 +8,8 @@ import Button from "@material-ui/core/Button"; | ||||
| import Typography from "@material-ui/core/Typography"; | ||||
| import Popover from "@material-ui/core/Popover"; | ||||
| import LinearProgress from "@material-ui/core/LinearProgress"; | ||||
| import CircularProgress from "@material-ui/core/CircularProgress"; | ||||
| import Paper from "@material-ui/core/Paper"; | ||||
| 
 | ||||
| import { Redirect } from "react-router-dom"; | ||||
| 
 | ||||
| @ -21,34 +23,34 @@ import { Queue } from "../utils/queue"; | ||||
| 
 | ||||
| interface IProps { | ||||
|     levelId?: number; | ||||
|     vocabByLevel?: (level: number) => IVocab[]; | ||||
|     vocabByQueue?: () => IVocab[]; | ||||
| 
 | ||||
|     setLastReview: (meta: IReviewMetadata) => void; | ||||
|     vocabByLevel?: (level: number) => Promise<IVocab[]>; | ||||
|     vocabByQueue?: () => Promise<IVocab[]>; | ||||
| 
 | ||||
|     reviewType: ReviewType; | ||||
| 
 | ||||
|     drawerButtonState: (state: boolean) => void; | ||||
| } | ||||
| 
 | ||||
| interface IState { | ||||
|     input: string; | ||||
|     loading: boolean; | ||||
|     vocab: IVocab[]; | ||||
|     current: IReviewCard; | ||||
| 
 | ||||
|     metadata: IReviewMetadata; | ||||
| 
 | ||||
|     toSummary: boolean; | ||||
| 
 | ||||
|     popoverOpen: boolean; | ||||
|     popoverText: string; | ||||
|     popoverColor: string; | ||||
| 
 | ||||
|     setSummary: (state: boolean) => void; | ||||
|     setPopover: (state: boolean, text: string, color: string) => void; | ||||
|     drawerButtonState: (state: boolean) => void; | ||||
|     setLastReview: (meta: IReviewMetadata) => void; | ||||
|     setReview: (curent: IReviewCard, meta: IReviewMetadata) => void; | ||||
|     setLoading: (state: boolean) => void; | ||||
| } | ||||
| 
 | ||||
| export default class ReviewPage extends React.Component<IProps, IState> { | ||||
| export default class ReviewPage extends React.Component<IProps> { | ||||
|     private vocab: IVocab[] = []; | ||||
|     private reviewQueue: Queue<IReviewCard> = undefined; | ||||
|     private reviewQueue: Queue<IReviewCard> = new Queue(); | ||||
|     // Used for positioning the popover
 | ||||
|     private buttonRef: HTMLButtonElement; | ||||
|     private inputRef: HTMLInputElement; | ||||
|     private metadata: IReviewMetadata = { correct: 0, wrong: 0 }; | ||||
| 
 | ||||
|     constructor(props: any) { | ||||
|         super(props); | ||||
| @ -56,6 +58,17 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|         // Hide the drawer button
 | ||||
|         this.props.drawerButtonState(false); | ||||
| 
 | ||||
|         const vocToQueue = () => { | ||||
|             this.vocab.forEach((vocab) => { | ||||
|                 vocabToReviewCard(vocab).forEach(this.reviewQueue.enqueue); | ||||
|             }); | ||||
|             this.props.setReview(this.reviewQueue.dequeue(), { | ||||
|                 correct: 0, | ||||
|                 wrong: 0, | ||||
|             }); | ||||
|             this.props.setLoading(false); | ||||
|         }; | ||||
| 
 | ||||
|         // Get the correct vocabulary
 | ||||
|         const { reviewType, vocabByLevel, levelId, vocabByQueue } = this.props; | ||||
|         switch (reviewType) { | ||||
| @ -63,7 +76,10 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|                 if (!vocabByLevel || !levelId) { | ||||
|                     alert("[ReviewPage::constructor] vocabByLevel or levelId undefined"); | ||||
|                 } else { | ||||
|                     this.vocab = vocabByLevel(levelId); | ||||
|                     vocabByLevel(levelId).then(res => { | ||||
|                         this.vocab = res; | ||||
|                         vocToQueue(); | ||||
|                     }); | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
| @ -71,38 +87,18 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|                 if (!vocabByQueue) { | ||||
|                     alert("[ReviewPage::constructor] vocabByQueue undefined"); | ||||
|                 } else { | ||||
|                     this.vocab = vocabByQueue(); | ||||
|                     vocabByQueue().then(res => { | ||||
|                         this.vocab = res; | ||||
|                         vocToQueue(); | ||||
|                     }); | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         // Turn the vocabulary into IReviewCards and queue them
 | ||||
|         if (!this.reviewQueue) { | ||||
|             this.reviewQueue = new Queue(); | ||||
|             this.vocab.forEach((vocab) => { | ||||
|                 vocabToReviewCard(vocab).forEach(this.reviewQueue.enqueue); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         this.state = { | ||||
|             input: "", | ||||
|             current: this.reviewQueue.dequeue(), | ||||
|             metadata: { | ||||
|                 correct: 0, | ||||
|                 wrong: 0, | ||||
|             }, | ||||
| 
 | ||||
|             toSummary: false, | ||||
| 
 | ||||
|             popoverOpen: false, | ||||
|             popoverText: "", | ||||
|             popoverColor: "red", | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     increaseMeta = (correct: number, wrong: number): IReviewMetadata => { | ||||
|         const { metadata } = this.state; | ||||
|         const { metadata } = this; | ||||
| 
 | ||||
|         return { | ||||
|             wrong: metadata.wrong + wrong, | ||||
| @ -111,21 +107,21 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|     } | ||||
| 
 | ||||
|     vocabFromId = (id: number) => { | ||||
|         return this.vocab.find((el) => el.id === this.state.current.id); | ||||
|         return this.vocab.find((el) => el.id === this.props.current.id); | ||||
|     } | ||||
| 
 | ||||
|     checkInput = () => { | ||||
|         // Check if the given answer is somewhere in the german words
 | ||||
|         const { input } = this.state; | ||||
|         const input = this.inputRef.value || ""; | ||||
| 
 | ||||
|         // Map all possible answers to lowercase ( => ignore casing)
 | ||||
|         const answers = this.state.current.answers.map((el) => el.toLowerCase()); | ||||
|         const answers = this.props.current.answers.map((el) => el.toLowerCase()); | ||||
|         // Calculate the distances to all possible answers
 | ||||
|         const dists = answers.map((el) => levW(input.toLowerCase(), el)); | ||||
|         // Find the lowest distance
 | ||||
|         const minDist = Math.min(...dists); | ||||
| 
 | ||||
|         console.log(this.reviewQueue.size()); | ||||
|         console.log("Review Queue size:", this.reviewQueue.size()); | ||||
| 
 | ||||
|         // Check if the user's answer was correct
 | ||||
|         if (minDist === 0) { | ||||
| @ -133,57 +129,76 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|             // Show the next vocab word
 | ||||
|             if (this.reviewQueue.size() === 0) { | ||||
|                 // Go to the summary screen
 | ||||
|                 this.setState({ | ||||
|                     toSummary: true, | ||||
|                 }, () => { | ||||
|                     // Update the "Last Review" data
 | ||||
|                     this.props.setLastReview(this.state.metadata); | ||||
|                 }); | ||||
|                 this.props.setLastReview(this.metadata); | ||||
|                 this.props.setSummary(true); | ||||
|             } else { | ||||
|                 // Increase the vocab
 | ||||
|                 this.setState({ | ||||
|                     current: this.reviewQueue.dequeue(), | ||||
|                     input: "", | ||||
|                     // Add one correct answer
 | ||||
|                     metadata: this.increaseMeta(1, 0), | ||||
|                 }); | ||||
|                 this.props.setReview(this.reviewQueue.dequeue(), this.increaseMeta(1, 0)); | ||||
|                 this.inputRef.value = ""; | ||||
|             } | ||||
|         } else if (minDist <= LEVENSHTEIN_MAX_DISTANCE) { | ||||
|             // TODO: Show a hint
 | ||||
|             console.log("Partially correct"); | ||||
|         } else { | ||||
|             // Find the IVocab item
 | ||||
|             const vocab = this.vocabFromId(this.state.current.id); | ||||
|             const vocab = this.vocabFromId(this.props.current.id); | ||||
|             if (vocab) { | ||||
|                 // Re-Add the vocabulary item to the review queue
 | ||||
|                 // TODO: Only re-add when it when it's not re-queued
 | ||||
|                 vocabToReviewCard(vocab).forEach(this.reviewQueue.enqueue); | ||||
|                 // vocabToReviewCard(vocab).forEach(this.reviewQueue.enqueue);
 | ||||
|             } else { | ||||
|                 console.log("[ReviewPage::checkInput] Could not find IVocab item for wrong IReviewCard"); | ||||
|             } | ||||
| 
 | ||||
|             this.setState({ | ||||
|                 popoverOpen: true, | ||||
|                 popoverText: "Das war nicht richtig", | ||||
|                 popoverColor: "red", | ||||
|                 // TODO: Or maybe don't reset the text
 | ||||
|                 input: "", | ||||
|                 metadata: this.increaseMeta(0, 1), | ||||
|             }); | ||||
|             this.props.setPopover(true, "Das war nicht richtig", "red"); | ||||
|         } | ||||
| 
 | ||||
|         // TODO(?): Show a snackbar for showing the updated score
 | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|         const { question, qtype } = this.state.current; | ||||
|         if (this.props.loading) { | ||||
|             return <div> | ||||
|                 {/* | ||||
|                   * This would be the case when the user presses the "to | ||||
|                   * review" button. That is because we need the state of loading | ||||
|                   * to be true, when this page gets called  | ||||
|                   * TODO:? | ||||
|                   */} | ||||
|                 { | ||||
|                     this.props.toSummary ? ( | ||||
|                         <Redirect to="/review/summary" /> | ||||
|                     ) : undefined | ||||
|                 } | ||||
| 
 | ||||
|                 <Grid | ||||
|                     container | ||||
|                     spacing={0} | ||||
|                     direction="column" | ||||
|                     alignItems="center" | ||||
|                     justify="center" | ||||
|                     style={{ minHeight: '100vh' }}> | ||||
|                     <Grid item xs={12}> | ||||
|                         <Paper className="paper"> | ||||
|                             <Grid container direction="column" spacing={8}> | ||||
|                                 <CircularProgress /> | ||||
|                             </Grid> | ||||
|                         </Paper> | ||||
|                     </Grid> | ||||
|                 </Grid> | ||||
| 
 | ||||
|             </div>; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         const { question, qtype } = this.props.current; | ||||
|         const questionTitle = `${question} (${reviewQTypeToStr(qtype)})`; | ||||
|         // TODO:
 | ||||
|         const progress = 50; | ||||
| 
 | ||||
|         return <div> | ||||
|             { | ||||
|                 this.state.toSummary ? ( | ||||
|                 this.props.toSummary ? ( | ||||
|                     <Redirect to="/review/summary" /> | ||||
|                 ) : undefined | ||||
|             } | ||||
| @ -198,10 +213,7 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|                                 <TextField | ||||
|                                     margin="normal" | ||||
|                                     fullWidth={true} | ||||
|                                     value={this.state.input} | ||||
|                                     onChange={(ev) => this.setState({ | ||||
|                                         input: ev.target.value, | ||||
|                                     })} | ||||
|                                     inputRef={node => this.inputRef = node} | ||||
|                                     onKeyPress={(ev) => { | ||||
|                                         // Allow checking of the answer by pressing Enter
 | ||||
|                                         if (ev.key === "Enter") | ||||
| @ -211,7 +223,7 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|                                     variant="determinate" | ||||
|                                     value={progress} /> | ||||
|                                 <Popover | ||||
|                                     open={this.state.popoverOpen} | ||||
|                                     open={this.props.popoverOpen} | ||||
|                                     anchorOrigin={{ | ||||
|                                         vertical: "center", | ||||
|                                         horizontal: "center" | ||||
| @ -221,12 +233,10 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|                                         horizontal: "center" | ||||
|                                     }} | ||||
|                                     anchorEl={this.buttonRef} | ||||
|                                     onClose={() => this.setState({ | ||||
|                                         popoverOpen: false, | ||||
|                                     })} | ||||
|                                     onClose={() => this.props.setPopover(false, "", "")} | ||||
|                                     PaperProps={{ | ||||
|                                         style: { | ||||
|                                             backgroundColor: this.state.popoverColor, | ||||
|                                             backgroundColor: this.props.popoverColor, | ||||
|                                             padding: 10, | ||||
|                                             color: "white" | ||||
|                                         } | ||||
| @ -234,7 +244,7 @@ export default class ReviewPage extends React.Component<IProps, IState> { | ||||
|                                     <Typography | ||||
|                                         variant="button" | ||||
|                                         color="inherit"> | ||||
|                                         {this.state.popoverText} | ||||
|                                         {this.props.popoverText} | ||||
|                                     </Typography> | ||||
|                                 </Popover> | ||||
|                                 <Button | ||||
|  | ||||
| @ -1,8 +1,10 @@ | ||||
| import * as Actions from "../actions"; | ||||
| 
 | ||||
| import { ILearner } from "../models/learner"; | ||||
| import { ILevel } from "../models/level"; | ||||
| import { IUser } from "../models/user"; | ||||
| import { IVocab } from "../models/vocab"; | ||||
| import { IReviewCard, IReviewMetadata } from "../models/review"; | ||||
| 
 | ||||
| interface IState { | ||||
|     drawer: boolean; | ||||
| @ -12,6 +14,9 @@ interface IState { | ||||
|     // TODO: Rework this
 | ||||
|     user: IUser | {}, | ||||
| 
 | ||||
|     // All available levels
 | ||||
|     levels: ILevel[]; | ||||
| 
 | ||||
|     login: { | ||||
|         loading: boolean; | ||||
|         snackMsg: string; | ||||
| @ -26,7 +31,22 @@ interface IState { | ||||
|         loading: boolean; | ||||
|     }; | ||||
| 
 | ||||
|     review: { | ||||
|         current: IReviewCard; | ||||
| 
 | ||||
|         loading: boolean; | ||||
|         vocab: IVocab[]; | ||||
|         metadata: IReviewMetadata; | ||||
|         toSummary: boolean; | ||||
|         popoverOpen: boolean; | ||||
|         popoverText: string; | ||||
|         popoverColor: string; | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
|     topTen: ILearner[]; | ||||
| 
 | ||||
|     lastReview: any; | ||||
| }; | ||||
| 
 | ||||
| const initialState: IState = { | ||||
| @ -46,6 +66,8 @@ const initialState: IState = { | ||||
|         snackOpen: false, | ||||
|     }, | ||||
| 
 | ||||
|     levels: [], | ||||
| 
 | ||||
|     level: { | ||||
|         currentVocab: {} as IVocab, | ||||
|         lookedAt: [0], | ||||
| @ -54,6 +76,23 @@ const initialState: IState = { | ||||
|         loading: true, | ||||
|     }, | ||||
| 
 | ||||
|     review: { | ||||
|         current: {} as IReviewCard, | ||||
| 
 | ||||
|         loading: true, | ||||
|         vocab: [], | ||||
|         metadata: {} as IReviewMetadata, | ||||
|         toSummary: false, | ||||
|         popoverOpen: false, | ||||
|         popoverText: "", | ||||
|         popoverColor: "", | ||||
|     }, | ||||
| 
 | ||||
|     lastReview: { | ||||
|         correct: 0, | ||||
|         wrong: 0, | ||||
|     }, | ||||
| 
 | ||||
|     // The top ten
 | ||||
|     topTen: [], | ||||
| }; | ||||
| @ -125,7 +164,46 @@ export function LateinicusApp(state: IState = initialState, action: any) { | ||||
|                     loading: action.state, | ||||
|                 }), | ||||
|             }); | ||||
|         case Actions.SET_LEVELS: | ||||
|             return Object.assign({}, state, { | ||||
|                 levels: action.levels, | ||||
|             }); | ||||
|         case Actions.REVIEW_SET_POPOVER: | ||||
|             return Object.assign({}, state, { | ||||
|                 review: Object.assign({}, state.review, { | ||||
|                     popoverText: action.text, | ||||
|                     popoverOpen: action.state, | ||||
|                     popoverColor: action.color, | ||||
|                 }), | ||||
|             }); | ||||
|         case Actions.SET_REVIEW: | ||||
|             return Object.assign({}, state, { | ||||
|                 review: Object.assign({}, state.review, { | ||||
|                     current: action.current, | ||||
|                     metadata: action.meta, | ||||
|                 }), | ||||
|             }); | ||||
|         case Actions.SET_LAST_REVIEW: | ||||
|             return Object.assign({}, state, { | ||||
|                 lastReview: action.metadata, | ||||
|             }); | ||||
|         case Actions.REVIEW_SET_LOADING: | ||||
|             return Object.assign({}, state, { | ||||
|                 review: Object.assign({}, state.review, { | ||||
|                     loading: action.state, | ||||
|                 }), | ||||
|             }); | ||||
|         case Actions.REVIEW_SET_SUMMARY: | ||||
|             return Object.assign({}, state, { | ||||
|                 review: Object.assign({}, state.review, { | ||||
|                     toSummary: action.state, | ||||
|                 }), | ||||
|             }); | ||||
|         default: | ||||
|             if (action.type) { | ||||
|                 console.log("Reducer not implemented:", action.type); | ||||
|             } | ||||
| 
 | ||||
|             return state; | ||||
|     } | ||||
| }; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Alexander Polynomdivision
						Alexander Polynomdivision